Saturday, February 9, 2013

NURBS Curves: How to use Knot Vectors

When working in Maya, we create curves freely without crunching numbers. We use them in Maya Hair, Spline IK rigs, Motion/Flow paths, as control curves for characters rigs, create them procedurally for modeling, amongst other uses. My goal in this post is for you to better understand how to generate curves using knot vectors.

Linear curves are simply lines that follow the standard y = mx + b formula. In Maya, they are created as a curve of 1 degree. That means that the highest power in the equation is 1. In theory, this curve type has 2 knots. The relation between knots to CV is: #knots = (#CVs+deg -1).

string $curve = `curve -d 1 -p -2 0 0 -p 2 0 -2`;

Simply pass in your two points, and tell Maya that you’re drawing a linear curve. Let’s attach a curveInfo node to this curve and poke around a little bit.

string $cInfo = `arclen -ch 1 $curve`;

// Result: 0 1 //

It seems that there are two knots on this curve that are weighted to each CV on the curve. Using #knots = (#CVs+deg -1), we know that we have 2 CVs on a curve of 1 degree, minus 1: that’s 2 knots. So we know that checks out.

Before we investigate further, let’s try the same thing with a quadratic curve. Behind the scenes, Maya will draw the smooth curve using an equation where the highest degree order is 2. Since we all miss our high school math classes, let’s draw a parabola:

$curve = `curve -d 2 -p -1 0 -2 -p -1 0 0 -p 1 0 0 -p 1 0 -2`;
$cInfo = `arclen -ch 1 $curve`;

// Result: 0 0 1 2 2 //

We have a curve of 2 degrees, we plotted 4 points, minus 1: that’s a total of 5 knots. The collection of knots on a curve is referred to its Knot Vector. However, what do these knot magnitudes mean? Each element in the vector determines where in parameter space the curve will be drawn. I know that’s a very vague statement but please stay with me!

Think of the first and last points on a curve as an anchor. This is the most common type of knot vector: Pinned Uniform Knot Vectors. Each anchor needs to be held down by the same number of knots as the curve’s degree. In our first example, we had a curve of 1 degree being pinned down by one knot on each end point. In our second example, we had a curve being held down by 2 knots on each end point.

So then what does the 1 mean in the [0 0 1 2 2] result? It turns out that these numbers are arbitrary. The number values don’t matter in a Knot Vector. Say what? Yes, that’s right. What matters is the ratios of the values to each other. The main rule is that Maya requires each knot’s magnitude to be in ascending order. So what happens if we create a curve but mess with that middle knot? What results will we get? Let’s try it!
curve -d 2 -p -1 0 -2 -p -1 0 0 -p 1 0 0 -p 1 0 –2
      -k 0 -k 0 -k 0 -k 2 -k 2;
By specifying the knot values to the curve command, it seems we have created a curve with non-uniform weighting. We modified the middle knot in a way that we made the curve appear discontinuous.

Just for fun, we can weight the center knot to the other end to get a mirrored result.
curve -d 2 -p -1 0 -2 -p -1 0 0 -p 1 0 0 -p 1 0 –2
-k 0 -k 0 -k 2 -k 2 -k 2;
Go ahead and release the pins on this 2nd degree curve. Notice that you can easily un-anchor the curve from their start and end points by simply supplying different weights. This also makes your curve a lot shorter. This is something you need to try for yourself because it’s one of those things that are too abstract in words.

Uniformly distributing our knots makes our NURBS curve simply a B-Spline. Having the ability to specify and interactively adjust the knots is a feature of NURBS, or Non-Uniform Rational B-Splines. Allowing a partial knot weight is a nice feature:
curve -d 2 -p -1 0 -2 -p -1 0 0 -p 1 0 0 -p 1 0 –2
      -k 0 -k 0 -k 1.5 -k 2 -k 2;
curve -d 2 -p -1 0 -2 -p -1 0 0 -p 1 0 0 -p 1 0 –2
      -k 0 -k 0 -k 0.5 -k 2 -k 2;
Finally, to nail the point, let’s try drawing an pinned cubic curve with a degree of 3.
curve -d 3 -p -1 0 -3 -p -2 0 -2 -p 0 0 0 -p 2 0 -2 -p 1 0 –3
      -k 0 -k 0 -k 0 -k 1 -k 2 -k 2 -k 2;
Notice that I used 3 pinned knots to hold down the end points. The middle knot is exactly half way between 0 and 2. This makes the curve uniformly weighted. If you have questions, please let me know in the comment section! I’m sure there are things I can clarify. I want to be sure the information comes through clearly.

- Maya seems to ignore knot magnitudes on linear curves.
- When creating curves with the -pointWeight flag, accurate knot values are not returned.
- When editing curves created with the -pointWeight flag in the viewport, the curves seem to snap to a weighted value of 1 to each CV.

1 comment:

  1. Thanks for the post! Currently I'm a 3d animation student, but I'm still a big fan of math. So it's nice to be able to combine these two and understand what's going on in maya :)