diff options
Diffstat (limited to '')
-rw-r--r-- | rwsdk/include/d3d8/rtquat.h | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/rwsdk/include/d3d8/rtquat.h b/rwsdk/include/d3d8/rtquat.h new file mode 100644 index 00000000..05e971d0 --- /dev/null +++ b/rwsdk/include/d3d8/rtquat.h @@ -0,0 +1,646 @@ +/* + * Data structures for Quaternions + * See http://www-groups.dcs.st-and.ac.uk/~history/Mathematicians/Hamilton.html + * + * Copyright (c) Criterion Software Limited + */ + +#ifndef RTQUAT_H +#define RTQUAT_H + +/** + * \defgroup rtquat RtQuat + * \ingroup rttool + * + * Quaternion Toolkit for RenderWare. + * + * See also http://www.gamasutra.com/features/19980703/quaternions_01.htm + */ + +/* + * See http://www-groups.dcs.st-and.ac.uk/~history/Mathematicians/Hamilton.html + * On 16 October 1843 (a Monday) Hamilton was walking in along the Royal + * Canal with his wife to preside at a Council meeting of the Royal Irish + * Academy. + * + * Although his wife talked to him now and again Hamilton hardly + * heard, for the discovery of the quaternions, the first noncommutative + * algebra to be studied, was taking shape in his mind:- + * + * "And here there dawned on me the notion that we must admit, in + * some sense, a fourth dimension of space for the purpose of calculating + * with triples ... An electric circuit seemed to close, and a spark + * flashed forth." + */ + + +/**************************************************************************** + Includes + */ + +#include <math.h> +/* renderware */ +#include "rwcore.h" + +#include "rtquat.rpe" /* automatically generated header file */ + +#define RW_TOL_ORTHONORMAL ((RwReal)0.01) + +/**************************************************************************** + Global Types + */ + + +typedef struct RtQuat RtQuat; +/** + * \ingroup rtquat + * \struct RtQuat + * A structure describing a Quaternion + * +*/ +struct RtQuat +{ + RwV3d imag; /**< The imaginary part(s) */ + RwReal real; /**< The real part */ +}; + + +/**************************************************************************** + Defines + */ + +#define RtQuatInitMacro( result, _x, _y, _z, _w) \ +MACRO_START \ +{ \ + (result)->real = (_w); \ + (result)->imag.x = (_x); \ + (result)->imag.y = (_y); \ + (result)->imag.z = (_z); \ +} \ +MACRO_STOP + +#if (!defined(RtQuatAssignMacro)) +#define RtQuatAssignMacro(_target, _source) \ + ( *(_target) = *(_source) ) +#endif /* (!defined(RtQuatAssignMacro)) */ + +#define RtQuatAddMacro( result, q1, q2 ) \ +MACRO_START \ +{ \ + (result)->real = (q1)->real + (q2)->real; \ + RwV3dAddMacro(&(result)->imag, &(q1)->imag, &(q2)->imag); \ +} \ +MACRO_STOP + +#define RtQuatIncrementRealPartMacro(result, s, q) \ +MACRO_START \ +{ \ + (result)->real = (q)->real + s; \ + (result)->imag.x = (q)->imag.x; \ + (result)->imag.y = (q)->imag.y; \ + (result)->imag.z = (q)->imag.z; \ +} \ +MACRO_STOP + +#define RtQuatDecrementRealPartMacro(result, s, q) \ +MACRO_START \ +{ \ + (result)->real = (q)->real - s; \ + (result)->imag.x = (q)->imag.x; \ + (result)->imag.y = (q)->imag.y; \ + (result)->imag.z = (q)->imag.z; \ +} \ +MACRO_STOP + +#define RtQuatIncrementMacro( result, dq ) \ +MACRO_START \ +{ \ + (result)->real = (result)->real + (dq)->real; \ + RwV3dAddMacro(&(result)->imag, &(result)->imag, &(dq)->imag); \ +} \ +MACRO_STOP + +#define RtQuatSubMacro( result, q1, q2 ) \ +MACRO_START \ +{ \ + (result)->real = (q1)->real - (q2)->real; \ + RwV3dSubMacro(&(result)->imag, &(q1)->imag, &(q2)->imag); \ +} \ +MACRO_STOP + +#define RtQuatNegateMacro( result, q ) \ +MACRO_START \ +{ \ + (result)->real = -(q)->real; \ + (result)->imag.x = -(q)->imag.x; \ + (result)->imag.y = -(q)->imag.y; \ + (result)->imag.z = -(q)->imag.z; \ +} \ +MACRO_STOP + +#define RtQuatConjugateMacro( result, q) \ +MACRO_START \ +{ \ + (result)->real = (q)->real; \ + (result)->imag.x = -(q)->imag.x; \ + (result)->imag.y = -(q)->imag.y; \ + (result)->imag.z = -(q)->imag.z; \ +} \ +MACRO_STOP + +#define RtQuatScaleMacro(result, q, scale ) \ +MACRO_START \ +{ \ + (result)->real = (q)->real * scale; \ + RwV3dScaleMacro(&(result)->imag, &(q)->imag, scale); \ +} \ +MACRO_STOP + +#define RtQuatModulusSquaredMacro( q ) \ + ((q)->real * (q)->real + \ + RwV3dDotProductMacro(&(q)->imag, &(q)->imag)) + +#define RtQuatModulusMacro( result, q ) \ +MACRO_START \ +{ \ + (result) = RtQuatModulusSquaredMacro(q); \ + rwSqrtMacro(&result, result); \ +} \ +MACRO_STOP + +#define RtQuatMultiplyMacro( result, q1, q2) \ +MACRO_START \ +{ \ + /* \ + * Assumes q1 != result != q2 \ + */ \ + (result)->real = \ + (q1)->real * (q2)->real - \ + RwV3dDotProductMacro(&(q1)->imag,&(q2)->imag); \ + RwV3dCrossProductMacro(&(result)->imag, &(q1)->imag, &(q2)->imag); \ + RwV3dIncrementScaledMacro(&(result)->imag, &(q2)->imag, (q1)->real); \ + RwV3dIncrementScaledMacro(&(result)->imag, &(q1)->imag, (q2)->real); \ +} \ +MACRO_STOP + +#define RtQuatReciprocalMacro( result, q) \ +MACRO_START \ +{ \ + /* \ + * Assumes result != q \ + */ \ + RwReal val = RtQuatModulusSquaredMacro(q); \ + \ + if (val > (RwReal) 0) \ + { \ + val = ((RwReal)1) / val; \ + (result)->real = (q)->real * val; \ + val = -val; \ + RwV3dScaleMacro(&(result)->imag, &(q)->imag, val); \ + } \ +} \ +MACRO_STOP + +#define RtQuatSquareMacro( result, q ) \ +MACRO_START \ +{ \ + /* \ + * Assumes result != q \ + */ \ + RwReal val = ((RwReal)2) * (q)->real ; \ + \ + (result)->real = \ + (q)->real * (q)->real - \ + RwV3dDotProductMacro(&(q)->imag, &(q)->imag); \ + RwV3dScaleMacro(&(result)->imag, &(q)->imag, val); \ +} \ +MACRO_STOP + +#define RtQuatSquareRootMacro( result, q ) \ +MACRO_START \ +{ \ + /* \ + * Assumes result != q \ + * other root is of course -result \ + */ \ + RwReal val; \ + \ + RtQuatModulusMacro(val,q); \ + val = ((q)->real + val) * ((RwReal) 0.5); \ + \ + if (val > ((RwReal)0)) \ + { \ + rwSqrtMacro(&val, val); \ + (result)->real = val; \ + val = ((RwReal)0.5) / val; \ + RwV3dScale(&(result)->imag, &(q)->imag, val); \ + } \ + else \ + { \ + result->imag.x = -(q)->real; \ + rwSqrtMacro(&(result->imag.x), result->imag.x); \ + result->imag.y = ((RwReal)0); \ + result->imag.x = ((RwReal)0); \ + result->real = ((RwReal)0); \ + } \ +} \ +MACRO_STOP + +#define RtQuatLogMacro(result, q) \ +MACRO_START \ +{ \ + /* \ + * Assumes result != q \ + */ \ + const RwReal mod2 = RtQuatModulusSquaredMacro(q); \ + RwReal sin_b; \ + RwReal radians; \ + RwReal factor; \ + \ + sin_b = RwV3dDotProduct(&(q)->imag, &(q)->imag); \ + rwSqrtMacro(&sin_b, sin_b); \ + radians = (RwReal) RwATan2(sin_b, (q)->real); \ + factor = (sin_b > (RwReal) 0) ? (((RwReal)radians) / sin_b) : 0 ; \ + \ + RwV3dScaleMacro(&(result)->imag, &(q)->imag, factor); \ + (result)->real = ((RwReal) RwLog(mod2)) * ((RwReal) 0.5); \ + \ +} \ +MACRO_STOP + +#define RtQuatExpMacro(result, q) \ +MACRO_START \ +{ \ + /* \ + * Assumes result != q \ + */ \ + const RwReal exp_a = (RwReal)RwExp((q)->real); \ + RwReal mod_b; \ + RwReal factor; \ + \ + mod_b = RwV3dDotProduct(&(q)->imag, &(q)->imag); \ + rwSqrtMacro(&mod_b, mod_b); \ + factor = ( (mod_b > (RwReal) 0) ? \ + (exp_a * ((RwReal)RwSin(mod_b)) / mod_b) : \ + 0 ) ; \ + \ + RwV3dScaleMacro(&(result)->imag, &(q)->imag, factor); \ + (result)->real = exp_a * (RwReal)RwCos(mod_b); \ +} \ +MACRO_STOP + +#define RtQuatPowMacro( result, q, e) \ +MACRO_START \ +{ \ + RtQuat qLog; \ + \ + RtQuatLogMacro(&qLog, q); \ + RtQuatScaleMacro(&qLog, &qLog, e); \ + RtQuatExpMacro(result, &qLog); \ +} \ +MACRO_STOP + +#define RtQuatUnitLogMacro(result, q) \ +MACRO_START \ +{ \ + /* \ + * Assumes result != q \ + */ \ + RwReal sin_b ; \ + RwReal radians ; \ + RwReal factor ; \ + \ + sin_b = RwV3dDotProduct(&(q)->imag, &(q)->imag); \ + rwSqrtMacro(&sin_b, sin_b); \ + radians = (RwReal)RwATan2(sin_b, (q)->real); \ + factor = (sin_b > (RwReal) 0) ? (((RwReal)radians) / sin_b) : 0 ; \ + \ + RwV3dScaleMacro(&(result)->imag, &(q)->imag, factor); \ + (result)->real = (RwReal)0; \ + \ +} \ +MACRO_STOP + +#define RtQuatUnitExpMacro(result, q) \ +MACRO_START \ +{ \ + /* \ + * Assumes result != q \ + */ \ + RwReal mod_b; \ + RwReal factor; \ + \ + mod_b = RwV3dDotProduct(&(q)->imag, &(q)->imag); \ + rwSqrtMacro(&mod_b, mod_b); \ + factor = (mod_b > (RwReal) 0) ? (((RwReal)RwSin(mod_b)) / mod_b) : 0 ; \ + \ + RwV3dScaleMacro(&(result)->imag, &(q)->imag, factor); \ + (result)->real = (RwReal)RwCos(mod_b); \ + \ +} \ +MACRO_STOP + +#define RtQuatUnitPowMacro( result, q, e) \ +MACRO_START \ +{ \ + RtQuat qLog; \ + \ + RtQuatUnitLogMacro(&qLog, q); \ + RwV3dScaleMacro(&qLog.imag, &qLog.imag, e); \ + RtQuatUnitExpMacro(result, &qLog); \ +} \ +MACRO_STOP + +#define RtQuatConvertToMatrixMacro(qpQuat, mpMatrix) \ +MACRO_START \ +{ \ + RwReal rS; \ + RwV3d rV; \ + RwV3d rW; \ + RwV3d square; \ + RwV3d cross; \ + \ + rS = ((RwReal) 2) / RtQuatModulusSquaredMacro((qpQuat)); \ + \ + RwV3dScale(&rV, &(qpQuat)->imag, rS); \ + RwV3dScale(&rW, &rV, (qpQuat)->real); \ + \ + square.x = (qpQuat)->imag.x * rV.x; \ + square.y = (qpQuat)->imag.y * rV.y; \ + square.z = (qpQuat)->imag.z * rV.z; \ + \ + cross.x = (qpQuat)->imag.y * rV.z; \ + cross.y = (qpQuat)->imag.z * rV.x; \ + cross.z = (qpQuat)->imag.x * rV.y; \ + \ + (mpMatrix)->right.x = ((RwReal) 1) - (square.y + square.z); \ + (mpMatrix)->right.y = cross.z + rW.z; \ + (mpMatrix)->right.z = cross.y - rW.y; \ + \ + (mpMatrix)->up.x = cross.z - rW.z; \ + (mpMatrix)->up.y = ((RwReal) 1) - (square.z + square.x); \ + (mpMatrix)->up.z = cross.x + rW.x; \ + \ + (mpMatrix)->at.x = cross.y + rW.y; \ + (mpMatrix)->at.y = cross.x - rW.x; \ + (mpMatrix)->at.z = ((RwReal) 1) - (square.x + square.y); \ + \ + /* Set position */ \ + (mpMatrix)->pos.x = ((RwReal) 0); \ + (mpMatrix)->pos.y = ((RwReal) 0); \ + (mpMatrix)->pos.z = ((RwReal) 0); \ + \ + /* Matrix is orthogonal */ \ + rwMatrixSetFlags((mpMatrix), \ + (rwMATRIXTYPEORTHOGANAL & \ + ~rwMATRIXINTERNALIDENTITY) ); \ + \ +} \ +MACRO_STOP + +#define RtQuatUnitConvertToMatrixMacro(qpQuat, mpMatrix) \ +MACRO_START \ +{ \ + const RwReal x = (qpQuat)->imag.x; \ + const RwReal y = (qpQuat)->imag.y; \ + const RwReal z = (qpQuat)->imag.z; \ + const RwReal w = (qpQuat)->real; \ + RwV3d square; \ + RwV3d cross; \ + RwV3d wimag; \ + \ + square.x = x * x; \ + square.y = y * y; \ + square.z = z * z; \ + \ + cross.x = y * z; \ + cross.y = z * x; \ + cross.z = x * y; \ + \ + wimag.x = w * x; \ + wimag.y = w * y; \ + wimag.z = w * z; \ + \ + (mpMatrix)->right.x = 1 - 2 * (square.y + square.z); \ + (mpMatrix)->right.y = 2 * (cross.z + wimag.z); \ + (mpMatrix)->right.z = 2 * (cross.y - wimag.y); \ + \ + (mpMatrix)->up.x = 2 * (cross.z - wimag.z); \ + (mpMatrix)->up.y = 1 - 2 * (square.x + square.z); \ + (mpMatrix)->up.z = 2 * (cross.x + wimag.x); \ + \ + (mpMatrix)->at.x = 2 * (cross.y + wimag.y); \ + (mpMatrix)->at.y = 2 * (cross.x - wimag.x); \ + (mpMatrix)->at.z = (1 - 2 * (square.x + square.y)); \ + \ + /* Set position */ \ + (mpMatrix)->pos.x = ((RwReal) 0); \ + (mpMatrix)->pos.y = ((RwReal) 0); \ + (mpMatrix)->pos.z = ((RwReal) 0); \ + \ + /* Matrix is orthonormal */ \ + rwMatrixSetFlags((mpMatrix), \ + (rwMATRIXTYPEORTHONORMAL & \ + ~rwMATRIXINTERNALIDENTITY) ); \ +} \ +MACRO_STOP + +#if (! ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) )) + +#define RtQuatInit( result, _x, _y, _z, _w) \ + RtQuatInitMacro( result, _x, _y, _z, _w) + +#define RtQuatAssign( to, from ) \ + RtQuatAssignMacro( to, from ) + +#define RtQuatAdd( result, q1, q2 ) \ + RtQuatAddMacro( result, q1, q2 ) + +#define RtQuatIncrementRealPart(result, s, q) \ + RtQuatIncrementRealPartMacro(result, s, q) + +#define RtQuatDecrementRealPart(result, s, q) \ + RtQuatDecrementRealPartMacro(result, s, q) + +#define RtQuatIncrement( result, dq ) \ + RtQuatIncrementMacro( result, dq ) + +#define RtQuatSub( result, q1, q2 ) \ + RtQuatSubMacro( result, q1, q2 ) + +#define RtQuatNegate( result, q ) \ + RtQuatNegateMacro( result, q ) + +#define RtQuatConjugate( result, q) \ + RtQuatConjugateMacro( result, q) + +#define RtQuatScale(result, q, scale ) \ + RtQuatScaleMacro(result, q, scale ) + +#define RtQuatModulusSquared( q ) \ + RtQuatModulusSquaredMacro( q ) + +#define RtQuatMultiply( result, q1, q2) \ + RtQuatMultiplyMacro( result, q1, q2) + +#define RtQuatReciprocal( result, q) \ + RtQuatReciprocalMacro( result, q) + +#define RtQuatSquare( result, q ) \ + RtQuatSquareMacro( result, q ) + +#define RtQuatSquareRoot( result, q ) \ + RtQuatSquareRootMacro( result, q ) + +#define RtQuatLog( result, q ) \ + RtQuatLogMacro( result, q ) + +#define RtQuatExp( result, q ) \ + RtQuatExpMacro( result, q ) + +#define RtQuatPow( result, q, e ) \ + RtQuatPowMacro( result, q, e ) + +#define RtQuatUnitLog( result, q ) \ + RtQuatUnitLogMacro( result, q ) + +#define RtQuatUnitExp( result, q ) \ + RtQuatUnitExpMacro( result, q ) + +#define RtQuatUnitPow( result, q, e ) \ + RtQuatUnitPowMacro( result, q, e ) + +#define RtQuatConvertToMatrix(qpQuat, mpMatrix) \ + RtQuatConvertToMatrixMacro(qpQuat, mpMatrix) + +#define RtQuatUnitConvertToMatrix(qpQuat, mpMatrix) \ + RtQuatUnitConvertToMatrixMacro(qpQuat, mpMatrix) + +#endif /* (! ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) )) */ + +/**************************************************************************** + Function prototypes + */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +extern RwBool +RtQuatConvertFromMatrix(RtQuat * const qpQuat, + const RwMatrix * const mpMatrix); + +extern RtQuat * +RtQuatRotate(RtQuat * quat, + const RwV3d * axis, + RwReal angle, + RwOpCombineType combineOp); + +extern const RtQuat * +RtQuatQueryRotate(const RtQuat *quat, + RwV3d * unitAxis, + RwReal * angle); + +extern RwV3d * +RtQuatTransformVectors(RwV3d * vectorsOut, + const RwV3d * vectorsIn, + const RwInt32 numPoints, + const RtQuat *quat); + +extern RwReal +RtQuatModulus(RtQuat * q); + +#if ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) ) + +extern void +RtQuatInit(RtQuat * result, RwReal x, RwReal y, RwReal z, RwReal w); + +extern void +RtQuatAssign(RtQuat * to, RtQuat * from); + +extern void +RtQuatAdd(RtQuat * result, RtQuat * q1, RtQuat * q2); + +extern void +RtQuatIncrementRealPart(RtQuat * result, RwReal s, RtQuat * q); + +extern void +RtQuatDecrementRealPart(RtQuat * result, RwReal s, RtQuat * q); + +extern void +RtQuatIncrement(RtQuat * result, RtQuat * dq); + +extern void +RtQuatSub(RtQuat * result, RtQuat * q1, RtQuat * q2); + +extern void +RtQuatNegate(RtQuat * result, RtQuat * q); + +extern void +RtQuatConjugate(RtQuat * result, RtQuat * q); + +extern void +RtQuatScale(RtQuat * result, RtQuat * q, RwReal scale); + +extern RwReal +RtQuatModulusSquared(RtQuat * q); + +extern void +RtQuatMultiply(RtQuat * result, RtQuat * q1, RtQuat * q2); + +extern void +RtQuatReciprocal(RtQuat * result, RtQuat * q); + +extern void +RtQuatSquare(RtQuat * result, RtQuat * q); + +extern void +RtQuatSquareRoot(RtQuat * result, RtQuat * q); + +extern void +RtQuatLog(RtQuat * result, RtQuat * q); + +extern void +RtQuatExp(RtQuat * result, RtQuat * q); + +extern void +RtQuatPow(RtQuat * result, RtQuat * q, RwReal e); + +extern void +RtQuatUnitLog(RtQuat * result, RtQuat * q); + +extern void +RtQuatUnitExp(RtQuat * result, RtQuat * q); + +extern void +RtQuatUnitPow(RtQuat * result, RtQuat * q, RwReal e); + +extern void +RtQuatConvertToMatrix(const RtQuat * const qpQuat, + RwMatrix * const mpMatrix); + +extern void +RtQuatUnitConvertToMatrix(const RtQuat * const qpQuat, + RwMatrix * const mpMatrix); + +#endif /* ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) ) */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/* + * Backwards compatibility code + */ + +typedef RtQuat RpQuat; + +#define RpAnimQuatConvertFromMatrix(qpQuat, mpMatrix) \ + RtQuatConvertFromMatrix(qpQuat, mpMatrix) + +#define RpAnimQuatConvertToMatrix(qpQuat,mpMatrix) \ + RtQuatUnitConvertToMatrix(qpQuat,mpMatrix) + + +#endif /* RTQUAT_H */ + |