6
\$\begingroup\$

I have an implementation of a simple Catmull-Rom spline. It works, but I'm trying my hardest to be able to place vertices at extrusions along the curve. For this I need the normal (and tangent in the process) to be able to find the correct locations off of the curve. I cannot find any information anywhere, at least nothing that I can understand, on how to quickly calculate the tangent for a given t value on the curve. I've tried to do the derivative myself but I quickly realized I had no idea what I was doing.

How can I find the derivative/tangent/normal for a point at a t value on a Catmull-Rom spline?

Just to be extra clear, here is an incredibly rough picture of what I need.

enter image description here

I need to sample a point at a location along the curve and find an orthogonal vector, represented here by the blue lines. At the end of the blue lines I will place vertices. I have a working implementation of this already but it is for a bezier curve.

\$\endgroup\$
6
\$\begingroup\$

OK, I continued fiddling with it and I went ahead and just tried to do the math.

This is the equation I am using for the interpolation between two points:

(2t³ - 3t² + 1) * p0 + (t³ - 2t² + t) * m0 + (-2t³ + 3t²) * p1 + (t³ - t²) * m1

p0 and p1 are the control points and m0 and m1 are their respective tangents calculated elsewhere.

Previously I said I had no idea what I was doing with the math, but that was only because the derivative route felt too easy, so I figured I must have been doing something wrong. I went ahead and tried it and implemented it anyway. This is the formula that results:

p'(t) = (6t² - 6t)p0 + (3t² - 4t + 1)m0 + (-6t² + 6t)p1 + (3t² - 2t)m1

And wouldn't you know it works! Using this will give you the tangent vector at any interpolated t value on the curve.

From here the conversion to a normal is simple. In my case I'm in 3D and I don't need any special rotation, so I just have to do Vector3.Cross(Vector3.up, tangent), and that gives a vector in a direction orthogonal to the curve on the x/z plane (in Unity).

Here's a visual to show what I was trying to achieve:

enter image description here

\$\endgroup\$
  • \$\begingroup\$ I noticed a downvote here so if there is any error please point it out and I will correct it. \$\endgroup\$ – ssb Jun 21 '14 at 5:17
  • 1
    \$\begingroup\$ How did you calculate m0 and m1 for random number of points? \$\endgroup\$ – Virgiliu Oct 9 '15 at 9:51
  • \$\begingroup\$ Nevermind, I found your github account and read your code. Awesome job :D \$\endgroup\$ – Virgiliu Oct 9 '15 at 10:32
  • \$\begingroup\$ In the future you could estimate the length of the whole piecewise curve so you can take equidistant steps (look how the right side seems to have more samples than the left side). Like in here: stackoverflow.com/questions/29438398/… \$\endgroup\$ – R. Navega Nov 20 '18 at 11:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.