fix [#34098] Crash after using Decimate or Remesh modifiers
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
index 9aaeb4c8baf652bb9056b8c98e6231e0ae7d6b29..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 "BLF_translation.h"
-
+#include "BKE_pbvh.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_displist.h"
 #include "BKE_key.h"
@@ -171,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);
@@ -181,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);
@@ -191,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);
@@ -201,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);
@@ -211,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);
@@ -267,9 +265,11 @@ void DM_init_funcs(DerivedMesh *dm)
        dm->getVertData = DM_get_vert_data;
        dm->getEdgeData = DM_get_edge_data;
        dm->getTessFaceData = DM_get_tessface_data;
+       dm->getPolyData = DM_get_poly_data;
        dm->getVertDataArray = DM_get_vert_data_layer;
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getTessFaceDataArray = DM_get_tessface_data_layer;
+       dm->getPolyDataArray = DM_get_poly_data_layer;
 
        bvhcache_init(&dm->bvhCache);
 }
@@ -289,6 +289,13 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
        dm->needsFree = 1;
        dm->auto_bump_scale = -1.0f;
        dm->dirty = 0;
+
+       /* don't use CustomData_reset(...); because we dont want to touch customdata */
+       fill_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
+       fill_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1);
+       fill_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1);
+       fill_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1);
+       fill_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
 }
 
 void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
@@ -306,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;
@@ -385,7 +394,7 @@ void DM_ensure_tessface(DerivedMesh *dm)
        }
 
        else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) {
-               BLI_assert(CustomData_has_layer(&dm->faceData, CD_POLYINDEX));
+               BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX) || numTessFaces == 0);
                DM_update_tessface_data(dm);
        }
 
@@ -409,7 +418,7 @@ void DM_update_tessface_data(DerivedMesh *dm)
        const int hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
        const int hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
 
-       int *polyindex = CustomData_get_layer(fdata, CD_POLYINDEX);
+       int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
 
        int mf_idx,
            totface = dm->getNumTessFaces(dm),
@@ -466,21 +475,23 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
        int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
        int did_shapekeys = 0;
        
-       memset(&tmp.vdata, 0, sizeof(tmp.vdata));
-       memset(&tmp.edata, 0, sizeof(tmp.edata));
-       memset(&tmp.fdata, 0, sizeof(tmp.fdata));
-       memset(&tmp.ldata, 0, sizeof(tmp.ldata));
-       memset(&tmp.pdata, 0, sizeof(tmp.pdata));
+       CustomData_reset(&tmp.vdata);
+       CustomData_reset(&tmp.edata);
+       CustomData_reset(&tmp.fdata);
+       CustomData_reset(&tmp.ldata);
+       CustomData_reset(&tmp.pdata);
 
        totvert = tmp.totvert = dm->getNumVerts(dm);
        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;
@@ -531,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);
@@ -550,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;
 }
 
@@ -562,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;
@@ -627,6 +646,12 @@ void *DM_get_tessface_data(DerivedMesh *dm, int index, int type)
        return CustomData_get(&dm->faceData, index, type);
 }
 
