Fix T47038: Particles in Particle Edit Mode get added in completely wrong location.
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 4 Jan 2016 11:19:45 +0000 (12:19 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 4 Jan 2016 11:19:45 +0000 (12:19 +0100)
It also fixes another issue (crash) related to symmetric editing.

Quite involved, we (try to!) fix complete broken logic of parts of particle code, which would use poly index
as tessface one (or vice-versa). Issue most probably goes back to BMesh integration time...

This patch mostly fixes particle editing mode:
  - Adding/removing particles when using generative modifiers (like subsurf) should now work.
  - Adding/removing particles with a non-tessellated mesh (i.e. one having ngons) should also mostly work.
  - X-axis-mirror-editing particles over ngons does not really work, not sure why currently.
  - All this in both 'modes' (with or without using modifier stack for particles).

Tech side:
  - Store a deformed-only DM in particle modifier data.
  - Rename existing DM to make it clear it's a final one.
  - Use deformed-only DM's tessface2poly mapping to 'solve' poly/tessface mismatches.
  - Make (part of) mirror-editing code able to use a DM instead of raw mesh, so that we can mirror based on final DM
    when editing particles using modifier stack (mandatory, since there is no way currently to find orig tessface
    from an final DM tessface index).

Note that this patch is not really nice and clean (current particles are beyond hope on this side anyway),
it's more like some urgency bandage. Whole crap needs complete rewrite anyway,
BMesh's polygons make it really hard to work with current system (and looptri would not help much here).

Also, did not test everything possibly affected by those changes, so it needs some users' testing & validation too.

Reviewers: psy-fi

Subscribers: dfelinto, eyecandy

Maniphest Tasks: T47038

Differential Revision: https://developer.blender.org/D1685

33 files changed:
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_distribute.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenlib/BLI_math_vector.h
source/blender/blenlib/intern/math_vector_inline.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/armature/armature_skinning.c
source/blender/editors/armature/meshlaplacian.c
source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/editface.c
source/blender/editors/mesh/editmesh_utils.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_shapekey.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/particle_object.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/util/ed_util.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_object_api.c
source/blender/makesrna/intern/rna_particle.c
source/blender/modifiers/intern/MOD_explode.c
source/blender/modifiers/intern/MOD_particleinstance.c
source/blender/modifiers/intern/MOD_particlesystem.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/pointdensity.c
source/blenderplayer/bad_level_call_stubs/stubs.c

index 00cc48cf713b67b1a19c96cef0b9e9dd9b377ad8..ed453754648f42de5eba013e23f328323c0be3e3 100644 (file)
@@ -302,7 +302,7 @@ void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
 void psys_free(struct Object *ob, struct ParticleSystem *psys);
 
 void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
-void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
+void psys_render_restore(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
 bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
 
 void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
@@ -413,15 +413,15 @@ void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], floa
 
 /* BLI_bvhtree_ray_cast callback */
 void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit);
-void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache,
+void psys_particle_on_dm(struct DerivedMesh *dm_final, int from, int index, int index_dmcache,
                          const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
                          float orco[3], float ornor[3]);
 
 /* particle_system.c */
 void distribute_particles(struct ParticleSimulationData *sim, int from);
 void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
-void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);
-int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node);
+void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, struct ParticleSystem *psys);
+int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes);
 
 void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra);
 
index e26e5148ff639517142ce980df6a84330d04788d..9fc438319cb5552813ab49d93d0cfeb016401b52 100644 (file)
@@ -43,6 +43,7 @@
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
+#include "BLI_array.h"
 #include "BLI_blenlib.h"
 #include "BLI_bitmap.h"
 #include "BLI_math.h"
@@ -3668,26 +3669,73 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
 
 void DM_init_origspace(DerivedMesh *dm)
 {
-       static float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
+       const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
 
        OrigSpaceLoop *lof_array = CustomData_get_layer(&dm->loopData, CD_ORIGSPACE_MLOOP);
-       OrigSpaceLoop *lof;
        const int numpoly = dm->getNumPolys(dm);
        // const int numloop = dm->getNumLoops(dm);
+       MVert *mv = dm->getVertArray(dm);
+       MLoop *ml = dm->getLoopArray(dm);
        MPoly *mp = dm->getPolyArray(dm);
-       int i, j;
+       int i, j, k;
+
+       float (*vcos_2d)[2] = NULL;
+       BLI_array_staticdeclare(vcos_2d, 64);
 
        for (i = 0; i < numpoly; i++, mp++) {
-               /* only quads/tri's for now */
+               OrigSpaceLoop *lof = lof_array + mp->loopstart;
+
                if (mp->totloop == 3 || mp->totloop == 4) {
-                       lof = lof_array + mp->loopstart;
                        for (j = 0; j < mp->totloop; j++, lof++) {
                                copy_v2_v2(lof->uv, default_osf[j]);
                        }
                }
+               else {
+                       MLoop *l = &ml[mp->loopstart];
+                       float p_nor[3], co[3];
+                       float mat[3][3];
+
+                       float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {FLT_MIN, FLT_MIN};
+                       float translate[2], scale[2];
+
+                       BKE_mesh_calc_poly_normal(mp, l, mv, p_nor);
+                       axis_dominant_v3_to_m3(mat, p_nor);
+
+                       BLI_array_empty(vcos_2d);
+                       BLI_array_reserve(vcos_2d, mp->totloop);
+                       for (j = 0; j < mp->totloop; j++, l++) {
+                               mul_v3_m3v3(co, mat, mv[l->v].co);
+                               copy_v2_v2(vcos_2d[j], co);
+
+                               for (k = 0; k < 2; k++) {
+                                       if (co[k] > max[k])
+                                               max[k] = co[k];
+                                       else if (co[k] < min[k])
+                                               min[k] = co[k];
+                               }
+                       }
+
+                       /* Brings min to (0, 0). */
+                       negate_v2_v2(translate, min);
+
+                       /* Scale will bring max to (1, 1). */
+                       sub_v2_v2v2(scale, max, min);
+                       if (scale[0] == 0.0f)
+                               scale[0] = 1e-9f;
+                       if (scale[1] == 0.0f)
+                               scale[1] = 1e-9f;
+                       invert_v2(scale);
+
+                       /* Finally, transform all vcos_2d into ((0, 0), (1, 1)) square and assing them as origspace. */
+                       for (j = 0; j < mp->totloop; j++, lof++) {
+                               add_v2_v2v2(lof->uv, vcos_2d[j], translate);
+                               mul_v2_v2(lof->uv, scale);
+                       }
+               }
        }
 
        dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+       BLI_array_free(vcos_2d);
 }
 
 
index 89f22b8e7428440147cd3255f6d4dd8fa80e4719..b448bec84e3c0c36647241a355fa1d8931418390 100644 (file)
@@ -364,10 +364,15 @@ void BKE_object_free_caches(Object *object)
        for (md = object->modifiers.first; md != NULL; md = md->next) {
                if (md->type == eModifierType_ParticleSystem) {
                        ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
-                       if (psmd->dm != NULL) {
-                               psmd->dm->needsFree = 1;
-                               psmd->dm->release(psmd->dm);
-                               psmd->dm = NULL;
+                       if (psmd->dm_final != NULL) {
+                               psmd->dm_final->needsFree = 1;
+                               psmd->dm_final->release(psmd->dm_final);
+                               psmd->dm_final = NULL;
+                               if (psmd->dm_deformed != NULL) {
+                                       psmd->dm_deformed->needsFree = 1;
+                                       psmd->dm_deformed->release(psmd->dm_deformed);
+                                       psmd->dm_deformed = NULL;
+                               }
                                psmd->flag |= eParticleSystemFlag_file_loaded;
                                update_flag |= OB_RECALC_DATA;
                        }
index b3be5676607aa856c564d91c85fe2cf34c7813ba..39f0e7cbb84217148424aee31cae5453f005a9f7 100644 (file)
@@ -623,8 +623,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
        data->childcachebufs.last = psys->childcachebufs.last;
        data->totchildcache = psys->totchildcache;
 
-       if (psmd->dm)
-               data->dm = CDDM_copy(psmd->dm);
+       if (psmd->dm_final)
+               data->dm = CDDM_copy(psmd->dm_final);
        data->totdmvert = psmd->totdmvert;
        data->totdmedge = psmd->totdmedge;
        data->totdmface = psmd->totdmface;
@@ -651,7 +651,7 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
                psys->recalc |= PSYS_RECALC_RESET;
 }
 
-void psys_render_restore(Object *ob, ParticleSystem *psys)
+void psys_render_restore(Scene *scene, Object *ob, ParticleSystem *psys)
 {
        ParticleRenderData *data;
        ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
@@ -665,9 +665,14 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
        if (data->elems)
                MEM_freeN(data->elems);
 
-       if (psmd->dm) {
-               psmd->dm->needsFree = 1;
-               psmd->dm->release(psmd->dm);
+       if (psmd->dm_final) {
+               psmd->dm_final->needsFree = 1;
+               psmd->dm_final->release(psmd->dm_final);
+       }
+       if (psmd->dm_deformed) {
+               psmd->dm_deformed->needsFree = 1;
+               psmd->dm_deformed->release(psmd->dm_deformed);
+               psmd->dm_deformed = NULL;
        }
 
        psys_free_path_cache(psys, NULL);
@@ -689,14 +694,19 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
        psys->childcachebufs.last = data->childcachebufs.last;
        psys->totchildcache = data->totchildcache;
 
-       psmd->dm = data->dm;
+       psmd->dm_final = data->dm;
        psmd->totdmvert = data->totdmvert;
        psmd->totdmedge = data->totdmedge;
        psmd->totdmface = data->totdmface;
        psmd->flag &= ~eParticleSystemFlag_psys_updated;
 
-       if (psmd->dm)
-               psys_calc_dmcache(ob, psmd->dm, psys);
+       if (psmd->dm_final) {
+               if (!psmd->dm_final->deformedOnly) {
+                       psmd->dm_deformed = CDDM_copy(mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE));
+                       DM_ensure_tessface(psmd->dm_deformed);
+               }
+               psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys);
+       }
 
        MEM_freeN(data);
        psys->renderdata = NULL;
@@ -1383,78 +1393,114 @@ static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4
        }
 }
 
