Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/ED_mesh.h10
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c127
-rw-r--r--source/blender/editors/mesh/meshtools.c118
-rw-r--r--source/blender/editors/physics/particle_edit.c133
-rw-r--r--source/blender/editors/physics/particle_object.c76
-rw-r--r--source/blender/editors/transform/transform_conversions.c4
7 files changed, 369 insertions, 101 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 787cf7f0524..dfa5a51a775 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -226,9 +226,14 @@ typedef struct MirrTopoStore_t {
bool ED_mesh_mirrtopo_recalc_check(
struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store);
+bool ED_mesh_mirrtopo_recalc_check__real_mesh(
+ struct Mesh *me, struct Mesh *dm, MirrTopoStore_t *mesh_topo_store);
void ED_mesh_mirrtopo_init(
struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
const bool skip_em_vert_array_init);
+void ED_mesh_mirrtopo_init__real_mesh(
+ struct Mesh *me, struct Mesh *dm, MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
@@ -318,16 +323,21 @@ 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, struct DerivedMesh *dm, const float co[3], char mode);
+int ED_mesh_mirror_spatial_table__real_mesh(
+ struct Object *ob, struct BMEditMesh *em, struct Mesh *mesh, const float co[3], char mode);
int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode);
+int ED_mesh_mirror_topo_table__real_mesh(struct Object *ob, struct Mesh *mesh, 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, struct DerivedMesh *dm, int index, const bool use_topology);
+int mesh_get_x_mirror_vert__real_mesh(struct Object *ob, struct Mesh *mesh, 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, struct DerivedMesh *dm);
+int *mesh_get_x_mirror_faces__real_mesh(struct Object *ob, struct BMEditMesh *em, struct Mesh *mesh);
int ED_mesh_mirror_get_vert(struct Object *ob, int index);
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index e8f3e592715..ab44e017fc6 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1030,7 +1030,7 @@ void EDBM_verts_mirror_cache_begin_ex(
BM_mesh_elem_index_ensure(bm, BM_VERT);
if (use_topology) {
- ED_mesh_mirrtopo_init(me, NULL, &mesh_topo_store, true);
+ ED_mesh_mirrtopo_init__real_mesh(me, NULL, &mesh_topo_store, true);
}
else {
tree = BLI_kdtree_new(bm->totvert);
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 22bfd8eedea..4c078d2ac8b 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -37,6 +37,8 @@
#include "BKE_DerivedMesh.h"
#include "BLI_kdtree.h"
#include "BKE_editmesh.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
#include "ED_mesh.h"
@@ -93,7 +95,73 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, co
else {
MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
int i;
-
+
+ for (i = 0; i < totvert; i++, mvert++) {
+ BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
+ }
+ }
+
+ BLI_kdtree_balance(MirrKdStore.tree);
+ }
+ else if (mode == 'e') { /* end table */
+ if (MirrKdStore.tree) {
+ BLI_kdtree_free(MirrKdStore.tree);
+ MirrKdStore.tree = NULL;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return 0;
+}
+
+/* mode is 's' start, or 'e' end, or 'u' use */
+/* if end, ob can be NULL */
+int ED_mesh_mirror_spatial_table__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, const float co[3], char mode)
+{
+ if (mode == 'u') { /* use table */
+ if (MirrKdStore.tree == NULL)
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 's');
+
+ if (MirrKdStore.tree) {
+ KDTreeNearest nearest;
+ const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
+
+ if (i != -1) {
+ if (nearest.dist < KD_THRESH) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+ else if (mode == 's') { /* start table */
+ Mesh *me = ob->data;
+ const bool use_em = (!mesh && em && me->edit_btmesh == em);
+ const int totvert = use_em ? em->bm->totvert : mesh ? mesh->totvert : me->totvert;
+
+ if (MirrKdStore.tree) /* happens when entering this call without ending it */
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, co, 'e');
+
+ MirrKdStore.tree = BLI_kdtree_new(totvert);
+
+ if (use_em) {
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ /* this needs to be valid for index lookups later (callers need) */
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ BLI_kdtree_insert(MirrKdStore.tree, i, eve->co);
+ }
+ }
+ else {
+ MVert *mvert = mesh ? mesh->mvert : me->mvert;
+ int i;
+
for (i = 0; i < totvert; i++, mvert++) {
BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
}
@@ -172,11 +240,62 @@ bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, MirrTopoStore_t *m
}
}
+bool ED_mesh_mirrtopo_recalc_check__real_mesh(Mesh *me, Mesh *dm, MirrTopoStore_t *mesh_topo_store)
+{
+ const bool is_editmode = (me->edit_btmesh != NULL);
+ int totvert;
+ int totedge;
+
+ if (dm) {
+ totvert = dm->totvert;
+ totedge = dm->totedge;
+ }
+ else if (me->edit_btmesh) {
+ totvert = me->edit_btmesh->bm->totvert;
+ totedge = me->edit_btmesh->bm->totedge;
+ }
+ else {
+ totvert = me->totvert;
+ totedge = me->totedge;
+ }
+
+ if ((mesh_topo_store->index_lookup == NULL) ||
+ (mesh_topo_store->prev_is_editmode != is_editmode) ||
+ (totvert != mesh_topo_store->prev_vert_tot) ||
+ (totedge != mesh_topo_store->prev_edge_tot))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+
+}
+
void ED_mesh_mirrtopo_init(
Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
const bool skip_em_vert_array_init)
{
+ Mesh *fake_mesh = NULL;
+
+ if (dm != NULL) {
+ /* ED_real_mesh_mirrtopo_init() only uses the counts, not the actual data */
+ fake_mesh = BKE_mesh_new_nomain(dm->getNumVerts(dm), dm->getNumEdges(dm), dm->getNumTessFaces(dm),
+ dm->getNumLoops(dm), dm->getNumPolys(dm));
+ }
+
+ ED_mesh_mirrtopo_init__real_mesh(me, fake_mesh, mesh_topo_store, skip_em_vert_array_init);
+
+ if (dm != NULL) {
+ BKE_id_free(NULL, fake_mesh);
+ }
+}
+
+void ED_mesh_mirrtopo_init__real_mesh(
+ Mesh *me, Mesh *dm, MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init)
+{
const bool is_editmode = (me->edit_btmesh != NULL);
MEdge *medge = NULL, *med;
BMEditMesh *em = dm ? NULL : me->edit_btmesh;
@@ -208,7 +327,7 @@ void ED_mesh_mirrtopo_init(
totvert = em->bm->totvert;
}
else {
- totvert = dm ? dm->getNumVerts(dm) : me->totvert;
+ totvert = dm ? dm->totvert : me->totvert;
}
topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
@@ -224,8 +343,8 @@ void ED_mesh_mirrtopo_init(
}
}
else {
- totedge = dm ? dm->getNumEdges(dm) : me->totedge;
- medge = dm ? dm->getEdgeArray(dm) : me->medge;
+ totedge = dm ? dm->totedge : me->totedge;
+ medge = dm ? dm->medge : me->medge;
for (a = 0, med = medge; a < totedge; a++, med++) {
const unsigned int i1 = med->v1, i2 = med->v2;
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 83458127820..9b86f904161 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -707,6 +707,30 @@ int ED_mesh_mirror_topo_table(
return 0;
}
+/* 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__real_mesh(
+ Object *ob, Mesh *mesh, char mode)
+{
+ if (mode == 'u') { /* use table */
+ if (ED_mesh_mirrtopo_recalc_check__real_mesh(ob->data, mesh, &mesh_topo_store)) {
+ ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 's');
+ }
+ }
+ else if (mode == 's') { /* start table */
+ ED_mesh_mirrtopo_init__real_mesh(ob->data, mesh, &mesh_topo_store, false);
+ }
+ else if (mode == 'e') { /* end table */
+ ED_mesh_mirrtopo_free(&mesh_topo_store);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return 0;
+}
+
/** \} */
@@ -742,6 +766,38 @@ int mesh_get_x_mirror_vert(Object *ob, DerivedMesh *dm, int index, const bool us
}
}
+static int mesh_get_x_mirror_vert_spatial__real_mesh(Object *ob, Mesh *mesh, int index)
+{
+ Mesh *me = ob->data;
+ MVert *mvert = mesh ? mesh->mvert : me->mvert;
+ float vec[3];
+
+ mvert = &mvert[index];
+ vec[0] = -mvert->co[0];
+ vec[1] = mvert->co[1];
+ vec[2] = mvert->co[2];
+
+ return ED_mesh_mirror_spatial_table__real_mesh(ob, NULL, mesh, vec, 'u');
+}
+
+static int mesh_get_x_mirror_vert_topo__real_mesh(Object *ob, Mesh *mesh, int index)
+{
+ if (ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 'u') == -1)
+ return -1;
+
+ return mesh_topo_store.index_lookup[index];
+}
+
+int mesh_get_x_mirror_vert__real_mesh(Object *ob, Mesh *mesh, int index, const bool use_topology)
+{
+ if (use_topology) {
+ return mesh_get_x_mirror_vert_topo__real_mesh(ob, mesh, index);
+ }
+ else {
+ return mesh_get_x_mirror_vert_spatial__real_mesh(ob, mesh, index);
+ }
+}
+
static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, const float co[3])
{
float vec[3];
@@ -991,7 +1047,67 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
BLI_ghash_free(fhash, NULL, NULL);
MEM_freeN(mirrorverts);
-
+
+ return mirrorfaces;
+}
+
+/* This is a Mesh-based copy of mesh_get_x_mirror_faces() */
+int *mesh_get_x_mirror_faces__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh)
+{
+ Mesh *me = ob->data;
+ MVert *mv, *mvert;
+ MFace mirrormf, *mf, *hashmf, *mface;
+ GHash *fhash;
+ 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 = mesh ? mesh->totvert : me->totvert;
+ const int totface = mesh ? mesh->totface : me->totface;
+ int a;
+
+ mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
+ mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces");
+
+ mvert = mesh ? mesh->mvert : me->mvert;
+ mface = mesh ? mesh->mface : me->mface;
+
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 's');
+
+ for (a = 0, mv = mvert; a < totvert; a++, mv++)
+ mirrorverts[a] = mesh_get_x_mirror_vert__real_mesh(ob, mesh, a, use_topology);
+
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 'e');
+
+ fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
+ for (a = 0, mf = mface; a < totface; a++, mf++)
+ BLI_ghash_insert(fhash, mf, 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];
+ mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0;
+
+ /* make sure v4 is not 0 if a quad */
+ if (mf->v4 && mirrormf.v4 == 0) {
+ SWAP(unsigned int, mirrormf.v1, mirrormf.v3);
+ SWAP(unsigned int, mirrormf.v2, mirrormf.v4);
+ }
+
+ hashmf = BLI_ghash_lookup(fhash, &mirrormf);
+ if (hashmf) {
+ mirrorfaces[a * 2] = hashmf - mface;
+ mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf);
+ }
+ else
+ mirrorfaces[a * 2] = -1;
+ }
+
+ BLI_ghash_free(fhash, NULL, NULL);
+ MEM_freeN(mirrorverts);
+
return mirrorfaces;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 3df934a8dca..164001b6150 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -55,6 +55,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
+#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
@@ -364,7 +365,7 @@ typedef struct PEData {
Scene *scene;
ViewLayer *view_layer;
Object *ob;
- DerivedMesh *dm;
+ Mesh *mesh;
PTCacheEdit *edit;
BVHTreeFromMesh shape_bvh;
Depsgraph *depsgraph;
@@ -426,15 +427,15 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
static bool PE_create_shape_tree(PEData *data, Object *shapeob)
{
- DerivedMesh *dm = shapeob->derivedFinal;
+ Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_object(shapeob, 0);
memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
- if (!dm) {
+ if (!mesh) {
return false;
}
- return (bvhtree_from_mesh_get(&data->shape_bvh, dm, BVHTREE_FROM_LOOPTRI, 4) != NULL);
+ return (BKE_bvhtree_from_mesh_get(&data->shape_bvh, mesh, BVHTREE_FROM_LOOPTRI, 4) != NULL);
}
static void PE_free_shape_tree(PEData *data)
@@ -667,7 +668,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_final, psys->part->from, psys->particles + p, mat);
+ psys_mat_hair_to_global(data->ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
invert_m4_m4(imat, mat);
}
@@ -682,7 +683,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_final, psys->part->from, psys->particles + p, mat);
+ psys_mat_hair_to_global(data->ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
invert_m4_m4(imat, mat);
}
@@ -769,7 +770,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
psmd= psys_get_modifier(ob, psys);
totpart= psys->totpart;
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
tree= BLI_kdtree_new(totpart);
@@ -777,7 +778,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_final, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
BLI_kdtree_insert(tree, p, co);
@@ -791,7 +792,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
LOOP_PARTICLES {
key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
co[0] = -co[0];
@@ -817,7 +818,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
BLI_kdtree_free(tree);
}
-static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
+static void PE_mirror_particle(Object *ob, Mesh *mesh, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
{
HairKey *hkey, *mhkey;
PTCacheEditPoint *point, *mpoint;
@@ -868,8 +869,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
}
/* mirror positions and tags */
- psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
- psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
+ psys_mat_hair_to_orco(ob, mesh, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, mesh, psys->part->from, mpa, mmat);
invert_m4_m4(immat, mmat);
hkey=pa->hair;
@@ -906,7 +907,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
edit= psys->edit;
psmd= psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
if (!edit->mirror_cache)
@@ -919,7 +920,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_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
if (edit->mirror_cache[p] != -1)
edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
@@ -954,11 +955,11 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
psys = edit->psys;
psmd = psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
LOOP_EDITED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
+ psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles + p, hairmat);
LOOP_KEYS {
mul_m4_v3(hairmat, key->co);
@@ -1105,12 +1106,12 @@ void recalc_emitter_field(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
- DerivedMesh *dm = psys_get_modifier(object_eval, psys_eval)->dm_final;
+ Mesh *mesh = psys_get_modifier(object_eval, psys_eval)->mesh_final;
PTCacheEdit *edit = psys->edit;
float *vec, *nor;
int i, totface /*, totvert*/;
- if (!dm)
+ if (!mesh)
return;
if (edit->emitter_cosnos)
@@ -1118,7 +1119,7 @@ void recalc_emitter_field(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys
BLI_kdtree_free(edit->emitter_field);
- totface=dm->getNumTessFaces(dm);
+ totface = mesh->totface;
/*totvert=dm->getNumVerts(dm);*/ /*UNSUED*/
edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float), "emitter cosnos");
@@ -1129,23 +1130,23 @@ void recalc_emitter_field(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys
nor=vec+3;
for (i=0; i<totface; i++, vec+=6, nor+=6) {
- MFace *mface=dm->getTessFaceData(dm, i, CD_MFACE);
+ MFace *mface = &mesh->mface[i];
MVert *mvert;
- mvert=dm->getVertData(dm, mface->v1, CD_MVERT);
+ mvert = &mesh->mvert[mface->v1];
copy_v3_v3(vec, mvert->co);
VECCOPY(nor, mvert->no);
- mvert=dm->getVertData(dm, mface->v2, CD_MVERT);
+ mvert = &mesh->mvert[mface->v2];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
- mvert=dm->getVertData(dm, mface->v3, CD_MVERT);
+ mvert = &mesh->mvert[mface->v3];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
if (mface->v4) {
- mvert=dm->getVertData(dm, mface->v4, CD_MVERT);
+ mvert = &mesh->mvert[mface->v4];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
@@ -1208,12 +1209,12 @@ void update_world_cos(Depsgraph *depsgraph, Object *ob, PTCacheEdit *edit)
psys_eval = psmd_eval->psys;
}
- if (psys == 0 || psys->edit == 0 || psmd_eval->dm_final == NULL)
+ if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL)
return;
LOOP_POINTS {
if (!(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob_eval, psmd_eval->dm_final, psys->part->from, psys_eval->particles+p, hairmat);
+ psys_mat_hair_to_global(ob_eval, psmd_eval->mesh_final, psys->part->from, psys_eval->particles+p, hairmat);
LOOP_KEYS {
copy_v3_v3(key->world_co, key->co);
@@ -1860,7 +1861,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_final, psys->part->from, psys->particles + p, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
if (pset->selectmode==SCE_SELECT_POINT) {
LOOP_KEYS {
@@ -2305,7 +2306,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_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
}
}
@@ -2385,7 +2386,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
LOOP_POINTS {
LOOP_TAGGED_KEYS {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
break;
}
}
@@ -2600,7 +2601,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_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_object(ob, psmd->mesh_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);
@@ -2610,7 +2611,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_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
@@ -2845,17 +2846,17 @@ static void PE_mirror_x(
return;
psmd= psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
- const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly);
+ const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only);
/* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
BKE_mesh_tessface_ensure(me);
- /* Note: In case psys uses DM tessface indices, we mirror final DM itself, 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);
+ /* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible)
+ * mesh -> orig -> mesh tessface indices conversion... */
+ mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd->mesh_final : NULL);
if (!edit->mirror_cache)
PE_update_mirror_cache(ob, psys);
@@ -2869,7 +2870,7 @@ static void PE_mirror_x(
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_final, psys, pa, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, pa, NULL);
continue;
}
else
@@ -2882,7 +2883,7 @@ static void PE_mirror_x(
}
if (newtotpart != psys->totpart) {
- MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface;
+ MFace *mtessface = use_dm_final_indices ? psmd->mesh_final->mface : me->mface;
/* allocate new arrays and copy existing */
new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
@@ -2951,7 +2952,7 @@ static void PE_mirror_x(
}
else {
newpa->num_dmcache = psys_particle_dm_face_lookup(
- psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
+ psmd->mesh_final, psmd->mesh_deformed, newpa->num, newpa->fuv, NULL);
}
/* update edit key pointers */
@@ -2962,7 +2963,7 @@ static void PE_mirror_x(
}
/* map key positions as mirror over x axis */
- PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, pa, newpa);
newpa++;
newpoint++;
@@ -3172,7 +3173,7 @@ static void brush_puff(PEData *data, int point_index)
}
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
+ psys_mat_hair_to_global(data->ob, data->mesh, psys->part->from, psys->particles + point_index, mat);
invert_m4_m4(imat, mat);
}
else {
@@ -3367,7 +3368,7 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons
}
/* check intersection with a derivedmesh */
-static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, DerivedMesh *dm,
+static int particle_intersect_mesh(const bContext *C, Scene *scene, Object *ob, Mesh *mesh,
float *vert_cos,
const float co1[3], const float co2[3],
float *min_d, int *min_face, float *min_w,
@@ -3381,10 +3382,11 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3];
float cur_ipoint[3];
- if (dm == NULL) {
+ if (mesh == NULL) {
psys_disable_all(ob);
- dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
+ /* TODO(Sybren): port to Mesh when we have decided how to handle derivedFinal and derivedDeform */
+ DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
if (dm == NULL)
dm = mesh_get_derived_deform(depsgraph, scene, ob, 0);
@@ -3392,10 +3394,13 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
if (dm == NULL)
return 0;
+
+ mesh = BKE_id_new_nomain(ID_ME, NULL);
+ DM_to_mesh(dm, mesh, ob, CD_MASK_EVERYTHING, false);
}
/* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
+ BKE_mesh_tessface_ensure(mesh);
if (pa_minmax==0) {
@@ -3408,9 +3413,9 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
copy_v3_v3(p_max, pa_minmax+3);
}
- totface=dm->getNumTessFaces(dm);
- mface=dm->getTessFaceDataArray(dm, CD_MFACE);
- mvert=dm->getVertDataArray(dm, CD_MVERT);
+ totface = mesh->totface;
+ mface = mesh->mface;
+ mvert = mesh->mvert;
/* lets intersect the faces */
for (i=0; i<totface; i++, mface++) {
@@ -3504,7 +3509,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene= data->scene;
Object *ob= data->ob;
- DerivedMesh *dm;
+ Mesh *mesh;
PTCacheEdit *edit = data->edit;
ParticleSystem *psys= edit->psys;
ParticleData *add_pars;
@@ -3537,13 +3542,13 @@ static int brush_add(const bContext *C, PEData *data, short number)
timestep= psys_get_timestep(&sim);
- if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) {
- dm = psmd->dm_final;
+ if (psys->part->use_modifier_stack || psmd->mesh_final->runtime.deformed_only) {
+ mesh = psmd->mesh_final;
}
else {
- dm = psmd->dm_deformed;
+ mesh = psmd->mesh_deformed;
}
- BLI_assert(dm);
+ BLI_assert(mesh);
for (i=0; i<number; i++) {
if (number>1) {
@@ -3570,16 +3575,16 @@ static int brush_add(const bContext *C, PEData *data, short number)
min_d=2.0;
/* warning, returns the derived mesh face */
- if (particle_intersect_dm(C, scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
- if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
+ if (particle_intersect_mesh(C, scene, ob, mesh, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
+ if (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only) {
add_pars[n].num = add_pars[n].num_dmcache;
add_pars[n].num_dmcache = DMCACHE_ISCHILD;
}
- else if (dm == psmd->dm_deformed) {
+ else if (mesh == psmd->mesh_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,
+ psmd->mesh_final, psmd->mesh_deformed,
add_pars[n].num, add_pars[n].fuv, NULL);
}
else {
@@ -3621,7 +3626,7 @@ static int brush_add(const bContext *C, 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_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
+ psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
BLI_kdtree_insert(tree, i, cur_co);
}
@@ -3665,7 +3670,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
int w, maxw;
float maxd, totw=0.0, weight[3];
- psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
+ psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3);
maxd= ptn[maxw-1].dist;
@@ -3730,7 +3735,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
}
}
for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
invert_m4_m4(imat, hairmat);
mul_m4_v3(imat, hkey->co);
}
@@ -3922,7 +3927,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_PUFF:
{
if (edit->psys) {
- data.dm= psmd->dm_final;
+ data.mesh = psmd->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
data.select= selected;
@@ -3978,7 +3983,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_WEIGHT:
{
if (edit->psys) {
- data.dm= psmd->dm_final;
+ data.mesh = psmd->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
@@ -4325,7 +4330,7 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
LOOP_VISIBLE_POINTS {
if (psys)
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
LOOP_SELECTED_KEYS {
copy_v3_v3(co, key->co);
@@ -4363,7 +4368,7 @@ void PE_create_particle_edit(
}
/* no psmd->dm happens in case particle system modifier is not enabled */
- if (!(psys && psmd_eval && psmd_eval->dm_final) && !cache)
+ if (!(psys && psmd_eval && psmd_eval->mesh_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 79d52abb32d..cb7c90a6c3d 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
@@ -48,6 +49,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -574,7 +576,7 @@ static void disconnect_hair(
point++;
}
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
mul_m4_v3(hairmat, key->co);
@@ -653,13 +655,13 @@ static bool remap_hair_emitter(
MFace *mface = NULL, *mf;
MEdge *medge = NULL, *me;
MVert *mvert;
- DerivedMesh *dm, *target_dm;
+ Mesh *mesh, *target_mesh;
int numverts;
int i, k;
float from_ob_imat[4][4], to_ob_imat[4][4];
float from_imat[4][4], to_imat[4][4];
- if (!target_psmd->dm_final)
+ if (!target_psmd->mesh_final)
return false;
if (!psys->part || psys->part->type != PART_HAIR)
return false;
@@ -673,40 +675,46 @@ static bool remap_hair_emitter(
invert_m4_m4(from_imat, from_mat);
invert_m4_m4(to_imat, to_mat);
- if (target_psmd->dm_final->deformedOnly) {
+ if (target_psmd->mesh_final->runtime.deformed_only) {
/* we don't want to mess up target_psmd->dm when converting to global coordinates below */
- dm = target_psmd->dm_final;
+ mesh = target_psmd->mesh_final;
}
else {
- dm = target_psmd->dm_deformed;
+ mesh = target_psmd->mesh_deformed;
}
- target_dm = target_psmd->dm_final;
- if (dm == NULL) {
+ target_mesh = target_psmd->mesh_final;
+ if (mesh == NULL) {
return false;
}
/* don't modify the original vertices */
- dm = CDDM_copy(dm);
+ BKE_id_copy_ex(
+ NULL, &mesh->id, (ID **)&mesh,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
/* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
+ BKE_mesh_tessface_ensure(mesh);
- numverts = dm->getNumVerts(dm);
- mvert = dm->getVertArray(dm);
+ numverts = mesh->totvert;
+ mvert = mesh->mvert;
/* convert to global coordinates */
for (i=0; i<numverts; i++)
mul_m4_v3(to_mat, mvert[i].co);
- if (dm->getNumTessFaces(dm) != 0) {
- mface = dm->getTessFaceArray(dm);
- bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_FACES, 2);
+ if (mesh->totface != 0) {
+ mface = mesh->mface;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2);
}
- else if (dm->getNumEdges(dm) != 0) {
- medge = dm->getEdgeArray(dm);
- bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_EDGES, 2);
+ else if (mesh->totedge != 0) {
+ medge = mesh->medge;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2);
}
else {
- dm->release(dm);
+ BKE_id_free(NULL, mesh);
return false;
}
@@ -751,7 +759,7 @@ static bool remap_hair_emitter(
tpa->foffset = 0.0f;
tpa->num = nearest.index;
- tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL);
+ tpa->num_dmcache = psys_particle_dm_face_lookup(target_mesh, mesh, tpa->num, tpa->fuv, NULL);
}
else {
me = &medge[nearest.index];
@@ -777,7 +785,7 @@ static bool remap_hair_emitter(
copy_m4_m4(imat, target_ob->obmat);
else {
/* note: using target_dm here, which is in target_ob object space and has full modifiers */
- psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat);
+ psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat);
invert_m4_m4(imat, hairmat);
}
mul_m4_m4m4(imat, imat, to_imat);
@@ -823,7 +831,7 @@ static bool remap_hair_emitter(
}
free_bvhtree_from_mesh(&bvhtree);
- dm->release(dm);
+ BKE_id_free(NULL, mesh);
psys_free_path_cache(target_psys, target_edit);
@@ -994,7 +1002,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
ModifierData *md;
ParticleSystem *psys_start = NULL, *psys, *psys_from;
ParticleSystem **tmp_psys;
- DerivedMesh *final_dm;
+ Mesh *final_mesh;
CustomDataMask cdmask;
int i, totpsys;
@@ -1036,8 +1044,11 @@ static bool copy_particle_systems_to_object(const bContext *C,
psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
/* get the DM (psys and their modifiers have not been appended yet) */
- final_dm = mesh_get_derived_final(depsgraph, scene, ob_to, cdmask);
-
+ /* TODO(Sybren): use mesh_evaluated instead */
+ DerivedMesh *final_dm = mesh_get_derived_final(depsgraph, scene, ob_to, cdmask);
+ final_mesh = BKE_id_new_nomain(ID_ME, NULL);
+ DM_to_mesh(final_dm, final_mesh, ob_to, CD_MASK_EVERYTHING, false);
+
/* now append psys to the object and make modifiers */
for (i = 0, psys_from = PSYS_FROM_FIRST;
i < totpsys;
@@ -1060,10 +1071,17 @@ static bool copy_particle_systems_to_object(const bContext *C,
modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
psmd->psys = psys;
- psmd->dm_final = CDDM_copy(final_dm);
- CDDM_calc_normals(psmd->dm_final);
- DM_ensure_tessface(psmd->dm_final);
-
+ BKE_id_copy_ex(
+ NULL, &final_mesh->id, (ID **)&psmd->mesh_final,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
+
+ BKE_mesh_calc_normals(psmd->mesh_final);
+ BKE_mesh_tessface_ensure(psmd->mesh_final);
+
if (psys_from->edit) {
copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from);
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 3c026f71769..12229b8c940 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2027,7 +2027,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_final, psys->part->from, psys->particles + i, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_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) {
@@ -2105,7 +2105,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_final, psys->part->from, psys->particles + i, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + i, mat);
invert_m4_m4(imat, mat);
for (k = 0, key = point->keys; k < point->totkey; k++, key++) {