Archived

This topic is now archived and is closed to further replies.

Floating

How is a point transformed by a quaternion?

Recommended Posts

/*
v'' = q * v * q^-1
(q^-1 is the inverse or conjugate of q)
i.e. two quaternion multiplications, with v treated as a quaternion (0, vx, vy, vz)
*/
inline vector3 RotateByQuaternion( const quaternion& q, const vector3& v )
{
float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
x2 = q.x + q.x; y2 = q.y + q.y; z2 = q.z + q.z;

xx = q.x * x2; xy = q.x * y2; xz = q.x * z2;
yy = q.y * y2; yz = q.y * z2; zz = q.z * z2;
wx = q.w * x2; wy = q.w * y2; wz = q.w * z2;

vector3 Res( v.x - v.x * (yy + zz) + v.y * (xy - wz) + v.z * (xz + wy),
v.y + v.x * (xy + wz) - v.y * (xx + zz) + v.z * (yz - wx),
v.z + v.x * (xz - wy) + v.y * (yz + wx) - v.z * (xx + yy) );
// 18 mul, 21 add, 12 - ïåðåìåííûõ
#ifdef _DEBUG
quaternion cq = q ;
ASSERT( QuaternionValid( cq ) );

{ // second method
quaternion q0(v.x * q.w + v.z * q.y - v.y * q.z,
v.y * q.w + v.x * q.z - v.z * q.x,
v.z * q.w + v.y * q.x - v.x * q.y,
v.x * q.x + v.y * q.y + v.z * q.z);

vector3 Res2(q.w * q0.x + q.x * q0.w + q.y * q0.z - q.z * q0.y,
q.w * q0.y + q.y * q0.w + q.z * q0.x - q.x * q0.z,
q.w * q0.z + q.z * q0.w + q.x * q0.y - q.y * q0.x);
// 24 muls, 20 adds, 4 ïåðåìåííûå
ASSERT(Res2.isequal( Res, 0.001f*v.len() ) );
}

{
//refrence method
quaternion vq( v.x, v.y, v.z, 0 );
quaternion iq( q );
iq.conjugate();
quaternion vres = (q * vq) * iq;
vector3 RefRes( vres.x, vres.y ,vres.z );
ASSERT(RefRes.isequal( Res, 0.00001f*v.len() ) );
}

{ // matrix code check
matrix33 M(q);
vector3 MR( M*v );
ASSERT( MR.isequal(Res,0.00001f*v.len() ) );
}

#endif
return Res;
}
//------------------------------------------------------------------

Share this post


Link to post
Share on other sites
Thanks minorlogic!

Now I have seen sometimes that instead of having p=(0,x,y,z), p=(1,x,y,z). Does it have the same effect? I tried both and I couldn''t notice any difference.

Share this post


Link to post
Share on other sites
That's coz (0,0,0,1) is the identity quaternion (I)
thus for any q and its inverse p :

q*(0,0,0,1)*p = q*p = (0,0,0,1) = I

now :
q*(x,y,z,1)*p = q*((x,y,z,0)+I)*p = ( q*(x,y,z,0) + q*I )*p // linearity
= q*(x,y,z,0)*p + q*I*p = q*(x,y,z,0)*p + I

So if (x',y',z',0) = q*(x,y,z,0)*p

then q*(x,y,z,1)*p = (x',y',z',0) + (0,0,0,1) = (x',y',z',1)

So considering the first 3 coordinates nothing changes and w remains intact. so this can be 0, 1 or any other value. That effectively changes nothing except smaller formulas when you develop with 0 (simplification) I suppose.

[edited by - Charles B on July 4, 2003 7:01:09 PM]

Share this post


Link to post
Share on other sites