Fix a crash with duplivert, and move to evaluated mesh in object_dupli.c

There are still lots of issues/TODOs here though, like missing 'cage'
for editmesh, etc.
This commit is contained in:
Bastien Montagne 2018-09-13 15:55:36 +02:00
parent 3d2f596d94
commit 3e6f37b936
1 changed files with 33 additions and 57 deletions

View File

@ -44,18 +44,19 @@
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
#include "BKE_animsys.h"
#include "BKE_collection.h"
#include "BKE_DerivedMesh.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_iterators.h"
#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@ -389,7 +390,7 @@ static const DupliGenerator gen_dupli_frames = {
/* OB_DUPLIVERTS */
typedef struct VertexDupliData {
DerivedMesh *dm;
Mesh *me_eval;
BMEditMesh *edit_btmesh;
int totvert;
float (*orco)[3];
@ -459,37 +460,15 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
static void make_child_duplis_verts(const DupliContext *ctx, void *userdata, Object *child)
{
VertexDupliData *vdd = userdata;
DerivedMesh *dm = vdd->dm;
Mesh *me_eval = vdd->me_eval;
vdd->inst_ob = child;
invert_m4_m4(child->imat, child->obmat);
/* relative transform from parent to child space */
mul_m4_m4m4(vdd->child_imat, child->imat, ctx->object->obmat);
if (vdd->edit_btmesh) {
dm->foreachMappedVert(dm, vertex_dupli__mapFunc, vdd,
vdd->use_rotation ? DM_FOREACH_USE_NORMAL : 0);
}
else {
int a, totvert = vdd->totvert;
float vec[3], no[3];
if (vdd->use_rotation) {
for (a = 0; a < totvert; a++) {
dm->getVertCo(dm, a, vec);
dm->getVertNo(dm, a, no);
vertex_dupli__mapFunc(vdd, a, vec, no, NULL);
}
}
else {
for (a = 0; a < totvert; a++) {
dm->getVertCo(dm, a, vec);
vertex_dupli__mapFunc(vdd, a, vec, NULL, NULL);
}
}
}
BKE_mesh_foreach_mapped_vert(me_eval, vertex_dupli__mapFunc, vdd,
vdd->use_rotation ? MESH_FOREACH_USE_NORMAL : 0);
}
static void make_duplis_verts(const DupliContext *ctx)
@ -504,32 +483,31 @@ static void make_duplis_verts(const DupliContext *ctx)
/* gather mesh info */
{
Mesh *me = parent->data;
BMEditMesh *em = BKE_editmesh_from_object(parent);
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH);
vdd.edit_btmesh = BKE_editmesh_from_object(parent);
if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER) {
vdd.dm = mesh_create_derived_render(ctx->depsgraph, scene, parent, dm_mask);
}
else if (em) {
vdd.dm = editbmesh_get_derived_cage(ctx->depsgraph, scene, parent, em, dm_mask);
/* We do not need any render-smecific handling anymore, depsgraph takes care of that. */
if (vdd.edit_btmesh != NULL) {
/* XXX TODO replace with equivalent of editbmesh_get_derived_cage when available. */
vdd.me_eval = mesh_get_eval_deform(ctx->depsgraph, scene, parent, dm_mask);
}
else {
vdd.dm = mesh_get_derived_final(ctx->depsgraph, scene, parent, dm_mask);
vdd.me_eval = mesh_get_eval_final(ctx->depsgraph, scene, parent, dm_mask);
}
vdd.edit_btmesh = me->edit_btmesh;
if (use_texcoords)
vdd.orco = vdd.dm->getVertDataArray(vdd.dm, CD_ORCO);
else
if (use_texcoords) {
vdd.orco = CustomData_get_layer(&vdd.me_eval->vdata, CD_ORCO);
}
else {
vdd.orco = NULL;
}
vdd.totvert = vdd.dm->getNumVerts(vdd.dm);
vdd.totvert = vdd.me_eval->totvert;
}
make_child_duplis(ctx, &vdd, make_child_duplis_verts);
vdd.dm->release(vdd.dm);
vdd.me_eval = NULL;
}
static const DupliGenerator gen_dupli_verts = {
@ -654,7 +632,7 @@ static const DupliGenerator gen_dupli_verts_font = {
/* OB_DUPLIFACES */
typedef struct FaceDupliData {
DerivedMesh *dm;
Mesh *me_eval;
int totface;
MPoly *mpoly;
MLoop *mloop;
@ -778,36 +756,34 @@ static void make_duplis_faces(const DupliContext *ctx)
BMEditMesh *em = BKE_editmesh_from_object(parent);
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH);
if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER) {
fdd.dm = mesh_create_derived_render(ctx->depsgraph, scene, parent, dm_mask);
}
else if (em) {
fdd.dm = editbmesh_get_derived_cage(ctx->depsgraph, scene, parent, em, dm_mask);
/* We do not need any render-smecific handling anymore, depsgraph takes care of that. */
if (em != NULL) {
/* XXX TODO replace with equivalent of editbmesh_get_derived_cage when available. */
fdd.me_eval = mesh_get_eval_deform(ctx->depsgraph, scene, parent, dm_mask);
}
else {
fdd.dm = mesh_get_derived_final(ctx->depsgraph, scene, parent, dm_mask);
fdd.me_eval = mesh_get_eval_final(ctx->depsgraph, scene, parent, dm_mask);
}
if (use_texcoords) {
CustomData *ml_data = fdd.dm->getLoopDataLayout(fdd.dm);
const int uv_idx = CustomData_get_render_layer(ml_data, CD_MLOOPUV);
fdd.orco = fdd.dm->getVertDataArray(fdd.dm, CD_ORCO);
fdd.mloopuv = CustomData_get_layer_n(ml_data, CD_MLOOPUV, uv_idx);
fdd.orco = CustomData_get_layer(&fdd.me_eval->vdata, CD_ORCO);
const int uv_idx = CustomData_get_render_layer(&fdd.me_eval->ldata, CD_MLOOPUV);
fdd.mloopuv = CustomData_get_layer_n(&fdd.me_eval->ldata, CD_MLOOPUV, uv_idx);
}
else {
fdd.orco = NULL;
fdd.mloopuv = NULL;
}
fdd.totface = fdd.dm->getNumPolys(fdd.dm);
fdd.mpoly = fdd.dm->getPolyArray(fdd.dm);
fdd.mloop = fdd.dm->getLoopArray(fdd.dm);
fdd.mvert = fdd.dm->getVertArray(fdd.dm);
fdd.totface = fdd.me_eval->totpoly;
fdd.mpoly = fdd.me_eval->mpoly;
fdd.mloop = fdd.me_eval->mloop;
fdd.mvert = fdd.me_eval->mvert;
}
make_child_duplis(ctx, &fdd, make_child_duplis_faces);
fdd.dm->release(fdd.dm);
fdd.me_eval = NULL;
}
static const DupliGenerator gen_dupli_faces = {