EditMesh: Avoid creating deform-vert layer every redraw

Getting a new edit-derived-bmesh was always creating a deform-vert array, even when it wasn't needed.
Since this was called on redraw, in many cases it was doing it unnecessarily.

Now pass in a custom-data mask and only fill in deform-verts when needed.

Gives noticeable drawing speedup (~10-30% here).
This commit is contained in:
Campbell Barton 2016-06-22 21:20:09 +10:00
parent 493c6b622f
commit b204bdad47
5 changed files with 63 additions and 22 deletions

View File

@ -694,7 +694,7 @@ DerivedMesh *mesh_create_derived_render(
CustomDataMask dataMask);
DerivedMesh *getEditDerivedBMesh(
struct BMEditMesh *em, struct Object *ob,
struct BMEditMesh *em, struct Object *ob, CustomDataMask data_mask,
float (*vertexCos)[3]);
DerivedMesh *mesh_create_derived_index_render(
@ -723,7 +723,7 @@ DerivedMesh *mesh_create_derived_physics(
CustomDataMask dataMask);
DerivedMesh *editbmesh_get_derived_base(
struct Object *, struct BMEditMesh *em);
struct Object *ob, struct BMEditMesh *em, CustomDataMask data_mask);
DerivedMesh *editbmesh_get_derived_cage(
struct Scene *scene, struct Object *,
struct BMEditMesh *em, CustomDataMask dataMask);

View File

@ -1433,10 +1433,12 @@ static void calc_weightpaint_vert_array(
Object *ob, DerivedMesh *dm, int const draw_flag, DMWeightColorInfo *dm_wcinfo,
unsigned char (*r_wtcol_v)[4])
{
MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
int numVerts = dm->getNumVerts(dm);
BMEditMesh *em = (dm->type == DM_TYPE_EDITBMESH) ? BKE_editmesh_from_object(ob) : NULL;
const int numVerts = dm->getNumVerts(dm);
if (dv && (ob->actdef != 0)) {
if ((ob->actdef != 0) &&
(CustomData_has_layer(em ? &em->bm->vdata : &dm->vertData, CD_MDEFORMVERT)))
{
unsigned char (*wc)[4] = r_wtcol_v;
unsigned int i;
@ -1455,8 +1457,30 @@ static void calc_weightpaint_vert_array(
}
}
for (i = numVerts; i != 0; i--, wc++, dv++) {
calc_weightpaint_vert_color((unsigned char *)wc, dv, dm_wcinfo, defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag);
/* editmesh won't have deform verts unless modifiers require it,
* avoid having to create an array of deform-verts only for drawing
* by reading from the bmesh directly. */
if (em) {
BMIter iter;
BMVert *eve;
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
BLI_assert(cd_dvert_offset != -1);
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
const MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
calc_weightpaint_vert_color(
(unsigned char *)wc, dv, dm_wcinfo,
defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag);
wc++;
}
}
else {
const MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
for (i = numVerts; i != 0; i--, wc++, dv++) {
calc_weightpaint_vert_color(
(unsigned char *)wc, dv, dm_wcinfo,
defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag);
}
}
if (defbase_sel) {
@ -2282,7 +2306,7 @@ static void editbmesh_calc_modifiers(
modifiers_clearErrors(ob);
if (r_cage && cageIndex == -1) {
*r_cage = getEditDerivedBMesh(em, ob, NULL);
*r_cage = getEditDerivedBMesh(em, ob, dataMask, NULL);
}
md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@ -2448,7 +2472,7 @@ static void editbmesh_calc_modifiers(
}
else {
*r_cage = getEditDerivedBMesh(
em, ob,
em, ob, mask,
deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
}
}
@ -2484,7 +2508,7 @@ static void editbmesh_calc_modifiers(
}
else {
/* this is just a copy of the editmesh, no need to calc normals */
*r_final = getEditDerivedBMesh(em, ob, deformedVerts);
*r_final = getEditDerivedBMesh(em, ob, dataMask, deformedVerts);
deformedVerts = NULL;
/* In this case, we should never have weight-modifying modifiers in stack... */
@ -2847,9 +2871,9 @@ DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh
return em->derivedCage;
}
DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em, CustomDataMask data_mask)
{
return getEditDerivedBMesh(em, obedit, NULL);
return getEditDerivedBMesh(em, obedit, data_mask, NULL);
}
/***/

View File

@ -39,6 +39,7 @@
#include "DNA_meshdata_types.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BKE_crazyspace.h"
@ -275,7 +276,13 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob,
if (mti->type == eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
if (!defmats) {
dm = getEditDerivedBMesh(em, ob, NULL);
const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
CustomDataMask data_mask = CD_MASK_BAREMESH;
CDMaskLink *datamasks = modifiers_calcDataMasks(scene, ob, md, data_mask, required_mode, NULL, 0);
data_mask = datamasks->mask;
BLI_linklist_free((LinkNode *)datamasks, NULL);
dm = getEditDerivedBMesh(em, ob, data_mask, NULL);
deformedVerts = editbmesh_get_vertex_cos(em, &numVerts);
defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats");

View File

@ -2226,16 +2226,17 @@ static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
return &bmdm->em->bm->pdata;
}
/**
* \note This may be called per-draw,
* avoid allocating large arrays where possible and keep this a thin wrapper for #BMesh.
*/
DerivedMesh *getEditDerivedBMesh(
BMEditMesh *em,
Object *UNUSED(ob),
BMEditMesh *em, struct Object *UNUSED(ob),
CustomDataMask data_mask,
float (*vertexCos)[3])
{
EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
BMesh *bm = em->bm;
const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
const int cd_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
bmdm->em = em;
@ -2304,6 +2305,9 @@ DerivedMesh *getEditDerivedBMesh(
bmdm->vertexCos = (const float (*)[3])vertexCos;
bmdm->dm.deformedOnly = (vertexCos != NULL);
const int cd_dvert_offset = (data_mask & CD_MASK_MDEFORMVERT) ?
CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT) : -1;
if (cd_dvert_offset != -1) {
BMIter iter;
BMVert *eve;
@ -2317,6 +2321,9 @@ DerivedMesh *getEditDerivedBMesh(
}
}
const int cd_skin_offset = (data_mask & CD_MASK_MVERT_SKIN) ?
CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN) : -1;
if (cd_skin_offset != -1) {
BMIter iter;
BMVert *eve;

View File

@ -4250,12 +4250,15 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
if (ob == obedit || drawlinked) {
DerivedMesh *finalDM, *cageDM;
if (obedit != ob)
finalDM = cageDM = editbmesh_get_derived_base(ob, em);
else
if (obedit != ob) {
finalDM = cageDM = editbmesh_get_derived_base(
ob, em, scene->customdata_mask);
}
else {
cageDM = editbmesh_get_derived_cage_and_final(
scene, ob, em, scene->customdata_mask,
&finalDM);
}
const bool use_material = ((me->drawflag & ME_DRAWEIGHT) == 0);
@ -8480,7 +8483,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
DerivedMesh *dm = NULL, *edm = NULL;
if (ob->mode & OB_MODE_EDIT) {
edm = editbmesh_get_derived_base(ob, me->edit_btmesh);
edm = editbmesh_get_derived_base(ob, me->edit_btmesh, CD_MASK_BAREMESH);
DM_update_materials(edm, ob);
}
else {