[SOLVED] Quaternion - Vector multiplication?

I’m still trying to get skeleton animation working, but first I need to be able to load a model.

At first I was like “WHAT THE HELL IS THIS?!”. Then I was like “Oh, this actually kind of makes sense!”. Then I was like “WHAT THE HECK IS A QUATERNION?!”. Then I was like “Haha! There’s a Quaternion class in LWJGL!”.
Then my example code was like

vec3 rotPos = joint.m_Orient * weight.m_Pos; //m_Orient is a quaternion

and I was like “NO WAI YOU DID NOT JUST DO THAT” and it was like “Oh, yes, I did.” and I was like “But there is no quaternion-vector multiplication function in the LWJGL classes!” and it was like “Well, screw you.” Then Google was like “Did ya mean quaternion-quaternion multiplication X 1 000 000?” and I was like “NO.” and then, well, here I am.

So, how do I multiply a quaternion and a vector to get a new magical vector?

I assume that your question is “how do I rotate a vector by a quaternion that represents a rotation?” Because there’s more that one meaning of multiple a vector by a quaternion. If so, the the answer depends on how many vectors you want to rotate since there are multiple formulations.

LWJGL’s Quaternion class is … well it just isn’t very good. I’m not sure it even has a method to transform a Vector.

Java3D has a much more fully-featured quaternion class. You can find it here though you might want to find an alternative implementation with source both for licensing and documentation reasons (that one doesn’t even have a javadoc artifact)

You’re exactly right. I want to rotate my position vector by the orientation quaternion. What do you mean by multiple formulations?

Also, this seems to be the relevant code in the C-something file:


   inline detail::tvec3<T> operator* 
	(
		detail::tquat<T> const & q, 
		detail::tvec3<T> const & v
	)
	{
		typename detail::tquat<T>::value_type Two(2);

		detail::tvec3<T> uv, uuv;
		detail::tvec3<T> QuatVector(q.x, q.y, q.z);
		uv = glm::cross(QuatVector, v);
		uuv = glm::cross(QuatVector, uv);
		uv *= (Two * q.w); 
		uuv *= Two; 

		return v + uv + uuv;
	}

I have no idea what this means though…

I looked at the javadoc for that library, but I couldn’t find a function for that either…

I’m not at home, so here’s a quick answer off the top of my head. (In other words, it probably doesn’t work so verify it)


public final Vect3f rot(Vect3f v)
{
  float  k0 = w*w - 0.5f;
  float  k1;
  float  rx,ry,rz;

  // k1 = Q.V
  k1    = v.x*x;
  k1   += v.y*y;
  k1   += v.z*z;

  // (qq-1/2)V+(Q.V)Q
  rx  = v.x*k0 + x*k1;
  ry  = v.y*k0 + y*k1;
  rz  = v.z*k0 + z*k1;

  // (Q.V)Q+(qq-1/2)V+q(QxV)
  rx += w*(y*v.z-z*v.y);
  ry += w*(z*v.x-x*v.z);
  rz += w*(x*v.y-y*v.x);

  //  2((Q.V)Q+(qq-1/2)V+q(QxV))
  rx += rx;
  ry += ry;
  rz += rz;

  return new Vect3f(rx,ry,rz);
}

There are three main ways to have a quaternion represent a rotation. Each of these can be “reversed” yielding six formulations with different properties (they are all related). Given a specific mathematical formulation, each of may be used directly as if one was performing the operation in quaternions or it can be converted to some other mathematical type (almost always a matrix). The above (assuming I didn’t screw up) is a direct formulation where the quaternion is assume to be of unit length (otherwise it will yield a scaled rotation, where the scaling factor is the magnitude of the quaternion squared). This question and your previous are really the same “in wolves clothing”. If you were to pug the vectors (1,0,0), (0,1,0), & (0,0,1) into the above it will yield three vectors (really every where we’re saying vectors should be bivectors, but that’s a different story). Shove these three vectors into either a row or column of a matrix and you have the (misnamed) quaternion to matrix conversion. Make it a 4x4 matrix and you can shove the translation vector in the appropriate spot and bingo…you’re done.

It doesn’t really do anything and was obviously thrown together by someone with no understanding of quaternions (no offense intended if said person is reading this…you’re far from alone.)

That was exactly what I needed! Thanks a lot! I also look forward to actually understanding that code when I get to college… >_>

“Take this appreciation! It’s been in my family for years, but I feel that you should have it.”

These two might be helpful…
https://code.google.com/p/libgdx/source/browse/trunk/gdx/src/com/badlogic/gdx/math/Vector3.java
https://code.google.com/p/libgdx/source/browse/trunk/gdx/src/com/badlogic/gdx/math/Quaternion.java#170

Nate: You might want to add comments to methods which are not thread-safe.

Those tmp variables looked really bad, but were they actually used somewhere in the code?

I only use quaternion to interpolate rotation. When I have I have compute all rotations, I transform quaternions to matrices. Then I only use matrix. I have never use quaternion with vector directly.

The sweet point between direct computation and conversion to a matrix is hard to qualify. For scalar computation converting to matrices generally be a win past some very small number of conversions. For SIMD it really depends on the low level ops exposed.

@theagentd: I just skimmed…didn’t look that closely.

Opps…I was actually thinking of some other library…I guess I should check my facts before opening my mouth.