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
This commit is contained in:
Philipp Oeser
2024-04-28 11:36:56 +02:00
parent 16a29a7a75
commit 0bf4568abd
3 changed files with 62 additions and 34 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,