Finding the rotation of a point on a curve

Here’s the situation:

I want to create a part that, upon request, updates it’s position and rotation given a point on a curve, for the purpose of simulating a roller coaster.

The position is the easy part - I’ve written a NURBs module to create the curve and return a Vector3 position for U (along with other curve parameters), where U is the scale parameter, ranging from 0-1 (start and end, respectively).

The problem is the rotation - I’ve used a “best guess” by the, lookAt) method, but it starts to behave a little weird when I attempt to invert the curve.


The Hinge surface is set to Front, so all the grey bricks are facing the right direction, however as they become steeper than 90 degrees, they flip to face the wrong way.

I don’t exactly have a great understanding of calculus but I get the sense if I could calculate the tangent of the curve at position U, I might be able to construct a rotation vector from there??

Any help on this would be very much appreciated.

local rotation = {}

function rotation.calc(p0, p1)
	local targCF = p0.CFrame:Lerp(p1.CFrame, 0.5)	--Move to the middle of the two points
	local face =, p1.Position)	--Rotate to face toward the next point
	p0.CFrame = face

return rotation

This is because, lookAt) wouldn’t make sense if it wasn’t for the default 3rd parameter, which is a Vector3 indicating the desired up direction. It would be under constrained if it wasn’t there. You can overwrite the default (the world Y axis) by passing any Vector3 as a 3rd parameter. This explains the behavior you see in the picture: gives you the result out of all the infinite possibilities that is closest to having it’s Y axis point towards the world Y axis, i.e. up, so instead of getting upside-down parts you get upside-up parts which isn’t what you want when trying to preserver continuity along the curve.

Anyway, you need two vectors to uniquely define a rotation in 3D. uses the front and up vectors, so those a most convenient. If you have 2 direction vectors you can get the 3rd by taking their cross product. Like you said, the tangent of the curve at any point would be the lookvector on that point. The upvector would be the normal of the curve. I’m having a hard time googling for results for how to do this, but here’s a python library that seems to be able to do it: It’s open source so you can maybe check out how they do it: