diff options
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_customdata.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 55 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 30 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 5 | ||||
-rw-r--r-- | source/blender/collada/collada_utils.cpp | 3 | ||||
-rw-r--r-- | source/blender/editors/object/object_add.c | 3 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 4 |
8 files changed, 86 insertions, 24 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 04251641d9b..236eae29967 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -503,7 +503,7 @@ int DM_release(DerivedMesh *dm); /** utility function to convert a DerivedMesh to a Mesh */ -void DM_to_mesh(DerivedMesh *dm, struct Mesh *me, struct Object *ob, CustomDataMask mask); +void DM_to_mesh(DerivedMesh *dm, struct Mesh *me, struct Object *ob, CustomDataMask mask, bool take_ownership); struct BMEditMesh *DM_to_editbmesh(struct DerivedMesh *dm, struct BMEditMesh *existing, const bool do_tessellate); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 9028ad09265..6a0cfefb1c2 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -96,6 +96,11 @@ bool CustomData_has_math(const struct CustomData *data); bool CustomData_has_interp(const struct CustomData *data); bool CustomData_bmesh_has_free(const struct CustomData *data); +/** + * Checks if any of the customdata layers is referenced. + */ +bool CustomData_has_referenced(const struct CustomData *data); + /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to * another, while not overwriting anything else (e.g. flags). probably only * implemented for mloopuv/mloopcol, for now.*/ @@ -142,6 +147,9 @@ void CustomData_reset(struct CustomData *data); */ void CustomData_free(struct CustomData *data, int totelem); +/* same as above, but only frees layers which matches the given mask. */ +void CustomData_free_typemask(struct CustomData *data, int totelem, CustomDataMask mask); + /* frees all layers with CD_FLAG_TEMPORARY */ void CustomData_free_temporary(struct CustomData *data, int totelem); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 870b020c8de..0bfa3628967 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -531,13 +531,26 @@ MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr) return tf_base; } -void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) +void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask, bool take_ownership) { /* dm might depend on me, so we need to do everything with a local copy */ Mesh tmp = *me; int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; int did_shapekeys = 0; - + int alloctype = CD_DUPLICATE; + + if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) { + bool has_any_referenced_layers = + CustomData_has_referenced(&dm->vertData) || + CustomData_has_referenced(&dm->edgeData) || + CustomData_has_referenced(&dm->loopData) || + CustomData_has_referenced(&dm->faceData) || + CustomData_has_referenced(&dm->polyData); + if (!has_any_referenced_layers) { + alloctype = CD_ASSIGN; + } + } + CustomData_reset(&tmp.vdata); CustomData_reset(&tmp.edata); CustomData_reset(&tmp.fdata); @@ -552,10 +565,10 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) totpoly = tmp.totpoly = dm->getNumPolys(dm); tmp.totface = 0; - CustomData_copy(&dm->vertData, &tmp.vdata, mask, CD_DUPLICATE, totvert); - CustomData_copy(&dm->edgeData, &tmp.edata, mask, CD_DUPLICATE, totedge); - CustomData_copy(&dm->loopData, &tmp.ldata, mask, CD_DUPLICATE, totloop); - CustomData_copy(&dm->polyData, &tmp.pdata, mask, CD_DUPLICATE, totpoly); + CustomData_copy(&dm->vertData, &tmp.vdata, mask, alloctype, totvert); + CustomData_copy(&dm->edgeData, &tmp.edata, mask, alloctype, totedge); + CustomData_copy(&dm->loopData, &tmp.ldata, mask, alloctype, totloop); + CustomData_copy(&dm->polyData, &tmp.pdata, mask, alloctype, totpoly); tmp.cd_flag = dm->cd_flag; if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) { @@ -590,13 +603,19 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) /* not all DerivedMeshes store their verts/edges/faces in CustomData, so * we set them here in case they are missing */ - if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) - CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, dm->dupVertArray(dm), totvert); - if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) - CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge); + if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) { + CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, + (alloctype == CD_ASSIGN) ? dm->getVertArray(dm) : dm->dupVertArray(dm), + totvert); + } + if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) { + CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, + (alloctype == CD_ASSIGN) ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm), + totedge); + } if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) { - tmp.mloop = dm->dupLoopArray(dm); - tmp.mpoly = dm->dupPolyArray(dm); + tmp.mloop = (alloctype == CD_ASSIGN) ? dm->getLoopArray(dm) : dm->dupLoopArray(dm); + tmp.mpoly = (alloctype == CD_ASSIGN) ? dm->getPolyArray(dm) : dm->dupPolyArray(dm); CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop); CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly); @@ -607,7 +626,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) if (CustomData_has_layer(&me->ldata, CD_MDISPS)) { if (totloop == me->totloop) { MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); - CustomData_add_layer(&tmp.ldata, CD_MDISPS, CD_DUPLICATE, mdisps, totloop); + CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop); } } @@ -641,6 +660,16 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) /* skip the listbase */ MEMCPY_STRUCT_OFS(me, &tmp, id.prev); + + if (take_ownership) { + if (alloctype == CD_ASSIGN) { + CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask); + CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask); + CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask); + CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask); + } + dm->release(dm); + } } void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 65ec6be5a60..999f411cece 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1559,6 +1559,25 @@ void CustomData_free(CustomData *data, int totelem) CustomData_reset(data); } +void CustomData_free_typemask(struct CustomData *data, int totelem, CustomDataMask mask) +{ + int i; + + for (i = 0; i < data->totlayer; ++i) { + CustomDataLayer *layer = &data->layers[i]; + if (!(mask & CD_TYPE_AS_MASK(layer->type))) { + continue; + } + customData_free_layer__internal(layer, totelem); + } + + if (data->layers) + MEM_freeN(data->layers); + + CustomData_external_free(data); + CustomData_reset(data); +} + static void customData_update_offsets(CustomData *data) { const LayerTypeInfo *typeInfo; @@ -2876,6 +2895,17 @@ bool CustomData_has_interp(const struct CustomData *data) return false; } +bool CustomData_has_referenced(const struct CustomData *data) +{ + int i; + for (i = 0; i < data->totlayer; ++i) { + if (data->layers[i].flag & CD_FLAG_NOFREE) { + return true; + } + } + return false; +} + /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to * another, while not overwriting anything else (e.g. flags)*/ void CustomData_data_copy_value(int type, const void *source, void *dest) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 7757babaca2..809d2137187 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1501,7 +1501,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use } else { me = BKE_mesh_add(G.main, "Mesh"); - DM_to_mesh(dm, me, ob, CD_MASK_MESH); + DM_to_mesh(dm, me, ob, CD_MASK_MESH, false); } me->totcol = cu->totcol; @@ -2256,8 +2256,7 @@ Mesh *BKE_mesh_new_from_object( dm = mesh_create_derived_view(sce, ob, mask); tmpmesh = BKE_mesh_add(bmain, "Mesh"); - DM_to_mesh(dm, tmpmesh, ob, mask); - dm->release(dm); + DM_to_mesh(dm, tmpmesh, ob, mask, true); } /* BKE_mesh_add/copy gives us a user count we don't need */ diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index d91689ff496..f15efa89ea6 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -164,8 +164,7 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh } tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here - DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH); - dm->release(dm); + DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true); if (triangulate) { bc_triangulate_mesh(tmpmesh); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index db7cd991338..99b351561c7 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1700,11 +1700,10 @@ static int convert_exec(bContext *C, wmOperator *op) dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH); // dm = mesh_create_derived_no_deform(ob1, NULL); /* this was called original (instead of get_derived). man o man why! (ton) */ - DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH); + DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true); /* re-tessellation is called by DM_to_mesh */ - dm->release(dm); BKE_object_free_modifiers(newob); /* after derivedmesh calls! */ } else if (ob->type == OB_FONT) { diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index bed85444101..710cf2dbdd2 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -614,9 +614,7 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, return 0; } - DM_to_mesh(dm, me, ob, CD_MASK_MESH); - - dm->release(dm); + DM_to_mesh(dm, me, ob, CD_MASK_MESH, true); if (md->type == eModifierType_Multires) multires_customdata_delete(me); |