Fix: GPv3: Draw Tool: First point too large when using angle factor

The first point was always set to the brush radius, even when the
angle setting was used. Additionally, the approximation for the
pen direction started at (0, 0).

This fixes the issue by overwriting the radius of the first point
once we get the first extension sample and with that the first
approximation of the pen direction.
The pen direction is also set to the initial direction from the
first to the second point.
This commit is contained in:
Falk David
2024-06-26 13:50:54 +02:00
parent e9291548d3
commit 2c773ce857

View File

@@ -733,18 +733,25 @@ struct PaintOperationExecutor {
const int last_active_point = curve_points.last();
const float2 prev_coords = self.screen_space_coords_orig_.last();
const float prev_radius = drawing_->radii()[last_active_point];
float prev_radius = drawing_->radii()[last_active_point];
const float prev_opacity = drawing_->opacities()[last_active_point];
const ColorGeometry4f prev_vertex_color = drawing_->vertex_colors()[last_active_point];
/* Use the vector from the previous to the next point and then interpolate it with the previous
* direction to get a smoothed value over time. */
self.smoothed_pen_direction_ = math::interpolate(
self.smoothed_pen_direction_, coords - self.screen_space_coords_orig_.last(), 0.1f);
const bool is_first_sample = (curve_points.size() == 1);
const float distance_px = math::distance(coords, prev_coords);
/* Use the vector from the previous to the next point. Set the direction based on the first two
* samples. For subsuquent samples, interpolate with the previous direction to get a smoothed
* value over time. */
if (is_first_sample) {
self.smoothed_pen_direction_ = self.screen_space_coords_orig_.last() - coords;
}
else {
self.smoothed_pen_direction_ = math::interpolate(
self.smoothed_pen_direction_, self.screen_space_coords_orig_.last() - coords, 0.1f);
}
/* Approximate brush with non-circular shape by changing the radius based on the angle. */
float radius_factor = 1.0f;
if (settings_->draw_angle_factor > 0.0f) {
const float angle = settings_->draw_angle;
const float2 angle_vec = float2(math::cos(angle), math::sin(angle));
@@ -754,15 +761,13 @@ struct PaintOperationExecutor {
1.0f - math::abs(math::dot(angle_vec, math::normalize(self.smoothed_pen_direction_)));
/* Influence is controlled by `draw_angle_factor`. */
const float radius_factor = math::interpolate(
1.0f, angle_factor, settings_->draw_angle_factor);
radius_factor = math::interpolate(1.0f, angle_factor, settings_->draw_angle_factor);
radius *= radius_factor;
}
/* Overwrite last point if it's very close. */
const bool is_first_sample = (curve_points.size() == 1);
const float distance_px = math::distance(coords, prev_coords);
constexpr float point_override_threshold_px = 2.0f;
if (distance_px < point_override_threshold_px) {
self.accum_distance_ += distance_px;
/* Don't move the first point of the stroke. */
@@ -781,6 +786,12 @@ struct PaintOperationExecutor {
return;
}
/* Adjust the first points radius based on the computed angle. */
if (is_first_sample && settings_->draw_angle_factor > 0.0f) {
drawing_->radii_for_write()[last_active_point] *= radius_factor;
prev_radius = drawing_->radii()[last_active_point];
}
/* Clamp the number of points within a pixel in screen space. */
constexpr int max_points_per_pixel = 4;
/* The value `brush_->spacing` is a percentage of the brush radius in pixels. */