[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [57145] trunk/blender/source/blender: modifier stack: lazy initialize normals

Campbell Barton ideasman42 at gmail.com
Thu May 30 19:36:44 CEST 2013


Revision: 57145
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=57145
Author:   campbellbarton
Date:     2013-05-30 17:36:43 +0000 (Thu, 30 May 2013)
Log Message:
-----------
modifier stack: lazy initialize normals

many modifiers were calculating normals, when those normals were ignored by the next modifier.
now flag normals as dirty and recalculate for modifiers that set use `dependsOnNormals()` callback.

Quick test on mesh with 12 modifiers (mostly build type), calculated normals 6 times, now it only runs once - so this will give some speedup too.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h
    trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c
    trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c
    trunk/blender/source/blender/blenkernel/intern/editderivedmesh.c
    trunk/blender/source/blender/blenkernel/intern/modifiers_bmesh.c
    trunk/blender/source/blender/blenkernel/intern/smoke.c
    trunk/blender/source/blender/blenkernel/intern/subsurf_ccg.c
    trunk/blender/source/blender/editors/space_view3d/drawobject.c
    trunk/blender/source/blender/modifiers/intern/MOD_array.c
    trunk/blender/source/blender/modifiers/intern/MOD_bevel.c
    trunk/blender/source/blender/modifiers/intern/MOD_boolean_util.c
    trunk/blender/source/blender/modifiers/intern/MOD_edgesplit.c
    trunk/blender/source/blender/modifiers/intern/MOD_explode.c
    trunk/blender/source/blender/modifiers/intern/MOD_mask.c
    trunk/blender/source/blender/modifiers/intern/MOD_mirror.c
    trunk/blender/source/blender/modifiers/intern/MOD_ocean.c
    trunk/blender/source/blender/modifiers/intern/MOD_particleinstance.c
    trunk/blender/source/blender/modifiers/intern/MOD_remesh.c
    trunk/blender/source/blender/modifiers/intern/MOD_screw.c
    trunk/blender/source/blender/modifiers/intern/MOD_skin.c
    trunk/blender/source/blender/modifiers/intern/MOD_solidify.c
    trunk/blender/source/blender/modifiers/intern/MOD_triangulate.c
    trunk/blender/source/blender/modifiers/intern/MOD_util.c

Modified: trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h	2013-05-30 16:58:34 UTC (rev 57144)
+++ trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h	2013-05-30 17:36:43 UTC (rev 57145)
@@ -160,8 +160,11 @@
 	 * without actually rebuilding dm (hence by defautl keeping same GPUDrawObject, and same colors
 	 * buffer, which prevents update during a stroke!). */
 	DM_DIRTY_MCOL_UPDATE_DRAW = 1 << 1,
-} DMDirtyFlag;
 
+	/* check this with modifier dependsOnNormals callback to see if normals need recalculation */
+	DM_DIRTY_NORMALS = 1 << 2,
+}  DMDirtyFlag;
+
 typedef struct DerivedMesh DerivedMesh;
 struct DerivedMesh {
 	/** Private DerivedMesh data, only for internal DerivedMesh use */
@@ -560,6 +563,7 @@
 /*sets up mpolys for a DM based on face iterators in source*/
 void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
 
+void DM_ensure_normals(DerivedMesh *dm);
 void DM_ensure_tessface(DerivedMesh *dm);
 
 void DM_update_tessface_data(DerivedMesh *dm);

Modified: trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c	2013-05-30 16:58:34 UTC (rev 57144)
+++ trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c	2013-05-30 17:36:43 UTC (rev 57145)
@@ -376,6 +376,14 @@
 	}
 }
 
+void DM_ensure_normals(DerivedMesh *dm)
+{
+	if (dm->dirty & DM_DIRTY_NORMALS) {
+		dm->calcNormals(dm);
+	}
+	BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
+}
+
 /* note: until all modifiers can take MPoly's as input,
  * use this at the start of modifiers  */
 void DM_ensure_tessface(DerivedMesh *dm)
@@ -818,16 +826,68 @@
 	if (!dm)
 		return NULL;
 	
-	if (vertCos)
+	if (vertCos) {
 		CDDM_apply_vert_coords(dm, vertCos);
+	}
 
-	CDDM_calc_normals(dm);
-
 	return dm;
 }
 
 /***/
 
