37

As Nathan Reed and teodron exposed, the recipe for rotating a vector v by a unit-length quaternion q is: 1) Create a pure quaternion p out of v. This simply means adding a fourth coordinate of 0: $$p = (v_x, v_y, v_z, 0) \Leftrightarrow p = (v, 0)$$ 2) Pre-multiply it with q and post-multiply it with the conjugate q*: $$p' = q \times p \times q*$$ 3) ...


23

Quaternions solve a few problems elegantly: They are as compact as axis-angle representations (4 scalar values) They are easily converted to and from matrix representations Interpolation works from any start to end angle without special casing They never exhibit gimbal lock You can get around these issues with other representations, but quaternions are a ...


23

Multiplication At least in terms of Unity's implementation of Quaternions, the multiplication order described in the question is not correct. This is important because 3D rotation is not commutative. So, if I want to rotate an object by rotationChange starting from its currentOrientation I'd write it like this: Quaternion newOrientation = rotationChange * ...


16

You could decompose your quaternion into a yaw/pitch/roll set of angles, but that's overkill usually. Instead of composing your quaternions like this: cameraOrientation = cameraOrientation * framePitch * frameYaw; Try this: cameraOrientation = framePitch * cameraOrientation * frameYaw; It will then never generate tilt/roll and is equivalent to storing ...


13

Where's the dot product used? In Unity, one of the most common users of the dot product is whenever you check if two quaternions are equal via == or !=. Unity computes the dot product to check similarity rather than directly comparing the internal x,y,z,w values. It's worth keeping this one in mind as it makes the call more expensive than you might expect ...


12

Given only a point and a direction there is no defined 'right' or 'left'. Imagine being a falling raindrop, which direction is right or left for you in that case? In order to calculate (or even define) a right or left you need two directions, typically forward and up. You seem to already have a forward direction, so you need to define a up direction. ...


11

You should probably use glm::angleAxis() (documentation here): glm::quat rot = glm::angleAxis(glm::radians(90.f), glm::vec3(0.f, 1.f, 0.f));


10

One of the visualization methods I like is to represent quaternion (orientation in 3d space) as vector (x,y,z components) + spin (the rotation around that vector, stored in w component). If you are looking for some online visualizer for quaternions, you can always use wolframalpha: http://www.wolframalpha.com/input/?i=quaternion%3A+0%2B2i-j-3k&lk=3 ...


8

This is a problem I had for a while, and I couldn't find any answers for, so I thought I would post it here. It is actually quite simple. How you are most likely doing the rotations is like this: currentDirection * newRotation; But, doing it like this doesn't work either. newRotation * currentDirection; What you have to do, is do it in the first order ...


8

You are correct that a combined axis-angle representation like the one you describe has a stronger expressive power than many other systems because it can more conveniently store a rotation speed. However, in practice, people actually use quaternions and 3×3 matrices to manipulate rotations a lot more than just represent them. One typical operation is the ...


7

First of all, q^(-1) is not -q/magnitude(q); it's q*/(magnitude(q))^2 (q* is the conjugate; that negates all the components except the real one). Of course, you can leave off the division by the magnitude if all your quaternions are normalized already, which they typically would be in a rotation system. As for the multiplication with a vector, you just ...


7

It seems that most engines do have those rotation methods. XNA has one in it's Vector3 struct. // Returns a new Vector3 that results from the rotation. public static Vector3 Transform ( Vector3 value, Quaternion rotation ) three.js has the function exactly as you wrote it. In Unity's case, their Vector3.Rotate() method might be internally ...


7

I can think of two reasons: if your quats represent infinitesimal rotations, adding them together actually yields the composite rotation, provided the result is infinitesimal too (i.e. an element of that algebraic group). Quaternion addition, as opposed to multiplication, is commutative and, well, numerically fast. One situation where this might be "a thing"...


6

1) The non-scary way to do 90-degree rotations is to swap a set of axes, and negate one of them: Rotated along x-axis: swap Y/Z to Z/-Y (a,b,c) -> (a,c,-b)


6

The problem is neither of the conversion functions, the problem is the input matrix. It is not an affine transformation matrix, because the rotational part is not a pure rotation matrix, it has one or more flipping/negated axis in it. Only Rotation matrices can be converted to quaternions. More specifically rotation matrices are orthogonal matrices with ...


5

