Skip to main content
GameDev.net gamedev.net
🔒 Locked

Moving & Angles

Started by Frisker Sep 2, 2006 at 12:51 PM 11 replies 1.6k views
Original Post
Frisker
Frisker
Hello, I'm quite sure that this has been posted many times before, but since I dont know what it is called I can only say that I'm sorry if I'm right. If I want to rotate an object in 2D and then move it in the same direction it's pointing I can use some simple cos & sin calculations. x += Speed * Sin(xrotation); y += Speed * Cos(xrotation); My problem basicly is, how do I do this in 3D when I have three angles?. Thanks in advance :-)
Zakwayda
Zakwayda
Assuming you mean Euler angles, you'll want to construct a matrix from your Euler angles and then extract the direction vectors from the matrix. Googling 'euler angle matrix' might help, but keep in mind there are a number of different ways to construct such a matrix, so the examples you find may not give you the exact results you're after. There's some code by Ken Shoemake available online though that supports Euler angle conversion in any order; if you can find that you'll be able to use the order that's appropriate for your setup.

Keep in mind though that Euler angles aren't very effective for certain types of 3D motion. If you need more info, you might tell us what type of object this is for and what sort of motion you want.
Bob Janova
Bob Janova
For a simple problem you can simply calculate the direction thus:

x = cos(phi)cos(elev)
y = sin(phi)cos(elev)
z = sin(elev)

