Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/DerivedMesh.c
| Show All 22 Lines | |||||
| #include <string.h> | #include <string.h> | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "DNA_cloth_types.h" | #include "DNA_cloth_types.h" | ||||
| #include "DNA_customdata_types.h" | |||||
| #include "DNA_key_types.h" | #include "DNA_key_types.h" | ||||
| #include "DNA_material_types.h" | #include "DNA_material_types.h" | ||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "BLI_array.h" | #include "BLI_array.h" | ||||
| ▲ Show 20 Lines • Show All 317 Lines • ▼ Show 20 Lines | |||||
| /** | /** | ||||
| * Utility function to initialize a DerivedMesh for the desired number | * Utility function to initialize a DerivedMesh for the desired number | ||||
| * of vertices, edges and faces, with a layer setup copied from source | * of vertices, edges and faces, with a layer setup copied from source | ||||
| */ | */ | ||||
| void DM_from_template_ex( | void DM_from_template_ex( | ||||
| DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, | DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, | ||||
| int numVerts, int numEdges, int numTessFaces, | int numVerts, int numEdges, int numTessFaces, | ||||
| int numLoops, int numPolys, | int numLoops, int numPolys, | ||||
| CustomDataMask mask) | const CustomData_MeshMasks *mask) | ||||
| { | { | ||||
| CustomData_copy(&source->vertData, &dm->vertData, mask, CD_CALLOC, numVerts); | CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts); | ||||
| CustomData_copy(&source->edgeData, &dm->edgeData, mask, CD_CALLOC, numEdges); | CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges); | ||||
| CustomData_copy(&source->faceData, &dm->faceData, mask, CD_CALLOC, numTessFaces); | CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces); | ||||
| CustomData_copy(&source->loopData, &dm->loopData, mask, CD_CALLOC, numLoops); | CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_CALLOC, numLoops); | ||||
| CustomData_copy(&source->polyData, &dm->polyData, mask, CD_CALLOC, numPolys); | CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_CALLOC, numPolys); | ||||
| dm->cd_flag = source->cd_flag; | dm->cd_flag = source->cd_flag; | ||||
| dm->type = type; | dm->type = type; | ||||
| dm->numVertData = numVerts; | dm->numVertData = numVerts; | ||||
| dm->numEdgeData = numEdges; | dm->numEdgeData = numEdges; | ||||
| dm->numTessFaceData = numTessFaces; | dm->numTessFaceData = numTessFaces; | ||||
| dm->numLoopData = numLoops; | dm->numLoopData = numLoops; | ||||
| dm->numPolyData = numPolys; | dm->numPolyData = numPolys; | ||||
| DM_init_funcs(dm); | DM_init_funcs(dm); | ||||
| dm->needsFree = 1; | dm->needsFree = 1; | ||||
| dm->dirty = 0; | dm->dirty = 0; | ||||
| } | } | ||||
| void DM_from_template( | void DM_from_template( | ||||
| DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, | DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, | ||||
| int numVerts, int numEdges, int numTessFaces, | int numVerts, int numEdges, int numTessFaces, | ||||
| int numLoops, int numPolys) | int numLoops, int numPolys) | ||||
| { | { | ||||
| DM_from_template_ex( | DM_from_template_ex( | ||||
| dm, source, type, | dm, source, type, | ||||
| numVerts, numEdges, numTessFaces, | numVerts, numEdges, numTessFaces, | ||||
| numLoops, numPolys, | numLoops, numPolys, | ||||
| CD_MASK_DERIVEDMESH); | &CD_MASK_DERIVEDMESH); | ||||
| } | } | ||||
| int DM_release(DerivedMesh *dm) | int DM_release(DerivedMesh *dm) | ||||
| { | { | ||||
| if (dm->needsFree) { | if (dm->needsFree) { | ||||
| bvhcache_free(&dm->bvhCache); | bvhcache_free(&dm->bvhCache); | ||||
| CustomData_free(&dm->vertData, dm->numVertData); | CustomData_free(&dm->vertData, dm->numVertData); | ||||
| CustomData_free(&dm->edgeData, dm->numEdgeData); | CustomData_free(&dm->edgeData, dm->numEdgeData); | ||||
| Show All 24 Lines | int DM_release(DerivedMesh *dm) | ||||
| } | } | ||||
| } | } | ||||
| void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) | void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) | ||||
| { | { | ||||
| CustomData_free(&target->loopData, source->numLoopData); | CustomData_free(&target->loopData, source->numLoopData); | ||||
| CustomData_free(&target->polyData, source->numPolyData); | CustomData_free(&target->polyData, source->numPolyData); | ||||
| CustomData_copy(&source->loopData, &target->loopData, CD_MASK_DERIVEDMESH, CD_DUPLICATE, source->numLoopData); | CustomData_copy(&source->loopData, &target->loopData, CD_MASK_DERIVEDMESH.lmask, CD_DUPLICATE, source->numLoopData); | ||||
| CustomData_copy(&source->polyData, &target->polyData, CD_MASK_DERIVEDMESH, CD_DUPLICATE, source->numPolyData); | CustomData_copy(&source->polyData, &target->polyData, CD_MASK_DERIVEDMESH.pmask, CD_DUPLICATE, source->numPolyData); | ||||
| target->numLoopData = source->numLoopData; | target->numLoopData = source->numLoopData; | ||||
| target->numPolyData = source->numPolyData; | target->numPolyData = source->numPolyData; | ||||
| if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) { | if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) { | ||||
| MPoly *mpoly; | MPoly *mpoly; | ||||
| MLoop *mloop; | MLoop *mloop; | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (dm->looptris.array_wip == NULL) { | ||||
| dm->looptris.array_wip = MEM_malloc_arrayN(looptris_num, sizeof(*dm->looptris.array_wip), __func__); | dm->looptris.array_wip = MEM_malloc_arrayN(looptris_num, sizeof(*dm->looptris.array_wip), __func__); | ||||
| dm->looptris.num_alloc = looptris_num; | dm->looptris.num_alloc = looptris_num; | ||||
| } | } | ||||
| dm->looptris.num = looptris_num; | dm->looptris.num = looptris_num; | ||||
| } | } | ||||
| } | } | ||||
| void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask, bool take_ownership) | void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership) | ||||
| { | { | ||||
| /* dm might depend on me, so we need to do everything with a local copy */ | /* dm might depend on me, so we need to do everything with a local copy */ | ||||
| Mesh tmp = *me; | Mesh tmp = *me; | ||||
| int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; | int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; | ||||
| int did_shapekeys = 0; | int did_shapekeys = 0; | ||||
| eCDAllocType alloctype = CD_DUPLICATE; | eCDAllocType alloctype = CD_DUPLICATE; | ||||
| if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) { | if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) { | ||||
| Show All 17 Lines | void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership) | ||||
| DM_ensure_normals(dm); | DM_ensure_normals(dm); | ||||
| totvert = tmp.totvert = dm->getNumVerts(dm); | totvert = tmp.totvert = dm->getNumVerts(dm); | ||||
| totedge = tmp.totedge = dm->getNumEdges(dm); | totedge = tmp.totedge = dm->getNumEdges(dm); | ||||
| totloop = tmp.totloop = dm->getNumLoops(dm); | totloop = tmp.totloop = dm->getNumLoops(dm); | ||||
| totpoly = tmp.totpoly = dm->getNumPolys(dm); | totpoly = tmp.totpoly = dm->getNumPolys(dm); | ||||
| tmp.totface = 0; | tmp.totface = 0; | ||||
| CustomData_copy(&dm->vertData, &tmp.vdata, mask, alloctype, totvert); | CustomData_copy(&dm->vertData, &tmp.vdata, mask->vmask, alloctype, totvert); | ||||
| CustomData_copy(&dm->edgeData, &tmp.edata, mask, alloctype, totedge); | CustomData_copy(&dm->edgeData, &tmp.edata, mask->emask, alloctype, totedge); | ||||
| CustomData_copy(&dm->loopData, &tmp.ldata, mask, alloctype, totloop); | CustomData_copy(&dm->loopData, &tmp.ldata, mask->lmask, alloctype, totloop); | ||||
| CustomData_copy(&dm->polyData, &tmp.pdata, mask, alloctype, totpoly); | CustomData_copy(&dm->polyData, &tmp.pdata, mask->pmask, alloctype, totpoly); | ||||
| tmp.cd_flag = dm->cd_flag; | tmp.cd_flag = dm->cd_flag; | ||||
| tmp.runtime.deformed_only = dm->deformedOnly; | tmp.runtime.deformed_only = dm->deformedOnly; | ||||
| if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) { | if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) { | ||||
| KeyBlock *kb; | KeyBlock *kb; | ||||
| int uid; | int uid; | ||||
| if (ob) { | if (ob) { | ||||
| ▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | if (me->bb) { | ||||
| tmp.bb = NULL; | tmp.bb = NULL; | ||||
| } | } | ||||
| /* skip the listbase */ | /* skip the listbase */ | ||||
| MEMCPY_STRUCT_OFS(me, &tmp, id.prev); | MEMCPY_STRUCT_OFS(me, &tmp, id.prev); | ||||
| if (take_ownership) { | if (take_ownership) { | ||||
| if (alloctype == CD_ASSIGN) { | if (alloctype == CD_ASSIGN) { | ||||
| CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask); | CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask->vmask); | ||||
| CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask); | CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask->emask); | ||||
| CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask); | CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask->lmask); | ||||
| CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask); | CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask->pmask); | ||||
| } | } | ||||
| dm->release(dm); | dm->release(dm); | ||||
| } | } | ||||
| } | } | ||||
| /** Utility function to convert an (evaluated) Mesh to a shape key block. */ | /** Utility function to convert an (evaluated) Mesh to a shape key block. */ | ||||
| /* Just a shallow wrapper around BKE_keyblock_convert_from_mesh, | /* Just a shallow wrapper around BKE_keyblock_convert_from_mesh, | ||||
| * that ensures both evaluated mesh and original one has same number of vertices. */ | * that ensures both evaluated mesh and original one has same number of vertices. */ | ||||
| void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb) | void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb) | ||||
| { | { | ||||
| const int totvert = me_deformed->totvert; | const int totvert = me_deformed->totvert; | ||||
| if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) { | if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) { | ||||
| return; | return; | ||||
| } | } | ||||
| BKE_keyblock_convert_from_mesh(me_deformed, me->key, kb); | BKE_keyblock_convert_from_mesh(me_deformed, me->key, kb); | ||||
| } | } | ||||
| /** | /** | ||||
| * set the CD_FLAG_NOCOPY flag in custom data layers where the mask is | * set the CD_FLAG_NOCOPY flag in custom data layers where the mask is | ||||
| * zero for the layer type, so only layer types specified by the mask | * zero for the layer type, so only layer types specified by the mask | ||||
| * will be copied | * will be copied | ||||
| */ | */ | ||||
| void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask) | void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask) | ||||
| { | { | ||||
| CustomData_set_only_copy(&dm->vertData, mask); | CustomData_set_only_copy(&dm->vertData, mask->vmask); | ||||
| CustomData_set_only_copy(&dm->edgeData, mask); | CustomData_set_only_copy(&dm->edgeData, mask->emask); | ||||
| CustomData_set_only_copy(&dm->faceData, mask); | CustomData_set_only_copy(&dm->faceData, mask->fmask); | ||||
| /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with | /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with | ||||
| * weight paint mode when there are modifiers applied, needs further investigation, | * weight paint mode when there are modifiers applied, needs further investigation, | ||||
| * see replies to r50969, Campbell */ | * see replies to r50969, Campbell */ | ||||
| #if 0 | #if 0 | ||||
| CustomData_set_only_copy(&dm->loopData, mask); | CustomData_set_only_copy(&dm->loopData, mask->lmask); | ||||
| CustomData_set_only_copy(&dm->polyData, mask); | CustomData_set_only_copy(&dm->polyData, mask->pmask); | ||||
| #endif | #endif | ||||
| } | } | ||||
| static void mesh_set_only_copy(Mesh *mesh, CustomDataMask mask) | static void mesh_set_only_copy(Mesh *mesh, const CustomData_MeshMasks *mask) | ||||
| { | { | ||||
| CustomData_set_only_copy(&mesh->vdata, mask); | CustomData_set_only_copy(&mesh->vdata, mask->vmask); | ||||
| CustomData_set_only_copy(&mesh->edata, mask); | CustomData_set_only_copy(&mesh->edata, mask->emask); | ||||
| CustomData_set_only_copy(&mesh->fdata, mask); | CustomData_set_only_copy(&mesh->fdata, mask->fmask); | ||||
| /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with | /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with | ||||
| * weight paint mode when there are modifiers applied, needs further investigation, | * weight paint mode when there are modifiers applied, needs further investigation, | ||||
| * see replies to r50969, Campbell */ | * see replies to r50969, Campbell */ | ||||
| #if 0 | #if 0 | ||||
| CustomData_set_only_copy(&mesh->ldata, mask); | CustomData_set_only_copy(&mesh->ldata, mask->lmask); | ||||
| CustomData_set_only_copy(&mesh->pdata, mask); | CustomData_set_only_copy(&mesh->pdata, mask->pmask); | ||||
| #endif | #endif | ||||
| } | } | ||||
| void DM_add_vert_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) | void DM_add_vert_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) | ||||
| { | { | ||||
| CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData); | CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 286 Lines • ▼ Show 20 Lines | |||||
| static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer) | static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer) | ||||
| { | { | ||||
| Mesh *mesh; | Mesh *mesh; | ||||
| float (*orco)[3]; | float (*orco)[3]; | ||||
| int free; | int free; | ||||
| if (em) { | if (em) { | ||||
| mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, 0); | mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL); | ||||
| } | } | ||||
| else { | else { | ||||
| mesh = BKE_mesh_copy_for_eval(me, true); | mesh = BKE_mesh_copy_for_eval(me, true); | ||||
| } | } | ||||
| orco = get_orco_coords(ob, em, layer, &free); | orco = get_orco_coords(ob, em, layer, &free); | ||||
| if (orco) { | if (orco) { | ||||
| ▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | if (me_orig->flag & ME_AUTOSMOOTH) { | ||||
| me->flag |= ME_AUTOSMOOTH; | me->flag |= ME_AUTOSMOOTH; | ||||
| me->smoothresh = me_orig->smoothresh; | me->smoothresh = me_orig->smoothresh; | ||||
| } | } | ||||
| } | } | ||||
| static void mesh_calc_modifiers( | static void mesh_calc_modifiers( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, float (*inputVertexCos)[3], | struct Depsgraph *depsgraph, Scene *scene, Object *ob, float (*inputVertexCos)[3], | ||||
| int useDeform, | int useDeform, | ||||
| const bool need_mapping, CustomDataMask dataMask, | const bool need_mapping, const CustomData_MeshMasks *dataMask, | ||||
| const int index, const bool useCache, const bool build_shapekey_layers, | const int index, const bool useCache, const bool build_shapekey_layers, | ||||
| /* return args */ | /* return args */ | ||||
| Mesh **r_deform, Mesh **r_final) | Mesh **r_deform, Mesh **r_final) | ||||
| { | { | ||||
| ModifierData *firstmd, *md, *previewmd = NULL; | ModifierData *firstmd, *md, *previewmd = NULL; | ||||
| CDMaskLink *datamasks, *curr; | CDMaskLink *datamasks, *curr; | ||||
| /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ | /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ | ||||
| CustomDataMask mask, nextmask, previewmask = 0, append_mask = CD_MASK_ORIGINDEX | CD_MASK_BAREMESH; | CustomData_MeshMasks mask, nextmask, previewmask = {0}, append_mask = CD_MASK_BAREMESH_ORIGINDEX; | ||||
| float (*deformedVerts)[3] = NULL; | float (*deformedVerts)[3] = NULL; | ||||
| int numVerts = ((Mesh *)ob->data)->totvert; | int numVerts = ((Mesh *)ob->data)->totvert; | ||||
| const bool useRenderParams = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); | const bool useRenderParams = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); | ||||
| const int required_mode = useRenderParams ? eModifierMode_Render : eModifierMode_Realtime; | const int required_mode = useRenderParams ? eModifierMode_Render : eModifierMode_Realtime; | ||||
| bool isPrevDeform = false; | bool isPrevDeform = false; | ||||
| MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); | MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); | ||||
| const bool has_multires = (mmd && mmd->sculptlvl != 0); | const bool has_multires = (mmd && mmd->sculptlvl != 0); | ||||
| bool multires_applied = false; | bool multires_applied = false; | ||||
| Show All 29 Lines | static void mesh_calc_modifiers( | ||||
| if (do_mod_mcol) { | if (do_mod_mcol) { | ||||
| /* Find the last active modifier generating a preview, or NULL if none. */ | /* Find the last active modifier generating a preview, or NULL if none. */ | ||||
| /* XXX Currently, DPaint modifier just ignores this. | /* XXX Currently, DPaint modifier just ignores this. | ||||
| * Needs a stupid hack... | * Needs a stupid hack... | ||||
| * The whole "modifier preview" thing has to be (re?)designed, anyway! */ | * The whole "modifier preview" thing has to be (re?)designed, anyway! */ | ||||
| previewmd = modifiers_getLastPreview(scene, md, required_mode); | previewmd = modifiers_getLastPreview(scene, md, required_mode); | ||||
| } | } | ||||
| datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, previewmd, previewmask); | datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, previewmd, &previewmask); | ||||
| curr = datamasks; | curr = datamasks; | ||||
| if (r_deform) { | if (r_deform) { | ||||
| *r_deform = NULL; | *r_deform = NULL; | ||||
| } | } | ||||
| *r_final = NULL; | *r_final = NULL; | ||||
| if (useDeform) { | if (useDeform) { | ||||
| ▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | if (need_mapping && !modifier_supportsMapping(md)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { | if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* add an orco layer if needed by this modifier */ | /* add an orco layer if needed by this modifier */ | ||||
| if (mti->requiredDataMask) | memset(&mask, 0, sizeof(mask)); | ||||
| mask = mti->requiredDataMask(ob, md); | if (mti->requiredDataMask) { | ||||
| else | mti->requiredDataMask(ob, md, &mask); | ||||
| mask = 0; | } | ||||
| if (me && (mask & CD_MASK_ORCO)) { | if (me && (mask.vmask & CD_MASK_ORCO)) { | ||||
| add_orco_mesh(ob, NULL, me, me_orco, CD_ORCO); | add_orco_mesh(ob, NULL, me, me_orco, CD_ORCO); | ||||
| } | } | ||||
| /* How to apply modifier depends on (a) what we already have as | /* How to apply modifier depends on (a) what we already have as | ||||
| * a result of previous modifiers (could be a Mesh or just | * a result of previous modifiers (could be a Mesh or just | ||||
| * deformed vertices) and (b) what type the modifier is. | * deformed vertices) and (b) what type the modifier is. | ||||
| */ | */ | ||||
| Show All 23 Lines | if (mti->type == eModifierTypeType_OnlyDeform) { | ||||
| modwrap_deformVerts(md, &mectx_deform, me, deformedVerts, numVerts); | modwrap_deformVerts(md, &mectx_deform, me, deformedVerts, numVerts); | ||||
| } | } | ||||
| else { | else { | ||||
| /* determine which data layers are needed by following modifiers */ | /* determine which data layers are needed by following modifiers */ | ||||
| if (curr->next) | if (curr->next) | ||||
| nextmask = curr->next->mask; | nextmask = curr->next->mask; | ||||
| else | else | ||||
| nextmask = dataMask; | nextmask = *dataMask; | ||||
| /* apply vertex coordinates or build a Mesh as necessary */ | /* apply vertex coordinates or build a Mesh as necessary */ | ||||
| if (me) { | if (me) { | ||||
| if (deformedVerts) { | if (deformedVerts) { | ||||
| BKE_mesh_apply_vert_coords(me, deformedVerts); | BKE_mesh_apply_vert_coords(me, deformedVerts); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 10 Lines | else { | ||||
| /* Constructive modifiers need to have an origindex | /* Constructive modifiers need to have an origindex | ||||
| * otherwise they wont have anywhere to copy the data from. | * otherwise they wont have anywhere to copy the data from. | ||||
| * | * | ||||
| * Also create ORIGINDEX data if any of the following modifiers | * Also create ORIGINDEX data if any of the following modifiers | ||||
| * requests it, this way Mirror, Solidify etc will keep ORIGINDEX | * requests it, this way Mirror, Solidify etc will keep ORIGINDEX | ||||
| * data by using generic DM_copy_vert_data() functions. | * data by using generic DM_copy_vert_data() functions. | ||||
| */ | */ | ||||
| if (need_mapping || (nextmask & CD_MASK_ORIGINDEX)) { | if (need_mapping || ((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) { | ||||
| /* calc */ | /* calc */ | ||||
| CustomData_add_layer(&me->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totvert); | CustomData_add_layer(&me->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totvert); | ||||
| CustomData_add_layer(&me->edata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totedge); | CustomData_add_layer(&me->edata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totedge); | ||||
| CustomData_add_layer(&me->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totpoly); | CustomData_add_layer(&me->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totpoly); | ||||
| /* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */ | /* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */ | ||||
| range_vn_i(CustomData_get_layer(&me->vdata, CD_ORIGINDEX), me->totvert, 0); | range_vn_i(CustomData_get_layer(&me->vdata, CD_ORIGINDEX), me->totvert, 0); | ||||
| range_vn_i(CustomData_get_layer(&me->edata, CD_ORIGINDEX), me->totedge, 0); | range_vn_i(CustomData_get_layer(&me->edata, CD_ORIGINDEX), me->totedge, 0); | ||||
| range_vn_i(CustomData_get_layer(&me->pdata, CD_ORIGINDEX), me->totpoly, 0); | range_vn_i(CustomData_get_layer(&me->pdata, CD_ORIGINDEX), me->totpoly, 0); | ||||
| } | } | ||||
| } | } | ||||
| /* set the Mesh to only copy needed data */ | /* set the Mesh to only copy needed data */ | ||||
| mask = curr->mask; | mask = curr->mask; | ||||
| /* needMapping check here fixes bug [#28112], otherwise it's | /* needMapping check here fixes bug [#28112], otherwise it's | ||||
| * possible that it won't be copied */ | * possible that it won't be copied */ | ||||
| mask |= append_mask; | CustomData_MeshMasks_update(&mask, &append_mask); | ||||
| mesh_set_only_copy(me, mask | (need_mapping ? CD_MASK_ORIGINDEX : 0)); | if (need_mapping) { | ||||
| mask.vmask |= CD_MASK_ORIGINDEX; | |||||
| mask.emask |= CD_MASK_ORIGINDEX; | |||||
| mask.pmask |= CD_MASK_ORIGINDEX; | |||||
| } | |||||
| mesh_set_only_copy(me, &mask); | |||||
| /* add cloth rest shape key if needed */ | /* add cloth rest shape key if needed */ | ||||
| if (mask & CD_MASK_CLOTH_ORCO) | if (mask.vmask & CD_MASK_CLOTH_ORCO) { | ||||
| add_orco_mesh(ob, NULL, me, me_orco, CD_CLOTH_ORCO); | add_orco_mesh(ob, NULL, me, me_orco, CD_CLOTH_ORCO); | ||||
| } | |||||
| /* add an origspace layer if needed */ | /* add an origspace layer if needed */ | ||||
| if ((curr->mask) & CD_MASK_ORIGSPACE_MLOOP) { | if ((curr->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) { | ||||
| if (!CustomData_has_layer(&me->ldata, CD_ORIGSPACE_MLOOP)) { | if (!CustomData_has_layer(&me->ldata, CD_ORIGSPACE_MLOOP)) { | ||||
| CustomData_add_layer(&me->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, me->totloop); | CustomData_add_layer(&me->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, me->totloop); | ||||
| mesh_init_origspace(me); | mesh_init_origspace(me); | ||||
| } | } | ||||
| } | } | ||||
| Mesh *me_next = modwrap_applyModifier(md, &mectx_apply, me); | Mesh *me_next = modwrap_applyModifier(md, &mectx_apply, me); | ||||
| ASSERT_IS_VALID_MESH(me_next); | ASSERT_IS_VALID_MESH(me_next); | ||||
| Show All 12 Lines | else { | ||||
| } | } | ||||
| deformedVerts = NULL; | deformedVerts = NULL; | ||||
| } | } | ||||
| mesh_copy_autosmooth(me, ob->data); | mesh_copy_autosmooth(me, ob->data); | ||||
| } | } | ||||
| /* create an orco mesh in parallel */ | /* create an orco mesh in parallel */ | ||||
| if (nextmask & CD_MASK_ORCO) { | if (nextmask.vmask & CD_MASK_ORCO) { | ||||
| if (!me_orco) { | if (!me_orco) { | ||||
| me_orco = create_orco_mesh(ob, ob->data, NULL, CD_ORCO); | me_orco = create_orco_mesh(ob, ob->data, NULL, CD_ORCO); | ||||
| } | } | ||||
| nextmask &= ~CD_MASK_ORCO; | nextmask.vmask &= ~CD_MASK_ORCO; | ||||
| mesh_set_only_copy(me_orco, nextmask | CD_MASK_ORIGINDEX | | CustomData_MeshMasks temp_cddata_masks = {.vmask=CD_MASK_ORIGINDEX, .emask=CD_MASK_ORIGINDEX, .fmask=CD_MASK_ORIGINDEX, .pmask=CD_MASK_ORIGINDEX}; | ||||
| (mti->requiredDataMask ? | if (mti->requiredDataMask != NULL) { | ||||
| mti->requiredDataMask(ob, md) : 0)); | mti->requiredDataMask(ob, md, &temp_cddata_masks); | ||||
| } | |||||
| CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask); | |||||
| mesh_set_only_copy(me_orco, &temp_cddata_masks); | |||||
| me_next = modwrap_applyModifier(md, &mectx_orco, me_orco); | me_next = modwrap_applyModifier(md, &mectx_orco, me_orco); | ||||
| ASSERT_IS_VALID_MESH(me_next); | ASSERT_IS_VALID_MESH(me_next); | ||||
| if (me_next) { | if (me_next) { | ||||
| /* if the modifier returned a new mesh, release the old one */ | /* if the modifier returned a new mesh, release the old one */ | ||||
| if (me_orco && me_orco != me_next) { | if (me_orco && me_orco != me_next) { | ||||
| BLI_assert(me_orco != ob->data); | BLI_assert(me_orco != ob->data); | ||||
| BKE_id_free(NULL, me_orco); | BKE_id_free(NULL, me_orco); | ||||
| } | } | ||||
| me_orco = me_next; | me_orco = me_next; | ||||
| } | } | ||||
| } | } | ||||
| /* create cloth orco mesh in parallel */ | /* create cloth orco mesh in parallel */ | ||||
| if (nextmask & CD_MASK_CLOTH_ORCO) { | if (nextmask.vmask & CD_MASK_CLOTH_ORCO) { | ||||
| if (!me_orco_cloth) { | if (!me_orco_cloth) { | ||||
| me_orco_cloth = create_orco_mesh(ob, ob->data, NULL, CD_CLOTH_ORCO); | me_orco_cloth = create_orco_mesh(ob, ob->data, NULL, CD_CLOTH_ORCO); | ||||
| } | } | ||||
| nextmask &= ~CD_MASK_CLOTH_ORCO; | nextmask.vmask &= ~CD_MASK_CLOTH_ORCO; | ||||
| mesh_set_only_copy(me_orco_cloth, nextmask | CD_MASK_ORIGINDEX); | nextmask.vmask |= CD_MASK_ORIGINDEX; | ||||
| nextmask.emask |= CD_MASK_ORIGINDEX; | |||||
| nextmask.pmask |= CD_MASK_ORIGINDEX; | |||||
| mesh_set_only_copy(me_orco_cloth, &nextmask); | |||||
| me_next = modwrap_applyModifier(md, &mectx_orco, me_orco_cloth); | me_next = modwrap_applyModifier(md, &mectx_orco, me_orco_cloth); | ||||
| ASSERT_IS_VALID_MESH(me_next); | ASSERT_IS_VALID_MESH(me_next); | ||||
| if (me_next) { | if (me_next) { | ||||
| /* if the modifier returned a new mesh, release the old one */ | /* if the modifier returned a new mesh, release the old one */ | ||||
| if (me_orco_cloth && me_orco_cloth != me_next) { | if (me_orco_cloth && me_orco_cloth != me_next) { | ||||
| BLI_assert(me_orco != ob->data); | BLI_assert(me_orco != ob->data); | ||||
| BKE_id_free(NULL, me_orco_cloth); | BKE_id_free(NULL, me_orco_cloth); | ||||
| } | } | ||||
| me_orco_cloth = me_next; | me_orco_cloth = me_next; | ||||
| } | } | ||||
| } | } | ||||
| /* in case of dynamic paint, make sure preview mask remains for following modifiers */ | /* in case of dynamic paint, make sure preview mask remains for following modifiers */ | ||||
| /* XXX Temp and hackish solution! */ | /* XXX Temp and hackish solution! */ | ||||
| if (md->type == eModifierType_DynamicPaint) | if (md->type == eModifierType_DynamicPaint) { | ||||
| append_mask |= CD_MASK_PREVIEW_MLOOPCOL; | append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL; | ||||
| } | |||||
| me->runtime.deformed_only = false; | me->runtime.deformed_only = false; | ||||
| } | } | ||||
| isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); | isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); | ||||
| /* grab modifiers until index i */ | /* grab modifiers until index i */ | ||||
| if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index)) | if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index)) | ||||
| Show All 26 Lines | else { | ||||
| } | } | ||||
| if (deformedVerts) { | if (deformedVerts) { | ||||
| BKE_mesh_apply_vert_coords(*r_final, deformedVerts); | BKE_mesh_apply_vert_coords(*r_final, deformedVerts); | ||||
| } | } | ||||
| } | } | ||||
| /* add an orco layer if needed */ | /* add an orco layer if needed */ | ||||
| if (dataMask & CD_MASK_ORCO) { | if (dataMask->vmask & CD_MASK_ORCO) { | ||||
| add_orco_mesh(ob, NULL, *r_final, me_orco, CD_ORCO); | add_orco_mesh(ob, NULL, *r_final, me_orco, CD_ORCO); | ||||
| if (r_deform && *r_deform) | if (r_deform && *r_deform) | ||||
| add_orco_mesh(ob, NULL, *r_deform, NULL, CD_ORCO); | add_orco_mesh(ob, NULL, *r_deform, NULL, CD_ORCO); | ||||
| } | } | ||||
| if (do_loop_normals) { | if (do_loop_normals) { | ||||
| /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */ | /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */ | ||||
| BKE_mesh_calc_normals_split(*r_final); | BKE_mesh_calc_normals_split(*r_final); | ||||
| BKE_mesh_tessface_clear(*r_final); | BKE_mesh_tessface_clear(*r_final); | ||||
| } | } | ||||
| if (sculpt_dyntopo == false) { | if (sculpt_dyntopo == false) { | ||||
| /* watch this! after 2.75a we move to from tessface to looptri (by default) */ | /* watch this! after 2.75a we move to from tessface to looptri (by default) */ | ||||
| if (dataMask & CD_MASK_MFACE) { | if (dataMask->fmask & CD_MASK_MFACE) { | ||||
| BKE_mesh_tessface_ensure(*r_final); | BKE_mesh_tessface_ensure(*r_final); | ||||
| } | } | ||||
| /* without this, drawing ngon tri's faces will show ugly tessellated face | /* without this, drawing ngon tri's faces will show ugly tessellated face | ||||
| * normals and will also have to calculate normals on the fly, try avoid | * normals and will also have to calculate normals on the fly, try avoid | ||||
| * this where possible since calculating polygon normals isn't fast, | * this where possible since calculating polygon normals isn't fast, | ||||
| * note that this isn't a problem for subsurf (only quads) or editmode | * note that this isn't a problem for subsurf (only quads) or editmode | ||||
| * which deals with drawing differently. | * which deals with drawing differently. | ||||
| Show All 25 Lines | static void mesh_calc_modifiers( | ||||
| BLI_linklist_free((LinkNode *)datamasks, NULL); | BLI_linklist_free((LinkNode *)datamasks, NULL); | ||||
| } | } | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| static void mesh_calc_modifiers_dm( | static void mesh_calc_modifiers_dm( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, float (*inputVertexCos)[3], | struct Depsgraph *depsgraph, Scene *scene, Object *ob, float (*inputVertexCos)[3], | ||||
| int useDeform, | int useDeform, | ||||
| const bool need_mapping, CustomDataMask dataMask, | const bool need_mapping, const CustomData_MeshMasks *dataMask, | ||||
| const int index, const bool useCache, const bool build_shapekey_layers, | const int index, const bool useCache, const bool build_shapekey_layers, | ||||
| /* return args */ | /* return args */ | ||||
| DerivedMesh **r_deformdm, DerivedMesh **r_finaldm) | DerivedMesh **r_deformdm, DerivedMesh **r_finaldm) | ||||
| { | { | ||||
| Mesh *deform_mesh = NULL, *final_mesh = NULL; | Mesh *deform_mesh = NULL, *final_mesh = NULL; | ||||
| mesh_calc_modifiers( | mesh_calc_modifiers( | ||||
| depsgraph, scene, ob, inputVertexCos, useDeform, | depsgraph, scene, ob, inputVertexCos, useDeform, | ||||
| need_mapping, dataMask, index, useCache, build_shapekey_layers, | need_mapping, dataMask, index, useCache, build_shapekey_layers, | ||||
| (r_deformdm ? &deform_mesh : NULL), &final_mesh); | (r_deformdm ? &deform_mesh : NULL), &final_mesh); | ||||
| if (deform_mesh) { | if (deform_mesh) { | ||||
| *r_deformdm = CDDM_from_mesh_ex(deform_mesh, CD_DUPLICATE, CD_MASK_MESH); | *r_deformdm = CDDM_from_mesh_ex(deform_mesh, CD_DUPLICATE, &CD_MASK_MESH); | ||||
| BKE_id_free(NULL, deform_mesh); | BKE_id_free(NULL, deform_mesh); | ||||
| } | } | ||||
| *r_finaldm = CDDM_from_mesh_ex(final_mesh, CD_DUPLICATE, CD_MASK_MESH); | *r_finaldm = CDDM_from_mesh_ex(final_mesh, CD_DUPLICATE, &CD_MASK_MESH); | ||||
| BKE_id_free(NULL, final_mesh); | BKE_id_free(NULL, final_mesh); | ||||
| } | } | ||||
| #endif | #endif | ||||
| float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3] | float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3] | ||||
| { | { | ||||
| BMIter iter; | BMIter iter; | ||||
| BMVert *eve; | BMVert *eve; | ||||
| Show All 25 Lines | if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| static void editbmesh_calc_modifiers( | static void editbmesh_calc_modifiers( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, | struct Depsgraph *depsgraph, Scene *scene, Object *ob, | ||||
| BMEditMesh *em, CustomDataMask dataMask, | BMEditMesh *em, const CustomData_MeshMasks *dataMask, | ||||
| /* return args */ | /* return args */ | ||||
| Mesh **r_cage, Mesh **r_final) | Mesh **r_cage, Mesh **r_final) | ||||
| { | { | ||||
| ModifierData *md; | ModifierData *md; | ||||
| float (*deformedVerts)[3] = NULL; | float (*deformedVerts)[3] = NULL; | ||||
| CustomDataMask mask = 0, append_mask = CD_MASK_BAREMESH; | CustomData_MeshMasks mask = {0}, append_mask = CD_MASK_BAREMESH; | ||||
| int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); | int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); | ||||
| CDMaskLink *datamasks, *curr; | CDMaskLink *datamasks, *curr; | ||||
| const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; | const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; | ||||
| const bool do_init_statvis = false; /* FIXME: use V3D_OVERLAY_EDIT_STATVIS. */ | const bool do_init_statvis = false; /* FIXME: use V3D_OVERLAY_EDIT_STATVIS. */ | ||||
| VirtualModifierData virtualModifierData; | VirtualModifierData virtualModifierData; | ||||
| /* TODO(sybren): do we really need multiple objects, or shall we change the flags where needed? */ | /* TODO(sybren): do we really need multiple objects, or shall we change the flags where needed? */ | ||||
| const ModifierEvalContext mectx = {depsgraph, ob, 0}; | const ModifierEvalContext mectx = {depsgraph, ob, 0}; | ||||
| const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO}; | const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO}; | ||||
| const ModifierEvalContext mectx_cache = {depsgraph, ob, MOD_APPLY_USECACHE}; | const ModifierEvalContext mectx_cache = {depsgraph, ob, MOD_APPLY_USECACHE}; | ||||
| const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH) != 0; | const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH) != 0; | ||||
| modifiers_clearErrors(ob); | modifiers_clearErrors(ob); | ||||
| if (r_cage && cageIndex == -1) { | if (r_cage && cageIndex == -1) { | ||||
| *r_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, dataMask, NULL); | *r_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, dataMask, NULL); | ||||
| mesh_copy_autosmooth(*r_cage, ob->data); | mesh_copy_autosmooth(*r_cage, ob->data); | ||||
| } | } | ||||
| md = modifiers_getVirtualModifierList(ob, &virtualModifierData); | md = modifiers_getVirtualModifierList(ob, &virtualModifierData); | ||||
| /* copied from mesh_calc_modifiers */ | /* copied from mesh_calc_modifiers */ | ||||
| datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, NULL, 0); | datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, NULL, NULL); | ||||
| curr = datamasks; | curr = datamasks; | ||||
| Mesh *me = NULL; | Mesh *me = NULL; | ||||
| Mesh *me_orco = NULL; | Mesh *me_orco = NULL; | ||||
| for (i = 0; md; i++, md = md->next, curr = curr->next) { | for (i = 0; md; i++, md = md->next, curr = curr->next) { | ||||
| const ModifierTypeInfo *mti = modifierType_getInfo(md->type); | const ModifierTypeInfo *mti = modifierType_getInfo(md->type); | ||||
| memset(&mask, 0, sizeof(mask)); | |||||
| if (!editbmesh_modifier_is_enabled(scene, md, me != NULL)) { | if (!editbmesh_modifier_is_enabled(scene, md, me != NULL)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* add an orco layer if needed by this modifier */ | /* add an orco layer if needed by this modifier */ | ||||
| if (me && mti->requiredDataMask) { | if (me && mti->requiredDataMask) { | ||||
| mask = mti->requiredDataMask(ob, md); | mti->requiredDataMask(ob, md, &mask); | ||||
| if (mask & CD_MASK_ORCO) { | if (mask.vmask & CD_MASK_ORCO) { | ||||
| add_orco_mesh(ob, em, me, me_orco, CD_ORCO); | add_orco_mesh(ob, em, me, me_orco, CD_ORCO); | ||||
| } | } | ||||
| } | } | ||||
| /* How to apply modifier depends on (a) what we already have as | /* How to apply modifier depends on (a) what we already have as | ||||
| * a result of previous modifiers (could be a DerivedMesh or just | * a result of previous modifiers (could be a DerivedMesh or just | ||||
| * deformed vertices) and (b) what type the modifier is. | * deformed vertices) and (b) what type the modifier is. | ||||
| */ | */ | ||||
| Show All 34 Lines | else { | ||||
| } | } | ||||
| else if (r_cage && me == *r_cage) { | else if (r_cage && me == *r_cage) { | ||||
| /* 'me' may be changed by this modifier, so we need to copy it. */ | /* 'me' may be changed by this modifier, so we need to copy it. */ | ||||
| me = BKE_mesh_copy_for_eval(me, false); | me = BKE_mesh_copy_for_eval(me, false); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, 0); | me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL); | ||||
| ASSERT_IS_VALID_MESH(me); | ASSERT_IS_VALID_MESH(me); | ||||
| mesh_copy_autosmooth(me, ob->data); | mesh_copy_autosmooth(me, ob->data); | ||||
| if (deformedVerts) { | if (deformedVerts) { | ||||
| BKE_mesh_apply_vert_coords(me, deformedVerts); | BKE_mesh_apply_vert_coords(me, deformedVerts); | ||||
| } | } | ||||
| } | } | ||||
| /* create an orco derivedmesh in parallel */ | /* create an orco derivedmesh in parallel */ | ||||
| mask = curr->mask; | mask = curr->mask; | ||||
| if (mask & CD_MASK_ORCO) { | if (mask.vmask & CD_MASK_ORCO) { | ||||
| if (!me_orco) { | if (!me_orco) { | ||||
| me_orco = create_orco_mesh(ob, ob->data, em, CD_ORCO); | me_orco = create_orco_mesh(ob, ob->data, em, CD_ORCO); | ||||
| } | } | ||||
| mask &= ~CD_MASK_ORCO; | mask.vmask &= ~CD_MASK_ORCO; | ||||
| mesh_set_only_copy(me_orco, mask | CD_MASK_ORIGINDEX); | mask.vmask |= CD_MASK_ORIGINDEX; | ||||
| mask.emask |= CD_MASK_ORIGINDEX; | |||||
| mask.pmask |= CD_MASK_ORIGINDEX; | |||||
| mesh_set_only_copy(me_orco, &mask); | |||||
| me_next = modwrap_applyModifier(md, &mectx_orco, me_orco); | me_next = modwrap_applyModifier(md, &mectx_orco, me_orco); | ||||
| ASSERT_IS_VALID_MESH(me_next); | ASSERT_IS_VALID_MESH(me_next); | ||||
| if (me_next) { | if (me_next) { | ||||
| /* if the modifier returned a new dm, release the old one */ | /* if the modifier returned a new dm, release the old one */ | ||||
| if (me_orco && me_orco != me_next) { | if (me_orco && me_orco != me_next) { | ||||
| BKE_id_free(NULL, me_orco); | BKE_id_free(NULL, me_orco); | ||||
| } | } | ||||
| me_orco = me_next; | me_orco = me_next; | ||||
| } | } | ||||
| } | } | ||||
| /* set the DerivedMesh to only copy needed data */ | /* set the DerivedMesh to only copy needed data */ | ||||
| mask |= append_mask; | CustomData_MeshMasks_update(&mask, &append_mask); | ||||
| mask = curr->mask; /* CD_MASK_ORCO may have been cleared above */ | mask = curr->mask; /* CD_MASK_ORCO may have been cleared above */ /* XXX WHAT? ovewrites mask ??? */ | ||||
| mask.vmask |= CD_MASK_ORIGINDEX; | |||||
| mask.emask |= CD_MASK_ORIGINDEX; | |||||
| mask.pmask |= CD_MASK_ORIGINDEX; | |||||
| mesh_set_only_copy(me, mask | CD_MASK_ORIGINDEX); | mesh_set_only_copy(me, &mask); | ||||
| if (mask & CD_MASK_ORIGSPACE_MLOOP) { | if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) { | ||||
| if (!CustomData_has_layer(&me->ldata, CD_ORIGSPACE_MLOOP)) { | if (!CustomData_has_layer(&me->ldata, CD_ORIGSPACE_MLOOP)) { | ||||
| CustomData_add_layer(&me->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, me->totloop); | CustomData_add_layer(&me->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, me->totloop); | ||||
| mesh_init_origspace(me); | mesh_init_origspace(me); | ||||
| } | } | ||||
| } | } | ||||
| me_next = modwrap_applyModifier(md, &mectx_cache, me); | me_next = modwrap_applyModifier(md, &mectx_cache, me); | ||||
| ASSERT_IS_VALID_MESH(me_next); | ASSERT_IS_VALID_MESH(me_next); | ||||
| Show All 24 Lines | if (r_cage && i == cageIndex) { | ||||
| } | } | ||||
| else { | else { | ||||
| Mesh *me_orig = ob->data; | Mesh *me_orig = ob->data; | ||||
| if (me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) { | if (me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) { | ||||
| BKE_mesh_runtime_ensure_edit_data(me_orig); | BKE_mesh_runtime_ensure_edit_data(me_orig); | ||||
| me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformedVerts); | me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformedVerts); | ||||
| } | } | ||||
| *r_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap( | *r_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap( | ||||
| em, mask, | em, &mask, | ||||
| deformedVerts ? MEM_dupallocN(deformedVerts) : NULL); | deformedVerts ? MEM_dupallocN(deformedVerts) : NULL); | ||||
| mesh_copy_autosmooth(*r_cage, ob->data); | mesh_copy_autosmooth(*r_cage, ob->data); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_linklist_free((LinkNode *)datamasks, NULL); | BLI_linklist_free((LinkNode *)datamasks, NULL); | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (r_cage && *r_cage && (*r_cage != *r_final)) { | ||||
| BKE_mesh_tessface_clear(*r_cage); | BKE_mesh_tessface_clear(*r_cage); | ||||
| } | } | ||||
| } | } | ||||
| /* BMESH_ONLY, ensure tessface's used for drawing, | /* BMESH_ONLY, ensure tessface's used for drawing, | ||||
| * but don't recalculate if the last modifier in the stack gives us tessfaces | * but don't recalculate if the last modifier in the stack gives us tessfaces | ||||
| * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential | * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential | ||||
| * but quiets annoying error messages since tessfaces wont be created. */ | * but quiets annoying error messages since tessfaces wont be created. */ | ||||
| if (dataMask & CD_MASK_MFACE) { | if (dataMask->fmask & CD_MASK_MFACE) { | ||||
| if ((*r_final)->edit_mesh == NULL) { | if ((*r_final)->edit_mesh == NULL) { | ||||
| BKE_mesh_tessface_ensure(*r_final); | BKE_mesh_tessface_ensure(*r_final); | ||||
| } | } | ||||
| if (r_cage && *r_cage) { | if (r_cage && *r_cage) { | ||||
| if ((*r_cage)->edit_mesh == NULL) { | if ((*r_cage)->edit_mesh == NULL) { | ||||
| if (*r_cage != *r_final) { | if (*r_cage != *r_final) { | ||||
| BKE_mesh_tessface_ensure(*r_cage); | BKE_mesh_tessface_ensure(*r_cage); | ||||
| } | } | ||||
| Show All 16 Lines | if (CustomData_has_layer(&(*r_final)->ldata, CD_NORMAL)) { | ||||
| CustomData_free_layers(&(*r_final)->ldata, CD_NORMAL, (*r_final)->totloop); | CustomData_free_layers(&(*r_final)->ldata, CD_NORMAL, (*r_final)->totloop); | ||||
| } | } | ||||
| if (r_cage && CustomData_has_layer(&(*r_cage)->ldata, CD_NORMAL)) { | if (r_cage && CustomData_has_layer(&(*r_cage)->ldata, CD_NORMAL)) { | ||||
| CustomData_free_layers(&(*r_cage)->ldata, CD_NORMAL, (*r_cage)->totloop); | CustomData_free_layers(&(*r_cage)->ldata, CD_NORMAL, (*r_cage)->totloop); | ||||
| } | } | ||||
| } | } | ||||
| /* add an orco layer if needed */ | /* add an orco layer if needed */ | ||||
| if (dataMask & CD_MASK_ORCO) | if (dataMask->vmask & CD_MASK_ORCO) | ||||
| add_orco_mesh(ob, em, *r_final, me_orco, CD_ORCO); | add_orco_mesh(ob, em, *r_final, me_orco, CD_ORCO); | ||||
| if (me_orco) { | if (me_orco) { | ||||
| BKE_id_free(NULL, me_orco); | BKE_id_free(NULL, me_orco); | ||||
| } | } | ||||
| if (deformedVerts) { | if (deformedVerts) { | ||||
| MEM_freeN(deformedVerts); | MEM_freeN(deformedVerts); | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| UNUSED_VARS_NDEBUG(mesh); | UNUSED_VARS_NDEBUG(mesh); | ||||
| BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)); | BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)); | ||||
| BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL)); | BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL)); | ||||
| BLI_assert(!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL)); | BLI_assert(!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL)); | ||||
| } | } | ||||
| static void mesh_build_data( | static void mesh_build_data( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask, | struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask, | ||||
| const bool build_shapekey_layers, const bool need_mapping) | const bool build_shapekey_layers, const bool need_mapping) | ||||
| { | { | ||||
| BLI_assert(ob->type == OB_MESH); | BLI_assert(ob->type == OB_MESH); | ||||
| /* Evaluated meshes aren't supposed to be created on original instances. If you do, | /* Evaluated meshes aren't supposed to be created on original instances. If you do, | ||||
| * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ | * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ | ||||
| BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | ||||
| BKE_object_free_derived_caches(ob); | BKE_object_free_derived_caches(ob); | ||||
| BKE_object_sculpt_modifiers_changed(ob); | BKE_object_sculpt_modifiers_changed(ob); | ||||
| #if 0 /* XXX This is already taken care of in mesh_calc_modifiers()... */ | |||||
| if (need_mapping) { | if (need_mapping) { | ||||
| /* Also add the flag so that it is recorded in lastDataMask. */ | /* Also add the flag so that it is recorded in lastDataMask. */ | ||||
| dataMask |= CD_MASK_ORIGINDEX; | dataMask->vmask |= CD_MASK_ORIGINDEX; | ||||
| dataMask->emask |= CD_MASK_ORIGINDEX; | |||||
| dataMask->pmask |= CD_MASK_ORIGINDEX; | |||||
| } | } | ||||
| #endif | |||||
| mesh_calc_modifiers( | mesh_calc_modifiers( | ||||
| depsgraph, scene, ob, NULL, 1, need_mapping, dataMask, -1, true, build_shapekey_layers, | depsgraph, scene, ob, NULL, 1, need_mapping, dataMask, -1, true, build_shapekey_layers, | ||||
| &ob->runtime.mesh_deform_eval, &ob->runtime.mesh_eval); | &ob->runtime.mesh_deform_eval, &ob->runtime.mesh_eval); | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| /* TODO(campbell): remove these copies, they are expected in various places over the code. */ | /* TODO(campbell): remove these copies, they are expected in various places over the code. */ | ||||
| ob->derivedDeform = CDDM_from_mesh_ex(ob->runtime.mesh_deform_eval, CD_REFERENCE, CD_MASK_MESH); | ob->derivedDeform = CDDM_from_mesh_ex(ob->runtime.mesh_deform_eval, CD_REFERENCE, &CD_MASK_MESH); | ||||
| ob->derivedFinal = CDDM_from_mesh_ex(ob->runtime.mesh_eval, CD_REFERENCE, CD_MASK_MESH); | ob->derivedFinal = CDDM_from_mesh_ex(ob->runtime.mesh_eval, CD_REFERENCE, &CD_MASK_MESH); | ||||
| #endif | #endif | ||||
| BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval); | BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval); | ||||
| /* Only copy texspace from orig mesh if some modifier (hint: smoke sim, see T58492) | /* Only copy texspace from orig mesh if some modifier (hint: smoke sim, see T58492) | ||||
| * did not re-enable that flag (which always get disabled for eval mesh as a start). */ | * did not re-enable that flag (which always get disabled for eval mesh as a start). */ | ||||
| if (!(ob->runtime.mesh_eval->texflag & ME_AUTOSPACE)) { | if (!(ob->runtime.mesh_eval->texflag & ME_AUTOSPACE)) { | ||||
| BKE_mesh_texspace_copy_from_object(ob->runtime.mesh_eval, ob); | BKE_mesh_texspace_copy_from_object(ob->runtime.mesh_eval, ob); | ||||
| } | } | ||||
| mesh_finalize_eval(ob); | mesh_finalize_eval(ob); | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| ob->derivedFinal->needsFree = 0; | ob->derivedFinal->needsFree = 0; | ||||
| ob->derivedDeform->needsFree = 0; | ob->derivedDeform->needsFree = 0; | ||||
| #endif | #endif | ||||
| ob->runtime.last_data_mask = dataMask; | ob->runtime.last_data_mask = *dataMask; | ||||
| ob->runtime.last_need_mapping = need_mapping; | ob->runtime.last_need_mapping = need_mapping; | ||||
| if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { | if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { | ||||
| /* create PBVH immediately (would be created on the fly too, | /* create PBVH immediately (would be created on the fly too, | ||||
| * but this avoids waiting on first stroke) */ | * but this avoids waiting on first stroke) */ | ||||
| /* XXX Disabled for now. | /* XXX Disabled for now. | ||||
| * This can create horrible nasty bugs by generating re-entrant call of mesh_get_eval_final! */ | * This can create horrible nasty bugs by generating re-entrant call of mesh_get_eval_final! */ | ||||
| // BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); | // BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); | ||||
| } | } | ||||
| mesh_runtime_check_normals_valid(ob->runtime.mesh_eval); | mesh_runtime_check_normals_valid(ob->runtime.mesh_eval); | ||||
| mesh_build_extra_data(depsgraph, ob); | mesh_build_extra_data(depsgraph, ob); | ||||
| } | } | ||||
| static void editbmesh_build_data( | static void editbmesh_build_data( | ||||
| struct Depsgraph *depsgraph, Scene *scene, | struct Depsgraph *depsgraph, Scene *scene, | ||||
| Object *obedit, BMEditMesh *em, CustomDataMask dataMask) | Object *obedit, BMEditMesh *em, CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| BLI_assert(em->ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | BLI_assert(em->ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | ||||
| BKE_object_free_derived_caches(obedit); | BKE_object_free_derived_caches(obedit); | ||||
| BKE_object_sculpt_modifiers_changed(obedit); | BKE_object_sculpt_modifiers_changed(obedit); | ||||
| BKE_editmesh_free_derivedmesh(em); | BKE_editmesh_free_derivedmesh(em); | ||||
| Mesh *me_cage; | Mesh *me_cage; | ||||
| Mesh *me_final; | Mesh *me_final; | ||||
| editbmesh_calc_modifiers( | editbmesh_calc_modifiers( | ||||
| depsgraph, scene, obedit, em, dataMask, | depsgraph, scene, obedit, em, dataMask, | ||||
| &me_cage, &me_final); | &me_cage, &me_final); | ||||
| em->mesh_eval_final = me_final; | em->mesh_eval_final = me_final; | ||||
| em->mesh_eval_cage = me_cage; | em->mesh_eval_cage = me_cage; | ||||
| BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final); | BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final); | ||||
| em->lastDataMask = dataMask; | em->lastDataMask = *dataMask; | ||||
| mesh_runtime_check_normals_valid(em->mesh_eval_final); | mesh_runtime_check_normals_valid(em->mesh_eval_final); | ||||
| } | } | ||||
| static CustomDataMask object_get_datamask(const Depsgraph *depsgraph, Object *ob, bool *r_need_mapping) | static void object_get_datamask(const Depsgraph *depsgraph, Object *ob, CustomData_MeshMasks *r_mask, bool *r_need_mapping) | ||||
| { | { | ||||
| ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); | ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); | ||||
| Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL; | Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL; | ||||
| CustomDataMask mask = DEG_get_customdata_mask_for_object(depsgraph, ob); | |||||
| DEG_get_customdata_mask_for_object(depsgraph, ob, r_mask); | |||||
| if (r_need_mapping) { | if (r_need_mapping) { | ||||
| *r_need_mapping = false; | *r_need_mapping = false; | ||||
| } | } | ||||
| if (DEG_get_original_object(ob) == actob) { | if (DEG_get_original_object(ob) == actob) { | ||||
| bool editing = BKE_paint_select_face_test(actob); | bool editing = BKE_paint_select_face_test(actob); | ||||
| /* weight paint and face select need original indices because of selection buffer drawing */ | /* weight paint and face select need original indices because of selection buffer drawing */ | ||||
| if (r_need_mapping) { | if (r_need_mapping) { | ||||
| *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT))); | *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT))); | ||||
| } | } | ||||
| /* check if we need tfaces & mcols due to face select or texture paint */ | /* check if we need tfaces & mcols due to face select or texture paint */ | ||||
| if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) { | if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) { | ||||
| mask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTFACE; | r_mask->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; | ||||
| r_mask->fmask |= CD_MASK_MTFACE; | |||||
| } | } | ||||
| /* check if we need mcols due to vertex paint or weightpaint */ | /* check if we need mcols due to vertex paint or weightpaint */ | ||||
| if (ob->mode & OB_MODE_VERTEX_PAINT) { | if (ob->mode & OB_MODE_VERTEX_PAINT) { | ||||
| mask |= CD_MASK_MLOOPCOL; | r_mask->lmask |= CD_MASK_MLOOPCOL; | ||||
| } | } | ||||
| if (ob->mode & OB_MODE_WEIGHT_PAINT) { | if (ob->mode & OB_MODE_WEIGHT_PAINT) { | ||||
| mask |= CD_MASK_MDEFORMVERT; | r_mask->vmask |= CD_MASK_MDEFORMVERT; | ||||
| } | } | ||||
| if (ob->mode & OB_MODE_EDIT) | if (ob->mode & OB_MODE_EDIT) | ||||
| mask |= CD_MASK_MVERT_SKIN; | r_mask->vmask |= CD_MASK_MVERT_SKIN; | ||||
| } | } | ||||
| return mask; | |||||
| } | } | ||||
| void makeDerivedMesh( | void makeDerivedMesh( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, BMEditMesh *em, | struct Depsgraph *depsgraph, Scene *scene, Object *ob, BMEditMesh *em, | ||||
| CustomDataMask dataMask, const bool build_shapekey_layers) | const CustomData_MeshMasks *dataMask, const bool build_shapekey_layers) | ||||
| { | { | ||||
| bool need_mapping; | bool need_mapping; | ||||
| dataMask |= object_get_datamask(depsgraph, ob, &need_mapping); | CustomData_MeshMasks cddata_masks = *dataMask; | ||||
| object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); | |||||
| if (em) { | if (em) { | ||||
| editbmesh_build_data(depsgraph, scene, ob, em, dataMask); | editbmesh_build_data(depsgraph, scene, ob, em, &cddata_masks); | ||||
| } | } | ||||
| else { | else { | ||||
| mesh_build_data(depsgraph, scene, ob, dataMask, build_shapekey_layers, need_mapping); | mesh_build_data(depsgraph, scene, ob, &cddata_masks, build_shapekey_layers, need_mapping); | ||||
| } | } | ||||
| } | } | ||||
| /***/ | /***/ | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| /* Deprecated DM, use: 'mesh_get_eval_final'. */ | /* Deprecated DM, use: 'mesh_get_eval_final'. */ | ||||
| DerivedMesh *mesh_get_derived_final( | DerivedMesh *mesh_get_derived_final( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask) | struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| /* if there's no derived mesh or the last data mask used doesn't include | /* if there's no derived mesh or the last data mask used doesn't include | ||||
| * the data we need, rebuild the derived mesh | * the data we need, rebuild the derived mesh | ||||
| */ | */ | ||||
| bool need_mapping; | bool need_mapping; | ||||
| dataMask |= object_get_datamask(depsgraph, ob, &need_mapping); | CustomData_MeshMasks cddata_masks = *dataMask; | ||||
| object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); | |||||
| if (!ob->derivedFinal || | if (!ob->derivedFinal || | ||||
| ((dataMask & ob->lastDataMask) != dataMask) || | !CustomData_MeshMasks_are_matching(&(ob->lastDataMask), &cddata_masks) || | ||||
| (need_mapping != ob->lastNeedMapping)) | (need_mapping != ob->lastNeedMapping)) | ||||
| { | { | ||||
| mesh_build_data(depsgraph, scene, ob, dataMask, false, need_mapping); | mesh_build_data(depsgraph, scene, ob, cddata_masks, false, need_mapping); | ||||
| } | } | ||||
| if (ob->derivedFinal) { BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); } | if (ob->derivedFinal) { BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); } | ||||
| return ob->derivedFinal; | return ob->derivedFinal; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mesh *mesh_get_eval_final( | Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask) | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask) | |||||
| { | { | ||||
| /* This function isn't thread-safe and can't be used during evaluation. */ | /* This function isn't thread-safe and can't be used during evaluation. */ | ||||
| BLI_assert(DEG_debug_is_evaluating(depsgraph) == false); | BLI_assert(DEG_debug_is_evaluating(depsgraph) == false); | ||||
| /* Evaluated meshes aren't supposed to be created on original instances. If you do, | /* Evaluated meshes aren't supposed to be created on original instances. If you do, | ||||
| * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ | * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ | ||||
| BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | ||||
| /* if there's no evaluated mesh or the last data mask used doesn't include | /* if there's no evaluated mesh or the last data mask used doesn't include | ||||
| * the data we need, rebuild the derived mesh | * the data we need, rebuild the derived mesh | ||||
| */ | */ | ||||
| bool need_mapping; | bool need_mapping; | ||||
| dataMask |= object_get_datamask(depsgraph, ob, &need_mapping); | CustomData_MeshMasks cddata_masks = *dataMask; | ||||
| object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); | |||||
| if (!ob->runtime.mesh_eval || | if (!ob->runtime.mesh_eval || | ||||
| ((dataMask & ob->runtime.last_data_mask) != dataMask) || | !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || | ||||
| (need_mapping && !ob->runtime.last_need_mapping)) | (need_mapping && !ob->runtime.last_need_mapping)) | ||||
| { | { | ||||
| mesh_build_data(depsgraph, scene, ob, dataMask | ob->runtime.last_data_mask, | CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); | ||||
| mesh_build_data(depsgraph, scene, ob, &cddata_masks, | |||||
| false, need_mapping || ob->runtime.last_need_mapping); | false, need_mapping || ob->runtime.last_need_mapping); | ||||
| } | } | ||||
| if (ob->runtime.mesh_eval) { BLI_assert(!(ob->runtime.mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); } | if (ob->runtime.mesh_eval) { BLI_assert(!(ob->runtime.mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); } | ||||
| return ob->runtime.mesh_eval; | return ob->runtime.mesh_eval; | ||||
| } | } | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| /* Deprecated DM, use: 'mesh_get_eval_deform' instead. */ | /* Deprecated DM, use: 'mesh_get_eval_deform' instead. */ | ||||
| DerivedMesh *mesh_get_derived_deform(struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask) | DerivedMesh *mesh_get_derived_deform(struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| /* if there's no derived mesh or the last data mask used doesn't include | /* if there's no derived mesh or the last data mask used doesn't include | ||||
| * the data we need, rebuild the derived mesh | * the data we need, rebuild the derived mesh | ||||
| */ | */ | ||||
| bool need_mapping; | bool need_mapping; | ||||
| dataMask |= object_get_datamask(depsgraph, ob, &need_mapping); | CustomData_MeshMasks cddata_masks = *dataMask; | ||||
| object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); | |||||
| if (!ob->derivedDeform || | if (!ob->derivedDeform || | ||||
| ((dataMask & ob->lastDataMask) != dataMask) || | !CustomData_MeshMasks_are_matching(&(ob->lastDataMask), &cddata_masks) || | ||||
| (need_mapping != ob->lastNeedMapping)) | (need_mapping != ob->lastNeedMapping)) | ||||
| { | { | ||||
| mesh_build_data(depsgraph, scene, ob, dataMask, false, need_mapping); | mesh_build_data(depsgraph, scene, ob, cddata_masks, false, need_mapping); | ||||
| } | } | ||||
| return ob->derivedDeform; | return ob->derivedDeform; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask) | Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| /* This function isn't thread-safe and can't be used during evaluation. */ | /* This function isn't thread-safe and can't be used during evaluation. */ | ||||
| BLI_assert(DEG_debug_is_evaluating(depsgraph) == false); | BLI_assert(DEG_debug_is_evaluating(depsgraph) == false); | ||||
| /* Evaluated meshes aren't supposed to be created on original instances. If you do, | /* Evaluated meshes aren't supposed to be created on original instances. If you do, | ||||
| * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ | * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ | ||||
| BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); | ||||
| /* if there's no derived mesh or the last data mask used doesn't include | /* if there's no derived mesh or the last data mask used doesn't include | ||||
| * the data we need, rebuild the derived mesh | * the data we need, rebuild the derived mesh | ||||
| */ | */ | ||||
| bool need_mapping; | bool need_mapping; | ||||
| dataMask |= object_get_datamask(depsgraph, ob, &need_mapping); | CustomData_MeshMasks cddata_masks = *dataMask; | ||||
| object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); | |||||
| if (!ob->runtime.mesh_deform_eval || | if (!ob->runtime.mesh_deform_eval || | ||||
| ((dataMask & ob->runtime.last_data_mask) != dataMask) || | !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || | ||||
| (need_mapping && !ob->runtime.last_need_mapping)) | (need_mapping && !ob->runtime.last_need_mapping)) | ||||
| { | { | ||||
| mesh_build_data(depsgraph, scene, ob, dataMask | ob->runtime.last_data_mask, | CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); | ||||
| mesh_build_data(depsgraph, scene, ob, &cddata_masks, | |||||
| false, need_mapping || ob->runtime.last_need_mapping); | false, need_mapping || ob->runtime.last_need_mapping); | ||||
| } | } | ||||
| return ob->runtime.mesh_deform_eval; | return ob->runtime.mesh_deform_eval; | ||||
| } | } | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| /* Deprecated, use `mesh_create_eval_final_render` instead. */ | /* Deprecated, use `mesh_create_eval_final_render` instead. */ | ||||
| DerivedMesh *mesh_create_derived_render(struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask) | DerivedMesh *mesh_create_derived_render( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask) | |||||
| { | { | ||||
| DerivedMesh *final; | DerivedMesh *final; | ||||
| mesh_calc_modifiers_dm( | mesh_calc_modifiers_dm( | ||||
| depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| return final; | return final; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mesh *mesh_create_eval_final_render(struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask) | Mesh *mesh_create_eval_final_render(Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| Mesh *final; | Mesh *final; | ||||
| mesh_calc_modifiers( | mesh_calc_modifiers( | ||||
| depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| return final; | return final; | ||||
| } | } | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| /* Deprecated, use `mesh_create_eval_final_index_render` instead. */ | /* Deprecated, use `mesh_create_eval_final_index_render` instead. */ | ||||
| DerivedMesh *mesh_create_derived_index_render(struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask, int index) | DerivedMesh *mesh_create_derived_index_render( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask, int index) | |||||
| { | { | ||||
| DerivedMesh *final; | DerivedMesh *final; | ||||
| mesh_calc_modifiers_dm( | mesh_calc_modifiers_dm( | ||||
| depsgraph, scene, ob, NULL, 1, false, dataMask, index, false, false, | depsgraph, scene, ob, NULL, 1, false, dataMask, index, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| return final; | return final; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mesh *mesh_create_eval_final_index_render( | Mesh *mesh_create_eval_final_index_render( | ||||
| struct Depsgraph *depsgraph, struct Scene *scene, | Depsgraph *depsgraph, Scene *scene, | ||||
| struct Object *ob, CustomDataMask dataMask, int index) | Object *ob, const CustomData_MeshMasks *dataMask, int index) | ||||
| { | { | ||||
| Mesh *final; | Mesh *final; | ||||
| mesh_calc_modifiers( | mesh_calc_modifiers( | ||||
| depsgraph, scene, ob, NULL, 1, false, dataMask, index, false, false, | depsgraph, scene, ob, NULL, 1, false, dataMask, index, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| return final; | return final; | ||||
| } | } | ||||
| #ifdef USE_DERIVEDMESH | #ifdef USE_DERIVEDMESH | ||||
| /* Deprecated, use `mesh_create_eval_final_view` instead. */ | /* Deprecated, use `mesh_create_eval_final_view` instead. */ | ||||
| DerivedMesh *mesh_create_derived_view( | DerivedMesh *mesh_create_derived_view( | ||||
| struct Depsgraph *depsgraph, Scene *scene, | struct Depsgraph *depsgraph, Scene *scene, | ||||
| Object *ob, CustomDataMask dataMask) | Object *ob, const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| DerivedMesh *final; | DerivedMesh *final; | ||||
| /* XXX hack | /* XXX hack | ||||
| * psys modifier updates particle state when called during dupli-list generation, | * psys modifier updates particle state when called during dupli-list generation, | ||||
| * which can lead to wrong transforms. This disables particle system modifier execution. | * which can lead to wrong transforms. This disables particle system modifier execution. | ||||
| */ | */ | ||||
| ob->transflag |= OB_NO_PSYS_UPDATE; | ob->transflag |= OB_NO_PSYS_UPDATE; | ||||
| mesh_calc_modifiers_dm( | mesh_calc_modifiers_dm( | ||||
| depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| ob->transflag &= ~OB_NO_PSYS_UPDATE; | ob->transflag &= ~OB_NO_PSYS_UPDATE; | ||||
| return final; | return final; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mesh *mesh_create_eval_final_view( | Mesh *mesh_create_eval_final_view( | ||||
| struct Depsgraph *depsgraph, Scene *scene, | Depsgraph *depsgraph, Scene *scene, | ||||
| Object *ob, CustomDataMask dataMask) | Object *ob, const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| Mesh *final; | Mesh *final; | ||||
| /* XXX hack | /* XXX hack | ||||
| * psys modifier updates particle state when called during dupli-list generation, | * psys modifier updates particle state when called during dupli-list generation, | ||||
| * which can lead to wrong transforms. This disables particle system modifier execution. | * which can lead to wrong transforms. This disables particle system modifier execution. | ||||
| */ | */ | ||||
| ob->transflag |= OB_NO_PSYS_UPDATE; | ob->transflag |= OB_NO_PSYS_UPDATE; | ||||
| mesh_calc_modifiers( | mesh_calc_modifiers( | ||||
| depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | depsgraph, scene, ob, NULL, 1, false, dataMask, -1, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| ob->transflag &= ~OB_NO_PSYS_UPDATE; | ob->transflag &= ~OB_NO_PSYS_UPDATE; | ||||
| return final; | return final; | ||||
| } | } | ||||
| Mesh *mesh_create_eval_no_deform( | Mesh *mesh_create_eval_no_deform( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, | Depsgraph *depsgraph, Scene *scene, Object *ob, | ||||
| float (*vertCos)[3], CustomDataMask dataMask) | float (*vertCos)[3], const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| Mesh *final; | Mesh *final; | ||||
| mesh_calc_modifiers( | mesh_calc_modifiers( | ||||
| depsgraph, scene, ob, vertCos, 0, false, dataMask, -1, false, false, | depsgraph, scene, ob, vertCos, 0, false, dataMask, -1, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| return final; | return final; | ||||
| } | } | ||||
| Mesh *mesh_create_eval_no_deform_render( | Mesh *mesh_create_eval_no_deform_render( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *ob, | Depsgraph *depsgraph, Scene *scene, Object *ob, | ||||
| float (*vertCos)[3], CustomDataMask dataMask) | float (*vertCos)[3], const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| Mesh *final; | Mesh *final; | ||||
| mesh_calc_modifiers( | mesh_calc_modifiers( | ||||
| depsgraph, scene, ob, vertCos, 0, false, dataMask, -1, false, false, | depsgraph, scene, ob, vertCos, 0, false, dataMask, -1, false, false, | ||||
| NULL, &final); | NULL, &final); | ||||
| return final; | return final; | ||||
| } | } | ||||
| /***/ | /***/ | ||||
| Mesh *editbmesh_get_eval_cage_and_final( | Mesh *editbmesh_get_eval_cage_and_final( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *em, | Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *em, | ||||
| CustomDataMask dataMask, | const CustomData_MeshMasks *dataMask, | ||||
| /* return args */ | /* return args */ | ||||
| Mesh **r_final) | Mesh **r_final) | ||||
| { | { | ||||
| CustomData_MeshMasks cddata_masks = *dataMask; | |||||
| /* if there's no derived mesh or the last data mask used doesn't include | /* if there's no derived mesh or the last data mask used doesn't include | ||||
| * the data we need, rebuild the derived mesh | * the data we need, rebuild the derived mesh | ||||
| */ | */ | ||||
| dataMask |= object_get_datamask(depsgraph, obedit, NULL); | object_get_datamask(depsgraph, obedit, &cddata_masks, NULL); | ||||
| if (!em->mesh_eval_cage || | if (!em->mesh_eval_cage || | ||||
| (em->lastDataMask & dataMask) != dataMask) | !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) | ||||
| { | { | ||||
| editbmesh_build_data(depsgraph, scene, obedit, em, dataMask); | editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks); | ||||
| } | } | ||||
| *r_final = em->mesh_eval_final; | *r_final = em->mesh_eval_final; | ||||
| if (em->mesh_eval_final) { BLI_assert(!(em->mesh_eval_final->runtime.cd_dirty_vert & DM_DIRTY_NORMALS)); } | if (em->mesh_eval_final) { BLI_assert(!(em->mesh_eval_final->runtime.cd_dirty_vert & DM_DIRTY_NORMALS)); } | ||||
| return em->mesh_eval_cage; | return em->mesh_eval_cage; | ||||
| } | } | ||||
| Mesh *editbmesh_get_eval_cage( | Mesh *editbmesh_get_eval_cage( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *em, | struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *em, | ||||
| CustomDataMask dataMask) | const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| CustomData_MeshMasks cddata_masks = *dataMask; | |||||
| /* if there's no derived mesh or the last data mask used doesn't include | /* if there's no derived mesh or the last data mask used doesn't include | ||||
| * the data we need, rebuild the derived mesh | * the data we need, rebuild the derived mesh | ||||
| */ | */ | ||||
| dataMask |= object_get_datamask(depsgraph, obedit, NULL); | object_get_datamask(depsgraph, obedit, &cddata_masks, NULL); | ||||
| if (!em->mesh_eval_cage || | if (!em->mesh_eval_cage || | ||||
| (em->lastDataMask & dataMask) != dataMask) | !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) | ||||
| { | { | ||||
| editbmesh_build_data(depsgraph, scene, obedit, em, dataMask); | editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks); | ||||
| } | } | ||||
| return em->mesh_eval_cage; | return em->mesh_eval_cage; | ||||
| } | } | ||||
| Mesh *editbmesh_get_eval_cage_from_orig( | Mesh *editbmesh_get_eval_cage_from_orig( | ||||
| struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *UNUSED(em), | struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *UNUSED(em), | ||||
| CustomDataMask dataMask) | const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| BLI_assert((obedit->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0); | BLI_assert((obedit->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0); | ||||
| Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); | Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); | ||||
| Object *obedit_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obedit->id); | Object *obedit_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obedit->id); | ||||
| BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); | BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); | ||||
| return editbmesh_get_eval_cage(depsgraph, scene_eval, obedit_eval, em_eval, dataMask); | return editbmesh_get_eval_cage(depsgraph, scene_eval, obedit_eval, em_eval, dataMask); | ||||
| } | } | ||||
| Show All 33 Lines | DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) | ||||
| Mesh *me = ob->data; | Mesh *me = ob->data; | ||||
| DerivedMesh *dm; | DerivedMesh *dm; | ||||
| DMCoNo *vertexcosnos; | DMCoNo *vertexcosnos; | ||||
| /* lets prevent crashing... */ | /* lets prevent crashing... */ | ||||
| if (ob->type != OB_MESH || me->totvert == 0) | if (ob->type != OB_MESH || me->totvert == 0) | ||||
| return NULL; | return NULL; | ||||
| dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); | dm = mesh_get_derived_final(scene, ob, &CD_MASK_BAREMESH_ORIGINDEX); | ||||
| if (dm->foreachMappedVert) { | if (dm->foreachMappedVert) { | ||||
| vertexcosnos = MEM_calloc_arrayN(me->totvert, sizeof(DMCoNo), "vertexcosnos map"); | vertexcosnos = MEM_calloc_arrayN(me->totvert, sizeof(DMCoNo), "vertexcosnos map"); | ||||
| dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos); | dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos); | ||||
| } | } | ||||
| else { | else { | ||||
| DMCoNo *v_co_no = vertexcosnos = MEM_malloc_arrayN(me->totvert, sizeof(DMCoNo), "vertexcosnos map"); | DMCoNo *v_co_no = vertexcosnos = MEM_malloc_arrayN(me->totvert, sizeof(DMCoNo), "vertexcosnos map"); | ||||
| int a; | int a; | ||||
| ▲ Show 20 Lines • Show All 364 Lines • Show Last 20 Lines | |||||