-/* find the derived mesh face for a particle, set the mf passed. this is slow
- * and can be optimized but only for many lookups. returns the face index. */
-int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node)
+/**
+ * Find the final derived mesh tessface for a particle, from its original tessface index.
+ * This is slow and can be optimized but only for many lookups.
+ *
+ * \param dm_final final DM, it may not have the same topology as original mesh.
+ * \param dm_deformed deformed-only DM, it has the exact same topology as original mesh.
+ * \param findex_orig the input tessface index.
+ * \param fw face weights (position of the particle inside the \a findex_orig tessface).
+ * \param poly_nodes may be NULL, otherwise an array of linked list, one for each final DM polygon, containing all
+ *                   its tessfaces indices.
+ * \return the DM tessface index.
+ */
+int psys_particle_dm_face_lookup(
+        DerivedMesh *dm_final, DerivedMesh *dm_deformed,
+        int findex_orig, const float fw[4], struct LinkNode **poly_nodes)
 {
-       Mesh *me = (Mesh *)ob->data;
-       MPoly *mpoly;
-       OrigSpaceFace *osface;
-       int quad, findex, totface;
+       MFace *mtessface_final;
+       OrigSpaceFace *osface_final;
+       int totface_final;
+       int pindex_orig;
        float uv[2], (*faceuv)[2];
 
-       /* double lookup */
-       const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
-       const int *index_mp_to_orig  = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-       if (index_mf_to_mpoly == NULL) {
-               index_mp_to_orig = NULL;
+       const int *index_mf_to_mpoly_deformed = NULL;
+       const int *index_mf_to_mpoly = NULL;
+       const int *index_mp_to_orig = NULL;
+
+       index_mf_to_mpoly = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
+       index_mp_to_orig = dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
+       BLI_assert(index_mf_to_mpoly);
+
+       if (dm_deformed) {
+               index_mf_to_mpoly_deformed = dm_deformed->getTessFaceDataArray(dm_deformed, CD_ORIGINDEX);
+       }
+       else {
+               BLI_assert(dm_final->deformedOnly);
+               index_mf_to_mpoly_deformed = index_mf_to_mpoly;
+       }
+       BLI_assert(index_mf_to_mpoly_deformed);
+
+       pindex_orig = index_mf_to_mpoly_deformed[findex_orig];
+
+       if (dm_deformed == NULL) {
+               dm_deformed = dm_final;
        }
 
-       totface = dm->getNumTessFaces(dm);
-       if (!totface) {
+       index_mf_to_mpoly_deformed = NULL;
+
+       totface_final = dm_final->getNumTessFaces(dm_final);
+       if (!totface_final) {
                return DMCACHE_NOTFOUND;
        }
 
-       mpoly = dm->getPolyArray(dm);
-       osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
+       mtessface_final = dm_final->getTessFaceArray(dm_final);
+       osface_final = dm_final->getTessFaceDataArray(dm_final, CD_ORIGSPACE);
 
-       if (osface == NULL || index_mf_to_mpoly == NULL) {
-               /* Assume we don't need osface data */
-               if (index < totface) {
+       if (osface_final == NULL) {
+               /* Assume we don't need osface_final data, and we get a direct 1-1 mapping... */
+               if (findex_orig < totface_final) {
                        //printf("\tNO CD_ORIGSPACE, assuming not needed\n");
-                       return index;
+                       return findex_orig;
                }
                else {
                        printf("\tNO CD_ORIGSPACE, error out of range\n");
                        return DMCACHE_NOTFOUND;
                }
        }
-       else if (index >= me->totpoly)
+       else if (findex_orig >= dm_deformed->getNumTessFaces(dm_deformed)) {
                return DMCACHE_NOTFOUND;  /* index not in the original mesh */
+       }
 
        psys_w_to_origspace(fw, uv);
        
-       if (node) { /* we have a linked list of faces that we use, faster! */
-               for (; node; node = node->next) {
-                       findex = GET_INT_FROM_POINTER(node->link);
-                       faceuv = osface[findex].uv;
-                       quad = (mpoly[findex].totloop == 4);
+       if (poly_nodes) {
+               /* we can have a restricted linked list of faces to check, faster! */
+               LinkNode *tessface_node = poly_nodes[pindex_orig];
+
+               for (; tessface_node; tessface_node = tessface_node->next) {
+                       int findex_dst = GET_INT_FROM_POINTER(tessface_node->link);
+                       faceuv = osface_final[findex_dst].uv;
 
                        /* check that this intersects - Its possible this misses :/ -
                         * could also check its not between */
-                       if (quad) {
-                               if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3]))
-                                       return findex;
+                       if (mtessface_final[findex_dst].v4) {
+                               if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
+                                       return findex_dst;
+                               }
+                       }
+                       else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
+                               return findex_dst;
                        }
-                       else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2]))
-                               return findex;
                }
        }
        else { /* if we have no node, try every face */
-               for (findex = 0; findex < totface; findex++) {
-                       const int findex_orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex);
-                       if (findex_orig == index) {
-                               faceuv = osface[findex].uv;
-                               quad = (mpoly[findex].totloop == 4);
+               for (int findex_dst = 0; findex_dst < totface_final; findex_dst++) {
+                       /* If current tessface from 'final' DM and orig tessface (given by index) map to the same orig poly... */
+                       if (DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex_dst) == pindex_orig) {
+                               faceuv = osface_final[findex_dst].uv;
 
                                /* check that this intersects - Its possible this misses :/ -
                                 * could also check its not between */
-                               if (quad) {
-                                       if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3]))
-                                               return findex;
+                               if (mtessface_final[findex_dst].v4) {
+                                       if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
+                                               return findex_dst;
+                                       }
+                               }
+                               else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
+                                       return findex_dst;
                                }
-                               else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2]))
-                                       return findex;
                        }
                }
        }
@@ -1523,7 +1569,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
 }
 
 /* interprets particle data to get a point on a mesh in object space */
-void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache,
+void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_dmcache,
                          const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
                          float orco[3], float ornor[3])
 {
@@ -1531,7 +1577,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
        float (*orcodata)[3];
        int mapindex;
 
-       if (!psys_map_index_on_dm(dm, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
+       if (!psys_map_index_on_dm(dm_final, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
                if (vec) { vec[0] = vec[1] = vec[2] = 0.0; }
                if (nor) { nor[0] = nor[1] = 0.0; nor[2] = 1.0; }
                if (orco) { orco[0] = orco[1] = orco[2] = 0.0; }
@@ -1542,13 +1588,13 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
                return;
        }
 
-       orcodata = dm->getVertDataArray(dm, CD_ORCO);
+       orcodata = dm_final->getVertDataArray(dm_final, CD_ORCO);
 
        if (from == PART_FROM_VERT) {
-               dm->getVertCo(dm, mapindex, vec);
+               dm_final->getVertCo(dm_final, mapindex, vec);
 
                if (nor) {
-                       dm->getVertNo(dm, mapindex, nor);
+                       dm_final->getVertNo(dm_final, mapindex, nor);
                        normalize_v3(nor);
                }
 
@@ -1556,7 +1602,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
                        copy_v3_v3(orco, orcodata[mapindex]);
 
                if (ornor) {
-                       dm->getVertNo(dm, mapindex, ornor);
+                       dm_final->getVertNo(dm_final, mapindex, ornor);
                        normalize_v3(ornor);
                }
 
@@ -1570,9 +1616,9 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
                MTFace *mtface;
                MVert *mvert;
 
-               mface = dm->getTessFaceData(dm, mapindex, CD_MFACE);
-               mvert = dm->getVertDataArray(dm, CD_MVERT);
-               mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+               mface = dm_final->getTessFaceData(dm_final, mapindex, CD_MFACE);
+               mvert = dm_final->getVertDataArray(dm_final, CD_MVERT);
+               mtface = CustomData_get_layer(&dm_final->faceData, CD_MTFACE);
 
                if (mtface)
                        mtface += mapindex;
@@ -1689,7 +1735,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
                               float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
                               float orco[3], float ornor[3])
 {
-       if (psmd && psmd->dm) {
+       if (psmd && psmd->dm_final) {
                if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) {
                        if (vec)
                                copy_v3_v3(vec, fuv);
@@ -1699,7 +1745,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
                        return;
                }
                /* we cant use the num_dmcache */
-               psys_particle_on_dm(psmd->dm, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco, ornor);
+               psys_particle_on_dm(psmd->dm_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco, ornor);
        }
        else
                psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco, ornor);
@@ -1971,7 +2017,7 @@ void psys_find_parents(ParticleSimulationData *sim)
                psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0);
 
                /* Check if particle doesn't exist because of texture influence. Insert only existing particles into kdtree. */
-               get_cpa_texture(sim->psmd->dm, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
+               get_cpa_texture(sim->psmd->dm_final, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
 
                if (ptex.exist >= psys_frand(psys, p + 24)) {
                        BLI_kdtree_insert(tree, p, orco);
@@ -2183,7 +2229,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
                for (w = 0; w < 4; w++)
                        sub_v3_v3v3(off1[w], co, key[w]->co);
 
-               psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
+               psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
        }
        else {
                ParticleData *pa = psys->particles + cpa->parent;
@@ -2202,13 +2248,13 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
                cpa_from = part->from;
                cpa_num = pa->num;
                /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
-               if (cpa_num > ctx->sim.psmd->dm->getNumTessFaces(ctx->sim.psmd->dm))
+               if (cpa_num > ctx->sim.psmd->dm_final->getNumTessFaces(ctx->sim.psmd->dm_final))
                        cpa_num = 0;
                cpa_fuv = pa->fuv;
 
                psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, ornor, 0, 0, orco, 0);
 
-               psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
+               psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
        }
 
        child_keys->segments = ctx->segments;
@@ -2501,15 +2547,15 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
 
        if ((psys->flag & PSYS_GLOBAL_HAIR) == 0) {
                if ((psys->part->flag & PART_CHILD_EFFECT) == 0)
-                       vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR);
+                       vg_effector = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_EFFECTOR);
                
                if (!psys->totchild)
-                       vg_length = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_LENGTH);
+                       vg_length = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_LENGTH);
        }
 
        /* ensure we have tessfaces to be used for mapping */
        if (part->from != PART_FROM_VERT) {
-               DM_ensure_tessface(psmd->dm);
+               DM_ensure_tessface(psmd->dm_final);
        }
 
        /*---first main loop: create all actual particles' paths---*/
@@ -2518,7 +2564,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
                        psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
                        pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
                        if (vg_length)
-                               pa_length *= psys_particle_value_from_verts(psmd->dm, part->from, pa, vg_length);
+                               pa_length *= psys_particle_value_from_verts(psmd->dm_final, part->from, pa, vg_length);
                }
 
                pind.keyed = keyed;
@@ -2535,7 +2581,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
                init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
 
                /* hairmat is needed for for non-hair particle too so we get proper rotations */
-               psys_mat_hair_to_global(sim->ob, psmd->dm, psys->part->from, pa, hairmat);
+               psys_mat_hair_to_global(sim->ob, psmd->dm_final, psys->part->from, pa, hairmat);
                copy_v3_v3(rotmat[0], hairmat[2]);
                copy_v3_v3(rotmat[1], hairmat[1]);
                copy_v3_v3(rotmat[2], hairmat[0]);
@@ -2590,7 +2636,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
                        if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
                                float effector = 1.0f;
                                if (vg_effector)
-                                       effector *= psys_particle_value_from_verts(psmd->dm, psys->part->from, pa, vg_effector);
+                                       effector *= psys_particle_value_from_verts(psmd->dm_final, psys->part->from, pa, vg_effector);
 
                                sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
                                length = len_v3(vec);
@@ -2735,7 +2781,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
                init_particle_interpolation(ob, psys, pa, &pind);
 
                if (psys) {
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
                        copy_v3_v3(rotmat[0], hairmat[2]);
                        copy_v3_v3(rotmat[1], hairmat[1]);
                        copy_v3_v3(rotmat[2], hairmat[0]);
@@ -3491,7 +3537,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
                                                mul_m4_v3(mtex->object->imat, texvec);
                                        break;
                                case TEXCO_UV:
-                                       if (get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texvec))
+                                       if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec))
                                                break;
                                /* no break, failed to get uv's, so let's try orco's */
                                case TEXCO_ORCO:
