# GarrickW

Members

44

115 Neutral

• Rank
Member

2. ## Best practice for vertex normal calculations?

I'm looking to create arbitrarily-shaped meshes and calculate the proper vertex normals for each vertex. As I understand it (and I may be wrong), if you want smooth shading, you need to ensure that vertices have a normal that represents the combined normals of all the triangles that vertex is involved in. For instance, if you have a straight edge along your model where the surfaces extend down along Y starting at 0, right along X starting at 0 and infinitely into and out of the Z axis, then your vertices need to have normals that point exactly in the +Y, -X direction. I'm sure that's not the best description, but you get my gist. Otherwise, if the vertices in each triangle merely represent that triangle's normal, you'll get entirely flat shading. (EDIT: Just to be clear, I mean that given a triangle A, the vertices A1, A2 and A3 shouldn't all have identical normals - rather, their normals should be influenced by the normals of other triangles as well, such that, for example, normals A2 and A3 should have a normal also influenced by the normal of the separate triangle A2-A3-A4.) So, first question - is that indeed the way to achieve smoother-looking shading? If it is, I've got something of a problem, as the image below (which should be a pyramid) no doubt makes clear. The triangles themselves are all placed accurately, but I'm not calculating my normals properly. I should mention that the way I build my triangles internally is that I have a fixed set of vertices and, based on a number of parameters, choose some of these vertices as points in an arbitrary mesh (which are first stored as pointers, and then ultimately uploaded to a vertex buffer object as a series of floats). Since vertices store their normals as well as their position, I thought it would be easy to ensure that each time a vertex is used by a triangle, that triangle's normal influences the vertex's total normal. It appears that isn't the case. Currently, every time I make a new triangle, I calculate its normal and then add that normal to the existing normals of the three vertices involved. After making all my triangles, I reduce the length of each vertex's normal to 1. I've also tried adding them and then dividing by the number of triangles involved, but that doesn't work and it doesn't sound like it should work, either. This is my normal calculation. I run this for all triangles (which contain pointers to their Verts 1, 2, and 3). [code] float A[3] = {Vert2.x - Vert1.x, Vert2.y - Vert1.y, Vert2.z - Vert1.z}; float B[3] = {Vert3.x - Vert1.x, Vert3.y - Vert1.y, Vert3.z - Vert1.z}; float nX = A[1] * B[2] - A[2] * B[1]; float nY = A[2] * B[0] - A[0] * B[2]; float nZ = A[0] * B[1] - A[1] * B[0]; nX *= -1; nY *= -1; nZ *= -1; Vert1.nx += nX; Vert1.ny += nY; Vert1.nz += nZ; Vert2.nx += nX; Vert2.ny += nY; Vert2.nz += nZ; Vert3.nx += nX; Vert3.ny += nY; Vert3.nz += nZ; [/code] This is how I normalize the normals. I run this for all Verts after having run the above code for all triangles. [code] //Normalize! float Length = sqrt(Vert.nx * Vert.nx + Vert.ny * Vert.ny + Vert.nz * Vert.nz); Vert.nx /= Length; Vert.ny /= Length; Vert.nz /= Length; [/code] Clearly, the results aren't what I want. I was hoping somebody might be able to help me arrive at a better solution than this. Any advice?
3. ## How to Use a Quaternion as a Camera Orientation

Good news! I've solved the problem. The issue was that I should have been pushing a matrix created from the [i]inverse [/i]of the Orientation (as well as reversing all the transformation data, i.e. the rotation and translation). What I do now is [CODE] //Rotate camera glMultMatrixf( m_PlayerCamera.GetInvertedMatrix() ); //Translate camera sf::Vector3<float> CameraPos = m_PlayerCamera.GetPosition(); glTranslatef(CameraPos.x, CameraPos.y, CameraPos.z); [/CODE] Where GetInvertedMatrix() looks like this: [CODE] GLfloat* Camera::GetInvertedMatrix() { //Get a new quaternion, the inverse of the Orientation Quaternion InvertedOrientation = m_Orientation; InvertedOrientation.Invert(); //Fill the matrix with the orientation InvertedOrientation.RotationMatrix(m_RotationMatrix); //Return that matrix return m_RotationMatrix; } [/CODE] Once I do this, everything works as intended. In case anybody in the future is looking for the way to Invert() a quaternion, here's my code: [CODE] void Quaternion::Invert() { float Length = 1.0 / (x*x + y*y + z*z + w*w); x *= -Length; y *= -Length; z *= -Length; w *= Length; } [/CODE]
4. ## How to Use a Quaternion as a Camera Orientation

Thanks for the reply! [quote name='Matias Goldberg' timestamp='1337580247' post='4941832'] "Doing the reverse" means in this case m_TurnSpeed becomes "-m_TurnSpeed" And, when translating, m_MoveSpeed is also negated "- m_MoveSpeed" But don't change the order of the quaternion multiplcations, it's not the same. The idea behind the "camera matrix" (actually called view matrix) is that, if you can't the camera, move the whole world. This means if the camera is moved 2 units to the left, it's the same as if [i]everything else[/i] moves 2 units to the right. Same with rotations, etc. You get the idea. [/quote] See, I thought this was the case, but when I try that out (inverting m_TurnSpeed and m_MoveSpeed, leaving the order of the quaternion multiplication alone), what happens is the rotations are in the wrong direction, and they don't add up. So for example, if I turn to the right around the Y axis (by pressing the key meant to turn to the left), then try to rotate around the Z axis, I end up rotating around the global Z axis, not the camera's Z axis, i.e. I end up rotating around the camera's X axis (if it's a 90° turn). When I leave the values alone and reverse the multiplication order, rotation *appears* to work as expected (i.e. rotation around the Y axis, then around the Z axis, leads to a rotation around the new, post-Y-rotation Z axis and not the old one). It might not be, of course; if that's the case, then there's a deeper problem. [quote name='Matias Goldberg' timestamp='1337580247' post='4941832'] If you still don't get it working after negating those variables, the way you're extracting the translation part and then apply movement doesn't look quite right. Can't really tell without debugging the numbers. If I'm not mistaken, that code should make the camera spin around the origin when trying to rotate, rather than rotating around it's center. But in the models you don't see it glitch like that because you normalize the matrix, and use glTranslate to let OpenGL perform the translation for you, so it miraculous works. [/quote] Hm, that could be a problem. Here is what MultVect() looks like: [CODE] sf::Vector3<float> Quaternion::MultVect(sf::Vector3<float> Vector) { //From http://www.idevgames.com/articles/quaternions Quaternion VectorQuat = Quaternion(); VectorQuat.x = Vector.x; VectorQuat.y = Vector.y; VectorQuat.z = Vector.z; VectorQuat.w = 0.0; Quaternion Inverse = (*this); Inverse.Invert(); Quaternion Result = Inverse * VectorQuat * (*this); sf::Vector3<float> ResultVector; ResultVector.x = Result.x; ResultVector.y = Result.y; ResultVector.z = Result.z; return ResultVector; } [/CODE] I do use glTranslafef() when rendering the scene. Here is what that code looks like (it is called before anything else in the scene is rendered): [code] //Rotate camera glMultMatrixf(m_PlayerCamera.GetMatrix()); //Translate camera sf::Vector3<float> CameraPos = m_PlayerCamera.GetPosition(); glTranslatef(CameraPos.x, CameraPos.y, CameraPos.z); [/code] [quote name='Matias Goldberg' timestamp='1337580247' post='4941832'] But in the camera, you don't have that, so if I'm not mistaken, you are unable to move it, right? [/quote] It actually moves quite smoothly, just in the wrong direction. If I do the following, I get near-perfect movement so long as I don't try to rotate around the camera's Z axis. [CODE] //Create new quaternions for each axis Quaternion xOffset = Quaternion(); xOffset.FromAxisAngle(Rotation.x * m_TurnSpeed, 1.0, 0.0, 0.0); Quaternion yOffset = Quaternion(); yOffset.FromAxisAngle(Rotation.y * m_TurnSpeed, 0.0, 1.0, 0.0); Quaternion zOffset = Quaternion(); zOffset.FromAxisAngle(Rotation.z * m_TurnSpeed, 0.0, 0.0, 1.0); //Multiply the new quaternions into the orientation m_Orientation = m_Orientation * yOffset * zOffset * xOffset; //Get matrix m_Orientation.Normalize(); m_Orientation.RotationMatrix(m_RotationMatrix); ///Translate camera Translation = m_Orientation.MultVect(Translation); m_Position.x += (Translation.x * m_MoveSpeed); m_Position.y += (Translation.y * m_MoveSpeed); m_Position.z -= (Translation.z * m_MoveSpeed); [/CODE] Now, mathematically, I'm almost certain something isn't right here, since that's not what I'd expect the proper operations to look like.
5. ## How to Use a Quaternion as a Camera Orientation

So a while ago I was trying to figure out how to rotate objects using quaternions, and I eventually succeeded. Now, I'm trying to adapt the same system for use in my camera. I am coding in C++, using OpenGL and SFML. Here is how I rotate and translates objects at the moment: [CODE] //Create change quaternions for each axis Quaternion xOffset = Quaternion(); xOffset.FromAxisAngle(Rotation.x * m_TurnSpeed, 1.0, 0.0, 0.0); Quaternion yOffset = Quaternion(); yOffset.FromAxisAngle(Rotation.y * m_TurnSpeed, 0.0, 1.0, 0.0); Quaternion zOffset = Quaternion(); zOffset.FromAxisAngle(Rotation.z * m_TurnSpeed, 0.0, 0.0, 1.0); //Multiply the change quats by the current quat m_Orientation = yOffset * zOffset * xOffset * m_Orientation; //Get matrix m_Orientation.Normalize(); m_Orientation.RotationMatrix(m_RotationMatrix); Translation = m_Orientation.MultVect(Translation); m_Position.x += (Translation.x * m_MoveSpeed); m_Position.y += (Translation.y * m_MoveSpeed); m_Position.z += (Translation.z * m_MoveSpeed); [/CODE] I apply m_RotationMatrix using glMultMatrix(), and m_Position using glTranslatef(). This works fine for objects rotating and translating about, but when I apply this to my camera, obviously things don't work. Now, I say obviously, because as far as I know, if I want to change the direction I'm "looking at" in OpenGL, I need to apply the [i]reverse [/i]of the changes I'd apply to an object. However, I'm not quite sure how to do this, and all my attempts have failed. Leaving everything exactly the same, I find rotations don't add up and translations are backwards or inverted. Inverting the input doesn't help. I believe that using [CODE] m_Orientation = m_Orientation * yOffset * zOffset * xOffset; [/CODE] Instead of the previous form is appropriate for the camera, and this is enough to fix all the rotation issues, but I simply can't manage to get translations to work after that. I can get close by adding the X and Y changes to the position normally and then subtracting the Z change from the position, but this still leads to wonky behavior when moving and rotating around the Z axis at the same time, and the object ends off spiraling away from the point it is supposed to be pointing towards. So, any tips on how to adapt the above behavior for proper use as a camera? Also, when applying a camera to OpenGL, to I need to use glPushMatrix() and glPopMatrix()? I ask because that helped some tests run better than others, but it doesn't seem to make sense to do so, since those are basically for pushing a new [i]local [/i]space for transformations onto the stack (I'm horribly mangling my terminology, I'm sure).
6. ## Quaternion Object Rotation