If your Vector3 stores an euler angle (yaw, pitch, roll) you can use the following static method directly: Quaternion quaternion = Quaternion.CreateFromYawPitchRoll(vector.X, vector.Y, vector.Z); On the other hand, if you're not storing an euler angle, but just the direction (or forward vector) of the camera/object, then bear in mind that generally a ...


5

First observation: The inverse of q is not -q/magnitude(q), that is completely wrong. Rotations with quaternions imply that these 4D complex number equivalents have unitary norm, hence lie on the S3 unit sphere in that 4D space. The fact that a quat is unitary means that its norm is norm(q)^2=q*conjugate(q)=1 and that means that the quat's inverse is its ...


5

Although rotation-matrices and unit-quaternions both can represent an orientation/rotation in 3D space, that does not mean that negating each of its individual terms will result in the same geometrical operation. 1. Negating each number of a unit-quaternion There are always 2 unit-quaternions that represent a single unique orientation. One on each ...


5

For an FPS camera you usually don't want roll and are limited to +/- 90 degrees pitch, so I'd just keep track of the current state using yaw and pitch angles. The full power of quaternions isn't really helpful for this. You can still convert the yaw/pitch angles to and from quaternions in case you want to transition between the FPS camera and animated ...


5

Expressing rotations with quaternions can be done from an axis-angle representation, but not in a single way. For that same axis angle (w, a) pair, you get two quaternions performing the same task. One has its components based directly on the w vector and the a angle, the other has the same components, but negated. This is normal, since they describe the ...


5

Rotating a point p using a quaternion q is done with q * [0, p] / q. Replacing q with -q has absolutely no effect on the result. If your rotations "go the wrong direction" when the sign of the quaternion changes, then the problem lies in the way you use the quaternions to rotate points.


5

Actually, it turns out that you can't have it 'both ways': if your intention is to not have any sense of 'absolute orientation' on the sphere (that is, if the players aren't always e.g. facing towards the poles), then you'll need to have a notion of player orientation. This is because, contrary to what intuition might suggest, movement on the sphere is not ...


5

Your problem is purely two-dimensional, in the plane formed by the sphere centre and your source and destination points. Using quaternions is actually making things more complex, because in addition to a position on a 3D sphere, a quaternion encodes an orientation. You may already have something to interpolate on a circle, but just in case, here is some ...


5

rotationVelocity += addedRotation is actually fine. Angular velocity is a vector and adds in the usual way. The part you may be missing is that in your description of the desired motion, you have a rotation around a constant axis (the global up-vector) combined with a rotation about a rotating axis (the ship's roll axis, which is rotating because of the ...


5

Each orientation in 3D space can be represented by 2 distinct unit quaternions, q and -q (component-wise negated q). For instance the orientation represented by the 3x3 identity matrix I can be represented by 2 quaternions: q: { 0, 0, 0}, 1 -q: {-0, -0, -0}, -1 Both represent the same orientation in 3D space, their dot product is exactly -1, each of ...


5

"Is it wrong that I am counting total rotation and then creating [a] quaternion from it?" Yes, because rotations do not combine like simple addition. (In mathematical terms, rotations in three dimensions are not commutative) Here's an example you can do with any old mug. Turn it 90 degrees on the vertical axis, then flip it over away from you (finish ...


5

Euler angles aren't necessarily a good way of expressing limits over arbitrary ranges, as their behaviour close to zero is very different from their behaviour away from zero. Below I've visualized the forward, right, and up vectors of an object rotated with Euler angles over various ranges. Here yaw ∈ [-50, 50] and roll ∈ [-10, 10]. From left to right, I ...


4

You should really be storing the component vectors (rotation, translation, scale, velocity, etc.) in addition to the matrix and quaternion forms. Not only does that eliminate the problem your having, it reduces compound numerical errors that come up over time from floating point limits.


4

What you are looking for is the LookAt algorithm. OpenGL already has that in a nice function: gluLookAt, although it multiplies the current matrix instead of returning it to you so you may need some push/pop trickery to get at it. If you want to do it yourself, there are two ways; by constructing a transformation matrix, or by using quaternions. Here's the ...


4

Store a direction vector as a tangent to the sphere. When you move, you can take this tangent, the normal vector (normalized position on the sphere) and cross them to get a general axis to rotate around. If you're limiting all movement to a single 2D plane (you're just using a single angle), for direction all you need is a sign (+1 or -1) to multiply your ...


Only top voted, non community-wiki answers of a minimum length are eligible