   Relative euler rotation to absolute Quaternion
  I am building a free moving camera but I am having trouble reasoning out the math for the rotating it.  Here is some pseudo-pseudocode for the rotation method.  Assume the utility methods work. The comments are what I need to determine and flesh out:Quaternion currentRotation;...relativeRotate(float pitch, float yaw, float roll)}  Quaternion qRel = quaternionFromPitchYawRoll(pitch, yaw, roll);  //Quaternion qAbs = absoluteRotationFromRelativeRotation(currentRotation, qRel);  currentRotation = currentRotation*qAbs;}Just to be clear, the currentRotation holds the cameras rotation in relation to the world or its absolute rotation. When I tell it to pitch or yaw or roll, those are relative rotation inputs. Telling it to pitch down will always pitch down in its own frame of reference. However, with respect to the world, if I told it to yaw 90 degrees then pitch down, that relative pitch would actually be an absolute roll. This is the math I am trying to pin down. How do I, based on current rotation and some relative input, determine what the absolute rotation is? I have the current absolute rotation of the camera, and the relative rotational input, so Ra' = f(Ra, Rr), what is that function f?The more rigorous math the better, but I'll take anything.[Edited by - sequoroxx on September 11, 2007 2:30:10 PM]
  I wasn't quite able to figure out what you were getting at in your post, but I will ask this question: what do you need the 'absolute rotation' for? It's certainly not necessary for what you appear to be trying to do (that is, free 6DOF motion).You already have everything you need:Quaternion qRel = quaternionFromPitchYawRoll(pitch, yaw, roll);currentRotation = currentRotation*qAbs;Assuming your math library uses standard quaternion multiplication order, the above code will correctly apply pitch, yaw, and roll locally to your orientation quaternion (don't forget to normalize currentRotation occasionally).   ;  The rotation of the camera is the rotation relative to the world, or the absolute rotation. Its relative rotation is meaningless. It would be like storing its relative position which would always be (0,0,0) in its frame of reference. Imagine if it were at (20, 0, 0) and it was facing 90 degrees rotated about some axis. I then want to move it forward 5 units. Well, forward is relative to its rotation so we need to convert it from relative instruction of moving 5 units forward (+5,0,0) to world frame of reference (0, +5, 0) so there needs to be a conversion from TranslationRelative to TranslationAbsolute.I have already solved the translation math, but that was just an example. The following is not everything I need because if I told my camera to look downward from whatever rotation it was currently at, it couldn't.Quaternion qRel = quaternionFromPitchYawRoll(pitch, yaw, roll);currentRotation = currentRotation*qAbs;If I just modified my orientation by the relative coordinates, I could only correctly pitch downward in the cameras frame of reference when the camera was aligned with the world rotation axis.So, to summarize as best I can, I have a relative rotation change I want to make to the camera(turn left, look up...etc), but in order to make correct changes to its absolute rotation I need to convert those relative changes into absolute rotation instructions first.[Edited by - sequoroxx on September 11, 2007 2:00:14 PM];Quote:Original post by sequoroxxSo, to summarize as best I can, I have a relative rotation change I want to make to the camera(turn left, look up...etc), but in order to make correct changes to its absolute rotation I need to convert those relative changes into absolute rotation instructions first.Ok, I think I'm starting to see where the confusion is coming from.Before going into more detail, I have one question: what math library are you using? I ask because some math libraries use standard quaternion multiplication order while some use 'reverse' multiplication order, and I think the problem you're encountering may be a multiplication order issue.If you're using your own math code (and if you're not sure which form of quaternion multiplication you've implemented), perhaps you could just post the quaternion multiplication function so we can take a look at it.   ;  I'm using the XNA framework. It wraps directX 9c in .NET. I cannot tell you much about its multiplication features since I only just started using it. This code below was what I used until I found that upon moving around in the world (via first person view by moving the camera around), I noticed that the yaw, pitch and roll were static, meaning that if I was looking downward, and tried rolling, it would instead make me look left or right. Or if I turned around 180 degrees, trying to look up would instead make me look down. I knew immediately that I had made an error in treating my relative rotation instructions as absolute ones without converting them first.float yaw;    float pitch;    float roll;    Quaternion currentRotation;public void Rotate(float xRotation, float yRotation, float zRotation) {    this.yaw += xRotation;    this.pitch += yRotation;    this.roll += zRotation;    Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), this.yaw);    Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), this.pitch);    Quaternion q3 = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), this.roll);    currentRotation = q1 * q2 * q3;}As you can see, I've since done away with the euler coordinates. As I mentioned earlier, my relative translation method makes use of the rotation Quaternion and works correctly. So I just need to figure out how to tell the world that when my camera is looking down, telling it to look to the right means rolling it in the worlds frame of reference.PS: Thank you for taking the time to do this. I appreciate it.   ;Quote:So I just need to figure out how to tell the world that when my camera is looking down, telling it to look to the right means rolling it in the worlds frame of reference.Hm, I can't remember which convention XNA uses for quaternion multiplication. DX uses the 'reverse' form to mirror its use of row-vector notation, but I seem to remember that maybe they switched back to the 'standard' form for XNA...Anyway, there are only two ways to order the multiplication, so I'd suggest just trying both of them and seeing which one works. I gather that you currently have something like:Quaternion qRel = quaternionFromPitchYawRoll(pitch, yaw, roll);currentRotation = currentRotation*qRel;And that this is producing an absolute rotation (which is not what you want). So, try this instead:Quaternion qRel = quaternionFromPitchYawRoll(pitch, yaw, roll);currentRotation = qRel*currentRotation;And see if it fixes the problem.The basic idea here is this. Let's say you have two rotations, R1 and R2. If you combine these rotations in the order R1->R2, then R1 will appear to be relative to R2 (which is what you want). If you combine the rotations in the order R2->R1, R1 will appear to be in absolute coordinates.Now, with row-vector notation (and reverse quaternion multiplication order), the order R1->R2 translates to R1*R2. However, with column-vector notation (or standard quaternion multiplication order), it translates to R2*R1.Since I don't know how XNA handles quaternion multiplication, I can't say for sure which of these orders you want. However, since R2*R1 doesn't seem to be working, I'm going to guess that it's R1*R2 (i.e. qRel*currentRotation).Now if neither order works, then there's probably something wrong elsewhere in your code.   ;  Ok, upon your insistence that all I needed was already in front of me, I went ahead and worked out the math from scratch using some examples I thought would lead to a contradiction in your claim. Turns out you were right. I still don't intuitively understand how relative euler rotation commands, when converted into a quaternion then multiplied against the objects current rotation quaternion could result in the correct changes, but it did. The math I worked out always gave correct results for the current quaternion after I converted it back to euler so I could see it myself.Thanks for getting this stubborn programmer to understand.