Sign in to follow this  
Sevans

Rotation values from Tangent to Curve (Vector)

Recommended Posts

Hi, I have a vector, the tangent to a curve infact, and I would like to make something that is riding on the curve rotate to face in the direction of the vector (forward in relation to it traveling down the curve). How do I turn the vector into rotation values that I can pump into a rotation matrix? Thanks much! -sevans

Share this post


Link to post
Share on other sites
Assuming that the current facing (F) and the tangent (T) vectors are normalized, the angle between them is cos-1(F⋅T)

To get the angle between x,y,and z:
angle_x = acos(dot(T,X));
angle_y = acos(dot(T,Y));
angle_z = acos(dot(T,Z));

Where X=Vector(1,0,0), etc.

But simplifying that:
angle_x = acos(T.x);
angle_y = acos(T.y);
angle_z = acos(T.z);

Again, that's assuming T is normalized.

That's the jist of it anyways.

Share this post


Link to post
Share on other sites
Here is the basic c++ style psuedo code of what I am doing.
Please read the following and correct me if I am wrong:


// calculate the rotations needed to build rotation matricies
// somePlaceOnCurve is a point on the curve I am located at
calcRotations(){
Vector3 tanVec = curveFunction.derivitive.evalAt( somePlaceOnCurve );

// normalize the vector
normalize tanVec;

// use acos to find the angles, convert to degrees
double angleX = radiansToDegrees( acos( tanVec.v1 ) );
double angleY = radiansToDegrees( acos( tanVec.v2 ) );
double angleZ = radiansToDegrees( acos( tanVec.v3 ) );

// rotate!
// just do y for now
glRotated( angleY, 0,1,0 );
}

// T is a Vector3, the tangent vector from my last post
// normalize the Tangent vector
Vector3 normalize(Vector3 T){
// find length of the vector T
length = vectorLength(T);

T.x = T.x / length;
T.y = T.y / length;
T.z = T.z / length;

return T;
}

// find the length of the vector T
double vectorLength(Vector3 T){
GLdouble result = dot( T, T );
result = sqrt( result );
return result;
}

// find the dot product of the two vectors
double dot( Vector3 p1, Vector3 p2){
return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
}



Let me explain a little about my curve. For now it is an ellipse with all points on the same y plane. So an average point on the line is (X, 1, Z) for some X and Z.

With the rotation's algorithm shown above, angleY is always 90 degrees. Is there some other way that I should be interpreting these values that are in angleX, angleY, angleZ?

Thanks much!

-Sevans

Share this post


Link to post
Share on other sites
The way for incremental rotation would be a single vector to vector rotation step. It uses the now obsolete facing vector and rotates it to match the current tangent vector. Incremental rotation has the advantage not to suffer from abrupt mirroring when crossing poles (at least as long as the increments are small enough).

Computing the plane of rotation by determining the plane's (unit length) normal
n := t' x v'
where t' is the normalized tangent vector and v' is the normalized original vector, and the angle between these both vectors
arad := cos-1( t' . v' )
adeg := arad * 180 / pi
one can use the axis/angle pair to rotation matrix conversion, e.g. directly available in OpenGL by
glRotatef( a_deg, n.x, n.y, n.z )
or by computing the matrix self (I can post it if it is unknown).

Share this post


Link to post
Share on other sites
Rereading you question, you probably want to rotate around an arbitrary axis:

That axis being: F⊗T/|F⊗T|
The angle being cos-1(F⋅T/|F⋅T|)

Share this post


Link to post
Share on other sites
Quote:
Original post by erissian
Rereading you question, you probably want to rotate around an arbitrary axis:

That axis being: F⊗T/|F⊗T|
The angle being cos-1(F⋅T/|F⋅T|)


I take it that the dots are dot product
the circles with crosses are the cross product
and the || pipes are absolute value?

if the || pipes are length, where is that coming from?
the dot product returns a scalar.

Lastly, can anyone define the facing vector for me and leave a small example? I thought I knew what it is, but I am starting to think that may have been my problem all along.

Thanks again,

-sevans

[Edited by - Sevans on November 9, 2006 3:50:31 PM]

Share this post


Link to post
Share on other sites

Quote:
Original post by erissian
Rereading you question, you probably want to rotate around an arbitrary axis:

That axis being: F⊗T/|F⊗T|
The angle being cos-1(F⋅T/|F⋅T|)


I take it that the dots are dot product
the circles with crosses are the cross product
and the || pipes are absolute value?

if the || pipes are length, where is that coming from?
the dot product returns a scalar.

Also, can anyone define the facing vector for me and leave a small example? I thought I knew what it is, but I am starting to think that may have been my problem all along.

Lastly, I want to note that the method which haegarr posted worked beautifully when my curve has a constant y value, however if the curve moves up in y value, the object travels fine "up hill" (y axis being up) but then as it travels "down hill" it begins to rotate around the curve it is traveling on. and eventually flips all the way around befor hitting the end of the curve where the y levels back out. Anyone have any ideas on why this is? I'm going to keep at it but hints are appreciated!

Thanks again,

-sevans

Share this post


Link to post
Share on other sites
In a large font, ⊗ will look like an X surrounded by a circle. That's the cross product.
And you're right about the dot too. It's a dot product.

The use I describe comes from the two properties:
|(A/|A|)|=1
and
F⋅T = |F||T|cosΘ
therefore, F⋅T/|F||T| = cosΘ
leading to Θ=cos-1(F⋅T/|F||T|)

The first one being important in that if your axis has a length other than 1, then it will scale as well as rotate.

Share this post


Link to post
Share on other sites
Sorry about the double post, newbie mistake :(

Okay, well that helps, but what if I do not want rotation (for it to roll around the curve like it is)? is there a way that I can make my object rotate side to side to "turn" around curves and to "tilt" forward and backward on hills and slopes, without "leaning" to either side? How would I go about pulling that rotation out of this (the flip over)?

Something to note, the Z axis of the object lies on the curve it is following

Thanks again,

-sevans

Share this post


Link to post
Share on other sites
Quote:
Original post by Sevans
Okay, well that helps, but what if I do not want rotation (for it to roll around the curve like it is)? is there a way that I can make my object rotate side to side to "turn" around curves and to "tilt" forward and backward on hills and slopes, without "leaning" to either side?
You might be looking for a 'fixed reference frame'. In this case the reference vector would presumably be the world 'up' vector; the basis vectors of the object's local frame would then be computed as follows:

1. Forward = normalized curve tangent at t

2. Side = normalized cross product of forward and reference vector

3. Up = cross product of forward and side

I may have gotten the permutation wrong there (i.e. negative determinant), but I'm too lazy to go and back and check so I'll leave that to you :) In any case, with this method your object will follow the curve and 'pitch' along with it, but will never roll (what you're calling a 'lean').

The algorithm may fail if the path of the curve ever goes straight up or down, but if you know this will never happen, the fixed reference frame is probably a good choice.

Share this post


Link to post
Share on other sites
So once I have the:
1. Forward = normalized curve tangent at t
2. Side = normalized cross product of forward and reference vector
3. Up = cross product of forward and side

How do I build a rotation that I can pass to GL out of it?

-sevans

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this