* Added a new CustomData type for dyntopo vertex data: MDynTopoVert.

It stores:
   - Original coordiates, colors and mask (which were previously four
     seperate layers).
   - A bitmask with (currently) one bitflag, whether or not a vertex is
     on a boundary.

I needed to cache calculating vertex boundary state (which involves
iterating over the edges surrounding a vertex) and got fed up with
having so many CD layers for dyntopo.  This struct consolidates them
and saves having yet another layer just to store a flag.
This commit is contained in:
Joseph Eagar 2021-03-21 16:26:38 -07:00
parent 75a1116b51
commit 924b13b03a
16 changed files with 503 additions and 235 deletions

View File

@ -495,6 +495,7 @@ typedef struct SculptSession {
/* BMesh for dynamic topology sculpting */
struct BMesh *bm;
int cd_dyn_vert;
int cd_vert_node_offset;
int cd_face_node_offset;
int cd_vcol_offset;
@ -617,7 +618,7 @@ typedef struct SculptSession {
* Set #Main.is_memfile_undo_flush_needed when enabling.
*/
char needs_flush_to_id;
char update_boundary_info_bmesh;
} SculptSession;
void BKE_sculptsession_free(struct Object *ob);

View File

@ -224,15 +224,11 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset,
const int cd_origco_offset,
const int cd_origno_offset,
const int cd_origvcol_offset);
const int cd_dyn_vert);
void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_vert_node_offset,
const int cd_face_node_offset,
const int cd_origco_offset,
const int cd_origno_offset,
const int cd_origvcol_offset);
const int cd_dyn_vert);
void BKE_pbvh_free(PBVH *pbvh);
/** update original data, only data whose r_** parameters are passed in will be updated*/
@ -496,6 +492,7 @@ typedef struct PBVHVertexIter {
struct TableGSet *bm_unique_verts, *bm_other_verts;
struct CustomData *bm_vdata;
int cd_dyn_vert;
int cd_vert_mask_offset;
int cd_vcol_offset;
@ -511,12 +508,17 @@ typedef struct PBVHVertexIter {
bool visible;
} PBVHVertexIter;
#define BKE_PBVH_DYNVERT(cd_dyn_vert, v) ((MDynTopoVert *)BM_ELEM_CD_GET_VOID_P(v, cd_dyn_vert))
void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \
pbvh_vertex_iter_init(pbvh, node, &vi, mode); \
\
for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \
#if 0
# include "../bmesh/bmesh.h"
# include "DNA_meshdata_types.h"
# define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \
pbvh_vertex_iter_init(pbvh, node, &vi, mode); \
vi.i = vi.g = 0; \
if (vi.grids) { \
vi.width = vi.gridsize; \
vi.height = vi.gridsize; \
@ -530,87 +532,203 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi.width = vi.totvert; \
vi.height = 1; \
} \
while (BKE_pbvh_vertex_iter_step(pbvh, node, &vi, mode))
# define BKE_pbvh_vertex_iter_end ((void)0)
__attribute__((optnone)) static bool BKE_pbvh_vertex_iter_step(PBVH *pbvh,
PBVHNode *node,
PBVHVertexIter *vi,
int mode)
{
for (; vi->g < vi->totgrid; vi->g++) {
for (; vi->gy < vi->height; vi->gy++) {
for (; vi->gx < vi->width; vi->gx++, vi->i++) {
if (vi->grid) {
vi->co = CCG_elem_co(&vi->key, vi->grid);
vi->fno = CCG_elem_no(&vi->key, vi->grid);
vi->mask = vi->key.has_mask ? CCG_elem_mask(&vi->key, vi->grid) : NULL;
vi->grid = CCG_elem_next(&vi->key, vi->grid);
vi->index++;
vi->vertex.i++;
vi->visible = true;
if (vi->gh) {
if (BLI_BITMAP_TEST(vi->gh, vi->gy * vi->gridsize + vi->gx)) {
continue;
}
}
return true;
}
else if (vi->mverts) {
vi->mvert = &vi->mverts[vi->vert_indices[vi->gx]];
if (vi->respect_hide) {
vi->visible = !(vi->mvert->flag & ME_HIDE);
if (mode == PBVH_ITER_UNIQUE && !vi->visible) {
continue;
}
}
else {
BLI_assert(vi->visible);
}
vi->co = vi->mvert->co;
vi->no = vi->mvert->no;
vi->index = vi->vertex.i = vi->vert_indices[vi->i];
if (vi->vmask) {
vi->mask = &vi->vmask[vi->index];
}
if (vi->vcol) {
vi->col = vi->vcol[vi->index].color;
}
return true;
}
else {
struct BMVert *bv = 0;
while (!bv) {
if (!vi->bm_cur_set->elems || vi->bi >= vi->bm_cur_set->cur) {
if (vi->bm_cur_set != vi->bm_other_verts && mode != PBVH_ITER_UNIQUE) {
vi->bm_cur_set = vi->bm_other_verts;
vi->bi = 0;
if (!vi->bm_cur_set->elems || vi->bi >= vi->bm_other_verts->cur) {
break;
}
}
else {
break;
}
}
else {
bv = (BMVert*) vi->bm_cur_set->elems[vi->bi++];
}
}
if (!bv) {
continue;
}
vi->bm_vert = bv;
if (vi->cd_vcol_offset >= 0) {
MPropCol *vcol = (MPropCol*) BM_ELEM_CD_GET_VOID_P(bv, vi->cd_vcol_offset);
vi->col = vcol->color;
}
vi->vertex.i = (intptr_t)bv;
vi->index = BM_elem_index_get(vi->bm_vert);
vi->visible = !BM_elem_flag_test_bool(vi->bm_vert, BM_ELEM_HIDDEN);
if (mode == PBVH_ITER_UNIQUE && !vi->visible) {
continue;
}
vi->co = vi->bm_vert->co;
vi->fno = vi->bm_vert->no;
vi->mask = &BKE_PBVH_DYNVERT(vi->cd_dyn_vert, vi->bm_vert)->mask;
return true;
}
}
}
}
return false;
}
#else
# define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \
pbvh_vertex_iter_init(pbvh, node, &vi, mode); \
\
for (vi.gy = 0; vi.gy < vi.height; vi.gy++) { \
for (vi.gx = 0; vi.gx < vi.width; vi.gx++, vi.i++) { \
if (vi.grid) { \
vi.co = CCG_elem_co(&vi.key, vi.grid); \
vi.fno = CCG_elem_no(&vi.key, vi.grid); \
vi.mask = vi.key.has_mask ? CCG_elem_mask(&vi.key, vi.grid) : NULL; \
vi.grid = CCG_elem_next(&vi.key, vi.grid); \
vi.index++; \
vi.vertex.i++; \
vi.visible = true; \
if (vi.gh) { \
if (BLI_BITMAP_TEST(vi.gh, vi.gy * vi.gridsize + vi.gx)) { \
continue; \
for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \
if (vi.grids) { \
vi.width = vi.gridsize; \
vi.height = vi.gridsize; \
vi.vertex.i = vi.index = vi.grid_indices[vi.g] * vi.key.grid_area - 1; \
vi.grid = vi.grids[vi.grid_indices[vi.g]]; \
if (mode == PBVH_ITER_UNIQUE) { \
vi.gh = vi.grid_hidden[vi.grid_indices[vi.g]]; \
} \
} \
else { \
vi.width = vi.totvert; \
vi.height = 1; \
} \
\
for (vi.gy = 0; vi.gy < vi.height; vi.gy++) { \
for (vi.gx = 0; vi.gx < vi.width; vi.gx++, vi.i++) { \
if (vi.grid) { \
vi.co = CCG_elem_co(&vi.key, vi.grid); \
vi.fno = CCG_elem_no(&vi.key, vi.grid); \
vi.mask = vi.key.has_mask ? CCG_elem_mask(&vi.key, vi.grid) : NULL; \
vi.grid = CCG_elem_next(&vi.key, vi.grid); \
vi.index++; \
vi.vertex.i++; \
vi.visible = true; \
if (vi.gh) { \
if (BLI_BITMAP_TEST(vi.gh, vi.gy * vi.gridsize + vi.gx)) { \
continue; \
} \
} \
} \
} \
else if (vi.mverts) { \
vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
if (vi.respect_hide) { \
vi.visible = !(vi.mvert->flag & ME_HIDE); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
else if (vi.mverts) { \
vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
if (vi.respect_hide) { \
vi.visible = !(vi.mvert->flag & ME_HIDE); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
} \
} \
else { \
BLI_assert(vi.visible); \
} \
vi.co = vi.mvert->co; \
vi.no = vi.mvert->no; \
vi.index = vi.vertex.i = vi.vert_indices[vi.i]; \
if (vi.vmask) { \
vi.mask = &vi.vmask[vi.index]; \
} \
if (vi.vcol) { \
vi.col = vi.vcol[vi.index].color; \
} \
} \
else { \
BLI_assert(vi.visible); \
} \
vi.co = vi.mvert->co; \
vi.no = vi.mvert->no; \
vi.index = vi.vertex.i = vi.vert_indices[vi.i]; \
if (vi.vmask) { \
vi.mask = &vi.vmask[vi.index]; \
} \
if (vi.vcol) { \
vi.col = vi.vcol[vi.index].color; \
} \
} \
else { \
BMVert *bv = NULL; \
while (!bv) { \
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_cur_set->cur) { \
if (vi.bm_cur_set != vi.bm_other_verts && mode != PBVH_ITER_UNIQUE) { \
vi.bm_cur_set = vi.bm_other_verts; \
vi.bi = 0; \
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_other_verts->cur) { \
BMVert *bv = NULL; \
while (!bv) { \
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_cur_set->cur) { \
if (vi.bm_cur_set != vi.bm_other_verts && mode != PBVH_ITER_UNIQUE) { \
vi.bm_cur_set = vi.bm_other_verts; \
vi.bi = 0; \
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_other_verts->cur) { \
break; \
} \
} \
else { \
break; \
} \
} \
else { \
break; \
bv = vi.bm_cur_set->elems[vi.bi++]; \
} \
} \
else { \
bv = vi.bm_cur_set->elems[vi.bi++]; \
if (!bv) { \
continue; \
} \
} \
if (!bv) { \
continue; \
} \
vi.bm_vert = bv; \
if (vi.cd_vcol_offset >= 0) { \
MPropCol *vcol = BM_ELEM_CD_GET_VOID_P(bv, vi.cd_vcol_offset); \
vi.col = vcol->color; \
} \
vi.vertex.i = (intptr_t)bv; \
vi.index = BM_elem_index_get(vi.bm_vert); \
vi.visible = !BM_elem_flag_test_bool(vi.bm_vert, BM_ELEM_HIDDEN); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
} \
vi.co = vi.bm_vert->co; \
vi.fno = vi.bm_vert->no; \
vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \
}
vi.bm_vert = bv; \
if (vi.cd_vcol_offset >= 0) { \
MPropCol *vcol = BM_ELEM_CD_GET_VOID_P(bv, vi.cd_vcol_offset); \
vi.col = vcol->color; \
} \
vi.vertex.i = (intptr_t)bv; \
vi.index = BM_elem_index_get(vi.bm_vert); \
vi.visible = !BM_elem_flag_test_bool(vi.bm_vert, BM_ELEM_HIDDEN); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
} \
vi.co = vi.bm_vert->co; \
vi.fno = vi.bm_vert->no; \
vi.mask = (float*) BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset);\
}
#define BKE_pbvh_vertex_iter_end \
} \
} \
} \
((void)0)
# define BKE_pbvh_vertex_iter_end \
} \
} \
} \
((void)0)
#endif
#define BKE_pbvh_vertex_index_to_table(pbvh, v) \
(BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != -1 ? BM_elem_index_get((BMVert *)(v.i)) : (v.i))

