diff options
author | Joseph Eagar <joeedh@gmail.com> | 2021-09-14 05:24:21 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2021-09-14 05:24:21 +0300 |
commit | 3df335d330a694269a9ceefb7234a00c69ca4be9 (patch) | |
tree | e8ebcd41ab9ae8602ed1a8e762f4fd6a40c14cae /source/blender/editors | |
parent | 0676928408af53d6ca76690b1a9772b303ccc39d (diff) |
Sculpt dyntopo:
* Fixed noise on using autosmooth with tools that use original
coorinates. While this was most prominent with DynTopo,
it did happen with other tools.
* The solution is to smooth the original coordinates as well
as the explicit coordinates if the active tool requires
original data.
* I decided to replace the original coordinates system for
PBVH_FACES and PBVH_GRIDS with the same MDynTopoVert structure
DynTopo uses. The alternative would have been extremely messy
code.
* Todo: Rename MDynTopoVert to. . .SculptInfoVert?
* Todo: Cache boundary flag and corner info in MDynTopoVert->flag
for PBVH_FACES/GRIDS similar to PBVH_BMESH.
Diffstat (limited to 'source/blender/editors')
11 files changed, 256 insertions, 145 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index f2f4ca9582b..fc2720bc31d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -158,15 +158,40 @@ int SCULPT_vertex_count_get(SculptSession *ss) return 0; } -const float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex) +MDynTopoVert *SCULPT_vertex_get_mdyntopo(SculptSession *ss, SculptVertRef vertex) { - if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BMVert *v = (BMVert *)vertex.i; - return BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v)->origco; + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_BMESH: { + BMVert *v = (BMVert *)vertex.i; + return BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v); + } + + case PBVH_GRIDS: + case PBVH_FACES: { + return ss->mdyntopo_verts + vertex.i; + } } - // XXX implement me - return SCULPT_vertex_co_get(ss, vertex); + return NULL; +} + +float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_BMESH: { + BMVert *v = (BMVert *)vertex.i; + return BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v)->origco; + } + + case PBVH_GRIDS: + case PBVH_FACES: { + MDynTopoVert *mv = ss->mdyntopo_verts + vertex.i; + + return ss->mdyntopo_verts[vertex.i].origco; + } + } + + return NULL; } const float *SCULPT_vertex_co_get(SculptSession *ss, SculptVertRef index) @@ -2284,6 +2309,9 @@ typedef enum StrokeFlags { void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, SculptUndoNode *unode) { SculptSession *ss = ob->sculpt; + + // do nothing + BMesh *bm = ss->bm; memset(data, 0, sizeof(*data)); @@ -2295,12 +2323,9 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul if (bm) { data->bm_log = ss->bm_log; } + else { - data->datatype = data->unode->type; - data->coords = data->unode->co; - data->normals = data->unode->no; - data->vmasks = data->unode->mask; - data->colors = data->unode->col; + // data->datatype = data->unode->type; } } @@ -2316,75 +2341,58 @@ void SCULPT_orig_vert_data_init(SculptOrigVertData *data, SculptUndoNode *unode = NULL; data->ss = ob->sculpt; - /*do not allocate an undo node for bmesh pbvh*/ + // don't need undo node here anymore if (!ob->sculpt->bm) { - unode = SCULPT_undo_push_node(ob, node, type); + // unode = SCULPT_undo_push_node(ob, node, type); } SCULPT_orig_vert_data_unode_init(data, ob, unode); data->datatype = type; } -/** - * Update a #SculptOrigVertData for a particular vertex from the PBVH iterator. - */ -void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter) +void SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex) { // check if we need to update original data for current stroke - if (orig_data->bm_log) { - MDynTopoVert *mv = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert); - if (mv->stroke_id != orig_data->ss->stroke_id) { - mv->stroke_id = orig_data->ss->stroke_id; + MDynTopoVert *mv = ss->bm ? BKE_PBVH_DYNVERT(ss->cd_dyn_vert, (BMVert *)vertex.i) : + ss->mdyntopo_verts + vertex.i; - copy_v3_v3(mv->origco, iter->bm_vert->co); - copy_v3_v3(mv->origno, iter->bm_vert->no); + if (mv->stroke_id != ss->stroke_id) { + mv->stroke_id = ss->stroke_id; - const int cd_vcol = iter->cd_vcol_offset; - const int cd_mask = iter->cd_vert_mask_offset; - - if (cd_vcol >= 0) { - MPropCol *col = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, cd_vcol); - copy_v4_v4(mv->origcolor, col->color); - } + copy_v3_v3(mv->origco, SCULPT_vertex_co_get(ss, vertex)); + SCULPT_vertex_normal_get(ss, vertex, mv->origno); - if (cd_mask >= 0) { - mv->origmask = BM_ELEM_CD_GET_FLOAT(iter->bm_vert, cd_mask); - } + const float *color = SCULPT_vertex_color_get(ss, vertex); + if (color) { + copy_v4_v4(mv->origcolor, color); } + + mv->origmask = SCULPT_vertex_mask_get(ss, vertex); } +} - if (orig_data->datatype == SCULPT_UNDO_COORDS) { - if (orig_data->bm_log) { - orig_data->co = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origco; +/** + * DEPRECATED use Update a #SculptOrigVertData for a particular vertex from the PBVH iterator. + */ +void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, SculptVertRef vertex) +{ + // check if we need to update original data for current stroke + MDynTopoVert *mv = SCULPT_vertex_get_mdyntopo(orig_data->ss, vertex); - float *no = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origno; - normal_float_to_short_v3(orig_data->_no, no); - orig_data->no = orig_data->_no; + SCULPT_vertex_check_origdata(orig_data->ss, vertex); - orig_data->col = iter->cd_vcol_offset >= 0 ? - BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origcolor : - NULL; - } - else { - orig_data->co = orig_data->coords[iter->i]; - orig_data->no = orig_data->normals[iter->i]; - } + if (orig_data->datatype == SCULPT_UNDO_COORDS) { + float *no = mv->origno; + normal_float_to_short_v3(orig_data->_no, no); + + orig_data->no = orig_data->_no; + orig_data->co = mv->origco; } else if (orig_data->datatype == SCULPT_UNDO_COLOR) { - if (orig_data->bm_log) { - orig_data->col = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origcolor; - } - else { - orig_data->col = orig_data->colors[iter->i]; - } + orig_data->col = mv->origcolor; } else if (orig_data->datatype == SCULPT_UNDO_MASK) { - if (orig_data->bm_log) { - orig_data->mask = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origmask; - } - else { - orig_data->mask = orig_data->vmasks[iter->i]; - } + orig_data->mask = mv->origmask; } } @@ -2547,7 +2555,7 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (orig_data.unode->type == SCULPT_UNDO_COORDS) { copy_v3_v3(vd.co, orig_data.co); @@ -4050,20 +4058,25 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, } #endif - SCULPT_bmesh_four_neighbor_average(ss, - avg, - direction2, - vd.bm_vert, - data->rake_projection, - check_fsets, - data->cd_temp, - data->cd_dyn_vert); + int steps = data->do_origco ? 2 : 1; - sub_v3_v3v3(val, avg, vd.co); + for (int step = 0; step < steps; step++) { + float *co = step ? (float *)SCULPT_vertex_origco_get(ss, vd.vertex) : vd.co; - madd_v3_v3v3fl(val, vd.co, val, fade); + SCULPT_bmesh_four_neighbor_average(ss, + avg, + direction2, + vd.bm_vert, + data->rake_projection, + check_fsets, + data->cd_temp, + data->cd_dyn_vert, + step); - SCULPT_clip(sd, ss, vd.co, val); + sub_v3_v3v3(val, avg, co); + madd_v3_v3v3fl(val, co, val, fade); + SCULPT_clip(sd, ss, co, val); + } if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -4146,7 +4159,8 @@ static void bmesh_topology_rake( .strength = factor, .cd_temp = cd_temp, .cd_dyn_vert = ss->cd_dyn_vert, - .rake_projection = brush->topology_rake_projection}; + .rake_projection = brush->topology_rake_projection, + .do_origco = SCULPT_stroke_needs_original(brush)}; TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); @@ -4220,7 +4234,7 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) do_mask_brush_draw(sd, ob, nodes, totnode); break; case BRUSH_MASK_SMOOTH: - SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true, 0.0f); + SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true, 0.0f, false); break; } } @@ -4537,7 +4551,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -4620,7 +4634,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -4789,7 +4803,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -5188,7 +5202,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -5289,7 +5303,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, ¶ms, ss->cache->radius, force, 1.0f, brush->elastic_deform_volume_preservation); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); float final_disp[3]; switch (brush->elastic_deform_type) { case BRUSH_ELASTIC_DEFORM_GRAB: @@ -5740,7 +5754,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -5813,7 +5827,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -5916,7 +5930,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { continue; @@ -7710,11 +7724,18 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings totnode, brush->autosmooth_factor * (1.0f - ss->cache->pressure), false, - brush->autosmooth_projection); + brush->autosmooth_projection, + false); } else { - SCULPT_smooth( - sd, ob, nodes, totnode, brush->autosmooth_factor, false, brush->autosmooth_projection); + SCULPT_smooth(sd, + ob, + nodes, + totnode, + brush->autosmooth_factor, + false, + brush->autosmooth_projection, + false); } if (brush->autosmooth_radius_factor != 1.0f) { diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c index c77d9c92a2e..2e65c7afe65 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.c +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c @@ -1589,7 +1589,7 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, continue; } - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!SCULPT_check_vertex_pivot_symmetry( orig_data.co, boundary->initial_vertex_position, symm)) { continue; @@ -1638,7 +1638,7 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, continue; } - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!SCULPT_check_vertex_pivot_symmetry( orig_data.co, boundary->initial_vertex_position, symm)) { continue; @@ -1684,7 +1684,7 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, continue; } - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!SCULPT_check_vertex_pivot_symmetry( orig_data.co, boundary->initial_vertex_position, symm)) { continue; @@ -1730,7 +1730,7 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, continue; } - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!SCULPT_check_vertex_pivot_symmetry( orig_data.co, boundary->initial_vertex_position, symm)) { continue; @@ -1781,7 +1781,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, continue; } - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!SCULPT_check_vertex_pivot_symmetry( orig_data.co, boundary->initial_vertex_position, symm)) { continue; @@ -1827,7 +1827,7 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata, continue; } - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!SCULPT_check_vertex_pivot_symmetry( orig_data.co, boundary->initial_vertex_position, symm)) { continue; @@ -1913,7 +1913,7 @@ static void SCULPT_boundary_autosmooth(SculptSession *ss, SculptBoundary *bounda float sco[3]; SCULPT_neighbor_coords_average_interior( - ss, sco, vd.vertex, ss->cache->brush->autosmooth_projection, NULL); + ss, sco, vd.vertex, ss->cache->brush->autosmooth_projection, NULL, false); float *co = SCULPT_brush_deform_target_vertex_co_get( ss, ss->cache->brush->deform_target, &vd); @@ -1952,7 +1952,7 @@ static void SCULPT_boundary_build_smoothco(SculptSession *ss, SculptBoundary *bo float sco[3]; - SCULPT_neighbor_coords_average_interior(ss, sco, vd.vertex, projection, NULL); + SCULPT_neighbor_coords_average_interior(ss, sco, vd.vertex, projection, NULL, false); float *co = SCULPT_brush_deform_target_vertex_co_get( ss, ss->cache->brush->deform_target, &vd); diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c index 31919b82a82..888874941f7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c @@ -768,6 +768,11 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene SCULPT_pbvh_clear(ob); + if (ss->mdyntopo_verts) { + MEM_freeN(ss->mdyntopo_verts); + ss->mdyntopo_verts = NULL; + } + ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) != 0; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 6e204705953..dfb1f2e74dc 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -111,7 +111,7 @@ static void color_filter_task_cb(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); float orig_color[3], final_color[4], hsv_color[3]; int hue; float brightness, contrast, gain, delta, offset; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index e9d699d4f79..4e50b9fbd9b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -303,7 +303,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); float orig_co[3], val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3], final_pos[3]; float fade = vd.mask ? *vd.mask : 0.0f; fade = 1.0f - fade; @@ -334,7 +334,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, switch (filter_type) { case MESH_FILTER_SMOOTH: fade = clamp_f(fade, -1.0f, 1.0f); - SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, 0.0f, NULL); + SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, 0.0f, NULL, false); sub_v3_v3v3(val, avg, orig_co); madd_v3_v3v3fl(val, orig_co, val, fade); sub_v3_v3v3(disp, val, orig_co); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 131fbf4cf1c..5448ab5746b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -217,8 +217,9 @@ void SCULPT_vertex_neighbors_get(const struct SculptSession *ss, SculptVertRef SCULPT_active_vertex_get(SculptSession *ss); const float *SCULPT_active_vertex_co_get(SculptSession *ss); -const float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex); +float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex); void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3]); +MDynTopoVert *SCULPT_vertex_get_mdyntopo(SculptSession *ss, SculptVertRef vertex); /* Returns PBVH deformed vertices array if shape keys or deform modifiers are used, otherwise * returns mesh original vertices array. */ @@ -646,7 +647,8 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, float projection, bool check_fsets, int cd_temp, - int cd_dyn_vert); + int cd_dyn_vert, + bool do_origco); /* Smoothing api */ void SCULPT_neighbor_coords_average( @@ -659,7 +661,8 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], SculptVertRef index, float projection, - SculptCustomLayer *bound_scl); + SculptCustomLayer *bound_scl, + bool do_origco); void SCULPT_smooth_vcol_boundary( Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength); @@ -670,7 +673,8 @@ void SCULPT_smooth(Sculpt *sd, const int totnode, float bstrength, const bool smooth_mask, - float projection); + float projection, + bool do_origco); void SCULPT_do_smooth_brush( Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float projection); @@ -923,6 +927,7 @@ typedef struct SculptThreadedTaskData { float smooth_projection; float rake_projection; SculptCustomLayer *scl, *scl2; + bool do_origco; } SculptThreadedTaskData; /*************** Brush testing declarations ****************/ @@ -1446,11 +1451,13 @@ void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache, const float angle); void SCULPT_cache_free(StrokeCache *cache); +void SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex); + void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node, SculptUndoType type); -void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter); +void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, SculptVertRef vertex); void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, struct SculptUndoNode *unode); @@ -1692,3 +1699,13 @@ void SCULPT_replay_log_append(struct Sculpt *sd, struct SculptSession *ss, struc void SCULPT_replay_test(void); #endif + +#define SCULPT_stroke_needs_original(brush) \ + ELEM(brush->sculpt_tool, \ + SCULPT_TOOL_DRAW_SHARP, \ + SCULPT_TOOL_GRAB, \ + SCULPT_TOOL_ROTATE, \ + SCULPT_TOOL_THUMB, \ + SCULPT_TOOL_ELASTIC_DEFORM, \ + SCULPT_TOOL_BOUNDARY, \ + SCULPT_TOOL_POSE) diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c index a294108c228..e86c5b9ecb9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -140,7 +140,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, IMB_colormanagement_srgb_to_scene_linear_v3(brush_color); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); bool affect_vertex = false; float distance_to_stroke_location = 0.0f; diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index 07f0f763ff9..09517820485 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -175,7 +175,7 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata, SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); float total_disp[3]; zero_v3(total_disp); diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 33a6fadde7f..293702f33b0 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -78,9 +78,17 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], SculptVertRef vertex, float projection, - SculptCustomLayer *bound_scl) + SculptCustomLayer *bound_scl, + bool do_origco) { float avg[3] = {0.0f, 0.0f, 0.0f}; + + MDynTopoVert *mv = SCULPT_vertex_get_mdyntopo(ss, vertex); + + if (do_origco) { + SCULPT_vertex_check_origdata(ss, vertex); + } + float total = 0.0f; int neighbor_count = 0; bool check_fsets = ss->cache->brush->flag2 & BRUSH_SMOOTH_PRESERVE_FACE_SETS; @@ -97,11 +105,16 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, const SculptBoundaryType is_boundary = SCULPT_vertex_is_boundary(ss, vertex, bflag); - const float *co = SCULPT_vertex_co_get(ss, vertex); + const float *co = do_origco ? mv->origco : SCULPT_vertex_co_get(ss, vertex); float no[3]; if (true || projection > 0.0f) { - SCULPT_vertex_normal_get(ss, vertex, no); + if (do_origco) { + copy_v3_v3(no, mv->origno); + } + else { + SCULPT_vertex_normal_get(ss, vertex, no); + } } const bool weighted = (ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT) && !is_boundary; @@ -131,6 +144,16 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) { + MDynTopoVert *mv2 = SCULPT_vertex_get_mdyntopo(ss, ni.vertex); + const float *co2; + + if (!do_origco || mv2->stroke_id != ss->stroke_id) { + co2 = SCULPT_vertex_co_get(ss, ni.vertex); + } + else { + co2 = mv2->origco; + } + neighbor_count++; float tmp[3], w; @@ -186,12 +209,12 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, w *= slide_fset; - sub_v3_v3v3(t, SCULPT_vertex_co_get(ss, ni.vertex), co); + sub_v3_v3v3(t, co2, co); madd_v3_v3v3fl(tmp, co, no, dot_v3v3(t, no)); ok = true; } else if (final_boundary) { - copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex)); + copy_v3_v3(tmp, co2); ok = true; do_diffuse = false; } @@ -200,7 +223,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, } } else { - copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex)); + copy_v3_v3(tmp, co2); ok = true; } @@ -210,7 +233,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, makes more rounded edges. */ - copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex)); + copy_v3_v3(tmp, co2); ok = true; float len = len_v3v3(co, tmp); @@ -228,7 +251,13 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, btot += w2; float no2[3]; - SCULPT_vertex_normal_get(ss, ni.vertex, no2); + + if (!do_origco || mv2->stroke_id != ss->stroke_id) { + SCULPT_vertex_normal_get(ss, ni.vertex, no2); + } + else { + copy_v3_v3(no2, mv2->origno); + } float radius = ss->cache->radius * 10.0f; @@ -280,13 +309,13 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, /* Do not modify corner vertices. */ if (neighbor_count <= 2 && is_boundary) { - copy_v3_v3(result, SCULPT_vertex_co_get(ss, vertex)); + copy_v3_v3(result, co); return; } /* Avoid division by 0 when there are no neighbors. */ if (total == 0.0f) { - copy_v3_v3(result, SCULPT_vertex_co_get(ss, vertex)); + copy_v3_v3(result, co); return; } @@ -475,11 +504,12 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, float projection, bool check_fsets, int cd_temp, - int cd_dyn_vert) + int cd_dyn_vert, + bool do_origco) { - float avg_co[3] = {0.0f, 0.0f, 0.0f}; float tot_co = 0.0f; + float buckets[8] = {0}; // zero_v3(direction); @@ -493,6 +523,17 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, const bool weighted = (ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT); float *areas; + SCULPT_vertex_check_origdata(ss, (SculptVertRef){.i = (intptr_t)v}); + + if (do_origco) { + // SCULPT_vertex_check_origdata(ss, (SculptVertRef){.i = (intptr_t)v}); + madd_v3_v3fl(direction, mv->origno, -dot_v3v3(mv->origno, direction)); + normalize_v3(direction); + } + + float *co1 = do_origco ? mv->origco : v->co; + float *no1 = do_origco ? mv->origno : v->no; + if (weighted) { SculptVertRef vertex = {.i = (intptr_t)v}; @@ -508,12 +549,12 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, copy_v3_v3(dir, direction); } else { - closest_vec_to_perp(dir, direction, v->no, buckets, 1.0f); // col[3]); + closest_vec_to_perp(dir, direction, no1, buckets, 1.0f); // col[3]); } float totdir3 = 0.0f; - const float selfw = (float)mv->valence * 0.25f; + const float selfw = (float)mv->valence * 0.0025f; madd_v3_v3fl(dir3, direction, selfw); totdir3 += selfw; @@ -538,6 +579,18 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, //} MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v_other); + float *co2; + float *no2; + + if (!do_origco || mv2->stroke_id != ss->stroke_id) { + co2 = v_other->co; + no2 = v_other->no; + } + else { + co2 = mv2->origco; + no2 = mv2->origno; + } + // bool bound = (mv2->flag & // (DYNVERT_BOUNDARY)); // | DYNVERT_FSET_BOUNDARY | DYNVERT_SHARP_BOUNDARY)); // bool bound2 = (mv2->flag & @@ -552,8 +605,8 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, if (bound) { had_bound = true; - sub_v3_v3v3(dir2, v_other->co, v->co); - madd_v3_v3fl(dir2, v->no, -dot_v3v3(v->no, dir2)); + sub_v3_v3v3(dir2, co2, co1); + madd_v3_v3fl(dir2, no1, -dot_v3v3(no1, dir2)); normalize_v3(dir2); dirw = 100000.0f; } @@ -566,7 +619,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, } } - closest_vec_to_perp(dir, dir2, v->no, buckets, bucketw); // col2[3]); + closest_vec_to_perp(dir, dir2, no1, buckets, bucketw); // col2[3]); madd_v3_v3fl(dir3, dir2, dirw); totdir3 += dirw; @@ -577,9 +630,9 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, } float vec[3]; - sub_v3_v3v3(vec, v_other->co, v->co); + sub_v3_v3v3(vec, co2, co1); - madd_v3_v3fl(vec, v->no, -dot_v3v3(vec, v->no) * projection); + madd_v3_v3fl(vec, no1, -dot_v3v3(vec, no1) * projection); normalize_v3(vec); /* fac is a measure of how orthogonal or parallel the edge is @@ -610,7 +663,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, fac *= areas[area_i]; } - madd_v3_v3fl(avg_co, v_other->co, fac); + madd_v3_v3fl(avg_co, co2, fac); tot_co += fac; } @@ -620,14 +673,19 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, /* Preserve volume. */ float vec[3]; - sub_v3_v3(avg, v->co); - mul_v3_v3fl(vec, v->no, dot_v3v3(avg, v->no) * projection); + sub_v3_v3(avg, co1); + mul_v3_v3fl(vec, no1, dot_v3v3(avg, no1) * projection); sub_v3_v3(avg, vec); - add_v3_v3(avg, v->co); + add_v3_v3(avg, co1); } else { // zero_v3(avg); - copy_v3_v3(avg, v->co); + copy_v3_v3(avg, co1); + } + + // do not update in do_origco + if (do_origco) { + return; } if (totdir3 > 0.0f) { @@ -658,7 +716,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss, } // negate_v3(col); - vec_transform(col, v->no, bi); + vec_transform(col, no1, bi); // negate_v3(col); } } @@ -1077,10 +1135,16 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata, // continue; //} - SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, projection, bound_scl); - sub_v3_v3v3(val, avg, vd.co); - madd_v3_v3v3fl(val, vd.co, val, fade); - SCULPT_clip(sd, ss, vd.co, val); + int steps = data->do_origco ? 2 : 1; + for (int step = 0; step < steps; step++) { + float *co = step ? (float *)SCULPT_vertex_origco_get(ss, vd.vertex) : vd.co; + + SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, projection, bound_scl, step); + + sub_v3_v3v3(val, avg, co); + madd_v3_v3v3fl(val, co, val, fade); + SCULPT_clip(sd, ss, co, val); + } } if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -1159,7 +1223,8 @@ void SCULPT_smooth(Sculpt *sd, const int totnode, float bstrength, const bool smooth_mask, - float projection) + float projection, + bool do_origco) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -1221,15 +1286,18 @@ void SCULPT_smooth(Sculpt *sd, for (iteration = 0; iteration <= count; iteration++) { const float strength = (iteration != count) ? 1.0f : last; - SculptThreadedTaskData data = {.sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - .smooth_mask = smooth_mask, - .strength = strength, - .smooth_projection = projection, - .scl = have_scl ? &scl : NULL, - .scl2 = bound_scl}; + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + .smooth_mask = smooth_mask, + .strength = strength, + .smooth_projection = projection, + .scl = have_scl ? &scl : NULL, + .scl2 = bound_scl, + .do_origco = SCULPT_stroke_needs_original(ss->cache->brush), + }; TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); @@ -1263,7 +1331,7 @@ void SCULPT_do_smooth_brush( } else { /* Regular mode, smooth. */ - SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false, projection); + SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false, projection, false); } } @@ -1350,7 +1418,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); if (!sculpt_brush_test_sq_fn(&test, vd.co)) { continue; diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index 8d9497f6bef..61ea43efd66 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -165,7 +165,7 @@ static void sculpt_transform_task_cb(void *__restrict userdata, SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS); BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); float transformed_co[3], orig_co[3], disp[3]; float *start_co; float fade = vd.mask ? *vd.mask : 0.0f; diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 9df17c2c7e5..7a5bd81f358 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -1602,7 +1602,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode) } if (ss->deform_modifiers_active) { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_update(&orig_data, vd.vertex); int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, unode->index[vd.i]); |