diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 00cc48cf713..ed453754648 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -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); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index e26e5148ff6..9fc438319cb 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -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); } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 89f22b8e742..b448bec84e3 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -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; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index b3be5676607..39f0e7cbb84 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -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; diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 9523ece5f73..9f60cbb88e3 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -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; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 130b56987e2..bf506c8545b 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -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; ilink = 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 */ diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 01c00ddb48e..c51446d6cc8 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -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]); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index e625ac18685..17e2da3f1cb 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -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]); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a3bf673d5fa..86a7b10a378 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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; diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index c621d6f99c0..28fddbab796 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -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); diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 549b60c2ece..4bda8285029 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -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 */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index c509aeb4ac2..f072e707d00 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -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); diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index e5b4e661773..01be8f848aa 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -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; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 9cf80c8f4cf..feb0ef73f15 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -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); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index dee003135a2..431af56e13d 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -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"); - ED_mesh_mirror_spatial_table(ob, em, NULL, 's'); + mvert = dm ? dm->getVertArray(dm) : me->mvert; + mface = dm ? dm->getTessFaceArray(dm) : me->mface; - for (a = 0, mv = mvert; a < me->totvert; a++, mv++) - mirrorverts[a] = mesh_get_x_mirror_vert(ob, a, use_topology); + ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's'); - ED_mesh_mirror_spatial_table(ob, em, NULL, 'e'); + 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, 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]; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 64a69542e38..67c9f6e98da 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -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) { diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index ed71af71ac9..39bd34456be 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -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; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 2271baf46a5..c0b0303404e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -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) { diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 64ad3a100cc..deba3bbca32 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -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; pparticles + 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; iscene; 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; - else { - dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE); - release_dm = true; + if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) { + dm = psmd->dm_final; } - - index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + else { + dm = psmd->dm_deformed; + } + BLI_assert(dm); for (i=0; i1) { @@ -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; idm, 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; ktotaddkey; 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) diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 6d143fb13f3..ecd27646562 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -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; ktotkey; 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); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 5fa0c9fc71e..34870a112bc 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -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); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index dc0b153d6e9..c18501d0e36 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -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)) { diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 0463980dacd..1c3ab03c43a 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -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, diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 7bd29137aeb..d00e5d574fa 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -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; diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 95cb5c84bed..b284a683f8e 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 5645f018cad..ae8b3799bac 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -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); } } diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 8d4be2af533..94b33916cf4 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -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; diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index d57ace8d7fe..1ac18858f56 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -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 || diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 289611ad90a..4e78e758dc3 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -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); diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index de1b11eddd9..6b2b999d596 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -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)) { diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 820e129b0ce..69e45fea74d 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -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); } } diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 4028d80fd86..756801a82e8 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -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); } } diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 458d883666e..5748b9e3225 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -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