717 lines
18 KiB
C++
717 lines
18 KiB
C++
#include "StdAfx.h"
|
|
#include "AnimObject.h"
|
|
#include "StringUtils.h"
|
|
#include "cvars.h"
|
|
#include "DebugUtils.h"
|
|
|
|
#include <I3DEngine.h>
|
|
#include <IMovieSystem.h>
|
|
#include <ITimer.h>
|
|
#include "CryCharAnimationParams.h"
|
|
#include "Cry_Geo.h"
|
|
|
|
using namespace CryStringUtils;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimObject::CAnimObject()
|
|
{
|
|
m_nRefCount = 0;
|
|
m_characterModel.animSet.obj = this;
|
|
m_characterModel.pAnimObject = this;
|
|
|
|
m_bbox[0]=SetMaxBB();
|
|
m_bbox[1]=SetMinBB();
|
|
|
|
m_angles(0,0,0);
|
|
|
|
m_nFlags = CS_FLAG_UPDATE|CS_FLAG_DRAW_MODEL;
|
|
m_bNoTimeUpdate = false;
|
|
m_currAnimation = 0;
|
|
|
|
m_bAllNodesValid = false;
|
|
m_bboxValid = false;
|
|
|
|
m_time = 0;
|
|
m_animSpeed = 1;
|
|
m_physic = 0;
|
|
m_lastAnimTime = -1;
|
|
m_lastScale = 1.0f;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimObject::~CAnimObject()
|
|
{
|
|
ReleaseNodes();
|
|
ReleaseAnims();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::ReleaseNodes()
|
|
{
|
|
I3DEngine *engine = Get3DEngine();
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
Node *pNode = m_nodes[i];
|
|
if (pNode->m_object)
|
|
engine->ReleaseObject( pNode->m_object );
|
|
|
|
delete pNode;
|
|
}
|
|
m_nodes.clear();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::ReleaseAnims()
|
|
{
|
|
for (unsigned int i = 0; i < m_animations.size(); i++)
|
|
{
|
|
delete m_animations[i];
|
|
}
|
|
m_animations.clear();
|
|
m_currAnimation = 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//! set name of geometry for this animated object.
|
|
void CAnimObject::SetFileName( const char *szFileName )
|
|
{
|
|
m_fileName = szFileName;
|
|
UnifyFilePath( m_fileName );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimObject::Node* CAnimObject::CreateNode( const char *szNodeName )
|
|
{
|
|
// Try to create object.
|
|
I3DEngine *engine = Get3DEngine();
|
|
IStatObj *obj = engine->MakeObject( m_fileName.c_str(),szNodeName,evs_ShareAndSortForCache,true,true );
|
|
if (obj)
|
|
{
|
|
AddToBounds( obj->GetBoxMin(), m_bbox[0],m_bbox[1] );
|
|
AddToBounds( obj->GetBoxMax(), m_bbox[0],m_bbox[1] );
|
|
}
|
|
|
|
Node *node = new Node;
|
|
node->m_name = szNodeName;
|
|
node->m_object = obj;
|
|
node->m_id = (int)m_nodes.size();
|
|
|
|
m_nodes.push_back(node);
|
|
|
|
return node;
|
|
}
|
|
|
|
//! Render object ( register render elements into renderer )
|
|
void CAnimObject::Render(const struct SRendParams & rParams,const Vec3& t, int nLodLevel)
|
|
{
|
|
Draw (rParams,Vec3(123,123,123));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::Draw( const SRendParams &rp, const Vec3& t )
|
|
{
|
|
SRendParams nodeRP = rp;
|
|
Matrix44 renderTM;
|
|
if (rp.pMatrix)
|
|
{
|
|
renderTM = *rp.pMatrix;
|
|
}
|
|
else
|
|
{
|
|
//renderTM.Identity();
|
|
//renderTM=GetTranslationMat(rp.vPos)*renderTM;
|
|
//renderTM=GetRotationZYX44(-gf_DEGTORAD*rp.vAngles )*renderTM; //NOTE: angles in radians and negated
|
|
//renderTM=GetScale33(Vec3(rp.fScale,rp.fScale,rp.fScale))*renderTM;
|
|
|
|
//OPTIMISED_BY_IVO
|
|
Matrix33diag diag = Vec3(rp.fScale,rp.fScale,rp.fScale); //use diag-matrix for scaling
|
|
Matrix34 rt34 = Matrix34::CreateRotationXYZ( Deg2Rad(rp.vAngles),rp.vPos ); //set rotation and translation in one function call
|
|
renderTM = rt34*diag; //optimised concatenation: m34*diag
|
|
renderTM=GetTransposed44(renderTM); //TODO: remove this after E3 and use Matrix34 instead of Matrix44
|
|
}
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
Node *node = m_nodes[i];
|
|
if (node->m_object)
|
|
{
|
|
Matrix44 tm = GetNodeMatrix(node) * renderTM;
|
|
nodeRP.pMatrix = &tm;
|
|
nodeRP.dwFObjFlags |= FOB_TRANS_MASK;
|
|
m_nodes[i]->m_object->Render(nodeRP,Vec3(zero),0);
|
|
}
|
|
}
|
|
DrawBoundObjects( rp,renderTM,0 );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//! Draw the character shadow volumes into the stencil buffer using a set of specified
|
|
//! rendering parameters ( for indoors )
|
|
void CAnimObject::RenderShadowVolumes(const SRendParams *rParams, int nLimitLOD)
|
|
{
|
|
const SRendParams &rp = *rParams;
|
|
|
|
SRendParams nodeRP = rp;
|
|
Matrix44 renderTM;
|
|
if (rp.pMatrix)
|
|
{
|
|
renderTM = *rp.pMatrix;
|
|
}
|
|
else
|
|
{
|
|
//renderTM.Identity();
|
|
//renderTM=GetTranslationMat(rp.vPos)*renderTM;
|
|
//renderTM=GetRotationZYX44(-gf_DEGTORAD*rp.vAngles )*renderTM; //NOTE: angles in radians and negated
|
|
//renderTM=GetScale33(Vec3(rp.fScale,rp.fScale,rp.fScale))*renderTM;
|
|
|
|
//OPTIMISED_BY_IVO
|
|
Matrix33diag diag = Vec3(rp.fScale,rp.fScale,rp.fScale); //use diag-matrix for scaling
|
|
Matrix34 rt34 = Matrix34::CreateRotationXYZ(Deg2Rad(rp.vAngles),rp.vPos); //set rotation and translation in one function call
|
|
renderTM = rt34*diag; //optimised concatenation: m34*diag
|
|
renderTM=GetTransposed44(renderTM); //TODO: remove this after E3 and use Matrix34 instead of Matrix44
|
|
|
|
}
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
Node *node = m_nodes[i];
|
|
if (node->m_object)
|
|
{
|
|
Matrix44 tm = GetNodeMatrix(node) * renderTM;
|
|
nodeRP.pMatrix = &tm;
|
|
m_nodes[i]->m_object->RenderShadowVolumes(&nodeRP);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::Animate( float time )
|
|
{
|
|
if (!m_currAnimation)
|
|
return;
|
|
|
|
|
|
if (m_currAnimation->loop)
|
|
{
|
|
float timelen = m_currAnimation->endTime - m_currAnimation->startTime;
|
|
time = m_currAnimation->startTime + cry_fmod( time,timelen );
|
|
}
|
|
else
|
|
{
|
|
time = m_currAnimation->startTime + time;
|
|
}
|
|
if (time < 0)
|
|
{
|
|
// Go negative.
|
|
time = m_currAnimation->endTime + time;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
Node *node = m_nodes[i];
|
|
NodeAnim *nodeAnim = GetNodeAnim(node);
|
|
if (node->m_object && nodeAnim)
|
|
{
|
|
if (!m_bAllNodesValid)
|
|
{
|
|
node->m_pos = nodeAnim->m_pos;
|
|
node->m_scale = nodeAnim->m_scale;
|
|
node->m_rotate = nodeAnim->m_rotate;
|
|
node->m_bMatrixValid = false;
|
|
}
|
|
if (nodeAnim->m_posTrack)
|
|
{
|
|
node->m_pos = nodeAnim->m_posTrack->GetPosition( time );
|
|
node->m_bMatrixValid = false;
|
|
// Bounding box can change.
|
|
m_bboxValid = false;
|
|
}
|
|
if (nodeAnim->m_rotTrack)
|
|
{
|
|
node->m_rotate = nodeAnim->m_rotTrack->GetOrientation( time );
|
|
node->m_bMatrixValid = false;
|
|
m_bboxValid = false;
|
|
}
|
|
if (nodeAnim->m_scaleTrack)
|
|
{
|
|
node->m_scale = nodeAnim->m_scaleTrack->GetScale( time );
|
|
node->m_bMatrixValid = false;
|
|
m_bboxValid = false;
|
|
}
|
|
}
|
|
}
|
|
//m_bboxValid = false;
|
|
|
|
m_bAllNodesValid = true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::RecalcBBox()
|
|
{
|
|
AABB box;
|
|
m_bbox[0]=SetMaxBB();
|
|
m_bbox[1]=SetMinBB();
|
|
// Re calc bbox.
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
Node *node = m_nodes[i];
|
|
Matrix44 &tm = GetNodeMatrix(node);
|
|
if (node->m_object)
|
|
{
|
|
box.min = node->m_object->GetBoxMin();
|
|
box.max = node->m_object->GetBoxMax();
|
|
box.Transform( tm );
|
|
AddToBounds( box.min, m_bbox[0],m_bbox[1] );
|
|
AddToBounds( box.max, m_bbox[0],m_bbox[1] );
|
|
}
|
|
}
|
|
m_bboxValid = true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
Matrix44& CAnimObject::GetNodeMatrix( Node *node )
|
|
{
|
|
// fixme.
|
|
node->m_bMatrixValid = false;
|
|
|
|
|
|
assert(node);
|
|
if (!node->m_bMatrixValid)
|
|
{
|
|
// Make local matrix.
|
|
//Q2M_CHANGED_BY_IVO
|
|
//node->m_rotate.GetMatrix(node->m_tm);
|
|
//node->m_tm = GetTransposed44(node->m_rotate);
|
|
node->m_tm = Matrix44(node->m_rotate);
|
|
|
|
|
|
//SCALE_CHANGED_BY_IVO
|
|
//node->m_tm.ScaleMatrix( node->m_scale.x,node->m_scale.y,node->m_scale.z );
|
|
node->m_tm = Matrix33::CreateScale( Vec3(node->m_scale.x,node->m_scale.y,node->m_scale.z) ) * node->m_tm;
|
|
|
|
node->m_tm.SetTranslationOLD( node->m_pos );
|
|
node->m_bMatrixValid = true;
|
|
|
|
if (node->m_parent)
|
|
{
|
|
// Combine with parent matrix.
|
|
Matrix44 &parentTM = GetNodeMatrix(node->m_parent);
|
|
node->m_tm = node->m_tm * parentTM;
|
|
}
|
|
}
|
|
|
|
return node->m_tm;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimObject::NodeAnim* CAnimObject::GetNodeAnim( Node *node )
|
|
{
|
|
if (!m_currAnimation)
|
|
return 0;
|
|
if (node->m_id >= (int)m_currAnimation->nodeAnims.size())
|
|
{
|
|
return 0;
|
|
}
|
|
return &(m_currAnimation->nodeAnims[node->m_id]);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::AddAnimation( Animation* anim )
|
|
{
|
|
m_animations.push_back(anim);
|
|
if (m_animations.size() == 1)
|
|
{
|
|
// First anim, make current.
|
|
m_currAnimation = anim;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::RemoveAnimation( Animation* anim )
|
|
{
|
|
m_animations.erase( std::remove(m_animations.begin(),m_animations.end(),anim),m_animations.end() );
|
|
if (m_currAnimation = anim)
|
|
{
|
|
if (!m_animations.empty())
|
|
m_currAnimation = m_animations[0];
|
|
else
|
|
m_currAnimation = 0;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimObject::Animation* CAnimObject::FindAnimation( const char *szAnimationName )
|
|
{
|
|
for (unsigned int i = 0; i < m_animations.size(); i++)
|
|
{
|
|
if (stricmp(m_animations[i]->name.c_str(),szAnimationName)==0)
|
|
{
|
|
return m_animations[i];
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CAnimObject::FindNodeByName( const char *szNodeName )
|
|
{
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
if (stricmp(m_nodes[i]->m_name.c_str(),szNodeName)==0)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const char* CAnimObject::GetNodeName( int nodeId )
|
|
{
|
|
if (nodeId > 0 && nodeId < (int)m_nodes.size())
|
|
return m_nodes[nodeId]->m_name.c_str();
|
|
return "";
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::SetCurrent( Animation *anim )
|
|
{
|
|
if (anim != m_currAnimation)
|
|
{
|
|
m_time = 0;
|
|
m_lastAnimTime = -1;
|
|
m_bAllNodesValid = false;
|
|
m_bboxValid = false;
|
|
m_currAnimation = anim;
|
|
if (m_currAnimation)
|
|
{
|
|
Animate(m_currAnimation->startTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
//! Resets all animation layers ( stops all animations )
|
|
void CAnimObject::ResetAnimations()
|
|
{
|
|
if (m_currAnimation)
|
|
{
|
|
// Animate existing animation to 0.
|
|
Animate(m_currAnimation->startTime);
|
|
}
|
|
SetCurrent(0);
|
|
UpdatePhysics( m_lastScale );
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const CDLight* CAnimObject::GetBoundLight (int nIndex)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::Update( Vec3 vPos, float fRadius, unsigned uFlags)
|
|
{
|
|
if (!(m_nFlags & CS_FLAG_UPDATE))
|
|
return;
|
|
|
|
float m_lastAnimTime = m_time;
|
|
if (!m_bNoTimeUpdate)
|
|
{
|
|
float dt = g_GetTimer()->GetFrameTime();
|
|
m_time = m_time + dt*m_animSpeed;
|
|
|
|
if (m_currAnimation)
|
|
{
|
|
if (!m_currAnimation->loop && !m_currAnimation->haveLoopingController)
|
|
{
|
|
if (m_time > m_currAnimation->endTime)
|
|
m_time = m_currAnimation->endTime;
|
|
if (m_time < m_currAnimation->startTime)
|
|
m_time = m_currAnimation->startTime;
|
|
}
|
|
}
|
|
}
|
|
if (m_lastAnimTime != m_time)
|
|
Animate( m_time );
|
|
}
|
|
|
|
//! Set the current time of the given layer, in seconds
|
|
void CAnimObject::SetLayerTime (int nLayer, float fTimeSeconds)
|
|
{
|
|
m_time = fTimeSeconds;
|
|
m_fAnimTime = fTimeSeconds;
|
|
|
|
if (m_lastAnimTime != m_time)
|
|
Animate( m_time );
|
|
|
|
m_lastAnimTime = m_time;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CAnimObject::IsModelFileEqual (const char* szFileName)
|
|
{
|
|
string strPath = szFileName;
|
|
UnifyFilePath(strPath);
|
|
|
|
return stricmp(strPath.c_str(),m_fileName.c_str()) == 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::CreateDecal(CryEngineDecalInfo& Decal)
|
|
{
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Physics.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
IPhysicalEntity* CAnimObject::CreateCharacterPhysics(IPhysicalEntity *pHost, float mass,int surface_idx,float stiffness_scale, int nLod)
|
|
{
|
|
//m_physic = GetPhysicalWorld()->CreatePhysicalEntity(PE_STATIC,&partpos,(IEntity*)this);
|
|
assert( pHost );
|
|
m_physic = pHost;
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CAnimObject::CreateAuxilaryPhysics(IPhysicalEntity *pHost, int nLod)
|
|
{
|
|
//assert( pHost );
|
|
//m_physic = pHost;
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::BuildPhysicalEntity( IPhysicalEntity *pent,float mass,int surface_idx,float stiffness_scale,int nLod )
|
|
{
|
|
assert( pent );
|
|
|
|
m_physic = pent;
|
|
|
|
unsigned int i;
|
|
float totalVolume = 0;
|
|
|
|
for (i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
Node *node = m_nodes[i];
|
|
if (!node->m_object)
|
|
continue;
|
|
phys_geometry *geom = node->m_object->GetPhysGeom(0);
|
|
if (geom)
|
|
{
|
|
totalVolume += geom->V;
|
|
}
|
|
}
|
|
float density = mass/totalVolume;
|
|
|
|
pe_geomparams params;
|
|
for (i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
Node *node = m_nodes[i];
|
|
if (!node->m_object)
|
|
continue;
|
|
|
|
params.density = density;
|
|
|
|
// Add collision geometry.
|
|
params.flags = geom_collides;
|
|
phys_geometry *geom = node->m_object->GetPhysGeom(0);
|
|
if (geom)
|
|
{
|
|
m_physic->AddGeometry( geom, ¶ms, node->m_id );
|
|
node->bPhysics = true;
|
|
}
|
|
|
|
// Add obstruct geometry.
|
|
params.flags = geom_proxy;
|
|
geom = node->m_object->GetPhysGeom(1);
|
|
if (geom)
|
|
{
|
|
m_physic->AddGeometry( geom, ¶ms, node->m_id );
|
|
node->bPhysics = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::UpdatePhysics( float fScale )
|
|
{
|
|
if (!m_physic)
|
|
return;
|
|
|
|
m_lastScale = fScale;
|
|
|
|
Matrix44 parentTM;
|
|
parentTM.SetIdentity();
|
|
|
|
//SCALE_CHANGED_BY_IVO
|
|
//parentTM.ScaleMatrix( fScale,fScale,fScale );
|
|
parentTM=Matrix33::CreateScale( Vec3(fScale,fScale,fScale) )*parentTM;
|
|
|
|
int numNodes = (int)m_nodes.size();
|
|
pe_params_part params;
|
|
for (int i = 0; i < numNodes; i++)
|
|
{
|
|
Node *node = m_nodes[i];
|
|
if (!node->bPhysics)
|
|
continue;
|
|
|
|
params.partid = node->m_id;
|
|
params.bRecalcBBox = true;
|
|
//if (i == numNodes-1) // last node.
|
|
//params.bRecalcBBox = true;
|
|
|
|
Matrix44 tm = GetNodeMatrix(node) * parentTM;
|
|
params.pMtx4x4T = tm.GetData();
|
|
|
|
m_physic->SetParams( ¶ms );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::AddImpact(int partid, vectorf point,vectorf impact)
|
|
{
|
|
//
|
|
}
|
|
|
|
// Pushes the underlying tree of objects into the given Sizer object for statistics gathering
|
|
void CAnimObject::GetMemoryUsage(class ICrySizer* pSizer)const
|
|
{
|
|
#if ENABLE_GET_MEMORY_USAGE
|
|
if (!pSizer->Add (*this))
|
|
return;
|
|
pSizer->AddString (m_fileName);
|
|
#endif
|
|
}
|
|
|
|
void CAnimObject::Node::GetSize (ICrySizer* pSizer)const
|
|
{
|
|
#if ENABLE_GET_MEMORY_USAGE
|
|
if (!pSizer->Add (*this))
|
|
return;
|
|
pSizer->AddString (m_name);
|
|
m_parent->GetSize(pSizer);
|
|
|
|
if (pSizer->GetFlags() & CSF_RecurseSubsystems)
|
|
{
|
|
SIZER_COMPONENT_NAME(pSizer, "3DEngine");
|
|
m_object->GetMemoryUsage(pSizer);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
ICryBone* CAnimObject::GetBoneByName(const char * szName)
|
|
{
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
{
|
|
if (m_nodes[i] != NULL && stricmp(m_nodes[i]->m_name.c_str(),szName) == 0)
|
|
return m_nodes[i];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimObject::ObjectBindingHandle CAnimObject::AttachObjectToBone(IBindable * pWeaponModel, const char *szBoneName, bool bUseRelativeToDefPoseMatrix , unsigned nFlags )
|
|
{
|
|
if(!szBoneName)
|
|
{
|
|
// if you find this assert, this means someone passed here a model and NO bone to attach it to. What should it mean anyway??
|
|
assert (!pWeaponModel);
|
|
// just detach everything
|
|
DetachAll();
|
|
return nInvalidObjectBindingHandle;
|
|
}
|
|
|
|
int nBone = FindNodeByName(szBoneName);
|
|
if(nBone < 0)
|
|
{
|
|
if (!pWeaponModel)
|
|
{
|
|
// this is a severe bug if the bone name is invalid and someone tries to detach the model
|
|
// if we find such a situation, we should try to detach the model, as it might be destructed already
|
|
|
|
// but now we just detach everything, as it's simpler
|
|
//m_arrBoundObjects.clear();
|
|
//m_arrBoundObjectIndices.clear();
|
|
|
|
g_GetLog()->LogError ("\002AttachObjectToBone is called for bone \"%s\", which is not in the model \"%s\". Ignoring, but this may cause a crash because the corresponding object won't be detached after it's destroyed", szBoneName, GetFileName() );
|
|
#ifdef _DEBUG
|
|
// this assert will only happen if the ca_NoAttachAssert is off
|
|
// assert (GetCVars()->ca_NoAttachAssert());
|
|
#endif
|
|
}
|
|
return nInvalidObjectBindingHandle; // bone not found, do nothing
|
|
}
|
|
|
|
// detach all objects from this bone before creating a new one
|
|
DetachAllFromBone(nBone);
|
|
|
|
if(pWeaponModel == NULL)
|
|
{
|
|
// we didn't create a new binding, so return invalid handle
|
|
return nInvalidObjectBindingHandle;
|
|
}
|
|
else
|
|
{
|
|
return AttachToBone(pWeaponModel, nBone, nFlags);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::PreloadResources ( float fDistance, float fTime, int nFlags)
|
|
{
|
|
CryCharInstanceBase::PreloadResources( fDistance,fTime,nFlags );
|
|
|
|
for (unsigned int i = 0; i < m_nodes.size(); i++)
|
|
if (m_nodes[i] != NULL && m_nodes[i]->m_object)
|
|
m_nodes[i]->m_object->PreloadResources(fDistance, fTime, nFlags);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimObject::DrawBoundObjects(const SRendParams & rRendParams, Matrix44 &inmatTranRotMatrix, int nLOD)
|
|
{
|
|
static const float fColorBBoxAttached[4] = {0.5,1,1,0.75};
|
|
|
|
if (g_GetCVars()->ca_NoDrawBound())
|
|
return;
|
|
|
|
if (m_arrBinds.empty())
|
|
return;
|
|
|
|
Matrix44 matAttachedObjectMatrix;
|
|
SRendParams rParams (rRendParams);
|
|
// this is required to avoid the attachments using the parent character material (this is the material that overrides the default material in the attachment)
|
|
rParams.pMaterial = NULL;
|
|
|
|
if (m_nFlags & CS_FLAG_DRAW_NEAR)
|
|
{
|
|
rParams.dwFObjFlags |= FOB_NEAREST;
|
|
}
|
|
|
|
BindArray::iterator it, itEnd = m_arrBinds.end();
|
|
for (it = m_arrBinds.begin(); it != itEnd; ++it)
|
|
{
|
|
IBindable* pBoundObject = (*it)->pObj;
|
|
if (!pBoundObject)
|
|
continue;
|
|
|
|
int nBone = (*it)->nBone;
|
|
if (nBone < 0 || nBone >= (int)m_nodes.size())
|
|
continue;
|
|
|
|
Matrix44 &boneTM = GetNodeMatrix(m_nodes[nBone]);
|
|
matAttachedObjectMatrix = boneTM * inmatTranRotMatrix;
|
|
rParams.pMatrix = &matAttachedObjectMatrix;
|
|
|
|
if (g_GetCVars()->ca_DrawBBox()>1){
|
|
Matrix34 m34=Matrix34(GetTransposed44(matAttachedObjectMatrix));
|
|
|
|
CryAABB caabb;
|
|
pBoundObject->GetBBox(caabb.vMin, caabb.vMax);
|
|
|
|
debugDrawBBox (m34, caabb, g_GetCVars()->ca_DrawBBox()-1,fColorBBoxAttached);
|
|
}
|
|
//pBoundObject->SetShaderTemplate( rParams.nShaderTemplate, 0] ,0 );
|
|
pBoundObject->Render(rParams,Vec3(zero), nLOD);
|
|
}
|
|
}
|