Found it! It turns out my implementation of quaternions [i]wasn't[/i] correct after all. The code for quaternion multiplication I had was either wrong, or I copied it wrong. Either way, fixing it by referring to this site helped: [url="http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Quaternions.html"]http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Quaternions.html[/url] For the record, the correct quaternion multiplication code I now use is: [code]Quaternion Quaternion::operator* (Quaternion OtherQuat) { float A = (OtherQuat.a * a) - (OtherQuat.x * x) - (OtherQuat.y * y) - (OtherQuat.z * z); float X = (OtherQuat.a * x) + (OtherQuat.x * a) + (OtherQuat.y * z) - (OtherQuat.z * y); float Y = (OtherQuat.a * y) + (OtherQuat.y * a) + (OtherQuat.z * x) - (OtherQuat.x * z); float Z = (OtherQuat.a * z) + (OtherQuat.z * a) + (OtherQuat.x * y) - (OtherQuat.y * x); Quaternion NewQuat = Quaternion(); NewQuat.a = A; NewQuat.x = X; NewQuat.y = Y; NewQuat.z = Z; return NewQuat; }[/code] Many thanks to you, [b]alvaro[/b]! I otherwise would have just assumed this was beyond my capabilities. The object now rotates easily along all its local axes, no matter what previous rotations took place. Awesome!
7. ## Quaternion Object Rotation

All right, I'll do some more intensive debugging and get back with the results.
8. ## Quaternion Object Rotation

[quote name='alvaro' timestamp='1332426906' post='4924326'] What part of that code is initialization that you do once and what part is something you do in each iteration of the loop? Or do you do all of that every time? [/quote] The input code above is performed every time, assuming a certain flag is true. Rotation is then passed to the entity that is supposed to be rotating. Is that bad? EDIT: Just to be sure, I changed the code such that it is executed regardless of the flag, and the same problem occurs.
9. ## Quaternion Object Rotation

[quote name='alvaro' timestamp='1332426277' post='4924320'] I am not sure what "the problem" is at this stage. If you still haven't solved the issues with the volume of the object changing, you need to renormalize the quaternion periodically (for instance, after each step) by dividing it by its length. Does anything else seem broken? Also, can you explain what you put in Rotation? [/quote] I checked to make sure it was normalizing, and I wasn't normalizing every frame, so I added that in. The result is that the size stays the same (thank you!), but the model only wobbles a bit along the Y and Z axes. To clarify: Holding down Left, which should make it rotate along the Y axis, instead makes it rotate a tiny bit to the left, then a tiny bit to the right, repeatedly, as though the ship were shaking its head. Rotation around the X axis works fine, though. Here is how I fill Rotation: [code] ///Rotation float TurnSpeed = 0.01; sf::Vector3<float> Rotation; Rotation.x = 0.0; Rotation.y = 0.0; Rotation.z = 0.0; //Pitch if (m_App->GetInput().IsKeyDown(sf::Key::Up) == true) { Rotation.x -= TurnSpeed; } if (m_App->GetInput().IsKeyDown(sf::Key::Down) == true) { Rotation.x += TurnSpeed; } //Yaw if (m_App->GetInput().IsKeyDown(sf::Key::Left) == true) { Rotation.y -= TurnSpeed; } if (m_App->GetInput().IsKeyDown(sf::Key::Right) == true) { Rotation.y += TurnSpeed; } //Roll if (m_App->GetInput().IsKeyDown(sf::Key::Q) == true) { Rotation.z -= TurnSpeed; } if (m_App->GetInput().IsKeyDown(sf::Key::E) == true) { Rotation.z += TurnSpeed; }[/code]
10. ## Quaternion Object Rotation

