Fix T47038: Particles in Particle Edit Mode get added in completely wrong location.

It also fixes another issue (crash) related to symmetric editing.

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

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

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

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

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

Reviewers: psy-fi

Subscribers: dfelinto, eyecandy

Maniphest Tasks: T47038

Differential Revision: https://developer.blender.org/D1685
This commit is contained in:
Bastien Montagne 2016-01-04 12:19:45 +01:00
parent e83b3e577e
commit aad24468e2
Notes: blender-bot 2023-02-14 11:20:29 +01:00
Referenced by issue #47038, Particles in Particle Edit Mode get added in completely wrong location
33 changed files with 502 additions and 362 deletions

View File

@ -302,7 +302,7 @@ void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
void psys_free(struct Object *ob, struct ParticleSystem *psys);
void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
void psys_render_restore(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
@ -413,15 +413,15 @@ void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], floa
/* BLI_bvhtree_ray_cast callback */
void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit);
void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache,
void psys_particle_on_dm(struct DerivedMesh *dm_final, int from, int index, int index_dmcache,
const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
float orco[3], float ornor[3]);
/* particle_system.c */
void distribute_particles(struct ParticleSimulationData *sim, int from);
void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);
int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node);
void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, struct ParticleSystem *psys);
int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes);
void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra);

View File

@ -43,6 +43,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_array.h"
#include "BLI_blenlib.h"
#include "BLI_bitmap.h"
#include "BLI_math.h"
@ -3668,26 +3669,73 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
void DM_init_origspace(DerivedMesh *dm)
{
static float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
OrigSpaceLoop *lof_array = CustomData_get_layer(&dm->loopData, CD_ORIGSPACE_MLOOP);
OrigSpaceLoop *lof;
const int numpoly = dm->getNumPolys(dm);
// const int numloop = dm->getNumLoops(dm);
MVert *mv = dm->getVertArray(dm);
MLoop *ml = dm->getLoopArray(dm);
MPoly *mp = dm->getPolyArray(dm);
int i, j;
int i, j, k;
float (*vcos_2d)[2] = NULL;
BLI_array_staticdeclare(vcos_2d, 64);
for (i = 0; i < numpoly; i++, mp++) {
/* only quads/tri's for now */
OrigSpaceLoop *lof = lof_array + mp->loopstart;
if (mp->totloop == 3 || mp->totloop == 4) {
lof = lof_array + mp->loopstart;
for (j = 0; j < mp->totloop; j++, lof++) {
copy_v2_v2(lof->uv, default_osf[j]);
}
}
else {
MLoop *l = &ml[mp->loopstart];
float p_nor[3], co[3];
float mat[3][3];
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {FLT_MIN, FLT_MIN};
float translate[2], scale[2];
BKE_mesh_calc_poly_normal(mp, l, mv, p_nor);
axis_dominant_v3_to_m3(mat, p_nor);
BLI_array_empty(vcos_2d);
BLI_array_reserve(vcos_2d, mp->totloop);
for (j = 0; j < mp->totloop; j++, l++) {
mul_v3_m3v3(co, mat, mv[l->v].co);
copy_v2_v2(vcos_2d[j], co);
for (k = 0; k < 2; k++) {
if (co[k] > max[k])
max[k] = co[k];
else if (co[k] < min[k])
min[k] = co[k];
}
}
/* Brings min to (0, 0). */
negate_v2_v2(translate, min);
/* Scale will bring max to (1, 1). */
sub_v2_v2v2(scale, max, min);
if (scale[0] == 0.0f)
scale[0] = 1e-9f;
if (scale[1] == 0.0f)
scale[1] = 1e-9f;
invert_v2(scale);
/* Finally, transform all vcos_2d into ((0, 0), (1, 1)) square and assing them as origspace. */
for (j = 0; j < mp->totloop; j++, lof++) {
add_v2_v2v2(lof->uv, vcos_2d[j], translate);
mul_v2_v2(lof->uv, scale);
}
}
}
dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
BLI_array_free(vcos_2d);
}

View File

