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:
parent
a5f53346a6
commit
57d5fc7352
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
¶ms,
|
||||
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", ¶ms);
|
||||
|
||||
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, "", ¶ms, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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), ¶ms);
|
||||
}
|
||||
|
@ -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),
|
||||
¶ms);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue