How to get Yaw, Pitch and Roll from a 3D vector
Asked Answered
Q

5

22

I have a direction vector that applied to a position gives me the point at which the camera should look. How can I get from that yaw, pitch and roll in order to use glRotatef properly?

Thanks in advance

Quintessa answered 6/5, 2010 at 16:18 Comment(0)
Z
10

You probably don't actually want the yaw, pitch and roll. You just need the correct transformation. Try using gluLookAt to build it. Documentation.

Zinfandel answered 6/5, 2010 at 16:28 Comment(3)
Thank you for the hint. I just started using OpenGL and I didn't know about this function. I solved using this.Quintessa
This is a nice answer, but only practical for a subset of the common platforms which provide GLU (e.g. not necessarily OpenGL ES platforms)Avlona
@Avlona very easy to “roll your own” — classic example in almost every graphics textbook.Fluoride
T
29

None of these equations are 'wrong' but all are a little clumsy. Ryder052, you example does not account certain cases as you've commented. Why not use atan2?

Given unit (normalized) direction vector d

pitch = asin(-d.Y);
yaw = atan2(d.X, d.Z)
Thordia answered 18/11, 2015 at 21:2 Comment(3)
This trick did it for me, if I reversed pitch. A positive value made me look down while a negative value made me look up. Not hard to fix, but if someone else runs into this problem.Lace
Hello, how do I extend the pitch between -pi and pi?Brutish
pitch = asin(-d.Y); I think this is wrong as for as vec2(x,z).length is not oneAfrican
A
21

You cannot get yaw, pitch and roll from a direction vector as the direction vector will only tell which direction to look in (yaw and pitch)

To get the yaw and pitch you use trigonometry - I assume you have some working knowledge. Check out this wiki page for some useful diagrams to visualize the angles.

Letting Y = yaw, P = pitch.

First to get yaw you want:

tan(Y) = x/(-y)

Now to get pitch:

tan(P) = sqrt(x^2 + y^2)/z

To get the actual values for Y and P you'll need to use inverse tan, I've written it above using tan to make the derivation clearer.

Note that the minus signs depend on how you define you angles and axes, but you should get the idea.

You can then set roll to be 0 or whatever you like.

Arria answered 6/5, 2010 at 16:29 Comment(5)
But in practice there is usually an 'up' direction in any application and you can almost always choose an orientation that keeps 'up' as close to upwards as possible.Zinfandel
Thanks a lot for the reply. Yes you are right, the roll cannot be determined only by a vector I need an up vector (as user207442 suggests) or a scalar that determine the angle. I solved my problem using gluLookAt but I'm still curious about how to get these angles.Quintessa
Your expression for tan(Y) is more or less intuitive. For tan(P) not so much. Could you explain why this expression gives tan(P), or link to a source that explains it?Nick
@Nick - tan(P) = distance-in-ground-plane / distance-along-up-axis. As shown, z is distance-along-up-axis, the sqrt(..) is distance of 2D vector (x, y) in ground plane. Also note that in practice, using P = arctan(whatever) won't give the correct sign for half the angles (have to compute sign separately, not shown); in practice, use atan2. I think here it would be P = atan2(z, distance-in-ground-plane). Or switch the parameters if I'm wrong.Mantic
Hmm. Still problematic, because "distance" is unsigned; need to determine sign. Have to look elsewhere for complete answer...Mantic
Z
10

You probably don't actually want the yaw, pitch and roll. You just need the correct transformation. Try using gluLookAt to build it. Documentation.

Zinfandel answered 6/5, 2010 at 16:28 Comment(3)
Thank you for the hint. I just started using OpenGL and I didn't know about this function. I solved using this.Quintessa
This is a nice answer, but only practical for a subset of the common platforms which provide GLU (e.g. not necessarily OpenGL ES platforms)Avlona
@Avlona very easy to “roll your own” — classic example in almost every graphics textbook.Fluoride
H
4

pheelicks's equations are wrong. Dear future googlers, here you got what's working:

Assuming pitch: rotation by X axis, yaw: rotation by Y axis, roll: rotation by Z axis. Direction vector V(x,y,z)

pitch = asin(V.y / length(V));
yaw = asin( V.x / (cos(pitch)*length(V)) ); //Beware cos(pitch)==0, catch this exception!
roll = 0;
Herby answered 25/6, 2015 at 11:10 Comment(1)
It does look to me like it's pretty much the same thing, maybe you should check your trigonometry.Bachelorism
C
0

Well, I am not sure what any of these answers are about because I could not get any of them to work.

I created my own solution...

// get world target offset
// convert world target offset to world direction normal
// get my world transposed (inverted)
// rotate world direction normal to my space normal

Vector3D lWorldTargetOffset = gWorldTargetLocation - gWorldMyLocation;
Vector3D lWorldTargetDirection = lWorldTargetOffset.Normalize();
MatrixD lMyWorldTransposed = MatrixD.Transpose(MyWorldMatrix);
Vector3D lMySpaceTargetDirection = Vector3D.Rotate(lWorldTargetDirection, lMyWorldTransposed);

you now have the world target direction normal in my space

lMySpaceTargetDirection.X = pitch
lMySpaceTargetDirection.Y = yaw.
lMySpaceTargetDirection.Z = <0 infront >0 behind.

As per direction normals all values are -1 to 1 so if you want degrees simply * 90.

Not saying this is the best solution but it is the only one I could get to work after spending hours searching online and wading through copious amounts of obtuse and nebulous crud.

I hope you, someone, or anyone, will enjoy simply rotating the target direction normal making it relative to myspace, and find it easy and helpful :)

Cole answered 24/7, 2022 at 19:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.