View File

@ -1503,6 +1503,67 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool
return has_errors;
}
void layerDynTopoVert_copy(const void *source, void *dest, int count)
{
const MDynTopoVert *mv = (MDynTopoVert *)dest;
memcpy(dest, source, count * sizeof(MDynTopoVert));
}
void layerDynTopoVert_interp(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
{
float co[3], no[3], origmask, color[4];
MDynTopoVert *mv = (MDynTopoVert *)dest;
float totweight = 0.0f;
if (count == 0) {
memset(mv, 0, sizeof(*mv));
return;
}
zero_v3(co);
zero_v3(no);
origmask = 0.0f;
zero_v4(color);
for (int i = 0; i < count; i++) {
MDynTopoVert *mv2 = (MDynTopoVert *)sources[i];
float w;
if (i == 0) { // copy flag from first source
mv->flag = mv2->flag;
}
if (sub_weights) {
w = sub_weights[i];
}
else {
w = 1.0f;
}
madd_v3_v3fl(co, mv2->origco, w);
madd_v3_v3fl(no, mv2->origno, w);
madd_v4_v4fl(color, mv2->origcolor, w);
origmask += mv2->origmask * w;
totweight += w;
}
float mul = 1.0f / totweight;
mul_v3_fl(co, mul);
mul_v3_fl(no, mul);
mul_v4_fl(color, mul);
origmask *= mul;
copy_v3_v3(mv->origco, co);
copy_v3_v3(mv->origno, no);
copy_v4_v4(mv->origcolor, color);
mv->origmask = origmask;
}
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@ -1884,7 +1945,14 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
NULL,
NULL,
NULL},
};
{sizeof(MDynTopoVert),
NULL, // flag singleton layer
1,
N_("DynTopoVert"),
layerDynTopoVert_copy,
NULL,
layerDynTopoVert_interp
}};
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 0-4 */ "CDMVert",
@ -1940,7 +2008,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDPropFloat3",
"CDPropFloat2",
"CDPropBoolean",
};
"CDDyntopoVert"};
const CustomData_MeshMasks CD_MASK_BAREMESH = {
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT,
@ -1989,7 +2057,8 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
};
const CustomData_MeshMasks CD_MASK_BMESH = {
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR |
CD_MASK_DYNTOPO_VERT),
.emask = (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
.fmask = 0,
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |

View File

@ -77,9 +77,8 @@
#include "bmesh.h"
//XXX todo: work our bad module cross ref
void SCULPT_dynamic_topology_sync_layers(Object *ob,
Mesh *me);
// XXX todo: work our bad module cross ref
void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me);
static void palette_init_data(ID *id)
{
@ -2110,9 +2109,7 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
ob->sculpt->bm_log,
ob->sculpt->cd_vert_node_offset,
ob->sculpt->cd_face_node_offset,
ob->sculpt->cd_origco_offset,
ob->sculpt->cd_origno_offset,
ob->sculpt->cd_origvcol_offset);
ob->sculpt->cd_dyn_vert);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, false);

