Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurynas Duburas <laurynas>2022-01-22 01:40:49 +0300
committerHans Goudey <h.goudey@me.com>2022-01-22 01:40:49 +0300
commit45d038181ae25972011f9656ba4f7062aa1c534f (patch)
tree47dc5b9f30ceae95623c5172b43a2916146ce06b /source/blender/blenkernel/intern/spline_nurbs.cc
parentd590e223daf6e20d462f2b197d32606d69873051 (diff)
Curves: Improve accuracy and clarity of NURBS knots calculation
This commit improves NURBS knot generation by adding proper support for the combination of the Bezier and cyclic options. In other cases the resulting knot doesn't change. This cyclic Bezier knot is used to create accurate accurate "Nurbs Circle", "Nurbs Cylinder" primitives. "Nurbs Sphere" and "Nurbs Torus" primitives are also improved by tweaking the spin operator. The knot vector in 3rd order NURBS curve with Bezier option turned on (without cyclic) is changed in comparison to previous calculations, although it doesn't change the curve shape itself. The accuracy of the of NURBS circle is fixed, which can be checked by comparing with mesh circle. Tessellation spacing differences in circular NURBS is also fixed, which is observable with the NURBS cylinder and sphere primitives. These were causing seam-like effects. This commit contains comments from Piotr Makal (@pmakal). Differential Revision: https://developer.blender.org/D11664
Diffstat (limited to 'source/blender/blenkernel/intern/spline_nurbs.cc')
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc72
1 files changed, 21 insertions, 51 deletions
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index 719ba4b7ecd..5993b9a9a27 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -179,65 +179,35 @@ int NURBSpline::knots_size() const
void NURBSpline::calculate_knots() const
{
const KnotsMode mode = this->knots_mode;
- const int length = this->size();
const int order = order_;
+ const bool is_bezier = mode == NURBSpline::KnotsMode::Bezier;
+ const bool is_end_point = mode == NURBSpline::KnotsMode::EndPoint;
+ /* Inner knots are always repeated once except on Bezier case. */
+ const int repeat_inner = is_bezier ? order - 1 : 1;
+ /* How many times to repeat 0.0 at the beginning of knot. */
+ const int head = is_end_point && !is_cyclic_ ? order : (is_bezier ? order / 2 : 1);
+ /* Number of knots replicating widths of the starting knots.
+ * Covers both Cyclic and EndPoint cases. */
+ const int tail = is_cyclic_ ? 2 * order - 1 : (is_end_point ? order : 0);
knots_.resize(this->knots_size());
-
MutableSpan<float> knots = knots_;
- if (mode == NURBSpline::KnotsMode::Normal || is_cyclic_) {
- for (const int i : knots.index_range()) {
- knots[i] = static_cast<float>(i);
- }
- }
- else if (mode == NURBSpline::KnotsMode::EndPoint) {
- float k = 0.0f;
- for (const int i : IndexRange(1, knots.size())) {
- knots[i - 1] = k;
- if (i >= order && i <= length) {
- k += 1.0f;
- }
- }
- }
- else if (mode == NURBSpline::KnotsMode::Bezier) {
- BLI_assert(ELEM(order, 3, 4));
- if (order == 3) {
- float k = 0.6f;
- for (const int i : knots.index_range()) {
- if (i >= order && i <= length) {
- k += 0.5f;
- }
- knots[i] = std::floor(k);
- }
- }
- else {
- float k = 0.34f;
- for (const int i : knots.index_range()) {
- knots[i] = std::floor(k);
- k += 1.0f / 3.0f;
- }
- }
- }
+ int r = head;
+ float current = 0.0f;
- if (is_cyclic_) {
- const int b = length + order - 1;
- if (order > 2) {
- for (const int i : IndexRange(1, order - 2)) {
- if (knots[b] != knots[b - i]) {
- if (i == order - 1) {
- knots[length + order - 2] += 1.0f;
- break;
- }
- }
- }
+ for (const int i : IndexRange(knots.size() - tail)) {
+ knots[i] = current;
+ r--;
+ if (r == 0) {
+ current += 1.0;
+ r = repeat_inner;
}
+ }
- int c = order;
- for (int i = b; i < this->knots_size(); i++) {
- knots[i] = knots[i - 1] + (knots[c] - knots[c - 1]);
- c--;
- }
+ const int tail_index = knots.size() - tail;
+ for (const int i : IndexRange(tail)) {
+ knots[tail_index + i] = current + (knots[i] - knots[0]);
}
}