@ -364,10 +364,15 @@ void BKE_object_free_caches(Object *object)
for (md = object->modifiers.first; md != NULL; md = md->next) {
if (md->type == eModifierType_ParticleSystem) {
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
if (psmd->dm != NULL) {
psmd->dm->needsFree = 1;
psmd->dm->release(psmd->dm);
psmd->dm = NULL;
if (psmd->dm_final != NULL) {
psmd->dm_final->needsFree = 1;
psmd->dm_final->release(psmd->dm_final);
psmd->dm_final = NULL;
if (psmd->dm_deformed != NULL) {
psmd->dm_deformed->needsFree = 1;
psmd->dm_deformed->release(psmd->dm_deformed);
psmd->dm_deformed = NULL;
}
psmd->flag |= eParticleSystemFlag_file_loaded;
update_flag |= OB_RECALC_DATA;
}

View File

@ -623,8 +623,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
data->childcachebufs.last = psys->childcachebufs.last;
data->totchildcache = psys->totchildcache;
if (psmd->dm)
data->dm = CDDM_copy(psmd->dm);
if (psmd->dm_final)
data->dm = CDDM_copy(psmd->dm_final);
data->totdmvert = psmd->totdmvert;
data->totdmedge = psmd->totdmedge;
data->totdmface = psmd->totdmface;
@ -651,7 +651,7 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
psys->recalc |= PSYS_RECALC_RESET;
}
void psys_render_restore(Object *ob, ParticleSystem *psys)
void psys_render_restore(Scene *scene, Object *ob, ParticleSystem *psys)
{
ParticleRenderData *data;
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
@ -665,9 +665,14 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
if (data->elems)
MEM_freeN(data->elems);
if (psmd->dm) {
psmd->dm->needsFree = 1;
psmd->dm->release(psmd->dm);
if (psmd->dm_final) {
psmd->dm_final->needsFree = 1;
psmd->dm_final->release(psmd->dm_final);
}
if (psmd->dm_deformed) {
psmd->dm_deformed->needsFree = 1;
psmd->dm_deformed->release(psmd->dm_deformed);
psmd->dm_deformed = NULL;
}
psys_free_path_cache(psys, NULL);
@ -689,14 +694,19 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
psys->childcachebufs.last = data->childcachebufs.last;
psys->totchildcache = data->totchildcache;
psmd->dm = data->dm;
psmd->dm_final = data->dm;
psmd->totdmvert = data->totdmvert;
psmd->totdmedge = data->totdmedge;
psmd->totdmface = data->totdmface;
psmd->flag &= ~eParticleSystemFlag_psys_updated;
if (psmd->dm)
psys_calc_dmcache(ob, psmd->dm, psys);
if (psmd->dm_final) {
if (!psmd->dm_final->deformedOnly) {
psmd->dm_deformed = CDDM_copy(mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE));
DM_ensure_tessface(psmd->dm_deformed);
}
psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys);
}
MEM_freeN(data);
psys->renderdata = NULL;
@ -1383,78 +1393,114 @@ static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4
}
}
/* find the derived mesh face for a particle, set the mf passed. this is slow
* and can be optimized but only for many lookups. returns the face index. */
int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node)
/**
* Find the final derived mesh tessface for a particle, from its original tessface index.
* This is slow and can be optimized but only for many lookups.
*
* \param dm_final final DM, it may not have the same topology as original mesh.
* \param dm_deformed deformed-only DM, it has the exact same topology as original mesh.
* \param findex_orig the input tessface index.
* \param fw face weights (position of the particle inside the \a findex_orig tessface).
* \param poly_nodes may be NULL, otherwise an array of linked list, one for each final DM polygon, containing all
* its tessfaces indices.
* \return the DM tessface index.
*/
int psys_particle_dm_face_lookup(
DerivedMesh *dm_final, DerivedMesh *dm_deformed,
int findex_orig, const float fw[4], struct LinkNode **poly_nodes)
{
Mesh *me = (Mesh *)ob->data;
MPoly *mpoly;
OrigSpaceFace *osface;
int quad, findex, totface;
MFace *mtessface_final;
OrigSpaceFace *osface_final;
int totface_final;
int pindex_orig;
float uv[2], (*faceuv)[2];
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
if (index_mf_to_mpoly == NULL) {
index_mp_to_orig = NULL;
const int *index_mf_to_mpoly_deformed = NULL;
const int *index_mf_to_mpoly = NULL;
const int *index_mp_to_orig = NULL;
index_mf_to_mpoly = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
index_mp_to_orig = dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
BLI_assert(index_mf_to_mpoly);
if (dm_deformed) {
index_mf_to_mpoly_deformed = dm_deformed->getTessFaceDataArray(dm_deformed, CD_ORIGINDEX);
}
else {
BLI_assert(dm_final->deformedOnly);
index_mf_to_mpoly_deformed = index_mf_to_mpoly;
}
BLI_assert(index_mf_to_mpoly_deformed);
pindex_orig = index_mf_to_mpoly_deformed[findex_orig];
if (dm_deformed == NULL) {
dm_deformed = dm_final;
}
totface = dm->getNumTessFaces(dm);
if (!totface) {
index_mf_to_mpoly_deformed = NULL;
totface_final = dm_final->getNumTessFaces(dm_final);
if (!totface_final) {
return DMCACHE_NOTFOUND;
}
mpoly = dm->getPolyArray(dm);
osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
mtessface_final = dm_final->getTessFaceArray(dm_final);
osface_final = dm_final->getTessFaceDataArray(dm_final, CD_ORIGSPACE);
if (osface == NULL || index_mf_to_mpoly == NULL) {
/* Assume we don't need osface data */
if (index < totface) {
if (osface_final == NULL) {
/* Assume we don't need osface_final data, and we get a direct 1-1 mapping... */
if (findex_orig < totface_final) {
//printf("\tNO CD_ORIGSPACE, assuming not needed\n");
return index;
return findex_orig;
}
else {
printf("\tNO CD_ORIGSPACE, error out of range\n");
return DMCACHE_NOTFOUND;
}
}
else if (index >= me->totpoly)
else if (findex_orig >= dm_deformed->getNumTessFaces(dm_deformed)) {
return DMCACHE_NOTFOUND; /* index not in the original mesh */
}
psys_w_to_origspace(fw, uv);
if (node) { /* we have a linked list of faces that we use, faster! */
for (; node; node = node->next) {
findex = GET_INT_FROM_POINTER(node->link);
faceuv = osface[findex].uv;
quad = (mpoly[findex].totloop == 4);
if (poly_nodes) {
/* we can have a restricted linked list of faces to check, faster! */
LinkNode *tessface_node = poly_nodes[pindex_orig];
for (; tessface_node; tessface_node = tessface_node->next) {
int findex_dst = GET_INT_FROM_POINTER(tessface_node->link);
faceuv = osface_final[findex_dst].uv;
/* check that this intersects - Its possible this misses :/ -
* could also check its not between */
if (quad) {
if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3]))
return findex;
if (mtessface_final[findex_dst].v4) {
if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
return findex_dst;
}
}
else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
return findex_dst;
}
else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2]))
return findex;
}
}
else { /* if we have no node, try every face */
for (findex = 0; findex < totface; findex++) {
const int findex_orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex);
if (findex_orig == index) {
faceuv = osface[findex].uv;
quad = (mpoly[findex].totloop == 4);
for (int findex_dst = 0; findex_dst < totface_final; findex_dst++) {
/* If current tessface from 'final' DM and orig tessface (given by index) map to the same orig poly... */
if (DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex_dst) == pindex_orig) {
faceuv = osface_final[findex_dst].uv;
/* check that this intersects - Its possible this misses :/ -
* could also check its not between */
if (quad) {
if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3]))
return findex;
if (mtessface_final[findex_dst].v4) {
if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
return findex_dst;
}
}
else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
return findex_dst;
}
else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2]))
return findex;
}
}
}
@ -1523,7 +1569,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
}
/* interprets particle data to get a point on a mesh in object space */
void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache,
void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_dmcache,
const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
float orco[3], float ornor[3])
{
@ -1531,7 +1577,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
float (*orcodata)[3];
int mapindex;
if (!psys_map_index_on_dm(dm, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
if (!psys_map_index_on_dm(dm_final, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
if (vec) { vec[0] = vec[1] = vec[2] = 0.0; }
if (nor) { nor[0] = nor[1] = 0.0; nor[2] = 1.0; }
if (orco) { orco[0] = orco[1] = orco[2] = 0.0; }
@ -1542,13 +1588,13 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
return;
}
orcodata = dm->getVertDataArray(dm, CD_ORCO);
orcodata = dm_final->getVertDataArray(dm_final, CD_ORCO);
if (from == PART_FROM_VERT) {
dm->getVertCo(dm, mapindex, vec);
dm_final->getVertCo(dm_final, mapindex, vec);
if (nor) {
dm->getVertNo(dm, mapindex, nor);
dm_final->getVertNo(dm_final, mapindex, nor);
normalize_v3(nor);
}
@ -1556,7 +1602,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
copy_v3_v3(orco, orcodata[mapindex]);
if (ornor) {
dm->getVertNo(dm, mapindex, ornor);
dm_final->getVertNo(dm_final, mapindex, ornor);
normalize_v3(ornor);
}
@ -1570,9 +1616,9 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
MTFace *mtface;
MVert *mvert;
mface = dm->getTessFaceData(dm, mapindex, CD_MFACE);
mvert = dm->getVertDataArray(dm, CD_MVERT);
mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
mface = dm_final->getTessFaceData(dm_final, mapindex, CD_MFACE);
mvert = dm_final->getVertDataArray(dm_final, CD_MVERT);
mtface = CustomData_get_layer(&dm_final->faceData, CD_MTFACE);
if (mtface)
mtface += mapindex;
@ -1689,7 +1735,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
float orco[3], float ornor[3])
{
if (psmd && psmd->dm) {
if (psmd && psmd->dm_final) {
if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) {
if (vec)
copy_v3_v3(vec, fuv);
@ -1699,7 +1745,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
return;
}
/* we cant use the num_dmcache */
psys_particle_on_dm(psmd->dm, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco, ornor);
psys_particle_on_dm(psmd->dm_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco, ornor);
}
else
psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco, ornor);
@ -1971,7 +2017,7 @@ void psys_find_parents(ParticleSimulationData *sim)
psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0);
/* Check if particle doesn't exist because of texture influence. Insert only existing particles into kdtree. */
get_cpa_texture(sim->psmd->dm, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
get_cpa_texture(sim->psmd->dm_final, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
if (ptex.exist >= psys_frand(psys, p + 24)) {
BLI_kdtree_insert(tree, p, orco);
@ -2183,7 +2229,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
for (w = 0; w < 4; w++)
sub_v3_v3v3(off1[w], co, key[w]->co);
psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
}
else {
ParticleData *pa = psys->particles + cpa->parent;
@ -2202,13 +2248,13 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
cpa_from = part->from;
cpa_num = pa->num;
/* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
if (cpa_num > ctx->sim.psmd->dm->getNumTessFaces(ctx->sim.psmd->dm))
if (cpa_num > ctx->sim.psmd->dm_final->getNumTessFaces(ctx->sim.psmd->dm_final))
cpa_num = 0;
cpa_fuv = pa->fuv;
psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, ornor, 0, 0, orco, 0);
psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
}
child_keys->segments = ctx->segments;
@ -2501,15 +2547,15 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
if ((psys->flag & PSYS_GLOBAL_HAIR) == 0) {
if ((psys->part->flag & PART_CHILD_EFFECT) == 0)
vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR);
vg_effector = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_EFFECTOR);
if (!psys->totchild)
vg_length = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_LENGTH);
vg_length = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_LENGTH);
}
/* ensure we have tessfaces to be used for mapping */
if (part->from != PART_FROM_VERT) {
DM_ensure_tessface(psmd->dm);
DM_ensure_tessface(psmd->dm_final);
}
/*---first main loop: create all actual particles' paths---*/
@ -2518,7 +2564,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
if (vg_length)
pa_length *= psys_particle_value_from_verts(psmd->dm, part->from, pa, vg_length);
pa_length *= psys_particle_value_from_verts(psmd->dm_final, part->from, pa, vg_length);
}
pind.keyed = keyed;
@ -2535,7 +2581,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
/* hairmat is needed for for non-hair particle too so we get proper rotations */
psys_mat_hair_to_global(sim->ob, psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(sim->ob, psmd->dm_final, psys->part->from, pa, hairmat);
copy_v3_v3(rotmat[0], hairmat[2]);
copy_v3_v3(rotmat[1], hairmat[1]);
copy_v3_v3(rotmat[2], hairmat[0]);
@ -2590,7 +2636,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
float effector = 1.0f;
if (vg_effector)
effector *= psys_particle_value_from_verts(psmd->dm, psys->part->from, pa, vg_effector);
effector *= psys_particle_value_from_verts(psmd->dm_final, psys->part->from, pa, vg_effector);
sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
length = len_v3(vec);
@ -2735,7 +2781,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
init_particle_interpolation(ob, psys, pa, &pind);
if (psys) {
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
copy_v3_v3(rotmat[0], hairmat[2]);
copy_v3_v3(rotmat[1], hairmat[1]);
copy_v3_v3(rotmat[2], hairmat[0]);
@ -3491,7 +3537,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
mul_m4_v3(mtex->object->imat, texvec);
break;
case TEXCO_UV:
if (get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texvec))
if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec))
break;
/* no break, failed to get uv's, so let's try orco's */
case TEXCO_ORCO:
@ -3691,7 +3737,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
}
else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
if ((pa->flag & PARS_REKEY) == 0) {
psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat);
psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, part->from, pa, hairmat);
mul_m4_v3(hairmat, state->co);
mul_mat3_m4_v3(hairmat, state->vel);
@ -3758,7 +3804,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
if (part->type == PART_HAIR)
psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
else
unit_m4(hairmat);
@ -3779,7 +3825,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
if (part->type == PART_HAIR) {
psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco, 0);
psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
}
else {
copy_v3_v3(orco, cpa->fuv);
@ -3798,7 +3844,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
/* get different child parameters from textures & vgroups */
memset(&ctx, 0, sizeof(ParticleThreadContext));
ctx.sim = *sim;
ctx.dm = psmd->dm;
ctx.dm = psmd->dm_final;
ctx.ma = ma;
/* TODO: assign vertex groups */
get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
@ -4026,10 +4072,10 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part,
uv[0] = uv[1] = 0.f;
if (cpa) {
if ((part->childtype == PART_CHILD_FACES) && (psmd->dm != NULL)) {
mtface = CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
if ((part->childtype == PART_CHILD_FACES) && (psmd->dm_final != NULL)) {
mtface = CustomData_get_layer(&psmd->dm_final->faceData, CD_MTFACE);
if (mtface) {
mface = psmd->dm->getTessFaceData(psmd->dm, cpa->num, CD_MFACE);
mface = psmd->dm_final->getTessFaceData(psmd->dm_final, cpa->num, CD_MFACE);
mtface += cpa->num;
psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
}
@ -4042,21 +4088,21 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part,
}
}
if ((part->from == PART_FROM_FACE) && (psmd->dm != NULL)) {
mtface = CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
if ((part->from == PART_FROM_FACE) && (psmd->dm_final != NULL)) {
mtface = CustomData_get_layer(&psmd->dm_final->faceData, CD_MTFACE);
num = pa->num_dmcache;
if (num == DMCACHE_NOTFOUND)
num = pa->num;
if (num >= psmd->dm->getNumTessFaces(psmd->dm)) {
if (num >= psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
/* happens when simplify is enabled
* gives invalid coords but would crash otherwise */
num = DMCACHE_NOTFOUND;
}
if (mtface && !ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
mface = psmd->dm->getTessFaceData(psmd->dm, num, CD_MFACE);
mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
mtface += num;
psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
}
@ -4231,7 +4277,7 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
float hairmat[4][4], imat[4][4];
for (p = 0; p < psys->totpart; p++, pa++) {
psys_mat_hair_to_global(sim.ob, sim.psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, psys->part->from, pa, hairmat);
invert_m4_m4(imat, hairmat);
hkey = pa->hair;

View File

@ -79,7 +79,7 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
}
}
static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys)
{
ChildParticle *cpa = NULL;
int i, p;
@ -106,7 +106,7 @@ static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *fi
}
}
/* dmcache must be updated for parent particles if children from faces is used */
psys_calc_dmcache(ob, finaldm, psys);
psys_calc_dmcache(ob, finaldm, deformdm, psys);
}
static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
{
@ -763,7 +763,7 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
{
Scene *scene = sim->scene;
DerivedMesh *finaldm = sim->psmd->dm;
DerivedMesh *finaldm = sim->psmd->dm_final;
Object *ob = sim->ob;
ParticleSystem *psys= sim->psys;
ParticleData *pa=0, *tpars= 0;
@ -800,7 +800,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* Simple children */
if (part->childtype != PART_CHILD_FACES) {
BLI_srandom(31415926 + psys->seed + psys->child_seed);
distribute_simple_children(scene, ob, finaldm, psys);
distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys);
return 0;
}
}
@ -1110,7 +1110,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
TaskPool *task_pool;
ParticleThreadContext ctx;
ParticleTask *tasks;
DerivedMesh *finaldm = sim->psmd->dm;
DerivedMesh *finaldm = sim->psmd->dm_final;
int i, totpart, numtasks;
/* create a task pool for distribution tasks */
@ -1135,7 +1135,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
BLI_task_pool_free(task_pool);
psys_calc_dmcache(sim->ob, finaldm, sim->psys);
psys_calc_dmcache(sim->ob, finaldm, sim->psmd->dm_deformed, sim->psys);
if (ctx.dm != finaldm)
ctx.dm->release(ctx.dm);
@ -1159,7 +1159,7 @@ void distribute_particles(ParticleSimulationData *sim, int from)
int distr_error=0;
if (psmd) {
if (psmd->dm)
if (psmd->dm_final)
distribute_particles_on_dm(sim, from);
else
distr_error=1;

View File

@ -311,7 +311,7 @@ int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
/* Distribution */
/************************************************/
void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
void psys_calc_dmcache(Object *ob, DerivedMesh *dm_final, DerivedMesh *dm_deformed, ParticleSystem *psys)
{
/* use for building derived mesh mapping info:
*
@ -324,13 +324,13 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
PARTICLE_P;
/* CACHE LOCATIONS */
if (!dm->deformedOnly) {
if (!dm_final->deformedOnly) {
/* Will use later to speed up subsurf/derivedmesh */
LinkNode *node, *nodedmelem, **nodearray;
int totdmelem, totelem, i, *origindex, *origindex_poly = NULL;
if (psys->part->from == PART_FROM_VERT) {
totdmelem= dm->getNumVerts(dm);
totdmelem= dm_final->getNumVerts(dm_final);
if (use_modifier_stack) {
totelem= totdmelem;
@ -338,11 +338,11 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
}
else {
totelem= me->totvert;
origindex= dm->getVertDataArray(dm, CD_ORIGINDEX);
origindex= dm_final->getVertDataArray(dm_final, CD_ORIGINDEX);
}
}
else { /* FROM_FACE/FROM_VOLUME */
totdmelem= dm->getNumTessFaces(dm);
totdmelem= dm_final->getNumTessFaces(dm_final);
if (use_modifier_stack) {
totelem= totdmelem;
@ -350,20 +350,20 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
origindex_poly= NULL;
}
else {
totelem= me->totpoly;
origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
totelem = dm_deformed->getNumTessFaces(dm_deformed);
origindex = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
/* for face lookups we need the poly origindex too */
origindex_poly= dm->getPolyDataArray(dm, CD_ORIGINDEX);
origindex_poly= dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
if (origindex_poly == NULL) {
origindex= NULL;
}
}
}
nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems");
nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array");
for (i=0, node=nodedmelem; i<totdmelem; i++, node++) {
int origindex_final;
node->link = SET_INT_IN_POINTER(i);
@ -392,7 +392,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
}
}
}
/* cache the verts/faces! */
LOOP_PARTICLES {
if (pa->num < 0) {
@ -414,9 +414,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
pa->num_dmcache = DMCACHE_NOTFOUND;
}
else { /* FROM_FACE/FROM_VOLUME */
/* Note that sometimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this,
* but for now passing NULL is OK. every face will be searched for the particle so its slower - Campbell */
pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL);
pa->num_dmcache = psys_particle_dm_face_lookup(dm_final, dm_deformed, pa->num, pa->fuv, nodearray);
}
}
}
@ -429,8 +427,9 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
* should know to use the num or num_dmcache, set the num_dmcache to
* an invalid value, just in case */
LOOP_PARTICLES
LOOP_PARTICLES {
pa->num_dmcache = DMCACHE_NOTFOUND;
}
}
}
@ -439,7 +438,7 @@ void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData
{
memset(ctx, 0, sizeof(ParticleThreadContext));
ctx->sim = *sim;
ctx->dm = ctx->sim.psmd->dm;
ctx->dm = ctx->sim.psmd->dm_final;
ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
}
@ -3054,7 +3053,7 @@ static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int
pa->hair_index = hair_index;
use_hair = psys_hair_use_simulation(pa, max_length);
psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_object(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
normalize_m4(root_mat);
@ -3209,7 +3208,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra)
if (psys->recalc & PSYS_RECALC_RESET) {
/* need this for changing subsurf levels */
psys_calc_dmcache(sim->ob, sim->psmd->dm, psys);
psys_calc_dmcache(sim->ob, sim->psmd->dm_final, sim->psmd->dm_deformed, psys);
if (psys->clmd)
cloth_free_modifier(psys->clmd);
@ -3256,7 +3255,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
if (pa->totkey) {
sub_v3_v3(key->co, root->co);
psys_vec_rot_to_face(sim->psmd->dm, pa, key->co);
psys_vec_rot_to_face(sim->psmd->dm_final, pa, key->co);
}
key->time = pa->state.time;
@ -4064,11 +4063,11 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
return;
}
if (!sim.psmd->dm)
if (!sim.psmd->dm_final)
return;
if (part->from != PART_FROM_VERT) {
DM_ensure_tessface(sim.psmd->dm);
DM_ensure_tessface(sim.psmd->dm_final);
}
/* execute drivers only, as animation has already been done */

