forked from bartvdbraak/blender
Skip hidden elements in PBVH iterator, raycast, and drawing.
This commit is contained in:
parent
8717e35db3
commit
521e724edd
@ -32,17 +32,19 @@
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
enum MultiresModifiedFlags;
|
||||
struct DerivedMesh;
|
||||
struct Mesh;
|
||||
struct GridHidden;
|
||||
struct MDisps;
|
||||
struct MFace;
|
||||
struct Mesh;
|
||||
struct ModifierData;
|
||||
struct Multires;
|
||||
struct MultiresModifierData;
|
||||
struct ModifierData;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct MDisps;
|
||||
|
||||
void multires_mark_as_modified(struct Object *ob);
|
||||
void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags);
|
||||
|
||||
void multires_force_update(struct Object *ob);
|
||||
void multires_force_render_update(struct Object *ob);
|
||||
@ -50,6 +52,7 @@ void multires_force_external_reload(struct Object *ob);
|
||||
|
||||
/* internal, only called in subsurf_ccg.c */
|
||||
void multires_modifier_update_mdisps(struct DerivedMesh *dm);
|
||||
void multires_modifier_update_hidden(struct DerivedMesh *dm);
|
||||
|
||||
void multiresModifier_set_levels_from_disps(struct MultiresModifierData *mmd, struct Object *ob);
|
||||
|
||||
|
@ -71,6 +71,14 @@ int ccg_gridsize(int level);
|
||||
of this function to convert to grid coordinates at 'high_level' */
|
||||
int ccg_factor(int low_level, int high_level);
|
||||
|
||||
typedef enum MultiresModifiedFlags {
|
||||
/* indicates the grids have been sculpted on, so MDisps
|
||||
have to be updated */
|
||||
MULTIRES_COORDS_MODIFIED = 1,
|
||||
/* indicates elements have been hidden or unhidden */
|
||||
MULTIRES_HIDDEN_MODIFIED = 2
|
||||
} MultiresModifiedFlags;
|
||||
|
||||
/**************************** Internal *****************************/
|
||||
|
||||
typedef struct CCGDerivedMesh {
|
||||
@ -112,7 +120,7 @@ typedef struct CCGDerivedMesh {
|
||||
float (*orco)[3];
|
||||
|
||||
struct Object *ob;
|
||||
int modified;
|
||||
MultiresModifiedFlags modified_flags;
|
||||
} multires;
|
||||
|
||||
struct EdgeHash *ehash;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_pbvh.h"
|
||||
@ -76,6 +77,180 @@ typedef enum {
|
||||
static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert);
|
||||
static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, DispOp op, DMGridData **oldGridData, int totlvl);
|
||||
|
||||
/** Grid hiding **/
|
||||
static BLI_bitmap multires_mdisps_upsample_hidden(BLI_bitmap lo_hidden,
|
||||
int lo_level,
|
||||
int hi_level,
|
||||
|
||||
/* assumed to be at hi_level (or
|
||||
null) */
|
||||
BLI_bitmap prev_hidden)
|
||||
{
|
||||
BLI_bitmap subd;
|
||||
int hi_gridsize = ccg_gridsize(hi_level);
|
||||
int lo_gridsize = ccg_gridsize(lo_level);
|
||||
int yh, xh, xl, yl, xo, yo, hi_ndx;
|
||||
int offset, factor;
|
||||
|
||||
BLI_assert(lo_level <= hi_level);
|
||||
|
||||
/* fast case */
|
||||
if(lo_level == hi_level)
|
||||
return MEM_dupallocN(lo_hidden);
|
||||
|
||||
subd = BLI_BITMAP_NEW(hi_gridsize * hi_gridsize, "MDisps.hidden upsample");
|
||||
|
||||
factor = ccg_factor(lo_level, hi_level);
|
||||
offset = 1 << (hi_level - lo_level - 1);
|
||||
|
||||
/* low-res blocks */
|
||||
for(yl = 0; yl < lo_gridsize; yl++) {
|
||||
for(xl = 0; xl < lo_gridsize; xl++) {
|
||||
int lo_val = BLI_BITMAP_GET(lo_hidden, yl * lo_gridsize + xl);
|
||||
|
||||
/* high-res blocks */
|
||||
for(yo = -offset; yo <= offset; yo++) {
|
||||
yh = yl * factor + yo;
|
||||
if(yh < 0 || yh >= hi_gridsize)
|
||||
continue;
|
||||
|
||||
for(xo = -offset; xo <= offset; xo++) {
|
||||
xh = xl * factor + xo;
|
||||
if(xh < 0 || xh >= hi_gridsize)
|
||||
continue;
|
||||
|
||||
hi_ndx = yh * hi_gridsize + xh;
|
||||
|
||||
if(prev_hidden) {
|
||||
/* If prev_hidden is available, copy it to
|
||||
subd, except when the equivalent element in
|
||||
lo_hidden is different */
|
||||
if(lo_val != prev_hidden[hi_ndx])
|
||||
BLI_BITMAP_MODIFY(subd, hi_ndx, lo_val);
|
||||
else
|
||||
BLI_BITMAP_MODIFY(subd, hi_ndx, prev_hidden[hi_ndx]);
|
||||
}
|
||||
else {
|
||||
BLI_BITMAP_MODIFY(subd, hi_ndx, lo_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subd;
|
||||
}
|
||||
|
||||
static BLI_bitmap multires_mdisps_downsample_hidden(BLI_bitmap old_hidden,
|
||||
int old_level,
|
||||
int new_level)
|
||||
{
|
||||
BLI_bitmap new_hidden;
|
||||
int new_gridsize = ccg_gridsize(new_level);
|
||||
int old_gridsize = ccg_gridsize(old_level);
|
||||
int x, y, factor, old_value;
|
||||
|
||||
BLI_assert(new_level <= old_level);
|
||||
factor = ccg_factor(new_level, old_level);
|
||||
new_hidden = BLI_BITMAP_NEW(new_gridsize * new_gridsize,
|
||||
"downsample hidden");
|
||||
|
||||
|
||||
|
||||
for(y = 0; y < new_gridsize; y++) {
|
||||
for(x = 0; x < new_gridsize; x++) {
|
||||
old_value = BLI_BITMAP_GET(old_hidden,
|
||||
factor*y*old_gridsize + x*factor);
|
||||
|
||||
BLI_BITMAP_MODIFY(new_hidden, y*new_gridsize + x, old_value);
|
||||
}
|
||||
}
|
||||
|
||||
return new_hidden;
|
||||
}
|
||||
|
||||
static void multires_output_hidden_to_ccgdm(CCGDerivedMesh *ccgdm,
|
||||
Mesh *me, int level)
|
||||
{
|
||||
const MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
|
||||
BLI_bitmap *grid_hidden = ccgdm->gridHidden;
|
||||
int *gridOffset;
|
||||
int i, j;
|
||||
|
||||
gridOffset = ccgdm->dm.getGridOffset(&ccgdm->dm);
|
||||
|
||||
for (i = 0; i < me->totpoly; i++) {
|
||||
for (j = 0; j < me->mpoly[i].totloop; j++) {
|
||||
int g = gridOffset[i] + j;
|
||||
const MDisps *md = &mdisps[g];
|
||||
BLI_bitmap gh = md->hidden;
|
||||
|
||||
if (gh) {
|
||||
grid_hidden[g] =
|
||||
multires_mdisps_downsample_hidden(gh, md->level, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* subdivide mdisps.hidden if needed (assumes that md.level reflects
|
||||
the current level of md.hidden) */
|
||||
static void multires_mdisps_subdivide_hidden(MDisps *md, int new_level)
|
||||
{
|
||||
BLI_bitmap subd;
|
||||
|
||||
BLI_assert(md->hidden);
|
||||
|
||||
/* nothing to do if already subdivided enough */
|
||||
if(md->level >= new_level)
|
||||
return;
|
||||
|
||||
subd = multires_mdisps_upsample_hidden(md->hidden,
|
||||
md->level,
|
||||
new_level,
|
||||
NULL);
|
||||
|
||||
/* swap in the subdivided data */
|
||||
MEM_freeN(md->hidden);
|
||||
md->hidden = subd;
|
||||
}
|
||||
|
||||
static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level)
|
||||
{
|
||||
MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS,
|
||||
CD_CALLOC, 0, me->totloop);
|
||||
int gridsize = ccg_gridsize(level);
|
||||
int gridarea = gridsize * gridsize;
|
||||
int i, j, k;
|
||||
|
||||
for (i = 0; i < me->totpoly; i++) {
|
||||
int hide = 0;
|
||||
|
||||
for (j = 0; j < me->mpoly[i].totloop; j++) {
|
||||
if(me->mvert[me->mloop[me->mpoly[i].loopstart + j].v].flag & ME_HIDE) {
|
||||
hide = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!hide)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < me->mpoly[i].totloop; j++) {
|
||||
MDisps *md = &mdisps[me->mpoly[i].loopstart + j];
|
||||
|
||||
BLI_assert(!md->hidden);
|
||||
|
||||
md->hidden = BLI_BITMAP_NEW(gridarea, "MDisps.hidden initialize");
|
||||
|
||||
for(k = 0; k < gridarea; k++)
|
||||
BLI_BITMAP_SET(md->hidden, k);
|
||||
}
|
||||
}
|
||||
|
||||
return mdisps;
|
||||
}
|
||||
|
||||
DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob)
|
||||
{
|
||||
ModifierData *md= (ModifierData *)mmd;
|
||||
@ -156,16 +331,16 @@ static void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lv
|
||||
mmd->renderlvl = CLAMPIS(MAX2(mmd->renderlvl, lvl), 0, mmd->totlvl);
|
||||
}
|
||||
|
||||
static void multires_dm_mark_as_modified(DerivedMesh *dm)
|
||||
static void multires_dm_mark_as_modified(DerivedMesh *dm, MultiresModifiedFlags flags)
|
||||
{
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm;
|
||||
ccgdm->multires.modified = 1;
|
||||
ccgdm->multires.modified_flags |= flags;
|
||||
}
|
||||
|
||||
void multires_mark_as_modified(Object *ob)
|
||||
void multires_mark_as_modified(Object *ob, MultiresModifiedFlags flags)
|
||||
{
|
||||
if (ob && ob->derivedFinal)
|
||||
multires_dm_mark_as_modified(ob->derivedFinal);
|
||||
multires_dm_mark_as_modified(ob->derivedFinal, flags);
|
||||
}
|
||||
|
||||
void multires_force_update(Object *ob)
|
||||
@ -205,7 +380,7 @@ int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd,
|
||||
if (mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) {
|
||||
multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm));
|
||||
|
||||
multires_dm_mark_as_modified(mrdm);
|
||||
multires_dm_mark_as_modified(mrdm, MULTIRES_COORDS_MODIFIED);
|
||||
multires_force_update(ob);
|
||||
|
||||
mrdm->release(mrdm);
|
||||
@ -336,6 +511,9 @@ static void multires_reallocate_mdisps(int totloop, MDisps *mdisps, int lvl)
|
||||
|
||||
if (mdisps[i].disps)
|
||||
MEM_freeN(mdisps[i].disps);
|
||||
|
||||
if (mdisps[i].level && mdisps[i].hidden)
|
||||
multires_mdisps_subdivide_hidden(&mdisps[i], lvl);
|
||||
|
||||
mdisps[i].disps = disps;
|
||||
mdisps[i].totdisp = totdisp;
|
||||
@ -421,6 +599,14 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
|
||||
hdisps = mdisp->disps;
|
||||
|
||||
multires_copy_grid(ndisps, hdisps, nsize, hsize);
|
||||
if (mdisp->hidden) {
|
||||
BLI_bitmap gh =
|
||||
multires_mdisps_downsample_hidden(mdisp->hidden,
|
||||
mdisp->level,
|
||||
lvl);
|
||||
MEM_freeN(mdisp->hidden);
|
||||
mdisp->hidden = gh;
|
||||
}
|
||||
|
||||
ndisps += nsize*nsize;
|
||||
hdisps += hsize*hsize;
|
||||
@ -637,7 +823,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
|
||||
|
||||
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
|
||||
if (!mdisps)
|
||||
mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_DEFAULT, NULL, me->totloop);
|
||||
mdisps = multires_mdisps_initialize_hidden(me, totlvl);
|
||||
|
||||
if (mdisps->disps && !updateblock && totlvl > 1) {
|
||||
/* upsample */
|
||||
@ -940,6 +1126,37 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm)
|
||||
}
|
||||
}
|
||||
|
||||
void multires_modifier_update_hidden(DerivedMesh *dm)
|
||||
{
|
||||
CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
|
||||
BLI_bitmap *grid_hidden= ccgdm->gridHidden;
|
||||
Mesh *me = ccgdm->multires.ob->data;
|
||||
MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
|
||||
int totlvl = ccgdm->multires.totlvl;
|
||||
int lvl = ccgdm->multires.lvl;
|
||||
|
||||
if(mdisps) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < me->totloop; i++) {
|
||||
MDisps *md = &mdisps[i];
|
||||
BLI_bitmap gh = grid_hidden[i];
|
||||
|
||||
if(!gh && md->hidden) {
|
||||
MEM_freeN(md->hidden);
|
||||
md->hidden = NULL;
|
||||
}
|
||||
else if(gh) {
|
||||
gh = multires_mdisps_upsample_hidden(gh, lvl, totlvl,
|
||||
md->hidden);
|
||||
if(md->hidden)
|
||||
MEM_freeN(md->hidden);
|
||||
|
||||
md->hidden = gh;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to)
|
||||
{
|
||||
@ -1092,7 +1309,7 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
DerivedMesh *result;
|
||||
CCGDerivedMesh *ccgdm;
|
||||
CCGDerivedMesh *ccgdm = NULL;
|
||||
DMGridData **gridData, **subGridData;
|
||||
int lvl= multires_get_level(ob, mmd, useRenderParams);
|
||||
int i, gridSize, numGrids;
|
||||
@ -1112,7 +1329,7 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca
|
||||
ccgdm->multires.local_mmd = local_mmd;
|
||||
ccgdm->multires.lvl = lvl;
|
||||
ccgdm->multires.totlvl = mmd->totlvl;
|
||||
ccgdm->multires.modified = 0;
|
||||
ccgdm->multires.modified_flags = 0;
|
||||
}
|
||||
|
||||
numGrids = result->getNumGrids(result);
|
||||
@ -1132,6 +1349,10 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca
|
||||
/*run displacement*/
|
||||
multiresModifier_disp_run(result, ob->data, dm, APPLY_DISPLACEMENTS, subGridData, mmd->totlvl);
|
||||
|
||||
/* copy hidden elements for this level */
|
||||
if(ccgdm)
|
||||
multires_output_hidden_to_ccgdm(ccgdm, me, lvl);
|
||||
|
||||
for (i = 0; i < numGrids; i++)
|
||||
MEM_freeN(subGridData[i]);
|
||||
MEM_freeN(subGridData);
|
||||
@ -1753,7 +1974,7 @@ void multires_load_old(Object *ob, Mesh *me)
|
||||
|
||||
multires_load_old_dm(dm, me, mmd->totlvl+1);
|
||||
|
||||
multires_dm_mark_as_modified(dm);
|
||||
multires_dm_mark_as_modified(dm, MULTIRES_COORDS_MODIFIED);
|
||||
dm->release(dm);
|
||||
orig->release(orig);
|
||||
|
||||
|
@ -2341,12 +2341,18 @@ static void ccgDM_release(DerivedMesh *dm)
|
||||
|
||||
if (DM_release(dm)) {
|
||||
/* Before freeing, need to update the displacement map */
|
||||
if(ccgdm->multires.modified) {
|
||||
if(ccgdm->multires.modified_flags) {
|
||||
/* Check that mmd still exists */
|
||||
if(!ccgdm->multires.local_mmd && BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0)
|
||||
if(!ccgdm->multires.local_mmd &&
|
||||
BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0)
|
||||
ccgdm->multires.mmd = NULL;
|
||||
if(ccgdm->multires.mmd)
|
||||
multires_modifier_update_mdisps(dm);
|
||||
|
||||
if(ccgdm->multires.mmd) {
|
||||
if(ccgdm->multires.modified_flags & MULTIRES_COORDS_MODIFIED)
|
||||
multires_modifier_update_mdisps(dm);
|
||||
if(ccgdm->multires.modified_flags & MULTIRES_HIDDEN_MODIFIED)
|
||||
multires_modifier_update_hidden(dm);
|
||||
}
|
||||
}
|
||||
|
||||
if (ccgdm->ehash)
|
||||
@ -2815,7 +2821,7 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
|
||||
|
||||
ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
|
||||
BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
|
||||
numGrids, gridSize, (void**)ccgdm->gridFaces, ccgdm->gridFlagMats);
|
||||
numGrids, gridSize, (void**)ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden);
|
||||
} else if(ob->type == OB_MESH) {
|
||||
Mesh *me= ob->data;
|
||||
ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
|
||||
|
@ -57,7 +57,8 @@ void BLI_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
|
||||
int totface, int totvert);
|
||||
void BLI_pbvh_build_grids(PBVH *bvh, struct DMGridData **grids,
|
||||
struct DMGridAdjacency *gridadj, int totgrid,
|
||||
int gridsize, void **gridfaces, struct DMFlagMat *flagmats);
|
||||
int gridsize, void **gridfaces, struct DMFlagMat *flagmats,
|
||||
unsigned int **grid_hidden);
|
||||
void BLI_pbvh_free(PBVH *bvh);
|
||||
|
||||
/* Hierarchical Search in the BVH, two methods:
|
||||
@ -97,6 +98,9 @@ typedef enum {
|
||||
|
||||
PBVHType BLI_pbvh_type(const PBVH *bvh);
|
||||
|
||||
/* multires hidden data, only valid for type == PBVH_GRIDS */
|
||||
unsigned int **BLI_pbvh_grid_hidden(const PBVH *bvh);
|
||||
|
||||
/* Node Access */
|
||||
|
||||
typedef enum {
|
||||
|
@ -141,6 +141,7 @@ struct PBVH {
|
||||
const DMFlagMat *grid_flag_mats;
|
||||
int totgrid;
|
||||
int gridsize;
|
||||
BLI_bitmap *grid_hidden;
|
||||
|
||||
/* Only used during BVH build and update,
|
||||
* don't need to remain valid after */
|
||||
@ -639,7 +640,7 @@ void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int
|
||||
|
||||
/* Do a full rebuild with on Grids data structure */
|
||||
void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridadj,
|
||||
int totgrid, int gridsize, void **gridfaces, DMFlagMat *flagmats)
|
||||
int totgrid, int gridsize, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap *grid_hidden)
|
||||
{
|
||||
BBC *prim_bbc = NULL;
|
||||
BB cb;
|
||||
@ -652,6 +653,7 @@ void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridad
|
||||
bvh->grid_flag_mats= flagmats;
|
||||
bvh->totgrid= totgrid;
|
||||
bvh->gridsize= gridsize;
|
||||
bvh->grid_hidden= grid_hidden;
|
||||
bvh->leaf_limit = MAX2(LEAF_LIMIT/((gridsize-1)*(gridsize-1)), 1);
|
||||
|
||||
BB_reset(&cb);
|
||||
@ -1284,6 +1286,12 @@ PBVHType BLI_pbvh_type(const PBVH *bvh)
|
||||
return bvh->type;
|
||||
}
|
||||
|
||||
BLI_bitmap *BLI_pbvh_grid_hidden(const PBVH *bvh)
|
||||
{
|
||||
BLI_assert(bvh->type == PBVH_GRIDS);
|
||||
return bvh->grid_hidden;
|
||||
}
|
||||
|
||||
/***************************** Node Access ***********************************/
|
||||
|
||||
void BLI_pbvh_node_mark_update(PBVHNode *node)
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_lattice.h" /* for armature_deform_verts */
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_subsurf.h"
|
||||
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
@ -3346,7 +3347,7 @@ static void sculpt_flush_update(bContext *C)
|
||||
MultiresModifierData *mmd = ss->multires;
|
||||
|
||||
if(mmd)
|
||||
multires_mark_as_modified(ob);
|
||||
multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
|
||||
if(ob->derivedFinal) /* VBO no longer valid */
|
||||
GPU_drawobject_free(ob->derivedFinal);
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_subsurf.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
@ -209,7 +210,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
|
||||
BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateRedraw, NULL);
|
||||
|
||||
if((mmd=sculpt_multires_active(scene, ob)))
|
||||
multires_mark_as_modified(ob);
|
||||
multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
|
||||
|
||||
tag_update= ((Mesh*)ob->data)->id.us > 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user