Align to velocity vector using Quaternions

Started by
19 comments, last by nardove 14 years, 2 months ago
The jellyfish looks good! Is that your doing? If so, what mechanism are you using to animate the tentacles?

The little 'spins' that it does are actually kind of neat, but I'm guessing they're not intentional :) Anyway, for this type of motion I would definitely recommend accumulated relative rotations. To keep things simple, I'll skip the quaternion-specific version of the algorithm and just describe the straightforward version. In pseudocode, it looks something like this (typed directly into the post, and not tested in any way):
// Somewhere during initialization:quaternion q = whatever_you_want_the_initial_orientation_to_be();// For each update:matrix m = matrix_from_quaternion(q);vector3 forward = m.get_third_basis_vector(); // Ask if you're not sure what this meansvector3 desired_forward = normalize(velocity);vector3 axis = cross(forward, desired_forward);float length = axis.length();if (length > epsilon) {    axis /= length;    float angle = atan2(length, dot(forward, desired_forward));    quaternion rotation = quaternion_from_axis_angle(axis, angle);    q = rotation * q;    q.normalize();}
I think that's about the best advice I can offer at this point. If you have questions about the above pseudocode though, feel free to ask.
Advertisement
Thanks for the comments, the tentacles are a set of springs, most of the code I use a very good set of Java libraries from here http://toxiclibs.org/docs/core/ it does help me a lot to get all the crazy 3D formulas in to simple methods

So I try to translate your pseudocode to this

first initialize the variables

Quaternion quat = new Quaternion(1.0, 0.0, 0.0, 0.0);
Quaternion rotationQuat;
Matrix4x4 mat;

for the update

// INI CODE

mat = quat.getMatrix();

Vec3D forward = new Vec3D((float)mat.matrix[0][2],
(float)mat.matrix[1][2],
(float)mat.matrix[2][2]);

Vec3D desired_forward = forward.normalize();
Vec3D axis = forward.cross(desired_forward);
float leng = axis.magnitude();

if (leng > EPSILON) {
axis.scaleSelf(1.0 / leng);
float angle = atan2(leng, forward.dot(desired_forward));
rotationQuat = new Quaternion();
rotationQuat.createFromAxisAngle(axis, angle);
quat = quat.multiply(rotationQuat);
quat.normalize();
}

// perform transformation
pushMatrix();
// update location
translate(location.x, location.y, location.z);
// orientation to velocity
rotate(rotationQuat.w, rotationQuat.x, rotationQuat.y, rotationQuat.z);

agent.display();

popMatrix();

// END CODE

But I get rotationQuat = NULL

Any ideas?

Cheers
rS
Couple of things. First, you can use [ source ] tags (no spaces) when posting to get one of those nice little code boxes. Ok, on to the code. This:
Vec3D forward = new Vec3D((float)mat.matrix[0][2],(float)mat.matrix[1][2],(float)mat.matrix[2][2]);
Is probably right, but just be sure that your matrices are actually column-basis matrices (as opposed to having the basis vectors in the rows). Next, take a look at this line:
Vec3D desired_forward = forward.normalize();
And see if you can spot any difference between it and the corresponding line in the pseudocode I posted earlier.

Lastly, this:
rotate(rotationQuat.w, rotationQuat.x, rotationQuat.y, rotationQuat.z);
Looks a little suspicious. I don't know what your rotate() function does, but keep in mind that although a quaternion encodes an axis-angle rotation, under normal circumstances its elements cannot directly be interpreted as an axis-angle pair. (Typically, what you would do here is convert the quaternion to a matrix, and then upload the matrix to the graphics API.)
Hello, [ source ] hey lets give it a try ;) I am new to the forum and didn't find those tags, OK so I change the line

Vec3D desired_forward = velocity.normalize();


It is way better this way, sorry for the old ones

Now when I print the rotationQuat instead of Null I get axis: [0.0,0.0,0.0], w: 1.0 constantly any ideas?

And I think you are right after I get the rotationQuat I will need to gt a rotation matrix, bu tI need to fix the logic first

Cheers
rS
It looks like there is something wrong with the createFromAxisAngle method I use to build the rotationQuat, I will check it out and let you know, if it doesnt work I will have to do it manually

Cheers
rS
1. Does createFromAxisAngle() expect the angle in radians or degrees?

2. Does atan2() return the angle in radians or degrees?

3. What is the value of EPSILON?

4. What do you see if you also print out the values of 'axis' and 'angle'?

[Edit: If there's something wrong with createFromAxisAngle(), that could explain it. If you have access to the code for that function, you might post it.]
Hi jyk,

Everything is radians

EPSILON = 1.0E-4

...

length: 0.8714546
angle: 1.05816
axis: {x:1.6277998E-8, y:0.9906332, z:0.13654976}
rotationQuat: {axis: [0.0,0.0,0.0], w: 1.0}

length: 0.86895746
angle: 1.0530915
axis: {x:1.6521371E-8, y:0.99034965, z:0.13859132}
rotationQuat: {axis: [0.0,0.0,0.0], w: 1.0}

...


The library is a .jar file not sure how/if is possible to look inside

I am still testing and throwing arrows like crazy

Cheers
rS
Quote:length: 0.8714546
angle: 1.05816
axis: {x:1.6277998E-8, y:0.9906332, z:0.13654976}
rotationQuat: {axis: [0.0,0.0,0.0], w: 1.0}

length: 0.86895746
angle: 1.0530915
axis: {x:1.6521371E-8, y:0.99034965, z:0.13859132}
rotationQuat: {axis: [0.0,0.0,0.0], w: 1.0}
With those axis-angle values, you shouldn't be getting an identity quaternion. What math library are you using? Can you post a link to the documentation?

(Also, as a side note, it's a bit inaccurate to label the the x, y, and z elements of a quaternion as the 'axis'. When a quaternion is used to represent a rotation, these elements are related to the axis of rotation, but they are not equivalent to the axis of rotation.)
Documentation can be found here http://toxiclibs.org/docs/core/

Whate are the [ tags ] for a url?

rS
Quote:Original post by nardove
Documentation can be found here http://toxiclibs.org/docs/core/

Whate are the [ tags ] for a url?

rS
For URLs, use the HTML 'a' element along with the 'href' attribute to create clickable links.

It looks to me like createFromAxisAngle() is a static member function that returns a new quaternion, but it doesn't look like you're doing anything with the return value. I imagine this is why your quaternion is coming out as identity.

This topic is closed to new replies.

Advertisement