View File

@ -149,6 +149,8 @@ MINLINE void negate_v4_v4(float r[4], const float a[3]);
MINLINE void negate_v3_short(short r[3]);
MINLINE void invert_v2(float r[2]);
MINLINE void abs_v2(float r[2]);
MINLINE void abs_v2_v2(float r[2], const float a[2]);
MINLINE void abs_v3(float r[3]);

View File

@ -633,6 +633,13 @@ MINLINE void negate_v3_short(short r[3])
r[2] = (short)-r[2];
}
MINLINE void invert_v2(float r[2])
{
BLI_assert(!ELEM(0.0f, r[0], r[1]));
r[0] = 1.0f / r[0];
r[1] = 1.0f / r[1];
}
MINLINE void abs_v2(float r[2])
{
r[0] = fabsf(r[0]);

View File

@ -5136,7 +5136,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
else if (md->type == eModifierType_ParticleSystem) {
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
psmd->dm= NULL;
psmd->dm_final = NULL;
psmd->dm_deformed = NULL;
psmd->psys= newdataadr(fd, psmd->psys);
psmd->flag &= ~eParticleSystemFlag_psys_updated;
psmd->flag |= eParticleSystemFlag_file_loaded;

View File

@ -214,7 +214,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
continue;
}
iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i, use_topology) : -1;
iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, NULL, i, use_topology) : -1;
/* for each skinnable bone */
for (j = 0; j < numbones; ++j) {
@ -411,7 +411,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
}
/* only generated in some cases but can call anyway */
ED_mesh_mirror_spatial_table(ob, NULL, NULL, 'e');
ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
/* free the memory allocated */
MEM_freeN(bonelist);

