Convert yaw, pitch AND roll to x,y,z vector in world coordinates
I don't think you're going to find an answer that's pure trig. Not an elegant one, anyway.
Euler angles(Pitch/Yaw/Roll) are not the right tool for this job. Gimble-lock will be a problem, as well as the ambiguity of the order of operations.
I suggest storing your objects' current rotational state in either a Matrix or a Quaternion. Only use Euler angles for relatively small deltas.
![ApproachingDarknessFish](https://i.stack.imgur.com/fG8z0.png?s=256&g=1)
ApproachingDarknessFish
main = putStrLn "Hello nerds!" I'm a mostly self-taught programmer and researcher who happens to have a degree in bioinformatics with a minor in CS. I haven't been very active on stack overflow since I accidentally hit 10K. I spend most of my time on scifi.se.
Updated on June 04, 2022Comments
-
ApproachingDarknessFish about 2 years
I'm working on some simple 3d graphics in OpenGL (java LWGJL), and I'm trying to figure out how to convert yaw, pitch and roll to the x, y and z components of my movement Vector. I know how to do this with just pitch and yaw (as explained here), but I haven't found anything the explains how to integrate roll into this formula.
I am aware that yaw and pitch are all that is needed to define a vector in 3d space, but I also need roll in this instance. I have keys bound to different movements relative to the camera in a basic WASD configuration (A is local left, W is local forward, SPACE is local up), so the roll affects how the camera moves (eg pressing D with a roll of pi/2 (the default) moves the camera right (in world coords), but pressing D with a roll of pi moves the camera up in world coords)).
Here's the code I have so far:
//b = back //f = forward //r = right //l = left //u = up //d = down private void move() { double dX = 0, dY = 0, dZ = 0; if (f ^ b) { dZ += cos(yaw) * cos(pitch) * (b ? 1 : -1); dX += sin(yaw) * cos(pitch) * (b ? 1 : -1); dY += -sin(pitch) * (b ? 1 : -1); } if (l ^ r) { dZ += sin(yaw) * sin(roll) * (l ? 1 : -1); dX += cos(yaw) * - sin(roll) * (l ? 1 : -1); dY += cos(roll) * (l ? 1 : -1); } if (u ^ d) //this part is particularly screwed up { dZ += sin(pitch) * sin(roll) * (u ? 1 : -1); dX += cos(roll) * (u ? 1 : -1); dY += cos(pitch) * sin(roll) * (u ? 1 : -1); } motion.x = (float) dX; motion.y = (float) dY; motion.z = (float) dZ; if (motion.length() != 0) { motion.normalise(); motion.scale(2); } x += motion.x; y += motion.y; z += motion.z;
This works for a few rotations, but for many it produces incorrect results.
So the question is:
How do I modify my code such that it successfully calculates the x, y, and z components of my motion vector based upon my desired direction (what key is pressed), accounting for my yaw, pitch, AND roll?
I'm fine with using raw trig (as I am attempting to do), a solution involving matrices, or pretty much anything.
EDIT:
Please don't answer by just linking to the Wikipedia article on Euler Angles. I've read it and I don't have a strong enough background in math to understand how to apply it to my situation.
EDIT #2:
I'm only using Euler angles to store my orientation in between re-orienting the camera. For the actual camera manipulations, I use rotational matrices. If needed, I can drop the euler angles and just use a matrix. All that matters is that I can convert from my orientation to a vector.
EDIT #3:
Found a solution by multiplying my forward vector by my rotation matrix as described in the comments:
//b = back //f = forward //r = right //l = left //u = up //d = down private Vector3f motion; protected void calcMotion() { //1 for positive motion along the axis, -1 for negative motion, 0 for no motion motion.x = r&&!l ? -1 : l ? 1 : 0; motion.y = u&&!d ? 1 : d ? -1 : 0; motion.z = f&&!b ? 1 : b ? -1 : 0; if (motion.length() == 0) { return; } motion.normalise(); //transform.getRotation() returns a Matrix3f containing the current orientation Matrix3f.transform(transform.getRotation(), motion, motion); }
Still having trouble with this, though.