Re: need help with mathematics... rotation
# Re: need help with mathematics... rotation

**Subject**: **Re: need help with mathematics... rotation**
- From: Joe Ante <email@hidden>
- Date: Sat, 04 Aug 2001 19:58:32 +0200
- User-agent: Microsoft-Outlook-Express-Macintosh-Edition/5.02.2022

template<class Real> inline

void GetRotMatrixNormVec (Real* out, const Real*const inVec, Real radians)

{

/* This function contributed by Erich Boleyn (email@hidden) */

/* This function used from the Mesa OpenGL code (matrix.c) */

Real s, c;

Real vx, vy, vz, xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;

s = sin (radians);

c = cos (radians);

vx = inVec[0];

vy = inVec[1];

vz = inVec[2];

#define M(row,col) out[row*3 + col]

/*

* Arbitrary axis rotation matrix.

*

* This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied

* like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation

* (which is about the X-axis), and the two composite transforms

* Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary

* from the arbitrary axis to the X-axis then back. They are

* all elementary rotations.

*

* Rz' is a rotation about the Z-axis, to bring the axis vector

* into the x-z plane. Then Ry' is applied, rotating about the

* Y-axis to bring the axis vector parallel with the X-axis. The

* rotation about the X-axis is then performed. Ry and Rz are

* simply the respective inverse transforms to bring the arbitrary

* axis back to it's original orientation. The first transforms

* Rz' and Ry' are considered inverses, since the data from the

* arbitrary axis gives you info on how to get to it, not how

* to get away from it, and an inverse must be applied.

*

* The basic calculation used is to recognize that the arbitrary

* axis vector (x, y, z), since it is of unit length, actually

* represents the sines and cosines of the angles to rotate the

* X-axis to the same orientation, with theta being the angle about

* Z and phi the angle about Y (in the order described above)

* as follows:

*

* cos ( theta ) = x / sqrt ( 1 - z^2 )

* sin ( theta ) = y / sqrt ( 1 - z^2 )

*

* cos ( phi ) = sqrt ( 1 - z^2 )

* sin ( phi ) = z

*

* Note that cos ( phi ) can further be inserted to the above

* formulas:

*

* cos ( theta ) = x / cos ( phi )

* sin ( theta ) = y / cos ( phi )

*

* ...etc. Because of those relations and the standard trigonometric

* relations, it is pssible to reduce the transforms down to what

* is used below. It may be that any primary axis chosen will give the

* same results (modulo a sign convention) using thie method.

*

* Particularly nice is to notice that all divisions that might

* have caused trouble when parallel to certain planes or

* axis go away with care paid to reducing the expressions.

* After checking, it does perform correctly under all cases, since

* in all the cases of division where the denominator would have

* been zero, the numerator would have been zero as well, giving

* the expected result.

*/

xx = vx * vx;

yy = vy * vy;

zz = vz * vz;

xy = vx * vy;

yz = vy * vz;

zx = vz * vx;

xs = vx * s;

ys = vy * s;

zs = vz * s;

one_c = 1.0F - c;

M(0,0) = (one_c * xx) + c;

M(1,0) = (one_c * xy) - zs;

M(2,0) = (one_c * zx) + ys;

M(0,1) = (one_c * xy) + zs;

M(1,1) = (one_c * yy) + c;

M(2,1) = (one_c * yz) - xs;

M(0,2) = (one_c * zx) - ys;

M(1,2) = (one_c * yz) + xs;

M(2,2) = (one_c * zz) + c;

#undef M

}