[Bf-blender-cvs] [8ea7c93a378] temp_bmesh_multires: Sculpt dyntopo: support sharp edge flags
Joseph Eagar
noreply at git.blender.org
Fri Aug 27 11:01:26 CEST 2021
Commit: 8ea7c93a3789e4371b896906e90e4c5ac2a5c47c
Author: Joseph Eagar
Date: Thu Aug 26 18:00:29 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB8ea7c93a3789e4371b896906e90e4c5ac2a5c47c
Sculpt dyntopo: support sharp edge flags
* Sharp edge flags are now supported and are
treated much the same as face set boundaries:
+ Dyntopo preserves them
+ Interior smoothing treats them as boundaries
+ Corners are detected and pinned in smoothing
+ TODO: add a brush flag to ignore sharp boundaries
for smoothing.
* Seams are also preserved, but don't affect smoothing.
* BMLog now saves edges.
* The new edge split function is enabled.
* Dyntopo now pushes new combined BMLog entries in
its top-level function, to avoid scary id reuse
edge cases.
* SCULPT_vertex_is_boundary/corner now take a bitmask
of which types of boundaries you wish to query instead
of check_face_sets.
===================================================================
M source/blender/blenkernel/BKE_pbvh.h
M source/blender/blenkernel/intern/brush.c
M source/blender/blenkernel/intern/dyntopo.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/bmesh/bmesh_class.h
M source/blender/bmesh/intern/bmesh_construct.c
M source/blender/bmesh/intern/bmesh_core.c
M source/blender/bmesh/intern/bmesh_interp.c
M source/blender/bmesh/intern/bmesh_log.c
M source/blender/bmesh/intern/bmesh_log.h
M source/blender/bmesh/intern/bmesh_mesh.c
M source/blender/bmesh/intern/bmesh_mesh.h
M source/blender/bmesh/operators/bmo_inset.c
M source/blender/bmesh/tests/bmesh_core_test.cc
M source/blender/editors/sculpt_paint/sculpt.c
M source/blender/editors/sculpt_paint/sculpt_automasking.c
M source/blender/editors/sculpt_paint/sculpt_boundary.c
M source/blender/editors/sculpt_paint/sculpt_dyntopo.c
M source/blender/editors/sculpt_paint/sculpt_expand.c
M source/blender/editors/sculpt_paint/sculpt_face_set.c
M source/blender/editors/sculpt_paint/sculpt_intern.h
M source/blender/editors/sculpt_paint/sculpt_smooth.c
M source/blender/editors/sculpt_paint/sculpt_undo.c
M source/blender/makesdna/DNA_meshdata_types.h
===================================================================
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 0b2e288cfb5..a63768633e7 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -213,7 +213,8 @@ typedef enum {
/* tri areas are not guaranteed to be up to date, tools should
update all nodes on first step of brush*/
- PBVH_UpdateTriAreas = 1 << 19
+ PBVH_UpdateTriAreas = 1 << 19,
+ PBVH_UpdateOtherVerts = 1 << 20
} PBVHNodeFlags;
typedef struct PBVHFrustumPlanes {
@@ -289,6 +290,10 @@ inside the verts and not in the nodes is to allow splitting of the pbvh during t
*/
bool BKE_pbvh_bmesh_check_origdata(PBVH *pbvh, struct BMVert *v, int stroke_id);
+/** used so pbvh can differentiate between different strokes,
+ see BKE_pbvh_bmesh_check_origdata */
+void BKE_pbvh_set_stroke_id(PBVH *pbvh, int stroke_id);
+
/* Hierarchical Search in the BVH, two methods:
* - for each hit calling a callback
* - gather nodes in an array (easy to multithread) */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 4b75109be3e..15fba14257d 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1978,11 +1978,13 @@ void BKE_brush_sculpt_reset(Brush *br)
// don't use DYNTOPO_INHERIT_BITMASK, we want to include
// future bits
- br->flag |= BRUSH_SMOOTH_PRESERVE_FACE_SETS;
+ br->flag |= BRUSH_SMOOTH_PRESERVE_FACE_SETS | BRUSH_SMOOTH_USE_AREA_WEIGHT |
+ BRUSH_CURVATURE_RAKE;
br->dyntopo.inherit = 0x7FFFFFFF &
~(DYNTOPO_INHERIT_ALL | DYNTOPO_SUBDIVIDE | DYNTOPO_COLLAPSE);
br->dyntopo.flag |= DYNTOPO_COLLAPSE | DYNTOPO_SUBDIVIDE;
- br->autosmooth_factor = 0.02;
+ br->autosmooth_factor = 0.05;
+ br->topology_rake_factor = 0.35;
break;
case SCULPT_TOOL_VCOL_BOUNDARY:
diff --git a/source/blender/blenkernel/intern/dyntopo.c b/source/blender/blenkernel/intern/dyntopo.c
index 991a01b87e7..45d1cf26fec 100644
--- a/source/blender/blenkernel/intern/dyntopo.c
+++ b/source/blender/blenkernel/intern/dyntopo.c
@@ -34,9 +34,13 @@
#define DYNVERT_VALENCE_TEMP (1 << 14)
-//#define USE_NEW_SPLIT
-#define DYNVERT_ALL_BOUNDARY (DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY)
-#define DYNVERT_ALL_CORNER (DYNVERT_CORNER | DYNVERT_FSET_CORNER)
+#define USE_NEW_SPLIT
+#define DYNVERT_SMOOTH_BOUNDARY (DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY | DYNVERT_SHARP_BOUNDARY)
+#define DYNVERT_ALL_BOUNDARY \
+ (DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY | DYNVERT_SHARP_BOUNDARY | DYNVERT_SEAM_BOUNDARY)
+#define DYNVERT_SMOOTH_CORNER (DYNVERT_CORNER | DYNVERT_FSET_CORNER | DYNVERT_SHARP_CORNER)
+#define DYNVERT_ALL_CORNER \
+ (DYNVERT_CORNER | DYNVERT_FSET_CORNER | DYNVERT_SHARP_CORNER | DYNVERT_SEAM_CORNER)
#define DYNTOPO_MAX_ITER 4096
@@ -105,6 +109,9 @@ static void pbvh_bmesh_verify(PBVH *pbvh);
* Take care since 'break' won't works as expected within these macros!
*/
+#define BM_DISK_EDGE(e, v) \
+ &(((&e->v1_disk_link)[v == e->v2])))
+
#define BM_LOOPS_OF_VERT_ITER_BEGIN(l_iter_radial_, v_) \
{ \
struct { \
@@ -150,6 +157,26 @@ static void pbvh_bmesh_verify(PBVH *pbvh);
static bool check_face_is_tri(PBVH *pbvh, BMFace *f);
static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v);
static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge);
+void bm_log_message(const char *fmt, ...);
+
+static BMEdge *bmesh_edge_create_log(PBVH *pbvh, BMVert *v1, BMVert *v2, BMEdge *e_example)
+{
+ BMEdge *e = BM_edge_exists(v1, v2);
+
+ if (e) {
+ return e;
+ }
+
+ e = BM_edge_create(pbvh->bm, v1, v2, e_example, BM_CREATE_NOP);
+
+ if (e_example) {
+ e->head.hflag |= e_example->head.hflag;
+ }
+
+ BM_log_edge_added(pbvh->bm_log, e);
+
+ return e;
+}
BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v)
{
@@ -171,9 +198,9 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v)
const int cd_dyn_vert = pbvh->cd_dyn_vert;
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(cd_dyn_vert, v);
- const bool bound1 = mv1->flag & DYNVERT_ALL_BOUNDARY;
+ const bool bound1 = mv1->flag & DYNVERT_SMOOTH_BOUNDARY;
- if (mv1->flag & DYNVERT_ALL_CORNER) {
+ if (mv1->flag & DYNVERT_SMOOTH_CORNER) {
return;
}
@@ -184,7 +211,7 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v)
// pbvh_check_vert_boundary(pbvh, v2);
MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v2);
- const bool bound2 = mv2->flag & DYNVERT_ALL_BOUNDARY;
+ const bool bound2 = mv2->flag & DYNVERT_SMOOTH_BOUNDARY;
if (bound1 != bound2) {
e = v == e->v1 ? e->v1_disk_link.next : e->v2_disk_link.next;
@@ -214,11 +241,44 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v)
atomic_cas_float(&v->co[2], z, z + co[2] * DYNTOPO_SAFE_SMOOTH_FAC);
}
-static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
+ATTR_NO_OPT static void pbvh_kill_vert(PBVH *pbvh, BMVert *v)
+{
+ BMEdge *e = v->e;
+
+ if (e) {
+ do {
+ BM_log_edge_removed(pbvh->bm_log, e);
+ e = BM_DISK_EDGE_NEXT(e, v);
+ } while (e != v->e);
+ }
+
+ BM_vert_kill(pbvh->bm, v);
+}
+
+ATTR_NO_OPT static void pbvh_log_vert_edges_kill(PBVH *pbvh, BMVert *v)
+{
+ BMEdge *e = v->e;
+
+ if (e) {
+ do {
+ BM_log_edge_removed(pbvh->bm_log, e);
+ e = BM_DISK_EDGE_NEXT(e, v);
+ } while (e != v->e);
+ }
+}
+
+static void bm_edges_from_tri(PBVH *pbvh, BMVert *v_tri[3], BMEdge *e_tri[3])
{
- e_tri[0] = BM_edge_create(bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
- e_tri[1] = BM_edge_create(bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
- e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE);
+ e_tri[0] = bmesh_edge_create_log(pbvh, v_tri[0], v_tri[1], NULL);
+ e_tri[1] = bmesh_edge_create_log(pbvh, v_tri[1], v_tri[2], NULL);
+ e_tri[2] = bmesh_edge_create_log(pbvh, v_tri[2], v_tri[0], NULL);
+}
+
+static void bm_edges_from_tri_example(PBVH *pbvh, BMVert *v_tri[3], BMEdge *e_tri[3])
+{
+ e_tri[0] = bmesh_edge_create_log(pbvh, v_tri[0], v_tri[1], e_tri[0]);
+ e_tri[1] = bmesh_edge_create_log(pbvh, v_tri[1], v_tri[2], e_tri[1]);
+ e_tri[2] = bmesh_edge_create_log(pbvh, v_tri[2], v_tri[0], e_tri[2]);
}
BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3])
@@ -289,11 +349,16 @@ static BMVert *bm_vert_hash_lookup_chain(GHash *deleted_verts, BMVert *v)
}
}
-static void pbvh_bmesh_copy_facedata(BMesh *bm, BMFace *dest, BMFace *src)
+static void pbvh_bmesh_copy_facedata(PBVH *pbvh, BMesh *bm, BMFace *dest, BMFace *src)
{
dest->head.hflag = src->head.hflag;
dest->mat_nr = src->mat_nr;
+
+ int ni = BM_ELEM_CD_GET_INT(dest, pbvh->cd_face_node_offset);
+
CustomData_bmesh_copy_data(&bm->pdata, &bm->pdata, src->head.data, &dest->head.data);
+
+ BM_ELEM_CD_SET_INT(dest, pbvh->cd_face_node_offset, ni);
}
static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
@@ -309,6 +374,9 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
/* avoid initializing customdata because its quite involved */
BMVert *v = BM_vert_create(pbvh->bm, co, NULL, BM_CREATE_NOP);
+ MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
+
+ mv->flag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_DISK_SORT | DYNVERT_NEED_VALENCE;
if (v_example) {
v->head.hflag = v_example->head.hflag;
@@ -336,7 +404,7 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
BLI_table_gset_insert(node->bm_unique_verts, v);
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index);
- node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_UpdateTris;
+ node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_UpdateTris | PBVH_UpdateOtherVerts;
/* Log the new vertex */
BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset);
@@ -345,6 +413,44 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
return v;
}
+static BMFace *bmesh_face_create_edge_log(PBVH *pbvh,
+ BMVert *v_tri[3],
+ BMEdge *e_tri[3],
+ const BMFace *f_example)
+{
+ BMFace *f;
+
+ if (!e_tri) {
+ BMEdge *e_tri2[3];
+
+ for (int i = 0; i < 3; i++) {
+ BMVert *v1 = v_tri[i];
+ BMVert *v2 = v_tri[(i + 1) % 3];
+
+ BMEdge *e = BM_edge_exists(v1, v2);
+
+ if (!e) {
+ e = BM_edge_create(pbvh->bm, v1, v2, NULL, BM_CREATE_NOP);
+ BM_log_edge_added(pbvh->bm_log, e);
+ }
+
+ e_tri2[i] = e;
+ }
+
+ // f = BM_face_create_verts(pbvh->bm, v_tri, 3, f_example, BM_CREATE_NOP, true);
+ f = BM_face_create(pbvh->bm, v_tri, e_tri2, 3, f_example, BM_CREATE_NOP);
+ }
+ else {
+ f = BM_face_create(pbvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
+ }
+
+ if (f_example) {
+ f->head.hflag = f_example->head.hflag;
+ }
+
+ return f;
+}
+
/**
* \note Callers are responsible for checking if the face exists before adding.
*/
@@ -361,24 +467,14 @@ static BMFace *pbvh_bmesh_face_create(PBVH *pbvh,
/* ensure we never add existing face */
BLI_assert(!BM_face_exists(v_tri, 3));
- BMFace *f;
-
- if (!e_tri) {
- f = BM_face_create_verts(pbvh->bm, v_tri, 3, f_example, BM_CREATE_NOP, true);
- }
- else {
- f = BM_face_create(pbvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
- }
-
- if (f_example) {
- f->head.hflag = f_example->head.hflag;
- }
+ BMFace *f = bmesh_face_create_edge_log(pbvh, v_tri, e_tri, f_example);
BLI_table_gset_insert(node->bm_faces, f);
BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index);
/* mark node for update */
- node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateTris;
+ node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateTris |
+ PBVH_UpdateOtherVerts;
node->flag &= ~PBVH_FullyHidden;
/* Log the new face */
@@ -397,15 +493,24 @@ static BMFace *pbvh_bmesh_face_create(PBVH *pbvh,
BLI_table_gset_add(node->bm_unique_verts, l->v);
BM_ELEM_CD_SET_INT(l->v, cd_vert_node, node_index);
- node->flag |= PBVH_UpdateDrawBuff
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list