+void *DM_get_poly_data(DerivedMesh *dm, int index, int type)
+{
+       return CustomData_get(&dm->polyData, index, type);
+}
+
+
 void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
 {
        if (type == CD_MVERT)
@@ -844,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;
 
@@ -876,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
@@ -903,7 +925,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int lay
        float (*orco)[3];
        int free;
 
-       if (em) dm = CDDM_from_BMEditMesh(em, me, FALSE, FALSE);
+       if (em) dm = CDDM_from_editbmesh(em, FALSE, FALSE);
        else dm = CDDM_from_mesh(me, ob);
 
        orco = get_orco_coords_dm(ob, em, layer, &free);
@@ -1146,119 +1168,64 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag,
        ColorBand *coba = stored_cb; /* warning, not a local var */
 
        unsigned char *wtcol_v;
-#if 0 /* See coment below. */
-       unsigned char *wtcol_f = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
-#endif
        unsigned char(*wtcol_l)[4] = CustomData_get_layer(dm->getLoopDataLayout(dm), CD_PREVIEW_MLOOPCOL);
-#if 0 /* See coment below. */
-       MFace *mf = dm->getTessFaceArray(dm);
-#endif
        MLoop *mloop = dm->getLoopArray(dm), *ml;
        MPoly *mp = dm->getPolyArray(dm);
-#if 0
-       int numFaces = dm->getNumTessFaces(dm);
-#endif
        int numVerts = dm->getNumVerts(dm);
        int totloop;
        int i, j;
 
-#if 0 /* See comment below */
-         /* If no CD_PREVIEW_MCOL existed yet, add a new one! */
-       if (!wtcol_f)
-               wtcol_f = CustomData_add_layer(&dm->faceData, CD_PREVIEW_MCOL, CD_CALLOC, NULL, numFaces);
-
-       if (wtcol_f) {
-               unsigned char *wtcol_f_step = wtcol_f;
-# else
-#if 0
-       /* XXX We have to create a CD_PREVIEW_MCOL, else it might sigsev (after a SubSurf mod, eg)... */
-       if (!dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL))
-               CustomData_add_layer(&dm->faceData, CD_PREVIEW_MCOL, CD_CALLOC, NULL, numFaces);
-#endif
-
-       {
-#endif
-
-               /* Weights are given by caller. */
-               if (weights) {
-                       float *w = weights;
-                       /* If indices is not NULL, it means we do not have weights for all vertices,
-                        * so we must create them (and set them to zero)... */
-                       if (indices) {
-                               w = MEM_callocN(sizeof(float) * numVerts, "Temp weight array DM_update_weight_mcol");
-                               i = num;
-                               while (i--)
-                                       w[indices[i]] = weights[i];
-                       }
-
-                       /* Convert float weights to colors. */
-                       wtcol_v = calc_colors_from_weights_array(numVerts, w);
-
-                       if (indices)
-                               MEM_freeN(w);
+       /* Weights are given by caller. */
+       if (weights) {
+               float *w = weights;
+               /* If indices is not NULL, it means we do not have weights for all vertices,
+                * so we must create them (and set them to zero)... */
+               if (indices) {
+                       w = MEM_callocN(sizeof(float) * numVerts, "Temp weight array DM_update_weight_mcol");
+                       i = num;
+                       while (i--)
+                               w[indices[i]] = weights[i];
                }
 
-               /* No weights given, take them from active vgroup(s). */
-               else
-                       wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba);
-
-               /* Now copy colors in all face verts. */
-               /* first add colors to the tessellation faces */
-               /* XXX Why update that layer? We have to update WEIGHT_MLOOPCOL anyway, 
-                *     and tessellation recreates mface layers from mloop/mpoly ones, so no
-                *     need to fill WEIGHT_MCOL here. */
-#if 0
-               for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) {
-                       /*origindex being NULL means we're operating on original mesh data*/
-#if 0
-                       unsigned int fidx = mf->v4 ? 3 : 2;
+               /* Convert float weights to colors. */
+               wtcol_v = calc_colors_from_weights_array(numVerts, w);
 
-#else   /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */
-                       unsigned int fidx;
-                       if (mf->v4) {
-                               fidx = 3;
-                       }
-                       else {
-                               fidx = 2;
-                               *(int *)(&wtcol_f_step[3 * 4]) = 0;
-                       }
-#endif
+               if (indices)
+                       MEM_freeN(w);
+       }
 
-                       do {
-                               copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4],
-                                               (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]);
-                       } while (fidx--);
-               }
-#endif
-               /*now add to loops, so the data can be passed through the modifier stack*/
-               /* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */
-               if (!wtcol_l) {
-                       BLI_array_declare(wtcol_l);
-                       totloop = 0;
-                       for (i = 0; i < dm->numPolyData; i++, mp++) {
-                               ml = mloop + mp->loopstart;
-
-                               BLI_array_grow_items(wtcol_l, mp->totloop);
-                               for (j = 0; j < mp->totloop; j++, ml++, totloop++) {
-                                       copy_v4_v4_char((char *)&wtcol_l[totloop],
-                                                       (char *)&wtcol_v[4 * ml->v]);
-                               }
+       /* No weights given, take them from active vgroup(s). */
+       else
+               wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba);
+
+       /* now add to loops, so the data can be passed through the modifier stack */
+       /* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */
+       if (!wtcol_l) {
+               BLI_array_declare(wtcol_l);
+               totloop = 0;
+               for (i = 0; i < dm->numPolyData; i++, mp++) {
+                       ml = mloop + mp->loopstart;
+
+                       BLI_array_grow_items(wtcol_l, mp->totloop);
+                       for (j = 0; j < mp->totloop; j++, ml++, totloop++) {
+                               copy_v4_v4_char((char *)&wtcol_l[totloop],
+                                               (char *)&wtcol_v[4 * ml->v]);
                        }
-                       CustomData_add_layer(&dm->loopData, CD_PREVIEW_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop);
                }
-               else {
-                       totloop = 0;
-                       for (i = 0; i < dm->numPolyData; i++, mp++) {
-                               ml = mloop + mp->loopstart;
+               CustomData_add_layer(&dm->loopData, CD_PREVIEW_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop);
+       }
+       else {
+               totloop = 0;
+               for (i = 0; i < dm->numPolyData; i++, mp++) {
+                       ml = mloop + mp->loopstart;
 
-                               for (j = 0; j < mp->totloop; j++, ml++, totloop++) {
-                                       copy_v4_v4_char((char *)&wtcol_l[totloop],
-                                                       (char *)&wtcol_v[4 * ml->v]);
-                               }
+                       for (j = 0; j < mp->totloop; j++, ml++, totloop++) {
+                               copy_v4_v4_char((char *)&wtcol_l[totloop],
+                                               (char *)&wtcol_v[4 * ml->v]);
                        }
                }
-               MEM_freeN(wtcol_v);
        }
+       MEM_freeN(wtcol_v);
 
        dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
 }
@@ -1270,7 +1237,7 @@ static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape
        int i, j, tot;
        
        if (!me->key)
-               return; 
+               return;
        
        tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY);
        for (i = 0; i < tot; i++) {
@@ -1375,7 +1342,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        ModifierData *firstmd, *md, *previewmd = NULL;
        CDMaskLink *datamasks, *curr;
        /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */
-       CustomDataMask mask, nextmask, append_mask = CD_MASK_POLYINDEX;
+       CustomDataMask mask, nextmask, append_mask = CD_MASK_ORIGINDEX;
        float (*deformedVerts)[3] = NULL;
        DerivedMesh *dm = NULL, *orcodm, *clothorcodm, *finaldm;
        int numVerts = me->totvert;
@@ -1385,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));
@@ -1452,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);
 
@@ -1463,7 +1431,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                        }
                        
                        /* grab modifiers until index i */
-                       if ((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
+                       if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
                                break;
                }
 
@@ -1507,12 +1475,17 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                if (!modifier_isEnabled(scene, md, required_mode)) continue;
                if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
                if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
-                       modifier_setError(md, "%s", TIP_("Modifier requires original data, bad stack position."));
+                       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;
 
@@ -1520,7 +1493,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                        unsupported |= multires_applied;
 
                        if (unsupported) {
-                               modifier_setError(md, "%s", TIP_("Not supported in sculpt mode."));
+                               modifier_setError(md, "Not supported in sculpt mode");
                                continue;
                        }
                }
@@ -1618,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); }
+                                       }
                                }
                        }
 
@@ -1667,8 +1646,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 
                                nextmask &= ~CD_MASK_ORCO;
                                DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX |
-                                                                (mti->requiredDataMask ?
-                                                                 mti->requiredDataMask(ob, md) : 0));
+                                                (mti->requiredDataMask ?
+                                                 mti->requiredDataMask(ob, md) : 0));
                                ndm = mti->applyModifier(md, ob, orcodm, app_flags & ~MOD_APPLY_USECACHE);
 
                                if (ndm) {
@@ -1708,7 +1687,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
 
                /* grab modifiers until index i */
-               if ((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
+               if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
                        break;
 
                if (sculpt_mode && md->type == eModifierType_Multires)
@@ -1803,7 +1782,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 #if 0
                if (num_tessface == 0 && finaldm->getNumTessFaces(finaldm) == 0)
 #else
-               if (finaldm->getNumTessFaces(finaldm) == 0) /* || !CustomData_has_layer(&finaldm->faceData, CD_POLYINDEX)) */
+               if (finaldm->getNumTessFaces(finaldm) == 0) /* || !CustomData_has_layer(&finaldm->faceData, CD_ORIGINDEX)) */
 #endif
                {
                        finaldm->recalcTessellation(finaldm);
@@ -1811,8 +1790,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                /* Even if tessellation is not needed, some modifiers might have modified CD layers
                 * (like mloopcol or mloopuv), hence we have to update those. */
                else if (finaldm->dirty & DM_DIRTY_TESS_CDLAYERS) {
-                       /* A tessellation already exists, it should always have a CD_POLYINDEX. */
-                       BLI_assert(CustomData_has_layer(&finaldm->faceData, CD_POLYINDEX));
+                       /* A tessellation already exists, it should always have a CD_ORIGINDEX. */
+                       BLI_assert(CustomData_has_layer(&finaldm->faceData, CD_ORIGINDEX));
                        DM_update_tessface_data(finaldm);
                }
                /* Need to watch this, it can cause issues, see bug [#29338]             */
@@ -1857,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;
 
-       cos = MEM_mallocN(sizeof(float) * 3 * numVerts, "vertexcos");
+       *numVerts_r = em->bm->totvert;
 
-       eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
-       for (i = 0; eve; eve = BM_iter_step(&iter), i++) {
+       cos = MEM_mallocN(sizeof(float) * 3 * em->bm->totvert, "vertexcos");
+
+       BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
                copy_v3_v3(cos[i], eve->co);
        }
 
@@ -1881,7 +1861,7 @@ int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *d
 
        if (!modifier_isEnabled(scene, md, required_mode)) return 0;
        if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
-               modifier_setError(md, "%s", TIP_("Modifier requires original data, bad stack position."));
+               modifier_setError(md, "Modifier requires original data, bad stack position");
                return 0;
        }
        
@@ -1976,7 +1956,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
 
                        }
                        else {
-                               dm = CDDM_from_BMEditMesh(em, ob->data, FALSE, FALSE);
+                               dm = CDDM_from_editbmesh(em, FALSE, FALSE);
 
                                if (deformedVerts) {
                                        CDDM_apply_vert_coords(dm, deformedVerts);
@@ -2067,12 +2047,18 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        }
        else if (dm) {
                *final_r = dm;
-               (*final_r)->calcNormals(*final_r); /* BMESH_ONLY - BMESH_TODO. check if this is needed */
+
+               /* once we support skipping normal calculation with modifiers we may want to add this back */
+#if 0  // was added for bmesh but is not needed
+               (*final_r)->calcNormals(*final_r);
+#endif
        }
        else if (!deformedVerts && cage_r && *cage_r) {
                /* cage should already have up to date normals */
                *final_r = *cage_r;
-               (*final_r)->calcNormals(*final_r); /* BMESH_ONLY - BMESH_TODO. check if this is needed */
+#if 0  // was added for bmesh but is not needed
+               (*final_r)->calcNormals(*final_r);
+#endif
        }
        else {
                /* this is just a copy of the editmesh, no need to calc normals */
@@ -2148,6 +2134,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
        /* weight paint and face select need original indices because of selection buffer drawing */
        int needMapping = (ob == obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)));
 
+       BLI_assert(ob->type == OB_MESH);
+
        clear_mesh_caches(ob);
 
        mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
@@ -2249,8 +2237,16 @@ DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask d
 {
        DerivedMesh *final;
 
+       /* XXX hack
+        * psys modifier updates particle state when called during dupli-list generation,
+        * which can lead to wrong transforms. This disables particle system modifier execution.
+        */
+       ob->transflag |= OB_NO_PSYS_UPDATE;
+
        mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0, 0);
 
+       ob->transflag &= ~OB_NO_PSYS_UPDATE;
+
        return final;
 }
 
@@ -2338,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);
        }
 }
 
@@ -2360,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);
                }
        }
        
@@ -2420,7 +2414,7 @@ static int GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_
 
 static void GetPosition(const SMikkTSpaceContext *pContext, float fPos[], const int face_num, const int vert_index)
 {
-       //assert(vert_index>=0 && vert_index<4);
+       //assert(vert_index >= 0 && vert_index < 4);
        SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
        const float *co = pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].co;
        copy_v3_v3(fPos, co);
@@ -2428,7 +2422,7 @@ static void GetPosition(const SMikkTSpaceContext *pContext, float fPos[], const
 
 static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float fUV[], const int face_num, const int vert_index)
 {
-       //assert(vert_index>=0 && vert_index<4);
+       //assert(vert_index >= 0 && vert_index < 4);
        SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
 
        if (pMesh->mtface != NULL) {
@@ -2443,7 +2437,7 @@ static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float fUV[]
 
 static void GetNormal(const SMikkTSpaceContext *pContext, float fNorm[], const int face_num, const int vert_index)
 {
-       //assert(vert_index>=0 && vert_index<4);
+       //assert(vert_index >= 0 && vert_index < 4);
        SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
 
        const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH);
@@ -2473,7 +2467,7 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float fNorm[], const i
 }
 static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert)
 {
-       //assert(vert_index>=0 && vert_index<4);
+       //assert(vert_index >= 0 && vert_index < 4);
        SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
        float *pRes = pMesh->tangent[4 * face_num + iVert];
        copy_v3_v3(pRes, fvTangent);
@@ -2484,15 +2478,11 @@ static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[
 void DM_add_tangent_layer(DerivedMesh *dm)
 {
        /* mesh vars */
-       MTFace *mtface, *tf;
-       MFace *mface, *mf;
-       MVert *mvert, *v1, *v2, *v3, *v4;
-       MemArena *arena = NULL;
-       VertexTangent **vtangents = NULL;
+       MVert *mvert;
+       MTFace *mtface;
+       MFace *mface;
        float (*orco)[3] = NULL, (*tangent)[4];
-       float *uv1, *uv2, *uv3, *uv4, *vtang;
-       float fno[3], tang[3], uv[4][2];
-       int i, j, len, mf_vi[4], totvert, totface, iCalcNewMethod;
+       int /* totvert, */ totface;
        float *nors;
 
        if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
@@ -2501,7 +2491,7 @@ void DM_add_tangent_layer(DerivedMesh *dm)
        nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
 
        /* check we have all the needed layers */
-       totvert = dm->getNumVerts(dm);
+       /* totvert = dm->getNumVerts(dm); */ /* UNUSED */
        totface = dm->getNumTessFaces(dm);
 
        mvert = dm->getVertArray(dm);
@@ -2518,14 +2508,8 @@ void DM_add_tangent_layer(DerivedMesh *dm)
        DM_add_tessface_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
        tangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
        
-       /* allocate some space */
-       arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "tangent layer arena");
-       BLI_memarena_use_calloc(arena);
-       vtangents = MEM_callocN(sizeof(VertexTangent *) * totvert, "VertexTangent");
-
        /* new computation method */
-       iCalcNewMethod = 1;
-       if (iCalcNewMethod != 0) {
+       {
                SGLSLMeshToTangent mesh2tangent = {0};
                SMikkTSpaceContext sContext = {0};
                SMikkTSpaceInterface sInterface = {0};
@@ -2548,87 +2532,13 @@ void DM_add_tangent_layer(DerivedMesh *dm)
                sInterface.m_setTSpaceBasic = SetTSpace;
 
                /* 0 if failed */
-               iCalcNewMethod = genTangSpaceDefault(&sContext);
-       }
-
-       if (!iCalcNewMethod) {
-               /* sum tangents at connected vertices */
-               for (i = 0, tf = mtface, mf = mface; i < totface; mf++, tf++, i++) {
-                       v1 = &mvert[mf->v1];
-                       v2 = &mvert[mf->v2];
-                       v3 = &mvert[mf->v3];
-
-                       if (mf->v4) {
-                               v4 = &mvert[mf->v4];
-                               normal_quad_v3(fno, v4->co, v3->co, v2->co, v1->co);
-                       }
-                       else {
-                               v4 = NULL;
-                               normal_tri_v3(fno, v3->co, v2->co, v1->co);
-                       }
-               
-                       if (mtface) {
-                               uv1 = tf->uv[0];
-                               uv2 = tf->uv[1];
-                               uv3 = tf->uv[2];
-                               uv4 = tf->uv[3];
-                       }
-                       else {
-                               uv1 = uv[0]; uv2 = uv[1]; uv3 = uv[2]; uv4 = uv[3];
-                               map_to_sphere(&uv[0][0], &uv[0][1], orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
-                               map_to_sphere(&uv[1][0], &uv[1][1], orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
-                               map_to_sphere(&uv[2][0], &uv[2][1], orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
-                               if (v4)
-                                       map_to_sphere(&uv[3][0], &uv[3][1], orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
-                       }
-               
-                       tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
-                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
-                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
-                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
-               
-                       if (mf->v4) {
-                               v4 = &mvert[mf->v4];
-                       
-                               tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
-                               sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
-                               sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
-                               sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
-                       }
-               }
-       
-               /* write tangent to layer */
-               for (i = 0, tf = mtface, mf = mface; i < totface; mf++, tf++, i++, tangent += 4) {
-                       len = (mf->v4) ? 4 : 3;
-
-                       if (mtface == NULL) {
-                               map_to_sphere(&uv[0][0], &uv[0][1], orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]);
-                               map_to_sphere(&uv[1][0], &uv[1][1], orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]);
-                               map_to_sphere(&uv[2][0], &uv[2][1], orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]);
-                               if (len == 4)
-                                       map_to_sphere(&uv[3][0], &uv[3][1], orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]);
-                       }
-               
-                       mf_vi[0] = mf->v1;
-                       mf_vi[1] = mf->v2;
-                       mf_vi[2] = mf->v3;
-                       mf_vi[3] = mf->v4;
-               
-                       for (j = 0; j < len; j++) {
-                               vtang = find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]);
-                               normalize_v3_v3(tangent[j], vtang);
-                               ((float *) tangent[j])[3] = 1.0f;
-                       }
-               }
+               genTangSpaceDefault(&sContext);
        }
-       
-       BLI_memarena_free(arena);
-       MEM_freeN(vtangents);
 }
 
 void DM_calc_auto_bump_scale(DerivedMesh *dm)
 {
-       /* int totvert= dm->getNumVerts(dm); */ /* UNUSED */
+       /* int totvert = dm->getNumVerts(dm); */ /* UNUSED */
        int totface = dm->getNumTessFaces(dm);
 
        MVert *mvert = dm->getVertArray(dm);