// first vector, the surface vector of the terrain
_terrainNormal = _terrain.GetTerrainNormal( _x, _y );
// second vector
Vector3 tankNormal = new Vector3( 0, 0, -1 );
// calculate angles
_angleX = (float) Math.Asin( ( _terrainNormal.X - tankNormal.X ) / ( Math.Sqrt( _terrainNormal.X * _terrainNormal.X + _terrainNormal.Z * _terrainNormal.Z )) );
_angleY = (float) Math.Asin( ( _terrainNormal.Y - tankNormal.Y ) / ( Math.Sqrt( _terrainNormal.Y * _terrainNormal.Y + _terrainNormal.Z * _terrainNormal.Z )) );
that is, im doing the regular sin(angle) = a/b thingy here, and sort of "projecting" the vectors on a 2d picture. like, when calculating angleX i totally forgett about the difference between the vectors in Y. can you do it like this?
if you can do like that, maybe there is something wrong with the code that get the terrain normal? this code takes three points and makes it a normal:
public Vector3 GetTerrainNormal( float x, float y )
{
Vector3 p1 = Vector3.Empty;
Vector3 p2 = Vector3.Empty;
Vector3 p3 = Vector3.Empty;
float fPosX = (x / _spacing);
float fPosY = (_terrainHeight-y)/_spacing;
int posX = (int) fPosX;
int posY = (int) fPosY;
float percentX = fPosX - (int) posX;
float percentY = fPosY - (int) posY;
float balance = percentX + percentY;
int triangle;
if( balance < 1 ) triangle = 0;
else triangle = 1;
if( triangle == 0 ) // top left triangle
{
p1.X = GridXToTerrainX( posX );
p1.Y = GridYToTerrainY( posY );
p1.Z = GridZToTerrainZ( GetGridHeight( posX, posY ) );
p2.X = GridXToTerrainX( posX + 1 );
p2.Y = GridYToTerrainY( posY );
p2.Z = GridZToTerrainZ( GetGridHeight( posX + 1, posY ) );
p3.X = GridXToTerrainX( posX );
p3.Y = GridYToTerrainY( posY + 1 );
p3.Z = GridZToTerrainZ( GetGridHeight( posX, posY + 1 ) );
}
else // bottom right triangle
{
p1.X = GridXToTerrainX( posX );
p1.Y = GridYToTerrainY( posY + 1 );
p1.Z = GridZToTerrainZ( GetGridHeight( posX, posY + 1 ) );
p2.X = GridXToTerrainX( posX + 1 );
p2.Y = GridYToTerrainY( posY );
p2.Z = GridZToTerrainZ( GetGridHeight( posX + 1, posY ) );
p3.X = GridXToTerrainX( posX + 1 );
p3.Y = GridYToTerrainY( posY + 1 );
p3.Z = GridZToTerrainZ( GetGridHeight( posX + 1, posY + 1 ) );
}
// TextWriter.AddText( " triangle: " + triangle );
// calculate the x and y angles to the terrain plane normal from the tank normal
Vector3 v12 = p1 - p2;
Vector3 v13 = p1 - p3;
Vector3 normalTerrain = Vector3.Cross( v12, v13 );
// TextWriter.AddText( " normal: (" + normalTerrain.X + ", " + normalTerrain.Y + ", " + normalTerrain.Z + ")" );
normalTerrain.Normalize();
return normalTerrain;
}
thanks for any help!
[edited by - apanjocko on October 23, 2003 9:21:32 PM]
angles between two vectors
if you have two vectors (in world space), how do you calculate the x, y (you could skip the z angle) between them?
i have done like this, but it seems to sometimes give slightly bad results (looks right most of the time though!):
i belive you want to user Arc Tangent instead
angle=convertToDegrees(atan2(deltax,deltay));
where deltax and y are the origin based distances of the vectors
somthing along those lines =)
Raymond Jacobs,
www.EDIGames.com
www.EtherealDarkness.com
Voice your discontent! help stop the flames!
angle=convertToDegrees(atan2(deltax,deltay));
where deltax and y are the origin based distances of the vectors
somthing along those lines =)
Raymond Jacobs,
www.EDIGames.com
www.EtherealDarkness.com
Voice your discontent! help stop the flames!
can you tell me _why_, more exactly? i'm actually really interested thanks...
i mean why use tan, not sin...
[edited by - apanjocko on October 24, 2003 12:14:21 PM]
i mean why use tan, not sin...
[edited by - apanjocko on October 24, 2003 12:14:21 PM]
You can use the dot-product to get the angle
A.B = |A||B|cos(theta)
where theta is the angle between the 2 vectors
also
A.B = (A.x * B.x) + (A.y * B.y)
you know what A and B are so you can solve for theta
cos(theta) = A.B / |A||B|
theta = acos((A.xB.x + A.yB.y) / (sqr(A.x^2 + A.y^2) * sqr(B.x^2 + B.y^2)))
A.B = |A||B|cos(theta)
where theta is the angle between the 2 vectors
also
A.B = (A.x * B.x) + (A.y * B.y)
you know what A and B are so you can solve for theta
cos(theta) = A.B / |A||B|
theta = acos((A.xB.x + A.yB.y) / (sqr(A.x^2 + A.y^2) * sqr(B.x^2 + B.y^2)))
well, that''s not what i want,
you see,
you only get one,
i want two angles, x and y - how much to rotate in the world X axis and how much to rotate in the world Y axis... that angle is not helping me in this case
you see,
you only get one,
i want two angles, x and y - how much to rotate in the world X axis and how much to rotate in the world Y axis... that angle is not helping me in this case
the reason why you use the arctangent2 instead of atan, acos or asin is beacuse of their precision at their limits. atan2 doesn''t have anyh precision limits to it. Read the help files and documentation for a full explaination.
Also, check out this post http://www.gamedev.net/community/forums/topic.asp?topic_id=185968 (recent) in the maths forum. one by minorlogic. It will save me ALOT of explaining hopefully
me off - taking gf out to the hair stylists.
Also, check out this post http://www.gamedev.net/community/forums/topic.asp?topic_id=185968 (recent) in the maths forum. one by minorlogic. It will save me ALOT of explaining hopefully
me off - taking gf out to the hair stylists.
in the post by ob, the code he uses is quite bad (mathematically it is completely correct, but for computational maths and physics (as one of my university subjects was called) it''s not accurate) as
(original)
theta = acos((A.xB.x + A.yB.y) / (sqr(A.x^2 + A.y^2) * sqr(B.x^2 + B.y^2)))
is loosing precision twice NOT including the floating point precision.
calling sqrt twice isn''t good. on really small vectors, it buggers up basically. instead of being accurate to about 12 sig figures (1.xxxx numbers) it will drop to about 10. I can post an example if you wish.
original
theta = acos((Ai*Bi+Aj*Bj+Ak*Bk)/(sqrt(Ai*Ai+Aj*Aj+Ak*Ak)*sqrt(Bi*Bi+Bj*Bj+Bk*Bk)))
rearrange to
theta = acos((Ai*Bi+Aj*Bj+Ak*Bk)/sqrt((Ai*Ai+Aj*Aj+Ak*Ak)*(Bi*Bi+Bj*Bj+Bk*Bk)))
That is one part that will help. The other is that acos (as I said before) looses precision in at different angles.
Bascially, use atan2 like EDI said to get around that
try
atan2l(cross(&v1,&v2).length(),dot(&v1,&v2));
(v1 and v2 are vectors)
(cross is the cross product)
(dot is the dot product)
(length is the length of a vector - in this case the cross product)
Hope I didn''t confuse you too much.
Also - not sure how old you are, but atleast at my university I took up some electives (I''m an engineer) in the physics and maths strands (which may be part of a double latter) called computational maths and physics. there is alot of image manipulation, and alot of maths stuff that you learn, like the one above (quite simple) in it. if your at uni, see if you are able to do some similar electives. my advice anyway.
(original)
theta = acos((A.xB.x + A.yB.y) / (sqr(A.x^2 + A.y^2) * sqr(B.x^2 + B.y^2)))
is loosing precision twice NOT including the floating point precision.
calling sqrt twice isn''t good. on really small vectors, it buggers up basically. instead of being accurate to about 12 sig figures (1.xxxx numbers) it will drop to about 10. I can post an example if you wish.
original
theta = acos((Ai*Bi+Aj*Bj+Ak*Bk)/(sqrt(Ai*Ai+Aj*Aj+Ak*Ak)*sqrt(Bi*Bi+Bj*Bj+Bk*Bk)))
rearrange to
theta = acos((Ai*Bi+Aj*Bj+Ak*Bk)/sqrt((Ai*Ai+Aj*Aj+Ak*Ak)*(Bi*Bi+Bj*Bj+Bk*Bk)))
That is one part that will help. The other is that acos (as I said before) looses precision in at different angles.
Bascially, use atan2 like EDI said to get around that
try
atan2l(cross(&v1,&v2).length(),dot(&v1,&v2));
(v1 and v2 are vectors)
(cross is the cross product)
(dot is the dot product)
(length is the length of a vector - in this case the cross product)
Hope I didn''t confuse you too much.
Also - not sure how old you are, but atleast at my university I took up some electives (I''m an engineer) in the physics and maths strands (which may be part of a double latter) called computational maths and physics. there is alot of image manipulation, and alot of maths stuff that you learn, like the one above (quite simple) in it. if your at uni, see if you are able to do some similar electives. my advice anyway.
thank you very much for your time,
i mangaged to solve it with tan, and will as soon as i've read the thread you linked to try it with atan2.
this however does the work with fewer operations:
_angleX = (float) Math.Atan( ( -_terrainNormal.X + tankNormal.X ) / tankNormal.Z );
_angleY = (float) Math.Atan( ( -_terrainNormal.Y + tankNormal.Y ) / tankNormal.Z );
why does everyone have to make it so complicated?
[edited by - apanjocko on October 24, 2003 7:37:49 AM]
[edited by - apanjocko on October 24, 2003 7:39:59 AM]
i mangaged to solve it with tan, and will as soon as i've read the thread you linked to try it with atan2.
this however does the work with fewer operations:
_angleX = (float) Math.Atan( ( -_terrainNormal.X + tankNormal.X ) / tankNormal.Z );
_angleY = (float) Math.Atan( ( -_terrainNormal.Y + tankNormal.Y ) / tankNormal.Z );
why does everyone have to make it so complicated?
[edited by - apanjocko on October 24, 2003 7:37:49 AM]
[edited by - apanjocko on October 24, 2003 7:39:59 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement