From 0bf4568abdd607f1bcbc9359eebddfcfb2827f32 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Sun, 28 Apr 2024 11:36:56 +0200 Subject: [PATCH] revert 4d49c78e74f0b53b348111a487eece05b3e7e5ab revert Fix: weight and vertex paint radial symmetry wrong with mirror Was causing #121155, will check again on Monday Both vertexpaint and weightpaint would only apply all of radial symmetry for the "initial stroke". When going over the combinations of symmetry axis, some of radial symmetry would be skipped, e.g. when mirroring from right to left with `Mirror X` turned ON, a dab on the right would have radial symmetry from that point, and an additional dab on the left from mirroring (but the mirrored dab would not have radial symmetry on its own). This does not lead to symmetric results at all, sculptmode also does not behave that way (there, radial symmetry is performed on the mirror axis as well). Now do the same thing as in sculptmode to get symmetric results when using mirror and radial symmetry together. Also use the utility function to skip invalid symmetry iterations. Stumbled over this when looking into #120843 Pull Request: https://projects.blender.org/blender/blender/pulls/120931 --- .../editors/sculpt_paint/paint_vertex.cc | 47 ++++++++++++------- .../editors/sculpt_paint/paint_weight.cc | 47 ++++++++++++------- source/blender/editors/sculpt_paint/sculpt.cc | 2 - 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index 9bcff41ade2..920c03e5025 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -1864,7 +1864,8 @@ static void vpaint_do_radial_symmetry(bContext *C, } } -/* near duplicate of: #do_symmetrical_brush_actions and #wpaint_do_symmetrical_brush_actions. */ +/* near duplicate of: sculpt.cc's, + * 'do_symmetrical_brush_actions' and 'wpaint_do_symmetrical_brush_actions'. */ static void vpaint_do_symmetrical_brush_actions(bContext *C, VPaint *vp, VPaintData *vpd, @@ -1875,26 +1876,40 @@ static void vpaint_do_symmetrical_brush_actions(bContext *C, SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; const char symm = SCULPT_mesh_symmetry_xyz_get(ob); + int i = 0; + + /* initial stroke */ + const ePaintSymmetryFlags initial_symm = ePaintSymmetryFlags(0); + cache->mirror_symmetry_pass = ePaintSymmetryFlags(0); + vpaint_do_paint(C, vp, vpd, ob, mesh, brush, initial_symm, 'X', 0, 0); + vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, initial_symm, 'X'); + vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, initial_symm, 'Y'); + vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, initial_symm, 'Z'); cache->symmetry = symm; - /* symm is a bit combination of XYZ - - * 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ - for (int i = 0; i <= symm; i++) { + /* symm is a bit combination of XYZ - 1 is mirror + * X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ + for (i = 1; i <= symm; i++) { + if (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5))) { + const ePaintSymmetryFlags symm_pass = ePaintSymmetryFlags(i); + cache->mirror_symmetry_pass = symm_pass; + cache->radial_symmetry_pass = 0; + SCULPT_cache_calc_brushdata_symm(cache, symm_pass, 0, 0); - if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { - continue; + if (i & (1 << 0)) { + vpaint_do_paint(C, vp, vpd, ob, mesh, brush, symm_pass, 'X', 0, 0); + vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, symm_pass, 'X'); + } + if (i & (1 << 1)) { + vpaint_do_paint(C, vp, vpd, ob, mesh, brush, symm_pass, 'Y', 0, 0); + vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, symm_pass, 'Y'); + } + if (i & (1 << 2)) { + vpaint_do_paint(C, vp, vpd, ob, mesh, brush, symm_pass, 'Z', 0, 0); + vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, symm_pass, 'Z'); + } } - - const ePaintSymmetryFlags symm_pass = ePaintSymmetryFlags(i); - cache->mirror_symmetry_pass = symm_pass; - cache->radial_symmetry_pass = 0; - SCULPT_cache_calc_brushdata_symm(cache, symm_pass, 0, 0); - - vpaint_do_paint(C, vp, vpd, ob, mesh, brush, symm_pass, 'X', 0, 0); - vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, symm_pass, 'X'); - vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, symm_pass, 'Y'); - vpaint_do_radial_symmetry(C, vp, vpd, ob, mesh, brush, symm_pass, 'Z'); } copy_v3_v3(cache->true_last_location, cache->true_location); diff --git a/source/blender/editors/sculpt_paint/paint_weight.cc b/source/blender/editors/sculpt_paint/paint_weight.cc index 86a19e3b7f9..b312dc525d3 100644 --- a/source/blender/editors/sculpt_paint/paint_weight.cc +++ b/source/blender/editors/sculpt_paint/paint_weight.cc @@ -1726,7 +1726,8 @@ static void wpaint_do_radial_symmetry(bContext *C, } } -/* near duplicate of: #do_symmetrical_brush_actions and #vpaint_do_symmetrical_brush_actions. */ +/* near duplicate of: sculpt.cc's, + * 'do_symmetrical_brush_actions' and 'vpaint_do_symmetrical_brush_actions'. */ static void wpaint_do_symmetrical_brush_actions( bContext *C, Object *ob, VPaint *wp, WPaintData *wpd, WeightPaintInfo *wpi) { @@ -1735,6 +1736,14 @@ static void wpaint_do_symmetrical_brush_actions( SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; const char symm = SCULPT_mesh_symmetry_xyz_get(ob); + int i = 0; + + /* initial stroke */ + cache->mirror_symmetry_pass = ePaintSymmetryFlags(0); + wpaint_do_paint(C, ob, wp, wpd, wpi, mesh, brush, ePaintSymmetryFlags(0), 'X', 0, 0); + wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, ePaintSymmetryFlags(0), 'X'); + wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, ePaintSymmetryFlags(0), 'Y'); + wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, ePaintSymmetryFlags(0), 'Z'); cache->symmetry = symm; @@ -1745,22 +1754,28 @@ static void wpaint_do_symmetrical_brush_actions( return; } - /* symm is a bit combination of XYZ - - * 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ - for (int i = 0; i <= symm; i++) { - if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { - continue; + /* symm is a bit combination of XYZ - 1 is mirror + * X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ + for (i = 1; i <= symm; i++) { + if (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5))) { + const ePaintSymmetryFlags symm = ePaintSymmetryFlags(i); + cache->mirror_symmetry_pass = symm; + cache->radial_symmetry_pass = 0; + SCULPT_cache_calc_brushdata_symm(cache, symm, 0, 0); + + if (i & (1 << 0)) { + wpaint_do_paint(C, ob, wp, wpd, wpi, mesh, brush, symm, 'X', 0, 0); + wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, symm, 'X'); + } + if (i & (1 << 1)) { + wpaint_do_paint(C, ob, wp, wpd, wpi, mesh, brush, symm, 'Y', 0, 0); + wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, symm, 'Y'); + } + if (i & (1 << 2)) { + wpaint_do_paint(C, ob, wp, wpd, wpi, mesh, brush, symm, 'Z', 0, 0); + wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, symm, 'Z'); + } } - - const ePaintSymmetryFlags symm = ePaintSymmetryFlags(i); - cache->mirror_symmetry_pass = symm; - cache->radial_symmetry_pass = 0; - SCULPT_cache_calc_brushdata_symm(cache, symm, 0, 0); - - wpaint_do_paint(C, ob, wp, wpd, wpi, mesh, brush, symm, 'X', 0, 0); - wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, symm, 'X'); - wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, symm, 'Y'); - wpaint_do_radial_symmetry(C, ob, wp, wpd, wpi, mesh, brush, symm, 'Z'); } copy_v3_v3(cache->true_last_location, cache->true_location); cache->is_last_valid = true; diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index f1cad16cc10..01be621ca98 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -4001,8 +4001,6 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob) } } -/* near duplicate of: #wpaint_do_symmetrical_brush_actions and - * #vpaint_do_symmetrical_brush_actions. */ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob, BrushActionFunc action,