@@ -3691,7 +3737,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                        }
                        else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
                                if ((pa->flag & PARS_REKEY) == 0) {
-                                       psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat);
+                                       psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, part->from, pa, hairmat);
                                        mul_m4_v3(hairmat, state->co);
                                        mul_mat3_m4_v3(hairmat, state->vel);
 
@@ -3758,7 +3804,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
 
                                psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
                                if (part->type == PART_HAIR)
-                                       psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+                                       psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
                                else
                                        unit_m4(hairmat);
 
@@ -3779,7 +3825,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                                psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
                                if (part->type == PART_HAIR) {
                                        psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco, 0);
-                                       psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+                                       psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
                                }
                                else {
                                        copy_v3_v3(orco, cpa->fuv);
@@ -3798,7 +3844,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                        /* get different child parameters from textures & vgroups */
                        memset(&ctx, 0, sizeof(ParticleThreadContext));
                        ctx.sim = *sim;
-                       ctx.dm = psmd->dm;
+                       ctx.dm = psmd->dm_final;
                        ctx.ma = ma;
                        /* TODO: assign vertex groups */
                        get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
@@ -4026,10 +4072,10 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part,
        uv[0] = uv[1] = 0.f;
 
        if (cpa) {
-               if ((part->childtype == PART_CHILD_FACES) && (psmd->dm != NULL)) {
-                       mtface = CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
+               if ((part->childtype == PART_CHILD_FACES) && (psmd->dm_final != NULL)) {
+                       mtface = CustomData_get_layer(&psmd->dm_final->faceData, CD_MTFACE);
                        if (mtface) {
-                               mface = psmd->dm->getTessFaceData(psmd->dm, cpa->num, CD_MFACE);
+                               mface = psmd->dm_final->getTessFaceData(psmd->dm_final, cpa->num, CD_MFACE);
                                mtface += cpa->num;
                                psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
                        }
@@ -4042,21 +4088,21 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part,
                }
        }
 
-       if ((part->from == PART_FROM_FACE) && (psmd->dm != NULL)) {
-               mtface = CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
+       if ((part->from == PART_FROM_FACE) && (psmd->dm_final != NULL)) {
+               mtface = CustomData_get_layer(&psmd->dm_final->faceData, CD_MTFACE);
                num = pa->num_dmcache;
 
                if (num == DMCACHE_NOTFOUND)
                        num = pa->num;
 
-               if (num >= psmd->dm->getNumTessFaces(psmd->dm)) {
+               if (num >= psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
                        /* happens when simplify is enabled
                         * gives invalid coords but would crash otherwise */
                        num = DMCACHE_NOTFOUND;
                }
 
                if (mtface && !ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
-                       mface = psmd->dm->getTessFaceData(psmd->dm, num, CD_MFACE);
+                       mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
                        mtface += num;
                        psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
                }
@@ -4231,7 +4277,7 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
                float hairmat[4][4], imat[4][4];
 
                for (p = 0; p < psys->totpart; p++, pa++) {
-                       psys_mat_hair_to_global(sim.ob, sim.psmd->dm, psys->part->from, pa, hairmat);
+                       psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, psys->part->from, pa, hairmat);
                        invert_m4_m4(imat, hairmat);
 
                        hkey = pa->hair;
index 9523ece5f73df8bea25f2afcf1025df7d58bcd81..9f60cbb88e3d5bb7cbc50a73894fa3aeacdd4f20 100644 (file)
@@ -79,7 +79,7 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
        }
 }
 
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
+static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys)
 {
        ChildParticle *cpa = NULL;
        int i, p;
@@ -106,7 +106,7 @@ static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *fi
                }
        }
        /* dmcache must be updated for parent particles if children from faces is used */
-       psys_calc_dmcache(ob, finaldm, psys);
+       psys_calc_dmcache(ob, finaldm, deformdm, psys);
 }
 static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
 {
@@ -763,7 +763,7 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
 static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
 {
        Scene *scene = sim->scene;
-       DerivedMesh *finaldm = sim->psmd->dm;
+       DerivedMesh *finaldm = sim->psmd->dm_final;
        Object *ob = sim->ob;
        ParticleSystem *psys= sim->psys;
        ParticleData *pa=0, *tpars= 0;
@@ -800,7 +800,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
                /* Simple children */
                if (part->childtype != PART_CHILD_FACES) {
                        BLI_srandom(31415926 + psys->seed + psys->child_seed);
-                       distribute_simple_children(scene, ob, finaldm, psys);
+                       distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys);
                        return 0;
                }
        }
@@ -1110,7 +1110,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
        TaskPool *task_pool;
        ParticleThreadContext ctx;
        ParticleTask *tasks;
-       DerivedMesh *finaldm = sim->psmd->dm;
+       DerivedMesh *finaldm = sim->psmd->dm_final;
        int i, totpart, numtasks;
        
        /* create a task pool for distribution tasks */
@@ -1135,7 +1135,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
        
        BLI_task_pool_free(task_pool);
        
-       psys_calc_dmcache(sim->ob, finaldm, sim->psys);
+       psys_calc_dmcache(sim->ob, finaldm, sim->psmd->dm_deformed, sim->psys);
        
        if (ctx.dm != finaldm)
                ctx.dm->release(ctx.dm);
@@ -1159,7 +1159,7 @@ void distribute_particles(ParticleSimulationData *sim, int from)
        int distr_error=0;
 
        if (psmd) {
-               if (psmd->dm)
+               if (psmd->dm_final)
                        distribute_particles_on_dm(sim, from);
                else
                        distr_error=1;
index 130b56987e26bd9ed7a62aed36f0d63d204d436d..bf506c8545beb4b6ea59fe858ae087e2d2091752 100644 (file)
@@ -311,7 +311,7 @@ int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
 /*                     Distribution                                            */
 /************************************************/
 
-void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
+void psys_calc_dmcache(Object *ob, DerivedMesh *dm_final, DerivedMesh *dm_deformed, ParticleSystem *psys)
 {
        /* use for building derived mesh mapping info:
         *
@@ -324,13 +324,13 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
        PARTICLE_P;
        
        /* CACHE LOCATIONS */
-       if (!dm->deformedOnly) {
+       if (!dm_final->deformedOnly) {
                /* Will use later to speed up subsurf/derivedmesh */
                LinkNode *node, *nodedmelem, **nodearray;
                int totdmelem, totelem, i, *origindex, *origindex_poly = NULL;
 
                if (psys->part->from == PART_FROM_VERT) {
-                       totdmelem= dm->getNumVerts(dm);
+                       totdmelem= dm_final->getNumVerts(dm_final);
 
                        if (use_modifier_stack) {
                                totelem= totdmelem;
@@ -338,11 +338,11 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                        }
                        else {
                                totelem= me->totvert;
-                               origindex= dm->getVertDataArray(dm, CD_ORIGINDEX);
+                               origindex= dm_final->getVertDataArray(dm_final, CD_ORIGINDEX);
                        }
                }
                else { /* FROM_FACE/FROM_VOLUME */
-                       totdmelem= dm->getNumTessFaces(dm);
+                       totdmelem= dm_final->getNumTessFaces(dm_final);
 
                        if (use_modifier_stack) {
                                totelem= totdmelem;
@@ -350,20 +350,20 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                                origindex_poly= NULL;
                        }
                        else {
-                               totelem= me->totpoly;
-                               origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+                               totelem = dm_deformed->getNumTessFaces(dm_deformed);
+                               origindex = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
 
                                /* for face lookups we need the poly origindex too */
-                               origindex_poly= dm->getPolyDataArray(dm, CD_ORIGINDEX);
+                               origindex_poly= dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
                                if (origindex_poly == NULL) {
                                        origindex= NULL;
                                }
                        }
                }
-       
+
                nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems");
                nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array");
-               
+
                for (i=0, node=nodedmelem; i<totdmelem; i++, node++) {
                        int origindex_final;
                        node->link = SET_INT_IN_POINTER(i);
@@ -392,7 +392,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                                }
                        }
                }
-               
+
                /* cache the verts/faces! */
                LOOP_PARTICLES {
                        if (pa->num < 0) {
@@ -414,9 +414,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                                                pa->num_dmcache = DMCACHE_NOTFOUND;
                                }
                                else { /* FROM_FACE/FROM_VOLUME */
-                                       /* Note that sometimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this,
-                                        * but for now passing NULL is OK. every face will be searched for the particle so its slower - Campbell */
-                                       pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL);
+                                       pa->num_dmcache = psys_particle_dm_face_lookup(dm_final, dm_deformed, pa->num, pa->fuv, nodearray);
                                }
                        }
                }
@@ -429,8 +427,9 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                 * should know to use the num or num_dmcache, set the num_dmcache to
                 * an invalid value, just in case */
                
-               LOOP_PARTICLES
+               LOOP_PARTICLES {
                        pa->num_dmcache = DMCACHE_NOTFOUND;
+               }
        }
 }
 
@@ -439,7 +438,7 @@ void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData
 {
        memset(ctx, 0, sizeof(ParticleThreadContext));
        ctx->sim = *sim;
-       ctx->dm = ctx->sim.psmd->dm;
+       ctx->dm = ctx->sim.psmd->dm_final;
        ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
 }
 
@@ -3054,7 +3053,7 @@ static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int
                pa->hair_index = hair_index;
                use_hair = psys_hair_use_simulation(pa, max_length);
                
-               psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
+               psys_mat_hair_to_object(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
                mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
                normalize_m4(root_mat);
                
@@ -3209,7 +3208,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra)
 
        if (psys->recalc & PSYS_RECALC_RESET) {
                /* need this for changing subsurf levels */
-               psys_calc_dmcache(sim->ob, sim->psmd->dm, psys);
+               psys_calc_dmcache(sim->ob, sim->psmd->dm_final, sim->psmd->dm_deformed, psys);
 
                if (psys->clmd)
                        cloth_free_modifier(psys->clmd);
@@ -3256,7 +3255,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
 
                if (pa->totkey) {
                        sub_v3_v3(key->co, root->co);
-                       psys_vec_rot_to_face(sim->psmd->dm, pa, key->co);
+                       psys_vec_rot_to_face(sim->psmd->dm_final, pa, key->co);
                }
 
                key->time = pa->state.time;
@@ -4064,11 +4063,11 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
                        return;
        }
 
-       if (!sim.psmd->dm)
+       if (!sim.psmd->dm_final)
                return;
 
        if (part->from != PART_FROM_VERT) {
-               DM_ensure_tessface(sim.psmd->dm);
+               DM_ensure_tessface(sim.psmd->dm_final);
        }
 
        /* execute drivers only, as animation has already been done */
index 01c00ddb48e626325370cc678692b5a565387c52..c51446d6cc8012ec91ae336e954020a76d6f41c4 100644 (file)
@@ -149,6 +149,8 @@ MINLINE void negate_v4_v4(float r[4], const float a[3]);
 
 MINLINE void negate_v3_short(short r[3]);
 
+MINLINE void invert_v2(float r[2]);
+
 MINLINE void abs_v2(float r[2]);
 MINLINE void abs_v2_v2(float r[2], const float a[2]);
 MINLINE void abs_v3(float r[3]);
index e625ac18685088cd80be62d22494b0f83f185ac4..17e2da3f1cbf1ebb81f2395930f1a70990e95b3b 100644 (file)
@@ -633,6 +633,13 @@ MINLINE void negate_v3_short(short r[3])
        r[2] = (short)-r[2];
 }
 
+MINLINE void invert_v2(float r[2])
+{
+       BLI_assert(!ELEM(0.0f, r[0], r[1]));
+       r[0] = 1.0f / r[0];
+       r[1] = 1.0f / r[1];
+}
+
 MINLINE void abs_v2(float r[2])
 {
        r[0] = fabsf(r[0]);
index a3bf673d5fa134c86bc3f4f7a06fe2aa54d61736..86a7b10a3784d6006719d9f65270cd94f5484127 100644 (file)
@@ -5136,7 +5136,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                else if (md->type == eModifierType_ParticleSystem) {
                        ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
                        
-                       psmd->dm= NULL;
+                       psmd->dm_final = NULL;
+                       psmd->dm_deformed = NULL;
                        psmd->psys= newdataadr(fd, psmd->psys);
                        psmd->flag &= ~eParticleSystemFlag_psys_updated;
                        psmd->flag |= eParticleSystemFlag_file_loaded;
index c621d6f99c0051d46083a3b347e5214f847d96a0..28fddbab796ed9a656a73741abd7b527388a58b9 100644 (file)
@@ -214,7 +214,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
                        continue;
                }
 
-               iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i, use_topology) : -1;
+               iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, NULL, i, use_topology) : -1;
                
                /* for each skinnable bone */
                for (j = 0; j < numbones; ++j) {
@@ -411,7 +411,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
        }
 
        /* only generated in some cases but can call anyway */
-       ED_mesh_mirror_spatial_table(ob, NULL, NULL, 'e');
+       ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
 
        /* free the memory allocated */
        MEM_freeN(bonelist);
index 549b60c2ecea489c5af0e90cd163a5ac8844bbf9..4bda82850290930be6617c7a99464d1a93fc44e8 100644 (file)
@@ -675,7 +675,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
        if (dgroupflip) {
                vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
                for (a = 0; a < me->totvert; a++)
-                       vertsflipped[a] = mesh_get_x_mirror_vert(ob, a, use_topology);
+                       vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology);
        }
        
        /* compute weights per bone */
index c509aeb4ac2fd08447d2486f6b8d73abd40bb6a4..f072e707d00e489a92b56b870f9bb88d0cb1e699 100644 (file)
@@ -218,8 +218,8 @@ typedef struct MirrTopoStore_t {
        int prev_ob_mode;
 } MirrTopoStore_t;
 
-bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
-void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
+bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
+void ED_mesh_mirrtopo_init(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
                            const bool skip_em_vert_array_init);
 void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
 
@@ -308,17 +308,18 @@ int         join_mesh_exec(struct bContext *C, struct wmOperator *op);
 int         join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
 
 /* mirror lookup api */
-int         ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode);
-int         ED_mesh_mirror_topo_table(struct Object *ob, char mode);
+int ED_mesh_mirror_spatial_table(
+        struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, const float co[3], char mode);
+int  ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode);
 
 /* retrieves mirrored cache vert, or NULL if there isn't one.
  * note: calling this without ensuring the mirror cache state
  * is bad.*/
-int            mesh_get_x_mirror_vert(struct Object *ob, int index, const bool use_topology);
+int            mesh_get_x_mirror_vert(struct Object *ob, struct DerivedMesh *dm, int index, const bool use_topology);
 struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em,
                                            struct BMVert *eve, const float co[3],
                                            int index, const bool use_topology);
-int           *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
+int           *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm);
 
 int ED_mesh_mirror_get_vert(struct Object *ob, int index);
 
index e5b4e66177315782bbd55307de7f47de724f3ff6..01be8f848aa48b4df292a6c98fd8087c2a5cb666 100644 (file)
@@ -632,12 +632,16 @@ static int mirrtopo_vert_sort(const void *v1, const void *v2)
        return 0;
 }
 
-bool ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
+bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
 {
        int totvert;
        int totedge;
 
-       if (me->edit_btmesh) {
+       if (dm) {
+               totvert = dm->getNumVerts(dm);
+               totedge = dm->getNumEdges(dm);
+       }
+       else if (me->edit_btmesh) {
                totvert = me->edit_btmesh->bm->totvert;
                totedge = me->edit_btmesh->bm->totedge;
        }
@@ -659,11 +663,11 @@ bool ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t
 
 }
 
-void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
+void ED_mesh_mirrtopo_init(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
                            const bool skip_em_vert_array_init)
 {
-       MEdge *medge;
-       BMEditMesh *em = me->edit_btmesh;
+       MEdge *medge = NULL, *med;
+       BMEditMesh *em = dm ?  NULL : me->edit_btmesh;
 
        /* editmode*/
        BMEdge *eed;
@@ -692,7 +696,7 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
                totvert = em->bm->totvert;
        }
        else {
-               totvert = me->totvert;
+               totvert = dm ? dm->getNumVerts(dm) : me->totvert;
        }
 
        topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
@@ -708,10 +712,11 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
                }
        }
        else {
-               totedge = me->totedge;
+               totedge = dm ? dm->getNumEdges(dm) : me->totedge;
+               medge = dm ? dm->getEdgeArray(dm) : me->medge;
 
-               for (a = 0, medge = me->medge; a < me->totedge; a++, medge++) {
-                       const unsigned int i1 = medge->v1, i2 = medge->v2;
+               for (a = 0, med = medge; a < totedge; a++, med++) {
+                       const unsigned int i1 = med->v1, i2 = med->v2;
                        topo_hash[i1]++;
                        topo_hash[i2]++;
                }
@@ -736,8 +741,8 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
                        }
                }
                else {
-                       for (a = 0, medge = me->medge; a < me->totedge; a++, medge++) {
-                               const unsigned int i1 = medge->v1, i2 = medge->v2;
+                       for (a = 0, med = medge; a < totedge; a++, med++) {
+                               const unsigned int i1 = med->v1, i2 = med->v2;
                                topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
                                topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
                                tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
@@ -782,7 +787,6 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
                }
        }
 
-
        for (a = 0; a < totvert; a++) {
                topo_pairs[a].hash    = topo_hash[a];
                topo_pairs[a].v_index = a;
index 9cf80c8f4cf7c84837c1232412cdf582cf867e6b..feb0ef73f15ee9609adbb221701d72368b549793 100644 (file)
@@ -415,8 +415,8 @@ void EDBM_mesh_free(BMEditMesh *em)
        /* These tables aren't used yet, so it's not strictly necessary
         * to 'end' them (with 'e' param) but if someone tries to start
         * using them, having these in place will save a lot of pain */
-       ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
-       ED_mesh_mirror_topo_table(NULL, 'e');
+       ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+       ED_mesh_mirror_topo_table(NULL, NULL, 'e');
 
        BKE_editmesh_free(em);
 }
@@ -1140,7 +1140,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
        BM_mesh_elem_index_ensure(bm, BM_VERT);
 
        if (use_topology) {
-               ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true);
+               ED_mesh_mirrtopo_init(me, NULL, -1, &mesh_topo_store, true);
        }
        else {
                tree = BLI_kdtree_new(bm->totvert);
index dee003135a2352c5614fe1b60766d4126d58e30b..431af56e13d84a34e1d9975248ce13715480da64 100644 (file)
@@ -672,18 +672,15 @@ static struct { void *tree; } MirrKdStore = {NULL};
 
 /* mode is 's' start, or 'e' end, or 'u' use */
 /* if end, ob can be NULL */
-int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, const float co[3], char mode)
+int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, const float co[3], char mode)
 {
        if (mode == 'u') {        /* use table */
                if (MirrKdStore.tree == NULL)
-                       ED_mesh_mirror_spatial_table(ob, em, NULL, 's');
+                       ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's');
 
                if (MirrKdStore.tree) {
                        KDTreeNearest nearest;
-
-                       int i;
-
-                       i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
+                       const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
 
                        if (i != -1) {
                                if (nearest.dist < KD_THRESH) {
@@ -695,22 +692,15 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, const float co[3],
        }
        else if (mode == 's') {   /* start table */
                Mesh *me = ob->data;
-               int totvert;
+               const bool use_em = (!dm && em && me->edit_btmesh == em);
+               const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert;
 
                if (MirrKdStore.tree) /* happens when entering this call without ending it */
-                       ED_mesh_mirror_spatial_table(ob, em, co, 'e');
-
-               if (em && me->edit_btmesh == em) {
-                       totvert = em->bm->totvert;
-               }
-               else {
-                       totvert = me->totvert;
-               }
+                       ED_mesh_mirror_spatial_table(ob, em, dm, co, 'e');
 
                MirrKdStore.tree = BLI_kdtree_new(totvert);
 
-               if (em && me->edit_btmesh == em) {
-
+               if (use_em) {
                        BMVert *eve;
                        BMIter iter;
                        int i;
@@ -723,10 +713,10 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, const float co[3],
                        }
                }
                else {
-                       MVert *mvert;
+                       MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
                        int i;
                        
-                       for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
+                       for (i = 0; i < totvert; i++, mvert++) {
                                BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
                        }
                }
@@ -760,15 +750,15 @@ static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
 /* mode is 's' start, or 'e' end, or 'u' use */
 /* if end, ob can be NULL */
 /* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */
-int ED_mesh_mirror_topo_table(Object *ob, char mode)
+int ED_mesh_mirror_topo_table(Object *ob, DerivedMesh *dm, char mode)
 {
        if (mode == 'u') {        /* use table */
-               if (ED_mesh_mirrtopo_recalc_check(ob->data, ob->mode, &mesh_topo_store)) {
-                       ED_mesh_mirror_topo_table(ob, 's');
+               if (ED_mesh_mirrtopo_recalc_check(ob->data, dm, ob->mode, &mesh_topo_store)) {
+                       ED_mesh_mirror_topo_table(ob, dm, 's');
                }
        }
        else if (mode == 's') { /* start table */
-               ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store, false);
+               ED_mesh_mirrtopo_init(ob->data, dm, ob->mode, &mesh_topo_store, false);
        }
        else if (mode == 'e') { /* end table */
                ED_mesh_mirrtopo_free(&mesh_topo_store);
@@ -783,35 +773,35 @@ int ED_mesh_mirror_topo_table(Object *ob, char mode)
 /** \} */
 
 
-static int mesh_get_x_mirror_vert_spatial(Object *ob, int index)
+static int mesh_get_x_mirror_vert_spatial(Object *ob, DerivedMesh *dm, int index)
 {
        Mesh *me = ob->data;
-       MVert *mvert;
+       MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
        float vec[3];
        
-       mvert = me->mvert + index;
+       mvert = &mvert[index];
        vec[0] = -mvert->co[0];
        vec[1] = mvert->co[1];
        vec[2] = mvert->co[2];
        
-       return ED_mesh_mirror_spatial_table(ob, NULL, vec, 'u');
+       return ED_mesh_mirror_spatial_table(ob, NULL, dm, vec, 'u');
 }
 
-static int mesh_get_x_mirror_vert_topo(Object *ob, int index)
+static int mesh_get_x_mirror_vert_topo(Object *ob, DerivedMesh *dm, int index)
 {
-       if (ED_mesh_mirror_topo_table(ob, 'u') == -1)
+       if (ED_mesh_mirror_topo_table(ob, dm, 'u') == -1)
                return -1;
 
        return mesh_topo_store.index_lookup[index];
 }
 
-int mesh_get_x_mirror_vert(Object *ob, int index, const bool use_topology)
+int mesh_get_x_mirror_vert(Object *ob, DerivedMesh *dm, int index, const bool use_topology)
 {
        if (use_topology) {
-               return mesh_get_x_mirror_vert_topo(ob, index);
+               return mesh_get_x_mirror_vert_topo(ob, dm, index);
        }
        else {
-               return mesh_get_x_mirror_vert_spatial(ob, index);
+               return mesh_get_x_mirror_vert_spatial(ob, dm, index);
        }
 }
 
@@ -832,7 +822,7 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
        vec[1] = co[1];
        vec[2] = co[2];
        
-       i = ED_mesh_mirror_spatial_table(ob, em, vec, 'u');
+       i = ED_mesh_mirror_spatial_table(ob, em, NULL, vec, 'u');
        if (i != -1) {
                return BM_vert_at_index(em->bm, i);
        }
@@ -842,7 +832,7 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
 static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *em, BMVert *eve, int index)
 {
        intptr_t poinval;
-       if (ED_mesh_mirror_topo_table(ob, 'u') == -1)
+       if (ED_mesh_mirror_topo_table(ob, NULL, 'u') == -1)
                return NULL;
 
        if (index == -1) {
@@ -897,7 +887,7 @@ int ED_mesh_mirror_get_vert(Object *ob, int index)
                index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
        }
        else {
-               index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology);
+               index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, use_topology);
        }
 
        return index_mirr;
@@ -1007,31 +997,39 @@ static bool mirror_facecmp(const void *a, const void *b)
 }
 
 /* BMESH_TODO, convert to MPoly (functions above also) */
-int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
+int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
 {
        Mesh *me = ob->data;
-       MVert *mv, *mvert = me->mvert;
-       MFace mirrormf, *mf, *hashmf, *mface = me->mface;
+       MVert *mv, *mvert;
+       MFace mirrormf, *mf, *hashmf, *mface;
        GHash *fhash;
-       const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
        int *mirrorverts, *mirrorfaces;
+
+       BLI_assert(em == NULL);  /* Does not work otherwise, currently... */
+
+       const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+       const int totvert = dm ? dm->getNumVerts(dm) : me->totvert;
+       const int totface = dm ? dm->getNumTessFaces(dm) : me->totface;
        int a;
 
-       mirrorverts = MEM_callocN(sizeof(int) * me->totvert, "MirrorVerts");
-       mirrorfaces = MEM_callocN(sizeof(int) * 2 * me->totface, "MirrorFaces");
+       mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
+       mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces");
+
+       mvert = dm ? dm->getVertArray(dm) : me->mvert;
+       mface = dm ? dm->getTessFaceArray(dm) : me->mface;
 
-       ED_mesh_mirror_spatial_table(ob, em, NULL, 's');
+       ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's');
 
-       for (a = 0, mv = mvert; a < me->totvert; a++, mv++)
-               mirrorverts[a] = mesh_get_x_mirror_vert(ob, a, use_topology);
+       for (a = 0, mv = mvert; a < totvert; a++, mv++)
+               mirrorverts[a] = mesh_get_x_mirror_vert(ob, dm, a, use_topology);
 
-       ED_mesh_mirror_spatial_table(ob, em, NULL, 'e');
+       ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 'e');
 
        fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
-       for (a = 0, mf = mface; a < me->totface; a++, mf++)
+       for (a = 0, mf = mface; a < totface; a++, mf++)
                BLI_ghash_insert(fhash, mf, mf);
 
-       for (a = 0, mf = mface; a < me->totface; a++, mf++) {
+       for (a = 0, mf = mface; a < totface; a++, mf++) {
                mirrormf.v1 = mirrorverts[mf->v3];
                mirrormf.v2 = mirrorverts[mf->v2];
                mirrormf.v3 = mirrorverts[mf->v1];
index 64a69542e3828e53ddaeb2045f32f711b9ff1ddc..67c9f6e98da1bfcda8c629c37301007c6c218bd8 100644 (file)
@@ -342,8 +342,8 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
                        me->edit_btmesh = NULL;
                }
                if (obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
-                       ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
-                       ED_mesh_mirror_topo_table(NULL, 'e');
+                       ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+                       ED_mesh_mirror_topo_table(NULL, NULL, 'e');
                }
        }
        else if (obedit->type == OB_ARMATURE) {
index ed71af71ac9332b868d90944ab09e4e621f8ffe3..39bd34456beb3317cb474d7bfb66f064f67b8339 100644 (file)
@@ -131,10 +131,10 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
                        float *fp1, *fp2;
                        float tvec[3];
 
-                       ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's');
+                       ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
 
                        for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
-                               i2 = mesh_get_x_mirror_vert(ob, i1, use_topology);
+                               i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
                                if (i2 == i1) {
                                        fp1 = ((float *)kb->data) + i1 * 3;
                                        fp1[0] = -fp1[0];
@@ -162,7 +162,7 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
                                }
                        }
 
-                       ED_mesh_mirror_spatial_table(ob, NULL, NULL, 'e');
+                       ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
                }
                else if (ob->type == OB_LATTICE) {
                        Lattice *lt = ob->data;
index 2271baf46a5f2432c0a8dbeb18fbb3622b25a6bd..c0b0303404e76957f423ab36e638e3f62729ecda 100644 (file)
@@ -517,7 +517,7 @@ static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
        if (vidx == -1)
                return;
 
-       vidx_mirr = mesh_get_x_mirror_vert(ob, vidx, use_topology);
+       vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology);
 
        if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
                MDeformVert *dvert_src = &me->dvert[vidx];
