////////////////////////////////////////////////////////////////////////// // // Crytek Character Animation source code // // File:CryBoneDesc.h // // History: // Created by Sergiy Migdalskiy 01/14/2003 // ///////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _CRY_BONE_DESC_HDR_ #define _CRY_BONE_DESC_HDR_ // this class contains the information that's common to all instances of bones // in the given model: like bone name, and misc. shared properties // We use a base structure to separate the bunch of parameters that get serialized // together #pragma pack(push,4) template struct TCryBoneDescData { unsigned int m_nControllerID; // unic id of bone (generated from bone name in the max) // [Sergiy] physics info for different lods // lod 0 is the physics of alive body, lod 1 is the physics of a dead body TBonePhysics m_PhysInfo[2]; float m_fMass; Matrix44 m_matInvDefGlobal; // allows to get difference to def pose matrices int m_nLimbId; // set by model state class // this bone parent is this[m_nOffsetParent], 0 if the bone is root. Normally this is <= 0 int m_nOffsetParent; // The whole hierarchy of bones is kept in one big array that belongs to the ModelState // Each bone that has children has its own range of bone objects in that array, // and this points to the beginning of that range and defines the number of bones. unsigned m_numChildren; // the beginning of the subarray of children is at this[m_nOffsetChildren] // this is 0 if there are no children int m_nOffsetChildren; }; typedef TCryBoneDescData CryBoneDescData; // compatible structure typedef TCryBoneDescData CryBoneDescData_Comp; #define __copy(x) left.x = right.x inline void CopyCryBone (CryBoneDescData_Comp& left, const CryBoneDescData& right) { __copy(m_nControllerID); CopyPhysInfo (left.m_PhysInfo[0], right.m_PhysInfo[0]); CopyPhysInfo (left.m_PhysInfo[1], right.m_PhysInfo[1]); __copy(m_fMass); __copy(m_matInvDefGlobal); __copy(m_nLimbId); __copy(m_nOffsetParent); __copy(m_numChildren); __copy(m_nOffsetChildren); } inline void CopyCryBone (CryBoneDescData& left, const CryBoneDescData_Comp& right) { __copy(m_nControllerID); CopyPhysInfo (left.m_PhysInfo[0], right.m_PhysInfo[0]); CopyPhysInfo (left.m_PhysInfo[1], right.m_PhysInfo[1]); __copy(m_fMass); __copy(m_matInvDefGlobal); __copy(m_nLimbId); __copy(m_nOffsetParent); __copy(m_numChildren); __copy(m_nOffsetChildren); } #undef __copy #pragma pack(pop) class CryBoneDesc: public CryBoneDescData { public: CryBoneDesc (); ~CryBoneDesc (); // returns the bone name, if available const char* getNameCStr()const; const string& getName()const; unsigned getControllerId()const {return m_nControllerID;} // sets the name of the bone out of the given buffer of the given max size void setName (const char* szName); unsigned numChildren ()const {return m_numChildren;} bool hasParent() const {return m_nOffsetParent != 0;} int getParentIndexOffset()const {return m_nOffsetParent;} int getFirstChildIndexOffset() const {return m_nOffsetChildren;} const Matrix44& getInvDefGlobal() const {return m_matInvDefGlobal;} void setDefaultGlobal(const Matrix44& mxDefault); int getLimbId () const {return m_nLimbId;} BONE_PHYSICS& getPhysInfo (int nLod) {return m_PhysInfo[nLod];} // updates this bone physics, from the given entity descriptor, and of the given lod void UpdatePhysics (const BONE_ENTITY& entity, int nLod); void setPhysics (int nLod, const BONE_PHYSICS& BonePhysics) { assert (nLod >= 0 && nLod < sizeof(m_PhysInfo)/sizeof(m_PhysInfo[0])); m_PhysInfo[nLod] = BonePhysics; } // the physics for the given LOD is not available void resetPhysics (int nLod) { assert (nLod >= 0 && nLod < sizeof(m_PhysInfo)/sizeof(m_PhysInfo[0])); memset (&m_PhysInfo[nLod], 0, sizeof(m_PhysInfo[nLod])); } const BONE_PHYSICS& getPhysics (int nLod)const { assert (nLod >= 0 && nLod < sizeof(m_PhysInfo)/sizeof(m_PhysInfo[0])); return m_PhysInfo[nLod]; } // Returns the id of the bone mesh chunk from which the bone physical geometry // should be taken. The caller should take this id, find the corresponding chunk in the CCG/CGF file // and construct physical geometry using IGeomManager::CreateMesh. // Then, register it with RegisterGeometry(). It will return phys_geometry* that the caller // should put into the corresponding LOD m_PhysInfo.pPhysGeom // CryBoneInfo::PostInitPhysGeom uses this same id to find the physical geometry in the map INT_PTR getPhysGeomId (unsigned nLOD) {return (INT_PTR)m_PhysInfo[nLOD].pPhysGeom;} // compares two bone descriptions and returns true if they're the same bone // (the same name and the same position in the hierarchy) bool isEqual(const CryBoneDesc& desc)const; // 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 Serialize (bool bSave, void *pStream, unsigned nSize); // scales the bone with the given multiplier void scale (float fScale); protected: // loads the bone from a raw chunk data (no header) // returns false if the bone couldn't be loaded bool LoadRaw (const BONE_ENTITY* pEntity); //! 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. //! NOTE: //! The entries of the map that were used are deleted typedef std::map ChunkIdToPhysGeomMap; bool PostInitPhysGeom (ChunkIdToPhysGeomMap& mapChunkIdToPhysGeom, int nLodLevel); friend class CryBoneHierarchyLoader; protected: string m_strName; }; #endif