Commit: bde54e127eace4bc865044673beb21e9034bad60 Author: Joseph Eagar Date: Mon Aug 23 21:06:10 2021 -0700 Branches: temp_bmesh_multires https://developer.blender.org/rBbde54e127eace4bc865044673beb21e9034bad60
Sculpt dyntopo: Smooth improvements and bug fixes * Added an option to weight smooth by face areas * Dyntopo now caches face areas in a CD_PROP_FLOAT layer * Dyntopo also caches number of edges around verts inside of MDynTopoVert. To avoid increasing the struct size flag was made a short. * Cleanup mode (dissolves 3/4-valence verts) now piggybacks on subdivide code to build list of verts; this is much faster. =================================================================== M release/scripts/startup/bl_ui/properties_paint_common.py M source/blender/blenkernel/BKE_paint.h M source/blender/blenkernel/BKE_pbvh.h M source/blender/blenkernel/intern/dyntopo.c 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/paint_mask.c M source/blender/editors/sculpt_paint/sculpt.c M source/blender/editors/sculpt_paint/sculpt_dyntopo.c M source/blender/editors/sculpt_paint/sculpt_smooth.c M source/blender/editors/sculpt_paint/sculpt_undo.c M source/blender/makesdna/DNA_brush_enums.h M source/blender/makesdna/DNA_meshdata_types.h M source/blender/makesrna/intern/rna_brush.c =================================================================== diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 1b71dae5e35..1043e8af1dc 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -567,6 +567,8 @@ def brush_settings(layout, context, brush, popover=False): slider=True, ) + box.prop(brush, "use_weighted_smooth") + box.prop(brush, "use_custom_auto_smooth_spacing", text="Custom Spacing") if brush.use_custom_auto_smooth_spacing: UnifiedPaintPanel.prop_unified( @@ -812,7 +814,9 @@ def brush_settings(layout, context, brush, popover=False): elif sculpt_tool == 'SMOOTH': col = layout.column() + col.prop(brush, "use_weighted_smooth") col.prop(brush, "smooth_deform_type") + if brush.smooth_deform_type == 'SURFACE': col.prop(brush, "surface_smooth_shape_preservation") col.prop(brush, "surface_smooth_current_vertex") diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index db091a8b878..2b829e8f569 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -533,6 +533,7 @@ typedef struct SculptSession { int cd_face_node_offset; int cd_vcol_offset; int cd_faceset_offset; + int cd_face_areas; bool bm_smooth_shading; /* Undo/redo log for dynamic topology sculpting */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 05837f8f847..0b2e288cfb5 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -209,7 +209,11 @@ typedef enum { PBVH_Delete = 1 << 15, PBVH_UpdateCurvatureDir = 1 << 16, PBVH_UpdateTris = 1 << 17, - PBVH_RebuildNodeVerts = 1 << 18 + PBVH_RebuildNodeVerts = 1 << 18, + + /* tri areas are not guaranteed to be up to date, tools should + update all nodes on first step of brush*/ + PBVH_UpdateTriAreas = 1 << 19 } PBVHNodeFlags; typedef struct PBVHFrustumPlanes { @@ -263,11 +267,13 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh, const int cd_vert_node_offset, const int cd_face_node_offset, const int cd_dyn_vert, + const int cd_face_areas, bool fast_draw); void BKE_pbvh_update_offsets(PBVH *pbvh, const int cd_vert_node_offset, const int cd_face_node_offset, - const int cd_dyn_vert); + const int cd_dyn_vert, + const int cd_face_areas); void BKE_pbvh_free(PBVH *pbvh); /** update original data, only data whose r_** parameters are passed in will be updated*/ @@ -436,6 +442,18 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh, void *mask_cb_data); /* Node Access */ +void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node); + +// updates boundaries and valences for whole mesh +void BKE_pbvh_bmesh_on_mesh_change(PBVH *pbvh); +bool BKE_pbvh_bmesh_check_valence(PBVH *pbvh, SculptVertRef vertex); +void BKE_pbvh_bmesh_update_valence(int cd_dyn_vert, SculptVertRef vertex); +void BKE_pbvh_bmesh_update_all_valence(PBVH *pbvh); +void BKE_pbvh_bmesh_flag_all_disk_sort(PBVH *pbvh); +bool BKE_pbvh_bmesh_mark_update_valence(PBVH *pbvh, SculptVertRef vertex); + +void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node); +void BKE_pbvh_update_all_tri_areas(PBVH *pbvh); void BKE_pbvh_node_mark_update(PBVHNode *node); void BKE_pbvh_node_mark_update_mask(PBVHNode *node); void BKE_pbvh_node_mark_update_color(PBVHNode *node); @@ -751,6 +769,8 @@ void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, struc 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); + #if 0 typedef enum { SCULPT_TEXTURE_UV = 1 << 0, // per-uv diff --git a/source/blender/blenkernel/intern/dyntopo.c b/source/blender/blenkernel/intern/dyntopo.c index da3e42e629d..023cb324346 100644 --- a/source/blender/blenkernel/intern/dyntopo.c +++ b/source/blender/blenkernel/intern/dyntopo.c @@ -32,6 +32,8 @@ #include <stdio.h> +#define DYNVERT_VALENCE_TEMP (1 << 14) + //#define USE_NEW_SPLIT #define DYNVERT_ALL_BOUNDARY (DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY) @@ -162,6 +164,7 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v) if (!e) { return; } + pbvh_check_vert_boundary(pbvh, v); const int cd_dyn_vert = pbvh->cd_dyn_vert; @@ -172,7 +175,8 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v) do { BMVert *v2 = e->v1 == v ? e->v2 : e->v1; - pbvh_check_vert_boundary(pbvh, v2); + // can't check for boundary here, thread + // pbvh_check_vert_boundary(pbvh, v2); MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v2); const bool bound2 = mv2->flag & DYNVERT_ALL_BOUNDARY; @@ -846,8 +850,40 @@ typedef struct { float max_elen; float min_elen; float totedge; + BMVert **val34_verts; + int val34_verts_tot; + int val34_verts_size; } EdgeQueueContext; +static void edge_queue_insert_val34_vert(EdgeQueueContext *eq_ctx, BMVert *v) +{ + MDynTopoVert *mv = BKE_PBVH_DYNVERT(eq_ctx->cd_dyn_vert, v); + // prevent double adding + + if (mv->flag & DYNVERT_VALENCE_TEMP) { + return; + } + + mv->flag |= DYNVERT_VALENCE_TEMP; + + eq_ctx->val34_verts_tot++; + + if (eq_ctx->val34_verts_tot > eq_ctx->val34_verts_size) { + int size2 = 4 + eq_ctx->val34_verts_tot + (eq_ctx->val34_verts_tot >> 1); + + if (eq_ctx->val34_verts) { + eq_ctx->val34_verts = MEM_reallocN(eq_ctx->val34_verts, sizeof(void *) * size2); + } + else { + eq_ctx->val34_verts = MEM_mallocN(sizeof(void *) * size2, "val34_verts"); + } + + eq_ctx->val34_verts_size = size2; + } + + eq_ctx->val34_verts[eq_ctx->val34_verts_tot - 1] = v; +} + BLI_INLINE float maskcb_get(EdgeQueueContext *eq_ctx, BMEdge *e) { if (eq_ctx->mask_cb) { @@ -1019,6 +1055,8 @@ typedef struct EdgeQueueThreadData { PBVH *pbvh; PBVHNode *node; BMEdge **edges; + BMVert **val34_verts; + int val34_verts_tot; EdgeQueueContext *eq_ctx; int totedge; int size; @@ -1346,6 +1384,8 @@ static void long_edge_queue_edge_add_recursive_2(EdgeQueueThreadData *tdata, } } +static int _long_edge_queue_task_cb_seed = 0; + static void long_edge_queue_task_cb(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) @@ -1353,6 +1393,9 @@ static void long_edge_queue_task_cb(void *__restrict userdata, EdgeQueueThreadData *tdata = ((EdgeQueueThreadData *)userdata) + n; PBVHNode *node = tdata->node; EdgeQueueContext *eq_ctx = tdata->eq_ctx; + RNG *rng = BLI_rng_new(_long_edge_queue_task_cb_seed++); // I don't care if seed becomes mangled + BMVert **val34 = NULL; + BLI_array_declare(val34); BMFace *f; const int cd_dyn_vert = tdata->pbvh->cd_dyn_vert; @@ -1381,9 +1424,23 @@ static void long_edge_queue_task_cb(void *__restrict userdata, BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter = l_first; do { + MDynTopoVert *mv = BKE_PBVH_DYNVERT(eq_ctx->cd_dyn_vert, l_iter->v); + + /* + If valence is not up to date, just add it to the list; + long_edge_queue_create will check and de-duplicate this for us. + + Can't update valence in a thread after all. + */ + if (mv->valence < 5 || (mv->flag & DYNVERT_NEED_VALENCE)) { + BLI_array_append(val34, l_iter->v); + } + // try to improve convergence by applying a small amount of smoothing to topology, // but tangentially to surface. - surface_smooth_v_safe(tdata->pbvh, l_iter->v); + if (BLI_rng_get_float(rng) > 0.75) { + surface_smooth_v_safe(tdata->pbvh, l_iter->v); + } #ifdef USE_EDGEQUEUE_EVEN_SUBDIV float w = maskcb_get(eq_ctx, l_iter->e); @@ -1405,6 +1462,11 @@ static void long_edge_queue_task_cb(void *__restrict userdata, } } TGSET_ITER_END + + BLI_rng_free(rng); + + tdata->val34_verts = val34; + tdata->val34_verts_tot = BLI_array_len(val34); } static void short_edge_queue_task_cb(void *__restrict userdata, @@ -1573,17 +1635,25 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f) static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v) { - BMFace **fs = NULL; - BLI_array_staticdeclare(fs, 32); - MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v); + if (!(mv->flag & DYNVERT_NEED_TRIANGULATE)) { return true; } + BMFace **fs = NULL; + BLI_array_staticdeclare(fs, 32); + BMIter iter; BMFace *f; BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { + BMLoop *l = f->l_first; + + do { + MDynTopoVert *mv_l = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, l->v); + + mv_l->flag |= DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT; + } while ((l = l->next) != f->l_first); BLI_array_append(fs, f); } @@ -1598,6 +1668,34 @@ static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v) return false; } +static void edge_queue_init(EdgeQueueContext *eq_ctx, + bool use_projected, + bool use_frontface, + const float center[3], + const float view_normal[3], + const float radius) +{ + if (use_projected) { + eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_circle; + eq_ctx->q->edge_queue_vert_in_range = edge_queue_vert_in_circle; + project_plane_normalized_v3_v3v3(eq_ctx->q->center_proj, center, view_normal); + } + else { + eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere; + eq_ctx->q->edge_queue_vert_in_range = edge_queue_vert_in_sphere; + } + + eq_ctx->q->center = center; + eq_ctx- @@ 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