This is a very simple yet efficient adaptation of
quaternions to combined x/y/z rotations. Quaternions
avoid the gimble lock problem.
to rotate a point only requires 3 multiplies and 4
additions.
It took me a couple of days to digest:
http://www.gamedev.net/reference/articles/article1095.asp
and
http://www.cs.ualberta.ca/~andreas/math/matrfaq_latest.html
See http://www.geocities.com/capgadget
for where I use this.
This is the result. I am throwing my Euler rotation
matrix code into the bit bucket=========================================================
/* Given an array of xyz points I do translation and
scaling elsewhere*/
typedef struct {
float x, y, z;
} points;
static double quat4[4], qrmat4[4][4]; /*quat4 is
the Quaternion qrmat4 is the 4x4 Quaternion rotation
matrix /
float x, y, z; / w not currently used /
static float qr4_00, qr4_10, qr4_20,
qr4_01, qr4_11, qr4_21; / don’t really need double
unless you have a football field sized
100 DPI monitor, but I
kept double in the quaternion derivation
function /
float xplot, yplot; / Rotated point */
/* and angles (Note that angles are in 1/10th of a
degree) */
int xrotation, yrotation, zrotation;
if(rotation_changed) { /* Only need to recalculate if
the angles have changed /
euler_to_quat4(xrotation, yrotation, zrotation,
quat4, qrmat4); / angles are in 1/10th degree /
qr4_00 = qrmat4[0][0];
qr4_10 = qrmat4[1][0];
qr4_20 = qrmat4[2][0];
qr4_01 = qrmat4[0][1];
qr4_11 = qrmat4[1][1];
qr4_21 = qrmat4[2][1];
} / if(rotation_changed) */
/*$ LOOP THROUGH POINTS */
for(i = 0; i < NUMBER_OR_POINTS; i++) { /* Need to
make some of these inline */
xplot = particle_frame[i].x;
yplot = particle_frame[i].y;
if((xrotation != 0) || (yrotation != 0) ||
(zrotation != 0)) { /* Do quaternion rotation */
x = particle_frame[i].x;
y = particle_frame[i].y;
z = particle_frame[i].z;
/*$F Original
xplot = x * qrmat4[0][0] + y * qrmat4[1][0] + z *
qrmat4[2][0] + qrmat4[3][0]; 30 is always 0
yplot = x * qrmat4[0][1] + y * qrmat4[1][1] + z *
qrmat4[2][1] + qrmat4[3][1]; 31 is always 0
/
/$F Hand opimized version of the above. /
xplot = x * qr4_00 + y * qr4_10 + z * qr4_20;
yplot = x * qr4_01 + y * qr4_11 + z * qr4_21;
} / if((xrotation != 0) || (yrotation != 0) ||
(zrotation != 0)) /
} / for(i = 0; i < NUMBER_OR_POINTS; i++) */
=========================================================================================
/*$T bg_euler_to_quat4.c GC 1.129 02/27/02 17:38:08 */
/*$6
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/*$F
Use quaternions to do multi axis rotations. Avoids
gimbal lock
Derivedfrom
http://www.gamedev.net/reference/articles/article1095.asp
and
http://www.cs.ualberta.ca/~andreas/math/matrfaq_latest.html
*/
/*$F
This source is free software; you can redistribute it
and/or
modify it under the terms of the GNU Library General
Public
License as published by the Free Software Foundation;
either
version 2 of the License, or (at your option) any
later
version.
This source is distributed in the hope that it will
be useful,
but WITHOUT ANY WARRANTY; without even the implied
warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Library General Public License for more
details.
You should have received a copy of the GNU Library
General
Public License along with this library; if not, write
to the
Free Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA
02111-1307 USA
Copyright © 2002 John B. Battles
Any feedback is very welcome. For any question,
comments,
see http://www.geocities.com/capgadget.html or email
*/
#include <math.h>
/*
=======================================================================================================================
=======================================================================================================================
*/
/* Parts of this can be gutted out for the special
case above */
void euler_to_quat4(const int ax, const int ay, const
int az, double quat4[4], double qrmat4[4][4]) {
/~~//
/ angles are in 1/10th degree /
double ex, ey, ez, x, y, z, w; / temp half
euler angles /
double cr, cp, cy, sr, sp, sy, cpcy, spsy; / temp
vars in roll,pitch yaw /
double norm;
double xx, xy, xz, xw, yy, yz, yw, zz, zw;
static double dbl_1 = 1.0;
static double dbl_2 = 2.0;
enum { X = 0, Y = 1, Z = 2, W = 3 };
/
ex = (double) (M_PI * (double) ax / (double) 1800.0);
ey = (double) (M_PI * (double) ay / (double) 1800.0);
ez = (double) (M_PI * (double) az / (double) 1800.0);
/*
* ex = DEGTORAD(x) / 2.0; // convert to rads and
half them ey = DEGTORAD(y) /
* 2.0; ez = DEGTORAD(z) / 2.0;
*/
cr = cos(ex);
cp = cos(ey);
cy = cos(ez);
sr = sin(ex);
sp = sin(ey);
sy = sin(ez);
cpcy = cp * cy;
spsy = sp * sy;
x = sr * cpcy - cr * spsy;
y = cr * sp * cy + sr * cp * sy;
z = cr * cp * sy - sr * sp * cy;
w = cr * cpcy + sr * spsy;
/* Normalize(); Should always == 1 */
norm = sqrt(x * x + y * y + z * z + w * w);
quat4[X] = x / norm;
quat4[Y] = y / norm;
quat4[Z] = z / norm;
quat4[W] = w / norm;
/* Create the Quaternion 4x4 Rotation Matrix */
xx = quat4[X] * quat4[X];
xy = quat4[X] * quat4[Y];
xz = quat4[X] * quat4[Z];
xw = quat4[X] * quat4[W];
yy = quat4[Y] * quat4[Y];
yz = quat4[Y] * quat4[Z];
yw = quat4[Y] * quat4[W];
zz = quat4[Z] * quat4[Z];
zw = quat4[Z] * quat4[W];
qrmat4[0][0] = dbl_1 - dbl_2 * (yy + zz);
qrmat4[1][0] = dbl_2 * (xy - zw);
qrmat4[2][0] = dbl_2 * (xz + yw);
qrmat4[0][1] = dbl_2 * (xy + zw);
qrmat4[1][1] = dbl_1 - dbl_2 * (xx + zz);
qrmat4[2][1] = dbl_2 * (yz - xw);
qrmat4[0][2] = dbl_2 * (xz - yw);
qrmat4[1][2] = dbl_2 * (yz + xw);
qrmat4[2][2] = dbl_1 - dbl_2 * (xx + yy);
qrmat4[3][0] = qrmat4[3][1] = qrmat4[3][2] =
qrmat4[0][3] = qrmat4[1][3] = qrmat4[2][3] = 0.0;
qrmat4[3][3] = dbl_1;
/*$F
Here
OpenGL
| [0][0] [0][1] [0][2] [0][3] |
| 0 4 8 12 |
| |
| |
| [1][0] [1][1] [1][2] [1][3] |
| 1 5 9 13 |
M = | | M =
| |
| [2][0] [2][1] [2][2] [2][3] |
| 2 6 10 14 |
| |
| |
| [3][0] [3][1] [3][2] [3][3] |
| 3 7 11 15 |
*/
return;
}
Do You Yahoo!?
Yahoo! Greetings - Send FREE e-cards for every occasion!
http://greetings.yahoo.com