+/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */
+
+static DerivedMesh *modwrap_applyModifier(
+        ModifierData *md, Object *ob,
+        DerivedMesh *dm,
+        ModifierApplyFlag flag)
+{
+	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+	if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+		DM_ensure_normals(dm);
+	}
+	return mti->applyModifier(md, ob, dm, flag);
+}
+
+static DerivedMesh *modwrap_applyModifierEM(
+        ModifierData *md, Object *ob,
+        BMEditMesh *em,
+        DerivedMesh *dm,
+        ModifierApplyFlag flag)
+{
+	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+	if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+		DM_ensure_normals(dm);
+	}
+	return mti->applyModifierEM(md, ob, em, dm, flag);
+}
+
+static void modwrap_deformVerts(
+        ModifierData *md, Object *ob,
+        DerivedMesh *dm,
+        float (*vertexCos)[3], int numVerts,
+        ModifierApplyFlag flag)
+{
+	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+	if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+		DM_ensure_normals(dm);
+	}
+	mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag);
+}
+
+static void modwrap_deformVertsEM(
+        ModifierData *md, Object *ob,
+        BMEditMesh *em, DerivedMesh *dm,
+        float (*vertexCos)[3], int numVerts)
+{
+	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+	if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+		DM_ensure_normals(dm);
+	}
+	mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts);
+}
+/* end modifier callback wrappers */
+
 DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, 
                                               ModifierData *md, int build_shapekey_layers)
 {
@@ -849,7 +909,7 @@
 		int numVerts;
 		float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts);
 
-		mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0);
+		modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, 0);
 		dm = mesh_create_derived(me, ob, deformedVerts);
 
 		if (build_shapekey_layers)
@@ -863,7 +923,7 @@
 		if (build_shapekey_layers)
 			add_shapekey_layers(tdm, me, ob);
 		
-		dm = mti->applyModifier(md, ob, tdm, 0);
+		dm = modwrap_applyModifier(md, ob, tdm, 0);
 
 		if (tdm != dm) tdm->release(tdm);
 	}
@@ -937,8 +997,6 @@
 		if (free) MEM_freeN(orco);
 	}
 
-	CDDM_calc_normals(dm);
-
 	return dm;
 }
 
@@ -1372,6 +1430,20 @@
 	}
 }
 
+/**
+ * Called after calculating all modifiers.
+ *
+ * \note tessfaces should already be calculated.
+ */
+static void dm_ensure_display_normals(DerivedMesh *dm)
+{
+	if ((dm->type == DM_TYPE_CDDM) &&
+	    ((dm->dirty & DM_DIRTY_NORMALS) || CustomData_has_layer(&dm->faceData, CD_NORMAL) == FALSE))
+	{
+		/* if normals are dirty we want to calculate vertex normals too */
+		CDDM_calc_normals_mapping_ex(dm, (dm->dirty & DM_DIRTY_NORMALS) ? false : true);
+	}
+}
 /* new value for useDeform -1  (hack for the gameengine):
  * - apply only the modifier stack of the object, skipping the virtual modifiers,
  * - don't apply the key
@@ -1468,7 +1540,7 @@
 				if (!deformedVerts)
 					deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts);
 
-				mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, deform_app_flags);
+				modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, deform_app_flags);
 			}
 			else {
 				break;
@@ -1491,7 +1563,6 @@
 			
 			if (deformedVerts) {
 				CDDM_apply_vert_coords(*deform_r, deformedVerts);
-				CDDM_calc_normals(*deform_r);
 			}
 		}
 	}
@@ -1582,11 +1653,10 @@
 				/* XXX, this covers bug #23673, but we may need normal calc for other types */
 				if (dm && dm->type == DM_TYPE_CDDM) {
 					CDDM_apply_vert_coords(dm, deformedVerts);
-					CDDM_calc_normals(dm);
 				}
 			}
 
-			mti->deformVerts(md, ob, dm, deformedVerts, numVerts, deform_app_flags);
+			modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, deform_app_flags);
 		}
 		else {
 			DerivedMesh *ndm;
@@ -1605,7 +1675,6 @@
 					dm = tdm;
 
 					CDDM_apply_vert_coords(dm, deformedVerts);
-					CDDM_calc_normals(dm);
 				}
 			}
 			else {
@@ -1616,7 +1685,6 @@
 
 				if (deformedVerts) {
 					CDDM_apply_vert_coords(dm, deformedVerts);
-					CDDM_calc_normals(dm);
 				}
 
 				if (do_init_wmcol)
@@ -1667,7 +1735,7 @@
 				}
 			}
 