View File

@ -675,7 +675,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
if (dgroupflip) {
vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
for (a = 0; a < me->totvert; a++)
vertsflipped[a] = mesh_get_x_mirror_vert(ob, a, use_topology);
vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology);
}
/* compute weights per bone */

View File

@ -218,8 +218,8 @@ typedef struct MirrTopoStore_t {
int prev_ob_mode;
} MirrTopoStore_t;
bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
void ED_mesh_mirrtopo_init(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
const bool skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
@ -308,17 +308,18 @@ int join_mesh_exec(struct bContext *C, struct wmOperator *op);
int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
/* mirror lookup api */
int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode);
int ED_mesh_mirror_topo_table(struct Object *ob, char mode);
int ED_mesh_mirror_spatial_table(
struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, const float co[3], char mode);
int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode);
/* retrieves mirrored cache vert, or NULL if there isn't one.
* note: calling this without ensuring the mirror cache state
* is bad.*/
int mesh_get_x_mirror_vert(struct Object *ob, int index, const bool use_topology);
int mesh_get_x_mirror_vert(struct Object *ob, struct DerivedMesh *dm, int index, const bool use_topology);
struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em,
struct BMVert *eve, const float co[3],
int index, const bool use_topology);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm);
int ED_mesh_mirror_get_vert(struct Object *ob, int index);

View File

@ -632,12 +632,16 @@ static int mirrtopo_vert_sort(const void *v1, const void *v2)
return 0;
}
bool ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
{
int totvert;
int totedge;
if (me->edit_btmesh) {
if (dm) {
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
}
else if (me->edit_btmesh) {
totvert = me->edit_btmesh->bm->totvert;
totedge = me->edit_btmesh->bm->totedge;
}
@ -659,11 +663,11 @@ bool ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t
}
void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
void ED_mesh_mirrtopo_init(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
const bool skip_em_vert_array_init)
{
MEdge *medge;
BMEditMesh *em = me->edit_btmesh;
MEdge *medge = NULL, *med;
BMEditMesh *em = dm ? NULL : me->edit_btmesh;
/* editmode*/
BMEdge *eed;
@ -692,7 +696,7 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
totvert = em->bm->totvert;
}
else {
totvert = me->totvert;
totvert = dm ? dm->getNumVerts(dm) : me->totvert;
}
topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
@ -708,10 +712,11 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
}
}
else {
totedge = me->totedge;
totedge = dm ? dm->getNumEdges(dm) : me->totedge;
medge = dm ? dm->getEdgeArray(dm) : me->medge;
for (a = 0, medge = me->medge; a < me->totedge; a++, medge++) {
const unsigned int i1 = medge->v1, i2 = medge->v2;
for (a = 0, med = medge; a < totedge; a++, med++) {
const unsigned int i1 = med->v1, i2 = med->v2;
topo_hash[i1]++;
topo_hash[i2]++;
}
@ -736,8 +741,8 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
}
}
else {
for (a = 0, medge = me->medge; a < me->totedge; a++, medge++) {
const unsigned int i1 = medge->v1, i2 = medge->v2;
for (a = 0, med = medge; a < totedge; a++, med++) {
const unsigned int i1 = med->v1, i2 = med->v2;
topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
@ -782,7 +787,6 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
}
}
for (a = 0; a < totvert; a++) {
topo_pairs[a].hash = topo_hash[a];
topo_pairs[a].v_index = a;

View File

@ -415,8 +415,8 @@ void EDBM_mesh_free(BMEditMesh *em)
/* These tables aren't used yet, so it's not strictly necessary
* to 'end' them (with 'e' param) but if someone tries to start
* using them, having these in place will save a lot of pain */
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, 'e');
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, NULL, 'e');
BKE_editmesh_free(em);
}
@ -1140,7 +1140,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
BM_mesh_elem_index_ensure(bm, BM_VERT);
if (use_topology) {
ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true);
ED_mesh_mirrtopo_init(me, NULL, -1, &mesh_topo_store, true);
}
else {
tree = BLI_kdtree_new(bm->totvert);

View File

@ -672,18 +672,15 @@ static struct { void *tree; } MirrKdStore = {NULL};
/* mode is 's' start, or 'e' end, or 'u' use */
/* if end, ob can be NULL */
int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, const float co[3], char mode)
int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, const float co[3], char mode)
{
if (mode == 'u') { /* use table */
if (MirrKdStore.tree == NULL)
ED_mesh_mirror_spatial_table(ob, em, NULL, 's');
ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's');
if (MirrKdStore.tree) {
KDTreeNearest nearest;
int i;
i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
if (i != -1) {
if (nearest.dist < KD_THRESH) {
@ -695,22 +692,15 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, const float co[3],
}
else if (mode == 's') { /* start table */
Mesh *me = ob->data;
int totvert;
const bool use_em = (!dm && em && me->edit_btmesh == em);
const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert;
if (MirrKdStore.tree) /* happens when entering this call without ending it */
ED_mesh_mirror_spatial_table(ob, em, co, 'e');
if (em && me->edit_btmesh == em) {
totvert = em->bm->totvert;
}
else {
totvert = me->totvert;
}
ED_mesh_mirror_spatial_table(ob, em, dm, co, 'e');
MirrKdStore.tree = BLI_kdtree_new(totvert);
if (em && me->edit_btmesh == em) {
if (use_em) {
BMVert *eve;
BMIter iter;
int i;
@ -723,10 +713,10 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, const float co[3],
}
}
else {
MVert *mvert;
MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
int i;
for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
for (i = 0; i < totvert; i++, mvert++) {
BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
}
}
@ -760,15 +750,15 @@ static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
/* mode is 's' start, or 'e' end, or 'u' use */
/* if end, ob can be NULL */
/* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */
int ED_mesh_mirror_topo_table(Object *ob, char mode)
int ED_mesh_mirror_topo_table(Object *ob, DerivedMesh *dm, char mode)
{
if (mode == 'u') { /* use table */
if (ED_mesh_mirrtopo_recalc_check(ob->data, ob->mode, &mesh_topo_store)) {
ED_mesh_mirror_topo_table(ob, 's');
if (ED_mesh_mirrtopo_recalc_check(ob->data, dm, ob->mode, &mesh_topo_store)) {
ED_mesh_mirror_topo_table(ob, dm, 's');
}
}
else if (mode == 's') { /* start table */
ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store, false);
ED_mesh_mirrtopo_init(ob->data, dm, ob->mode, &mesh_topo_store, false);
}
else if (mode == 'e') { /* end table */
ED_mesh_mirrtopo_free(&mesh_topo_store);
@ -783,35 +773,35 @@ int ED_mesh_mirror_topo_table(Object *ob, char mode)
/** \} */
static int mesh_get_x_mirror_vert_spatial(Object *ob, int index)
static int mesh_get_x_mirror_vert_spatial(Object *ob, DerivedMesh *dm, int index)
{
Mesh *me = ob->data;
MVert *mvert;
MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
float vec[3];
mvert = me->mvert + index;
mvert = &mvert[index];
vec[0] = -mvert->co[0];
vec[1] = mvert->co[1];
vec[2] = mvert->co[2];
return ED_mesh_mirror_spatial_table(ob, NULL, vec, 'u');
return ED_mesh_mirror_spatial_table(ob, NULL, dm, vec, 'u');
}
static int mesh_get_x_mirror_vert_topo(Object *ob, int index)
static int mesh_get_x_mirror_vert_topo(Object *ob, DerivedMesh *dm, int index)
{
if (ED_mesh_mirror_topo_table(ob, 'u') == -1)
if (ED_mesh_mirror_topo_table(ob, dm, 'u') == -1)
return -1;
return mesh_topo_store.index_lookup[index];
}
int mesh_get_x_mirror_vert(Object *ob, int index, const bool use_topology)
int mesh_get_x_mirror_vert(Object *ob, DerivedMesh *dm, int index, const bool use_topology)
{
if (use_topology) {
return mesh_get_x_mirror_vert_topo(ob, index);
return mesh_get_x_mirror_vert_topo(ob, dm, index);
}
else {
return mesh_get_x_mirror_vert_spatial(ob, index);
return mesh_get_x_mirror_vert_spatial(ob, dm, index);
}
}
@ -832,7 +822,7 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
vec[1] = co[1];
vec[2] = co[2];
i = ED_mesh_mirror_spatial_table(ob, em, vec, 'u');
i = ED_mesh_mirror_spatial_table(ob, em, NULL, vec, 'u');
if (i != -1) {
return BM_vert_at_index(em->bm, i);
}
@ -842,7 +832,7 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *em, BMVert *eve, int index)
{
intptr_t poinval;
if (ED_mesh_mirror_topo_table(ob, 'u') == -1)
if (ED_mesh_mirror_topo_table(ob, NULL, 'u') == -1)
return NULL;
if (index == -1) {
@ -897,7 +887,7 @@ int ED_mesh_mirror_get_vert(Object *ob, int index)
index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
}
else {
index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology);
index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, use_topology);
}
return index_mirr;
@ -1007,31 +997,39 @@ static bool mirror_facecmp(const void *a, const void *b)
}
/* BMESH_TODO, convert to MPoly (functions above also) */
int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
{
Mesh *me = ob->data;
MVert *mv, *mvert = me->mvert;
MFace mirrormf, *mf, *hashmf, *mface = me->mface;
MVert *mv, *mvert;
MFace mirrormf, *mf, *hashmf, *mface;
GHash *fhash;
const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
int *mirrorverts, *mirrorfaces;
BLI_assert(em == NULL); /* Does not work otherwise, currently... */
const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
const int totvert = dm ? dm->getNumVerts(dm) : me->totvert;
const int totface = dm ? dm->getNumTessFaces(dm) : me->totface;
int a;
mirrorverts = MEM_callocN(sizeof(int) * me->totvert, "MirrorVerts");
mirrorfaces = MEM_callocN(sizeof(int) * 2 * me->totface, "MirrorFaces");
mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces");
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];

View File

@ -342,8 +342,8 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
me->edit_btmesh = NULL;
}
if (obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, 'e');
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, NULL, 'e');
}
}
else if (obedit->type == OB_ARMATURE) {

View File

@ -131,10 +131,10 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
float *fp1, *fp2;
float tvec[3];
ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's');
ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
i2 = mesh_get_x_mirror_vert(ob, i1, use_topology);
i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
if (i2 == i1) {
fp1 = ((float *)kb->data) + i1 * 3;
fp1[0] = -fp1[0];
@ -162,7 +162,7 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
}
}
ED_mesh_mirror_spatial_table(ob, NULL, NULL, 'e');
ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;

