[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