[quote name='alvaro' timestamp='1332425519' post='4924313'] I think you got it. The non-conmutativeness of the quaternion product is not apparent under small angles, so I would start by just ignoring it. [/quote] Okay, so that part works; thanks for the confirm! I've interpreted that as this in my current code: [code] Quaternion xOffset = Quaternion(); Quaternion yOffset = Quaternion(); Quaternion zOffset = Quaternion(); xOffset.FromAxisAngle(Rotation.x, 1.0, 0.0, 0.0); yOffset.FromAxisAngle(Rotation.y, 0.0, 1.0, 0.0); zOffset.FromAxisAngle(Rotation.z, 0.0, 0.0, 1.0); m_Orientation = xOffset * yOffset * zOffset * m_Orientation; m_Orientation.RotationMatrix(m_RotationMatrix);[/code] To clarify: Rotation is basically a vector {x, y, z} where each value represents either a positive, negative or null change, as implied by player input. Currently that change is 0.01. Quaternions are initialized as identity quaternions (so {a, x, y, z} = {1, 0, 0, 0}), but that data is overwritten in FromAxisAngle(...), so that shouldn't be an issue. So if that part of my code is correct, what could be causing the problem? m_RotationMatrix is a GLfloat[16], stored in column-major format (I think that's what it's called - the first 4 floats represent the first column, etc.), so that should be okay. Should I be using something other than glMultMatrix()?
11. ## Quaternion Object Rotation

[quote name='alvaro' timestamp='1332421825' post='4924289'] If you want to do 6DOF movement using quaternions, do *not* use roll, pitch and yaw. You want to take the user's input and apply small incremental rotations along the three axes to the existing quaternion. Does that make sense? [/quote] Hm... So say the user wants the ship to pitch down a little (relative to the ship's previous orientation, not global orientation). What confuses me is "apply rotations." I take that to mean: 1. Create a quaternion [b]qPitch [/b]from an axis-angle value where the Axis = [b]{1.0, 0.0, 0.0}[/b] and the Angle is, for example, [b]0.1[/b] 2. Multiply qPitch by m_Orientation, the current orientation of the ship, so [b]m_Orientation = qPitch * m_Orientation[/b] Does that sound right? That has been my intuition up until now, so I assume it's wrong, but I'm not quite sure in what way. Also, because quaternion multiplications are noncommutative, I've been worried about extending this approach to all three possible axes at once, since the order in which I multiply them will determine the kind of result I get - although I want all rotations to be relative to local axes. It seems that any order I put them in will shortchange one of the axes or another.
12. ## Quaternion Object Rotation