@@ -2244,7 +2244,7 @@ void ED_vgroup_mirror(Object *ob,
 
                        for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
                                if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
-                                       if ((vidx_mirr = mesh_get_x_mirror_vert(ob, vidx, use_topology)) != -1) {
+                                       if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
                                                if (vidx != vidx_mirr) {
                                                        mv_mirr = &me->mvert[vidx_mirr];
                                                        if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
index 64ad3a100cca666be75c0b20b15d5e1f13e9bd3b..deba3bbca32eb0048809431221d4e701515f347c 100644 (file)
@@ -659,7 +659,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
                                if (selected==0 || key->flag & PEK_SELECT) {
                                        if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
                                                if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
-                                                       psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat);
+                                                       psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
                                                        invert_m4_m4(imat, mat);
                                                }
 
@@ -674,7 +674,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
                                if (selected==0 || key->flag & PEK_SELECT) {
                                        if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
                                                if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
-                                                       psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat);
+                                                       psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
                                                        invert_m4_m4(imat, mat);
                                                }
 
@@ -761,7 +761,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        psmd= psys_get_modifier(ob, psys);
        totpart= psys->totpart;
 
-       if (!psmd->dm)
+       if (!psmd->dm_final)
                return;
 
        tree= BLI_kdtree_new(totpart);
@@ -769,7 +769,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        /* insert particles into kd tree */
        LOOP_PARTICLES {
                key = pa->hair;
-               psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
+               psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
                copy_v3_v3(co, key->co);
                mul_m4_v3(mat, co);
                BLI_kdtree_insert(tree, p, co);
@@ -783,7 +783,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        
        LOOP_PARTICLES {
                key = pa->hair;
-               psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
+               psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
                copy_v3_v3(co, key->co);
                mul_m4_v3(mat, co);
                co[0] = -co[0];
@@ -898,7 +898,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
        edit= psys->edit;
        psmd= psys_get_modifier(ob, psys);
 
-       if (!psmd->dm)
+       if (!psmd->dm_final)
                return;
 
        if (!edit->mirror_cache)
@@ -911,7 +911,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
         * to avoid doing mirror twice */
        LOOP_POINTS {
                if (point->flag & PEP_EDIT_RECALC) {
-                       PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
+                       PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
 
                        if (edit->mirror_cache[p] != -1)
                                edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
@@ -946,11 +946,11 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
        psys = edit->psys;
        psmd = psys_get_modifier(ob, psys);
 
-       if (!psmd->dm)
+       if (!psmd->dm_final)
                return;
 
        LOOP_EDITED_POINTS {
-               psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles + p, hairmat);
+               psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
        
                LOOP_KEYS {
                        mul_m4_v3(hairmat, key->co);
@@ -1095,7 +1095,7 @@ void recalc_lengths(PTCacheEdit *edit)
 /* calculate a tree for finding nearest emitter's vertice */
 void recalc_emitter_field(Object *ob, ParticleSystem *psys)
 {
-       DerivedMesh *dm=psys_get_modifier(ob, psys)->dm;
+       DerivedMesh *dm=psys_get_modifier(ob, psys)->dm_final;
        PTCacheEdit *edit= psys->edit;
        float *vec, *nor;
        int i, totface /*, totvert*/;
@@ -1188,12 +1188,12 @@ void update_world_cos(Object *ob, PTCacheEdit *edit)
        POINT_P; KEY_K;
        float hairmat[4][4];
 
-       if (psys==0 || psys->edit==0 || psmd->dm==NULL)
+       if (psys==0 || psys->edit==0 || psmd->dm_final==NULL)
                return;
 
        LOOP_POINTS {
                if (!(psys->flag & PSYS_GLOBAL_HAIR))
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, hairmat);
+                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, hairmat);
 
                LOOP_KEYS {
                        copy_v3_v3(key->world_co, key->co);
@@ -1839,7 +1839,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
 
        LOOP_VISIBLE_POINTS {
                if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + p, mat);
+                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
 
                if (pset->selectmode==SCE_SELECT_POINT) {
                        LOOP_KEYS {
@@ -2273,7 +2273,7 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
                psmd= psys_get_modifier(ob, psys);
 
                LOOP_TAGGED_POINTS {
-                       PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
+                       PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
                }
        }
 
@@ -2353,7 +2353,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
 
                LOOP_POINTS {
                        LOOP_TAGGED_KEYS {
-                               PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
+                               PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
                                break;
                        }
                }
@@ -2567,7 +2567,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
                        
                /* insert particles into kd tree */
                LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
+                       psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
                        copy_v3_v3(co, point->keys->co);
                        mul_m4_v3(mat, co);
                        BLI_kdtree_insert(tree, p, co);
@@ -2577,7 +2577,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
 
                /* tag particles to be removed */
                LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
+                       psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
                        copy_v3_v3(co, point->keys->co);
                        mul_m4_v3(mat, co);
 
@@ -2808,13 +2808,17 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                return;
 
        psmd= psys_get_modifier(ob, psys);
-       if (!psmd->dm)
+       if (!psmd->dm_final)
                return;
 
+       const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly);
+
        /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
        BKE_mesh_tessface_ensure(me);
 
-       mirrorfaces= mesh_get_x_mirror_faces(ob, NULL);
+       /* Note: In case psys uses DM tessface indices, we mirror final DM iteslef, not orig mesh. Avoids an (impossible)
+        *       dm -> orig -> dm tessface indices conversion... */
+       mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd->dm_final : NULL);
 
        if (!edit->mirror_cache)
                PE_update_mirror_cache(ob, psys);
@@ -2823,11 +2827,12 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
        newtotpart= psys->totpart;
        LOOP_VISIBLE_POINTS {
                pa = psys->particles + p;
+
                if (!tagged) {
                        if (point_is_selected(point)) {
                                if (edit->mirror_cache[p] != -1) {
                                        /* already has a mirror, don't need to duplicate */
-                                       PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
+                                       PE_mirror_particle(ob, psmd->dm_final, psys, pa, NULL);
                                        continue;
                                }
                                else
@@ -2840,6 +2845,8 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
        }
 
        if (newtotpart != psys->totpart) {
+               MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface;
+
                /* allocate new arrays and copy existing */
                new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
                new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint new");
@@ -2869,10 +2876,12 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
 
                for (p=0, point=edit->points; p<totpart; p++, point++) {
                        pa = psys->particles + p;
+                       const int pa_num = pa->num;
 
                        if (point->flag & PEP_HIDE)
                                continue;
-                       if (!(point->flag & PEP_TAG) || mirrorfaces[pa->num*2] == -1)
+
+                       if (!(point->flag & PEP_TAG) || mirrorfaces[pa_num * 2] == -1)
                                continue;
 
                        /* duplicate */
@@ -2882,27 +2891,31 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                        if (point->keys) newpoint->keys= MEM_dupallocN(point->keys);
 
                        /* rotate weights according to vertex index rotation */
-                       rotation= mirrorfaces[pa->num*2+1];
+                       rotation= mirrorfaces[pa_num * 2 + 1];
                        newpa->fuv[0] = pa->fuv[2];
                        newpa->fuv[1] = pa->fuv[1];
                        newpa->fuv[2] = pa->fuv[0];
                        newpa->fuv[3] = pa->fuv[3];
-                       while (rotation-- > 0)
-                               if (me->mface[pa->num].v4) {
+                       while (rotation--) {
+                               if (mtessface[pa_num].v4) {
                                        SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3]);
                                }
                                else {
                                        SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2]);
                                }
+                       }
 
-                       /* assign face inddex */
-                       newpa->num= mirrorfaces[pa->num*2];
-                       newpa->num_dmcache= psys_particle_dm_face_lookup(ob, psmd->dm, newpa->num, newpa->fuv, NULL);
+                       /* assign face index */
+                       /* NOTE: mesh_get_x_mirror_faces generates -1 for non-found mirror, same as DMCACHE_NOTFOUND... */
+                       newpa->num = mirrorfaces[pa_num * 2];
 
-                       if ((newpa->num_dmcache != DMCACHE_NOTFOUND) && psys->part->use_modifier_stack && !psmd->dm->deformedOnly) {
-                               newpa->num = newpa->num_dmcache;
+                       if (use_dm_final_indices) {
                                newpa->num_dmcache = DMCACHE_ISCHILD;
                        }
+                       else {
+                               newpa->num_dmcache = psys_particle_dm_face_lookup(
+                                                        psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
+                       }
 
                        /* update edit key pointers */
                        key= newpoint->keys;
@@ -2912,7 +2925,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                        }
 
                        /* map key positions as mirror over x axis */
-                       PE_mirror_particle(ob, psmd->dm, psys, pa, newpa);
+                       PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa);
 
                        newpa++;
                        newpoint++;
@@ -3360,7 +3373,7 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
        totface=dm->getNumTessFaces(dm);
        mface=dm->getTessFaceDataArray(dm, CD_MFACE);
        mvert=dm->getVertDataArray(dm, CD_MVERT);
-       
+
        /* lets intersect the faces */
        for (i=0; i<totface; i++, mface++) {
                if (vert_cos) {
@@ -3452,6 +3465,7 @@ static int brush_add(PEData *data, short number)
 {
        Scene *scene= data->scene;
        Object *ob= data->ob;
+       DerivedMesh *dm;
        PTCacheEdit *edit = data->edit;
        ParticleSystem *psys= edit->psys;
        ParticleData *add_pars;
@@ -3465,11 +3479,7 @@ static int brush_add(PEData *data, short number)
        float framestep, timestep;
        short size= pset->brush[PE_BRUSH_ADD].size;
        short size2= size*size;
-       DerivedMesh *dm=0;
        RNG *rng;
-       const int *index_mf_to_mpoly;
-       const int *index_mp_to_orig;
-       bool release_dm = false;
 
        invert_m4_m4(imat, ob->obmat);
 
@@ -3487,15 +3497,13 @@ static int brush_add(PEData *data, short number)
 
        timestep= psys_get_timestep(&sim);
 
-       if (psmd->dm->deformedOnly || psys->part->use_modifier_stack)
-               dm = psmd->dm;
+       if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) {
+               dm = psmd->dm_final;
+       }
        else {
-               dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE);
-               release_dm = true;
+               dm = psmd->dm_deformed;
        }
-
-       index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
-       index_mp_to_orig  = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+       BLI_assert(dm);
 
        for (i=0; i<number; i++) {
                if (number>1) {
@@ -3523,16 +3531,22 @@ static int brush_add(PEData *data, short number)
                
                /* warning, returns the derived mesh face */
                if (particle_intersect_dm(scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
-                       if (index_mf_to_mpoly && index_mp_to_orig)
-                               add_pars[n].num = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, add_pars[n].num_dmcache);
-                       else
+                       if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
+                               add_pars[n].num = add_pars[n].num_dmcache;
+                               add_pars[n].num_dmcache = DMCACHE_ISCHILD;
+                       }
+                       else if (dm == psmd->dm_deformed) {
+                               /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
+                               add_pars[n].num = add_pars[n].num_dmcache;
+                               add_pars[n].num_dmcache = psys_particle_dm_face_lookup(
+                                                             psmd->dm_final, psmd->dm_deformed,
+                                                             add_pars[n].num, add_pars[n].fuv, NULL);
+                       }
+                       else {
                                add_pars[n].num = add_pars[n].num_dmcache;
+                       }
 
-                       if (psys_particle_dm_face_lookup(ob, psmd->dm, add_pars[n].num_dmcache, add_pars[n].fuv, NULL) != DMCACHE_NOTFOUND) {
-                               if (psys->part->use_modifier_stack && !psmd->dm->deformedOnly) {
-                                       add_pars[n].num = add_pars[n].num_dmcache;
-                                       add_pars[n].num_dmcache = DMCACHE_ISCHILD;
-                               }
+                       if (add_pars[n].num != DMCACHE_NOTFOUND) {
                                n++;
                        }
                }
@@ -3567,7 +3581,7 @@ static int brush_add(PEData *data, short number)
                        tree=BLI_kdtree_new(psys->totpart);
                        
                        for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
-                               psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0);
+                               psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0);
                                BLI_kdtree_insert(tree, i, cur_co);
                        }
 
@@ -3611,7 +3625,7 @@ static int brush_add(PEData *data, short number)
                                int w, maxw;
                                float maxd, totw=0.0, weight[3];
 
-                               psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
+                               psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
                                maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3);
 
                                maxd= ptn[maxw-1].dist;
@@ -3676,7 +3690,7 @@ static int brush_add(PEData *data, short number)
                                }
                        }
                        for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
-                               psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+                               psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
                                invert_m4_m4(imat, hairmat);
                                mul_m4_v3(imat, hkey->co);
                        }
@@ -3688,9 +3702,6 @@ static int brush_add(PEData *data, short number)
 
        MEM_freeN(add_pars);
 
-       if (release_dm)
-               dm->release(dm);
-
        BLI_rng_free(rng);
        
        return n;
@@ -3866,7 +3877,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                                case PE_BRUSH_PUFF:
                                {
                                        if (edit->psys) {
-                                               data.dm= psmd->dm;
+                                               data.dm= psmd->dm_final;
                                                data.mval= mval;
                                                data.rad= pe_brush_size_get(scene, brush);
                                                data.select= selected;
@@ -3922,7 +3933,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                                case PE_BRUSH_WEIGHT:
                                {
                                        if (edit->psys) {
-                                               data.dm= psmd->dm;
+                                               data.dm= psmd->dm_final;
                                                data.mval= mval;
                                                data.rad= pe_brush_size_get(scene, brush);
 
@@ -4545,7 +4556,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
 
        LOOP_VISIBLE_POINTS {
                if (psys)
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
+                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
 
                LOOP_SELECTED_KEYS {
                        copy_v3_v3(co, key->co);
@@ -4576,7 +4587,7 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic
        int totpoint;
 
        /* no psmd->dm happens in case particle system modifier is not enabled */
-       if (!(psys && psmd && psmd->dm) && !cache)
+       if (!(psys && psmd && psmd->dm_final) && !cache)
                return;
 
        if (cache && cache->flag & PTCACHE_DISK_CACHE)
index 6d143fb13f3dc1d1acd0b75a64731b2748f58cb9..ecd276465625617d24d79a76e9f9ca3809c13e14 100644 (file)
@@ -592,7 +592,7 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
                        point++;
                }
 
-               psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+               psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
 
                for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
                        mul_m4_v3(hairmat, key->co);
@@ -676,7 +676,7 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
        float from_ob_imat[4][4], to_ob_imat[4][4];
        float from_imat[4][4], to_imat[4][4];
 
-       if (!target_psmd->dm)
+       if (!target_psmd->dm_final)
                return false;
        if (!psys->part || psys->part->type != PART_HAIR)
                return false;
@@ -690,15 +690,14 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
        invert_m4_m4(from_imat, from_mat);
        invert_m4_m4(to_imat, to_mat);
        
-       if (target_psmd->dm->deformedOnly) {
+       if (target_psmd->dm_final->deformedOnly) {
                /* we don't want to mess up target_psmd->dm when converting to global coordinates below */
-               dm = target_psmd->dm;
+               dm = target_psmd->dm_final;
        }
        else {
-               /* warning: this rebuilds target_psmd->dm! */
-               dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH | CD_MASK_MFACE);
+               dm = target_psmd->dm_deformed;
        }
-       target_dm = target_psmd->dm;
+       target_dm = target_psmd->dm_final;
        /* don't modify the original vertices */
        dm = CDDM_copy(dm);
 
@@ -766,7 +765,7 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
                        tpa->foffset = 0.0f;
 
                        tpa->num = nearest.index;
-                       tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL);
+                       tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL);
                }
                else {
                        me = &medge[nearest.index];
@@ -1066,9 +1065,9 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Parti
                modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
                
                psmd->psys = psys;
-               psmd->dm = CDDM_copy(final_dm);
-               CDDM_calc_normals(psmd->dm);
-               DM_ensure_tessface(psmd->dm);
+               psmd->dm_final = CDDM_copy(final_dm);
+               CDDM_calc_normals(psmd->dm_final);
+               DM_ensure_tessface(psmd->dm_final);
                
                if (psys_from->edit)
                        copy_particle_edit(scene, ob_to, psys, psys_from);
index 5fa0c9fc71e5b6c16a2d31a0ecbc60d46d16cbe9..34870a112bc8a417fce296d3809d6bea6a9cbd6e 100644 (file)
@@ -412,7 +412,7 @@ bool ED_wpaint_fill(VPaint *wp, Object *ob, float paintweight)
                                        dw->weight = paintweight;
 
                                        if (me->editflag & ME_EDIT_MIRROR_X) {  /* x mirror painting */
-                                               int j = mesh_get_x_mirror_vert(ob, vidx, topology);
+                                               int j = mesh_get_x_mirror_vert(ob, NULL, vidx, topology);
                                                if (j >= 0) {
                                                        /* copy, not paint again */
                                                        if (vgroup_mirror != -1) {
@@ -1718,7 +1718,7 @@ static void do_weight_paint_vertex(
 
        /* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
        if (me->editflag & ME_EDIT_MIRROR_X) {
-               index_mirr = mesh_get_x_mirror_vert(ob, index, topology);
+               index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
                vgroup_mirr = (wpi->vgroup_mirror != -1) ? wpi->vgroup_mirror : wpi->vgroup_active;
 
                /* another possible error - mirror group _and_ active group are the same (which is fine),
@@ -1956,8 +1956,8 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
                }
 
                /* weight paint specific */
-               ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
-               ED_mesh_mirror_topo_table(NULL, 'e');
+               ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+               ED_mesh_mirror_topo_table(NULL, NULL, 'e');
 
                paint_cursor_delete_textures();
        }
@@ -1972,7 +1972,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
                BKE_paint_init(scene, ePaintWeight, PAINT_CURSOR_WEIGHT_PAINT);
 
                /* weight paint specific */
-               ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's');
+               ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
                ED_vgroup_sync_from_pose(ob);
        }
        
index dc0b153d6e90af98aa5a851b2553a06ceadc2826..c18501d0e36bed9bc2125aff17d938abb59c2e40 100644 (file)
@@ -1865,7 +1865,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
                if (!(point->flag & PEP_TRANSFORM)) continue;
 
                if (psys && !(psys->flag & PSYS_GLOBAL_HAIR))
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
+                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
 
                for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
                        if (key->flag & PEK_USE_WCO) {
@@ -1939,7 +1939,7 @@ void flushTransParticles(TransInfo *t)
                if (!(point->flag & PEP_TRANSFORM)) continue;
 
                if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
+                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
                        invert_m4_m4(imat, mat);
 
                        for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
@@ -6280,7 +6280,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
                if (t->obedit->type == OB_MESH) {
                        BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
                        /* table needs to be created for each edit command, since vertices can move etc */
-                       ED_mesh_mirror_spatial_table(t->obedit, em, NULL, 'e');
+                       ED_mesh_mirror_spatial_table(t->obedit, em, NULL, NULL, 'e');
                }
        }
        else if ((t->flag & T_POSE) && (t->poseobj)) {
index 0463980dacd2fc91c09a04e3c7a2fbf89c746eec..1c3ab03c43a95d1e7df6fc75814e78c9a9569db0 100644 (file)
@@ -151,8 +151,8 @@ void ED_editors_exit(bContext *C)
        }
 
        /* global in meshtools... */
-       ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
-       ED_mesh_mirror_topo_table(NULL, 'e');
+       ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+       ED_mesh_mirror_topo_table(NULL, NULL, 'e');
 }
 
 /* flush any temp data from object editing to DNA before writing files,
index 7bd29137aebabc2fa300d398d968d1b719af75f3..d00e5d574fa3bdc87b9f9054437a6ceefd8eb890 100644 (file)
@@ -716,7 +716,8 @@ typedef struct ParticleSystemModifierData {
        ModifierData modifier;
 
        struct ParticleSystem *psys;
-       struct DerivedMesh *dm;
+       struct DerivedMesh *dm_final;  /* Final DM - its topology may differ from orig mesh. */
+       struct DerivedMesh *dm_deformed;  /* Deformed-onle DM - its topology is same as orig mesh one. */
        int totdmvert, totdmedge, totdmface;
        short flag, pad;
 } ParticleSystemModifierData;
index 95cb5c84bed1b11cdd806488ea34e02e400e81a6..b284a683f8e6172fa12c84e72add10ae328853e8 100644 (file)
@@ -109,6 +109,7 @@ typedef struct ParticleData {
        float time, lifetime;   /* dietime is not nescessarily time+lifetime as */
        float dietime;                  /* particles can die unnaturally (collision)    */
 
+       /* WARNING! Those two indices, when not affected to vertices, are for !!! TESSELLATED FACES !!!, not POLYGONS! */
        int num;                                /* index to vert/edge/face */
        int num_dmcache;                /* index to derived mesh data (face) to avoid slow lookups */
 
index 5645f018cad1e0ddcde28e0ce402fc069e9f273d..ae8b3799bac2751914b227d2afa5b5425da1bd6d 100644 (file)
@@ -167,7 +167,7 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
                                if (enable)
                                        psys_render_set(ob, psys, mat, mat, 1, 1, 0.f);
                                else
-                                       psys_render_restore(ob, psys);
+                                       psys_render_restore(scene, ob, psys);
                        }
                }
 
index 8d4be2af533992064ffd609845a7277f27346fad..94b33916cf4561b5671146aa9798877881142b84 100644 (file)
@@ -175,7 +175,7 @@ static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr, ParticleSy
        for (md = ob->modifiers.first; md; md = md->next) {
                if (md->type == eModifierType_ParticleSystem) {
                        psmd = (ParticleSystemModifierData *) md;
-                       if (psmd && psmd->dm && psmd->psys) {
+                       if (psmd && psmd->dm_final && psmd->psys) {
                                psys = psmd->psys;
                                for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
                                        /* hairkeys are stored sequentially in memory, so we can
@@ -210,7 +210,7 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu
                }
                else {
                        float hairmat[4][4];
-                       psys_mat_hair_to_object(ob, psmd->dm, psmd->psys->part->from, pa, hairmat);
+                       psys_mat_hair_to_object(ob, psmd->dm_final, psmd->psys->part->from, pa, hairmat);
                        copy_v3_v3(values, hkey->co);
                        mul_m4_v3(hairmat, values);
                }
@@ -240,7 +240,7 @@ static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float
                        float hairmat[4][4];
                        float imat[4][4];
 
-                       psys_mat_hair_to_object(ob, psmd->dm, psmd->psys->part->from, pa, hairmat);
+                       psys_mat_hair_to_object(ob, psmd->dm_final, psmd->psys->part->from, pa, hairmat);
                        invert_m4_m4(imat, hairmat);
                        copy_v3_v3(hkey->co, values);
                        mul_m4_v3(imat, hkey->co);
@@ -263,7 +263,7 @@ static void rna_ParticleHairKey_co_object(HairKey *hairkey, Object *object, Part
                }
                else {
                        float hairmat[4][4];
-                       psys_mat_hair_to_object(object, modifier->dm, modifier->psys->part->from, particle, hairmat);
+                       psys_mat_hair_to_object(object, modifier->dm_final, modifier->psys->part->from, particle, hairmat);
                        copy_v3_v3(n_co, hairkey->co);
                        mul_m4_v3(hairmat, n_co);
                }
@@ -282,14 +282,14 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *repor
        int num = particle->num_dmcache;
        int from = modifier->psys->part->from;
 
-       if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
+       if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPUV)) {
                BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
                return;
        }
-       DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+       DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
 
        if (num == DMCACHE_NOTFOUND)
-               if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
+               if (particle->num < modifier->dm_final->getNumTessFaces(modifier->dm_final))
                        num = particle->num;
 
        /* get uvco */
@@ -299,8 +299,8 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *repor
                        MFace *mface;
                        MTFace *mtface;
 
-                       mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
-                       mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+                       mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
+                       mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MTFACE, 0);
 
                        if (mface && mtface) {
                                mtface += num;
@@ -446,8 +446,8 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
        int totface;
        int num = -1;
 
-       DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-       totface = modifier->dm->getNumTessFaces(modifier->dm);
+       DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+       totface = modifier->dm_final->getNumTessFaces(modifier->dm_final);
 
        /* 1. check that everything is ok & updated */
        if (!particlesystem || !totface) {
@@ -476,9 +476,6 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
        if (particle_no < totpart) {
                num = (ELEM(particle->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? particle->num : particle->num_dmcache;
 
-               if (num == DMCACHE_NOTFOUND)
-                       num = particle->num;
-
                if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
                        if (num != DMCACHE_NOTFOUND && num < totface) {
                                *r_fuv = &particle->fuv;
@@ -521,7 +518,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
                                              ParticleSystemModifierData *modifier, ParticleData *particle,
                                              int particle_no, int uv_no, float r_uv[2])
 {
-       if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
+       if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPUV)) {
                BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
                zero_v2(r_uv);
                return;
@@ -538,8 +535,8 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
                        zero_v2(r_uv);
                }
                else {
-                       MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
-                       MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
+                       MFace *mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
+                       MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MTFACE, uv_no);
 
                        psys_interpolate_uvs(&mtface[num], mface->v4, *fuv, r_uv);
                }
@@ -550,7 +547,7 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, R
                                                ParticleSystemModifierData *modifier, ParticleData *particle,
                                                int particle_no, int vcol_no, float r_mcol[3])
 {
-       if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPCOL)) {
+       if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPCOL)) {
                BKE_report(reports, RPT_ERROR, "Mesh has no VCol data");
                zero_v3(r_mcol);
                return;
@@ -567,8 +564,8 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, R
                        zero_v3(r_mcol);
                }
                else {
-                       MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
-                       MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
+                       MFace *mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
+                       MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MCOL, vcol_no);
                        MCol mcol;
 
                        psys_interpolate_mcol(&mc[num * 4], mface->v4, *fuv, &mcol);
@@ -595,7 +592,7 @@ static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Sc
                ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
                
                if (particlesystem->renderdata) {
-                       psys_render_restore(object, particlesystem);
+                       psys_render_restore(scene, object, particlesystem);
                }
                
                psmd->flag &= ~eParticleSystemFlag_psys_updated;
index d57ace8d7fec9aa38217df8d077f24a0ea230432..1ac18858f56769bf1ca934100bb4471fb1b5fb44 100644 (file)
@@ -1006,7 +1006,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
 
                if (psys == NULL || psys->totpart == 0) return derivedData;
                if (psys->part == NULL || psys->particles == NULL) return derivedData;
-               if (psmd->dm == NULL) return derivedData;
+               if (psmd->dm_final== NULL) return derivedData;
 
                /* 1. find faces to be exploded if needed */
                if (emd->facepa == NULL ||
index 289611ad90aab8bac693d58ab3f459742915115c..4e78e758dc3568b8f7af629c5ccd61716b85057d 100644 (file)
@@ -351,7 +351,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                                ChildParticle *cpa = psys->child + (p - psys->totpart);
                                                pa = psys->particles + cpa->parent;
                                        }
-                                       psys_mat_hair_to_global(sim.ob, sim.psmd->dm, sim.psys->part->from, pa, hairmat);
+                                       psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat);
                                        copy_m3_m4(mat, hairmat);
                                        /* to quaternion */
                                        mat3_to_quat(frame, mat);
index de1b11eddd92fecd346cc7a5d26b03dd01166948..6b2b999d5963767eb5547dd9227ffbfabc3b8bcc 100644 (file)
@@ -51,17 +51,23 @@ static void initData(ModifierData *md)
 {
        ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
        psmd->psys = NULL;
-       psmd->dm = NULL;
+       psmd->dm_final = NULL;
+       psmd->dm_deformed = NULL;
        psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
 }
 static void freeData(ModifierData *md)
 {
        ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
 
-       if (psmd->dm) {
-               psmd->dm->needsFree = 1;
-               psmd->dm->release(psmd->dm);
-               psmd->dm = NULL;
+       if (psmd->dm_final) {
+               psmd->dm_final->needsFree = 1;
+               psmd->dm_final->release(psmd->dm_final);
+               psmd->dm_final = NULL;
+               if (psmd->dm_deformed) {
+                       psmd->dm_deformed->needsFree = 1;
+                       psmd->dm_deformed->release(psmd->dm_deformed);
+                       psmd->dm_deformed = NULL;
+               }
        }
 
        /* ED_object_modifier_remove may have freed this first before calling
@@ -78,7 +84,8 @@ static void copyData(ModifierData *md, ModifierData *target)
 
        modifier_copyData_generic(md, target);
 
-       tpsmd->dm = NULL;
+       tpsmd->dm_final = NULL;
+       tpsmd->dm_deformed = NULL;
        tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
 }
 
@@ -119,9 +126,14 @@ static void deformVerts(ModifierData *md, Object *ob,
        }
 
        /* clear old dm */
-       if (psmd->dm) {
-               psmd->dm->needsFree = 1;
-               psmd->dm->release(psmd->dm);
+       if (psmd->dm_final) {
+               psmd->dm_final->needsFree = 1;
+               psmd->dm_final->release(psmd->dm_final);
+               if (psmd->dm_deformed) {
+                       psmd->dm_deformed->needsFree = 1;
+                       psmd->dm_deformed->release(psmd->dm_deformed);
+                       psmd->dm_deformed = NULL;
+               }
        }
        else if (psmd->flag & eParticleSystemFlag_file_loaded) {
                /* in file read dm just wasn't saved in file so no need to reset everything */
@@ -133,9 +145,9 @@ static void deformVerts(ModifierData *md, Object *ob,
        }
 
        /* make new dm */
-       psmd->dm = CDDM_copy(dm);
-       CDDM_apply_vert_coords(psmd->dm, vertexCos);
-       CDDM_calc_normals(psmd->dm);
+       psmd->dm_final = CDDM_copy(dm);
+       CDDM_apply_vert_coords(psmd->dm_final, vertexCos);
+       CDDM_calc_normals(psmd->dm_final);
 
        if (needsFree) {
                dm->needsFree = 1;
@@ -143,19 +155,27 @@ static void deformVerts(ModifierData *md, Object *ob,
        }
 
        /* protect dm */
-       psmd->dm->needsFree = 0;
+       psmd->dm_final->needsFree = 0;
+
+       DM_ensure_tessface(psmd->dm_final);
+
+       if (!psmd->dm_final->deformedOnly) {
+               /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set.
+                *     This is awfully weak though. :| */
+               psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
+               DM_ensure_tessface(psmd->dm_deformed);
+       }
 
        /* report change in mesh structure */
-       DM_ensure_tessface(psmd->dm);
-       if (psmd->dm->getNumVerts(psmd->dm) != psmd->totdmvert ||
-           psmd->dm->getNumEdges(psmd->dm) != psmd->totdmedge ||
-           psmd->dm->getNumTessFaces(psmd->dm) != psmd->totdmface)
+       if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
+           psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
+           psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
        {
                psys->recalc |= PSYS_RECALC_RESET;
 
-               psmd->totdmvert = psmd->dm->getNumVerts(psmd->dm);
-               psmd->totdmedge = psmd->dm->getNumEdges(psmd->dm);
-               psmd->totdmface = psmd->dm->getNumTessFaces(psmd->dm);
+               psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
+               psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
+               psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
        }
 
        if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
index 820e129b0ce408a119b889e368271d987da5f570..69e45fea74dbfd22f361a464a55a393c7debcdf9 100644 (file)
@@ -1392,16 +1392,16 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
        re->flag |= R_HALO;
 
-       RE_set_customdata_names(obr, &psmd->dm->faceData);
-       sd.totuv = CustomData_number_of_layers(&psmd->dm->faceData, CD_MTFACE);
-       sd.totcol = CustomData_number_of_layers(&psmd->dm->faceData, CD_MCOL);
+       RE_set_customdata_names(obr, &psmd->dm_final->faceData);
+       sd.totuv = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MTFACE);
+       sd.totcol = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MCOL);
 
        if (ma->texco & TEXCO_UV && sd.totuv) {
                sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
 
                if (ma->strand_uvname[0]) {
-                       sd.override_uv = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, ma->strand_uvname);
-                       sd.override_uv -= CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
+                       sd.override_uv = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, ma->strand_uvname);
+                       sd.override_uv -= CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
                }
        }
        else
@@ -1412,15 +1412,15 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
 /* 2.2 setup billboards */
        if (part->ren_as == PART_DRAW_BB) {
-               int first_uv = CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
+               int first_uv = CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
 
-               bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[0]);
+               bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[0]);
                if (bb.uv[0] < 0)
-                       bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm->faceData, CD_MTFACE);
+                       bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
 
-               bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[1]);
+               bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[1]);
 
-               bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[2]);
+               bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[2]);
 
                if (first_uv >= 0) {
                        bb.uv[0] -= first_uv;
@@ -1500,9 +1500,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                if (ma->amb != 0.0f)
                                        do_surfacecache = true;
 
-                       totface= psmd->dm->getNumTessFaces(psmd->dm);
-                       index_mf_to_mpoly = psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX);
-                       index_mp_to_orig = psmd->dm->getPolyDataArray(psmd->dm, CD_ORIGINDEX);
+                       totface= psmd->dm_final->getNumTessFaces(psmd->dm_final);
+                       index_mf_to_mpoly = psmd->dm_final->getTessFaceDataArray(psmd->dm_final, CD_ORIGINDEX);
+                       index_mp_to_orig = psmd->dm_final->getPolyDataArray(psmd->dm_final, CD_ORIGINDEX);
                        if (index_mf_to_mpoly == NULL) {
                                index_mp_to_orig = NULL;
                        }
@@ -1557,10 +1557,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                        num= pa->num_dmcache;
 
                        if (num == DMCACHE_NOTFOUND)
-                               if (pa->num < psmd->dm->getNumTessFaces(psmd->dm))
+                               if (pa->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
                                        num= pa->num;
 
-                       get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
+                       get_particle_uvco_mcol(part->from, psmd->dm_final, pa->fuv, num, &sd);
 
                        pa_size = pa->size;
 
@@ -1611,17 +1611,17 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
                        /* get uvco & mcol */
                        if (part->childtype==PART_CHILD_FACES) {
-                               get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd);
+                               get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm_final, cpa->fuv, cpa->num, &sd);
                        }
                        else {
                                ParticleData *parent = psys->particles + cpa->parent;
                                num = parent->num_dmcache;
 
                                if (num == DMCACHE_NOTFOUND)
-                                       if (parent->num < psmd->dm->getNumTessFaces(psmd->dm))
+                                       if (parent->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
                                                num = parent->num;
 
-                               get_particle_uvco_mcol(part->from, psmd->dm, parent->fuv, num, &sd);
+                               get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd);
                        }
 
                        do_simplify = psys_render_simplify_params(psys, cpa, simplify);