But like jyk says, Euler angles have some problems for certain types of object (particularly, at high elevation – near vertical – the phi angle doesn't have any effect).
TheAdmiral
TheAdmiral
Are you sure you need three angles? Often, people like to express their 3D rotation in three parts - one rotation around each axis. In my opinion, under most circumstances, this is a bad idea.

The 2D setup requires one angle only. Extending to 3D adds one degree of freedom so you only need one more constraint. Two angles are necessary and sufficient to represent a [rotation Edit: orientation] in three dimensions. Keeping your rotation to two coordinates has many benefits, not least of which being that your rotations are now unique. (There are infinitely many ways to represent the same overall rotation if you have three angles to play with).

Euler angles have their place in the world, but I think spherical polar coordinates (with fixed r=1) are generally more suitable to game design.

If you do choose to use spherical polars, you now know what to Google to get your analogous equations (they aren't much more complicated at all).

Regards
Admiral

[Edited by - TheAdmiral on September 3, 2006 11:17:48 AM]
Ring3 Circus - Diary of a programmer, journal of a hacker.
Zakwayda
Zakwayda
Quote:
Original post by TheAdmiral
Extending to 3D adds one degree of freedom so you only need one more constraint. Two angles are necessary and sufficient to represent a rotation in three dimensions.
Just wanted to clarify for the OP that in fact three angles are required in order to represent any rotation or orientation in 3D. However, two is sufficient for many purposes, such as for representing the orientation of a humanoid character.
Frisker
Frisker
Thanks for all the answers!, I'm making a flying game.

x = cos(phi)cos(elev)
y = sin(phi)cos(elev)
z = sin(elev)

Seems to work, but sometimes the controls gets inverted, I fly backwards with the forward key and vice versa, any1 know what this could be?
Bob Janova
Bob Janova
A flying game is exactly where 'gimbal lock' is a problem with using angles – you should look into orientation matrices or quaternions. (It is impossible to perform a loop-the-loop with angles without doing some nasty stuff when going over the top. I suspect this is the reason the controls get reversed; if you go beyond the vertical this will happen.)

The third degree of freedom (and angle), 'roll', is necessary if the angles represent an object that is not a point.
TheAdmiral
TheAdmiral
Quote:
Original post by jyk
Just wanted to clarify for the OP that in fact three angles are required in order to represent any rotation or orientation in 3D.

Indeed, perhaps I could have been clearer. Two angles are sufficient to represent any direction in three dimensions. If you want periodicity in your angles or you need any of a small list of properties that we're used to in two dimensions, then you'll probably want to employ Euler angles.

Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Frisker
Frisker
So, I should look up "Euler Angles", and use it to get a perfect plane flight?
Zakwayda
Zakwayda
Quote:
Original post by TheAdmiral
Indeed, perhaps I could have been clearer. Two angles are sufficient to represent any direction in three dimensions.
Right, exactly - I just wanted to make sure the OP was aware of that distinction.
Zakwayda
Zakwayda
Quote:
Original post by Frisker
So, I should look up "Euler Angles", and use it to get a perfect plane flight?
No, you should not use Euler angles to get perfect plane flight. You should use rotation matrices or quaternions. (If you re-read the thread I think you'll see this is what the previous posters intended to convey.)
Raghar
Raghar
Equations for 3D rotations So lets derive it.

Your problems are you need to rotate around axis a, b, and c.

So lets take a point A(1, 0, 0) and rotation around center in 0, 0, 0

If you need to rotate around axis a, you'd

Aww WTH, why bother with typing.


Quote:
copyright Raghar 2005

Note this is beta version so take it carefully.

Derivation of a rotation in 3D space

snip

by just trial and error.

Lets have center of rotation on position B(0,0,0) and a point at position A(1,0,0)
We would try to find a simple 2D equation, under assumption that 2D equation would be easily extend able to 3D equation, or we could use that 2D equation directly for 3D like rotation.
Lets say we want to rotate it by 30 to the left.
Look at this picture. It's clearly obvious that distance between point and center would stay at one. It's also obvious that position on axes "a" and "b" would be equal to sin and cos of angle.

So the most basic equations would be.
Original rotation angle c = 0;
Next rotation angle d = 30;

a2 = cos(d)
b2 = sin(d)

These equations are nice. Now imagine a situation when there would be some original angle for example 20.
a2 would be a2 = cos(50)
This means
a2 = cos(c + d)
b2 = sin(c + d)

Thats cute, however this would force us to calculate original angle every time. Isn't here some other way how to just add these angles in reasonable way? Lets pretend we don't know that way, and lets pretend we can't google it in a few minutes.
Now we could try some analysis.
We want a simple equation that would compute "a2" and "b2" and we know original (rotated) positions at non unity distance, and we want to simply rotate them around B(0,0,0) (This is a simple common situation in for example OpenGL. However we will want to use it for simple geometry rotations, where we could easily add additional restrictions to make it more simple.)
So we don't know how to compute it however we can try it by writing a simple equations.
Lets try c = 30 d = 30
a2 = cos(2*c)
a2 = cos(c) + cos(c) // it doesn't work
a2 = cos(c)^2 + sin(c)^2 // it's 1
a2 = cos(c) * cos(c) // it looks better it is nearly correct it's correct when c is 0.
So we need an aditional term to make it correct. We also have sin(c).
a2 = cos(c) * cos(c) - sin(c) // it's better in some situation however too small
a2 = cos(c) * cos(c) - sin(c) * sin(c) // this is correct.
For second equation we will play a little until we found that.
b2 = cos(c) * sin(c) // is looking nearly correct It looks like half.
b2 = cos(c) * sin(c) + cos(c) * sin(c) // this is correct

So we created a simple test case and tried exaustive search on a = combination of sin cos +-*/ sin cos

However we would like to get a modified version to allow for two angles.

Try modification
a2 = cos(c) * cos(d) - sin(c) * sin(d) // now we have both angles in the equation.
b2 = cos(c) * sin(d) + cos(c) * sin(d) // it doesn't work
b2 = cos(c) * sin(d) + cos(d) * sin(c) // it works much better

Of course we started with assumption that distance between center and A would be unity. Now assume the distance would be "e".

Original equation would change to
a2 = e * cos(c)
Thus we needs to add "e" to second equation.
a2 = e * cos(c) * cos(d) - e * sin(c) * sin(d)
however note that we have original rotation already with these equations
a = e * cos(c)
b = e * sin(c)
so we could change that second equation into
a2 = a * cos(d) - b * sin(d)
b2 = a * sin(d) + b * cos(d)
This is exactly what we want. We can precalculate cos(d) and sin(d) and use them for each point extremely easily.

Now we could try it with point A. remember original rotation is 0, so a = 1, b = 0
a2 = 1 * cos(20) - 0 * sin(20)
it simplifies to
a2 = cos(20);
b2 = 1 * sin(20) + 0 * cos(20)
b2 = sin(20)
So we ended with that two original equations. Now we could try to rotate it with a = cos(20), b = sin(20) by additional 30
a3 = cos(20) * cos(30) - sin(20) * sin(30)
b3 = cos(20) * sin(30) + sin(20) * cos(30)

It works well so now we could play with 3D space, or not. Lets look how it would look in 3D space with rotations 20 by axis "b" and 10 by axis "a" and additional 40 by axis "c"

Lets say we have A(2,0,0) and B(3,3,3)
aR = 10
bR = 20
cR = 40

point A
a = 2
b = 0
c = 0

point B
a = 3
b = 3
c = 3

so first try rotation for the point A rotation around axis "b"

coordinate system is defined as (1,1,1) recommended center is at the bottom center part of the screen.

right to front
a2 = a * cos(bR) - c * sin(bR) RF angle
c2 = a * sin(bR) + c * cos(bR)

up to front
b2 = c * cos(aR) - b * sin(aR) UF angle
c2 = c * sin(aR) + b * cos(aR)

right to up
a2 = a * cos(cR) - b * sin(cR) RU angle
b2 = a * sin(cR) + b * cos(cR)

so a little combination would show equations

a2 = a * cos(bR) - c * sin(bR) + a * cos(cR) - b * sin(cR)
b2 = (a * sin(bR) + c * cos(bR)) * cos(aR) - b * sin(aR)
c2 = (a * sin(bR) + c * cos(bR)) * sin(aR) + b * cos(aR)


b2 = (a * sin(bR) + c * cos(bR)) * cos(aR) - b * sin(aR)
c2 = (a * sin(bR) + c * cos(bR)) * sin(aR) + b * cos(aR)

a2 = (a * cos(bR) - c * sin(bR)) * cos(cR) - ((a * sin(bR) + c * cos(bR)) * cos(aR) - b * sin(aR)) * sin(cR)
b2 = (a * cos(bR) - c * sin(bR)) * sin(cR) + ((a * sin(bR) + c * cos(bR)) * cos(aR) - b * sin(aR)) * cos(cR)
c2 = (a * sin(bR) + c * cos(bR)) * sin(aR) + b * cos(aR)


a2 = a * cos(bR) * cos(cR) - c * sin(bR) * cos(cR) - (a * sin(bR) * cos(aR) + c * cos(bR) * cos(aR) - b * sin(aR)) * sin(cR)
b2 = a * cos(bR) * sin(cR) - c * sin(bR) * sin(cR) + (a * sin(bR)* cos(aR) + c * cos(bR) * cos(aR) - b * sin(aR)) * cos(cR)
c2 = (a * sin(bR) + c * cos(bR)) * sin(aR) + b * cos(aR)


Simplified pipeline would be


snipped because the above material would teach you all things thus derivation of the correct equations is trivial.

Not to mention in OpenGL you'd use vertex lists, and build in mechanisms.
Raghar
Raghar
As for your problem, do you have a direction vector?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.