00001 #ifndef __GXKEYFRAMETEMPLATE
00002 #define __GXKEYFRAMETEMPLATE
00003
00004
00005 #include "GXAutoArray.h"
00006 #include "GXInteroplationTemplates.h"
00007
00008 #include "fastmath.h"
00009
00010 template<typename type>
00011 class CGXKeyframeTemplate
00012 {
00013 friend class CGXKeyframeTemplate<type>;
00014
00015 public:
00016 CGXKeyframeTemplate(){}
00017 ~CGXKeyframeTemplate(){}
00018
00019 bool WriteToStream(IStream* pStream)
00020 {
00021 return m_Frames.WriteToStream(pStream);
00022 }
00023
00024
00025 bool LoadFromStream(IStream* pStream)
00026 {
00027 return m_Frames.LoadFromStream(pStream);
00028 }
00029
00030
00031 bool LoadFromData(type* pKeyFrames, UINT uFrameCount)
00032 {
00033 assert(0!=uFrameCount);
00034 assert(NULL!=pKeyFrames);
00035
00036 if(!m_Frames.Init(uFrameCount))
00037 {
00038 return false;
00039 }
00040
00041 if(!m_Frames.CopyIn(pKeyFrames, uFrameCount))
00042 {
00043 return false;
00044 }
00045
00046 return true;
00047 }
00048
00049
00050
00051 void GetLerpValAt(float fPos, type* pOut)
00052 {
00053 assert(NULL!=pOut);
00054 assert(fPos<=1.0f);
00055 assert(fPos>=0.0f);
00056
00057
00058 float fMid=(m_Frames.GetCount()-1)*fPos;
00059
00060 float fFloor=(float)floor(fMid);
00061 float fCeil=(float)ceil(fMid);
00062
00063 UINT uFloor;
00064 UINT uCeil;
00065
00066 FloatToInt((int*)&uFloor, fFloor);
00067 FloatToInt((int*)&uCeil, fCeil);
00068
00069
00070
00071
00072 float fLerpAmt=fMid-uFloor;
00073
00074 assert(fLerpAmt<=1.0f);
00075 assert(fLerpAmt>=0.0f);
00076
00077
00078 type Floor, Ceil;
00079
00080 m_Frames.GetValAt(uFloor, &Floor);
00081 m_Frames.GetValAt(uCeil, &Ceil);
00082
00083 BlakeUtilLerp(fLerpAmt, &Floor, &Ceil, pOut);
00084 }
00085
00086
00087
00088 void GetQuadInterpValAt(float fPos, type* pOut)
00089 {
00090 assert(NULL!=pOut);
00091 assert(fPos<=1.0f);
00092 assert(fPos>=0.0f);
00093
00094 UINT uFrameCount=m_Frames.GetCount();
00095
00096 if(uFrameCount<=2)
00097 {
00098 GetLerpValAt(fPos, pOut);
00099 return;
00100 }
00101
00102
00103 float fMid=uFrameCount*fPos;
00104
00105 UINT uFloor, uCeil;
00106 float fFloor, fCeil;
00107
00108 fFloor=(float)(floor(fMid));
00109 fCeil=(float)(ceil(fMid));
00110
00111 FloatToInt((int*)&uFloor, fFloor);
00112 FloatToInt((int*)&uCeil, fCeil);
00113
00114
00115
00116
00117 UINT uMid;
00118
00119
00120
00121
00122 if((uFloor>0) && ((uFloor%2)==1))
00123 {
00124
00125 uMid=uFloor;
00126 --uFloor;
00127 }
00128
00129 else if ((uCeil<(uFrameCount-1)) && ((uCeil%2)==1))
00130 {
00131 uMid=uCeil;
00132 ++uCeil;
00133 }
00134 else
00135 {
00136 assert(0&&"Got to unreachable in GetQuadInterpValAt()");
00137 }
00138
00139
00140 float fInterpAmt=(fMid-uFloor)/2;
00141
00142 assert(fInterpAmt<=1.0f);
00143 assert(fInterAmt>=0.0f);
00144
00145 type Floor, Mid, Ceil;
00146
00147 m_Frames.GetValAt(uFloor, &Floor);
00148 m_Frames.GetValAt(uMid, &Mid);
00149 m_Frames.GetValAt(uCeil, &Ceil);
00150
00151 BlakeUtilQuaderp(fInterpAmt, &Floor, &Ceil, &Mid, pOut);
00152 }
00153
00154
00155 UINT GetFrameCount()
00156 {
00157 return m_Frames.GetCount();
00158 }
00159
00160 bool LoadFromKeyframeTemplate(CGXKeyframeTemplate<type>& In)
00161 {
00162 if(!m_Frames.Init(In.GetFrameCount()))
00163 {
00164 return false;
00165 }
00166
00167 if(!m_Frames.CopyIn(In.m_Frames.GetPtr(), In.GetFrameCount()))
00168 {
00169 return false;
00170 }
00171
00172 return true;
00173 }
00174
00175 protected:
00176 CGXAutoArray<type> m_Frames;
00177 };
00178
00179
00180
00181
00182
00183
00184
00185 #endif