@@ -1737,14 +1737,14 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                                sub_v3_v3v3(loc0, loc1, loc);
                                                add_v3_v3v3(loc0, loc1, loc0);
 
-                                               particle_curve(re, obr, psmd->dm, ma, &sd, loc1, loc0, seed, pa_co);
+                                               particle_curve(re, obr, psmd->dm_final, ma, &sd, loc1, loc0, seed, pa_co);
                                        }
 
                                        sd.first = 0;
                                        sd.time = time;
 
                                        if (k)
-                                               particle_curve(re, obr, psmd->dm, ma, &sd, loc, loc1, seed, pa_co);
+                                               particle_curve(re, obr, psmd->dm_final, ma, &sd, loc, loc1, seed, pa_co);
 
                                        copy_v3_v3(loc1, loc);
                                }
@@ -1803,7 +1803,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                        pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct;
                                        pa_co[1] = (float)i/(float)(trail_count-1);
 
-                                       particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co);
+                                       particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
                                }
                        }
                        else {
@@ -1839,7 +1839,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                        bb.lifetime = pa_dietime-pa_birthtime;
                                }
 
-                               particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co);
+                               particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
                        }
                }
 
@@ -1851,7 +1851,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        }
 
        if (do_surfacecache)
-               strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset);
+               strandbuf->surface= cache_strand_surface(re, obr, psmd->dm_final, mat, timeoffset);
 
 /* 4. clean up */
 #if 0  /* XXX old animation system */
