Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

quaternion difficulties



Im working on using quaternions for opengl rotations and my implementation, based mostly on the matrix and quaternion faq and also a little on apples own qmath library in its sample code, has some interesting behavior when it comes to model transformations as opposed to viewing transformations.

It seems that, in order to get correct relative transformations for a quaternion representing the camera, I need to do the multiplication with the original rotation on the right and the transformation on the left (ie, rotation = transformation * rotation). When the quaternion is to represent the orientation of a model in the scene, the multiplication must be done with the transformation on the left (rotation = rotation * transformation). I am unsure if this is the expected behavior, or an error in the quaternion implementation. I believe it is an error. Ive included the relevant code below.

Another problem I am having with quaternions is the lack of accurate references. My implementation is based on the matrix and quaternion faq, and except for the behavior I described above, seems to be passing all of my sanity checks (setting a quaternion from an axis and angle, then getting the axis and angle from the quaternion and comparing the new with the original, and other similar tests). However, it cant seem to agree on whether its dealing with unit quaternions only or the general case, and whether it is using row major or column major matrices. Some of the algorithms described are wrong altogether. Where can I find an accurate reference for operations on unit quaternions being used for opengl-style matrices and rotations? Better still, where can I find working, tested sample code to test my implementation against?

// the following are based heavily on:
// The Matrix and Quaternion FAQ (search google)
// the accuracy of these methods has yet to be verified
const double FLOAT_ERROR = 0.0000000001;
void quaternion::normalize()
{
double dist, square;
square = sqrt(w * w + x * x + y * y + z * z);
if (square > FLOAT_ERROR ||
(1.0  FLOAT_ERROR < square &&
1.0 + FLOAT_ERROR > square))
dist = 1.0 / square;
else
dist = 1.0;

x *= dist;
y *= dist;
z *= dist;
w *= dist;
}

// note: angle is in radians
void quaternion::set_axis_angle(double angle, double ax,
double ay, double az)
{
angle *= 0.5;
double scale(sin(angle));

w = cos(angle);
x = ax * scale;
y = ay * scale;
z = az * scale;
}

void quaternion::operator*=(const quaternion& rhs)
{
double tw(w), tx(x), ty(y), tz(z);
w = tw * rhs.w  tx * rhs.x  ty * rhs.y  tz * rhs.z;
x = tw * rhs.x + tx * rhs.w + ty * rhs.z  tz * rhs.y;
y = tw * rhs.y + ty * rhs.w + tz * rhs.x  tx * rhs.z;
z = tw * rhs.z + tz * rhs.w + tx * rhs.y  ty * rhs.x;
this->normalize();
}

quaternion operator*(const quaternion& rhs)
{
quaternion ret(*this);
ret *= rhs;
return ret;
}

// note: angle is in radians
void quaternion::rotate_model_x(double angle)
{
quaternion xrot;
xrot.set_axis_angle(angle, 1.0, 0.0, 0.0);
(*this) *= xrot;
}

void quaternion::rotate_view_x(double rotation)
{
quaternion xrot;
xrot.set_axis_angle(angle, 1.0, 0.0, 0.0);
(*this) = xrot * (*this);
}
_______________________________________________
mac-opengl mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/mac-opengl
Do not post admin requests to the list. They will be ignored.



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.