View File

@ -517,7 +517,7 @@ static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
if (vidx == -1)
return;
vidx_mirr = mesh_get_x_mirror_vert(ob, vidx, use_topology);
vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology);
if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
MDeformVert *dvert_src = &me->dvert[vidx];
@ -2244,7 +2244,7 @@ void ED_vgroup_mirror(Object *ob,
for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
if ((vidx_mirr = mesh_get_x_mirror_vert(ob, vidx, use_topology)) != -1) {
if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
if (vidx != vidx_mirr) {
mv_mirr = &me->mvert[vidx_mirr];
if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {

View File

@ -659,7 +659,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
if (selected==0 || key->flag & PEK_SELECT) {
if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat);
psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
invert_m4_m4(imat, mat);
}
@ -674,7 +674,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
if (selected==0 || key->flag & PEK_SELECT) {
if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat);
psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
invert_m4_m4(imat, mat);
}
@ -761,7 +761,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
psmd= psys_get_modifier(ob, psys);
totpart= psys->totpart;
if (!psmd->dm)
if (!psmd->dm_final)
return;
tree= BLI_kdtree_new(totpart);
@ -769,7 +769,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
/* insert particles into kd tree */
LOOP_PARTICLES {
key = pa->hair;
psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
BLI_kdtree_insert(tree, p, co);
@ -783,7 +783,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
LOOP_PARTICLES {
key = pa->hair;
psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
co[0] = -co[0];
@ -898,7 +898,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
edit= psys->edit;
psmd= psys_get_modifier(ob, psys);
if (!psmd->dm)
if (!psmd->dm_final)
return;
if (!edit->mirror_cache)
@ -911,7 +911,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
* to avoid doing mirror twice */
LOOP_POINTS {
if (point->flag & PEP_EDIT_RECALC) {
PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
if (edit->mirror_cache[p] != -1)
edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
@ -946,11 +946,11 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
psys = edit->psys;
psmd = psys_get_modifier(ob, psys);
if (!psmd->dm)
if (!psmd->dm_final)
return;
LOOP_EDITED_POINTS {
psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles + p, hairmat);
psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
LOOP_KEYS {
mul_m4_v3(hairmat, key->co);
@ -1095,7 +1095,7 @@ void recalc_lengths(PTCacheEdit *edit)
/* calculate a tree for finding nearest emitter's vertice */
void recalc_emitter_field(Object *ob, ParticleSystem *psys)
{
DerivedMesh *dm=psys_get_modifier(ob, psys)->dm;
DerivedMesh *dm=psys_get_modifier(ob, psys)->dm_final;
PTCacheEdit *edit= psys->edit;
float *vec, *nor;
int i, totface /*, totvert*/;
@ -1188,12 +1188,12 @@ void update_world_cos(Object *ob, PTCacheEdit *edit)
POINT_P; KEY_K;
float hairmat[4][4];
if (psys==0 || psys->edit==0 || psmd->dm==NULL)
if (psys==0 || psys->edit==0 || psmd->dm_final==NULL)
return;
LOOP_POINTS {
if (!(psys->flag & PSYS_GLOBAL_HAIR))
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, hairmat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, hairmat);
LOOP_KEYS {
copy_v3_v3(key->world_co, key->co);
@ -1839,7 +1839,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
LOOP_VISIBLE_POINTS {
if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + p, mat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
if (pset->selectmode==SCE_SELECT_POINT) {
LOOP_KEYS {
@ -2273,7 +2273,7 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
psmd= psys_get_modifier(ob, psys);
LOOP_TAGGED_POINTS {
PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
}
}
@ -2353,7 +2353,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
LOOP_POINTS {
LOOP_TAGGED_KEYS {
PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
break;
}
}
@ -2567,7 +2567,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* insert particles into kd tree */
LOOP_SELECTED_POINTS {
psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
BLI_kdtree_insert(tree, p, co);
@ -2577,7 +2577,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* tag particles to be removed */
LOOP_SELECTED_POINTS {
psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
@ -2808,13 +2808,17 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
return;
psmd= psys_get_modifier(ob, psys);
if (!psmd->dm)
if (!psmd->dm_final)
return;
const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly);
/* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
BKE_mesh_tessface_ensure(me);
mirrorfaces= mesh_get_x_mirror_faces(ob, NULL);
/* Note: In case psys uses DM tessface indices, we mirror final DM iteslef, not orig mesh. Avoids an (impossible)
* dm -> orig -> dm tessface indices conversion... */
mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd->dm_final : NULL);
if (!edit->mirror_cache)
PE_update_mirror_cache(ob, psys);
@ -2823,11 +2827,12 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
newtotpart= psys->totpart;
LOOP_VISIBLE_POINTS {
pa = psys->particles + p;
if (!tagged) {
if (point_is_selected(point)) {
if (edit->mirror_cache[p] != -1) {
/* already has a mirror, don't need to duplicate */
PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
PE_mirror_particle(ob, psmd->dm_final, psys, pa, NULL);
continue;
}
else
@ -2840,6 +2845,8 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
}
if (newtotpart != psys->totpart) {
MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface;
/* allocate new arrays and copy existing */
new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint new");
@ -2869,10 +2876,12 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
for (p=0, point=edit->points; p<totpart; p++, point++) {
pa = psys->particles + p;
const int pa_num = pa->num;
if (point->flag & PEP_HIDE)
continue;
if (!(point->flag & PEP_TAG) || mirrorfaces[pa->num*2] == -1)
if (!(point->flag & PEP_TAG) || mirrorfaces[pa_num * 2] == -1)
continue;
/* duplicate */
@ -2882,27 +2891,31 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
if (point->keys) newpoint->keys= MEM_dupallocN(point->keys);
/* rotate weights according to vertex index rotation */
rotation= mirrorfaces[pa->num*2+1];
rotation= mirrorfaces[pa_num * 2 + 1];
newpa->fuv[0] = pa->fuv[2];
newpa->fuv[1] = pa->fuv[1];
newpa->fuv[2] = pa->fuv[0];
newpa->fuv[3] = pa->fuv[3];
while (rotation-- > 0)
if (me->mface[pa->num].v4) {
while (rotation--) {
if (mtessface[pa_num].v4) {
SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3]);
}
else {
SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2]);
}
}
/* assign face inddex */
newpa->num= mirrorfaces[pa->num*2];
newpa->num_dmcache= psys_particle_dm_face_lookup(ob, psmd->dm, newpa->num, newpa->fuv, NULL);
/* assign face index */
/* NOTE: mesh_get_x_mirror_faces generates -1 for non-found mirror, same as DMCACHE_NOTFOUND... */
newpa->num = mirrorfaces[pa_num * 2];
if ((newpa->num_dmcache != DMCACHE_NOTFOUND) && psys->part->use_modifier_stack && !psmd->dm->deformedOnly) {
newpa->num = newpa->num_dmcache;
if (use_dm_final_indices) {
newpa->num_dmcache = DMCACHE_ISCHILD;
}
else {
newpa->num_dmcache = psys_particle_dm_face_lookup(
psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
}
/* update edit key pointers */
key= newpoint->keys;
@ -2912,7 +2925,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
}
/* map key positions as mirror over x axis */
PE_mirror_particle(ob, psmd->dm, psys, pa, newpa);
PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa);
newpa++;
newpoint++;
@ -3360,7 +3373,7 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
totface=dm->getNumTessFaces(dm);
mface=dm->getTessFaceDataArray(dm, CD_MFACE);
mvert=dm->getVertDataArray(dm, CD_MVERT);
/* lets intersect the faces */
for (i=0; i<totface; i++, mface++) {
if (vert_cos) {
@ -3452,6 +3465,7 @@ static int brush_add(PEData *data, short number)
{
Scene *scene= data->scene;
Object *ob= data->ob;
DerivedMesh *dm;
PTCacheEdit *edit = data->edit;
ParticleSystem *psys= edit->psys;
ParticleData *add_pars;
@ -3465,11 +3479,7 @@ static int brush_add(PEData *data, short number)
float framestep, timestep;
short size= pset->brush[PE_BRUSH_ADD].size;
short size2= size*size;
DerivedMesh *dm=0;
RNG *rng;
const int *index_mf_to_mpoly;
const int *index_mp_to_orig;
bool release_dm = false;
invert_m4_m4(imat, ob->obmat);
@ -3487,15 +3497,13 @@ static int brush_add(PEData *data, short number)
timestep= psys_get_timestep(&sim);
if (psmd->dm->deformedOnly || psys->part->use_modifier_stack)
dm = psmd->dm;
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; i<number; i++) {
if (number>1) {
@ -3523,16 +3531,22 @@ static int brush_add(PEData *data, short number)
/* warning, returns the derived mesh face */
if (particle_intersect_dm(scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
if (index_mf_to_mpoly && index_mp_to_orig)
add_pars[n].num = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, add_pars[n].num_dmcache);
else
if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
add_pars[n].num = add_pars[n].num_dmcache;
add_pars[n].num_dmcache = DMCACHE_ISCHILD;
}
else if (dm == psmd->dm_deformed) {
/* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
add_pars[n].num = add_pars[n].num_dmcache;
add_pars[n].num_dmcache = psys_particle_dm_face_lookup(
psmd->dm_final, psmd->dm_deformed,
add_pars[n].num, add_pars[n].fuv, NULL);
}
else {
add_pars[n].num = add_pars[n].num_dmcache;
}
if (psys_particle_dm_face_lookup(ob, psmd->dm, add_pars[n].num_dmcache, add_pars[n].fuv, NULL) != DMCACHE_NOTFOUND) {
if (psys->part->use_modifier_stack && !psmd->dm->deformedOnly) {
add_pars[n].num = add_pars[n].num_dmcache;
add_pars[n].num_dmcache = DMCACHE_ISCHILD;
}
if (add_pars[n].num != DMCACHE_NOTFOUND) {
n++;
}
}
@ -3567,7 +3581,7 @@ static int brush_add(PEData *data, short number)
tree=BLI_kdtree_new(psys->totpart);
for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0);
psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0);
BLI_kdtree_insert(tree, i, cur_co);
}
@ -3611,7 +3625,7 @@ static int brush_add(PEData *data, short number)
int w, maxw;
float maxd, totw=0.0, weight[3];
psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3);
maxd= ptn[maxw-1].dist;
@ -3676,7 +3690,7 @@ static int brush_add(PEData *data, short number)
}
}
for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
invert_m4_m4(imat, hairmat);
mul_m4_v3(imat, hkey->co);
}
@ -3688,9 +3702,6 @@ static int brush_add(PEData *data, short number)
MEM_freeN(add_pars);
if (release_dm)
dm->release(dm);
BLI_rng_free(rng);
return n;
@ -3866,7 +3877,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_PUFF:
{
if (edit->psys) {
data.dm= psmd->dm;
data.dm= psmd->dm_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
data.select= selected;
@ -3922,7 +3933,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_WEIGHT:
{
if (edit->psys) {
data.dm= psmd->dm;
data.dm= psmd->dm_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
@ -4545,7 +4556,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
LOOP_VISIBLE_POINTS {
if (psys)
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
LOOP_SELECTED_KEYS {
copy_v3_v3(co, key->co);
@ -4576,7 +4587,7 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic
int totpoint;
/* no psmd->dm happens in case particle system modifier is not enabled */
if (!(psys && psmd && psmd->dm) && !cache)
if (!(psys && psmd && psmd->dm_final) && !cache)
return;
if (cache && cache->flag & PTCACHE_DISK_CACHE)

View File

@ -592,7 +592,7 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
point++;
}
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
mul_m4_v3(hairmat, key->co);
@ -676,7 +676,7 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
float from_ob_imat[4][4], to_ob_imat[4][4];
float from_imat[4][4], to_imat[4][4];
if (!target_psmd->dm)
if (!target_psmd->dm_final)
return false;
if (!psys->part || psys->part->type != PART_HAIR)
return false;
@ -690,15 +690,14 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
invert_m4_m4(from_imat, from_mat);
invert_m4_m4(to_imat, to_mat);
if (target_psmd->dm->deformedOnly) {
if (target_psmd->dm_final->deformedOnly) {
/* we don't want to mess up target_psmd->dm when converting to global coordinates below */
dm = target_psmd->dm;
dm = target_psmd->dm_final;
}
else {
/* warning: this rebuilds target_psmd->dm! */
dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH | CD_MASK_MFACE);
dm = target_psmd->dm_deformed;
}
target_dm = target_psmd->dm;
target_dm = target_psmd->dm_final;
/* don't modify the original vertices */
dm = CDDM_copy(dm);
@ -766,7 +765,7 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
tpa->foffset = 0.0f;
tpa->num = nearest.index;
tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL);
tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL);
}
else {
me = &medge[nearest.index];
@ -1066,9 +1065,9 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Parti
modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
psmd->psys = psys;
psmd->dm = CDDM_copy(final_dm);
CDDM_calc_normals(psmd->dm);
DM_ensure_tessface(psmd->dm);
psmd->dm_final = CDDM_copy(final_dm);
CDDM_calc_normals(psmd->dm_final);
DM_ensure_tessface(psmd->dm_final);
if (psys_from->edit)
copy_particle_edit(scene, ob_to, psys, psys_from);

View File

@ -412,7 +412,7 @@ bool ED_wpaint_fill(VPaint *wp, Object *ob, float paintweight)
dw->weight = paintweight;
if (me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
int j = mesh_get_x_mirror_vert(ob, vidx, topology);
int j = mesh_get_x_mirror_vert(ob, NULL, vidx, topology);
if (j >= 0) {
/* copy, not paint again */
if (vgroup_mirror != -1) {
@ -1718,7 +1718,7 @@ static void do_weight_paint_vertex(
/* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
if (me->editflag & ME_EDIT_MIRROR_X) {
index_mirr = mesh_get_x_mirror_vert(ob, index, topology);
index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
vgroup_mirr = (wpi->vgroup_mirror != -1) ? wpi->vgroup_mirror : wpi->vgroup_active;
/* another possible error - mirror group _and_ active group are the same (which is fine),
@ -1956,8 +1956,8 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
}
/* weight paint specific */
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, 'e');
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, NULL, 'e');
paint_cursor_delete_textures();
}
@ -1972,7 +1972,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
BKE_paint_init(scene, ePaintWeight, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's');
ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
ED_vgroup_sync_from_pose(ob);
}

View File

@ -1865,7 +1865,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
if (!(point->flag & PEP_TRANSFORM)) continue;
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR))
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
if (key->flag & PEK_USE_WCO) {
@ -1939,7 +1939,7 @@ void flushTransParticles(TransInfo *t)
if (!(point->flag & PEP_TRANSFORM)) continue;
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
invert_m4_m4(imat, mat);
for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
@ -6280,7 +6280,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if (t->obedit->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
/* table needs to be created for each edit command, since vertices can move etc */
ED_mesh_mirror_spatial_table(t->obedit, em, NULL, 'e');
ED_mesh_mirror_spatial_table(t->obedit, em, NULL, NULL, 'e');
}
}
else if ((t->flag & T_POSE) && (t->poseobj)) {

View File

@ -151,8 +151,8 @@ void ED_editors_exit(bContext *C)
}
/* global in meshtools... */
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, 'e');
ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
ED_mesh_mirror_topo_table(NULL, NULL, 'e');
}
/* flush any temp data from object editing to DNA before writing files,

View File

@ -716,7 +716,8 @@ typedef struct ParticleSystemModifierData {
ModifierData modifier;
struct ParticleSystem *psys;
struct DerivedMesh *dm;
struct DerivedMesh *dm_final; /* Final DM - its topology may differ from orig mesh. */
struct DerivedMesh *dm_deformed; /* Deformed-onle DM - its topology is same as orig mesh one. */
int totdmvert, totdmedge, totdmface;
short flag, pad;
} ParticleSystemModifierData;

View File

@ -109,6 +109,7 @@ typedef struct ParticleData {
float time, lifetime; /* dietime is not nescessarily time+lifetime as */
float dietime; /* particles can die unnaturally (collision) */
/* WARNING! Those two indices, when not affected to vertices, are for !!! TESSELLATED FACES !!!, not POLYGONS! */
int num; /* index to vert/edge/face */
int num_dmcache; /* index to derived mesh data (face) to avoid slow lookups */

View File

@ -167,7 +167,7 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
if (enable)
psys_render_set(ob, psys, mat, mat, 1, 1, 0.f);
else
psys_render_restore(ob, psys);
psys_render_restore(scene, ob, psys);
}
}

View File

@ -175,7 +175,7 @@ static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr, ParticleSy
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_ParticleSystem) {
psmd = (ParticleSystemModifierData *) md;
if (psmd && psmd->dm && psmd->psys) {
if (psmd && psmd->dm_final && psmd->psys) {
psys = psmd->psys;
for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
/* hairkeys are stored sequentially in memory, so we can
@ -210,7 +210,7 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu
}
else {
float hairmat[4][4];
psys_mat_hair_to_object(ob, psmd->dm, psmd->psys->part->from, pa, hairmat);
psys_mat_hair_to_object(ob, psmd->dm_final, psmd->psys->part->from, pa, hairmat);
copy_v3_v3(values, hkey->co);
mul_m4_v3(hairmat, values);
}
@ -240,7 +240,7 @@ static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float
float hairmat[4][4];
float imat[4][4];
psys_mat_hair_to_object(ob, psmd->dm, psmd->psys->part->from, pa, hairmat);
psys_mat_hair_to_object(ob, psmd->dm_final, psmd->psys->part->from, pa, hairmat);
invert_m4_m4(imat, hairmat);
copy_v3_v3(hkey->co, values);
mul_m4_v3(imat, hkey->co);
@ -263,7 +263,7 @@ static void rna_ParticleHairKey_co_object(HairKey *hairkey, Object *object, Part
}
else {
float hairmat[4][4];
psys_mat_hair_to_object(object, modifier->dm, modifier->psys->part->from, particle, hairmat);
psys_mat_hair_to_object(object, modifier->dm_final, modifier->psys->part->from, particle, hairmat);
copy_v3_v3(n_co, hairkey->co);
mul_m4_v3(hairmat, n_co);
}
@ -282,14 +282,14 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *repor
int num = particle->num_dmcache;
int from = modifier->psys->part->from;
if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPUV)) {
BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
return;
}
DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
if (num == DMCACHE_NOTFOUND)
if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
if (particle->num < modifier->dm_final->getNumTessFaces(modifier->dm_final))
num = particle->num;
/* get uvco */
@ -299,8 +299,8 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *repor
MFace *mface;
MTFace *mtface;
mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MTFACE, 0);
if (mface && mtface) {
mtface += num;
@ -446,8 +446,8 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
int totface;
int num = -1;
DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
totface = modifier->dm->getNumTessFaces(modifier->dm);
DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
totface = modifier->dm_final->getNumTessFaces(modifier->dm_final);
/* 1. check that everything is ok & updated */
if (!particlesystem || !totface) {
@ -476,9 +476,6 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
if (particle_no < totpart) {
num = (ELEM(particle->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? particle->num : particle->num_dmcache;
if (num == DMCACHE_NOTFOUND)
num = particle->num;
if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
if (num != DMCACHE_NOTFOUND && num < totface) {
*r_fuv = &particle->fuv;
@ -521,7 +518,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
ParticleSystemModifierData *modifier, ParticleData *particle,
int particle_no, int uv_no, float r_uv[2])
{
if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPUV)) {
BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
zero_v2(r_uv);
return;
@ -538,8 +535,8 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
zero_v2(r_uv);
}
else {
MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
MFace *mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MTFACE, uv_no);
psys_interpolate_uvs(&mtface[num], mface->v4, *fuv, r_uv);
}
@ -550,7 +547,7 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, R
ParticleSystemModifierData *modifier, ParticleData *particle,
int particle_no, int vcol_no, float r_mcol[3])
{
if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPCOL)) {
if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPCOL)) {
BKE_report(reports, RPT_ERROR, "Mesh has no VCol data");
zero_v3(r_mcol);
return;
@ -567,8 +564,8 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, R
zero_v3(r_mcol);
}
else {
MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
MFace *mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MCOL, vcol_no);
MCol mcol;
psys_interpolate_mcol(&mc[num * 4], mface->v4, *fuv, &mcol);
@ -595,7 +592,7 @@ static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Sc
ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
if (particlesystem->renderdata) {
psys_render_restore(object, particlesystem);
psys_render_restore(scene, object, particlesystem);
}
psmd->flag &= ~eParticleSystemFlag_psys_updated;

View File

@ -1006,7 +1006,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (psys == NULL || psys->totpart == 0) return derivedData;
if (psys->part == NULL || psys->particles == NULL) return derivedData;
if (psmd->dm == NULL) return derivedData;
if (psmd->dm_final== NULL) return derivedData;
/* 1. find faces to be exploded if needed */
if (emd->facepa == NULL ||

View File

@ -351,7 +351,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
ChildParticle *cpa = psys->child + (p - psys->totpart);
pa = psys->particles + cpa->parent;
}
psys_mat_hair_to_global(sim.ob, sim.psmd->dm, sim.psys->part->from, pa, hairmat);
psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat);
copy_m3_m4(mat, hairmat);
/* to quaternion */
mat3_to_quat(frame, mat);

View File

@ -51,17 +51,23 @@ static void initData(ModifierData *md)
{
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
psmd->psys = NULL;
psmd->dm = NULL;
psmd->dm_final = NULL;
psmd->dm_deformed = NULL;
psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
}
static void freeData(ModifierData *md)
{
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
if (psmd->dm) {
psmd->dm->needsFree = 1;
psmd->dm->release(psmd->dm);
psmd->dm = NULL;
if (psmd->dm_final) {
psmd->dm_final->needsFree = 1;
psmd->dm_final->release(psmd->dm_final);
psmd->dm_final = NULL;
if (psmd->dm_deformed) {
psmd->dm_deformed->needsFree = 1;
psmd->dm_deformed->release(psmd->dm_deformed);
psmd->dm_deformed = NULL;
}
}
/* ED_object_modifier_remove may have freed this first before calling
@ -78,7 +84,8 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
tpsmd->dm = NULL;
tpsmd->dm_final = NULL;
tpsmd->dm_deformed = NULL;
tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
}
@ -119,9 +126,14 @@ static void deformVerts(ModifierData *md, Object *ob,
}
/* clear old dm */
if (psmd->dm) {
psmd->dm->needsFree = 1;
psmd->dm->release(psmd->dm);
if (psmd->dm_final) {
psmd->dm_final->needsFree = 1;
psmd->dm_final->release(psmd->dm_final);
if (psmd->dm_deformed) {
psmd->dm_deformed->needsFree = 1;
psmd->dm_deformed->release(psmd->dm_deformed);
psmd->dm_deformed = NULL;
}
}
else if (psmd->flag & eParticleSystemFlag_file_loaded) {
/* in file read dm just wasn't saved in file so no need to reset everything */
@ -133,9 +145,9 @@ static void deformVerts(ModifierData *md, Object *ob,
}
/* make new dm */
psmd->dm = CDDM_copy(dm);
CDDM_apply_vert_coords(psmd->dm, vertexCos);
CDDM_calc_normals(psmd->dm);
psmd->dm_final = CDDM_copy(dm);
CDDM_apply_vert_coords(psmd->dm_final, vertexCos);
CDDM_calc_normals(psmd->dm_final);
if (needsFree) {
dm->needsFree = 1;
@ -143,19 +155,27 @@ static void deformVerts(ModifierData *md, Object *ob,
}
/* protect dm */
psmd->dm->needsFree = 0;
psmd->dm_final->needsFree = 0;
DM_ensure_tessface(psmd->dm_final);
if (!psmd->dm_final->deformedOnly) {
/* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set.
* This is awfully weak though. :| */
psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
DM_ensure_tessface(psmd->dm_deformed);
}
/* report change in mesh structure */
DM_ensure_tessface(psmd->dm);
if (psmd->dm->getNumVerts(psmd->dm) != psmd->totdmvert ||
psmd->dm->getNumEdges(psmd->dm) != psmd->totdmedge ||
psmd->dm->getNumTessFaces(psmd->dm) != psmd->totdmface)
if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
{
psys->recalc |= PSYS_RECALC_RESET;
psmd->totdmvert = psmd->dm->getNumVerts(psmd->dm);
psmd->totdmedge = psmd->dm->getNumEdges(psmd->dm);
psmd->totdmface = psmd->dm->getNumTessFaces(psmd->dm);
psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
}
if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {

View File

@ -1392,16 +1392,16 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
re->flag |= R_HALO;
RE_set_customdata_names(obr, &psmd->dm->faceData);
sd.totuv = CustomData_number_of_layers(&psmd->dm->faceData, CD_MTFACE);
sd.totcol = CustomData_number_of_layers(&psmd->dm->faceData, CD_MCOL);
RE_set_customdata_names(obr, &psmd->dm_final->faceData);
sd.totuv = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MTFACE);
sd.totcol = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MCOL);
if (ma->texco & TEXCO_UV && sd.totuv) {
sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
if (ma->strand_uvname[0]) {
sd.override_uv = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, ma->strand_uvname);
sd.override_uv -= CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
sd.override_uv = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, ma->strand_uvname);
sd.override_uv -= CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
}
}
else
@ -1412,15 +1412,15 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
/* 2.2 setup billboards */
if (part->ren_as == PART_DRAW_BB) {
int first_uv = CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
int first_uv = CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[0]);
bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[0]);
if (bb.uv[0] < 0)
bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm->faceData, CD_MTFACE);
bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[1]);
bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[1]);
bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[2]);
bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[2]);
if (first_uv >= 0) {
bb.uv[0] -= first_uv;
@ -1500,9 +1500,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (ma->amb != 0.0f)
do_surfacecache = true;
totface= psmd->dm->getNumTessFaces(psmd->dm);
index_mf_to_mpoly = psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX);
index_mp_to_orig = psmd->dm->getPolyDataArray(psmd->dm, CD_ORIGINDEX);
totface= psmd->dm_final->getNumTessFaces(psmd->dm_final);
index_mf_to_mpoly = psmd->dm_final->getTessFaceDataArray(psmd->dm_final, CD_ORIGINDEX);
index_mp_to_orig = psmd->dm_final->getPolyDataArray(psmd->dm_final, CD_ORIGINDEX);
if (index_mf_to_mpoly == NULL) {
index_mp_to_orig = NULL;
}
@ -1557,10 +1557,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
num= pa->num_dmcache;
if (num == DMCACHE_NOTFOUND)
if (pa->num < psmd->dm->getNumTessFaces(psmd->dm))
if (pa->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
num= pa->num;
get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
get_particle_uvco_mcol(part->from, psmd->dm_final, pa->fuv, num, &sd);
pa_size = pa->size;
@ -1611,17 +1611,17 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
/* get uvco & mcol */
if (part->childtype==PART_CHILD_FACES) {
get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd);
get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm_final, cpa->fuv, cpa->num, &sd);
}
else {
ParticleData *parent = psys->particles + cpa->parent;
num = parent->num_dmcache;
if (num == DMCACHE_NOTFOUND)
if (parent->num < psmd->dm->getNumTessFaces(psmd->dm))
if (parent->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
num = parent->num;
get_particle_uvco_mcol(part->from, psmd->dm, parent->fuv, num, &sd);
get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd);
}
do_simplify = psys_render_simplify_params(psys, cpa, simplify);
@ -1737,14 +1737,14 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
sub_v3_v3v3(loc0, loc1, loc);
add_v3_v3v3(loc0, loc1, loc0);
particle_curve(re, obr, psmd->dm, ma, &sd, loc1, loc0, seed, pa_co);
particle_curve(re, obr, psmd->dm_final, ma, &sd, loc1, loc0, seed, pa_co);
}
sd.first = 0;
sd.time = time;
if (k)
particle_curve(re, obr, psmd->dm, ma, &sd, loc, loc1, seed, pa_co);
particle_curve(re, obr, psmd->dm_final, ma, &sd, loc, loc1, seed, pa_co);
copy_v3_v3(loc1, loc);
}
@ -1803,7 +1803,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct;
pa_co[1] = (float)i/(float)(trail_count-1);
particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co);
particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
}
}
else {
@ -1839,7 +1839,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
bb.lifetime = pa_dietime-pa_birthtime;
}
particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co);
particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
}
}
@ -1851,7 +1851,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
}
if (do_surfacecache)
strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset);
strandbuf->surface= cache_strand_surface(re, obr, psmd->dm_final, mat, timeoffset);
/* 4. clean up */
#if 0 /* XXX old animation system */
@ -4688,7 +4688,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
psys->flag |= PSYS_USE_IMAT;
init_render_object_data(re, obr, timeoffset);
if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
psys_render_restore(ob, psys);
psys_render_restore(re->scene, ob, psys);
psys->flag &= ~PSYS_USE_IMAT;
/* only add instance for objects that have not been used for dupli */
@ -4888,7 +4888,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
if (enable)
psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
else
psys_render_restore(ob, psys);
psys_render_restore(re->scene, ob, psys);
}
}

View File

@ -157,7 +157,7 @@ static void pointdensity_cache_psys(Scene *scene,
}
if ( !psys_check_enabled(ob, psys)) {
psys_render_restore(ob, psys);
psys_render_restore(scene, ob, psys);
return;
}
@ -253,7 +253,7 @@ static void pointdensity_cache_psys(Scene *scene,
}
if (use_render_params) {
psys_render_restore(ob, psys);
psys_render_restore(scene, ob, psys);
}
}
@ -711,7 +711,7 @@ static void particle_system_minmax(Scene *scene,
}
if (use_render_params) {
psys_render_restore(object, psys);
psys_render_restore(scene, object, psys);
}
}

View File

@ -498,8 +498,8 @@ void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con)
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode) RET_NONE
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_NONE
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_ZERO
int ED_mesh_mirror_topo_table(struct Object *ob, char mode) RET_ZERO
int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode) RET_ZERO
int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode) RET_ZERO
int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, const float co[3], char mode) RET_ZERO
float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const bool axis_only) RET_ZERO
void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height) RET_NONE