Nobody? I've tried all sorts of things, and nothing has worked. I've tried adding input directly to stored Euler angles and simply creating a new quaternion each time, but that results in rotations around global axes with no regard to local axes. [code]m_Rotation.x += Rotation.x; m_Rotation.y += Rotation.y; m_Rotation.z += Rotation.z; m_Orientation.FromPYR(m_Rotation.x, m_Rotation.y, m_Rotation.z); m_Orientation.RotationMatrix(m_RotationMatrix);[/code] I've tried passing input as axis-angle and creating offset quaternions with those, multiplying them into the main orientation, but this results in extremely fast rotation around the X axis and explosive scaling or near-invisible shivering along the y and z axes. [code]xOffset.FromAxisAngle(Rotation.x, 1.0, 0.0, 0.0); yOffset.FromAxisAngle(Rotation.y, 0.0, 1.0, 0.0); zOffset.FromAxisAngle(Rotation.z, 0.0, 0.0, 1.0); m_Orientation = xOffset * yOffset * zOffset * m_Orientation; m_Orientation.RotationMatrix(m_RotationMatrix);[/code] I've tried directly making an offest quaternion from the entire PYR input, but the roll command makes the plane pitch and everything else just makes it wobble ever so slightly. [code]Quaternion Change = Quaternion(); Change.FromPYR(Rotation.x, Rotation.y, Rotation.z); m_Orientation = Change * m_Orientation; m_Orientation.RotationMatrix(m_RotationMatrix);[/code] What other ways are there to transform input into quaternions? I have to use Pitch-Yaw-Roll because that's ultimately what players will be using their input as - mouse left-right for yaw, mouse up-down for pitch, and Q and E for roll (I'm copying the flight controls from [i]Star Wars: Battlefront II[/i]). I can't get away from Euler angles, or at least not from a Pitch-Yaw-Roll scheme. How do I do this? Also, please note that the objects have to rotate [i]independently [/i]of the camera. I've tried all sorts of tutorials: [url="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm"]http://www.euclidean...forms/index.htm[/url] [url="http://www.idevgames.com/articles/quaternions"]http://www.idevgames...les/quaternions[/url] [url="http://www.cprogramming.com/tutorial/3d/quaternions.html"]http://www.cprogramm...uaternions.html[/url] [url="http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Quaternions.html"]http://www.arcsynthe...uaternions.html[/url] But none of them cover implementation in a way I can grok. They mostly cover the mathematical operations for using quaternions, which I think I've already got. I would have thought just converting the PYR rotation to a quaternion and multiplying that with the orientation would work, but it doesn't, and I don't know where to go from here. EDIT: Just in case my quaternion math [i]is [/i]wrong, here are some parts of my Quaternion class: From [url="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm"]http://www.euclidean...rnion/index.htm[/url]: [code]void Quaternion::FromPYR(float Pitch, float Yaw, float Roll) { //Set Pi float Pi = 4 * atan(1); //Set the values, which came in degrees, to radians float rYaw = Yaw * Pi / 180; float rPitch = Pitch * Pi / 180; float rRoll = Roll * Pi / 180; //Components float C1 = cos(rYaw / 2); float C2 = cos(rPitch / 2); float C3 = cos(rRoll / 2); float S1 = sin(rYaw / 2); float S2 = sin(rPitch / 2); float S3 = sin(rRoll / 2); //Remember to convert A to degrees again a = ((C1 * C2 * C3) - (S1 * S2 * S3)); x = (S1 * S2 * C3) + (C1 * C2 * S3); y = (S1 * C2 * C3) + (C1 * S2 * S3); z = (C1 * S2 * C3) - (S1 * C2 * S3); //Normalize Normalize(); }[/code] From [url="http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm"]http://www.euclidean...rnion/index.htm[/url]: [code]//Rebuilds this quaternion using an angle and a rotation axis void Quaternion::FromAxisAngle(float Angle, float xAxis, float yAxis, float zAxis) { //Angle should be in radians a = cos(Angle/2); //Axes x = xAxis * sin(Angle/2); y = yAxis * sin(Angle/2); z = zAxis * sin(Angle/2); //Normalize Normalize(); }[/code] From [url="http://www.idevgames.com/articles/quaternions"]http://www.idevgames...les/quaternions[/url] [code]void Quaternion::RotationMatrix(GLfloat* Matrix) { //Column 1 Matrix[0] = 1.0 - (2.0*((y*y) + (z*z))); Matrix[1] = 2.0*((x*y) + (a*z)); Matrix[2] = 2.0*((x*z) - (a*y)); Matrix[3] = 0.0; //Column 2 Matrix[4] = 2.0*((x*y) - (a*z)); Matrix[5] = 1.0 - (2.0*((x*x) + (z*z))); Matrix[6] = 2.0*((y*z) + (a*x)); Matrix[7] = 0.0; //Column 3 Matrix[8] = 2.0*((x*z) + (a*y)); Matrix[9] = 2.0*((y*z) - (a*x)); Matrix[10] = 1.0 - (2.0*((x*x) + (y*y))); Matrix[11] = 0.0; //Column 4 Matrix[12] = 0.0; Matrix[13] = 0.0; Matrix[14] = 0.0; Matrix[15] = 1.0; }[/code]
13. ## Quaternion Object Rotation

