* 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:
parent
75a1116b51
commit
924b13b03a
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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? */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue