Fix T102537: Curve subdivide mishandles single point curves
Also, single point cyclic Catmull Rom curves aren't evaluated properly. Cyclic is meant to make no difference in that case. Now they correctly evaluate to a single point.
This commit is contained in:
parent
4401c93e45
commit
f7e0317b96
Notes:
blender-bot
2023-02-14 06:23:08 +01:00
Referenced by issue #100749, Blender LTS: Maintenance Task 3.3 Referenced by issue #102537, GN: Undefined behavior for subdivided cyclical single-point Catmull-Rom splines
|
@ -12,8 +12,12 @@ namespace blender::bke::curves::catmull_rom {
|
|||
int calculate_evaluated_num(const int points_num, const bool cyclic, const int resolution)
|
||||
{
|
||||
const int eval_num = resolution * segments_num(points_num, cyclic);
|
||||
if (cyclic) {
|
||||
/* Make sure there is a single evaluated point for the single-point curve case. */
|
||||
return std::max(eval_num, 1);
|
||||
}
|
||||
/* If the curve isn't cyclic, one last point is added to the final point. */
|
||||
return cyclic ? eval_num : eval_num + 1;
|
||||
return eval_num + 1;
|
||||
}
|
||||
|
||||
/* Adapted from Cycles #catmull_rom_basis_eval function. */
|
||||
|
|
|
@ -37,16 +37,21 @@ static void calculate_result_offsets(const bke::CurvesGeometry &src_curves,
|
|||
const IndexRange src_segments = curve_dst_offsets(src_points, curve_i);
|
||||
|
||||
MutableSpan<int> point_offsets = dst_point_offsets.slice(src_segments);
|
||||
|
||||
MutableSpan<int> point_counts = point_offsets.drop_back(1);
|
||||
cuts.materialize_compressed(src_points, point_counts);
|
||||
for (int &count : point_counts) {
|
||||
/* Make sure the number of cuts is greater than zero and add one for the existing point. */
|
||||
count = std::max(count, 0) + 1;
|
||||
|
||||
if (src_points.size() == 1) {
|
||||
point_counts.first() = 1;
|
||||
}
|
||||
if (!cyclic[curve_i]) {
|
||||
/* The last point only has a segment to be subdivided if the curve isn't cyclic. */
|
||||
point_counts.last() = 1;
|
||||
else {
|
||||
cuts.materialize_compressed(src_points, point_counts);
|
||||
for (int &count : point_counts) {
|
||||
/* Make sure there at least one cut, and add one for the existing point. */
|
||||
count = std::max(count, 0) + 1;
|
||||
}
|
||||
if (!cyclic[curve_i]) {
|
||||
/* The last point only has a segment to be subdivided if the curve isn't cyclic. */
|
||||
point_counts.last() = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bke::curves::accumulate_counts_to_offsets(point_offsets);
|
||||
|
|
Loading…
Reference in New Issue