Actually, I'm deriving a rotation matrix from the quaternion each time the quaternion is modified, and then multiplying the object's view matrix by that rotation matrix upon rendering. I've heard that reduces the issues you can sometimes get where some rotations continue to be around the global rather than local axes. Originlally I had reconverted them to Euler angles, and that was the problem I got. For example, for a given order, if I rotated along the X axis and then tried to rotate alone the Y axis, the Y rotation would still take place along the global axis. Which axes were a problem changed depending on the order, but there was no order that removed the problem entirely. This is how I render the VBO's transformations: [code]glPushMatrix(); //Apply transformations glTranslatef(m_Position.x, m_Position.y, m_Position.z); glMultMatrixf(m_RotationMatrix); //(...) VBO rendering code glPopMatrix();[/code]
14. ## Quaternion Object Rotation

So I'm trying to code something similar to a 3D space sim, where I want six degrees of freedom. Apparently the best way to achieve 6DoF is with quaternions, so I've spent the last two days reading up about them and trying to get some code to work. I am using SFML 1.6 and OpenGL, nothing else. I have a Quaternion class that I'm fairly certain is mathematically correct, and can create a quaternion from an axis and an angle; it normalizes itself, and the multiplication operator is overloaded to perform a proper multiplication. However, don't understand how to transform the player's input into a quaternion representing a change in rotation. The player can input changes into the Pitch, Yaw and Roll, potentially all three at once. The object they are controlling is supposed to then rotate according to this input along its LOCAL axes. Suppose the player wanted to change the Pitch by 30°, the Yaw by 45° and the Roll by 10° all at the same time (I'm using that example because it's the most complex possible situation my code will have to deal with). So I have these nice little values, 30-45-10 (which I could also convert to radians), but what do I do with them? I've read dozens of tutorials, and what little I can make sense of them seems to indicate I need to make the change quaternion like this (pseudocode): [code]Qaternion xChange = Quaternion.FromAxisAngle(30, 1, 0, 0); Qaternion yChange = Quaternion.FromAxisAngle(45, 0, 1, 0); Qaternion zChange = Quaternion.FromAxisAngle(10, 0, 0, 1); Qaternion totalChange = zChange * yChange * xChange;[/code] Where FromAxisAngle takes the parameters (float Angle, float X, float Y, float Z). Then I apparently need to perform this on the object's current Orientation, also a quaternion: [code]Orientation = totalChange * Orientation;[/code] And finally derive a matrix from Orientation and pass that to glMultMatrix(). Unfortunately, my current code doesn't really work. Trying to change the yaw or roll just makes the object shiver, and trying to change the pitch makes the object spin correctly for a moment and then start to roll and grow enormously large at the same time. The thing is, deep down I know my code shouldn't work, because quaternion multiplications are non-commutative. I can't just willy-nilly multiply quaternions for three different orientations with one another - the order will end up influencing the result, right? What do I do when a particular axis isn't supposed to be rotating at the moment? I've got this not-working system in place, but I've tried half a dozen other configurations that don't work either. Rotation is the user-input rotation around the X,Y,Z axes respectively. I'n not doing any translation at the moment. [code]void Entity::Transform(sf::Vector3<float> Translation, sf::Vector3<float> Rotation) { if (Rotation.x != 0) { Quaternion Offset = Quaternion(); Offset.FromAxisAngle(Rotation.x, 1, 0, 0); m_Orientation = Offset * m_Orientation; } if (Rotation.y != 0) { Quaternion Offset = Quaternion(); Offset.FromAxisAngle(Rotation.y, 0, 1, 0); m_Orientation = Offset * m_Orientation; } if (Rotation.z != 0) { Quaternion Offset = Quaternion(); Offset.FromAxisAngle(Rotation.z, 0, 0, 1); m_Orientation = Offset * m_Orientation; } //Derive a rotation matrix m_Orientation.RotationMatrix(m_RotationMatrix); } [/code] Can somebody tell me how I'm supposed to transform my player input into the appropriate quaternion transformations? Note that I've also tried directly creating a quaternion from stored PYR variables, but this didn't work and I was told by someone reading my code that that was the wrong way to implement this sort of thing (unfortunately, his explanation of the right way to do it was extremely vague, at least to me).