View File

@ -1457,7 +1457,7 @@ void BKE_pbvh_update_origcolor_bmesh(PBVH *pbvh, PBVHNode *node)
{
PBVHVertexIter vd;
if (!pbvh->bm || pbvh->cd_origvcol_offset < 0) {
if (!pbvh->bm || pbvh->cd_vcol_offset < 0) {
return;
}
@ -1469,10 +1469,10 @@ void BKE_pbvh_update_origcolor_bmesh(PBVH *pbvh, PBVHNode *node)
BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
float *c1 = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, pbvh->cd_origvcol_offset);
float *c2 = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, cd_vcol_offset);
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, vd.bm_vert);
float *c2 = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, pbvh->cd_vcol_offset);
copy_v4_v4(c1, c2);
copy_v4_v4(mv->origcolor, c2);
}
BKE_pbvh_vertex_iter_end;
}
@ -1481,17 +1481,16 @@ void BKE_pbvh_update_origco_bmesh(PBVH *pbvh, PBVHNode *node)
{
PBVHVertexIter vd;
if (!pbvh->bm || pbvh->cd_origco_offset < 0 || pbvh->cd_origno_offset < 0) {
if (!pbvh->bm || pbvh->cd_dyn_vert < 0) {
return;
}
BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
float *no = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, pbvh->cd_origno_offset);
float *co = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, pbvh->cd_origco_offset);
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, vd.bm_vert);
copy_v3_v3(co, vd.bm_vert->co);
copy_v3_v3(no, vd.bm_vert->no);
copy_v3_v3(mv->origco, vd.bm_vert->co);
copy_v3_v3(mv->origno, vd.bm_vert->no);
}
BKE_pbvh_vertex_iter_end;
}
@ -3095,6 +3094,8 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi->bm_vdata = &pbvh->bm->vdata;
vi->bm_vert = NULL;
vi->cd_dyn_vert = CustomData_get_offset(vi->bm_vdata, CD_DYNTOPO_VERT);
// we ensure pbvh->cd_vcol_offset is up to date here too
vi->cd_vcol_offset = pbvh->cd_vcol_offset = CustomData_get_offset(vi->bm_vdata, CD_PROP_COLOR);
vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK);
@ -3175,12 +3176,13 @@ void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes)
}
}
#include "BKE_global.h"
void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings,
bool use_threading,
int totnode)
{
memset(settings, 0, sizeof(*settings));
settings->use_threading = use_threading && totnode > 1;
settings->use_threading = use_threading && totnode > 1 && G.debug_value != 890;
}
MVert *BKE_pbvh_get_verts(const PBVH *pbvh)

View File

@ -18,24 +18,24 @@
* \ingroup bli
*/
/*
TODO:
/*
TODO:
Convergence improvements:
1. DONE: Limit number of edges processed per run.
2. Scale split steps by ratio of long to short edges to
prevent runaway tesselation.
3. Detect and dissolve three and four valence vertices that are surrounded by
all tris.
4. Use different (coarser) brush spacing for applying dyntopo
Convergence improvements:
1. DONE: Limit number of edges processed per run.
2. Scale split steps by ratio of long to short edges to
prevent runaway tesselation.
3. Detect and dissolve three and four valence vertices that are surrounded by
all tris.
4. Use different (coarser) brush spacing for applying dyntopo
Drawing improvements:
4. Build and cache vertex index buffers, to reduce GPU bandwidth
Drawing improvements:
4. Build and cache vertex index buffers, to reduce GPU bandwidth
Topology rake:
5. Enable new curvature topology rake code and add to UI.
6. Add code to cache curvature data per vertex in a CD layer.
Topology rake:
5. Enable new curvature topology rake code and add to UI.
6. Add code to cache curvature data per vertex in a CD layer.
*/
#include "MEM_guardedalloc.h"
@ -115,6 +115,8 @@ static void check_heap()
// #define USE_VERIFY
#define DYNTOPO_MASK(cd_mask_offset, v) BM_ELEM_CD_GET_FLOAT(v, cd_mask_offset)
#ifdef USE_VERIFY
static void pbvh_bmesh_verify(PBVH *pbvh);
#endif
@ -606,6 +608,13 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
BMVert *v = BM_vert_create(pbvh->bm, co, NULL, BM_CREATE_SKIP_CD);
CustomData_bmesh_set_default(&pbvh->bm->vdata, &v->head.data);
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
copy_v3_v3(mv->origco, co);
copy_v3_v3(mv->origno, no);
mv->origmask = 0.0f;
mv->flag = 0;
/* This value is logged below */
copy_v3_v3(v->no, no);
@ -875,6 +884,7 @@ typedef struct {
EdgeQueue *q;
BLI_mempool *pool;
BMesh *bm;
int cd_dyn_vert;
int cd_vert_mask_offset;
int cd_vert_node_offset;
int cd_face_node_offset;
@ -1232,7 +1242,7 @@ static bool edge_queue_vert_in_circle(const EdgeQueue *q, BMVert *v)
/* Return true if the vertex mask is less than 1.0, false otherwise */
static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
{
return BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f;
return DYNTOPO_MASK(eq_ctx->cd_dyn_vert, v) < 1.0f;
}
static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, float priority)
@ -1808,9 +1818,10 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
#endif
/* update paint mask */
if (eq_ctx->cd_vert_mask_offset != -1) {
float mask_v1 = BM_ELEM_CD_GET_FLOAT(e->v1, eq_ctx->cd_vert_mask_offset);
float mask_v2 = BM_ELEM_CD_GET_FLOAT(e->v2, eq_ctx->cd_vert_mask_offset);
if (eq_ctx->cd_dyn_vert != -1) {
float mask_v1 = DYNTOPO_MASK(eq_ctx->cd_dyn_vert, e->v1);
float mask_v2 = DYNTOPO_MASK(eq_ctx->cd_dyn_vert, e->v2);
float mask_v_new = 0.5f * (mask_v1 + mask_v2);
BM_ELEM_CD_SET_FLOAT(v_new, eq_ctx->cd_vert_mask_offset, mask_v_new);
@ -2079,8 +2090,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
#endif
/* one of the two vertices may be masked, select the correct one for deletion */
if (BM_ELEM_CD_GET_FLOAT(v1, eq_ctx->cd_vert_mask_offset) <
BM_ELEM_CD_GET_FLOAT(v2, eq_ctx->cd_vert_mask_offset)) {
if (DYNTOPO_MASK(eq_ctx->cd_vert_mask_offset, v1) <
DYNTOPO_MASK(eq_ctx->cd_vert_mask_offset, v2)) {
v_del = v1;
v_conn = v2;
}
@ -2329,32 +2340,31 @@ void BKE_pbvh_bmesh_update_origvert(
{
float *co = NULL, *no = NULL;
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
BM_log_vert_before_modified(pbvh->bm_log, v, pbvh->cd_vert_mask_offset, r_color != NULL);
if (r_co || r_no) {
co = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_origco_offset);
no = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_origno_offset);
copy_v3_v3(co, v->co);
copy_v3_v3(no, v->no);
copy_v3_v3(mv->origco, v->co);
copy_v3_v3(mv->origno, v->no);
if (r_co) {
*r_co = co;
*r_co = mv->origco;
}
if (r_no) {
*r_no = no;
*r_no = mv->origno;
}
}
if (r_color && pbvh->cd_vcol_offset >= 0 && pbvh->cd_origvcol_offset >= 0) {
if (r_color && pbvh->cd_vcol_offset >= 0) {
MPropCol *ml1 = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_vcol_offset);
MPropCol *ml2 = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_origvcol_offset);
copy_v4_v4(ml2->color, ml1->color);
copy_v4_v4(mv->origcolor, ml1->color);
if (r_color) {
*r_color = ml2->color;
*r_color = mv->origcolor;
}
}
else if (r_color) {
@ -2903,16 +2913,12 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset,
const int cd_origco_offset,
const int cd_origno_offset,
const int cd_origvcol_offset)
const int cd_dyn_vert)
{
pbvh->cd_vert_node_offset = cd_vert_node_offset;
pbvh->cd_face_node_offset = cd_face_node_offset;
pbvh->cd_origco_offset = cd_origco_offset;
pbvh->cd_origno_offset = cd_origno_offset;
pbvh->cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
pbvh->cd_origvcol_offset = cd_origvcol_offset;
pbvh->cd_dyn_vert = cd_dyn_vert;
pbvh->bm = bm;
@ -2929,23 +2935,26 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
BMIter iter;
BMVert *v;
int cd_vcol_offset = -1;
if (cd_origvcol_offset >= 0) {
cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
}
int cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
float *co = BM_ELEM_CD_GET_VOID_P(v, cd_origco_offset);
float *no = BM_ELEM_CD_GET_VOID_P(v, cd_origno_offset);
MDynTopoVert *mv = BKE_PBVH_DYNVERT(cd_dyn_vert, v);
copy_v3_v3(co, v->co);
copy_v3_v3(no, v->no);
mv->flag = 0;
if (cd_origvcol_offset >= 0) {
if (BM_vert_is_boundary(v)) {
mv->flag |= DYNVERT_BOUNDARY;
}
copy_v3_v3(mv->origco, v->co);
copy_v3_v3(mv->origno, v->no);
if (cd_vcol_offset >= 0) {
MPropCol *c1 = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
MPropCol *c2 = BM_ELEM_CD_GET_VOID_P(v, cd_origvcol_offset);
copy_v4_v4(c2->color, c1->color);
copy_v4_v4(mv->origcolor, c1->color);
}
else {
zero_v4(mv->origcolor);
}
}
if (smooth_shading) {
@ -3077,6 +3086,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
const int cd_vert_mask_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK);
const int cd_vert_node_offset = pbvh->cd_vert_node_offset;
const int cd_face_node_offset = pbvh->cd_face_node_offset;
const int cd_dyn_vert = pbvh->cd_dyn_vert;
bool modified = false;
@ -3091,6 +3101,8 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
&q,
queue_pool,
pbvh->bm,
cd_dyn_vert,
cd_vert_mask_offset,
cd_vert_node_offset,
cd_face_node_offset,
@ -3113,6 +3125,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
&q,
queue_pool,
pbvh->bm,
cd_dyn_vert,
cd_vert_mask_offset,
cd_vert_node_offset,
cd_face_node_offset,
@ -3869,17 +3882,12 @@ static void pbvh_bmesh_verify(PBVH *pbvh)
void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_vert_node_offset,
const int cd_face_node_offset,
const int cd_origco_offset,
const int cd_origno_offset,
const int cd_origvcol_offset)
const int cd_dyn_vert)
{
pbvh->cd_face_node_offset = cd_face_node_offset;
pbvh->cd_vert_node_offset = cd_vert_node_offset;
pbvh->cd_vert_mask_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK);
pbvh->cd_origco_offset = cd_origco_offset;
pbvh->cd_origno_offset = cd_origno_offset;
pbvh->cd_origvcol_offset = cd_origvcol_offset;
pbvh->cd_faceset_offset = CustomData_get_offset(&pbvh->bm->pdata, CD_SCULPT_FACE_SETS);
pbvh->cd_dyn_vert = cd_dyn_vert;
}
static void scan_edge_split(BMesh *bm, BMEdge **edges, int totedge)

