Commit: e4b36fb6bc4cc19ecd699ec9f1066a067e5ed032 Author: Joseph Eagar Date: Fri Aug 27 20:02:20 2021 -0700 Branches: temp_bmesh_multires https://developer.blender.org/rBe4b36fb6bc4cc19ecd699ec9f1066a067e5ed032
Sculpt dyntopo: split face set boundaries on mirror boundary Added an option to split face set boundaries on mirror boundaries; currently only DynTopo supports this. Very useful for making hard edges along mirror lines. =================================================================== M release/scripts/startup/bl_ui/space_view3d.py M release/scripts/startup/bl_ui/space_view3d_toolbar.py M source/blender/blenkernel/BKE_paint.h M source/blender/blenkernel/BKE_pbvh.h M source/blender/blenkernel/intern/paint.c M source/blender/blenkernel/intern/pbvh.c M source/blender/blenkernel/intern/pbvh_bmesh.c M source/blender/blenkernel/intern/pbvh_intern.h M source/blender/editors/sculpt_paint/sculpt.c M source/blender/editors/sculpt_paint/sculpt_dyntopo.c M source/blender/editors/sculpt_paint/sculpt_intern.h M source/blender/makesdna/DNA_mesh_types.h M source/blender/makesrna/intern/rna_mesh.c =================================================================== diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index c6bc6d9b5d3..c8c1858d914 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -171,6 +171,7 @@ class VIEW3D_HT_tool_header(Header): row.popover(panel="VIEW3D_PT_tools_weightpaint_symmetry_for_topbar", text="") elif mode_string == 'SCULPT': row.popover(panel="VIEW3D_PT_sculpt_symmetry_for_topbar", text="") + layout.prop(context.object.data, "use_fset_boundary_mirror"); elif mode_string == 'PAINT_VERTEX': row.popover(panel="VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar", text="") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 25e4f2d501a..5cf797bd075 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1009,6 +1009,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel): row.prop(sculpt, "tile_z", text="Z", toggle=True) layout.prop(sculpt, "use_symmetry_feather", text="Feather") + layout.prop(mesh, "use_fset_boundary_mirror") layout.prop(sculpt, "radial_symmetry", text="Radial") layout.prop(sculpt, "tile_offset", text="Tile Offset") diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 2b829e8f569..53d59c42a81 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -655,7 +655,7 @@ typedef struct SculptSession { // id of current stroke, used to detect // if vertex original data needs to be updated - int stroke_id; + int stroke_id, boundary_symmetry; bool fast_draw; // hides facesets/masks and forces smooth to save GPU bandwidth } SculptSession; @@ -701,6 +701,8 @@ void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d); +char BKE_get_fset_boundary_symflag(struct Object *object); + enum { SCULPT_MASK_LAYER_CALC_VERT = (1 << 0), SCULPT_MASK_LAYER_CALC_LOOP = (1 << 1), diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index a63768633e7..4ccdc66349b 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -768,13 +768,17 @@ PBVHNode *BKE_pbvh_node_from_face_bmesh(PBVH *pbvh, struct BMFace *f); PBVHNode *BKE_pbvh_node_from_index(PBVH *pbvh, int node_i); struct BMesh *BKE_pbvh_reorder_bmesh(PBVH *pbvh); -void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, struct BMVert *v); +void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, + int cd_faceset_offset, + struct BMVert *v, + int symmetry); #define DYNTOPO_DYNAMIC_TESS PBVHNode *BKE_pbvh_get_node_leaf_safe(PBVH *pbvh, int i); void BKE_pbvh_get_vert_face_areas(PBVH *pbvh, SculptVertRef vertex, float *r_areas, int valence); +void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry); #if 0 typedef enum { @@ -870,3 +874,4 @@ typedef struct SculptLayerEntry { #ifdef __cplusplus } #endif + diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 1c7a4303754..e5c7d4a183a 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1630,6 +1630,12 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) return false; } +char BKE_get_fset_boundary_symflag(Object *object) +{ + const Mesh *mesh = BKE_mesh_from_object(object); + return mesh->flag & ME_SCULPT_MIRROR_FSET_BOUNDARIES ? mesh->symmetry : 0; +} + /** * \param need_mask: So that the evaluated mesh that is returned has mask data. */ @@ -1668,6 +1674,8 @@ static void sculpt_update_object(Depsgraph *depsgraph, ss->shapekey_active = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL; + ss->boundary_symmetry = (int) BKE_get_fset_boundary_symflag(ob); + /* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path, * so no extra checks is needed here. */ if (mmd) { @@ -2146,6 +2154,9 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object) static PBVH *build_pbvh_for_dynamic_topology(Object *ob) { PBVH *pbvh = BKE_pbvh_new(); + + BKE_pbvh_set_symmetry(pbvh, 0, (int)BKE_get_fset_boundary_symflag(ob)); + BKE_pbvh_build_bmesh(pbvh, ob->sculpt->bm, ob->sculpt->bm_smooth_shading, diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index cbf95a035e0..a7c24e2c82f 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -4006,3 +4006,23 @@ void BKE_pbvh_set_stroke_id(PBVH *pbvh, int stroke_id) { pbvh->stroke_id = stroke_id; } + +void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry) { + if (symmetry == pbvh->symmetry && boundary_symmetry == pbvh->boundary_symmetry) { + return; + } + + pbvh->symmetry = symmetry; + pbvh->boundary_symmetry = boundary_symmetry; + + if (pbvh->bm && BKE_pbvh_type(pbvh) == PBVH_BMESH) { + BMIter iter; + BMVert *v; + + BM_ITER_MESH(v, &iter, pbvh->bm, BM_VERTS_OF_MESH) { + MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v); + + mv->flag |= DYNVERT_NEED_BOUNDARY; + } + } +} diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index d8dadd707e2..57b794307b0 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -1362,7 +1362,26 @@ typedef struct FSetTemp { bool boundary; } FSetTemp; -void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVert *v) +static int do_fset_sym(int fset, const int symflag, const float *co) { + fset = abs(fset); + + //surely we don't need more then 8 million face sets? + if (co[0] < 0.0f) { + fset |= (symflag&1) << 24; + } + + if (co[1] < 0.0f) { + fset |= (symflag&2) << 24; + } + + if (co[2] < 0.0f) { + fset |= (symflag&4) << 24; + } + + return fset; +} + +void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVert *v, int bound_symmetry) { MDynTopoVert *mv = BKE_PBVH_DYNVERT(cd_dyn_vert, v); @@ -1417,7 +1436,7 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVer } if (e->l) { - int fset = abs(BM_ELEM_CD_GET_INT(e->l->f, cd_faceset_offset)); + int fset = do_fset_sym(BM_ELEM_CD_GET_INT(e->l->f, cd_faceset_offset), bound_symmetry, v2->co); if (e->l->f->len > 3) { mv->flag |= DYNVERT_NEED_TRIANGULATE; @@ -1458,7 +1477,8 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVer // also check e->l->radial_next, in case we are not manifold // which can mess up the loop order if (e->l->radial_next != e->l) { - fset = abs(BM_ELEM_CD_GET_INT(e->l->radial_next->f, cd_faceset_offset)); + //fset = abs(BM_ELEM_CD_GET_INT(e->l->radial_next->f, cd_faceset_offset)); + fset = do_fset_sym(BM_ELEM_CD_GET_INT(e->l->radial_next->f, cd_faceset_offset), bound_symmetry, v2->co); if (e->l->radial_next->f->len > 3) { mv->flag |= DYNVERT_NEED_TRIANGULATE; @@ -1566,9 +1586,9 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVer BLI_array_free(fsets); } -void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVert *v) +void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVert *v, int bound_symmetry) { - bke_pbvh_update_vert_boundary(cd_dyn_vert, cd_faceset_offset, v); + bke_pbvh_update_vert_boundary(cd_dyn_vert, cd_faceset_offset, v, bound_symmetry); } /*Used by symmetrize to update boundary flags*/ @@ -1578,7 +1598,7 @@ void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh) BMIter iter; BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) { - bke_pbvh_update_vert_boundary(pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v); + bke_pbvh_update_vert_boundary(pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v, pbvh->boundary_symmetry); } } @@ -1708,7 +1728,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh, mv->flag = DYNVERT_NEED_DISK_SORT; - bke_pbvh_update_vert_boundary(pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v); + bke_pbvh_update_vert_boundary(pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v, pbvh->boundary_symmetry); BKE_pbvh_bmesh_update_valence(pbvh->cd_dyn_vert, (SculptVertRef){(intptr_t)v}); copy_v3_v3(mv->origco, v->co); diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index c91a97bdf83..050869ea351 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -203,6 +203,9 @@ struct PBVH { float planes[6][4]; int num_planes; + int symmetry; + int boundary_symmetry; + struct BMLog *bm_log; struct SubdivCCG *subdiv_ccg; @@ -317,14 +320,14 @@ bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index); void pbvh_bmesh_check_nodes(PBVH *pbvh); void bke_pbvh_insert_face_finalize(PBVH *pbvh, BMFace *f, const int ni); void bke_pbvh_insert_face(PBVH *pbvh, struct BMFace *f); -void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVert *v); +void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVert *v, int bound_symmetry); BLI_INLINE bool pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v) { MDynTopoVert *mv = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_dyn_vert); if (mv->flag & DYNVERT_NEED_BOUNDARY) { - bke_pbvh_update_vert_boundary(pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v); + bke_pbvh_update_vert_boundary(pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v, pbvh->boundary_symmetry); @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs