Page MenuHome

Fix (unreported): incorrect weights and radii interpolation when subdividing curves
Needs ReviewPublic

Authored by Matteo Falduto (matteolegna) on May 23 2021, 4:20 AM.
Tokens
"Like" token, awarded by EAW."Love" token, awarded by Fracture128."Yellow Medal" token, awarded by lone_noel."Like" token, awarded by campbellbarton."Like" token, awarded by RedMser.

Details

Summary

I've encountered a few issues with how the weight and radius parameters are calculated for new vertices created by subdividing curves.

  1. In the case of splines, all the newly generated vertices assume the very same values as radii and weights, instead of smoothly interpolating them along the curve to preserve its original appearance.

  1. In the case of polylines (and NURBS), the values for the radii are interpolated, but in the wrong order. Weights are not interpolated at all.


This patch fixes all the above-mentioned issues.

Diff Detail

Repository
rB Blender
Branch
FIX_curve_subdivide_radius (branched from master)
Build Status
Buildable 14718
Build 14718: arc lint + arc unit

Event Timeline

Matteo Falduto (matteolegna) requested review of this revision.May 23 2021, 4:20 AM
Matteo Falduto (matteolegna) created this revision.
Campbell Barton (campbellbarton) requested changes to this revision.May 25 2021, 7:28 AM
Campbell Barton (campbellbarton) added inline comments.
source/blender/editors/curve/editcurve.c
3490–3491

Multiplying a very small value by an integer can cause floating-point imprecision.

Even though it's unlikely to cause any problems in this particular case, as a rule of thumb I would rather avoid doing this entirely and use interpf here as is done elsewhere.

This revision now requires changes to proceed.May 25 2021, 7:28 AM
  • using interpf to interpolate weights and radii in the case of splines.
Matteo Falduto (matteolegna) marked an inline comment as done.May 25 2021, 6:34 PM

@Campbell Barton (campbellbarton) I've uploaded a diff using interpf instead of the manual interpolation formula used previously. As I noted in replying to your code comment, this required introducing a new, different factor parameter I've called factor_linear. You can choose the version you find leaner and more fitting the code style.
Thanks!

source/blender/editors/curve/editcurve.c
3490–3491

Thank you for the feedback.
One of the reasons I didn't use interpf here is that, in order to produce the correct result, in this case, it would require introducing a new, different factor parameter than the one used elsewhere in the block. It would look something like this:

float factor_linear;
for (int i = 0; i < number_cuts; i++) {
  factor = 1.0f / (number_cuts + 1 - i);
  factor_linear = (float)(i+1) / (number_cuts + 1);
  [...]
  beztn->radius = interpf(nextbezt->radius, bezt->radius, factor_linear);
  beztn->weight = interpf(nextbezt->weight, bezt->weight, factor_linear);
  [...]
}

I thought that would have looked not very neat and somehow less efficient. But I can surely do it if you find it more fitting.

Matteo Falduto (matteolegna) marked an inline comment as done.
  • Cleanup: removing unnecessary factor_linear

...Okay, actually never mind 😐
Ignore my previous comment: I didn't put enough effort into understanding the surrounding code and I didn't see that it was unnecessary to introduce that factor_linear.
In the last diff I got rid of it, harmonizing the logic of that two lines with the rest of the algorithm.

[EDIT] I only don't like too much the fact that, unlike my earlier code, this uses, at each iteration, the result of the previous interpolation as an input to interpolate the remaining vertices down the line, accumulating any possible precision errors...
Could you please compare the various Diffs and tell me which approach you think is the most suitable?
The difference is that my first two attempts used to interpolate all of the newly created vertices always using the preexisting vertices as interpolation interval, while Diff 3, in order to work with the available factor parameter, uses as interval the ever-shrinking span between the lastly created vertex and the final preexisting vertex.

@Campbell Barton (campbellbarton) I've uploaded a diff using interpf instead of the manual interpolation formula used previously. As I noted in replying to your code comment, this required introducing a new, different factor parameter I've called factor_linear. You can choose the version you find leaner and more fitting the code style.
Thanks!

I don't see what's necessary to use the previous interpolated result. Shouldn't this be an interpretation between the 2 end points? (the point that existed before the subdivided points or added)