sculpt-dev: Split boundary flags into its own attribute

Boundary and corner flags are now stored in their own
attribute instead of in MSculptVert->flag.  Note that
the other parts of MSculptVert will eventually become
their own indiviudual attibute (including the ->flag
which is still used by dyntopo).
This commit is contained in:
Joseph Eagar 2022-10-10 16:06:56 -07:00
parent a5f53346a6
commit 57d5fc7352
22 changed files with 611 additions and 512 deletions

View File

@ -735,6 +735,7 @@ typedef struct SculptAttributePointers {
SculptAttribute *smooth_bdist;
SculptAttribute *smooth_vel;
SculptAttribute *boundary_flags;
SculptAttribute *sculpt_vert;
SculptAttribute *stroke_id;
@ -971,7 +972,7 @@ typedef struct SculptSession {
bool fast_draw; // hides facesets/masks and forces smooth to save GPU bandwidth
struct MSculptVert *msculptverts; // for non-bmesh
int msculptverts_size;
int last_msculptverts_count;
/* This is a fixed-size array so we can pass pointers to its elements
* to client code. This is important to keep bmesh offsets up to date.
@ -989,7 +990,7 @@ typedef struct SculptSession {
*/
bool sticky_shading_color;
uchar stroke_id;
ushort stroke_id;
/**
* Last used painting canvas key.
@ -1007,6 +1008,28 @@ typedef struct SculptSession {
uchar last_automask_stroke_id;
} SculptSession;
typedef enum eSculptBoundary {
SCULPT_BOUNDARY_MESH = 1 << 0,
SCULPT_BOUNDARY_FACE_SET = 1 << 1,
SCULPT_BOUNDARY_SEAM = 1 << 2,
SCULPT_BOUNDARY_SHARP = 1 << 3,
SCULPT_BOUNDARY_UV = 1 << 4,
SCULPT_BOUNDARY_NEEDS_UPDATE = 1 << 5,
SCULPT_BOUNDARY_ALL = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4),
SCULPT_BOUNDARY_DEFAULT = (1 << 0) | (1 << 3) | (1 << 4) // mesh and sharp
} eSculptBoundary;
/* Note: This is stored in a single attribute with boundary flags */
typedef enum eSculptCorner {
SCULPT_CORNER_NONE = 0,
SCULPT_CORNER_MESH = 1 << 6,
SCULPT_CORNER_FACE_SET = 1 << 7,
SCULPT_CORNER_SEAM = 1 << 8,
SCULPT_CORNER_SHARP = 1 << 9,
SCULPT_CORNER_UV = 1 << 10,
} eSculptCorner;
void BKE_sculptsession_free(struct Object *ob);
void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
@ -1083,7 +1106,13 @@ BLI_INLINE void *BKE_sculpt_face_attr_get(const PBVHFaceRef vertex, const Sculpt
return NULL;
}
bool BKE_sculptsession_check_sculptverts(SculptSession *ss, struct PBVH *pbvh, int totvert);
BLI_INLINE void BKE_sculpt_boundary_flag_update(SculptSession *ss, PBVHVertRef vertex)
{
int *flags = (int *)BKE_sculpt_vertex_attr_get(vertex, ss->attrs.boundary_flags);
*flags |= SCULPT_BOUNDARY_NEEDS_UPDATE;
}
bool BKE_sculptsession_check_sculptverts(struct Object *ob, struct PBVH *pbvh, int totvert);
struct BMesh *BKE_sculptsession_empty_bmesh_create(void);
void BKE_sculptsession_bmesh_attr_update_internal(struct Object *ob);
@ -1135,7 +1164,7 @@ int *BKE_sculpt_face_sets_ensure(struct Object *ob);
* Note that changes to the face visibility have to be propagated to other domains
* (see #SCULPT_visibility_sync_all_from_faces).
*/
bool *BKE_sculpt_hide_poly_ensure(struct Mesh *mesh);
bool *BKE_sculpt_hide_poly_ensure(struct Object *ob);
int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd);
void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene);

View File

@ -426,6 +426,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
const int cd_face_node_offset,
const int cd_sculpt_vert,
const int cd_face_areas,
const int cd_boundary_flag,
bool fast_draw,
bool update_sculptverts);
void BKE_pbvh_update_offsets(PBVH *pbvh,
@ -433,7 +434,8 @@ void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_face_node_offset,
const int cd_sculpt_vert,
const int cd_face_areas,
const int cd_hide_poly);
const int cd_hide_poly,
const int cd_boudnary_flags);
void BKE_pbvh_update_bmesh_offsets(PBVH *pbvh, int cd_vert_node_offset, int cd_face_node_offset);
@ -1017,6 +1019,7 @@ void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node);
/*recalculates boundary flags for *all* vertices. used by
symmetrize.*/
void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh);
void BKE_pbvh_set_boundary_flags(PBVH *pbvh, int *boundary_flags);
/* saves all bmesh references to internal indices, to be restored later */
void BKE_pbvh_bmesh_save_indices(PBVH *pbvh);
@ -1052,6 +1055,7 @@ void BKE_pbvh_update_vert_boundary(int cd_sculpt_vert,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol,
int cd_boundary_flag,
struct BMVert *v,
int bound_symmetry,
const CustomData *ldata,
@ -1163,7 +1167,8 @@ typedef struct SculptLayerEntry {
int BKE_pbvh_do_fset_symmetry(int fset, const int symflag, const float *co);
bool BKE_pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v);
void BKE_pbvh_update_vert_boundary_faces(const int *face_sets,
void BKE_pbvh_update_vert_boundary_faces(int *boundary_flags,
const int *face_sets,
const bool *hide_poly,
const struct MVert *mvert,
const struct MEdge *medge,
@ -1176,8 +1181,6 @@ void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
struct SubdivCCG *subdiv_ccg,
PBVHVertRef vertex);
void BKE_pbvh_set_mdyntopo_verts(PBVH *pbvh, struct MSculptVert *mdyntopoverts);
#if 0
# include "DNA_meshdata_types.h"
ATTR_NO_OPT static void MV_ADD_FLAG(MSculptVert *mv, int flag)

View File

@ -4890,11 +4890,11 @@ void CustomData_bmesh_interp(CustomData *data,
}
}
void CustomData_to_bmesh_block(const CustomData *source,
CustomData *dest,
int src_index,
void **dest_block,
bool use_default_init)
ATTR_NO_OPT void CustomData_to_bmesh_block(const CustomData *source,
CustomData *dest,
int src_index,
void **dest_block,
bool use_default_init)
{
if (*dest_block == nullptr) {
CustomData_bmesh_alloc_block(dest, dest_block);

View File

@ -53,17 +53,17 @@
#define SCULPTVERT_VALENCE_TEMP SCULPTVERT_SPLIT_TEMP
#define SCULPTVERT_SMOOTH_BOUNDARY \
(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY | \
SCULPTVERT_SEAM_BOUNDARY | SCULPTVERT_UV_BOUNDARY)
(SCULPT_BOUNDARY_MESH | SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_SHARP | \
SCULPT_BOUNDARY_SEAM | SCULPT_BOUNDARY_UV)
#define SCULPTVERT_ALL_BOUNDARY \
(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY | \
SCULPTVERT_SEAM_BOUNDARY | SCULPTVERT_UV_BOUNDARY)
(SCULPT_BOUNDARY_MESH | SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_SHARP | \
SCULPT_BOUNDARY_SEAM | SCULPT_BOUNDARY_UV)
#define SCULPTVERT_SMOOTH_CORNER \
(SCULPTVERT_CORNER | SCULPTVERT_FSET_CORNER | SCULPTVERT_SHARP_CORNER | \
SCULPTVERT_SEAM_CORNER | SCULPTVERT_UV_CORNER)
(SCULPT_CORNER_MESH | SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SHARP | SCULPT_CORNER_SEAM | \
SCULPT_CORNER_UV)
#define SCULPTVERT_ALL_CORNER \
(SCULPTVERT_CORNER | SCULPTVERT_FSET_CORNER | SCULPTVERT_SHARP_CORNER | \
SCULPTVERT_SEAM_CORNER | SCULPTVERT_UV_CORNER)
(SCULPT_CORNER_MESH | SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SHARP | SCULPT_CORNER_SEAM | \
SCULPT_CORNER_UV)
#define DYNTOPO_MAX_ITER 4096
@ -181,6 +181,24 @@ static void pbvh_bmesh_verify(PBVH *pbvh);
struct EdgeQueueContext;
bool pbvh_boundary_needs_update_bmesh(PBVH *pbvh, BMVert *v)
{
int *flags = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
return *flags & SCULPT_BOUNDARY_NEEDS_UPDATE;
}
void pbvh_boundary_update_bmesh(PBVH *pbvh, BMVert *v)
{
if (pbvh->cd_boundary_flag == -1) {
printf("%s: error!\n", __func__);
return;
}
int *flags = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
*flags |= SCULPT_BOUNDARY_NEEDS_UPDATE;
}
static bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root);
static bool check_face_is_tri(PBVH *pbvh, BMFace *f);
static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v);
@ -222,8 +240,7 @@ static void fix_mesh(PBVH *pbvh, BMesh *bm)
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT |
SCULPTVERT_NEED_TRIANGULATE);
SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_TRIANGULATE);
}
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
@ -654,17 +671,18 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
return;
}
if (mv1->flag & SCULPTVERT_NEED_BOUNDARY) {
if (pbvh_boundary_needs_update_bmesh(pbvh, v)) {
pbvh_check_vert_boundary(pbvh, v);
}
// pbvh_check_vert_boundary(pbvh, v);
const int cd_sculpt_vert = pbvh->cd_sculpt_vert;
const int boundflag = BM_ELEM_CD_GET_INT(v, pbvh->cd_boundary_flag);
const bool bound1 = mv1->flag & SCULPTVERT_SMOOTH_BOUNDARY;
const bool bound1 = boundflag & SCULPTVERT_SMOOTH_BOUNDARY;
if (mv1->flag & SCULPTVERT_SMOOTH_CORNER) {
if (boundflag & SCULPTVERT_SMOOTH_CORNER) {
return;
}
@ -679,7 +697,9 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
// pbvh_check_vert_boundary(pbvh, v2);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, v2);
const bool bound2 = mv2->flag & SCULPTVERT_SMOOTH_BOUNDARY;
int boundflag2 = BM_ELEM_CD_GET_INT(v2, pbvh->cd_boundary_flag);
const bool bound2 = boundflag2 & SCULPTVERT_SMOOTH_BOUNDARY;
if (bound1 && !bound2) {
continue;
@ -884,7 +904,8 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
BMVert *v = BM_vert_create(pbvh->header.bm, co, NULL, BM_CREATE_NOP);
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE);
pbvh_boundary_update_bmesh(pbvh, v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE);
if (v_example) {
v->head.hflag = v_example->head.hflag;
@ -1004,9 +1025,10 @@ static BMFace *pbvh_bmesh_face_create(PBVH *pbvh,
PBVH_UpdateOtherVerts;
}
pbvh_boundary_update_bmesh(pbvh, l->v);
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->v);
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE);
l = l->next;
} while (l != f->l_first);
@ -1014,10 +1036,10 @@ static BMFace *pbvh_bmesh_face_create(PBVH *pbvh,
else {
BMLoop *l = f->l_first;
do {
pbvh_boundary_update_bmesh(pbvh, l->v);
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->v);
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE);
} while ((l = l->next) != f->l_first);
}
@ -1059,9 +1081,9 @@ BMVert *BKE_pbvh_vert_create_bmesh(
v = BM_vert_create(pbvh->header.bm, co, v_example, BM_CREATE_NOP);
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
pbvh_boundary_update_bmesh(pbvh, v);
MSculptVert *mv = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_sculpt_vert);
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_BOUNDARY);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
copy_v3_v3(mv->origco, co);
@ -2364,8 +2386,7 @@ static bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
BM_face_kill(pbvh->header.bm, f);
}
const int mupdateflag = SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT |
SCULPTVERT_NEED_VALENCE;
const int mupdateflag = SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE;
for (int i = 0; i < BLI_array_len(es); i++) {
BMEdge *e = es[i];
@ -2386,6 +2407,8 @@ static bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
BM_vert_kill(pbvh->header.bm, v);
}
else {
pbvh_boundary_update_bmesh(pbvh, v);
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
mv->flag |= mupdateflag;
}
@ -2461,9 +2484,9 @@ static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v)
do {
MSculptVert *mv_l = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->v);
pbvh_boundary_update_bmesh(pbvh, l->v);
MV_ADD_FLAG(mv_l,
SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv_l, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
} while ((l = l->next) != f->l_first);
BLI_array_append(fs, f);
}
@ -2919,11 +2942,14 @@ static void edge_queue_create_local(EdgeQueueContext *eq_ctx,
pbvh_check_vert_boundary(pbvh, e->v1);
pbvh_check_vert_boundary(pbvh, e->v2);
if ((mv1->flag & SCULPTVERT_ALL_CORNER) || (mv2->flag & SCULPTVERT_ALL_CORNER)) {
int boundflag1 = BM_ELEM_CD_GET_INT(e->v1, pbvh->cd_boundary_flag);
int boundflag2 = BM_ELEM_CD_GET_INT(e->v2, pbvh->cd_boundary_flag);
if ((boundflag1 & SCULPTVERT_ALL_CORNER) || (boundflag2 & SCULPTVERT_ALL_CORNER)) {
continue;
}
if ((mv1->flag & SCULPTVERT_ALL_BOUNDARY) != (mv2->flag & SCULPTVERT_ALL_BOUNDARY)) {
if ((boundflag1 & SCULPTVERT_ALL_BOUNDARY) != (boundflag2 & SCULPTVERT_ALL_BOUNDARY)) {
continue;
}
@ -2956,11 +2982,14 @@ static void edge_queue_create_local(EdgeQueueContext *eq_ctx,
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, e->v2);
if ((mv1->flag & SCULPTVERT_ALL_CORNER) || (mv2->flag & SCULPTVERT_ALL_CORNER)) {
int boundflag1 = BM_ELEM_CD_GET_INT(e->v1, pbvh->cd_boundary_flag);
int boundflag2 = BM_ELEM_CD_GET_INT(e->v2, pbvh->cd_boundary_flag);
if ((boundflag1 & SCULPTVERT_ALL_CORNER) || (boundflag2 & SCULPTVERT_ALL_CORNER)) {
continue;
}
if ((mv1->flag & SCULPTVERT_ALL_BOUNDARY) != (mv2->flag & SCULPTVERT_ALL_BOUNDARY)) {
if ((boundflag1 & SCULPTVERT_ALL_BOUNDARY) != (boundflag2 & SCULPTVERT_ALL_BOUNDARY)) {
continue;
}
@ -3179,8 +3208,10 @@ void col_on_vert_add(BMesh *bm, BMVert *v, void *userdata)
TraceData *data = (TraceData *)userdata;
PBVH *pbvh = data->pbvh;
pbvh_boundary_update_bmesh(pbvh, v);
MSculptVert *mv = BM_ELEM_CD_GET_VOID_P(v, data->pbvh->cd_sculpt_vert);
mv->flag |= SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT;
mv->flag |= SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT;
BM_log_vert_topo_post(pbvh->bm_log, v);
}
@ -3479,9 +3510,9 @@ static void collapse_ring_callback_pre(BMElem *elem, void *userdata)
case BM_VERT: {
BMVert *v = (BMVert *)elem;
MSculptVert *mv = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_sculpt_vert);
pbvh_boundary_update_bmesh(pbvh, v);
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
pbvh_bmesh_vert_remove(pbvh, v);
@ -3546,9 +3577,9 @@ static void collapse_ring_callback_post(BMElem *elem, void *userdata)
case BM_VERT: {
BMVert *v = (BMVert *)elem;
MSculptVert *mv = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_sculpt_vert);
pbvh_boundary_update_bmesh(pbvh, v);
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
break;
}
@ -3612,8 +3643,7 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
tracer.on_edge_kill = col_on_edge_kill;
tracer.on_face_kill = col_on_face_kill;
const int mupdateflag = SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY |
SCULPTVERT_NEED_DISK_SORT;
const int mupdateflag = SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT;
// updateflag |= SCULPTVERT_NEED_TRIANGULATE; // to check for non-manifold flaps
validate_edge(pbvh, pbvh->header.bm, e, true, true);
@ -3623,10 +3653,12 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v2);
int boundflag1 = BM_ELEM_CD_GET_INT(v1, pbvh->cd_boundary_flag);
int boundflag2 = BM_ELEM_CD_GET_INT(v2, pbvh->cd_boundary_flag);
/* one of the two vertices may be masked, select the correct one for deletion */
if (!(mv1->flag & SCULPTVERT_ALL_CORNER) || DYNTOPO_MASK(eq_ctx->cd_vert_mask_offset, v1) <
DYNTOPO_MASK(eq_ctx->cd_vert_mask_offset, v2)) {
if (!(boundflag1 & SCULPTVERT_ALL_CORNER) || DYNTOPO_MASK(eq_ctx->cd_vert_mask_offset, v1) <
DYNTOPO_MASK(eq_ctx->cd_vert_mask_offset, v2)) {
v_del = v1;
v_conn = v2;
}
@ -3635,10 +3667,11 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
v_conn = v1;
SWAP(MSculptVert *, mv1, mv2);
SWAP(int, boundflag1, boundflag2);
}
if ((mv1->flag & SCULPTVERT_ALL_CORNER) ||
(mv1->flag & SCULPTVERT_ALL_BOUNDARY) != (mv2->flag & SCULPTVERT_ALL_BOUNDARY)) {
if ((boundflag1 & SCULPTVERT_ALL_CORNER) ||
(boundflag1 & SCULPTVERT_ALL_BOUNDARY) != (boundflag2 & SCULPTVERT_ALL_BOUNDARY)) {
bm_logstack_pop();
return NULL;
}
@ -3660,16 +3693,16 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
/*have to check edge flags directly, vertex flag test above isn't specific enough and
can sometimes let bad edges through*/
if ((mv1->flag & SCULPTVERT_SHARP_BOUNDARY) && (e->head.hflag & BM_ELEM_SMOOTH)) {
if ((boundflag1 & SCULPT_BOUNDARY_SHARP) && (e->head.hflag & BM_ELEM_SMOOTH)) {
bm_logstack_pop();
return NULL;
}
if ((mv1->flag & SCULPTVERT_SEAM_BOUNDARY) && !(e->head.hflag & BM_ELEM_SEAM)) {
if ((boundflag1 & SCULPT_BOUNDARY_SEAM) && !(e->head.hflag & BM_ELEM_SEAM)) {
bm_logstack_pop();
return NULL;
}
bool snap = !(mv2->flag & SCULPTVERT_ALL_CORNER);
bool snap = !(boundflag2 & SCULPTVERT_ALL_CORNER);
/* snap customdata */
if (snap) {
@ -3855,6 +3888,8 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
do {
BMLoop *l2 = l->f->l_first;
do {
pbvh_boundary_update_bmesh(pbvh, l2->v);
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l2->v);
mv->flag |= mupdateflag;
} while ((l2 = l2->next) != l->f->l_first);
@ -3869,6 +3904,8 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
}
MSculptVert *mv_conn = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v_conn);
pbvh_boundary_update_bmesh(pbvh, v_conn);
MV_ADD_FLAG(mv_conn, mupdateflag);
#if 1
@ -3923,6 +3960,8 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
}
MSculptVert *mv3 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v_conn);
pbvh_boundary_update_bmesh(pbvh, v_conn);
MV_ADD_FLAG(mv3, mupdateflag);
if (!v_conn->e) {
@ -3997,7 +4036,7 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
const int cd_vert_node = pbvh->cd_vert_node_offset;
int updateflag = SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE;
int updateflag = SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE;
for (int i = 0; i < ectx->tot_used_verts; i++) {
BMVert *v = ectx->used_verts[i];
@ -4043,8 +4082,9 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
#endif
pbvh_check_vert_boundary(pbvh, v);
int boundflag = BM_ELEM_CD_GET_INT(v, pbvh->cd_boundary_flag);
if (mv->flag & SCULPTVERT_ALL_BOUNDARY) {
if (boundflag & SCULPTVERT_ALL_BOUNDARY) {
continue;
}
@ -4073,9 +4113,11 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
if (l->v == v) {
mv_l = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->next->v);
pbvh_boundary_update_bmesh(pbvh, l->next->v);
}
else {
mv_l = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->v);
pbvh_boundary_update_bmesh(pbvh, l->v);
}
MV_ADD_FLAG(mv_l, updateflag);
@ -4207,6 +4249,10 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, vs[1]);
MSculptVert *mv3 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, vs[2]);
pbvh_boundary_update_bmesh(pbvh, vs[0]);
pbvh_boundary_update_bmesh(pbvh, vs[1]);
pbvh_boundary_update_bmesh(pbvh, vs[2]);
MV_ADD_FLAG(mv1, updateflag);
MV_ADD_FLAG(mv2, updateflag);
MV_ADD_FLAG(mv3, updateflag);
@ -4242,6 +4288,10 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, vs[1]);
MSculptVert *mv3 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, vs[2]);
pbvh_boundary_update_bmesh(pbvh, vs[0]);
pbvh_boundary_update_bmesh(pbvh, vs[1]);
pbvh_boundary_update_bmesh(pbvh, vs[2]);
MV_ADD_FLAG(mv1, updateflag);
MV_ADD_FLAG(mv2, updateflag);
MV_ADD_FLAG(mv3, updateflag);
@ -4375,8 +4425,11 @@ static void on_vert_swap(BMVert *v1, BMVert *v2, void *userdata)
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v2);
MV_ADD_FLAG(mv1, SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv2, SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
pbvh_boundary_update_bmesh(pbvh, v1);
pbvh_boundary_update_bmesh(pbvh, v2);
MV_ADD_FLAG(mv1, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv2, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
int ni1 = BM_ELEM_CD_GET_INT(v1, pbvh->cd_vert_node_offset);
int ni2 = BM_ELEM_CD_GET_INT(v2, pbvh->cd_vert_node_offset);
@ -5074,9 +5127,9 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
l2->e->head.hflag &= ~SPLIT_TAG;
l2->v->head.hflag &= ~SPLIT_TAG;
pbvh_boundary_update_bmesh(pbvh, l2->v);
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l2->v);
MV_ADD_FLAG(
mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
if (_j > 10000) {
printf("infinite loop error 1\n");
@ -5240,12 +5293,14 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, newv);
newv->head.hflag |= SPLIT_TAG;
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT);
pbvh_boundary_update_bmesh(pbvh, newv);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
mv->stroke_id = pbvh->stroke_id;
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY);
mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, e->v1 != newv ? e->v1 : e->v2);
pbvh_boundary_update_bmesh(pbvh, e->v1 != newv ? e->v1 : e->v2);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE);
BM_ELEM_CD_SET_INT(newv, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
@ -5686,7 +5741,8 @@ void BKE_dyntopo_remesh(DynTopoState *ds,
BM_ITER_MESH (v, &iter, ds->pbvh->header.bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(ds->pbvh->cd_sculpt_vert, v);
mv->flag |= SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_TRIANGULATE;
pbvh_boundary_update_bmesh(ds->pbvh, v);
mv->flag |= SCULPTVERT_NEED_TRIANGULATE;
mv->valence = BM_vert_edge_count(v);
pbvh_check_vert_boundary(ds->pbvh, v);
@ -5749,17 +5805,19 @@ void BKE_dyntopo_remesh(DynTopoState *ds,
BM_ITER_MESH (v, &iter, ds->pbvh->header.bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(ds->pbvh->cd_sculpt_vert, v);
pbvh_check_vert_boundary(ds->pbvh, v);
int boundflag = BM_ELEM_CD_GET_INT(v, ds->pbvh->cd_boundary_flag);
float avg[3] = {0.0f, 0.0f, 0.0f};
float totw = 0.0f;
bool bound1 = mv->flag & SCULPTVERT_ALL_BOUNDARY;
bool bound1 = boundflag & SCULPTVERT_ALL_BOUNDARY;
if (bound1) {
continue;
}
if (mv->flag & SCULPTVERT_ALL_CORNER) {
if (boundflag & SCULPTVERT_ALL_CORNER) {
continue;
}
@ -5773,7 +5831,9 @@ void BKE_dyntopo_remesh(DynTopoState *ds,
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(ds->pbvh->cd_sculpt_vert, v2);
pbvh_check_vert_boundary(ds->pbvh, v2);
bool bound2 = mv2->flag & SCULPTVERT_ALL_BOUNDARY;
int boundflag2 = BM_ELEM_CD_GET_INT(v2, ds->pbvh->cd_boundary_flag);
bool bound2 = boundflag2 & SCULPTVERT_ALL_BOUNDARY;
if (bound1 && !bound2) {
continue;

View File

@ -1392,6 +1392,43 @@ bool paint_calculate_rake_rotation(UnifiedPaintSettings *ups,
return ok;
}
ATTR_NO_OPT static bool sculpt_boundary_flags_ensure(Object *ob, PBVH *pbvh, int totvert)
{
SculptSession *ss = ob->sculpt;
bool ret = false;
if (!ss->attrs.boundary_flags) {
SculptAttributeParams params = {0};
params.nointerp = true;
// params.nocopy = true;
ss->attrs.boundary_flags = sculpt_attribute_ensure_ex(ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_ATTRIBUTE_NAME(boundary_flags),
&params,
BKE_pbvh_type(pbvh));
for (int i = 0; i < totvert; i++) {
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(pbvh, i);
BKE_sculpt_boundary_flag_update(ss, vertex);
}
ret = true;
}
BKE_pbvh_set_boundary_flags(pbvh, reinterpret_cast<int *>(ss->attrs.boundary_flags->data));
return ret;
}
bool BKE_sculptsession_boundary_flags_ensure(Object *ob)
{
return sculpt_boundary_flags_ensure(
ob, ob->sculpt->pbvh, BKE_sculptsession_vertex_count(ob->sculpt));
}
void BKE_sculptsession_free_deformMats(SculptSession *ss)
{
MEM_SAFE_FREE(ss->orig_cos);
@ -1538,7 +1575,6 @@ void BKE_sculptsession_free(Object *ob)
SculptSession *ss = ob->sculpt;
if (ss->msculptverts) {
MEM_freeN(ss->msculptverts);
ss->msculptverts = NULL;
}
@ -1851,6 +1887,8 @@ static void sculpt_update_object(
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
sculpt_boundary_flags_ensure(ob, pbvh, BKE_sculptsession_vertex_count(ss));
BKE_pbvh_update_active_vcol(pbvh, me);
if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
@ -1991,7 +2029,7 @@ static void sculpt_update_object(
break;
}
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, totvert);
BKE_sculptsession_check_sculptverts(ob, pbvh, totvert);
if (ss->bm && me->key && ob->shapenr != ss->bm->shapenr) {
KeyBlock *actkey = static_cast<KeyBlock *>(BLI_findlink(&me->key->block, ss->bm->shapenr - 1));
@ -2142,6 +2180,11 @@ static void sculpt_update_object(
}
}
}
if (ss->pbvh) {
BKE_pbvh_set_face_areas(ss->pbvh, ss->face_areas);
BKE_pbvh_set_sculpt_verts(ss->pbvh, ss->msculptverts);
}
}
void BKE_sculpt_update_object_before_eval(Object *ob_eval)
@ -2273,14 +2316,14 @@ int *BKE_sculpt_face_sets_ensure(Object *ob)
face_sets.finish();
}
return static_cast<int *>(
return ss->face_sets = static_cast<int *>(
CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set"));
}
bool *BKE_sculpt_hide_poly_ensure(Object *ob)
{
if (ob->sculpt->attrs.hide_poly) {
return static_cast<bool *>(ob->sculpt->attrs.hide_poly->data);
return ob->sculpt->hide_poly = static_cast<bool *>(ob->sculpt->attrs.hide_poly->data);
}
SculptAttributeParams params = {0};
@ -2289,7 +2332,7 @@ bool *BKE_sculpt_hide_poly_ensure(Object *ob)
ob->sculpt->attrs.hide_poly = BKE_sculpt_attribute_ensure(
ob, ATTR_DOMAIN_POINT, CD_PROP_BOOL, ".hide_poly", &params);
return static_cast<bool *>(ob->sculpt->attrs.hide_poly->data);
return ob->sculpt->hide_poly = static_cast<bool *>(ob->sculpt->attrs.hide_poly->data);
}
int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
@ -2499,6 +2542,10 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob, bool update_sculptverts
pbvh = ob->sculpt->pbvh = BKE_pbvh_new(PBVH_BMESH);
BKE_pbvh_set_bmesh(pbvh, ob->sculpt->bm);
BM_mesh_elem_table_ensure(ob->sculpt->bm, BM_VERT | BM_EDGE | BM_FACE);
sculpt_boundary_flags_ensure(ob, pbvh, ob->sculpt->bm->totvert);
sculptsession_bmesh_add_layers(ob);
BKE_pbvh_build_bmesh(pbvh,
BKE_object_get_original_mesh(ob),
@ -2509,6 +2556,7 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob, bool update_sculptverts
ob->sculpt->attrs.dyntopo_node_id_face->bmesh_cd_offset,
ob->sculpt->cd_sculpt_vert,
ob->sculpt->cd_face_areas,
ob->sculpt->attrs.boundary_flags->bmesh_cd_offset,
ob->sculpt->fast_draw,
update_sculptverts);
}
@ -2578,7 +2626,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
BKE_mesh_recalc_looptri(
loops.data(), polys.data(), verts.data(), me->totloop, me->totpoly, looptri);
BKE_sculptsession_check_sculptverts(ss, pbvh, me->totvert);
BKE_sculptsession_check_sculptverts(ob, pbvh, me->totvert);
BKE_pbvh_build_mesh(pbvh,
me,
@ -2601,7 +2649,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
}
BKE_pbvh_set_pmap(pbvh, ss->pmap);
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, me->totvert);
BKE_sculptsession_check_sculptverts(ob, pbvh, me->totvert);
MEM_SAFE_FREE(ss->face_areas);
ss->face_areas = static_cast<float *>(
@ -2639,7 +2687,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
PBVH *pbvh = nullptr;
#endif
int totgridfaces = base_mesh->totpoly * (key.grid_size - 1) * (key.grid_size - 1);
int totgridfaces = base_mesh->totloop * (key.grid_size - 1) * (key.grid_size - 1);
MEM_SAFE_FREE(ss->face_areas);
ss->face_areas = static_cast<float *>(
MEM_calloc_arrayN(totgridfaces, sizeof(float) * 2, "ss->face_areas"));
@ -2682,7 +2730,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
BKE_pbvh_set_pmap(pbvh, ss->pmap);
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, BKE_pbvh_get_grid_num_verts(pbvh));
BKE_sculptsession_check_sculptverts(ob, pbvh, BKE_pbvh_get_grid_num_verts(pbvh));
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
@ -2694,43 +2742,51 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
return pbvh;
}
bool BKE_sculptsession_check_sculptverts(SculptSession *ss, PBVH *pbvh, int totvert)
extern "C" bool BKE_sculptsession_check_sculptverts(Object *ob, struct PBVH *pbvh, int totvert)
{
if (!ss->bm && (!ss->msculptverts || totvert != ss->msculptverts_size)) {
SculptSession *ss = ob->sculpt;
sculpt_boundary_flags_ensure(ob, pbvh, totvert);
if (!ss->attrs.sculpt_vert) {
SculptAttributeParams params = {0};
ss->attrs.sculpt_vert = sculpt_attribute_ensure_ex(
ob, ATTR_DOMAIN_POINT, CD_DYNTOPO_VERT, "", &params, BKE_pbvh_type(pbvh));
}
if (!ss->bm && (!ss->msculptverts || totvert != ss->last_msculptverts_count)) {
ss->last_msculptverts_count = totvert;
ss->msculptverts = static_cast<MSculptVert *>(ss->attrs.sculpt_vert->data);
init_sculptvert_layer(ss, pbvh, totvert);
return true;
}
BKE_pbvh_set_mdyntopo_verts(pbvh, ss->msculptverts);
BKE_pbvh_set_sculpt_verts(pbvh, ss->msculptverts);
return false;
}
static void init_sculptvert_layer_faces(SculptSession *ss, PBVH *pbvh, int totvert)
{
if (ss->msculptverts) {
MEM_freeN(ss->msculptverts);
}
ss->msculptverts = static_cast<MSculptVert *>(
MEM_calloc_arrayN(totvert, sizeof(*ss->msculptverts), "msculptverts"));
ss->msculptverts_size = totvert;
BKE_pbvh_set_mdyntopo_verts(pbvh, ss->msculptverts);
BKE_pbvh_set_sculpt_verts(pbvh, ss->msculptverts);
MSculptVert *mv = ss->msculptverts;
const bool is_grid = BKE_pbvh_type(pbvh) == PBVH_GRIDS;
for (int i = 0; i < totvert; i++, mv++) {
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
mv->stroke_id = -1;
PBVHVertRef vertex = {.i = i};
BKE_sculpt_boundary_flag_update(ss, vertex);
copy_v3_v3(mv->origco, ss->mvert[i].co);
BKE_pbvh_update_vert_boundary_faces(ss->face_sets,
BKE_pbvh_update_vert_boundary_faces(static_cast<int *>(ss->attrs.boundary_flags->data),
ss->face_sets,
ss->hide_poly,
ss->mvert,
ss->medge,
@ -2741,35 +2797,27 @@ static void init_sculptvert_layer_faces(SculptSession *ss, PBVH *pbvh, int totve
vertex);
// can't fully update boundary here, so still flag for update
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
BKE_sculpt_boundary_flag_update(ss, vertex);
}
}
static void init_sculptvert_layer_grids(SculptSession *ss, PBVH *pbvh, int totvert)
{
if (ss->msculptverts) {
MEM_freeN(ss->msculptverts);
}
ss->msculptverts = static_cast<MSculptVert *>(
MEM_calloc_arrayN(totvert, sizeof(*ss->msculptverts), "msculptverts"));
ss->msculptverts_size = totvert;
BKE_pbvh_set_mdyntopo_verts(pbvh, ss->msculptverts);
BKE_pbvh_set_sculpt_verts(pbvh, ss->msculptverts);
MSculptVert *mv = ss->msculptverts;
for (int i = 0; i < totvert; i++, mv++) {
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT);
mv->stroke_id = -1;
PBVHVertRef vertex = {.i = i};
BKE_sculpt_boundary_flag_update(ss, vertex);
BKE_pbvh_update_vert_boundary_grids(pbvh, ss->subdiv_ccg, vertex);
// can't fully update boundary here, so still flag for update
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
BKE_sculpt_boundary_flag_update(ss, vertex);
}
}
@ -2884,7 +2932,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
else if (ob->type == OB_MESH) {
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
BKE_sculptsession_check_sculptverts(ob->sculpt, me_eval_deform->totvert);
BKE_sculptsession_check_sculptverts(ob, me_eval_deform->totvert);
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
}
@ -3362,6 +3410,7 @@ ATTR_NO_OPT static bool sculpt_attr_update(Object *ob, SculptAttribute *attr)
if (ss->bm) {
attr->bmesh_cd_offset = cdata->layers[layer_index].offset;
attr->data = nullptr;
}
}
}
@ -3455,19 +3504,7 @@ SculptAttribute *BKE_sculpt_attribute_get(struct Object *ob,
int index = CustomData_get_named_layer_index(cdata, proptype, name);
if (index != -1) {
int totelem = 0;
switch (domain) {
case ATTR_DOMAIN_POINT:
totelem = BKE_sculptsession_vertex_count(ss);
break;
case ATTR_DOMAIN_FACE:
totelem = ss->totfaces;
break;
default:
BLI_assert_unreachable();
break;
}
int totelem = sculpt_attr_elem_count_get(ob, ATTR_DOMAIN_POINT);
attr = sculpt_alloc_attr(ss);
@ -3533,13 +3570,22 @@ static void sculptsession_bmesh_attr_update_internal(Object *ob)
int cd_sculpt_vert = CustomData_get_offset(&ss->bm->vdata, CD_DYNTOPO_VERT);
int cd_face_area = ss->attrs.face_areas ? ss->attrs.face_areas->bmesh_cd_offset : -1;
int cd_hide_poly = ss->attrs.hide_poly ? ss->attrs.hide_poly->bmesh_cd_offset : -1;
int cd_boundary_flags = ss->attrs.boundary_flags ? ss->attrs.boundary_flags->bmesh_cd_offset :
-1;
int cd_dyntopo_vert = ss->attrs.dyntopo_node_id_vertex ?
ss->attrs.dyntopo_node_id_vertex->bmesh_cd_offset :
-1;
int cd_dyntopo_face = ss->attrs.dyntopo_node_id_face ?
ss->attrs.dyntopo_node_id_face->bmesh_cd_offset :
-1;
BKE_pbvh_update_offsets(ss->pbvh,
ss->attrs.dyntopo_node_id_vertex->bmesh_cd_offset,
ss->attrs.dyntopo_node_id_face->bmesh_cd_offset,
cd_dyntopo_vert,
cd_dyntopo_face,
cd_sculpt_vert,
cd_face_area,
cd_hide_poly);
cd_hide_poly,
cd_boundary_flags);
}
}
@ -3593,6 +3639,17 @@ void BKE_sculpt_attributes_destroy_temporary_stroke(Object *ob)
SculptAttribute *attr = ss->temp_attributes + i;
if (attr->params.stroke_only) {
/* Don't free BMesh attribute as it is quite expensive;
* note that temporary attributes are still freed on
* exiting sculpt mode.
*
* Attributes allocated as simple arrays are fine however.
*/
if (!attr->params.simple_array && ss->bm) {
continue;
}
BKE_sculpt_attribute_destroy(ob, attr);
}
}
@ -3627,13 +3684,17 @@ static void update_bmesh_offsets(Mesh *me, SculptSession *ss)
ss->cd_face_areas = ss->attrs.face_areas ? ss->attrs.face_areas->bmesh_cd_offset : -1;
ss->cd_hide_poly = ss->attrs.hide_poly ? ss->attrs.hide_poly->bmesh_cd_offset : -1;
int cd_boundary_flags = ss->attrs.boundary_flags ? ss->attrs.boundary_flags->bmesh_cd_offset :
-1;
if (ss->pbvh) {
BKE_pbvh_update_offsets(ss->pbvh,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_sculpt_vert,
ss->cd_face_areas,
ss->cd_hide_poly);
ss->cd_hide_poly,
cd_boundary_flags);
}
}

