Sculpt: Drag dot fixes

* Drag dot now uses anchored's method
  of calculating brush rake angle, this
  is much more usable and less numerically
  unstable.

* There is now an option ("Smooth Raking" to
  smooth rake angles during brushes. This was
  a failed effort at fixing drag dot raking
  that turned out to be useful for other things.

* Drag dot no longer requests subspacing events
  from the brush system.  This made a huge
  difference in performance and is now on par
  with anchored mode.
This commit is contained in:
Joseph Eagar 2021-09-30 13:07:22 -07:00
parent 189d32823a
commit d02b557f10
9 changed files with 111 additions and 9 deletions

View File

@ -847,6 +847,13 @@ class StrokePanel(BrushPanel):
row.prop(brush, "spacing", text="Spacing")
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
UnifiedPaintPanel.channel_unified(
col,
context,
brush,
"use_smoothed_rake"
)
if brush.use_line or brush.use_curve:
row = col.row(align=True)
if mode == 'SCULPT':

View File

@ -210,7 +210,8 @@ void BKE_paint_face_set_overlay_color_get(const int face_set, const int seed, uc
/* stroke related */
bool paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups,
struct Brush *brush,
const float mouse_pos[2]);
const float mouse_pos[2],
const float initial_mouse_pos[2]);
void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups,
struct Brush *brush,
float rotation);

View File

@ -438,7 +438,7 @@ MAKE_FLOAT(pose_offset, "Pose Origin Offset", "Offset of the pose origin in rela
MAKE_FLOAT(disconnected_distance_max, "Max Element Distance",
"Maximum distance to search for disconnected loose parts in the mesh", 0.1f, 0.0f, 10.0f)
MAKE_INT(pose_smooth_iterations, "Smooth Iterations",
"Smooth iterations applied after calculating the pose factor of each vertex", 4.0f, 0.0f, 100.0f)
"Smooth iterations applied after calculating the pose factor of each vertex", 4, 0.0f, 100.0f)
MAKE_INT(pose_ik_segments, "Pose IK Segments",
"Number of segments of the inverse kinematics chain that will deform the mesh", 1, 1, 20)
MAKE_FLOAT(surface_smooth_shape_preservation, "Shape Preservation", "How much of the original shape is preserved when smoothing", 0.5f, 0.0f, 1.0f)
@ -524,6 +524,8 @@ MAKE_ENUM(elastic_deform_type, "Deformation", "Deformation type that is used in
})
MAKE_BOOL(use_ctrl_invert, "Use Ctrl Invert", "Take brush addition or subtraction mode into account", true)
MAKE_BOOL(use_smoothed_rake, "Smooth Raking", "Smooth angles of clay strips brush and raked textures", false)
//MAKE_FLOAT3_EX
/* clang-format on */
#if defined(BRUSH_CHANNEL_DEFINE_TYPES) || defined(BRUSH_CHANNEL_DEFINE_EXTERNAL)

View File

@ -47,6 +47,12 @@
# pragma warning(error : 4033) /* 'function' must return a value */
#endif
#if 1
struct {
char t1[32], t2[32], t3[32], t4[32];
} test[1] = {{1, 1, 1, 1}};
#endif
static bool check_builtin_init();
#if 1
@ -247,6 +253,7 @@ static bool check_builtin_init()
SETCAT(tip_scale_x, "Basic");
SETCAT(tip_roundness, "Basic");
SETCAT(normal_radius_factor, "Basic");
SETCAT(use_smoothed_rake, "Basic");
SETCAT(plane_offset, "Clay");
SETCAT(plane_trim, "Clay");
@ -925,6 +932,15 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
ADDCH(radius_unit);
ADDCH(unprojected_radius);
if (!BRUSHSET_LOOKUP(chset, use_smoothed_rake)) {
BrushChannel *ch = ADDCH(use_smoothed_rake);
if (tool == SCULPT_TOOL_CLAY_STRIPS) {
ch->flag |= BRUSH_CHANNEL_SHOW_IN_WORKSPACE;
ch->flag |= BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU;
}
}
ADDCH(plane_offset);
ADDCH(plane_trim);
ADDCH(use_plane_trim);
@ -1218,6 +1234,9 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
SHOWWRK(tip_roundness);
SHOWWRK(use_plane_trim);
SHOWWRK(use_smoothed_rake);
SHOWCTX(use_smoothed_rake);
SHOWCTX(autosmooth);
SHOWCTX(plane_offset);
SHOWCTX(plane_trim);

View File

@ -1309,7 +1309,8 @@ void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, f
bool paint_calculate_rake_rotation(UnifiedPaintSettings *ups,
Brush *brush,
const float mouse_pos[2])
const float mouse_pos[2],
const float initial_mouse_pos[2])
{
bool ok = false;
if ((brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
@ -1317,6 +1318,19 @@ bool paint_calculate_rake_rotation(UnifiedPaintSettings *ups,
const float r = RAKE_THRESHHOLD;
float rotation;
if (brush->flag & BRUSH_DRAG_DOT) {
const float dx = mouse_pos[0] - initial_mouse_pos[0];
const float dy = mouse_pos[1] - initial_mouse_pos[1];
if (dx * dx + dy * dy > 0.5f) {
ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI;
return true;
}
else {
return false;
}
}
float dpos[2];
sub_v2_v2v2(dpos, ups->last_rake, mouse_pos);

View File

@ -926,10 +926,46 @@ static float dist_Minkovsky(float x, float y, float z, float e)
return powf(powf(fabsf(x), e) + powf(fabsf(y), e) + powf(fabsf(z), e), 1.0f / e);
}
BLI_INLINE float calc_voronoi_dist(int dtype, float x, float y, float z, float e)
{
switch (dtype) {
case 1:
return (x * x + y * y + z * z);
break;
case 2:
return fabsf(x) + fabsf(y) + fabsf(z);
break;
case 3: {
x = fabsf(x);
y = fabsf(y);
z = fabsf(z);
float t = (x > y) ? x : y;
return ((z > t) ? z : t);
}
case 4: {
float d = sqrtf(fabsf(x)) + sqrtf(fabsf(y)) + sqrtf(fabsf(z));
return (d * d);
}
case 5: {
x *= x;
y *= y;
z *= z;
return sqrtf(sqrtf(x * x + y * y + z * z));
}
case 6: {
return powf(powf(fabsf(x), e) + powf(fabsf(y), e) + powf(fabsf(z), e), 1.0f / e);
}
case 0:
default:
return sqrtf(x * x + y * y + z * z);
}
}
/* Not 'pure' Worley, but the results are virtually the same.
* Returns distances in da and point coords in pa */
void BLI_noise_voronoi(float x, float y, float z, float *da, float *pa, float me, int dtype)
{
#if 1
float (*distfunc)(float, float, float, float);
switch (dtype) {
case 1:
@ -955,6 +991,7 @@ void BLI_noise_voronoi(float x, float y, float z, float *da, float *pa, float me
distfunc = dist_Real;
break;
}
#endif
int xi = (int)(floor(x));
int yi = (int)(floor(y));

View File

@ -1996,7 +1996,8 @@ static void paint_cursor_update_rake_rotation(PaintCursorContext *pcontext)
* and we may get interference with the stroke itself.
* For line strokes, such interference is visible. */
if (!pcontext->ups->stroke_active) {
paint_calculate_rake_rotation(pcontext->ups, pcontext->brush, pcontext->translation);
paint_calculate_rake_rotation(
pcontext->ups, pcontext->brush, pcontext->translation, pcontext->translation);
}
}

View File

@ -191,7 +191,7 @@ static bool paint_stroke_use_scene_spacing(Brush *brush, ePaintMode mode)
static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode mode)
{
if (brush->flag & BRUSH_ANCHORED) {
if (brush->flag & (BRUSH_ANCHORED|BRUSH_DRAG_DOT)) {
return false;
}
@ -400,7 +400,7 @@ static bool paint_brush_update(bContext *C,
}
/* curve strokes do their own rake calculation */
else if (!(brush->flag & BRUSH_CURVE)) {
if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) {
if (!paint_calculate_rake_rotation(ups, brush, mouse_init, stroke->initial_mouse)) {
/* Not enough motion to define an angle. */
if (!stroke->rake_started) {
is_dry_run = true;
@ -1574,7 +1574,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
(br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
}
paint_calculate_rake_rotation(stroke->ups, br, mouse);
paint_calculate_rake_rotation(stroke->ups, br, mouse, stroke->initial_mouse);
}
}
else if (first_modal ||

View File

@ -10720,13 +10720,34 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
add_v3_v3(cache->grab_delta, delta);
}
else if (sculpt_needs_delta_for_tip_orientation(brush)) {
if (brush->flag & BRUSH_ANCHORED) {
if (brush->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT)) {
float orig[3];
mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
sub_v3_v3v3(cache->grab_delta, grab_location, orig);
}
else {
sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
if (SCULPT_get_int(ss, use_smoothed_rake, NULL, brush)) {
float tmp1[3];
float tmp2[3];
sub_v3_v3v3(tmp1, grab_location, cache->old_grab_location);
copy_v3_v3(tmp2, ss->cache->grab_delta);
normalize_v3(tmp1);
normalize_v3(tmp2);
bool bad = len_v3v3(grab_location, cache->old_grab_location) < 0.0001f;
bad = bad || saacos(dot_v3v3(tmp1, tmp2) > 0.35f);
float t = bad ? 0.1f : 0.5f;
sub_v3_v3v3(tmp1, grab_location, cache->old_grab_location);
interp_v3_v3v3(cache->grab_delta, cache->grab_delta, tmp1, t);
}
else {
sub_v3_v3v3(ss->cache->grab_delta, grab_location, cache->old_grab_location);
}
// cache->grab_delta
}
invert_m4_m4(imat, ob->obmat);
mul_mat3_m4_v3(imat, cache->grab_delta);