diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 149 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 11 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/editderivedmesh.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifiers_bmesh.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/smoke.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 3 |
6 files changed, 120 insertions, 49 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 7b2ff7df670..4a5aaa65f90 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -376,6 +376,14 @@ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) } } +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 @@ DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) 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 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, 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 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, 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 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int lay if (free) MEM_freeN(orco); } - CDDM_calc_normals(dm); - return dm; } @@ -1372,6 +1430,20 @@ static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *UNUSED(ob)) } } +/** + * 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 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos 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 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos if (deformedVerts) { CDDM_apply_vert_coords(*deform_r, deformedVerts); - CDDM_calc_normals(*deform_r); } } } @@ -1582,11 +1653,10 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* 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 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos dm = tdm; CDDM_apply_vert_coords(dm, deformedVerts); - CDDM_calc_normals(dm); } } else { @@ -1616,7 +1685,6 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos if (deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); - CDDM_calc_normals(dm); } if (do_init_wmcol) @@ -1667,7 +1735,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } } - 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,7 +1760,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos 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 */ @@ -1708,7 +1777,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos 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 */ @@ -1751,7 +1821,6 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos 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,22 +1838,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos #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... */ @@ -1848,11 +1909,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos * 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 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D } 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 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D 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 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D if (deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); - CDDM_calc_normals(dm); } if (do_init_wmcol) { @@ -2031,9 +2088,9 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D 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 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D 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 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D if (!(cage_r && dm == *cage_r)) dm->release(dm); CDDM_apply_vert_coords(*final_r, deformedVerts); - CDDM_calc_normals(*final_r); /* was CDDM_calc_normals_mapping - campbell */ } else if (dm) { *final_r = dm; - - /* once we support skipping normal calculation with modifiers we may want to add this back */ -#if 0 // was added for bmesh but is not needed - (*final_r)->calcNormals(*final_r); -#endif } else if (!deformedVerts && cage_r && *cage_r) { /* cage should already have up to date normals */ *final_r = *cage_r; -#if 0 // was added for bmesh but is not needed - (*final_r)->calcNormals(*final_r); -#endif /* In this case, we should never have weight-modifying modifiers in stack... */ if (do_init_wmcol) @@ -2152,6 +2200,9 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D } /* --- */ + /* same as mesh_calc_modifiers */ + dm_ensure_display_normals(*final_r); + /* add an orco layer if needed */ if (dataMask & CD_MASK_ORCO) add_orco_dm(ob, em, *final_r, orcodm, CD_ORCO); @@ -2191,6 +2242,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask, * but this avoids waiting on first stroke) */ ob->sculpt->pbvh = ob->derivedFinal->getPBVH(ob, ob->derivedFinal); } + + BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); } static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask) @@ -2217,6 +2270,8 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C em->lastDataMask = dataMask; em->derivedFinal->needsFree = 0; em->derivedCage->needsFree = 0; + + BLI_assert(!(em->derivedFinal->dirty & DM_DIRTY_NORMALS)); } static CustomDataMask object_get_datamask(Scene *scene, Object *ob) @@ -2271,6 +2326,7 @@ DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dat if (!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask) mesh_build_data(scene, ob, dataMask, 0); + if (ob->derivedFinal) { BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); } return ob->derivedFinal; } @@ -2380,6 +2436,7 @@ DerivedMesh *editbmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, } *final_r = em->derivedFinal; + if (em->derivedFinal) { BLI_assert(!(em->derivedFinal->dirty & DM_DIRTY_NORMALS)); } return em->derivedCage; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 743b4a33bc2..80bd71e7b59 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1841,6 +1841,7 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase) dm = CDDM_new(totvert, totedge, 0, totloop, totpoly); dm->deformedOnly = 1; + dm->dirty |= DM_DIRTY_NORMALS; cddm = (CDDerivedMesh *)dm; @@ -2197,6 +2198,8 @@ void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3]) for (i = 0; i < dm->numVertData; ++i, ++vert) copy_v3_v3(vert->co, vertCoords[i]); + + cddm->dm.dirty |= DM_DIRTY_NORMALS; } void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) @@ -2211,6 +2214,8 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) for (i = 0; i < dm->numVertData; ++i, ++vert) copy_v3_v3_short(vert->no, vertNormals[i]); + + cddm->dm.dirty &= ~DM_DIRTY_NORMALS; } void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const short only_face_normals) @@ -2255,6 +2260,8 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const short only_face_normals CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numTessFaceData); + + cddm->dm.dirty &= ~DM_DIRTY_NORMALS; } @@ -2285,6 +2292,8 @@ void CDDM_calc_normals(DerivedMesh *dm) BKE_mesh_calc_normals_poly(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), dm->numLoopData, dm->numPolyData, poly_nors); + + cddm->dm.dirty &= ~DM_DIRTY_NORMALS; } void CDDM_calc_normals_tessface(DerivedMesh *dm) @@ -2305,6 +2314,8 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) BKE_mesh_calc_normals_tessface(cddm->mvert, dm->numVertData, cddm->mface, dm->numTessFaceData, face_nors); + + cddm->dm.dirty &= ~DM_DIRTY_NORMALS; } #if 1 diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 794e6481d34..be072d9cc16 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -74,10 +74,11 @@ typedef struct EditDerivedBMesh { float (*polyNos)[3]; } EditDerivedBMesh; -static void emDM_calcNormals(DerivedMesh *UNUSED(dm)) +static void emDM_calcNormals(DerivedMesh *dm) { /* Nothing to do: normals are already calculated and stored on the * BMVerts and BMFaces */ + dm->dirty &= ~DM_DIRTY_NORMALS; } static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm)) diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 85ed20bcb14..b5f07176e2b 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -157,7 +157,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) /* note: i_alt is aligned with bmesh faces which may not always align with mpolys */ mp = dm->getPolyArray(dm); mloop = dm->getLoopArray(dm); - face_normals = CustomData_get_layer(&dm->polyData, CD_NORMAL); /* can be NULL */ + face_normals = (dm->dirty & DM_DIRTY_NORMALS) ? NULL : CustomData_get_layer(&dm->polyData, CD_NORMAL); for (i = 0; i < dm->numPolyData; i++, mp++) { BMLoop *l_iter; BMLoop *l_first; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 2bf11b993c4..05c3550d810 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -2602,6 +2602,7 @@ static DerivedMesh *createDomainGeometry(SmokeDomainSettings *sds, Object *ob) CDDM_calc_edges(result); + result->dirty |= DM_DIRTY_NORMALS; return result; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 91a992ff92f..1934a7052e5 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -3071,9 +3071,10 @@ static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm)) /* Nothing to do: CCG handles creating its own tessfaces */ } -static void ccgDM_calcNormals(DerivedMesh *UNUSED(dm)) +static void ccgDM_calcNormals(DerivedMesh *dm) { /* Nothing to do: CCG calculates normals during drawing */ + dm->dirty &= ~DM_DIRTY_NORMALS; } static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, |