Archived

This topic is now archived and is closed to further replies.

Dark_Streak

Advanced rotation - can you help?

Recommended Posts

I HAVE posted this question in the 'Maths and Physics' forum, but have got no response. Please help. I am trying to Rotate an object to 'look' towards a certain point, but Im failing miserably. All this maths is really frying my brain. Can anyone help me, perhaps see something Im doing wrong? I have a model, which is facing, say, North. There is another object, say a pole, that is slightly in front (to the North) and to the left of my model. Lets say that the pole is at a 25 degree angle from the model. Now, I want to be able to rotate the model so that it is looking at the pole. So basically it needs to rotate by 25 degrees (using glRotate). Now, the problem is that the model and the pole are not static, so this angle may be constantly changing. Therefore, I need to calculate this number of degrees every frame (or however often) and this is where I am getting my problem. The results I am getting seem to be random, large values, which dont represent the correct degrees at all. I wonder if I am calculating the two vectors incorrectly? When finding a vector, you subtract the source point from the destination point right? Here's my code:
    
// This is the function that is supposed to calculate the angle in degrees

double findAngle()
{	
CVector3 toPoleVec = Normalize( destPoint1 - sourcePoint1);
CVector3 toModelVec = Normalize( destPoint2 - sourcePoint2);
float dotProduct = Dot(toPoleVec, toModelVec);			
double Angle = acos(dotProduct);	
if(_isnan(Angle))
Angle = 0;
// To convert radians to degress use this equation:   radians * (PI / 180)	

double AngleInDeg = Angle * (PI / 180);return AngleInDeg;}
}
// Here I rotate the model, by calling my function to return the degree of rotation.

glRotated(findAng(),0,1,0);// Draw model etc..  

    
Any suggestions? [edited by - Dark_Streak on September 1, 2002 2:15:54 PM]

Share this post


Link to post
Share on other sites
Ok, I'm going to give this a shot. I'm not the most knowledgable mathmatician, but I've delt with this problem before, so I'll try to explain it

Lets say you have your model(M), your pole(P), and a point in a right trangle that is produced when you find the distance on the x and the distance on the z from your pole to your model.


  

-10
P-----------0 Z
\ | |
\ | |
\ | X-------|-------X
\ | |
\ | |
\ |25 |
\ | Z
\ |
\ |
\ |
\ |
\|
M


Now you have a right trianlge based on the distance on the x, and distance on the z. You can use the inverse tangent to find the angle between your model and your pole, like this..

(atan(DEGTORAD((-10/25)))) = -21.8;

21.8 Would be your angle

I hope that helped.






"With my feet upon the ground I lose myself between the sounds and open wide to suck it in, I feel it move across my skin. I'm reaching up and reaching out. I'm reaching for the random or what ever will bewilder me, what ever will bewilder me. And following our will and wind we may just go where no one's been. We'll ride the spiral to the end and may just go where no one's been." - Maynard James Keenan
[TheBlackJester ]
[Wildfire Studios ]

