fix [#34098] Crash after using Decimate or Remesh modifiers
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
index 1f4cc9bc5c2bc3c676e6cfd9a8be03445a283f5d..8e740075bc64a2cf9f0203fb7e2ccc9e55982c2a 100644 (file)
 #include "BLI_math.h"
 #include "BLI_memarena.h"
 #include "BLI_array.h"
-#include "BLI_pbvh.h"
 #include "BLI_utildefines.h"
 #include "BLI_linklist.h"
 
+#include "BKE_pbvh.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_displist.h"
 #include "BKE_key.h"
@@ -169,7 +169,7 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm)
 
 static MVert *dm_dupVertArray(DerivedMesh *dm)
 {
-       MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm),
+       MVert *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumVerts(dm),
                                 "dm_dupVertArray tmp");
 
        if (tmp) dm->copyVertArray(dm, tmp);
@@ -179,7 +179,7 @@ static MVert *dm_dupVertArray(DerivedMesh *dm)
 
 static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
 {
-       MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm),
+       MEdge *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumEdges(dm),
                                 "dm_dupEdgeArray tmp");
 
        if (tmp) dm->copyEdgeArray(dm, tmp);
@@ -189,7 +189,7 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
 
 static MFace *dm_dupFaceArray(DerivedMesh *dm)
 {
-       MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumTessFaces(dm),
+       MFace *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumTessFaces(dm),
                                 "dm_dupFaceArray tmp");
 
        if (tmp) dm->copyTessFaceArray(dm, tmp);
@@ -199,7 +199,7 @@ static MFace *dm_dupFaceArray(DerivedMesh *dm)
 
 static MLoop *dm_dupLoopArray(DerivedMesh *dm)
 {
-       MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumLoops(dm),
+       MLoop *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumLoops(dm),
                                 "dm_dupLoopArray tmp");
 
        if (tmp) dm->copyLoopArray(dm, tmp);
@@ -209,7 +209,7 @@ static MLoop *dm_dupLoopArray(DerivedMesh *dm)
 
 static MPoly *dm_dupPolyArray(DerivedMesh *dm)
 {
-       MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumPolys(dm),
+       MPoly *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumPolys(dm),
                                 "dm_dupPolyArray tmp");
 
        if (tmp) dm->copyPolyArray(dm, tmp);
@@ -313,6 +313,8 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type
        CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
                        CD_CALLOC, numPolys);
 
+       dm->cd_flag = source->cd_flag;
+
        dm->type = type;
        dm->numVertData = numVerts;
        dm->numEdgeData = numEdges;
@@ -483,11 +485,13 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
        totedge = tmp.totedge = dm->getNumEdges(dm);
        totloop = tmp.totloop = dm->getNumLoops(dm);
        totpoly = tmp.totpoly = dm->getNumPolys(dm);
+       tmp.totface = 0;
 
        CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
        CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
        CustomData_copy(&dm->loopData, &tmp.ldata, CD_MASK_MESH, CD_DUPLICATE, totloop);
        CustomData_copy(&dm->polyData, &tmp.pdata, CD_MASK_MESH, CD_DUPLICATE, totpoly);
+       me->cd_flag = dm->cd_flag;
 
        if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) {
                KeyBlock *kb;
@@ -538,9 +542,10 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
        }
 
        /* yes, must be before _and_ after tessellate */
-       mesh_update_customdata_pointers(&tmp, TRUE);
+       mesh_update_customdata_pointers(&tmp, false);
 
-       BKE_mesh_tessface_calc(&tmp);
+       /* since 2.65 caller must do! */
+       // BKE_mesh_tessface_calc(&tmp);
 
        CustomData_free(&me->vdata, me->totvert);
        CustomData_free(&me->edata, me->totedge);
@@ -557,6 +562,13 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
                tmp.key = NULL;
        }
 
+       /* Clear selection history */
+       tmp.mselect = NULL;
+       tmp.totselect = 0;
+       if (me->mselect) {
+               MEM_freeN(me->mselect);
+       }
+
        *me = tmp;
 }
 
@@ -569,7 +581,7 @@ void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb)
        if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) return;
        
        if (kb->data) MEM_freeN(kb->data);
-       kb->data = MEM_callocN(me->key->elemsize * me->totvert, "kb->data");
+       kb->data = MEM_mallocN(me->key->elemsize * me->totvert, "kb->data");
        kb->totelem = totvert;
        
        fp = kb->data;
@@ -857,30 +869,27 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob,
        return dm;
 }
 
-static float *get_editbmesh_orco_verts(BMEditMesh *em)
+static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
 {
        BMIter iter;
        BMVert *eve;
-       float *orco;
-       int a, totvert;
+       float (*orco)[3];
+       int i;
 
        /* these may not really be the orco's, but it's only for preview.
         * could be solver better once, but isn't simple */
-
-       totvert = em->bm->totvert;
        
-       orco = MEM_mallocN(sizeof(float) * 3 * totvert, "BMEditMesh Orco");
+       orco = MEM_mallocN(sizeof(float) * 3 * em->bm->totvert, "BMEditMesh Orco");
 
-       eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
-       for (a = 0; eve; eve = BM_iter_step(&iter), a += 3) {
-               copy_v3_v3(orco + a, eve->co);
+       BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+               copy_v3_v3(orco[i], eve->co);
        }
        
        return orco;
 }
 
 /* orco custom data layer */
-static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free)
+static float (*get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free))[3]
 {
        *free = 0;
 
@@ -889,9 +898,9 @@ static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free
                *free = 1;
 
                if (em)
-                       return (float(*)[3])get_editbmesh_orco_verts(em);
+                       return get_editbmesh_orco_verts(em);
                else
-                       return (float(*)[3])BKE_mesh_orco_verts_get(ob);
+                       return BKE_mesh_orco_verts_get(ob);
        }
        else if (layer == CD_CLOTH_ORCO) {
                /* apply shape key for cloth, this should really be solved
@@ -1343,6 +1352,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
        int has_multires = mmd != NULL, multires_applied = 0;
        int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
+       int sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm);
 
        const int draw_flag = ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) |
                               (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0));
@@ -1410,7 +1420,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                        if (!modifier_isEnabled(scene, md, required_mode)) continue;
                        if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
-                       if (mti->type == eModifierTypeType_OnlyDeform) {
+                       if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
                                if (!deformedVerts)
                                        deformedVerts = mesh_getVertexCos(me, &numVerts);
 
@@ -1468,9 +1478,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                        modifier_setError(md, "Modifier requires original data, bad stack position");
                        continue;
                }
-               if (sculpt_mode && (!has_multires || multires_applied)) {
+               if (sculpt_mode &&
+                       (!has_multires || multires_applied || ob->sculpt->bm))
+               {
                        int unsupported = 0;
 
+                       if (sculpt_dyntopo)
+                               unsupported = TRUE;
+
                        if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM)
                                unsupported |= mti->type != eModifierTypeType_OnlyDeform;
 
@@ -1576,9 +1591,15 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                                        DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
                                        DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
 
-                                       range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
-                                       range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
-                                       range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0);
+#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= DM_OMP_LIMIT)
+                                       {
+#pragma omp section
+                                               { range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); }
+#pragma omp section
+                                               { range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); }
+#pragma omp section
+                                               { range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); }
+                                       }
                                }
                        }
 
@@ -1815,17 +1836,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        BLI_linklist_free((LinkNode *)datamasks, NULL);
 }
 
-float (*editbmesh_get_vertex_cos(BMEditMesh * em, int *numVerts_r))[3]
+float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3]
 {
-       int i, numVerts = *numVerts_r = em->bm->totvert;
-       float (*cos)[3];
        BMIter iter;
        BMVert *eve;
+       float (*cos)[3];
+       int i;
+
+       *numVerts_r = em->bm->totvert;
 
-       cos = MEM_mallocN(sizeof(float) * 3 * numVerts, "vertexcos");
+       cos = MEM_mallocN(sizeof(float) * 3 * em->bm->totvert, "vertexcos");
 
-       eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
-       for (i = 0; eve; eve = BM_iter_step(&iter), i++) {
+       BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
                copy_v3_v3(cos[i], eve->co);
        }
 
@@ -2312,20 +2334,19 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
 static void make_vertexcosnos__mapFunc(void *userData, int index, const float co[3],
                                        const float no_f[3], const short no_s[3])
 {
-       float *vec = userData;
-       
-       vec += 6 * index;
+       DMCoNo *co_no = &((DMCoNo *)userData)[index];
 
        /* check if we've been here before (normal should not be 0) */
-       if (vec[3] || vec[4] || vec[5]) return;
+       if (!is_zero_v3(co_no->no)) {
+               return;
+       }
 
-       copy_v3_v3(vec, co);
-       vec += 3;
+       copy_v3_v3(co_no->co, co);
        if (no_f) {
-               copy_v3_v3(vec, no_f);
+               copy_v3_v3(co_no->no, no_f);
        }
        else {
-               normal_short_to_float_v3(vec, no_s);
+               normal_short_to_float_v3(co_no->no, no_s);
        }
 }
 
@@ -2334,29 +2355,28 @@ static void make_vertexcosnos__mapFunc(void *userData, int index, const float co
 /* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
 /* in use now by vertex/weight paint and particle generating */
 
-float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
+DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
 {
        Mesh *me = ob->data;
        DerivedMesh *dm;
-       float *vertexcosnos;
+       DMCoNo *vertexcosnos;
        
        /* lets prevent crashing... */
        if (ob->type != OB_MESH || me->totvert == 0)
                return NULL;
        
        dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
-       vertexcosnos = MEM_callocN(6 * sizeof(float) * me->totvert, "vertexcosnos map");
        
        if (dm->foreachMappedVert) {
+               vertexcosnos = MEM_callocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map");
                dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
        }
        else {
-               float *fp = vertexcosnos;
+               DMCoNo *v_co_no = vertexcosnos = MEM_mallocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map");
                int a;
-               
-               for (a = 0; a < me->totvert; a++, fp += 6) {
-                       dm->getVertCo(dm, a, fp);
-                       dm->getVertNo(dm, a, fp + 3);
+               for (a = 0; a < me->totvert; a++, v_co_no++) {
+                       dm->getVertCo(dm, a, v_co_no->co);
+                       dm->getVertNo(dm, a, v_co_no->no);
                }
        }