Files
FC1/CryAnimation/ControllerCryBone.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

167 lines
4.1 KiB
C++

#include "stdafx.h"
#include "Controller.h"
#include "ControllerCryBone.h"
#include "CryKeyInterpolation.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static const bool g_bOptimizeAndLogKeys = false;
CControllerCryBone::CControllerCryBone():
m_nControllerId(0),
m_arrTimes ("CControllerCryBone.Keys"),
m_arrKeys ("CControllerCryBone.Keys")
{
}
CControllerCryBone::~CControllerCryBone()
{
}
// Loads (initializes) controller from the given chunk. The chunk descriptor is followed by the
// chunk data immediately, Returns true if successful.
bool CControllerCryBone::Load (const CONTROLLER_CHUNK_DESC_0826* pChunk, float fScale)
{
//m_Chunk = *pChunk;
m_nControllerId = pChunk->nControllerId;
if(pChunk->chdr.ChunkType != ChunkType_Controller || pChunk->chdr.ChunkVersion != CONTROLLER_CHUNK_DESC_0826::VERSION)
{
m_nControllerId = 0;
GetLog()->LogToFile("CControllerCryBone::Load: File version error");
return false;
}
if (pChunk->type != CTRL_CRYBONE)
return false;
unsigned i, numKeys = pChunk->nKeys;
m_arrKeys.reinit(numKeys);
m_arrTimes.reinit (numKeys);
{
const CryBoneKey * pCryBoneKey = (const CryBoneKey*)(pChunk+1); // iterator through the original keys
int *pTime = m_arrTimes.begin();
PQLog* pKey = m_arrKeys.begin();
CryQuat qLast; // the last orientation
for (i = 0; i < numKeys; ++i)
{
m_arrTimes[i] = pCryBoneKey->time;
m_arrKeys[i].vPos = pCryBoneKey->relpos * fScale;
// make sure we don't make >PI rotations per keyframe
if ( (qLast|(pCryBoneKey->relquat)) >= 0)
qLast = pCryBoneKey->relquat;
else
qLast = -pCryBoneKey->relquat;
m_arrKeys[i].vRotLog = log(qLast).v;
++pCryBoneKey, ++pTime, ++pKey;
}
}
return true;
}
// Loads (initializes) controller from the given chunk. The chunk descriptor is followed by the
// chunk data immediately. Returns true if successful
bool CControllerCryBone::Load (const CONTROLLER_CHUNK_DESC_0827* pChunk, unsigned nSize, float fScale)
{
m_nControllerId = pChunk->nControllerId;
unsigned numKeys = pChunk->numKeys;
const CryKeyPQLog* pCryKey = (const CryKeyPQLog*)(pChunk+1);
if ((const char*)(pCryKey + numKeys) > ((const char*)pChunk) + nSize)
{
GetLog()->LogError ("\002CControllerCryBone::Load: cannot load controller 0x%08X, chunk is truncated",
m_nControllerId);
return false;
}
m_arrKeys.reinit (numKeys);
m_arrTimes.reinit (numKeys);
int *pTime = m_arrTimes.begin();
PQLog* pKey = m_arrKeys.begin();
for (unsigned i = 0; i < numKeys; ++i)
{
m_arrTimes[i] = pCryKey->nTime;
m_arrKeys[i].vPos = pCryKey->vPos * fScale;
m_arrKeys[i].vRotLog = pCryKey->vRotLog;
++pCryKey, ++pTime, ++pKey;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// retrieves the position and orientation (in the logarithmic space,
// i.e. instead of quaternion, its logarithm is returned)
// may be optimal for motion interpolation
void CControllerCryBone::GetValue2 (float fTime, PQLog& pq)
{
assert(numKeys());
if(!(m_arrTimes[0] < fTime))
{
pq = m_arrKeys[0];
return ;
}
if(m_arrTimes[numKeys()-1] <= fTime)
{
pq = m_arrKeys[numKeys()-1];
return ;
}
assert(numKeys()>1);
int nPos = numKeys()>>1;
int nStep = numKeys()>>2;
// use binary search
while(nStep)
{
if(fTime < m_arrTimes[nPos])
nPos = nPos - nStep;
else
if(fTime > m_arrTimes[nPos])
nPos = nPos + nStep;
else
break;
nStep = nStep>>1;
}
// finetuning needed since time is not linear
while(fTime > m_arrTimes[nPos])
nPos++;
while(fTime < m_arrTimes[nPos-1])
nPos--;
assert(nPos > 0 && nPos < (int)numKeys());
assert(m_arrTimes[nPos] != m_arrTimes[nPos-1]);
float t = (float(fTime-m_arrTimes[nPos-1]))/(m_arrTimes[nPos] - m_arrTimes[nPos-1]);
PQLog pKeys[2] = {m_arrKeys[nPos-1], m_arrKeys[nPos]};
AdjustLogRotations (pKeys[0].vRotLog, pKeys[1].vRotLog);
pq.blendPQ (pKeys, t);
}
ILog* CControllerCryBone::GetLog() const
{
return g_GetLog();
}
size_t CControllerCryBone::sizeofThis ()const
{
return sizeof(*this) + m_arrKeys.size() * (sizeof(m_arrKeys[0])+sizeof(m_arrTimes[0]));
}