Archived

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

skullfire

vector math and angles....

Recommended Posts

Well, I am making a system much like Xenogears or Doom, in which you can look at a sprite from different angles, and, depending on it, the sprite texture will change. For instance, If you look at the character, and he''s facing the viewer, the sprite that will be selected wil be the front facing sprite. To do this, i have made some vectors: Camara.m_vPosition = position of cam Camara.m_vView = viewing vector of cam Camara.m_vUp = World Up Vector(0,1,0) Character1.m_vPosition = position of character Character1.m_vView = viewing vector of char So, having this vectors(im not using the world up vector), i want to calculate an angle between the cam''s position relative to the sprite, and the character''s view vector.... i have rad a lot, and all seems to point to using the dot product... but.. its not really workin... can any1 help me? Here''s the main formula source.
        TVector3 vDist1 = Normalize(Camara.m_vPosition - Character1.m_vPosition);
        TVector3 vDist2 = Normalize(Character1.m_vView);// - Character1.m_vPosition);

        vDist1.y = vDist2.y = 0;
        float angle = acos(DotProduct(vDist1,vDist2)*M_PI/180)*180/M_PI;

Share this post


Link to post
Share on other sites
Don''t put the *M_PI/180 inside the acos func...
you just want this:

acos(DotProduct(vDist1,vDist2))*180/M_PI;

This will return the angle diff in degrees, or leave off the 180/M_PI if ya want it in radians (as long as you are internally consistent, it won''t matter which you use, and unless you need to actually see the angle yourself, i''d stick with radians, less math calls... won''t make a mind-numbing difference, but every bit helps)

Share this post


Link to post
Share on other sites
The atan2() function is probably more suited, that would return the angle in the range [0, 2_PI].

cos(60.0f) = cos(-60.0f) = 0.5f;

Draw a triginometric circle, and you'll see you need one extra bit of information to decide if the angle is negative or positive.

The way you can do it is if you supply an extra side direction. Given the sign of the dot product of (side * Dist), you can use either acos() and change the sign of the result, or you can use atan2().

And you should normalise AFTER you set the y component to 0.0f;


TVector3 vDist1 = (Camera.m_vPosition - Character1.m_vPosition);
TVector3 vDist2 = (Character1.m_vView); // direction of camera


vDist1.y = 0.0f;
vDist2.y = 0.0f;
vDist1.Normalise();
vDist2.Normalise();

float fSign = (vDist2.Cross(vDist1)).Dot(Camera.m_vUp);
fSign = (fSign > 0.0f)? 1.0f : -1.0f;

float angle = acos(vDist1.Dot(vDist2)) * fSign * (180.0f / 2_PI);


[edited by - oliii on October 7, 2003 4:45:44 AM]

Share this post


Link to post
Share on other sites
Thanks olii and stonicus! I''ll post here if I have any more problems.
Oh, and olii, if I would use the atan function, then i wouldn''t have to do the sign thingie right? this is the code i have so far, working good.
        TVector3 vDist1 = Camara.m_vPosition - Character1.m_vPosition;
TVector3 vDist2 = Character1.m_vView;

vDist1.y = vDist2.y = 0;

vDist1 = Normalize(vDist1);
vDist2 = Normalize(vDist2);

float angle = RADTODEG(atan( DotProduct(vDist1,vDist2) ));

For some reason though, at the first scene(i''ve put the Character1.m-vView point at the cam), the angle I get is 45, and not zero, as it should be... why is this?

Share this post


Link to post
Share on other sites
Ok, i figured the rest and its working gr8, but sometimes there is a popup error on the acos function... the Dot product isnt giving a -1,1 result sometimes, but a bigger value... both vDist1 and vDist2 are normalized, how could I get through this error? here''s my code atm.

TVector3 vDist1 = g_Camara.m_vPosition - Character1.m_vPosition;
TVector3 vDist2 = Character1.m_vView - Character1.m_vPosition;

vDist1.y = vDist2.y = 0;

vDist1 = Normalize(vDist1);
vDist2 = Normalize(vDist2);
float fSign = Dot(Cross(vDist2,vDist1),g_Camara.m_vUpVector);
fSign = (fSign > 0.0f)? 1.0f : -1.0f;
float angle;
angle = RADTODEG( acos(Dot(vDist1,vDist2)) * fSign );

Share this post


Link to post
Share on other sites
quote:
Original post by skullfire
To get the deltas for the viewing vector...since Character1.m_vView is just another position on the map, the thing he's looking at(at the beginning it is set to be cam's position).



Ah, ok, your original post said Character1.m_vView = viewing vector of char, so I was wondering why you subtract the guys loc from it, but I see what yer doin now...

Still a little confused, you have:
A) Loc of player
B) Loc of camera
C) Loc of the object the player is looking at

And you want the angle between vectors 'C-A' (vector from player to ob) and 'C-B' (vector from cam to ob)??

Please clarify...

Also, a few things to keep in mind, Cross Product returns a vector that is orthogonal (perpendicular) but not necesarily normalized. Dot products need to use normalized vectors. So in yer code, the Cross product you get should be normalized before putting it into the Dot product with the camera's up vector.

Edit: technically, dot products don't NEED normalized vectors, as it is X*Y=|X||Y|cos(theta), but if they are normalized, |X||Y|=1, and makes it easier.


[edited by - stonicus on October 7, 2003 9:54:19 PM]

Share this post


Link to post
Share on other sites
Yeah, i know all of this...except for that of normalizing the cross product... so..in the end..the function will end up with 3 normalizes?
Oh, and the object the question was already answered.. ill explain it again though..
I have the CAMERA(which is basically the player itself, atm). I have the position of the camera, the viewing position, and the up vector. Now, i also have another OBJECT that is in the scene, called Character1. I have both the position as the viewing position.. What I wanted to do was to calculate an angle between the viewing vector of the character and the vector of the distance between the character and the camera...
All has been solved... but i had the problem with the acos sometimes popping an error... im gonna try normalizing the cross...lets see what happens...

Share this post


Link to post
Share on other sites