View File

@ -174,13 +174,12 @@ struct PBVH {
BMesh *bm;
float bm_max_edge_len;
float bm_min_edge_len;
int cd_dyn_vert;
int cd_vert_node_offset;
int cd_face_node_offset;
int cd_vert_mask_offset;
int cd_vcol_offset;
int cd_origco_offset;
int cd_origno_offset;
int cd_origvcol_offset;
int cd_faceset_offset;
float planes[6][4];

View File

@ -120,6 +120,7 @@ struct BMLog {
int cd_origco_offset;
int cd_origno_offset;
int cd_origvcol_offset;
int cd_dyn_vert;
};
typedef struct {
@ -578,7 +579,6 @@ static void bm_log_face_values_swap(BMLog *log, GHash *faces, BMLogEntry *entry)
}
}
#endif
}
}
@ -713,18 +713,18 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
/***************************** Public API *****************************/
void BM_log_set_cd_offsets(BMLog *log,
int cd_origco_offset,
int cd_origno_offset,
int cd_origvol_offset)
void BM_log_set_cd_offsets(
BMLog *log, int cd_origco_offset, int cd_origno_offset, int cd_origvol_offset, int cd_dyn_vert)
{
log->cd_origco_offset = cd_origco_offset;
log->cd_origno_offset = cd_origno_offset;
log->cd_origvcol_offset = cd_origvol_offset;
log->cd_dyn_vert = cd_dyn_vert;
}
/* Allocate, initialize, and assign a new BMLog */
BMLog *BM_log_create(BMesh *bm, int cd_origco_offset, int cd_origno_offset, int cd_origvcol_offset)
BMLog *BM_log_create(
BMesh *bm, int cd_origco_offset, int cd_origno_offset, int cd_origvcol_offset, int cd_dyn_vert)
{
BMLog *log = MEM_callocN(sizeof(*log), __func__);
const uint reserve_num = (uint)(bm->totvert + bm->totface);
@ -735,7 +735,7 @@ BMLog *BM_log_create(BMesh *bm, int cd_origco_offset, int cd_origno_offset, int
log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num);
BM_log_set_cd_offsets(log, cd_origco_offset, cd_origno_offset, cd_origvcol_offset);
BM_log_set_cd_offsets(log, cd_origco_offset, cd_origno_offset, cd_origvcol_offset, cd_dyn_vert);
/* Assign IDs to all existing vertices and faces */
bm_log_assign_ids(bm, log);
@ -775,7 +775,7 @@ void BM_log_cleanup_entry(BMLogEntry *entry)
*/
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
{
BMLog *log = BM_log_create(bm, -1, -1, -1);
BMLog *log = BM_log_create(bm, -1, -1, -1, -1);
if (entry->prev) {
log->current_entry = entry;

View File

@ -29,11 +29,13 @@ typedef struct BMLog BMLog;
typedef struct BMLogEntry BMLogEntry;
/* Allocate and initialize a new BMLog */
BMLog *BM_log_create(BMesh *bm, int cd_origco_offset, int cd_origno_offset, int cd_origvol_offset);
BMLog *BM_log_create(
BMesh *bm, int cd_origco_offset, int cd_origno_offset, int cd_origvol_offset, int cd_dyn_vert);
void BM_log_set_cd_offsets(BMLog *log,
int cd_origco_offset,
int cd_origno_offset,
int cd_origvcol_offset);
int cd_origvcol_offset,
int cd_dyn_vert);
/* Allocate and initialize a new BMLog using existing BMLogEntries */
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry);

View File

@ -1078,11 +1078,16 @@ static bool pixel_bounds_uv(const float uv_quad[4][2],
}
#endif
static bool pixel_bounds_array(
float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
__attribute__((optnone)) static bool pixel_bounds_array(
float (*in_uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
{
/* UV bounds */
float min_uv[2], max_uv[2];
float(*uv)[2] = in_uv;
if (tot < 0) {
printf("eek!\n");
}
if (tot == 0) {
return false;
@ -1090,9 +1095,8 @@ static bool pixel_bounds_array(
INIT_MINMAX2(min_uv, max_uv);
while (tot--) {
for (int i = 0; i < tot; i++, uv++) {
minmax_v2v2_v2(min_uv, max_uv, (*uv));
uv++;
}
bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
@ -1101,6 +1105,15 @@ static bool pixel_bounds_array(
bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
const int d = -1000;
if (bounds_px->xmin < d || bounds_px->ymin < d || bounds_px->xmax < d || bounds_px->ymax < d) {
printf("error! xmin %d xmax %d ymin %d ymax %d\n",
bounds_px->xmin,
bounds_px->xmax,
bounds_px->ymin,
bounds_px->ymax);
}
/*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
/* face uses no UV area when quantized to pixels? */

View File

@ -1164,16 +1164,16 @@ static bool sculpt_check_boundary_vertex_in_base_mesh(const SculptSession *ss,
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const SculptVertRef vertex)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, ((BMVert*)(vertex.i)));
return mv->flag & DYNVERT_BOUNDARY;
}
case PBVH_FACES: {
if (!SCULPT_vertex_all_face_sets_visible_get(ss, vertex)) {
return true;
}
return sculpt_check_boundary_vertex_in_base_mesh(ss, vertex);
}
case PBVH_BMESH: {
BMVert *v = (BMVert *)vertex.i;
return BM_vert_is_boundary(v);
}
case PBVH_GRIDS: {
int index = (int)vertex.i;
@ -1639,13 +1639,15 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter
{
if (orig_data->datatype == SCULPT_UNDO_COORDS) {
if (orig_data->bm_log) {
orig_data->co = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origco_offset);
orig_data->co = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origco;
float *no = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origno_offset);
float *no = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origno;
normal_float_to_short_v3(orig_data->_no, no);
orig_data->no = orig_data->_no;
orig_data->col = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origvcol_offset);
orig_data->col = iter->cd_vcol_offset >= 0 ?
BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origcolor :
NULL;
}
else {
orig_data->co = orig_data->coords[iter->i];
@ -1654,7 +1656,7 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter
}
else if (orig_data->datatype == SCULPT_UNDO_COLOR) {
if (orig_data->bm_log) {
orig_data->col = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origvcol_offset);
orig_data->col = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origcolor;
}
else {
orig_data->col = orig_data->colors[iter->i];
@ -1662,7 +1664,8 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter
}
else if (orig_data->datatype == SCULPT_UNDO_MASK) {
if (orig_data->bm_log) {
orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
orig_data->mask = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)
->origmask; // BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
}
else {
orig_data->mask = orig_data->vmasks[iter->i];
@ -3234,8 +3237,9 @@ typedef struct {
bool original;
} SculptFindNearestToRayData;
__attribute__((optnone)) static void do_topology_rake_bmesh_task_cb_ex(
void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
@ -4410,9 +4414,8 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
}
static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
__attribute__((optnone)) static void do_elastic_deform_brush_task_cb_ex(
void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
@ -6217,8 +6220,10 @@ static void sculpt_topology_update(Sculpt *sd,
symidx = 127;
}
bool modified;
/* do nodes under the brush cursor */
BKE_pbvh_bmesh_update_topology_nodes(ss->pbvh,
modified = BKE_pbvh_bmesh_update_topology_nodes(ss->pbvh,
SCULPT_search_sphere_cb,
topology_undopush_cb,
&sdata,
@ -6634,7 +6639,7 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
if (use_orco) {
if (ss->bm) {
float *co = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, ss->cd_origco_offset);
float *co = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, vd.bm_vert)->origco;
copy_v3_v3(val, co);
// copy_v3_v3(val, BM_log_original_vert_co(ss->bm_log, vd.bm_vert));
}
@ -8294,6 +8299,7 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
ss->update_boundary_info_bmesh = true;
#if 0
if (update_flags & SCULPT_UPDATE_COLOR) {
PBVHNode **nodes;
@ -9529,32 +9535,62 @@ void SCULPT_connected_components_ensure(Object *ob)
void SCULPT_boundary_info_ensure(Object *object)
{
SculptSession *ss = object->sculpt;
if (ss->vertex_info.boundary) {
return;
}
Mesh *base_mesh = BKE_mesh_from_object(object);
ss->vertex_info.boundary = BLI_BITMAP_NEW(base_mesh->totvert, "Boundary info");
int *adjacent_faces_edge_count = MEM_calloc_arrayN(
base_mesh->totedge, sizeof(int), "Adjacent face edge count");
if (ss->bm) {
if (!ss->update_boundary_info_bmesh) {
return;
}
for (int p = 0; p < base_mesh->totpoly; p++) {
MPoly *poly = &base_mesh->mpoly[p];
for (int l = 0; l < poly->totloop; l++) {
MLoop *loop = &base_mesh->mloop[l + poly->loopstart];
adjacent_faces_edge_count[loop->e]++;
ss->update_boundary_info_bmesh = 0;
BMVert *v;
BMIter iter;
MEM_SAFE_FREE(ss->vertex_info.boundary);
//return; //XXX
BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
SculptVertRef sv = {(uintptr_t)v};
if (BM_vert_is_boundary(v) || !SCULPT_vertex_all_face_sets_visible_get(ss, sv)) {
mv->flag |= DYNVERT_BOUNDARY;
}
else {
mv->flag &= ~DYNVERT_BOUNDARY;
}
}
}
for (int e = 0; e < base_mesh->totedge; e++) {
if (adjacent_faces_edge_count[e] < 2) {
MEdge *edge = &base_mesh->medge[e];
BLI_BITMAP_SET(ss->vertex_info.boundary, edge->v1, true);
BLI_BITMAP_SET(ss->vertex_info.boundary, edge->v2, true);
else {
if (ss->vertex_info.boundary) {
return;
}
}
MEM_freeN(adjacent_faces_edge_count);
Mesh *base_mesh = BKE_mesh_from_object(object);
ss->vertex_info.boundary = BLI_BITMAP_NEW(base_mesh->totvert, "Boundary info");
int *adjacent_faces_edge_count = MEM_calloc_arrayN(
base_mesh->totedge, sizeof(int), "Adjacent face edge count");
for (int p = 0; p < base_mesh->totpoly; p++) {
MPoly *poly = &base_mesh->mpoly[p];
for (int l = 0; l < poly->totloop; l++) {
MLoop *loop = &base_mesh->mloop[l + poly->loopstart];
adjacent_faces_edge_count[loop->e]++;
}
}
for (int e = 0; e < base_mesh->totedge; e++) {
if (adjacent_faces_edge_count[e] < 2) {
MEdge *edge = &base_mesh->medge[e];
BLI_BITMAP_SET(ss->vertex_info.boundary, edge->v1, true);
BLI_BITMAP_SET(ss->vertex_info.boundary, edge->v2, true);
}
}
MEM_freeN(adjacent_faces_edge_count);
}
}
void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist)

View File

@ -117,11 +117,15 @@ void SCULPT_dyntopo_save_origverts(SculptSession *ss)
BMVert *v;
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
float *co = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origco_offset);
float *no = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origno_offset);
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
copy_v3_v3(co, v->co);
copy_v3_v3(no, v->no);
copy_v3_v3(mv->origco, v->co);
copy_v3_v3(mv->origno, v->no);
if (ss->cd_vcol_offset >= 0) {
MPropCol *mp = (MPropCol *)BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset);
copy_v4_v4(mv->origcolor, mp->color);
}
}
}
@ -151,6 +155,13 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
}
}
if (!CustomData_has_layer(&ss->bm->vdata, CD_DYNTOPO_VERT)) {
BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_DYNTOPO_VERT);
int cd_dyn_vert = CustomData_get_layer_index(&ss->bm->vdata, CD_DYNTOPO_VERT);
ss->bm->vdata.layers[cd_dyn_vert].flag |= CD_FLAG_TEMPORARY;
}
cd_origco_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_FLOAT3, origco_id);
if (cd_origco_index == -1) {
BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_FLOAT3, origco_id);
@ -193,6 +204,8 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
ss->cd_origvcol_offset = -1;
}
ss->cd_dyn_vert = CustomData_get_offset(&ss->bm->vdata, CD_DYNTOPO_VERT);
ss->cd_origco_offset = CustomData_get_n_offset(
&ss->bm->vdata,
CD_PROP_FLOAT3,
@ -314,12 +327,8 @@ void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
if (modified) {
SCULPT_dyntopo_node_layers_update_offsets(ss);
BKE_pbvh_update_offsets(ss->pbvh,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_origco_offset,
ss->cd_origno_offset,
ss->cd_origvcol_offset);
BKE_pbvh_update_offsets(
ss->pbvh, ss->cd_vert_node_offset, ss->cd_face_node_offset, ss->cd_dyn_vert);
}
}
@ -360,21 +369,14 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
int cd_vcol_offset = CustomData_get_offset(&ss->bm->vdata, CD_PROP_COLOR);
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
if (ss->cd_origco_offset >= 0) {
float *co = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origco_offset);
copy_v3_v3(co, v->co);
}
if (ss->cd_origno_offset >= 0) {
float *no = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origno_offset);
copy_v3_v3(no, v->no);
}
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
if (ss->cd_origvcol_offset >= 0) {
copy_v3_v3(mv->origco, v->co);
copy_v3_v3(mv->origno, v->no);
float *ocolor = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origvcol_offset);
float *color = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
copy_v4_v4(ocolor, color);
if (ss->cd_vcol_offset >= 0) {
MPropCol *color = (MPropCol *)BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
copy_v4_v4(mv->origcolor, color->color);
}
}
@ -386,9 +388,11 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
/* Enable dynamic topology. */
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
ss->update_boundary_info_bmesh = 1;
/* Enable logging for undo/redo. */
ss->bm_log = BM_log_create(
ss->bm, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
ss->bm, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset, ss->cd_dyn_vert);
/* Update dependency graph, so modifiers that depend on dyntopo being enabled
* are re-evaluated and the PBVH is re-created. */

