# How can I find the tangent and normal at an interpolated point on a Catmull-Rom/Hermite spline?

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. 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.

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.

You can find some rudimentary source code here. • I noticed a downvote here so if there is any error please point it out and I will correct it.
– ssb
Jun 21 '14 at 5:17
• How did you calculate m0 and m1 for random number of points? Oct 9 '15 at 9:51
• Nevermind, I found your github account and read your code. Awesome job :D Oct 9 '15 at 10:32
• 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/… Nov 20 '18 at 11:19