diff options
Diffstat (limited to '')
-rw-r--r-- | rwsdk/include/d3d8/rtslerp.h | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/rwsdk/include/d3d8/rtslerp.h b/rwsdk/include/d3d8/rtslerp.h new file mode 100644 index 00000000..ec41752c --- /dev/null +++ b/rwsdk/include/d3d8/rtslerp.h @@ -0,0 +1,262 @@ +/* + * Data Structures for Slerps/Spherical Linear Interpolations + * See also GemsIII/quatspin.c in + * http://www.acm.org/pubs/tog/GraphicsGems/gemsiii.zip + * Copyright (c) Criterion Software Limited + */ + +/*************************************************************************** + * * + * Module : rtslerp.h * + * * + * Purpose : Slerp functionality * + * * + **************************************************************************/ + +#ifndef RTSLERP_H +#define RTSLERP_H + +/** + * \defgroup rtslerp RtSlerp + * \ingroup rttool + * + * Slerp/Spherical Linear Interpolations Toolkit for RenderWare. + * + * See also http://www.cis.ohio-state.edu/~parent/book/Full.html + */ + +#include "rwcore.h" +#include "rtquat.h" + +/**************************************************************************** + Includes + */ + +#include "rtslerp.rpe" /* automatically generated header file */ + +/**************************************************************************** + Defines + */ + +/* Masks for specifying which matrices to store by reference */ +#define rtSLERPREFNONE 0x00 +#define rtSLERPREFSTARTMAT 0x01 +#define rtSLERPREFENDMAT 0x02 +#define rtSLERPREFALL (~rtSLERPREFNONE) + +/**************************************************************************** + Global Types + */ + + +typedef struct RtSlerp RtSlerp; +/** + * \ingroup rtslerp + * \struct RtSlerp + * structure describing a Slerps/Spherical Linear Interpolations. + * See also GemsIII/quatspin.c in + * http://www.acm.org/pubs/tog/GraphicsGems/gemsiii.zip + */ +struct RtSlerp +{ + RwInt32 matRefMask; /**< Which matrices do we NOT own */ + RwMatrix *startMat; /**< The start matrix */ + RwMatrix *endMat; /**< The end matrix */ + RwV3d axis; /**< The axis of rotation for the slerp */ + RwReal angle; /**< The angle (in degrees) between src & dest */ + + /* Though a slerp may be a bad idea and opting for a lerp is better */ + RwBool useLerp; /**< Do we want to use lerps? */ +}; + +/* static frame sequence animation - contains no state */ + + +typedef struct RtQuatSlerpCache RtQuatSlerpCache; +/** + * \ingroup rtslerp + * \struct RtQuatSlerpCache + * structure describing a SlerpCache, + * which should be initialized with \ref RtQuatSetupSlerpCache. + */ +struct RtQuatSlerpCache +{ + RtQuat raFrom; /**< Scaled initial quaternion */ + RtQuat raTo; /**< Scaled final quaternion */ + RwReal omega; /**< Angular displacement in radians */ + RwBool nearlyZeroOm; /**< Flags near-zero angular + displacement*/ +}; + + +typedef struct RtQuatSlerpArgandCache RtQuatSlerpArgandCache; +/** + * \ingroup rtslerp + * \struct RtQuatSlerpArgandCache + * a structure describing + * an Argand SlerpCache which should be + * initialized with \ref RtQuatSetupSlerpArgandCache. + * See http://www-groups.dcs.st-and.ac.uk/~history/Mathematicians/Argand.html + * Jean Argand was an accountant and amateur mathematician. + * He is famed for his geometrical interpretation of the complex numbers + * where i is interpreted as a rotation through 90. + */ +struct RtQuatSlerpArgandCache +{ + RtQuat logTo; /**< field Logarithm of final quaternion */ + RtQuat logBase; /**< Logarithm of initial relative to final quaternion */ +}; + +#define RtQuatSlerpMacro(qpResult, qpFrom, qpTo, rT, sCache) \ +MACRO_START \ +{ \ + if ((rT) <= ((RwReal) 0)) \ + { \ + /* t is before start */ \ + *(qpResult) = *(qpFrom); \ + } \ + else if (((RwReal) 1) <= (rT)) \ + { \ + \ + /* t is after end */ \ + *(qpResult) = *(qpTo); \ + } \ + else \ + { \ + /* ... so t must be in the interior then */ \ + /* Calc coefficients rSclFrom, rSclTo */ \ + RwReal rSclFrom = ((RwReal) 1) - (rT); \ + RwReal rSclTo = (rT); \ + \ + if (!((sCache)->nearlyZeroOm)) \ + { \ + /* Standard case: slerp */ \ + /* SLERPMESSAGE(("Neither nearly ZERO nor nearly PI")); */ \ + \ + rSclFrom *= (sCache)->omega; \ + RwSinMinusPiToPiMacro(rSclFrom, rSclFrom); \ + rSclTo *= (sCache)->omega; \ + RwSinMinusPiToPiMacro(rSclTo, rSclTo); \ + } \ + \ + /* Calc final values */ \ + RwV3dScaleMacro(&(qpResult)->imag, \ + &(sCache)->raFrom.imag, rSclFrom); \ + RwV3dIncrementScaledMacro(&(qpResult)->imag, \ + &(sCache)->raTo.imag, rSclTo); \ + (qpResult)->real = \ + ((sCache)->raFrom.real * rSclFrom) + \ + ((sCache)->raTo.real * rSclTo); \ + } \ +} \ +MACRO_STOP + +#define RtQuatSlerpArgandMacro(qpResult, qpFrom, qpTo, rT, sArgandCache) \ +MACRO_START \ +{ \ + if ((rT) <= ((RwReal) 0)) \ + { \ + /* t is before start */ \ + *(qpResult) = *(qpFrom); \ + } \ + else if (((RwReal) 1) <= (rT)) \ + { \ + /* t is after end */ \ + *(qpResult) = *(qpTo); \ + } \ + else \ + { \ + RtQuat logBlend; \ + \ + /* ... so t must be in the interior then */ \ + \ + logBlend.imag.x = \ + (sArgandCache)->logBase.imag.x + \ + (rT) * (sArgandCache)->logTo.imag.x; \ + logBlend.imag.y = \ + (sArgandCache)->logBase.imag.y + \ + (rT) * (sArgandCache)->logTo.imag.y; \ + logBlend.imag.z = \ + (sArgandCache)->logBase.imag.z + \ + (rT) * (sArgandCache)->logTo.imag.z; \ + logBlend.real = 0; \ + \ + RtQuatUnitExpMacro((qpResult), &logBlend); \ + \ + } \ +} \ +MACRO_STOP + +#if (! ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) )) + +#define RtQuatSlerp(qpResult, qpFrom, qpTo, rT, sCache) \ + RtQuatSlerpMacro(qpResult, qpFrom, qpTo, rT, sCache) + +#define RtQuatSlerpArgand(qpResult, qpFrom, qpTo, rT, sArgandCache) \ + RtQuatSlerpArgandMacro(qpResult, qpFrom, qpTo, rT, sArgandCache) + +#endif /* (! ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) )) */ + +/**************************************************************************** + Function prototypes + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* Creating and destroying slerps */ + +extern RtSlerp *RtSlerpCreate(RwInt32 nMatRefMask); + +extern void RtSlerpDestroy(RtSlerp * spSlerp); + +/* setting up a slerp */ +extern RtSlerp *RtSlerpInitialize(RtSlerp * spSlerp, + RwMatrix * mpMat1, + RwMatrix * mpMat2); + +/* Get a matrix */ +extern RwMatrix *RtSlerpGetMatrix(RtSlerp * spSlerp, + RwMatrix * mpResultMat, + RwReal nDelta); + +/* Set if lerp or slerp */ +extern RtSlerp *RtSlerpSetLerp(RtSlerp * spSlerp, + RwBool bUseLerp); + +extern void +RtQuatSetupSlerpCache(RtQuat * qpFrom, + RtQuat * qpTo, + RtQuatSlerpCache * sCache); + +extern void +RtQuatSetupSlerpArgandCache(RtQuat * qpFrom, + RtQuat * qpTo, + RtQuatSlerpArgandCache * sArgandCache); + +#if ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) ) + +extern void +RtQuatSlerp(RtQuat * qpResult, + RtQuat * qpFrom, + RtQuat * qpTo, + RwReal rT, + RtQuatSlerpCache * sCache); + +extern void +RtQuatSlerpArgand(RtQuat * qpResult, + RtQuat * qpFrom, + RtQuat * qpTo, + RwReal rT, + RtQuatSlerpArgandCache * sArgandCache); + +#endif /* ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) ) */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* RTSLERP_H */ + |