summaryrefslogtreecommitdiffstats
path: root/rwsdk/include/d3d8/rtquat.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rwsdk/include/d3d8/rtquat.h646
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 */
+