问题
I have a projectile object that is moving along a velocity vector. I need to ensure that the object is always facing in the direction of the velocity vector. Furthermore, I am representing object rotation using quaternions, not matrices.
I know that the first step is to find an orthogonal basis:
forward = direction of velocity vector
up = vector.new(0, 1, 0)
right = cross(up, forward)
up = cross(forward, right)
How might I convert the basis into a rotation quaternion?
Solution
Note, I'd like to give credit to Noel Hughes for providing the answer, but I want to clarify with my own experiences. Pseudocode follows:
vec3 vel = direction of velocity vector
vec3 forward = (1, 0, 0) // Depends on direction your model faces. See below.
vec3 axis = cross(forward, vel)
if (axis == 0) then quit // Already facing the right direction!
axis = normalize(axis)
float theta = acos(vel.x/sqrt(vel.x^2, vel.y^2, vel.z^2))
quat result = (0, axis.y * sin(theta/2), axis.z * sin(theta/2), cos(theta/2)
The last element of the quaternion is the scalar part, the first three elements are the imaginary parts. Also, the above pseudocode assumes that your object in "model space" points down the positive x-axis. In my case, the object actually pointed down the positive y-axis, in which case I made the following changes:
vec3 vel = direction of velocity vector
vec3 forward = (0, 1, 0) // Note that y-component is now 1
vec3 axis = cross(forward, vel)
if (axis == 0) then quit
axis = normalize(axis)
float theta = acos(vel.x/sqrt(vel.x^2, vel.y^2, vel.z^2))
quat result = (axis.x * sin(theta/2), 0, axis.z * sin(theta/2), cos(theta/2)
// Note that SECOND component above is now 0
回答1:
I assume you don't care about the orientation of your projectile, other than having the longitudinal axis aligned with the velocity vector, and that the longitudinal axis is the x axis of (1, 0, 0).
You are on the right track. Normalize the velocity vector, (vx, vy, vz)/sqrt(vx^2 + vy^2 + vz^2) cross the x axis with it and normalize the result - (0, yn, zn) - this is the rotation axis for the quaternion. The rotation angle is simply theta = inverse cosine of vx/sqrt(vx^2 + vy^2 + vz^2). The resultant quaternion is then
(0, yn, zn)sn(theta/2) cos(theta/2)
Let me know if you have any questions.
Noel Hughes nhughes1ster@gmail.com
回答2:
I'd have a look at the vecmath library (Java). It's been around a long time and we use it in our community. It's based on 4-tuples and I would be disappointed if there weren't straightforward methods for the transformation.
I'd also write unit tests for the expected outcomes. It is very easy to muddle positive and negative, left- and right-handed, and movinig/reference frames. Start with the simple ones (e.g. xyz) to make sure you have the right answer.
来源:https://stackoverflow.com/questions/1620130/quaternion-from-orthogonal-basis