00001 #include "RakAssert.h"
00002 #include "RakMemoryOverride.h"
00003 #include "TransformationHistory.h"
00004
00005 TransformationHistoryCell::TransformationHistoryCell()
00006 {
00007
00008 }
00009 TransformationHistoryCell::TransformationHistoryCell(RakNetTime t, const Ogre::Vector3& pos, const Ogre::Vector3& vel, const Ogre::Quaternion& quat ) :
00010 time(t),
00011 velocity(vel),
00012 position(pos),
00013 orientation(quat)
00014 {
00015 }
00016
00017 void TransformationHistory::Init(RakNetTime maxWriteInterval, RakNetTime maxHistoryTime)
00018 {
00019 writeInterval=maxWriteInterval;
00020 maxHistoryLength = maxHistoryTime/maxWriteInterval+1;
00021 history.ClearAndForceAllocation(maxHistoryLength+1, __FILE__, __LINE__ );
00022 RakAssert(writeInterval>0);
00023 }
00024 void TransformationHistory::Write(const Ogre::Vector3 &position, const Ogre::Vector3 &velocity, const Ogre::Quaternion &orientation, RakNetTime curTimeMS)
00025 {
00026 if (history.Size()==0)
00027 {
00028 history.Push(TransformationHistoryCell(curTimeMS,position,velocity,orientation), __FILE__, __LINE__ );
00029 }
00030 else
00031 {
00032 const TransformationHistoryCell &lastCell = history.PeekTail();
00033 if (curTimeMS-lastCell.time>=writeInterval)
00034 {
00035 history.Push(TransformationHistoryCell(curTimeMS,position,velocity,orientation), __FILE__, __LINE__ );
00036 if (history.Size()>maxHistoryLength)
00037 history.Pop();
00038 }
00039 }
00040 }
00041 void TransformationHistory::Overwrite(const Ogre::Vector3 &position, const Ogre::Vector3 &velocity, const Ogre::Quaternion &orientation, RakNetTime when)
00042 {
00043 int historySize = history.Size();
00044 if (historySize==0)
00045 {
00046 history.Push(TransformationHistoryCell(when,position,velocity,orientation), __FILE__, __LINE__ );
00047 }
00048 else
00049 {
00050
00051 int i;
00052 for (i=historySize-1; i>=0; i--)
00053 {
00054 TransformationHistoryCell &cell = history[i];
00055 if (when >= cell.time)
00056 {
00057 if (i==historySize-1 && when-cell.time>=writeInterval)
00058 {
00059
00060 history.Push(TransformationHistoryCell(when,position,velocity,orientation), __FILE__, __LINE__ );
00061 if (history.Size()>maxHistoryLength)
00062 history.Pop();
00063 return;
00064 }
00065
00066 cell.time=when;
00067 cell.position=position;
00068 cell.velocity=velocity;
00069 cell.orientation=orientation;
00070 return;
00071 }
00072 }
00073 }
00074 }
00075 TransformationHistory::ReadResult TransformationHistory::Read(Ogre::Vector3 *position, Ogre::Vector3 *velocity, Ogre::Quaternion *orientation,
00076 RakNetTime when, RakNetTime curTime)
00077 {
00078 int historySize = history.Size();
00079 if (historySize==0)
00080 {
00081 return VALUES_UNCHANGED;
00082 }
00083
00084 int i;
00085 for (i=historySize-1; i>=0; i--)
00086 {
00087 const TransformationHistoryCell &cell = history[i];
00088 if (when >= cell.time)
00089 {
00090 if (i==historySize-1)
00091 {
00092 if (curTime<=cell.time)
00093 return VALUES_UNCHANGED;
00094
00095 float divisor = (float)(curTime-cell.time);
00096 RakAssert(divisor!=0.0f);
00097 float lerp = (float)(when - cell.time) / divisor;
00098 if (position)
00099 *position=cell.position + (*position-cell.position) * lerp;
00100 if (velocity)
00101 *velocity=cell.velocity + (*velocity-cell.velocity) * lerp;
00102 if (orientation)
00103 *orientation = Ogre::Quaternion::Slerp(lerp, cell.orientation, *orientation,true);
00104 }
00105 else
00106 {
00107 const TransformationHistoryCell &nextCell = history[i+1];
00108 float divisor = (float)(nextCell.time-cell.time);
00109 RakAssert(divisor!=0.0f);
00110 float lerp = (float)(when - cell.time) / divisor;
00111 if (position)
00112 *position=cell.position + (nextCell.position-cell.position) * lerp;
00113 if (velocity)
00114 *velocity=cell.velocity + (nextCell.velocity-cell.velocity) * lerp;
00115 if (orientation)
00116 *orientation = Ogre::Quaternion::Slerp(lerp, cell.orientation, nextCell.orientation,true);
00117 }
00118 return INTERPOLATED;
00119 }
00120 }
00121
00122
00123 const TransformationHistoryCell &cell = history.Peek();
00124 if (position)
00125 *position=cell.position;
00126 if (orientation)
00127 *orientation=cell.orientation;
00128 if (velocity)
00129 *velocity=cell.velocity;
00130 return READ_OLDEST;
00131 }
00132 void TransformationHistory::Clear(void)
00133 {
00134 history.Clear(__FILE__, __LINE__);
00135 }