View File

@ -464,7 +464,7 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode)
/* Restore the BMLog using saved entries. */
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
BM_log_set_cd_offsets(
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset, ss->cd_dyn_vert);
}
static void sculpt_undo_bmesh_restore_begin(bContext *C,
@ -599,7 +599,7 @@ static int sculpt_undo_bmesh_restore(bContext *C,
{
if (ss->bm_log) {
BM_log_set_cd_offsets(
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset, ss->cd_dyn_vert);
}
switch (unode->type) {

View File

@ -525,6 +525,7 @@ typedef enum eBrushUVSculptTool {
#define SCULPT_TOOL_HAS_TOPOLOGY_RAKE(t) \
(ELEM(t, /* These brushes, as currently coded, cannot support topology rake. */ \
SCULPT_TOOL_GRAB, \
SCULPT_TOOL_ELASTIC_DEFORM, \
SCULPT_TOOL_ROTATE, \
SCULPT_TOOL_THUMB, \
SCULPT_TOOL_DRAW_SHARP, \

View File

@ -75,11 +75,11 @@ typedef struct CustomData {
* MUST be >= CD_NUMTYPES, but we cant use a define here.
* Correct size is ensured in CustomData_update_typemap assert().
*/
int typemap[51];
int typemap[52];
/** Number of layers, size of layers array. */
int totlayer, maxlayer;
/** In editmode, total size of all data layers. */
int totsize;
int totsize, _pad;
/** (BMesh Only): Memory pool for allocation of blocks. */
struct BLI_mempool *pool;
/** External file storing customdata layers. */
@ -157,7 +157,8 @@ typedef enum CustomDataType {
CD_PROP_BOOL = 50,
CD_NUMTYPES = 51,
CD_DYNTOPO_VERT = 51,
CD_NUMTYPES = 52,
} CustomDataType;
/* Bits for CustomDataMask */
@ -211,6 +212,8 @@ typedef enum CustomDataType {
#define CD_MASK_PROP_FLOAT2 (1ULL << CD_PROP_FLOAT2)
#define CD_MASK_PROP_BOOL (1ULL << CD_PROP_BOOL)
#define CD_MASK_DYNTOPO_VERT (1ULL << CD_DYNTOPO_VERT)
/** Multires loop data. */
#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)

View File

@ -525,6 +525,21 @@ typedef struct MRecast {
/** \} */
typedef struct MDynTopoVert {
int flag;
/**original coordinates*/
float origco[3], origno[3];
/**original color*/
float origcolor[4];
float origmask;
} MDynTopoVert;
/*MDynTopoVert->flag*/
enum { DYNVERT_BOUNDARY = (1 << 0) };
#ifdef __cplusplus
}
#endif