[edited by - TheBlackJester on September 1, 2002 3:24:28 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi-
Your problem shouldn''t be that difficult to solve. First, consider the vector along which the character is looking. Then, consider the vector between the character and the object. Take the dot product of these two vectors. We''ll call this resultant R. given that A.B = |A||B|cos(theta), divide R by the magnitudes of the other vectors. Take the inverse cosine, apply a little math to figure out if you are in the right quadrant, and you should have the correct angle.

Share this post


Link to post
Share on other sites
Ok, this is actually really quite simple.

You need to construct an orthonormal frame to transform the model by.

Since you want the object to face a point, the "front" vector of this frame will be from the position of the object to the point. So:

front = point - object_position;


You then use an arbitary "up" vector to find the side vector, so let up equal [0, 1, 0] or something, and calculate the side vector using the cross product:

side = up x front;


You would then recalculate the up vector, so that the frame is actually orthonormal:

up = front x side


Using these vectors, plus the position vector of the object ( T ), you build a transformation matrix like so:

[Sx,Ux,Fx,Tx]
[Sy,Uy,Fy,Ty]
[Sz,Uz,Fz,Tz]
[0,0,0,1]

You would then multiply the object by this matrix, and bingo, the model will always face this point. It''s simply an extension of billboarding.

To make it even easier, this is some code to do it:

CVector front = point - pos;
CVector side = up * front; // up = { 0, 1, 0 }
side.Normalise();
up = front * side;
up.Normalise();
front.Normalise();
float m[16];

m[0] = side.dx;
m[1] = side.dy;
m[2] = side.dz;
m[3] = 0.0f;
m[4] = up.dx;
m[5] = up.dy;
m[6] = up.dz;
m[7] = 0.0f;
m[8] = front.dx;
m[9] = front.dy;
m[10] = front.dz;
m[11] = 0.0f;
m[12] = pos.dx;
m[13] = pos.dy;
m[14] = pos.dz;
m[15] = 1.0f;
glMultMatrixf( m );


Death of one is a tragedy, death of a million is just a statistic.

Share this post


Link to post
Share on other sites
Hey guys,

Thanks for all the feedback! Just in case you didnt know, in the code that I posted, the 'Dot' method is my bog standard Dot-Product method.

TheBlackJester - Thanks man. That seems really simple compared to what I was trying to do...I hope that it works. Im going to try it as soon as I get home from work.

Anonymous Poster - I think I have been trying to do what you have described...or at least something similar anyway. Just so I know, you say 'consider the vector between the character and the object'.
Now, to calculate this vector, would I simply subtract the objects position vector from the character's position vector? As in Destination vector - Source vector?

python_regious - Cheers. I have seen a little about billboarding before. Unfortunately, this doesnt really apply to my problem. Basically, I need to get the actual angle of rotation in degrees, so that I can rotate it at a certain speed. Sort of like for an animation. Billboarding and such similar techniques will make the object constantly face the correct direction, but I want to see the object rotating to that point.
Sorry, I feel bad about that since you have taken time to post all that code. I will eventually be delving into billboarding when my maths skills increase, so it wasn't for nothing

I'll be back tonight to say if I've got it working or not.

BTW - I have signed in as Paulus_newbieus by mistake, it is my older login...but I am actually Dark_Streak. Im getting rid of this username. Sorry for any confusion.

[edited by - Paulus_newbieus on September 2, 2002 5:59:00 AM]

Share this post


Link to post
Share on other sites
You might want to check,

radians = degrees * (PI/180.0)

degrees = radians * (180.0/PI)

(had to look it up myself, hope it's right )

python_regious's method is probably easiest, you're going to have to fiddle with the quadrants, plus getting the direction could be a pain. If you don't want to rotate all the way at first, just interpolate the 'lookat' point from where it is to the desired point (even if the desired point is moving).

If you really must have the object bolt upright you'll have to do some more math with the resulting matrix.

[edited by - JuNC on September 2, 2002 12:27:46 PM]

Share this post


Link to post
Share on other sites
Ok. Firstly this sounds like a tank turret problem, so I suggest you read up on that. If you wanted to know how to built something like this I could tell you ( with electronics ), but mathematically... Well, I've just wrote a load of stuff on a piece of paper to try and figure it out...

Firstly, heres a diagram:


Now, P1 is the old point the object was facing, P1 is the point you want the object to point too. r1 and r2 are the vectors from the objects position to these points.

Now, all of this doesn't use any sort of time based physics, do that yourself. Also, this maybe completely wrong, but as far as I can see, it should work...

Right, the problem is this, when you have a large angle between the vectors, you want to accelerate the objects rotation more towards the point. This makes sure the objects rotational velocity will slow as it reaches the point.

Now, you need to move the r1 vector along the vector "v" which is from p1 to p2. Ok, so heres the algorithm:


The vectors r1, r2 and v MUST be normalized.
Calculate acceleration:

acc = ( -r1.r2 + 1 ) / scale

Scale v according to the acceleration
v *= acc

The new point the object should point, and so the new "front" (r1) vector would be:
r1 = r1 + v;


Now let me explain some stuff. The acceleration will be based on a negative cosine curve + 1, which is low for low angles, and high for larger angles. The scale parameter scales this acceleration. This is important. If you do not have a correct scale value, your object will either take forever to rotate to the object, or will shoot pass and oscillate around the targetted point. The +1 in there is so that the curve starts at 2 and ends at 0 ( what you want ).

Once you have the look at/front(r1) vector you can build the frame as I said earlier, and transform the object.

Hope this helps...

Death of one is a tragedy, death of a million is just a statistic.

[edited by - python_regious on September 2, 2002 6:29:56 PM]

Share this post


Link to post
Share on other sites
Thanks for all the help guys, Ive solved it now - thanks for all your suggestions.

I actually did something rather stooooopid in my original attempt - I was returning radians instead of degrees, as Junc helpfully pointed out. Cheers. Dont you hate it when you overlook such small simple things.

Ive got some great rotation calculations in action now, so thanks again for all the help

Share this post


Link to post
Share on other sites