# Tangent to a cardinal cubic curve

## Recommended Posts

Sevans    204
Hi I am trying to compute the direction that an object traveling along a curve should be facing. The curve is defined in 3D using a set of control points and 20 points in between each control point are interpolated. For ease of description i'll call the object traveling a ship, and its curve a path. For now I am simply trying to rotate around the "ships" local y access to have it "turn" I have something like ship.angle = ATan((cp2.y - cp1.y)) / (cp2.x - cp1.x)) //ATan is inverse tan which would work in 2D but we are in 3D so I have: Vector3 slopes = {cp2.x-cp1.x, cp2.y-cp1.y, cp2.z-cp1.z}; ship.angle = acos( dot(slopes, {1,0,0}) / length(slopes)*length({1,0,0}) ); I believe (I very well may be wrong) that this gives me the angle between the Z axis origined at cp1 (represented by the vector {1,0,0}) and the point cp2 (which is in terms of its relative position to cp1). Where dot() is the dot product of the two parameters. This does not seem correct. Everything goes great as long as all control points are in the same y plane. When I start shifting up and down y I get some ugly behavior. The "ship" starts to jerk rather than turn smoothly around "sharp" turns that turn in the xzplane as they move up and down in the y plane (think of going down curved road on a steep hill). The ship faces the close to the same direction for most of its journey down the "hill" and at the bottom suddenly decides to do all of its turning. I really do not know if this would be considered "normal" behavior. I also was wondering, would I have to use the projection of the vector slopes onto the xz plane rather than the vector {1,0,0} to make this work? Any ideas, suggestions, comments, links would be greatly appreciated. -sevans

##### Share on other sites
Alrecenk    400
I've probably misunderstood the problem, but there aren't any replies yet so here are my two cents anyway.

It would take atleast 2 angles to represent an orientation in 3D. The angle you have:
ship.angle = acos( dot(slopes, {1,0,0}) / length(slopes) );
Is the angle between the vector and the X axis . Notice I removed the length({1,0,0}) because it's a unit vector and it's length is 1 so it's not necessarry to divide by it. The easiest angles to use imo would be the angle you were using in 2D(maybe use atan2 so it's not a reference angle) and then the angle between the xy plane and the vector:

angle2 = acos(dot(V,{Vx,Vy,0})/(length(V)*length({Vx,Vy,0})) ;

Note that this is also a reference angle and therefore will always be positive. You can throw in an if somewhere to make it not a reference angle.

If you are using these angles to form a matrix then I would suggest not using angles and instead using the tangent, normal and binormal vectors to form the matrix(not sure if you can use them directly or if you would need to invert the matrix, it's been a while since I've done this). Since cubic curves are generally defined via polynomials it should be a trivial task to differentiate and and get the tangent etc. This might be harder actually, but if your like me (and don't believe in using angles) then it could be the way to go.

Though either way I would suggest using the actual tangent equation(derivative of the position equation) rather than using a secent vector(the slope from 2 sample points). It will be much smoother.

##### Share on other sites
erissian    727
Say your ship is at interpolated point Pn. Have your considering making the facing vector Pn+1-Pn-1 normalized?

##### Share on other sites
Alrecenk    400
If you just need a facing vector and your position equations are something like At^3+Bt^2+Ct+D then the tangent is just the derivative 3At^2+2Bt+C where A,B,C, and D are vectors.