-			ndm = mti->applyModifier(md, ob, dm, app_flags);
+			ndm = modwrap_applyModifier(md, ob, dm, app_flags);
 
 			if (ndm) {
 				/* if the modifier returned a new dm, release the old one */
@@ -1692,8 +1760,9 @@
 				DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX |
 				                 (mti->requiredDataMask ?
 				                  mti->requiredDataMask(ob, md) : 0));
-				ndm = mti->applyModifier(md, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
 
+				ndm = modwrap_applyModifier(md, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+
 				if (ndm) {
 					/* if the modifier returned a new dm, release the old one */
 					if (orcodm && orcodm != ndm) orcodm->release(orcodm);
@@ -1708,8 +1777,9 @@
 
 				nextmask &= ~CD_MASK_CLOTH_ORCO;
 				DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX);
-				ndm = mti->applyModifier(md, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
 
+				ndm = modwrap_applyModifier(md, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+
 				if (ndm) {
 					/* if the modifier returned a new dm, release the old one */
 					if (clothorcodm && clothorcodm != ndm) clothorcodm->release(clothorcodm);
@@ -1751,7 +1821,6 @@
 		dm->release(dm);
 
 		CDDM_apply_vert_coords(finaldm, deformedVerts);
-		CDDM_calc_normals(finaldm);
 
 #if 0 /* For later nice mod preview! */
 		/* In case we need modified weights in CD_PREVIEW_MCOL, we have to re-compute it. */
@@ -1769,24 +1838,16 @@
 #endif
 	}
 	else {
-		int recalc_normals = 0;
-
 		finaldm = CDDM_from_mesh(me, ob);
 		
 		if (build_shapekey_layers) {
 			add_shapekey_layers(finaldm, me, ob);
-			recalc_normals = 1;
 		}
 		
 		if (deformedVerts) {
 			CDDM_apply_vert_coords(finaldm, deformedVerts);
-			recalc_normals = 1;
 		}
 
-		if (recalc_normals) {
-			CDDM_calc_normals(finaldm);
-		}
-
 		/* In this case, we should never have weight-modifying modifiers in stack... */
 		if (do_init_wmcol)
 			DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL);
@@ -1848,11 +1909,9 @@
 		 * note that this isn't a problem for subsurf (only quads) or editmode
 		 * which deals with drawing differently.
 		 *
-		 * Never calc vertex normals because other code ensures these are up to date.
+		 * Only calc vertex normals if they are flagged as dirty.
 		 */
-		if ((finaldm->type == DM_TYPE_CDDM) && (CustomData_has_layer(&finaldm->faceData, CD_NORMAL) == FALSE)) {
-			CDDM_calc_normals_mapping_ex(finaldm, TRUE);
-		}
+		dm_ensure_display_normals(finaldm);
 	}
 
 #ifdef WITH_GAMEENGINE
@@ -1984,9 +2043,9 @@
 			}
 
 			if (mti->deformVertsEM)
-				mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
+				modwrap_deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
 			else
-				mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0);
+				modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, 0);
 		}
 		else {
 			DerivedMesh *ndm;
@@ -1999,7 +2058,6 @@
 					dm = tdm;
 
 					CDDM_apply_vert_coords(dm, deformedVerts);
-					CDDM_calc_normals(dm);
 				}
 				else if (cage_r && dm == *cage_r) {
 					/* dm may be changed by this modifier, so we need to copy it
@@ -2013,7 +2071,6 @@
 
 				if (deformedVerts) {
 					CDDM_apply_vert_coords(dm, deformedVerts);
-					CDDM_calc_normals(dm);
 				}
 
 				if (do_init_wmcol) {
@@ -2031,9 +2088,9 @@
 				DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX);
 
 				if (mti->applyModifierEM)
-					ndm = mti->applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO);
+					ndm = modwrap_applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO);
 				else
-					ndm = mti->applyModifier(md, ob, orcodm, MOD_APPLY_ORCO);
+					ndm = modwrap_applyModifier(md, ob, orcodm, MOD_APPLY_ORCO);
 
 				if (ndm) {
 					/* if the modifier returned a new dm, release the old one */
@@ -2053,9 +2110,9 @@
 					DM_init_origspace(dm);
 				}
 			}
-			
+
 			if (mti->applyModifierEM)
-				ndm = mti->applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE);
+				ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE);
 			else
 				ndm = mti->applyModifier(md, ob, dm, MOD_APPLY_USECACHE);
 
@@ -2100,22 +2157,13 @@
 		if (!(cage_r && dm == *cage_r)) dm->release(dm);
 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list