@@ -4688,7 +4688,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
                                psys->flag |= PSYS_USE_IMAT;
                        init_render_object_data(re, obr, timeoffset);
                        if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
-                               psys_render_restore(ob, psys);
+                               psys_render_restore(re->scene, ob, psys);
                        psys->flag &= ~PSYS_USE_IMAT;
 
                        /* only add instance for objects that have not been used for dupli */
@@ -4888,7 +4888,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
                                if (enable)
                                        psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
                                else
-                                       psys_render_restore(ob, psys);
+                                       psys_render_restore(re->scene, ob, psys);
                        }
                }
 
index 4028d80fd86ef24dd477e817936bf0227f55f119..756801a82e862f8ba2b5c042a5cc277346ad5f7e 100644 (file)
@@ -157,7 +157,7 @@ static void pointdensity_cache_psys(Scene *scene,
        }
 
        if ( !psys_check_enabled(ob, psys)) {
-               psys_render_restore(ob, psys);
+               psys_render_restore(scene, ob, psys);
                return;
        }
 
@@ -253,7 +253,7 @@ static void pointdensity_cache_psys(Scene *scene,
        }
 
        if (use_render_params) {
-               psys_render_restore(ob, psys);
+               psys_render_restore(scene, ob, psys);
        }
 }
 
@@ -711,7 +711,7 @@ static void particle_system_minmax(Scene *scene,
        }
 
        if (use_render_params) {
-               psys_render_restore(object, psys);
+               psys_render_restore(scene, object, psys);
        }
 }
 
index 458d883666e4a89bf925efbcc08c2537de9017c2..5748b9e3225d478e4f9b617f3aab66ec7fb04138 100644 (file)
@@ -498,8 +498,8 @@ void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con)
 void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode) RET_NONE
 void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_NONE
 float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_ZERO
-int ED_mesh_mirror_topo_table(struct Object *ob, char mode) RET_ZERO
-int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode) RET_ZERO
+int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode) RET_ZERO
+int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, const float co[3], char mode) RET_ZERO
 
 float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const bool axis_only) RET_ZERO
 void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height) RET_NONE