View File

@ -620,11 +620,6 @@ void BKE_pbvh_set_face_areas(PBVH *pbvh, float *face_areas)
pbvh->face_areas = face_areas;
}
void BKE_pbvh_set_sculpt_verts(PBVH *pbvh, MSculptVert *sverts)
{
pbvh->msculptverts = sverts;
}
/* XXX investigate this global. */
bool pbvh_show_orig_co;
@ -1542,8 +1537,6 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
Mesh me_query;
BKE_id_attribute_copy_domains_temp(ID_ME, vdata, NULL, ldata, NULL, NULL, &me_query.id);
CustomDataLayer *render_vcol_layer = BKE_id_attributes_render_color_get(&me_query.id);
if (!pbvh->header.bm) {
vdata = pbvh->vdata;
ldata = pbvh->ldata;
@ -4128,16 +4121,18 @@ ATTR_NO_OPT void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node)
return;
}
if (pbvh->header.type == PBVH_BMESH && (!node->tribuf || !node->tribuf->tottri)) {
return;
if (pbvh->header.type == PBVH_BMESH) {
if (node->flag & PBVH_UpdateTris) {
BKE_pbvh_bmesh_check_tris(pbvh, node);
}
if (!node->tribuf || !node->tribuf->tottri) {
return;
}
}
node->flag &= ~PBVH_UpdateTriAreas;
if (pbvh->header.type == PBVH_BMESH && (node->flag & PBVH_UpdateTris)) {
BKE_pbvh_bmesh_check_tris(pbvh, node);
}
const int cur_i = pbvh->face_area_i ^ 1;
switch (BKE_pbvh_type(pbvh)) {
@ -4467,9 +4462,7 @@ static void pbvh_boundaries_flag_update(PBVH *pbvh)
BMIter iter;
BM_ITER_MESH (v, &iter, pbvh->header.bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_sculpt_vert);
mv->flag |= SCULPTVERT_NEED_BOUNDARY;
pbvh_boundary_update_bmesh(pbvh, v);
}
}
else {
@ -4480,7 +4473,7 @@ static void pbvh_boundaries_flag_update(PBVH *pbvh)
}
for (int i = 0; i < totvert; i++) {
pbvh->msculptverts[i].flag |= SCULPTVERT_NEED_BOUNDARY;
pbvh->boundary_flags[i] |= SCULPT_BOUNDARY_NEEDS_UPDATE;
}
}
}
@ -4497,9 +4490,9 @@ void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry)
pbvh_boundaries_flag_update(pbvh);
}
void BKE_pbvh_set_mdyntopo_verts(PBVH *pbvh, struct MSculptVert *mdyntopoverts)
void BKE_pbvh_set_sculpt_verts(PBVH *pbvh, struct MSculptVert *msculptverts)
{
pbvh->msculptverts = mdyntopoverts;
pbvh->msculptverts = msculptverts;
}
void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
@ -4508,9 +4501,10 @@ void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
{
MSculptVert *mv = pbvh->msculptverts + vertex.i;
mv->flag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
SCULPTVERT_FSET_CORNER | SCULPTVERT_CORNER | SCULPTVERT_SEAM_BOUNDARY |
SCULPTVERT_SHARP_BOUNDARY | SCULPTVERT_SEAM_CORNER | SCULPTVERT_SHARP_CORNER);
int *flags = pbvh->boundary_flags + vertex.i;
*flags = 0;
/* TODO: finish this function. */
int index = (int)vertex.i;
@ -4532,7 +4526,8 @@ void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
mv->flag &= ~SCULPTVERT_NEED_VALENCE;
}
void BKE_pbvh_update_vert_boundary_faces(const int *face_sets,
void BKE_pbvh_update_vert_boundary_faces(int *boundary_flags,
const int *face_sets,
const bool *hide_poly,
const MVert *mvert,
const MEdge *medge,
@ -4545,12 +4540,13 @@ void BKE_pbvh_update_vert_boundary_faces(const int *face_sets,
MSculptVert *mv = msculptverts + vertex.i;
const MeshElemMap *vert_map = &pmap[vertex.i];
mv->flag &= ~SCULPTVERT_VERT_FSET_HIDDEN;
int last_fset = -1;
int last_fset2 = -1;
mv->flag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
SCULPTVERT_FSET_CORNER | SCULPTVERT_CORNER | SCULPTVERT_SEAM_BOUNDARY |
SCULPTVERT_SHARP_BOUNDARY | SCULPTVERT_SEAM_CORNER | SCULPTVERT_SHARP_CORNER);
int *flags = boundary_flags + vertex.i;
*flags = 0;
int totsharp = 0, totseam = 0;
int visible = false;
@ -4571,12 +4567,12 @@ void BKE_pbvh_update_vert_boundary_faces(const int *face_sets,
if (j < mp->totloop) {
const MEdge *me = medge + ml->e;
if (me->flag & ME_SHARP) {
mv->flag |= SCULPTVERT_SHARP_BOUNDARY;
*flags |= SCULPT_BOUNDARY_SHARP;
totsharp++;
}
if (me->flag & ME_SEAM) {
mv->flag |= SCULPTVERT_SEAM_BOUNDARY;
*flags |= SCULPT_BOUNDARY_SEAM;
totseam++;
}
}
@ -4588,11 +4584,11 @@ void BKE_pbvh_update_vert_boundary_faces(const int *face_sets,
}
if (i > 0 && fset != last_fset) {
mv->flag |= SCULPTVERT_FSET_BOUNDARY;
*flags |= SCULPT_BOUNDARY_FACE_SET;
if (i > 1 && last_fset2 != last_fset && last_fset != -1 && last_fset2 != -1 && fset != -1 &&
last_fset2 != fset) {
mv->flag |= SCULPTVERT_FSET_CORNER;
*flags |= SCULPT_CORNER_FACE_SET;
}
}
@ -4608,11 +4604,11 @@ void BKE_pbvh_update_vert_boundary_faces(const int *face_sets,
}
if (totsharp > 2) {
mv->flag |= SCULPTVERT_SHARP_CORNER;
*flags |= SCULPT_CORNER_SHARP;
}
if (totseam > 2) {
mv->flag |= SCULPTVERT_SEAM_CORNER;
*flags |= SCULPT_CORNER_SEAM;
}
}
@ -4832,9 +4828,9 @@ void BKE_pbvh_invalidate_cache(Object *ob)
char key[PBVH_CACHE_KEY_SIZE];
pbvh_make_cached_key(ob_orig, key);
#ifdef WITH_PBVH_CACHE
PBVH *pbvh = BLI_ghash_lookup(cached_pbvhs, key);
#ifdef WITH_PBVH_CACHE
if (pbvh) {
BKE_pbvh_cache_remove(pbvh);
}
@ -5273,3 +5269,8 @@ int BKE_pbvh_debug_draw_gen_get(PBVHNode *node)
{
return node->debug_draw_gen;
}
void BKE_pbvh_set_boundary_flags(PBVH *pbvh, int *boundary_flags)
{
pbvh->boundary_flags = boundary_flags;
}

View File

@ -265,7 +265,9 @@ static void pbvh_bmesh_node_finalize(PBVH *pbvh,
do {
BMVert *v = l_iter->v;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
int *flags = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
*flags |= SCULPT_BOUNDARY_NEEDS_UPDATE;
if (!BLI_table_gset_haskey(n->bm_unique_verts, v)) {
if (BM_ELEM_CD_GET_INT(v, cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
@ -1666,6 +1668,7 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol,
int cd_boundary_flag,
BMVert *v,
int bound_symmetry,
const CustomData *ldata,
@ -1678,20 +1681,21 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
int newflag = mv->flag;
int oldflag = newflag;
int oldval = mv->valence;
int boundflag = 0;
BMEdge *e = v->e;
newflag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_FSET_CORNER | SCULPTVERT_CORNER |
SCULPTVERT_NEED_VALENCE | SCULPTVERT_SEAM_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY |
SCULPTVERT_SEAM_CORNER | SCULPTVERT_SHARP_CORNER | SCULPTVERT_PBVH_BOUNDARY |
SCULPTVERT_UV_BOUNDARY | SCULPTVERT_UV_CORNER);
newflag &= ~(SCULPTVERT_VERT_FSET_HIDDEN | SCULPTVERT_PBVH_BOUNDARY);
ushort stroke_id = (ushort)mv->stroke_id;
if (!e) {
newflag |= SCULPTVERT_BOUNDARY;
boundflag |= SCULPT_BOUNDARY_MESH;
int oldboundflag = BM_ELEM_CD_GET_INT(v, cd_boundary_flag);
atomic_cas_int32(&mv->flag, oldflag, newflag);
atomic_cas_int32((int *)BM_ELEM_CD_GET_VOID_P(v, cd_boundary_flag), oldboundflag, boundflag);
atomic_cas_short2(&mv->valence, (ushort)oldval, stroke_id, 0, stroke_id);
return;
@ -1752,11 +1756,11 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
}
if (e->head.hflag & BM_ELEM_SEAM) {
newflag |= SCULPTVERT_SEAM_BOUNDARY;
boundflag |= SCULPT_BOUNDARY_SEAM;
seamcount++;
if (seamcount > 2) {
newflag |= SCULPTVERT_SEAM_CORNER;
boundflag |= SCULPT_CORNER_SEAM;
}
}
@ -1773,17 +1777,17 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
int colorkey2 = color_boundary_key(color2);
if (colorkey1 != colorkey2) {
newflag |= SCULPTVERT_FSET_BOUNDARY;
boundflag |= SCUKPT_BOUNDARY_FACE_SETS;
}
}
#endif
if (!(e->head.hflag & BM_ELEM_SMOOTH)) {
newflag |= SCULPTVERT_SHARP_BOUNDARY;
boundflag |= SCULPT_BOUNDARY_SHARP;
sharpcount++;
if (sharpcount > 2) {
newflag |= SCULPTVERT_SHARP_CORNER;
boundflag |= SCULPT_CORNER_SHARP;
}
}
@ -1814,11 +1818,11 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
len_squared_v2v2(lastuv2[i], luv->uv) > uv_snap_limit;
if (!same) {
newflag |= SCULPTVERT_UV_BOUNDARY;
boundflag |= SCULPT_BOUNDARY_UV;
}
if (corner) {
newflag |= SCULPTVERT_UV_CORNER;
boundflag |= SCULPT_CORNER_UV;
}
if (!same) {
@ -1903,30 +1907,30 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
}
if (!e->l || e->l->radial_next == e->l) {
newflag |= SCULPTVERT_BOUNDARY;
boundflag |= SCULPT_BOUNDARY_MESH;
}
val++;
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
if (BLI_array_len(fsets) > 1) {
newflag |= SCULPTVERT_FSET_BOUNDARY;
boundflag |= SCULPT_BOUNDARY_FACE_SET;
}
if (BLI_array_len(fsets) > 2) {
newflag |= SCULPTVERT_FSET_CORNER;
boundflag |= SCULPT_CORNER_FACE_SET;
}
if (sharpcount == 1) {
newflag |= SCULPTVERT_SHARP_CORNER;
boundflag |= SCULPT_CORNER_SHARP;
}
if (seamcount == 1) {
newflag |= SCULPTVERT_SEAM_CORNER;
boundflag |= SCULPT_CORNER_SEAM;
}
if ((newflag & SCULPTVERT_BOUNDARY) && quadcount >= 3) {
newflag |= SCULPTVERT_CORNER;
if ((boundflag & SCULPT_BOUNDARY_MESH) && quadcount >= 3) {
boundflag |= SCULPT_CORNER_MESH;
}
#if 0
@ -1947,7 +1951,11 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
}
#endif
int oldboundflag = BM_ELEM_CD_GET_INT(v, cd_boundary_flag);
atomic_cas_int32(&mv->flag, oldflag, newflag);
atomic_cas_int32((int *)BM_ELEM_CD_GET_VOID_P(v, cd_boundary_flag), oldboundflag, boundflag);
atomic_cas_short2(&mv->valence, (ushort)oldval, stroke_id, (ushort)val, stroke_id);
/* no atomic_cas_int16, so do origmask and curv at once */
@ -1971,6 +1979,7 @@ void BKE_pbvh_update_vert_boundary(int cd_sculpt_vert,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol,
int cd_boundary_flag,
BMVert *v,
int bound_symmetry,
const CustomData *ldata,
@ -1982,6 +1991,7 @@ void BKE_pbvh_update_vert_boundary(int cd_sculpt_vert,
cd_vert_node_offset,
cd_face_node_offset,
cd_vcol,
cd_boundary_flag,
v,
bound_symmetry,
ldata,
@ -2000,6 +2010,7 @@ void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh)
pbvh->cd_vert_node_offset,
pbvh->cd_face_node_offset,
pbvh->cd_vcol_offset,
pbvh->cd_boundary_flag,
v,
pbvh->boundary_symmetry,
&pbvh->header.bm->ldata,
@ -2007,89 +2018,6 @@ void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh)
}
}
void BKE_pbvh_update_all_boundary_bmesh(PBVH *pbvh)
{
// update boundary flags in a hopefully faster manner then v->e iteration
// XXX or not, it's slower
BMIter iter;
BMEdge *e;
BMVert *v;
const int cd_fset = CustomData_get_offset_named(
&pbvh->header.bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
BM_ITER_MESH (v, &iter, pbvh->header.bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
mv->flag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
SCULPTVERT_VERT_FSET_HIDDEN);
if (cd_fset != -1 && v->e && v->e->l) {
mv->flag |= SCULPTVERT_VERT_FSET_HIDDEN;
}
}
BM_ITER_MESH (e, &iter, pbvh->header.bm, BM_EDGES_OF_MESH) {
if (!e->l || e->l == e->l->radial_next) {
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, e->v2);
mv1->flag |= SCULPTVERT_BOUNDARY;
mv2->flag |= SCULPTVERT_BOUNDARY;
}
if (!e->l) {
continue;
}
if (cd_fset == -1) {
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, e->v2);
BMLoop *l = e->l;
do {
if (l->f->len > 3) {
mv1->flag |= SCULPTVERT_NEED_TRIANGULATE;
mv2->flag |= SCULPTVERT_NEED_TRIANGULATE;
break;
}
l = l->radial_next;
} while (l != e->l);
continue;
}
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, e->v2);
BMLoop *l = e->l;
int lastfset = cd_fset != -1 ? BM_ELEM_CD_GET_INT(l->f, cd_fset) : 0;
do {
int fset = cd_fset != -1 ? BM_ELEM_CD_GET_INT(l->f, cd_fset) : 0;
if (l->f->len > 3) {
mv1->flag |= SCULPTVERT_NEED_TRIANGULATE;
mv2->flag |= SCULPTVERT_NEED_TRIANGULATE;
}
if (fset > 0) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->v);
mv->flag &= ~SCULPTVERT_VERT_FSET_HIDDEN;
}
if (lastfset != fset) {
mv1->flag |= SCULPTVERT_FSET_BOUNDARY;
mv2->flag |= SCULPTVERT_FSET_BOUNDARY;
}
lastfset = fset;
l = l->radial_next;
} while (l != e->l);
}
}
typedef struct FaceBinThread {
MemArena *arena;
FastNodeBuildInfo *nodes, **leaves;
@ -2244,6 +2172,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
const int cd_face_node_offset,
const int cd_sculpt_vert,
const int cd_face_areas,
const int cd_boundary_flag,
bool fast_draw,
bool update_sculptverts)
{
@ -2256,6 +2185,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
pbvh->cd_face_node_offset = cd_face_node_offset;
pbvh->cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
pbvh->cd_sculpt_vert = cd_sculpt_vert;
pbvh->cd_boundary_flag = cd_boundary_flag;
pbvh->mesh = me;
@ -2327,8 +2257,10 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
mv->flag |= SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_TRIANGULATE |
SCULPTVERT_NEED_DISK_SORT;
mv->flag |= SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT;
int *flags = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
*flags |= SCULPT_BOUNDARY_NEEDS_UPDATE;
BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE);
}
@ -3115,9 +3047,10 @@ void BKE_pbvh_bmesh_on_mesh_change(PBVH *pbvh)
BM_ITER_MESH (v, &iter, pbvh->header.bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, v);
int *flags = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
*flags |= SCULPT_BOUNDARY_NEEDS_UPDATE;
MV_ADD_FLAG(
mv, SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_TRIANGULATE);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_TRIANGULATE);
BKE_pbvh_bmesh_update_valence(pbvh->cd_sculpt_vert, (PBVHVertRef){.i = (intptr_t)v});
}
}
@ -3210,8 +3143,8 @@ static void pbvh_bmesh_join_subnodes(PBVH *pbvh, PBVHNode *node, PBVHNode *paren
TGSET_ITER (v, node->bm_unique_verts) {
BLI_table_gset_add(parent->bm_unique_verts, v);
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY); // need to update SCULPTVERT_PBVH_BOUNDARY flags
int *flags = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
*flags |= SCULPT_BOUNDARY_NEEDS_UPDATE;
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
}
@ -3651,8 +3584,8 @@ static void pbvh_bmesh_balance_tree(PBVH *pbvh)
TGSET_ITER_END;
TGSET_ITER (v, node2->bm_unique_verts) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
int *flags = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
*flags |= SCULPT_BOUNDARY_NEEDS_UPDATE;
BM_ELEM_CD_SET_INT(v, cd_vert_node, DYNTOPO_NODE_NONE);
}
@ -4006,7 +3939,8 @@ void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_face_node_offset,
const int cd_sculpt_vert,
const int cd_face_areas,
const int cd_hide_poly)
const int cd_hide_poly,
const int cd_boundary_flag)
{
pbvh->cd_hide_poly = cd_hide_poly;
pbvh->cd_face_node_offset = cd_face_node_offset;
@ -4018,6 +3952,7 @@ void BKE_pbvh_update_offsets(PBVH *pbvh,
&pbvh->header.bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
pbvh->totuv = CustomData_number_of_layers(&pbvh->header.bm->ldata, CD_MLOOPUV);
pbvh->cd_boundary_flag = cd_boundary_flag;
}
static void scan_edge_split(BMesh *bm, BMEdge **edges, int totedge)
@ -5505,6 +5440,7 @@ void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT32, "__dyntopo_vert_node");
BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT32, "__dyntopo_face_node");
BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT32, ".sculpt_boundary_flags");
BM_data_layer_add(bm, &bm->vdata, CD_PAINT_MASK);
BM_data_layer_add(bm, &bm->vdata, CD_DYNTOPO_VERT);
@ -5627,8 +5563,11 @@ void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
&bm->pdata, CD_PROP_INT32, "__dyntopo_face_node");
int cd_face_area = CustomData_get_named_layer_index(
&bm->pdata, CD_PROP_FLOAT2, "__dyntopo_face_areas");
int cd_boundary_flag = CustomData_get_named_layer_index(
&bm->vdata, CD_PROP_INT32, ".sculpt_boundary_flags");
cd_vert_node = bm->vdata.layers[cd_vert_node].offset;
cd_boundary_flag = bm->vdata.layers[cd_boundary_flag].offset;
cd_face_node = bm->pdata.layers[cd_face_node].offset;
cd_face_area = bm->pdata.layers[cd_face_area].offset;
@ -5651,6 +5590,7 @@ void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
cd_face_node,
cd_sculpt_vert,
cd_face_area,
cd_boundary_flag,
false,
true);

