[Bf-blender-cvs] [a8a536d] master: Bake-API: new approach for cage

Dalai Felinto noreply at git.blender.org
Wed Jun 11 07:40:04 CEST 2014


Commit: a8a536d23da73e3f57d54fa1f7c2276f3ca83025
Author: Dalai Felinto
Date:   Wed Jun 11 02:39:35 2014 -0300
https://developer.blender.org/rBa8a536d23da73e3f57d54fa1f7c2276f3ca83025

Bake-API: new approach for cage

There is a new option to select whether you want to use cage or not.
When not using cage the results will be more similar with Blender
Internal, where the inwards rays (trying to hit the highpoly objects)
don't always come from smooth normals. So if the active object has sharp
edges and an EdgeSplit modifier you get bad corners.

This is useful, however, to bake to planes without the need of adding
extra loops around the edges.

When cage is "on" the user can decide on setting a cage extrusion or to
pick a Custom Cage object. The cage extrusion option works in a
duplicated copy of the active object with EdgeSplit modifiers removed to
inforce smooth normals. The custom cage option takes an object with the
same number of faces as the active object (and the same face ordering).

The custom cage now controls the direction and the origin of the
rays casted to the highpoly objects. The direction is a ray from the
point in the cage mesh to the equivalent point to the base mesh. That
means the face normals are entirely ignored when using a cage object.

For developers:
When using an object cage the ray is calculated from the cage mesh to
the base mesh. It uses the barycentric coordinate from the base mesh UV,
so we expect both meshes to have the same primitive ids (which won't be
the case if the cage gets edited in a destructive way).

That fixes T40023 (giving the expected result when 'use_cage' is false).

Thanks for Andy Davies (metalliandy) for the consulting with normal
baking workflow and extensive testing. His 'stress-test' file will be
added later to our svn tests folder. (The file itself is not public yet
since he still has to add testing notes to it).

Many thanks for the reviewers.

More on cages:
http://wiki.polycount.com/NormalMap/#Working_with_Cages

Reviewers: campbellbarton, sergey

CC: adriano, metalliandy, brecht, malkavian

Differential Revision: https://developer.blender.org/D547

===================================================================

M	intern/cycles/blender/addon/ui.py
M	source/blender/editors/object/object_bake_api.c
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_scene.c
M	source/blender/render/extern/include/RE_bake.h
M	source/blender/render/intern/source/bake_api.c

===================================================================

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 5c8115b..1797f29 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1259,8 +1259,13 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
         sub = sub.column()
 
         sub.active = cbk.use_selected_to_active
-        sub.prop(cbk, "cage_extrusion", text="Distance")
-        sub.prop_search(cbk, "cage", scene, "objects")
+
+        sub.prop(cbk, "use_cage", text="Cage")
+        if cbk.use_cage:
+            sub.prop(cbk, "cage_extrusion", text="Cage Extrusion")
+            sub.prop_search(cbk, "custom_cage", scene, "objects")
+        else:
+            sub.prop(cbk, "cage_extrusion", text="Ray Distance")
 
         if cscene.bake_type == 'NORMAL':
             col.separator()
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 534ecd5..b69de3d 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -489,6 +489,7 @@ typedef struct BakeAPIRender {
 	bool is_split_materials;
 	bool is_automatic_name;
 	bool is_selected_to_active;
+	bool is_cage;
 
 	float cage_extrusion;
 	int normal_space;
@@ -512,7 +513,7 @@ static int bake(
         Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
         const ScenePassType pass_type, const int margin,
         const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
-        const bool is_automatic_name, const bool is_selected_to_active,
+        const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
         const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[],
         const char *custom_cage, const char *filepath, const int width, const int height,
         const char *identifier, ScrArea *sa)
@@ -529,6 +530,7 @@ static int bake(
 	char restrict_flag_cage;
 
 	Mesh *me_low = NULL;
+	Mesh *me_cage = NULL;
 	Render *re;
 
 	float *result = NULL;
@@ -614,14 +616,11 @@ static int bake(
 			tot_highpoly ++;
 		}
 
-		if (custom_cage[0] != '\0') {
+		if (is_cage && custom_cage[0] != '\0') {
 			ob_cage = BLI_findstring(&bmain->object, custom_cage, offsetof(ID, name) + 2);
 
-			/* TODO check if cage object has the same topology (num of triangles and a valid UV) */
 			if (ob_cage == NULL || ob_cage->type != OB_MESH) {
 				BKE_report(reports, RPT_ERROR, "No valid cage object");
-				op_result = OPERATOR_CANCELLED;
-
 				goto cleanup;
 			}
 			else {
@@ -640,20 +639,31 @@ static int bake(
 	pixel_array_low = MEM_callocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
 	result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
 
+	/* get the mesh as it arrives in the renderer */
+	me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
+
+	/* populate the pixel array with the face data */
+	if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
+		RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images);
+	/* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh)  */
+
 	if (is_selected_to_active) {
 		CollectionPointerLink *link;
 		ModifierData *md, *nmd;
 		ListBase modifiers_tmp, modifiers_original;
-		float mat_low[4][4];
 		int i = 0;
-		highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
 
 		/* prepare cage mesh */
 		if (ob_cage) {
-			me_low = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 1, 0);
-			copy_m4_m4(mat_low, ob_cage->obmat);
+			me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 1, 0);
+			if (me_low->totface != me_cage->totface) {
+				BKE_report(reports, RPT_ERROR,
+				           "Invalid cage object, the cage mesh must have the same number "
+				           "of faces as the active object");
+				goto cleanup;
+			}
 		}
-		else {
+		else if (is_cage) {
 			modifiers_original = ob_low->modifiers;
 			BLI_listbase_clear(&modifiers_tmp);
 
@@ -677,10 +687,12 @@ static int bake(
 			ob_low->modifiers = modifiers_tmp;
 
 			/* get the cage mesh as it arrives in the renderer */
-			me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
-			copy_m4_m4(mat_low, ob_low->obmat);
+			me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
+			RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images);
 		}
 
+		highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
+
 		/* populate highpoly array */
 		for (link = selected_objects->first; link; link = link->next) {
 			TriangulateModifierData *tmd;
@@ -723,15 +735,12 @@ static int bake(
 
 		BLI_assert(i == tot_highpoly);
 
-		/* populate the pixel array with the face data */
-		RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images);
-
 		ob_low->restrictflag |= OB_RESTRICT_RENDER;
 
 		/* populate the pixel arrays with the corresponding face data for each high poly object */
 		RE_bake_pixels_populate_from_objects(
-		        me_low, pixel_array_low, highpoly, tot_highpoly,
-		        num_pixels, cage_extrusion, mat_low);
+		        me_low, pixel_array_low, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
+		        cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage);
 
 		/* the baking itself */
 		for (i = 0; i < tot_highpoly; i++) {
@@ -752,7 +761,7 @@ static int bake(
 		if (ob_cage) {
 			ob_cage->restrictflag |= OB_RESTRICT_RENDER;
 		}
-		else {
+		else if (is_cage) {
 			ob_low->modifiers = modifiers_original;
 
 			while ((md = BLI_pophead(&modifiers_tmp))) {
@@ -761,12 +770,6 @@ static int bake(
 		}
 	}
 	else {
-		/* get the mesh as it arrives in the renderer */
-		me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0);
-
-		/* populate the pixel array with the face data */
-		RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images);
-
 		/* make sure low poly renders */
 		ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
 
@@ -965,6 +968,9 @@ cleanup:
 	if (me_low)
 		BKE_libblock_free(bmain, me_low);
 
+	if (me_cage)
+		BKE_libblock_free(bmain, me_cage);
+
 	return op_result;
 }
 
@@ -988,6 +994,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
 	bkr->is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
 	bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
 	bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
+	bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
 	bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
 
 	bkr->normal_space = RNA_enum_get(op->ptr, "normal_space");
@@ -1036,7 +1043,7 @@ static int bake_exec(bContext *C, wmOperator *op)
 		result = bake(
 		        bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
 		        bkr.pass_type, bkr.margin, bkr.save_mode,
-		        bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true,
+		        bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
 		        bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
 		        bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa);
 	}
@@ -1048,7 +1055,7 @@ static int bake_exec(bContext *C, wmOperator *op)
 			result = bake(
 			        bkr.main, bkr.scene, ob_iter, NULL, bkr.reports,
 			        bkr.pass_type, bkr.margin, bkr.save_mode,
-			        is_clear, bkr.is_split_materials, bkr.is_automatic_name, false,
+			        is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
 			        bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
 			        bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa);
 		}
@@ -1076,7 +1083,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *UNUSED(do_updat
 		bkr->result = bake(
 		        bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
 		        bkr->pass_type, bkr->margin, bkr->save_mode,
-		        bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true,
+		        bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
 		        bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
 		        bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa);
 	}
@@ -1088,7 +1095,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *UNUSED(do_updat
 			bkr->result = bake(
 			        bkr->main, bkr->scene, ob_iter, NULL, bkr->reports,
 			        bkr->pass_type, bkr->margin, bkr->save_mode,
-			        is_clear, bkr->is_split_materials, bkr->is_automatic_name, false,
+			        is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
 			        bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
 			        bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa);
 
@@ -1178,6 +1185,11 @@ static void bake_set_props(wmOperator *op, Scene *scene)
 		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR));
 	}
 
+	prop = RNA_struct_find_property(op->ptr, "use_cage");
+	if (!RNA_property_is_set(op->ptr, prop)) {
+		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE));
+	}
+
 	prop = RNA_struct_find_property(op->ptr, "use_split_materials");
 	if (!RNA_property_is_set(op->ptr, prop)) {
 		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT));
@@ -1254,8 +1266,8 @@ void OBJECT_OT_bake(wmOperatorType *ot)
 	                "Bake shading on the surface of selected objects to the active object");
 	RNA_def_float(ot->srna, "cage_extrusion", 0.0, 0.0, 1.0, "Cage Extrusion",
 	              "Distance to use for the inward ray cast when using selected to active", 0.0, 1.0);
-	RNA_def_string(ot->srna, "cage", NULL, MAX_NAME, "Cage",
-	               "Object to use as cage");
+	RNA_def_string(ot->srna, "cage", NULL, MAX_NAME, "Custom Cage",
+	               "Object to use as cage, instead

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list