Props remember who they're attached to and other mostly bone matrix related
things that should fix the heads-detached-from-bodies problem. This was SVN commit r3025.
This commit is contained in:
parent
2842098a49
commit
a357c7334e
@ -171,7 +171,11 @@ void CGameView::RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjec
|
||||
for (uint i=0;i<units.size();++i)
|
||||
{
|
||||
int status = losMgr->GetUnitStatus(units[i], g_Game->GetLocalPlayer());
|
||||
if (frustum.IsBoxVisible(CVector3D(0,0,0), units[i]->GetModel()->GetBounds())
|
||||
CModel* model = units[i]->GetModel();
|
||||
|
||||
model->ValidatePosition();
|
||||
|
||||
if (frustum.IsBoxVisible(CVector3D(0,0,0), model->GetBounds())
|
||||
&& status != UNIT_HIDDEN)
|
||||
{
|
||||
if(units[i] != g_BuildingPlacer.m_actor)
|
||||
@ -185,20 +189,25 @@ void CGameView::RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjec
|
||||
{
|
||||
color = CColor(0.7f, 0.7f, 0.7f, 1.0f);
|
||||
}
|
||||
units[i]->GetModel()->SetShadingColor(color);
|
||||
model->SetShadingColor(color);
|
||||
}
|
||||
|
||||
PROFILE( "submit models" );
|
||||
SubmitModelRecursive(units[i]->GetModel());
|
||||
SubmitModelRecursive(model);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<CProjectile*>& projectiles=pProjectileMan->GetProjectiles();
|
||||
for (uint i=0;i<projectiles.size();++i)
|
||||
{
|
||||
const CBound& bound = projectiles[i]->GetModel()->GetBounds();
|
||||
CModel* model = projectiles[i]->GetModel();
|
||||
|
||||
model->ValidatePosition();
|
||||
|
||||
const CBound& bound = model->GetBounds();
|
||||
CVector3D centre;
|
||||
bound.GetCentre(centre);
|
||||
|
||||
if (frustum.IsBoxVisible(CVector3D(0,0,0), bound)
|
||||
&& losMgr->GetStatus(centre.X, centre.Z, g_Game->GetLocalPlayer()) == LOS_VISIBLE)
|
||||
{
|
||||
@ -259,6 +268,7 @@ void CGameView::CameraLock(float x, float y, float z, bool smooth)
|
||||
|
||||
void CGameView::SubmitModelRecursive(CModel* model)
|
||||
{
|
||||
model->ValidatePosition();
|
||||
g_Renderer.Submit(model);
|
||||
|
||||
const std::vector<CModel::Prop>& props=model->GetProps();
|
||||
|
@ -26,9 +26,9 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
CModel::CModel()
|
||||
: m_Flags(0), m_Anim(0), m_AnimTime(0),
|
||||
m_BoneMatricesValid(false), m_BoneMatrices(0), m_InvBoneMatrices(0),
|
||||
m_ShadingColor(1,1,1,1)
|
||||
: m_Parent(0), m_Flags(0), m_Anim(0), m_AnimTime(0),
|
||||
m_BoneMatrices(0), m_InvBoneMatrices(0),
|
||||
m_PositionValid(false), m_ShadingColor(1,1,1,1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -36,6 +36,23 @@ CModel::CModel()
|
||||
// Destructor
|
||||
CModel::~CModel()
|
||||
{
|
||||
// Detach us from our parent
|
||||
if (m_Parent)
|
||||
{
|
||||
for(std::vector<Prop>::iterator iter = m_Parent->m_Props.begin();
|
||||
iter != m_Parent->m_Props.end();
|
||||
++iter)
|
||||
{
|
||||
if (iter->m_Model == this)
|
||||
{
|
||||
m_Parent->m_Props.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_Parent = 0;
|
||||
}
|
||||
|
||||
ReleaseData();
|
||||
}
|
||||
|
||||
@ -79,33 +96,13 @@ bool CModel::InitModel(CModelDefPtr modeldef)
|
||||
m.Translate(defpose[i].m_Translation);
|
||||
m.GetInverse(m_InvBoneMatrices[i]);
|
||||
}
|
||||
m_BoneMatricesValid=true;
|
||||
}
|
||||
|
||||
m_PositionValid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SkinPoint: skin the given point using the given blend and bonestate data
|
||||
/* JW: function is apparently currently unused
|
||||
|
||||
static CVector3D SkinPoint(const CVector3D& pos,const SVertexBlend& blend,
|
||||
const CBoneState* bonestates)
|
||||
{
|
||||
CVector3D result(0,0,0);
|
||||
for (int i=0;i<SVertexBlend::SIZE && blend.m_Bone[i]!=0xff;i++) {
|
||||
CMatrix3D m;
|
||||
m.SetIdentity();
|
||||
m.Rotate(bonestates[blend.m_Bone[i]].m_Rotation);
|
||||
m.Translate(bonestates[blend.m_Bone[i]].m_Translation);
|
||||
|
||||
CVector3D tmp=m.Transform(pos);
|
||||
result+=tmp*blend.m_Weight[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SkinPoint: skin the given point using the given blend and matrix data
|
||||
@ -183,8 +180,11 @@ void CModel::CalcAnimatedObjectBound(CSkeletonAnimDef* anim,CBound& result)
|
||||
// at the origin. The box is later re-transformed onto the object, without
|
||||
// having to recalculate the size of the box.
|
||||
CMatrix3D transform, oldtransform = GetTransform();
|
||||
CModel* oldparent = m_Parent;
|
||||
|
||||
m_Parent = 0;
|
||||
transform.SetIdentity();
|
||||
SetTransform(transform);
|
||||
CRenderableObject::SetTransform(transform);
|
||||
|
||||
// Following seems to stomp over the current animation time - which, unsurprisingly,
|
||||
// introduces artefacts in the currently playing animation. Save it here and restore it
|
||||
@ -192,17 +192,21 @@ void CModel::CalcAnimatedObjectBound(CSkeletonAnimDef* anim,CBound& result)
|
||||
float AnimTime = m_AnimTime;
|
||||
|
||||
// iterate through every frame of the animation
|
||||
for (size_t j=0;j<anim->GetNumFrames();j++) {
|
||||
for (size_t j=0;j<anim->GetNumFrames();j++) {
|
||||
m_PositionValid = false;
|
||||
ValidatePosition();
|
||||
|
||||
// extend bounds by vertex positions at the frame
|
||||
for (size_t i=0;i<numverts;i++) {
|
||||
CVector3D tmp=SkinPoint(verts[i].m_Coords,verts[i].m_Blend,GetBoneMatrices());
|
||||
CVector3D tmp = SkinPoint(verts[i].m_Coords,verts[i].m_Blend,GetBoneMatrices());
|
||||
result+=tmp;
|
||||
}
|
||||
// advance to next frame
|
||||
m_AnimTime+=anim->GetFrameTime();
|
||||
m_BoneMatricesValid=false;
|
||||
m_AnimTime += anim->GetFrameTime();
|
||||
}
|
||||
|
||||
m_PositionValid = false;
|
||||
m_Parent = oldparent;
|
||||
SetTransform(oldtransform);
|
||||
m_AnimTime = AnimTime;
|
||||
}
|
||||
@ -259,53 +263,81 @@ void CModel::Update(float time)
|
||||
SetDirty(RENDERDATA_UPDATE_VERTICES);
|
||||
|
||||
// mark matrices as dirty
|
||||
m_BoneMatricesValid = false;
|
||||
InvalidatePosition();
|
||||
}
|
||||
|
||||
// update props
|
||||
for (uint i=0; i<m_Props.size(); i++) {
|
||||
for (uint i=0; i<m_Props.size(); i++)
|
||||
{
|
||||
m_Props[i].m_Model->Update(time);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GenerateBoneMatrices: calculate necessary bone transformation matrices for skinning
|
||||
void CModel::GenerateBoneMatrices()
|
||||
// InvalidatePosition
|
||||
void CModel::InvalidatePosition()
|
||||
{
|
||||
if (!m_Anim || !m_BoneMatrices) return;
|
||||
m_PositionValid = false;
|
||||
|
||||
PROFILE( "generating bone matrices" );
|
||||
for (uint i = 0; i < m_Props.size(); ++i)
|
||||
m_Props[i].m_Model->InvalidatePosition();
|
||||
}
|
||||
|
||||
debug_assert(m_pModelDef->GetNumBones() == m_Anim->m_AnimDef->GetNumKeys());
|
||||
|
||||
m_Anim->m_AnimDef->BuildBoneMatrices(m_AnimTime,m_BoneMatrices);
|
||||
|
||||
const CMatrix3D& transform=GetTransform();
|
||||
for (size_t i=0;i<m_pModelDef->GetNumBones();i++) {
|
||||
m_BoneMatrices[i].Concatenate(transform);
|
||||
m_BoneMatrices[i].GetInverse(m_InvBoneMatrices[i]);
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ValidatePosition: ensure that current transform and bone matrices are both uptodate
|
||||
void CModel::ValidatePosition()
|
||||
{
|
||||
if (m_PositionValid)
|
||||
{
|
||||
debug_assert(!m_Parent || m_Parent->m_PositionValid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Parent && !m_Parent->m_PositionValid)
|
||||
{
|
||||
// Make sure we don't base our calculations on
|
||||
// a parent animation state that is out of date.
|
||||
m_Parent->ValidatePosition();
|
||||
|
||||
// Parent will recursively call our validation.
|
||||
debug_assert(m_PositionValid);
|
||||
return;
|
||||
}
|
||||
|
||||
// update transform of boned props
|
||||
// TODO, RC - ugh, we'll be doing this twice (for boned props, at least) - once here,
|
||||
// and once again in SetTransform; better to just do it in Update?
|
||||
for (size_t j=0;j<m_Props.size();j++) {
|
||||
if (m_Anim && m_BoneMatrices)
|
||||
{
|
||||
PROFILE( "generating bone matrices" );
|
||||
|
||||
debug_assert(m_pModelDef->GetNumBones() == m_Anim->m_AnimDef->GetNumKeys());
|
||||
|
||||
m_Anim->m_AnimDef->BuildBoneMatrices(m_AnimTime,m_BoneMatrices);
|
||||
|
||||
const CMatrix3D& transform=GetTransform();
|
||||
for (size_t i=0;i<m_pModelDef->GetNumBones();i++) {
|
||||
m_BoneMatrices[i].Concatenate(transform);
|
||||
m_BoneMatrices[i].GetInverse(m_InvBoneMatrices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
m_PositionValid = true;
|
||||
|
||||
// re-position and validate all props
|
||||
for (size_t j = 0; j < m_Props.size(); ++j)
|
||||
{
|
||||
const Prop& prop=m_Props[j];
|
||||
|
||||
if (prop.m_Point->m_BoneIndex!=0xff) {
|
||||
CMatrix3D proptransform=prop.m_Point->m_Transform;;
|
||||
if (prop.m_Point->m_BoneIndex!=0xff) {
|
||||
proptransform.Concatenate(m_BoneMatrices[prop.m_Point->m_BoneIndex]);
|
||||
} else {
|
||||
proptransform.Concatenate(transform);
|
||||
}
|
||||
prop.m_Model->SetTransform(proptransform);
|
||||
}
|
||||
CMatrix3D proptransform = prop.m_Point->m_Transform;;
|
||||
if (prop.m_Point->m_BoneIndex != 0xff)
|
||||
proptransform.Concatenate(m_BoneMatrices[prop.m_Point->m_BoneIndex]);
|
||||
else
|
||||
proptransform.Concatenate(m_Transform);
|
||||
|
||||
prop.m_Model->SetTransform(proptransform);
|
||||
prop.m_Model->ValidatePosition();
|
||||
}
|
||||
|
||||
m_BoneMatricesValid=true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetAnimation: set the given animation as the current animation on this model;
|
||||
// return false on error, else true
|
||||
@ -344,7 +376,7 @@ bool CModel::SetAnimation(CSkeletonAnim* anim, bool once, float speed, CSkeleton
|
||||
m_AnimSpeed = speed * anim->m_Speed;
|
||||
}
|
||||
|
||||
m_Anim=anim;
|
||||
m_Anim = anim;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -355,6 +387,7 @@ void CModel::AddProp(SPropPoint* point, CModel* model)
|
||||
{
|
||||
// position model according to prop point position
|
||||
model->SetTransform(point->m_Transform);
|
||||
model->m_Parent = this;
|
||||
|
||||
// check if we're already using this point, and replace
|
||||
// model on it if so
|
||||
@ -412,26 +445,12 @@ CModel* CModel::Clone() const
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetTransform: set the transform on this object, and reorientate props accordingly
|
||||
void CModel::SetTransform(const CMatrix3D& transform)
|
||||
void CModel::SetTransform(const CMatrix3D& transform)
|
||||
{
|
||||
// call base class to set transform on this object
|
||||
CRenderableObject::SetTransform(transform);
|
||||
InvalidateBounds();
|
||||
|
||||
GenerateBoneMatrices();
|
||||
|
||||
// now set transforms on props
|
||||
for (size_t i=0;i<m_Props.size();i++) {
|
||||
const Prop& prop=m_Props[i];
|
||||
|
||||
CMatrix3D proptransform=prop.m_Point->m_Transform;;
|
||||
if (prop.m_Point->m_BoneIndex!=0xff) {
|
||||
proptransform.Concatenate(m_BoneMatrices[prop.m_Point->m_BoneIndex]);
|
||||
} else {
|
||||
proptransform.Concatenate(transform);
|
||||
}
|
||||
prop.m_Model->SetTransform(proptransform);
|
||||
}
|
||||
InvalidatePosition();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -92,17 +92,22 @@ public:
|
||||
// calculate bounds encompassing all vertex positions for given animation
|
||||
void CalcAnimatedObjectBound(CSkeletonAnimDef* anim,CBound& result);
|
||||
|
||||
// set transform of this object, and recurse down into props to update their world space transform
|
||||
/**
|
||||
* SetTransform: Set transform of this object.
|
||||
*
|
||||
* @note In order to ensure that all child props are updated properly,
|
||||
* you must call ValidatePosition().
|
||||
*/
|
||||
void SetTransform(const CMatrix3D& transform);
|
||||
|
||||
// return the models bone matrices
|
||||
const CMatrix3D* GetBoneMatrices() {
|
||||
if (!m_BoneMatricesValid) GenerateBoneMatrices();
|
||||
debug_assert(m_PositionValid);
|
||||
return m_BoneMatrices;
|
||||
}
|
||||
// return the models inverted bone matrices
|
||||
const CMatrix3D* GetInvBoneMatrices() {
|
||||
if (!m_BoneMatricesValid) GenerateBoneMatrices();
|
||||
debug_assert(m_PositionValid);
|
||||
return m_InvBoneMatrices;
|
||||
}
|
||||
|
||||
@ -121,11 +126,27 @@ public:
|
||||
// return a clone of this model
|
||||
CModel* Clone() const;
|
||||
|
||||
/**
|
||||
* ValidatePosition: Ensure that both the transformation and the bone
|
||||
* matrices are correct for this model and all its props.
|
||||
*/
|
||||
void ValidatePosition();
|
||||
|
||||
private:
|
||||
// delete anything allocated by the model
|
||||
void ReleaseData();
|
||||
// calculate necessary bone transformation matrices for skinning
|
||||
void GenerateBoneMatrices();
|
||||
|
||||
/**
|
||||
* InvalidatePosition: Mark this model's position and bone matrices,
|
||||
* and all props' positions as invalid.
|
||||
*/
|
||||
void InvalidatePosition();
|
||||
|
||||
/**
|
||||
* m_Parent: If non-null, m_Parent points to the model that we
|
||||
* are attached to.
|
||||
*/
|
||||
CModel* m_Parent;
|
||||
|
||||
// object flags
|
||||
u32 m_Flags;
|
||||
@ -147,8 +168,6 @@ private:
|
||||
float m_AnimSpeed;
|
||||
// time (in MS) into the current animation
|
||||
float m_AnimTime;
|
||||
// flag stating whether bone matrices are currently valid
|
||||
bool m_BoneMatricesValid;
|
||||
// current state of all bones on this model; null if associated modeldef isn't skeletal
|
||||
CMatrix3D* m_BoneMatrices;
|
||||
// inverse of the above world space transform of the above matrices
|
||||
@ -156,6 +175,12 @@ private:
|
||||
// list of current props on model
|
||||
std::vector<Prop> m_Props;
|
||||
|
||||
/**
|
||||
* m_PositionValid: true if both transform and and bone matrices
|
||||
* are valid.
|
||||
*/
|
||||
bool m_PositionValid;
|
||||
|
||||
// modulating color
|
||||
CColor m_ShadingColor;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user