39

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) ...


24

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 * ...


14

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 it ...


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

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 ...


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));


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

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

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 ...


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

A more generic approach is detailed on Wikipedia. Essentially, that article explains there's no non-iterative method to find the generalized combination of N quaternions with weigths w_i. Nevertheless, if you can supply an approximation of that quaternion "mean", you can iteratively refine it using these update equations: So you could start with m_0 as ...


6

A quaternion can be thought of as an angle-axis representation: quaternion.xyz = sin(angle/2) * axis.xyz quaternion.w = cos(angle/2) So, converting them between two coordinate systems can be broken down into two steps: Map the axis into the new coordinate system. If changing between left & right hand coordinates (eg. if there's an odd number of axis ...


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

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

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

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

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

This is a late response, but I figured this question illustrates a common problem that many people are likely to run into and that deserves an answer. Quaternion rotation uses half the angle you want to rotate by. Since you (in this example case) are rotating by 90 degrees, the quaternion needs to calculate the sine and cosine of 45 degrees, both of which ...


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 ...


4

Since it seems acceptable, I’ll go for the following suggestion: just interpolate the quaternion components, then normalise the resulting quaternion. pro: it’s fast and the code is short pro: and there is no need to handle the case when the angle reaches 360 degrees and warps back to zero. con: you can still get singularities if the quaternions aren’t ...


4

The three component vectors right, up, and forward probably point along the axes x, y, and z relative to the camera. So by adding these vectors together you can compose any other vector. It works the same as if you built a vector by specifying its three elements individually, except that you are adding three vectors which each have one non-zero element. ...


4

It depends on the coordinate system you're working in. In a right-handed coordinate system (eg. x right, y up, z points toward the viewer), the right-hand rule applies, as mklingen describes in the existing answer. In a left-handed coordinate system (eg. x right, y up, z points away from the viewer), the left-hand rule applies - you point your left thumb ...


4

Rounding. If you attach the debugger and look at the values of your quaternion: You'll see that the values are just too small to be displayed with one tenth precision, as the debug value is displayed. You can confirm this by looking at: Debug.Log(LeftTurnLimit.eulerAngles); This will output the initial value you put in : 0.1, 0, 0 To address the ...


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