View File

@ -9,6 +9,7 @@
#include "DNA_material_types.h"
#include "BKE_attribute.h"
#include "BKE_paint.h" /* for SCULPT_BOUNDARY_NEEDS_UPDATE */
#include "BKE_pbvh.h"
#include "bmesh.h"
@ -280,6 +281,8 @@ struct PBVH {
bool draw_cache_invalid;
struct PBVHGPUFormat *vbo_id;
int *boundary_flags;
int cd_boundary_flag;
};
/* pbvh.c */
@ -422,21 +425,25 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol_offset,
BMVert *v,
int cd_boundary_flags,
BMVert * v,
int bound_symmetry,
const struct CustomData *ldata,
const int totuv);
void pbvh_boundary_update_bmesh(PBVH *pbvh, struct BMVert *v);
bool pbvh_boundary_needs_update_bmesh(PBVH *pbvh, struct BMVert *v);
BLI_INLINE bool pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v)
{
MSculptVert *mv = (MSculptVert *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_sculpt_vert);
int *flag = (int *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_boundary_flag);
if (mv->flag & SCULPTVERT_NEED_BOUNDARY) {
if (*flag & SCULPT_BOUNDARY_NEEDS_UPDATE) {
bke_pbvh_update_vert_boundary(pbvh->cd_sculpt_vert,
pbvh->cd_faceset_offset,
pbvh->cd_vert_node_offset,
pbvh->cd_face_node_offset,
pbvh->cd_vcol_offset,
pbvh->cd_boundary_flag,
v,
pbvh->boundary_symmetry,
&pbvh->header.bm->ldata,

View File

@ -597,6 +597,8 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
case PBVH_BMESH: {
const int cd_fset = CustomData_get_named_offset(
&ss->bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
const int cd_boundary_flag = CustomData_get_offset_named(
&ss->bm->vdata, CD_PROP_INT32, SCULPT_ATTRIBUTE_NAME(boundary_flags));
if (ss->bm && cd_fset != -1) {
const int cd_sculptvert = CustomData_get_offset(&ss->bm->vdata, CD_DYNTOPO_VERT);
@ -607,12 +609,17 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
const int next_face_set_id = SCULPT_face_set_next_available_get(ss);
const int updateflag = SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_VALENCE |
SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT;
const int updateflag = SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_TRIANGULATE |
SCULPTVERT_NEED_DISK_SORT;
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BM_ELEM_CD_GET_VOID_P(v, cd_sculptvert);
if (cd_boundary_flag != -1) {
int *flag = BM_ELEM_CD_GET_VOID_P(v, cd_boundary_flag);
*flag |= SCULPT_BOUNDARY_NEEDS_UPDATE;
}
mv->flag |= updateflag;
}

View File

@ -1443,6 +1443,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
sgcontext->ss->cd_face_node_offset,
sgcontext->ss->cd_sculpt_vert,
sgcontext->ss->cd_face_areas,
sgcontext->ss->attrs.boundary_flags->bmesh_cd_offset,
sgcontext->ss->fast_draw,
true);
}

View File

@ -918,10 +918,11 @@ bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef ve
void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_set)
{
BKE_sculpt_boundary_flag_update(ss, vertex);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MSculptVert *mv = ss->msculptverts + vertex.i;
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
BLI_assert(ss->face_sets != NULL);
const MeshElemMap *vert_map = &ss->pmap->pmap[vertex.i];
@ -936,8 +937,8 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
const MLoop *ml = ss->mloop + mp->loopstart;
for (int k = 0; k < mp->totloop; k++, ml++) {
MSculptVert *mv2 = ss->msculptverts + ml->v;
MV_ADD_FLAG(mv2, SCULPTVERT_NEED_BOUNDARY);
PBVHVertRef vertex2 = {ml->v};
BKE_sculpt_boundary_flag_update(ss, vertex2);
}
ss->face_sets[poly_index] = face_set;
@ -952,17 +953,14 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
int cd_hide_poly = ss->attrs.hide_poly->bmesh_cd_offset;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
int fset = BM_ELEM_CD_GET_INT(l->f, ss->cd_faceset_offset);
if (!BM_ELEM_CD_GET_BOOL(l->f, cd_hide_poly) && fset != face_set) {
BM_ELEM_CD_SET_INT(l->f, ss->cd_faceset_offset, abs(face_set));
}
MSculptVert *mv_l = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, l->v);
MV_ADD_FLAG(mv_l, SCULPTVERT_NEED_BOUNDARY);
PBVHVertRef vertex2 = {(intptr_t)l->v};
BKE_sculpt_boundary_flag_update(ss, vertex2);
}
break;
@ -1830,9 +1828,9 @@ void SCULPT_vertex_neighbors_get(const SculptSession *ss,
}
}
SculptBoundaryType SCULPT_edge_is_boundary(const SculptSession *ss,
const PBVHEdgeRef edge,
SculptBoundaryType typemask)
eSculptBoundary SCULPT_edge_is_boundary(const SculptSession *ss,
const PBVHEdgeRef edge,
eSculptBoundary typemask)
{
int ret = 0;
@ -1851,9 +1849,10 @@ SculptBoundaryType SCULPT_edge_is_boundary(const SculptSession *ss,
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, e->v2);
bool ok = (mv1->flag & SCULPTVERT_FSET_BOUNDARY) &&
(mv2->flag & SCULPTVERT_FSET_BOUNDARY);
ret |= ok ? SCULPT_BOUNDARY_FACE_SET : 0;
int boundflag1 = BM_ELEM_CD_GET_INT(e->v1, ss->attrs.boundary_flags->bmesh_cd_offset);
int boundflag2 = BM_ELEM_CD_GET_INT(e->v2, ss->attrs.boundary_flags->bmesh_cd_offset);
ret |= (boundflag1 | boundflag2) & SCULPT_BOUNDARY_FACE_SET;
}
else {
int fset1 = BM_ELEM_CD_GET_INT(e->l->f, ss->cd_faceset_offset);
@ -1868,11 +1867,10 @@ SculptBoundaryType SCULPT_edge_is_boundary(const SculptSession *ss,
}
if (typemask & SCULPT_BOUNDARY_UV) {
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, e->v2);
int boundflag1 = BM_ELEM_CD_GET_INT(e->v1, ss->attrs.boundary_flags->bmesh_cd_offset);
int boundflag2 = BM_ELEM_CD_GET_INT(e->v2, ss->attrs.boundary_flags->bmesh_cd_offset);
bool ok = (mv1->flag & SCULPTVERT_UV_BOUNDARY) && (mv2->flag & SCULPTVERT_UV_BOUNDARY);
ret |= ok ? SCULPT_BOUNDARY_UV : 0;
ret |= (boundflag1 | boundflag2) & SCULPT_BOUNDARY_UV;
}
if (typemask & SCULPT_BOUNDARY_SHARP) {
@ -1892,8 +1890,8 @@ SculptBoundaryType SCULPT_edge_is_boundary(const SculptSession *ss,
SCULPT_edge_get_verts(ss, edge, &v1, &v2);
if (mask) { // use less accurate approximation for now
SculptBoundaryType a = SCULPT_vertex_is_boundary(ss, v1, mask);
SculptBoundaryType b = SCULPT_vertex_is_boundary(ss, v2, mask);
eSculptBoundary a = SCULPT_vertex_is_boundary(ss, v1, mask);
eSculptBoundary b = SCULPT_vertex_is_boundary(ss, v2, mask);
ret |= a & b;
}
@ -1914,7 +1912,7 @@ SculptBoundaryType SCULPT_edge_is_boundary(const SculptSession *ss,
}
}
return (SculptBoundaryType)ret;
return (eSculptBoundary)ret;
}
void SCULPT_edge_get_verts(const SculptSession *ss,
@ -1963,9 +1961,9 @@ static bool sculpt_check_boundary_vertex_in_base_mesh(const SculptSession *ss, i
static void grids_update_boundary_flags(const SculptSession *ss, PBVHVertRef vertex)
{
MSculptVert *mv = ss->msculptverts + vertex.i;
int *flag = (int *)SCULPT_vertex_attr_get(vertex, ss->attrs.boundary_flags);
mv->flag &= ~(SCULPTVERT_CORNER | SCULPTVERT_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_FSET_CORNER);
*flag = 0;
int index = (int)vertex.i;
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
@ -1981,20 +1979,20 @@ static void grids_update_boundary_flags(const SculptSession *ss, PBVHVertRef ver
switch (adjacency) {
case SUBDIV_CCG_ADJACENT_VERTEX:
if (sculpt_check_unique_face_set_in_base_mesh(ss, v1)) {
mv->flag |= SCULPTVERT_FSET_BOUNDARY;
*flag |= SCULPT_BOUNDARY_FACE_SET;
}
if (sculpt_check_boundary_vertex_in_base_mesh(ss, v2)) {
mv->flag |= SCULPTVERT_BOUNDARY;
*flag |= SCULPT_BOUNDARY_MESH;
}
break;
case SUBDIV_CCG_ADJACENT_EDGE:
if (sculpt_check_unique_face_set_for_edge_in_base_mesh(ss, v1, v2)) {
mv->flag |= SCULPTVERT_FSET_BOUNDARY;
*flag |= SCULPT_BOUNDARY_FACE_SET;
}
if (sculpt_check_boundary_vertex_in_base_mesh(ss, v1) &&
sculpt_check_boundary_vertex_in_base_mesh(ss, v2)) {
mv->flag |= SCULPTVERT_BOUNDARY;
*flag |= SCULPT_BOUNDARY_MESH;
}
break;
case SUBDIV_CCG_ADJACENT_NONE:
@ -2004,7 +2002,8 @@ static void grids_update_boundary_flags(const SculptSession *ss, PBVHVertRef ver
static void faces_update_boundary_flags(const SculptSession *ss, const PBVHVertRef vertex)
{
BKE_pbvh_update_vert_boundary_faces(ss->face_sets,
BKE_pbvh_update_vert_boundary_faces((int *)ss->attrs.boundary_flags->data,
ss->face_sets,
ss->hide_poly,
ss->mvert,
ss->medge,
@ -2013,13 +2012,14 @@ static void faces_update_boundary_flags(const SculptSession *ss, const PBVHVertR
ss->msculptverts,
ss->pmap->pmap,
vertex);
// have to handle boundary here
MSculptVert *mv = ss->msculptverts + vertex.i;
mv->flag &= ~(SCULPTVERT_CORNER | SCULPTVERT_BOUNDARY);
/* We have to handle boundary here seperately. */
int *flag = SCULPT_vertex_attr_get(vertex, ss->attrs.boundary_flags);
*flag &= ~(SCULPT_CORNER_MESH | SCULPT_BOUNDARY_MESH);
if (sculpt_check_boundary_vertex_in_base_mesh(ss, vertex.i)) {
mv->flag |= SCULPTVERT_BOUNDARY;
*flag |= SCULPT_BOUNDARY_MESH;
if (ss->pmap->pmap[vertex.i].count < 4) {
bool ok = true;
@ -2031,32 +2031,34 @@ static void faces_update_boundary_flags(const SculptSession *ss, const PBVHVertR
}
}
if (ok) {
mv->flag |= SCULPTVERT_CORNER;
*flag |= SCULPT_CORNER_MESH;
}
else {
mv->flag &= ~SCULPTVERT_CORNER;
*flag &= ~SCULPT_CORNER_MESH;
}
}
}
}
SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
const PBVHVertRef vertex,
SculptCornerType cornertype)
eSculptCorner SCULPT_vertex_is_corner(const SculptSession *ss,
const PBVHVertRef vertex,
eSculptCorner cornertype)
{
SculptCornerType ret = 0;
MSculptVert *mv = NULL;
eSculptCorner ret = 0;
int flag = *(int *)SCULPT_vertex_attr_get(vertex, ss->attrs.boundary_flags);
bool needs_update = flag & SCULPT_BOUNDARY_NEEDS_UPDATE;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
BMVert *v = (BMVert *)vertex.i;
mv = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, v);
if (mv->flag & SCULPTVERT_NEED_BOUNDARY) {
if (needs_update) {
BKE_pbvh_update_vert_boundary(ss->cd_sculpt_vert,
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
-1,
ss->cd_vcol_offset,
ss->attrs.boundary_flags->bmesh_cd_offset,
(BMVert *)vertex.i,
ss->boundary_symmetry,
&ss->bm->ldata,
@ -2067,59 +2069,38 @@ SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
break;
}
case PBVH_FACES:
mv = ss->msculptverts + vertex.i;
if (mv->flag & SCULPTVERT_NEED_BOUNDARY) {
if (needs_update) {
faces_update_boundary_flags(ss, vertex);
}
break;
case PBVH_GRIDS: {
mv = ss->msculptverts + vertex.i;
if (mv->flag & SCULPTVERT_NEED_BOUNDARY) {
if (needs_update) {
grids_update_boundary_flags(ss, vertex);
}
break;
}
}
ret = 0;
if (cornertype & SCULPT_CORNER_MESH) {
ret |= (mv->flag & SCULPTVERT_CORNER) ? SCULPT_CORNER_MESH : 0;
}
if (cornertype & SCULPT_CORNER_FACE_SET) {
ret |= (mv->flag & SCULPTVERT_FSET_CORNER) ? SCULPT_CORNER_FACE_SET : 0;
}
if (cornertype & SCULPT_CORNER_SEAM) {
ret |= (mv->flag & SCULPTVERT_SEAM_CORNER) ? SCULPT_CORNER_SEAM : 0;
}
if (cornertype & SCULPT_CORNER_SHARP) {
ret |= (mv->flag & SCULPTVERT_SHARP_CORNER) ? SCULPT_CORNER_SHARP : 0;
}
if (cornertype & SCULPT_CORNER_UV) {
ret |= (mv->flag & SCULPTVERT_UV_CORNER) ? SCULPT_CORNER_UV : 0;
}
return ret;
return flag & (SCULPT_CORNER_MESH | SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SEAM |
SCULPT_CORNER_SHARP | SCULPT_CORNER_UV);
}
SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
const PBVHVertRef vertex,
SculptBoundaryType boundary_types)
eSculptBoundary SCULPT_vertex_is_boundary(const SculptSession *ss,
const PBVHVertRef vertex,
eSculptBoundary boundary_types)
{
MSculptVert *mv = NULL;
int flag = *(int *)SCULPT_vertex_attr_get(vertex, ss->attrs.boundary_flags);
bool needs_update = flag & SCULPT_BOUNDARY_NEEDS_UPDATE;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
mv = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, ((BMVert *)(vertex.i)));
if (mv->flag & SCULPTVERT_NEED_BOUNDARY) {
if (needs_update) {
BKE_pbvh_update_vert_boundary(ss->cd_sculpt_vert,
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
-1,
ss->cd_vcol_offset,
ss->attrs.boundary_flags->bmesh_cd_offset,
(BMVert *)vertex.i,
ss->boundary_symmetry,
&ss->bm->ldata,
@ -2130,9 +2111,7 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
break;
}
case PBVH_FACES: {
mv = ss->msculptverts + vertex.i;
if (mv->flag & SCULPTVERT_NEED_BOUNDARY) {
if (needs_update) {
faces_update_boundary_flags(ss, vertex);
}
break;
@ -2163,24 +2142,8 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
}
}
int flag = 0;
if (boundary_types & SCULPT_BOUNDARY_MESH) {
flag |= (mv->flag & SCULPTVERT_BOUNDARY) ? SCULPT_BOUNDARY_MESH : 0;
}
if (boundary_types & SCULPT_BOUNDARY_FACE_SET) {
flag |= (mv->flag & SCULPTVERT_FSET_BOUNDARY) ? SCULPT_BOUNDARY_FACE_SET : 0;
}
if (boundary_types & SCULPT_BOUNDARY_SHARP) {
flag |= (mv->flag & SCULPTVERT_SHARP_BOUNDARY) ? SCULPT_BOUNDARY_SHARP : 0;
}
if (boundary_types & SCULPT_BOUNDARY_SEAM) {
flag |= (mv->flag & SCULPTVERT_SEAM_BOUNDARY) ? SCULPT_BOUNDARY_SEAM : 0;
}
if (boundary_types & SCULPT_BOUNDARY_UV) {
flag |= (mv->flag & SCULPTVERT_UV_BOUNDARY) ? SCULPT_BOUNDARY_UV : 0;
}
return flag;
return flag & (SCULPT_BOUNDARY_MESH | SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_SEAM |
SCULPT_BOUNDARY_SHARP | SCULPT_BOUNDARY_UV);
}
/* Utilities */
@ -9498,6 +9461,8 @@ SculptAttribute *SCULPT_stroke_id_attribute_ensure(Object *ob)
if (!ss->attrs.stroke_id) {
SculptAttributeParams params = {0};
params.nointerp = true;
ss->attrs.stroke_id = BKE_sculpt_attribute_ensure(
ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, SCULPT_ATTRIBUTE_NAME(stroke_id), &params);
}
@ -9579,19 +9544,4 @@ void SCULPT_stroke_id_next(Object *ob)
ob->sculpt->stroke_id = (uchar)(((int)ob->sculpt->stroke_id + 1) & 255);
}
void SCULPT_stroke_id_ensure(Object *ob)
{
SculptSession *ss = ob->sculpt;
if (!ss->attrs.automasking_stroke_id) {
SculptAttributeParams params = {0};
ss->attrs.automasking_stroke_id = BKE_sculpt_attribute_ensure(
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT8,
SCULPT_ATTRIBUTE_NAME(automasking_stroke_id),
&params);
}
}
/** \} */

View File

@ -136,7 +136,7 @@ void SCULPT_array_datalayers_free(SculptArray *array, Object *ob)
ss->totvert = mesh->totvert;
}
BKE_sculptsession_check_sculptverts(ss, ss->pbvh, SCULPT_vertex_count_get(ss));
BKE_sculptsession_check_sculptverts(ob, ss->pbvh, SCULPT_vertex_count_get(ss));
}
#endif

View File

@ -243,12 +243,12 @@ static float automasking_view_normal_factor(AutomaskingCache *automasking,
static float automasking_view_occlusion_factor(AutomaskingCache *automasking,
SculptSession *ss,
PBVHVertRef vertex,
uchar stroke_id,
bool vertex_needs_update,
AutomaskingNodeData * /*automask_data*/)
{
char f = *(char *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_occlusion);
if (stroke_id != automasking->current_stroke_id) {
if (vertex_needs_update) {
f = *(char *)SCULPT_vertex_attr_get(
vertex,
ss->attrs.automasking_occlusion) = SCULPT_vertex_is_occluded(ss, vertex, true) ? 2 : 1;
@ -263,10 +263,6 @@ static float automasking_factor_end(SculptSession *ss,
PBVHVertRef vertex,
float value)
{
if (ss->attrs.automasking_stroke_id) {
*(uchar *)SCULPT_vertex_attr_get(
vertex, ss->attrs.automasking_stroke_id) = automasking->current_stroke_id;
}
return value;
}
@ -477,11 +473,10 @@ int SCULPT_automasking_settings_hash(Object *ob, AutomaskingCache *automasking)
static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
SculptSession *ss,
PBVHVertRef vertex)
PBVHVertRef vertex,
bool vertex_needs_update)
{
uchar stroke_id = *(uchar *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_stroke_id);
if (stroke_id != automasking->current_stroke_id) {
if (vertex_needs_update) {
sculpt_calc_blurred_cavity(ss, automasking, automasking->settings.cavity_blur_steps, vertex);
}
@ -507,6 +502,8 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
return 1.0f;
}
bool vertex_needs_update = SCULPT_stroke_id_test(ss, vert, STROKEID_USER_AUTOMASKING);
/* If the cache is initialized with valid info, use the cache. This is used when the
* automasking information can't be computed in real time per vertex and needs to be
* initialized for the whole mesh when the stroke starts. */
@ -514,21 +511,17 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
float factor = *(float *)SCULPT_vertex_attr_get(vert, ss->attrs.automasking_factor);
if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
factor *= sculpt_automasking_cavity_factor(automasking, ss, vert);
factor *= sculpt_automasking_cavity_factor(automasking, ss, vert, vertex_needs_update);
}
return factor;
}
uchar stroke_id = ss->attrs.automasking_stroke_id ?
*(uchar *)(SCULPT_vertex_attr_get(vert, ss->attrs.automasking_stroke_id)) :
-1;
bool do_occlusion = (automasking->settings.flags &
(BRUSH_AUTOMASKING_VIEW_OCCLUSION | BRUSH_AUTOMASKING_VIEW_NORMAL)) ==
(BRUSH_AUTOMASKING_VIEW_OCCLUSION | BRUSH_AUTOMASKING_VIEW_NORMAL);
if (do_occlusion &&
automasking_view_occlusion_factor(automasking, ss, vert, stroke_id, automask_data)) {
if (do_occlusion && automasking_view_occlusion_factor(
automasking, ss, vert, vertex_needs_update, automask_data)) {
return automasking_factor_end(ss, automasking, vert, 0.0f);
}
@ -563,7 +556,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
}
if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
mask *= sculpt_automasking_cavity_factor(automasking, ss, vert);
mask *= sculpt_automasking_cavity_factor(automasking, ss, vert, true);
}
return automasking_factor_end(ss, automasking, vert, mask);
@ -788,9 +781,8 @@ static void sculpt_normal_occlusion_automasking_fill(AutomaskingCache *automaski
f *= automasking_view_normal_factor(automasking, ss, vertex, &nodedata);
}
if (ss->attrs.automasking_stroke_id) {
*(uchar *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_stroke_id) = ss->stroke_id;
}
/* Flag vertex as updated for this stroke. */
SCULPT_stroke_id_test(ss, vertex, STROKEID_USER_AUTOMASKING);
*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor) = f;
}
@ -814,6 +806,8 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
return nullptr;
}
SCULPT_stroke_id_attribute_ensure(ob);
AutomaskingCache *automasking = (AutomaskingCache *)MEM_callocN(sizeof(AutomaskingCache),
"automasking cache");
@ -862,7 +856,7 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
}
if (use_stroke_id) {
SCULPT_stroke_id_ensure(ob);
SCULPT_stroke_id_attribute_ensure(ob);
bool have_occlusion = (mode & BRUSH_AUTOMASKING_VIEW_OCCLUSION) &&
(mode & BRUSH_AUTOMASKING_VIEW_NORMAL);

View File

@ -3341,7 +3341,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
void SCULPT_relax_vertex(SculptSession *ss,
PBVHVertexIter *vd,
float factor,
SculptBoundaryType boundary_mask,
eSculptBoundary boundary_mask,
float *r_final_pos)
{
float smooth_pos[3];
@ -3357,7 +3357,7 @@ void SCULPT_relax_vertex(SculptSession *ss,
bset |= SCULPT_BOUNDARY_FACE_SET;
}
if (SCULPT_vertex_is_corner(ss, vd->vertex, (SculptCornerType)bset)) {
if (SCULPT_vertex_is_corner(ss, vd->vertex, (eSculptCorner)bset)) {
copy_v3_v3(r_final_pos, vd->co);
return;
}
@ -4106,8 +4106,9 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
if (have_bmesh) {
BMVert *v = (BMVert *)vd.vertex.i;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, v);
int *flag = SCULPT_vertex_attr_get(vd.vertex, ss->attrs.boundary_flags);
if (mv->flag & (SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY)) {
if (*flag & (SCULPT_BOUNDARY_MESH | SCULPT_BOUNDARY_FACE_SETS)) {
continue;
}
}

View File

@ -30,6 +30,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@ -37,7 +38,6 @@
#include "BKE_pbvh.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_mesh_mapping.h"
#include "DEG_depsgraph.h"
@ -514,7 +514,7 @@ static void customdata_strip_templayers(CustomData *cdata, int totelem)
void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
Mesh *me = BKE_object_get_original_mesh(ob);
customdata_strip_templayers(&me->vdata, me->totvert);
customdata_strip_templayers(&me->pdata, me->totpoly);
@ -595,11 +595,6 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
const BMAllocTemplate allocsize = {
.totvert = 2048 * 16, .totface = 2048 * 16, .totloop = 4196 * 16, .totedge = 2048 * 16};
if (ss->msculptverts) {
MEM_freeN(ss->msculptverts);
ss->msculptverts = NULL;
}
if (ss->face_areas) {
MEM_freeN(ss->face_areas);
ss->face_areas = NULL;
@ -1004,6 +999,7 @@ typedef struct UVSolver {
double strength;
int cd_sculpt_vert;
int cd_boundary_flag;
} UVSolver;
/*that that currently this tool is *not* threaded*/
@ -1055,9 +1051,9 @@ void *uvsolver_calc_loop_key(UVSolver *solver, BMLoop *l)
intptr_t x = (intptr_t)(uv->uv[0] * 16384.0);
intptr_t y = (intptr_t)(uv->uv[1] * 16384.0);
intptr_t key;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, l->v);
int boundflag = BM_ELEM_CD_GET_INT(l->v, solver->cd_boundary_flag);
if ((mv->flag & (SCULPTVERT_SEAM_BOUNDARY | SCULPTVERT_UV_BOUNDARY)) ||
if ((boundflag & (SCULPT_BOUNDARY_SEAM | SCULPT_BOUNDARY_UV)) ||
(l->e->head.hflag | l->prev->e->head.hflag) & BM_ELEM_SEAM) {
key = y * 16384LL + x;
}
@ -1084,8 +1080,12 @@ static UVSmoothVert *uvsolver_get_vert(UVSolver *solver, BMLoop *l)
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, l->prev->v);
MSculptVert *mv3 = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, l->next->v);
v->boundary = mv->flag & SCULPTVERT_SEAM_BOUNDARY;
if ((mv->flag | mv2->flag | mv3->flag) & SCULPTVERT_SHARP_CORNER) {
int bound1 = BM_ELEM_CD_GET_INT(l->v, solver->cd_boundary_flag);
int bound2 = BM_ELEM_CD_GET_INT(l->prev->v, solver->cd_boundary_flag);
int bound3 = BM_ELEM_CD_GET_INT(l->next->v, solver->cd_boundary_flag);
v->boundary = bound1 & SCULPT_BOUNDARY_SEAM;
if ((bound1 | bound2 | bound3) & SCULPT_CORNER_SHARP) {
v->pinned = true;
}
@ -1515,9 +1515,9 @@ static float uvsolver_solve_step(UVSolver *solver)
for (int i = 0; i < con->totvert; i++) {
UVSmoothVert *sv = con->vs[i];
MSculptVert *mv = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, sv->v);
mv->flag |= SCULPTVERT_NEED_BOUNDARY;
*(int *)BM_ELEM_CD_GET_VOID_P(sv->v,
solver->cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
double w = uvsolver_vert_weight(sv) * totw;
w = MIN2(w, 1.0);
@ -1699,6 +1699,8 @@ void SCULPT_uv_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
BKE_curvemapping_init(brush->curve);
UVSolver *solver = uvsolver_new(cd_uv);
solver->cd_boundary_flag = ss->attrs.boundary_flags->bmesh_cd_offset;
solver->cd_sculpt_vert = ss->cd_sculpt_vert;
// solver->strength = powf(fabs(ss->cache->bstrength), 0.25) * signf(ss->cache->bstrength);
solver->strength = ss->cache->bstrength;

View File

@ -429,7 +429,9 @@ ATTR_NO_OPT void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
MSculptVert *mv = ss->msculptverts + ml->v;
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
*(int *)SCULPT_vertex_attr_get(
BKE_pbvh_make_vref(ml->v),
ss->attrs.boundary_flags) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
copy_v3_v3(fno, ss->vert_normals[ml->v]);
float mask = ss->vmask ? ss->vmask[ml->v] : 0.0f;
@ -537,8 +539,9 @@ ATTR_NO_OPT void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
break;
}
MSculptVert *mv = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, l->v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
*(int *)SCULPT_vertex_attr_get(
BKE_pbvh_make_vref((intptr_t)l->v),
ss->attrs.boundary_flags) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
} while ((l = l->next) != f->l_first);
if (ok) {
@ -650,7 +653,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
SCULPT_relax_vertex(ss,
&vd,
fade * bstrength,
(SculptBoundaryType)(SCULPT_BOUNDARY_DEFAULT | SCULPT_BOUNDARY_FACE_SET),
(eSculptBoundary)(SCULPT_BOUNDARY_DEFAULT | SCULPT_BOUNDARY_FACE_SET),
vd.co);
if (vd.mvert) {
BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex);
@ -1340,9 +1343,11 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
Mesh *mesh = BKE_object_get_original_mesh(ob);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
BKE_sculpt_face_sets_ensure(ob);
const int cd_hide_poly = ss->attrs.hide_poly ? ss->attrs.hide_poly->bmesh_cd_offset : -1;
BKE_sculpt_face_sets_ensure(ob);
BKE_sculpt_hide_poly_ensure(ob);
const int cd_hide_poly = ss->attrs.hide_poly->bmesh_cd_offset;
const int mode = RNA_enum_get(op->ptr, "mode");
const int tot_vert = SCULPT_vertex_count_get(ss);
const int active_face_set = SCULPT_active_face_set_get(ss);
@ -1431,6 +1436,10 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
SCULPT_undo_push_end(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
MEM_SAFE_FREE(nodes);
@ -2190,8 +2199,8 @@ static void sculpt_face_set_extrude_id(Object *ob,
BM_mesh_select_mode_set(bm, SCE_SELECT_FACE);
int mupdateflag = SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_DISK_SORT |
SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_VALENCE;
int mupdateflag = SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_TRIANGULATE |
SCULPTVERT_NEED_VALENCE;
Vector<BMVert *> retvs, vs;
Vector<BMEdge *> es;
@ -2342,6 +2351,9 @@ static void sculpt_face_set_extrude_id(Object *ob,
cd_faceset_offset = CustomData_get_offset_named(
&bm->pdata, CD_PROP_INT32, ".sculpt_face_sets"); // recalc in case bmop changed it
const int cd_boundary_flag = CustomData_get_offset_named(
&bm->vdata, CD_PROP_INT32, SCULPT_ATTRIBUTE_NAME(boundary_flags));
BMOIter siter;
BMElem *ele;
@ -2427,6 +2439,8 @@ static void sculpt_face_set_extrude_id(Object *ob,
if (cd_sculpt_vert != -1) {
BMLoop *l = f->l_first;
do {
*(int *)BM_ELEM_CD_GET_VOID_P(l->v,
cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, l->v);
MV_ADD_FLAG(mv, mupdateflag);
} while ((l = l->next) != f->l_first);
@ -2467,6 +2481,8 @@ static void sculpt_face_set_extrude_id(Object *ob,
if (cd_sculpt_vert >= 0) {
BMLoop *l = f->l_first;
do {
*(int *)BM_ELEM_CD_GET_VOID_P(l->v, cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, l->v);
MV_ADD_FLAG(mv, mupdateflag);
} while ((l = l->next) != f->l_first);
@ -2500,7 +2516,11 @@ static void sculpt_face_set_extrude_id(Object *ob,
int count = 0;
do {
if (cd_sculpt_vert >= 0) {
if (cd_boundary_flag != -1) {
*(int *)BM_ELEM_CD_GET_VOID_P(l->v, cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
}
if (cd_sculpt_vert != -1) {
MSculptVert *mv = (MSculptVert *)BM_ELEM_CD_GET_VOID_P(l->v, cd_sculpt_vert);
MV_ADD_FLAG(mv, mupdateflag);

View File

@ -111,26 +111,6 @@ typedef struct SculptVertexNeighborIter {
bool no_free;
} SculptVertexNeighborIter;
/* this is a bitmask */
typedef enum SculptCornerType {
SCULPT_CORNER_NONE = 0,
SCULPT_CORNER_MESH = 1 << 0,
SCULPT_CORNER_FACE_SET = 1 << 1,
SCULPT_CORNER_SEAM = 1 << 2,
SCULPT_CORNER_SHARP = 1 << 3,
SCULPT_CORNER_UV = 1 << 4,
} SculptCornerType;
typedef enum SculptBoundaryType {
SCULPT_BOUNDARY_MESH = 1 << 0,
SCULPT_BOUNDARY_FACE_SET = 1 << 1,
SCULPT_BOUNDARY_SEAM = 1 << 2,
SCULPT_BOUNDARY_SHARP = 1 << 3,
SCULPT_BOUNDARY_UV = 1 << 4,
SCULPT_BOUNDARY_ALL = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4),
SCULPT_BOUNDARY_DEFAULT = (1 << 0) | (1 << 3) | (1 << 4) // mesh and sharp
} SculptBoundaryType;
typedef struct SculptFaceSetIsland {
PBVHFaceRef *faces;
int totface;
@ -1300,14 +1280,14 @@ void SCULPT_fake_neighbors_free(struct Object *ob);
void SCULPT_boundary_info_ensure(Object *object);
/* Boundary Info needs to be initialized in order to use this function. */
SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
const PBVHVertRef index,
SculptCornerType cornertype);
eSculptCorner SCULPT_vertex_is_corner(const SculptSession *ss,
const PBVHVertRef index,
eSculptCorner cornertype);
/* Boundary Info needs to be initialized in order to use this function. */
SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
const PBVHVertRef index,
SculptBoundaryType boundary_types);
eSculptBoundary SCULPT_vertex_is_boundary(const SculptSession *ss,
const PBVHVertRef index,
eSculptBoundary boundary_types);
void SCULPT_connected_components_ensure(Object *ob);
@ -1915,7 +1895,7 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
void SCULPT_relax_vertex(SculptSession *ss,
PBVHVertexIter *vd,
float factor,
SculptBoundaryType boundary_mask,
eSculptBoundary boundary_mask,
float *r_final_pos);
/** \} */
@ -2356,9 +2336,9 @@ void SCULPT_OT_brush_stroke(struct wmOperatorType *ot);
/* end sculpt_ops.c */
SculptBoundaryType SCULPT_edge_is_boundary(const SculptSession *ss,
const PBVHEdgeRef edge,
SculptBoundaryType typemask);
eSculptBoundary SCULPT_edge_is_boundary(const SculptSession *ss,
const PBVHEdgeRef edge,
eSculptBoundary typemask);
void SCULPT_edge_get_verts(const SculptSession *ss,
const PBVHEdgeRef edge,
PBVHVertRef *r_v1,
@ -2556,6 +2536,52 @@ bool SCULPT_tool_can_reuse_automask(int sculpt_tool);
SculptAttribute *SCULPT_stroke_id_attribute_ensure(struct Object *ob);
typedef struct StrokeID {
short id;
short userflag;
} StrokeID;
typedef enum StrokeIDUser {
STROKEID_USER_AUTOMASKING = 1 << 0,
STROKEID_USER_BOUNDARY = 1 << 1,
STROKEID_USER_SCULPTVERT = 1 << 2,
STROKEID_USER_PREV_COLOR = 1 << 3,
} StrokeIDUser;
BLI_INLINE bool SCULPT_stroke_id_test(SculptSession *ss, PBVHVertRef vertex, StrokeIDUser user)
{
StrokeID *id = (StrokeID *)SCULPT_vertex_attr_get(vertex, ss->attrs.stroke_id);
bool ret;
if (id->id != ss->stroke_id) {
id->id = ss->stroke_id;
id->userflag = 0;
ret = true;
}
else {
ret = !(id->userflag & (int)user);
}
id->userflag |= (int)user;
return ret;
}
BLI_INLINE bool SCULPT_stroke_id_test_no_update(SculptSession *ss,
PBVHVertRef vertex,
StrokeIDUser user)
{
StrokeID *id = (StrokeID *)SCULPT_vertex_attr_get(vertex, ss->attrs.stroke_id);
if (id->id != ss->stroke_id) {
return true;
}
return !(id->userflag & (int)user);
}
#define SCULPT_boundary_flag_update BKE_sculpt_boundary_flag_update
#ifdef __cplusplus
}
#endif

View File

@ -1390,10 +1390,12 @@ static int sculpt_regularize_rake_exec(bContext *C, wmOperator *op)
for (int i = 0; i < bm->totvert; i++) {
BMVert *v = verts[i];
PBVHVertRef vertex = {(intptr_t)v};
MSculptVert *mv = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, v);
if (mv->flag & (SCULPTVERT_CORNER | SCULPTVERT_FSET_CORNER | SCULPTVERT_SHARP_CORNER |
SCULPTVERT_SEAM_CORNER)) {
int *boundflag = (int *)SCULPT_vertex_attr_get(vertex, ss->attrs.boundary_flags);
if (*boundflag & (SCULPT_CORNER_MESH, SCULPT_CORNER_FACE_SET, SCULPT_CORNER_SHARP, SCULPT_CORNER_SEAM)) {
continue;
}
@ -1414,8 +1416,8 @@ static int sculpt_regularize_rake_exec(bContext *C, wmOperator *op)
BLI_BITMAP_SET(visit, v->head.index, true);
ListBase queue = {node, node};
const int boundflag = SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY |
SCULPTVERT_SEAM_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY;
const int boundtest = SCULPT_BOUNDARY_MESH | SCULPT_BOUNDARY_FACE_SET |
SCULPT_BOUNDARY_SEAM | SCULPT_BOUNDARY_SHARP;
while (queue.first) {
BMLinkItem *node2 = BLI_poptail(&queue);
BMVert *v2 = node2->item;
@ -1491,7 +1493,7 @@ static int sculpt_regularize_rake_exec(bContext *C, wmOperator *op)
bool sing = thsum >= M_PI * 0.5f;
// still apply smoothing even with singularity?
if (tot > 0.0f && !(mv->flag & boundflag)) {
if (tot > 0.0f && !(*boundflag & boundtest)) {
mul_v3_fl(avg, 1.0 / tot);
interp_v3_v3v3(dir2, dir2, avg, sing ? 0.15 : 0.25);
normalize_v3(dir2);
@ -1541,10 +1543,15 @@ static int sculpt_regularize_rake_exec(bContext *C, wmOperator *op)
// int bits = closest_vec_to_perp(dir2, dir32, v2->no, buckets, 1.0f);
#if 0
MSculptVert *mv3 = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, v3);
if (mv3->flag & boundflag) {
// continue;
PBVHVertRef vertex3 = {(intptr_t)v3};
int *boundflag3 = (int *)SCULPT_vertex_attr_get(vertex3, ss->attrs.boundary_flags);
if (*boundflag3 & boundtest) {
continue;
}
#endif
BLI_BITMAP_SET(visit, v3->head.index, true);

View File

@ -98,7 +98,6 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
float hue_offset = data->hue_offset;
const SculptAttribute *buffer_scl = data->scl;
const SculptAttribute *stroke_id_scl = data->scl2;
const bool do_accum = SCULPT_get_int(ss, accumulate, NULL, brush);
@ -165,12 +164,9 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
// our temp layer. do this here before the brush check
// to ensure any geomtry dyntopo might subdivide has
// valid state.
int *stroke_id = (int *)SCULPT_vertex_attr_get(vd.vertex, stroke_id_scl);
float *color_buffer = (float *)SCULPT_vertex_attr_get(vd.vertex,
buffer_scl); // mv->origcolor;
if (*stroke_id != ss->stroke_id) {
*stroke_id = ss->stroke_id;
if (SCULPT_stroke_id_test(ss, vd.vertex, STROKEID_USER_PREV_COLOR)) {
zero_v4(color_buffer);
}
@ -428,7 +424,6 @@ void SCULPT_do_paint_brush(
}
SculptAttribute *buffer_scl;
SculptAttribute *stroke_id_scl;
SculptAttributeParams params = {.permanent = false, .simple_array = false, .stroke_only = true};
SculptAttributeParams params_id = {.permanent = false,
@ -443,7 +438,7 @@ void SCULPT_do_paint_brush(
}
buffer_scl = ss->attrs.smear_previous;
stroke_id_scl = SCULPT_stroke_id_attribute_ensure(ob);
SCULPT_stroke_id_attribute_ensure(ob);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
@ -455,7 +450,6 @@ void SCULPT_do_paint_brush(
.mat = mat,
.hue_offset = SCULPT_get_float(ss, hue_offset, sd, brush),
.scl = buffer_scl,
.scl2 = stroke_id_scl,
.brush_color = brush_color,
};

View File

@ -400,7 +400,7 @@ static void SCULPT_neighbor_coords_average_interior_boundary(SculptSession *ss,
bflag |= SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_SEAM | SCULPT_BOUNDARY_UV;
}
const SculptBoundaryType is_boundary = SCULPT_vertex_is_boundary(ss, vertex, bflag);
const eSculptBoundary is_boundary = SCULPT_vertex_is_boundary(ss, vertex, bflag);
const float *co = do_origco ? mv->origco : SCULPT_vertex_co_get(ss, vertex);
float no[3];
@ -423,7 +423,7 @@ static void SCULPT_neighbor_coords_average_interior_boundary(SculptSession *ss,
const bool weighted = args->do_weighted_smooth && !is_boundary;
float *areas = NULL;
SculptCornerType ctype = SCULPT_CORNER_MESH | SCULPT_CORNER_SHARP;
eSculptCorner ctype = SCULPT_CORNER_MESH | SCULPT_CORNER_SHARP;
if (check_fsets) {
ctype |= SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SEAM | SCULPT_CORNER_UV;
}
@ -489,7 +489,7 @@ static void SCULPT_neighbor_coords_average_interior_boundary(SculptSession *ss,
/*use the new edge api if edges are available, if not estimate boundary
from verts*/
SculptBoundaryType final_boundary = 0;
eSculptBoundary final_boundary = 0;
if (ni.has_edge) {
final_boundary = SCULPT_edge_is_boundary(ss, ni.edge, bflag);
@ -692,7 +692,7 @@ static void SCULPT_neighbor_coords_average_interior_boundary(SculptSession *ss,
PBVH_CHECK_NAN(co);
SculptCornerType c = SCULPT_vertex_is_corner(ss, vertex, ctype);
eSculptCorner c = SCULPT_vertex_is_corner(ss, vertex, ctype);
float corner_smooth;
if (c == 0) {
@ -748,7 +748,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
bflag |= SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_SEAM | SCULPT_BOUNDARY_UV;
}
const SculptBoundaryType is_boundary = SCULPT_vertex_is_boundary(ss, vertex, bflag);
const eSculptBoundary is_boundary = SCULPT_vertex_is_boundary(ss, vertex, bflag);
const float *co = do_origco ? mv->origco : SCULPT_vertex_co_get(ss, vertex);
float no[3];
@ -769,7 +769,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
const bool weighted = args->do_weighted_smooth && !is_boundary;
float *areas = NULL;
SculptCornerType ctype = SCULPT_CORNER_MESH | SCULPT_CORNER_SHARP;
eSculptCorner ctype = SCULPT_CORNER_MESH | SCULPT_CORNER_SHARP;
if (check_fsets) {
ctype |= SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SEAM | SCULPT_CORNER_UV;
}
@ -834,7 +834,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
/* use the new edge api if edges are available, if not estimate boundary
from verts
*/
SculptBoundaryType final_boundary = 0;
eSculptBoundary final_boundary = 0;
if (ni.has_edge) {
final_boundary = SCULPT_edge_is_boundary(ss, ni.edge, bflag);
@ -958,7 +958,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
PBVH_CHECK_NAN(co);
SculptCornerType c = SCULPT_vertex_is_corner(ss, vertex, ctype);
eSculptCorner c = SCULPT_vertex_is_corner(ss, vertex, ctype);
if (!c) {
return;
@ -1123,7 +1123,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
co2 = mv2->origco;
}
SculptBoundaryType bflag = SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_MESH |
eSculptBoundary bflag = SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_MESH |
SCULPT_BOUNDARY_SHARP | SCULPT_BOUNDARY_SEAM | SCULPT_BOUNDARY_UV;
int bound = SCULPT_edge_is_boundary(ss, (PBVHEdgeRef){.i = (intptr_t)e}, bflag);

View File

@ -550,7 +550,7 @@ typedef struct BmeshUndoData {
bool do_full_recalc;
bool balance_pbvh;
int cd_face_node_offset, cd_vert_node_offset;
int cd_sculpt_vert;
int cd_sculpt_vert, cd_boundary_flag;
bool regen_all_unique_verts;
bool is_redo;
} BmeshUndoData;
@ -586,10 +586,11 @@ static void bmesh_undo_on_vert_add(BMVert *v, void *userdata)
// let face add vert
BM_ELEM_CD_SET_INT(v, data->cd_vert_node_offset, -1);
*(int *)BM_ELEM_CD_GET_VOID_P(v, data->cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, v);
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_TRIANGULATE |
SCULPTVERT_NEED_BOUNDARY);
SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_TRIANGULATE);
}
static void bmesh_undo_on_face_kill(BMFace *f, void *userdata)
@ -621,8 +622,10 @@ static void bmesh_undo_on_face_add(BMFace *f, void *userdata)
BMLoop *l = f->l_first;
do {
*(int *)BM_ELEM_CD_GET_VOID_P(l->v, data->cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
MSculptVert *mv = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, l->v);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_BOUNDARY);
MV_ADD_FLAG(mv, SCULPTVERT_NEED_DISK_SORT);
int ni_l = BM_ELEM_CD_GET_INT(l->v, data->cd_vert_node_offset);
@ -658,12 +661,13 @@ static void bmesh_undo_on_edge_kill(BMEdge *e, void *userdata)
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, e->v2);
*(int *)BM_ELEM_CD_GET_VOID_P(e->v1, data->cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
*(int *)BM_ELEM_CD_GET_VOID_P(e->v2, data->cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
MV_ADD_FLAG(mv1,
SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT |
SCULPTVERT_NEED_VALENCE);
SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE);
MV_ADD_FLAG(mv2,
SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT |
SCULPTVERT_NEED_VALENCE);
SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE);
}
static void bmesh_undo_on_edge_add(BMEdge *e, void *userdata)
@ -673,10 +677,11 @@ static void bmesh_undo_on_edge_add(BMEdge *e, void *userdata)
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, e->v1);
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, e->v2);
mv1->flag |= SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT |
SCULPTVERT_NEED_VALENCE;
mv2->flag |= SCULPTVERT_NEED_BOUNDARY | SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT |
SCULPTVERT_NEED_VALENCE;
*(int *)BM_ELEM_CD_GET_VOID_P(e->v1, data->cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
*(int *)BM_ELEM_CD_GET_VOID_P(e->v2, data->cd_boundary_flag) |= SCULPT_BOUNDARY_NEEDS_UPDATE;
mv1->flag |= SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE;
mv2->flag |= SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE;
}
static void bmesh_undo_on_vert_change(BMVert *v, void *userdata, void *old_customdata)
@ -777,6 +782,7 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
ss->cd_face_node_offset,
ss->cd_vert_node_offset,
ss->cd_sculpt_vert,
ss->attrs.boundary_flags->bmesh_cd_offset,
false,
!unode->applied};
@ -3056,6 +3062,7 @@ void SCULPT_substep_undo(bContext *C, int dir)
ss->cd_face_node_offset,
ss->cd_vert_node_offset,
ss->cd_sculpt_vert,
ss->attrs.boundary_flags->bmesh_cd_offset,
false,
false};

View File

@ -566,23 +566,12 @@ typedef struct MSculptVert {
/* MSculptVert->flag */
enum {
SCULPTVERT_BOUNDARY = (1 << 0),
SCULPTVERT_VERT_FSET_HIDDEN = (1 << 1),
SCULPTVERT_FSET_BOUNDARY = (1 << 2),
SCULPTVERT_NEED_BOUNDARY = (1 << 3),
SCULPTVERT_NEED_TRIANGULATE = (1 << 4),
SCULPTVERT_NEED_DISK_SORT = (1 << 5),
SCULPTVERT_NEED_VALENCE = (1 << 6),
SCULPTVERT_FSET_CORNER = (1 << 7),
SCULPTVERT_CORNER = (1 << 8),
SCULPTVERT_SEAM_BOUNDARY = (1 << 9),
SCULPTVERT_SHARP_BOUNDARY = (1 << 10),
SCULPTVERT_SEAM_CORNER = (1 << 11),
SCULPTVERT_SHARP_CORNER = (1 << 12),
SCULPTVERT_SPLIT_TEMP = (1 << 13),
SCULPTVERT_PBVH_BOUNDARY = (1 << 14),
SCULPTVERT_UV_BOUNDARY = (1 << 15),
SCULPTVERT_UV_CORNER = (1 << 16)
};
/* for internal bmesh toolflags api */