Fix: GPv3: Outline perimeter cap radius too small when points are not coplanar
Stroke outlines are used by modifiers, fill tool, exporters, etc. When the input strokes are not co-planar (different depths from camera view) the end caps have smaller radii than they should have. When generating the outline caps the normal vector is created from the point tangents in 2D (after projection). When points have different depths (Z positions) the tangents have a non-zero Z component as well and discarding it leaves them unnormalized, thereby scaling the radius by an unwanted factor. Normalizing the vector fixes the issue. Object scale is now also taken into account. Pull Request: https://projects.blender.org/blender/blender/pulls/126687
This commit is contained in:
@@ -494,7 +494,7 @@ static void generate_cap(const float3 &point,
|
||||
Vector<float3> &r_perimeter,
|
||||
Vector<int> &r_src_indices)
|
||||
{
|
||||
const float3 normal = {tangent.y, -tangent.x, 0.0f};
|
||||
const float3 normal = math::normalize(float3{tangent.y, -tangent.x, 0.0f});
|
||||
switch (cap_type) {
|
||||
case GP_STROKE_CAP_ROUND:
|
||||
generate_arc_from_point_to_point(point - normal * radius,
|
||||
@@ -564,7 +564,7 @@ static void generate_corner(const float3 &pt_a,
|
||||
}
|
||||
|
||||
static void generate_stroke_perimeter(const Span<float3> all_positions,
|
||||
const VArray<float> all_radii,
|
||||
const Span<float> all_radii,
|
||||
const IndexRange points,
|
||||
const int corner_subdivisions,
|
||||
const bool is_cyclic,
|
||||
@@ -701,13 +701,20 @@ bke::CurvesGeometry create_curves_outline(const bke::greasepencil::Drawing &draw
|
||||
const VArray<int> src_material_index = *src_attributes.lookup_or_default(
|
||||
"material_index", bke::AttrDomain::Curve, 0);
|
||||
|
||||
/* Transform positions. */
|
||||
/* Transform positions and radii. */
|
||||
const float scale = math::average(math::to_scale(transform));
|
||||
Array<float3> transformed_positions(src_positions.size());
|
||||
Array<float> transformed_radii(src_radii.size());
|
||||
threading::parallel_for(transformed_positions.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
transformed_positions[i] = math::transform_point(transform, src_positions[i]);
|
||||
}
|
||||
});
|
||||
threading::parallel_for(transformed_radii.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
transformed_radii[i] = src_radii[i] * scale;
|
||||
}
|
||||
});
|
||||
|
||||
const float4x4 transform_inv = math::invert(transform);
|
||||
threading::EnumerableThreadSpecific<PerimeterData> thread_data;
|
||||
@@ -725,7 +732,7 @@ bke::CurvesGeometry create_curves_outline(const bke::greasepencil::Drawing &draw
|
||||
const IndexRange points = src_curves.points_by_curve()[curve_i];
|
||||
|
||||
generate_stroke_perimeter(transformed_positions,
|
||||
src_radii,
|
||||
transformed_radii,
|
||||
points,
|
||||
corner_subdivisions,
|
||||
is_cyclic_curve,
|
||||
|
||||
Reference in New Issue
Block a user