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

187 lines
5.4 KiB
C++

#include "stdafx.h"
#include "MathUtils.h"
#include "CryBoneDesc.h"
#include "StringUtils.h"
using namespace CryStringUtils;
CryBoneDesc::CryBoneDesc()
{
m_PhysInfo[0].pPhysGeom = m_PhysInfo[1].pPhysGeom = 0;
m_matInvDefGlobal.SetIdentity();; // allows to get difference to def pose matrices
}
CryBoneDesc::~CryBoneDesc()
{
}
//////////////////////////////////////////////////////////////////////////
// loads the bone from a raw chunk data (no header)
// PARAMETERS:
// pEntity - the chunk data to load the bone info from
// RETURNS:
// false if the bone couldn't be loaded
bool CryBoneDesc::LoadRaw (const BONE_ENTITY* pEntity)
{
//read bone info
assert(pEntity->nChildren<200);
// update the lod 0 physics of this bone
UpdatePhysics (*pEntity, 0);
//get bone info
m_nControllerID = pEntity->ControllerID;
return true;
}
//////////////////////////////////////////////////////////////////////////
// updates this bone physics, from the given entity descriptor, and of the given lod
void CryBoneDesc::UpdatePhysics (const BONE_ENTITY& entity, int nLod)
{
assert (nLod >= 0 && nLod < SIZEOF_ARRAY(m_PhysInfo));
CopyPhysInfo(m_PhysInfo[nLod], entity.phys);
int nFlags = 0;
if (entity.prop[0])
{
nFlags = joint_no_gravity|joint_isolated_accelerations;
}
else
{
if (!strnstr(entity.prop,"gravity", sizeof(entity.prop)))
nFlags |= joint_no_gravity;
if (!strnstr(entity.prop,"physical",sizeof(entity.prop)))
nFlags |= joint_isolated_accelerations;
}
m_PhysInfo[nLod].flags |= nFlags;
}
//! Performs post-initialization. This step is requred to initialize the pPhysGeom of the bones
//! After the bone has been loaded but before it is first used. When the bone is first loaded, pPhysGeom
//! is set to the value equal to the chunk id in the file where the physical geometry (BoneMesh) chunk is kept.
//! After those chunks are loaded, and chunk ids are mapped to the registered physical geometry objects,
//! call this function to replace pPhysGeom chunk ids with the actual physical geometry object pointers.
//! RETURNS:
// true if the corresponding physical geometry object has been found
//! NOTE:
//! The entries of the map that were used are deleted
bool CryBoneDesc::PostInitPhysGeom (ChunkIdToPhysGeomMap& mapChunkIdToPhysGeom, int nLodLevel)
{
phys_geometry*& pPhysGeom = m_PhysInfo[nLodLevel].pPhysGeom;
ChunkIdToPhysGeomMap::iterator it = mapChunkIdToPhysGeom.find ((INT_PTR)pPhysGeom);
if (it != mapChunkIdToPhysGeom.end())
{
// remap the chunk id to the actual pointer to the geometry
pPhysGeom = it->second;
mapChunkIdToPhysGeom.erase (it);
return true;
}
else
{
pPhysGeom = NULL;
return false;
}
}
// sets the name of the bone out of the given buffer of the given max size
void CryBoneDesc::setName (const char* szName)
{
m_strName.assign (szName);
static const char *g_arrLimbNames[4] = { "L UpperArm","R UpperArm","L Thigh","R Thigh" };
m_nLimbId = -1;
for (int j=0; j < SIZEOF_ARRAY(g_arrLimbNames) ;j++)
if (strstr(szName,g_arrLimbNames[j]))
{
m_nLimbId = j;
break;
}
}
// returns the bone name, if available
const char* CryBoneDesc::getNameCStr()const
{
return m_strName.c_str();
}
const string& CryBoneDesc::getName()const
{
return m_strName;
}
// compares two bone descriptions and returns true if they're the same bone
// (the same name and the same position in the hierarchy)
bool CryBoneDesc::isEqual (const CryBoneDesc& desc)const
{
return m_strName == desc.m_strName
&& m_nControllerID == desc.m_nControllerID
&& m_nOffsetParent == desc.m_nOffsetParent
&& m_numChildren == desc.m_numChildren
&& m_nOffsetChildren == desc.m_nOffsetChildren;
}
inline size_t align4 (size_t x)
{
return (x + 3)&~3;
}
// Serializes the description:
// returns the number of required bytes for serialization, if the data pointer is NULL
// returns 0 (if the buffer size is not enough) or the number of bytes written, if the data pointer is given
unsigned CryBoneDesc::Serialize (bool bSave, void *pStream, unsigned nSize)
{
if (bSave)
{
unsigned nSizeRequired = (unsigned)(sizeof(CryBoneDescData_Comp) + align4 (m_strName.length()+1));
if (!pStream)
return nSizeRequired;
if (nSize < nSizeRequired)
return 0;
CopyCryBone(*(CryBoneDescData_Comp*)pStream, *this);
memcpy ((CryBoneDescData_Comp*)pStream+1,m_strName.c_str(),m_strName.length()+1);
return nSizeRequired;
}
else
{
if (!pStream)
return 0;
if (nSize < sizeof(CryBoneDescData_Comp)+1)
return 0;
if (nSize & 3)
return 0; // alignment error
CopyCryBone(*this, *(CryBoneDescData_Comp*)pStream);
// end of the stream
const char* pEnd = (const char*)pStream + nSize;
// the start byte of the bone name
const char* pName = (const char*)((CryBoneDescData_Comp*)pStream+1);
// scan until the end of the name (\0 char) or the stream (pEnd address)
const char *pNameEnd;
for (pNameEnd = pName; pNameEnd < pEnd && *pNameEnd; ++pNameEnd);
m_strName.assign (pName, pNameEnd);
// return aligned size of the chunk including the string 0 terminator, but
// no more than the declared size of the stream
return min(nSize, (unsigned)align4 (pNameEnd+1-(const char*)pStream));
}
}
void CryBoneDesc::setDefaultGlobal(const Matrix44& matDefault)
{
m_matInvDefGlobal=OrthoUniformGetInverted (matDefault);
}
// scales the bone with the given multiplier
void CryBoneDesc::scale (float fScale)
{
m_matInvDefGlobal.SetTranslationOLD(m_matInvDefGlobal.GetTranslationOLD()*fScale);
}