PDA

View Full Version : how to orientate a vector to point towards a point



dodgyposse
09-07-2000, 05:21 AM
Ok:

I have a 3d mesh, centred about a point A.
The object has a point B within the mesh which denotes its front. Therefore the vector AB is its facing direction.

I want to be able to determine the angles of rotation to be applied to the mesh, to orientate it , so it faces a point Z.

I've tried to do the maths a few times, but I'm old ( school was 13 years ago! ), and my maths ain't what it was.

help!

dd

steveo
09-07-2000, 10:14 AM
This is harder than what you did at school! If you know vector maths then AB is the front vector and AZ is the vector where you want to point. The angle between AB and AZ is

inverse cosine of AB.AZ/(|AB| |AZ|)

AB.AZ is the dot product of vector AB and AZ
|AB| is the magnitude of AB etc.

To rotate the mesh through this angle we need to find a vector perpendicular to the plane containing A, B and Z. The vector is
the cross product of AB and AZ (AZxAB) call this vector V.

We now rotate AB through the required angle around vector V.

A bit of code to do that is:

void Vector_Rv(float* V,float *AB,float angle)
{
int i;
float B[3],C[3],d;
float x=cos(angle), y=sin(angle);
d=Vector_Dot(V,AB);
for(i=0;i<3;i++)
B[i]=V[i]-d*AB[i];
Vector_Cross(AB,B,C);
for(i=0;i<3;i++)
V[i]+=C[i]*y-B[i]*(1-x)/2;
}

and code for the dot product and cross product functions are:

float Vector_Dot(float *AB,float *AZ)
{
return AB[0]*AZ[0]+AB[1]*AZ[1]+AB[2]*AZ[2];
}


void Vector_Cross(float *AB,float *AZ,float *V)
{
V[0]=AB[1]*AZ[2]-AB[2]*AZ[1];
V[1]=AB[2]*AZ[0]-AB[0]*AZ[2];
V[2]=AB[0]*AZ[1]-AB[1]*AZ[0];
}


in these functions the vectors are represented as three floats.

Troubleshooting -- cross products are handed depending on the order of the vectors (AxB!=BxA) , so rotatiion may go the wrong way, reverse order of vectors for the other way.

Hope this helps -- and it works?!

Steve

Aster
09-07-2000, 10:46 AM
Hi, I hope this will answer your qestion.

The vector AB is the facing direction of the mesh, so, if you want it to point to Z, the vector AZ becomes its new facing direction.

To find the rotation angles for the transformation, you have to normalize vector AZ, e.i., reduce it to a length of 1. First, you have to find its length. If its components are

(x, y, z),

then its length is

l = sqrt(x^2 + y^2 + z^2),

and the normalized vector is

AZ/l = (x/l, y/l, z/l).

In fact, the components of this normalized vector are the cosines of the angles between the vector AZ and the axes Ox, Oy and Oz,

AZ/l = (x/l, y/l, z/l) = (cos[A], cos[B], cos[C]),

where A, B and C are the angles between vector AZ and axes Ox, Oy and Oz respectively.
They are called the direction cosines, but they aren't cosines of the rotation angles you need. You need to find the rotations ABOUT the axes. To get them, find the projections of the normalized vector AZ onto onto the planes xOy, yOz and zOx. The projection onto the xOy plane would be

a = (cos[A], cos[B], 0) = (x/l, y/l, 0);

onto yOz plane -

b = (0, cos[B], cos[C]) = (0, y/l, z/l),

and onto zOx plane -

c = (cos[A], 0, cos[C]) = (x/l, 0, z/l).

Now, if you know how to find a dot product of 2 vectors given their components, find the dot products of the vector AZ/l with vectors a, b and c. You should also know how to find the dot product beween two vectors given their lengths. First, find the lengths of all 3 vectors a, b and c,

|a|=sqrt(x^2, y^2, z^2),

the same for vectors b and c (x, y, and z are the components of each vector, of course).

You already know the length of the AZ/l vector; it is 1 (you normalized it). Now, the dot product of two vectors is equal to the product of their lengths times the cosine of the angle between them,

(AZ/l)*a = 1*|a|*cos(angle between vector AZ/l and vector a - what you need - angle of rotation about Oz axis)

Now, using the dot product of two vectors found from their components, you can find the angle of rotation about Oz axis (since you are using vector a which is the projection of vector AZ/l onto the xOy plane).

cos(rotation angle about Oz axis) = (AZ/l)*a/|a|

(you don't have to divide by 1)

Sorry, I'm not sure how to find the dot product of two vectors given their components (forgotten), but I hope you can find that yourself. I'll post another message when I remember how to do that.

09-07-2000, 11:13 AM
from steveo(above)

float Vector_Dot(float *AB,float *AZ)
{
return AB[0]*AZ[0]+AB[1]*AZ[1]+AB[2]*AZ[2];
}

Aster
09-08-2000, 07:18 PM
Sorry for all that mess with vector narmalization and direction cosines, you don't need to do any of that stuff. Just find the dot product of 2 vectors using their components, then write it again using their magnitudes and cosine of the angle between them. The inverted cosine is what you need - the angle of rotation.