Added bone merge; still a lot to fix
This commit is contained in:
parent
9b270322f7
commit
95146c3867
18 changed files with 333 additions and 434 deletions
|
@ -12,6 +12,7 @@
|
|||
#include "convar.h"
|
||||
#include "iconvar.h"
|
||||
#include "interpolatedvar.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "model_types.h"
|
||||
#include "bone_setup.h"
|
||||
#include "ivrenderview.h"
|
||||
|
@ -1498,7 +1499,7 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater
|
|||
m_pBoneMergeCache = new CBoneMergeCache;
|
||||
m_pBoneMergeCache->Init( this );
|
||||
}
|
||||
m_pBoneMergeCache->MergeMatchingBones( boneMask );
|
||||
m_pBoneMergeCache->MergeMatchingBones( boneMask, m_BoneAccessor.GetBoneArrayForWrite() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1890,7 +1891,7 @@ void C_BaseAnimating::AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Qua
|
|||
|
||||
void C_BaseAnimating::ChildLayerBlend( Vector pos[], Quaternion q[], float currentTime, int boneMask )
|
||||
{
|
||||
return;
|
||||
return;
|
||||
|
||||
Vector childPos[MAXSTUDIOBONES];
|
||||
Quaternion childQ[MAXSTUDIOBONES];
|
||||
|
@ -2743,82 +2744,6 @@ void C_BaseAnimating::ThreadedBoneSetup()
|
|||
g_PreviousBoneSetups.RemoveAll();
|
||||
}
|
||||
|
||||
void C_BaseAnimating::BuildMatricesWithBoneMerge(
|
||||
const CStudioHdr *pStudioHdr,
|
||||
const QAngle& angles,
|
||||
const Vector& origin,
|
||||
const Vector pos[MAXSTUDIOBONES],
|
||||
const Quaternion q[MAXSTUDIOBONES],
|
||||
matrix3x4_t bonetoworld[MAXSTUDIOBONES],
|
||||
C_BaseAnimating *pParent,
|
||||
CBoneCache *pParentCache
|
||||
)
|
||||
{
|
||||
CStudioHdr *fhdr = pParent->GetModelPtr();
|
||||
mstudiobone_t *pbones = pStudioHdr->pBone( 0 );
|
||||
|
||||
matrix3x4_t rotationmatrix; // model to world transformation
|
||||
AngleMatrix( angles, origin, rotationmatrix);
|
||||
|
||||
for ( int i=0; i < pStudioHdr->numbones(); i++ )
|
||||
{
|
||||
// Now find the bone in the parent entity.
|
||||
bool merged = false;
|
||||
int parentBoneIndex = Studio_BoneIndexByName( fhdr, pbones[i].pszName() );
|
||||
if ( parentBoneIndex >= 0 )
|
||||
{
|
||||
matrix3x4_t *pMat = pParentCache->GetCachedBone( parentBoneIndex );
|
||||
if ( pMat )
|
||||
{
|
||||
MatrixCopy( *pMat, bonetoworld[ i ] );
|
||||
merged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !merged )
|
||||
{
|
||||
// If we get down here, then the bone wasn't merged.
|
||||
matrix3x4_t bonematrix;
|
||||
QuaternionMatrix( q[i], pos[i], bonematrix );
|
||||
|
||||
if (pbones[i].parent == -1)
|
||||
{
|
||||
ConcatTransforms (rotationmatrix, bonematrix, bonetoworld[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConcatTransforms (bonetoworld[pbones[i].parent], bonematrix, bonetoworld[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_BaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime )
|
||||
{
|
||||
if(!pStudioHdr)
|
||||
{
|
||||
Assert(!"C_BaseAnimating::GetSkeleton() without a model");
|
||||
return;
|
||||
}
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, m_flPoseParameter );
|
||||
boneSetup.InitPose( pos, q );
|
||||
|
||||
boneSetup.AccumulatePose( pos, q, GetSequence(), GetCycle(), 1.0, currentTime, m_pIk );
|
||||
|
||||
if ( m_pIk )
|
||||
{
|
||||
CIKContext auto_ik;
|
||||
auto_ik.Init( pStudioHdr, GetRenderAngles(), GetRenderOrigin(), currentTime, 0, boneMask );
|
||||
boneSetup.CalcAutoplaySequences( pos, q, currentTime, &auto_ik );
|
||||
}
|
||||
else
|
||||
{
|
||||
boneSetup.CalcAutoplaySequences( pos, q, currentTime, NULL );
|
||||
}
|
||||
boneSetup.CalcBoneAdj( pos, q, m_flEncodedController );
|
||||
}
|
||||
|
||||
bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
|
||||
{
|
||||
VPROF_BUDGET( "C_BaseAnimating::SetupBones", VPROF_BUDGETGROUP_CLIENT_ANIMATION );
|
||||
|
|
|
@ -144,11 +144,6 @@ public:
|
|||
virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax );
|
||||
|
||||
// model specific
|
||||
void BuildMatricesWithBoneMerge( const CStudioHdr *pStudioHdr, const QAngle& angles,
|
||||
const Vector& origin, const Vector pos[MAXSTUDIOBONES],
|
||||
const Quaternion q[MAXSTUDIOBONES], matrix3x4_t bonetoworld[MAXSTUDIOBONES],
|
||||
CBaseAnimating *pParent, CBoneCache *pParentCache );
|
||||
virtual void GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime );
|
||||
virtual bool SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime );
|
||||
virtual void UpdateIKLocks( float currentTime );
|
||||
virtual void CalculateIKLocks( float currentTime );
|
||||
|
|
|
@ -370,66 +370,3 @@ CStudioHdr *C_BaseAnimatingOverlay::OnNewModel()
|
|||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
void C_BaseAnimatingOverlay::GetSkeleton( CStudioHdr* pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime )
|
||||
{
|
||||
if(!pStudioHdr)
|
||||
{
|
||||
Assert(!"C_BaseAnimating::GetSkeleton() without a model");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pStudioHdr->SequencesAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float poseparameters[MAXSTUDIOPOSEPARAM];
|
||||
GetPoseParameters(pStudioHdr, poseparameters);
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, poseparameters );
|
||||
boneSetup.InitPose( pos, q );
|
||||
|
||||
boneSetup.AccumulatePose( pos, q, GetSequence(), GetCycle(), 1.0, currentTime, m_pIk );
|
||||
|
||||
// sort the layers
|
||||
int layer[MAX_OVERLAYS] = {};
|
||||
int i;
|
||||
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
||||
{
|
||||
layer[i] = MAX_OVERLAYS;
|
||||
}
|
||||
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
||||
{
|
||||
CAnimationLayer &pLayer = m_AnimOverlay[i];
|
||||
if( (pLayer.m_flWeight > 0) && pLayer.IsActive() && pLayer.m_nOrder >= 0 && pLayer.m_nOrder < m_AnimOverlay.Count())
|
||||
{
|
||||
layer[pLayer.m_nOrder] = i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
||||
{
|
||||
if (layer[i] >= 0 && layer[i] < m_AnimOverlay.Count())
|
||||
{
|
||||
CAnimationLayer &pLayer = m_AnimOverlay[layer[i]];
|
||||
// UNDONE: Is it correct to use overlay weight for IK too?
|
||||
boneSetup.AccumulatePose( pos, q, pLayer.m_nSequence, pLayer.m_flCycle, pLayer.m_flWeight, currentTime, m_pIk );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_pIk )
|
||||
{
|
||||
CIKContext auto_ik;
|
||||
auto_ik.Init( pStudioHdr, GetRenderAngles(), GetRenderOrigin(), currentTime, 0, boneMask );
|
||||
boneSetup.CalcAutoplaySequences( pos, q, currentTime, &auto_ik );
|
||||
}
|
||||
else
|
||||
{
|
||||
boneSetup.CalcAutoplaySequences(pos, q, currentTime, NULL);
|
||||
}
|
||||
|
||||
float controllers[MAXSTUDIOBONECTRLS];
|
||||
GetBoneControllers(controllers);
|
||||
|
||||
boneSetup.CalcBoneAdj( pos, q, controllers );
|
||||
}
|
|
@ -38,8 +38,6 @@ public:
|
|||
// model specific
|
||||
virtual void AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime );
|
||||
virtual void DoAnimationEvents( CStudioHdr *pStudioHdr );
|
||||
virtual void GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime );
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_OVERLAYS = 15,
|
||||
|
|
|
@ -204,7 +204,7 @@ $Project
|
|||
$File "beamdraw.cpp"
|
||||
$File "$SRCDIR\game\shared\beam_shared.cpp"
|
||||
$File "$SRCDIR\public\bone_accessor.cpp"
|
||||
$File "bone_merge_cache.cpp"
|
||||
$File "$SRCDIR\game\shared\bone_merge_cache.cpp"
|
||||
$File "c_ai_basehumanoid.cpp"
|
||||
$File "c_ai_basenpc.cpp"
|
||||
$File "c_baseanimating.cpp"
|
||||
|
@ -674,7 +674,7 @@ $Project
|
|||
$File "baseanimatedtextureproxy.h"
|
||||
$File "baseclientrendertargets.h"
|
||||
$File "beamdraw.h"
|
||||
$File "bone_merge_cache.h"
|
||||
$File "$SRCDIR\game\shared\bone_merge_cache.h"
|
||||
$File "c_ai_basenpc.h"
|
||||
$File "c_baseanimating.h"
|
||||
$File "c_baseanimatingoverlay.h"
|
||||
|
|
|
@ -2598,103 +2598,12 @@ float C_CSPlayer::GetDeathCamInterpolationTime()
|
|||
return spec_freeze_time.GetFloat();
|
||||
else
|
||||
return CS_DEATH_ANIMATION_TIME;
|
||||
|
||||
}
|
||||
|
||||
ConVar cl_server_setup_bones("cl_server_setup_bones", "1");
|
||||
|
||||
bool C_CSPlayer::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
|
||||
{
|
||||
if (cl_server_setup_bones.GetBool())
|
||||
{
|
||||
AUTO_LOCK( m_BoneSetupLock );
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
Assert( GetModelPtr() );
|
||||
|
||||
CStudioHdr *pStudioHdr = GetModelPtr( );
|
||||
|
||||
if(!pStudioHdr)
|
||||
{
|
||||
Assert(!"C_BaseAnimating::GetSkeleton() without a model");
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert( !IsEFlagSet( EFL_SETTING_UP_BONES ) );
|
||||
|
||||
AddEFlags( EFL_SETTING_UP_BONES );
|
||||
|
||||
Vector pos[MAXSTUDIOBONES];
|
||||
Quaternion q[MAXSTUDIOBONES];
|
||||
|
||||
// adjust hit boxes based on IK driven offset
|
||||
Vector adjOrigin = GetRenderOrigin();
|
||||
|
||||
if ( m_pIk )
|
||||
{
|
||||
// FIXME: pass this into Studio_BuildMatrices to skip transforms
|
||||
CBoneBitList boneComputed;
|
||||
m_iIKCounter++;
|
||||
m_pIk->Init( pStudioHdr, GetRenderAngles(), adjOrigin, currentTime, m_iIKCounter, boneMask );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask, currentTime );
|
||||
|
||||
m_pIk->UpdateTargets( pos, q, m_BoneAccessor.GetBoneArrayForWrite(), boneComputed );
|
||||
CalculateIKLocks( currentTime );
|
||||
m_pIk->SolveDependencies( pos, q, m_BoneAccessor.GetBoneArrayForWrite(), boneComputed );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Msg( "%.03f : %s:%s\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask, currentTime );
|
||||
}
|
||||
|
||||
CBaseAnimating *pParent = dynamic_cast< CBaseAnimating* >( GetMoveParent() );
|
||||
if ( pParent )
|
||||
{
|
||||
// We're doing bone merging, so do special stuff here.
|
||||
CBoneCache *pParentCache = pParent->GetBoneCache(pParent->GetModelPtr());
|
||||
if ( pParentCache )
|
||||
{
|
||||
BuildMatricesWithBoneMerge(
|
||||
pStudioHdr,
|
||||
GetRenderAngles(),
|
||||
adjOrigin,
|
||||
pos,
|
||||
q,
|
||||
m_BoneAccessor.GetBoneArrayForWrite(),
|
||||
pParent,
|
||||
pParentCache );
|
||||
|
||||
RemoveEFlags( EFL_SETTING_UP_BONES );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Studio_BuildMatrices(
|
||||
pStudioHdr,
|
||||
GetRenderAngles(),
|
||||
adjOrigin,
|
||||
pos,
|
||||
q,
|
||||
-1,
|
||||
GetModelScale(), // Scaling
|
||||
m_BoneAccessor.GetBoneArrayForWrite(),
|
||||
boneMask );
|
||||
|
||||
RemoveEFlags(EFL_SETTING_UP_BONES);
|
||||
|
||||
if ( pBoneToWorldOut )
|
||||
{
|
||||
memcpy( pBoneToWorldOut, m_BoneAccessor.GetBoneArrayForWrite(), sizeof( matrix3x4_t ) * MAXSTUDIOBONES );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime );
|
||||
}
|
||||
return BaseClass::SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime );
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -447,7 +447,12 @@ void CBaseAnimatingOverlay::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Q
|
|||
return;
|
||||
}
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, GetPoseParameterArray() );
|
||||
float flPoseParams[MAXSTUDIOPOSEPARAM];
|
||||
float flEncodedParams[MAXSTUDIOBONECTRLS];
|
||||
|
||||
GetPoseParameters( pStudioHdr, flPoseParams );
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, flPoseParams );
|
||||
boneSetup.InitPose( pos, q );
|
||||
|
||||
boneSetup.AccumulatePose( pos, q, GetSequence(), GetCycle(), 1.0, gpGlobals->curtime, m_pIk );
|
||||
|
@ -486,12 +491,12 @@ void CBaseAnimatingOverlay::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Q
|
|||
else
|
||||
{
|
||||
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, NULL );
|
||||
}
|
||||
boneSetup.CalcBoneAdj( pos, q, GetEncodedControllerArray() );
|
||||
}
|
||||
GetEncodedControllers( pStudioHdr, flEncodedParams );
|
||||
boneSetup.CalcBoneAdj( pos, q, flEncodedParams );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: zero's out all non-restore safe fields
|
||||
// Output :
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "enginecallback.h"
|
||||
#include "entitylist_base.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/vmatrix.h"
|
||||
#include "player.h"
|
||||
#include "shareddefs.h"
|
||||
#include "studio.h"
|
||||
#include "bone_setup.h"
|
||||
|
@ -289,6 +291,8 @@ CBaseAnimating::CBaseAnimating()
|
|||
m_fadeMaxDist = 0;
|
||||
m_flFadeScale = 0.0f;
|
||||
m_fBoneCacheFlags = 0;
|
||||
m_pBoneMergeCache = NULL;
|
||||
m_pBoneCache = NULL;
|
||||
}
|
||||
|
||||
CBaseAnimating::~CBaseAnimating()
|
||||
|
@ -1693,6 +1697,32 @@ void CBaseAnimating::Teleport( const Vector *newPosition, const QAngle *newAngle
|
|||
}
|
||||
|
||||
|
||||
void CBaseAnimating::GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM])
|
||||
{
|
||||
if ( !pStudioHdr )
|
||||
return;
|
||||
|
||||
// interpolate pose parameters
|
||||
int i;
|
||||
for( i=0; i < pStudioHdr->GetNumPoseParameters(); i++)
|
||||
{
|
||||
poseParameter[i] = m_flPoseParameter[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseAnimating::GetEncodedControllers(CStudioHdr* pStudioHdr, float encodedControllers[MAXSTUDIOBONECTRLS])
|
||||
{
|
||||
if ( !pStudioHdr )
|
||||
return;
|
||||
|
||||
// interpolate pose parameters
|
||||
int i;
|
||||
for( i=0; i < pStudioHdr->GetNumPoseParameters(); i++)
|
||||
{
|
||||
encodedControllers[i] = m_flEncodedController[i];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: build matrices first from the parent, then from the passed in arrays if the bone doesn't exist on the parent
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1704,45 +1734,56 @@ void CBaseAnimating::BuildMatricesWithBoneMerge(
|
|||
const Vector pos[MAXSTUDIOBONES],
|
||||
const Quaternion q[MAXSTUDIOBONES],
|
||||
matrix3x4_t bonetoworld[MAXSTUDIOBONES],
|
||||
CBaseAnimating *pParent,
|
||||
CBoneCache *pParentCache
|
||||
int boneMask
|
||||
)
|
||||
{
|
||||
CStudioHdr *fhdr = pParent->GetModelPtr();
|
||||
mstudiobone_t *pbones = pStudioHdr->pBone( 0 );
|
||||
|
||||
matrix3x4_t rotationmatrix; // model to world transformation
|
||||
AngleMatrix( angles, origin, rotationmatrix);
|
||||
|
||||
for ( int i=0; i < pStudioHdr->numbones(); i++ )
|
||||
bool boneMerge = IsEffectActive(EF_BONEMERGE);
|
||||
if ( boneMerge || m_pBoneMergeCache )
|
||||
{
|
||||
// Now find the bone in the parent entity.
|
||||
bool merged = false;
|
||||
int parentBoneIndex = Studio_BoneIndexByName( fhdr, pbones[i].pszName() );
|
||||
if ( parentBoneIndex >= 0 )
|
||||
if ( boneMerge )
|
||||
{
|
||||
matrix3x4_t *pMat = pParentCache->GetCachedBone( parentBoneIndex );
|
||||
if ( pMat )
|
||||
if ( !m_pBoneMergeCache )
|
||||
{
|
||||
MatrixCopy( *pMat, bonetoworld[ i ] );
|
||||
merged = true;
|
||||
m_pBoneMergeCache = new CBoneMergeCache;
|
||||
m_pBoneMergeCache->Init( this );
|
||||
}
|
||||
m_pBoneMergeCache->MergeMatchingBones( boneMask, bonetoworld );
|
||||
}
|
||||
|
||||
if ( !merged )
|
||||
else
|
||||
{
|
||||
// If we get down here, then the bone wasn't merged.
|
||||
matrix3x4_t bonematrix;
|
||||
QuaternionMatrix( q[i], pos[i], bonematrix );
|
||||
delete m_pBoneMergeCache;
|
||||
m_pBoneMergeCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i=0; i < pStudioHdr->numbones(); i++ )
|
||||
{
|
||||
if (!(pStudioHdr->boneFlags(i) & boneMask))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_pBoneMergeCache && m_pBoneMergeCache->IsBoneMerged(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pbones[i].parent == -1)
|
||||
{
|
||||
ConcatTransforms (rotationmatrix, bonematrix, bonetoworld[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConcatTransforms (bonetoworld[pbones[i].parent], bonematrix, bonetoworld[i]);
|
||||
}
|
||||
// If we get down here, then the bone wasn't merged.
|
||||
matrix3x4_t bonematrix;
|
||||
QuaternionMatrix( q[i], pos[i], bonematrix );
|
||||
|
||||
if (pbones[i].parent == -1)
|
||||
{
|
||||
ConcatTransforms (rotationmatrix, bonematrix, bonetoworld[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConcatTransforms (bonetoworld[pbones[i].parent], bonematrix, bonetoworld[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1772,24 +1813,56 @@ inline bool CBaseAnimating::CanSkipAnimation( void )
|
|||
}
|
||||
|
||||
|
||||
void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
||||
void CBaseAnimating::SetupBones( CStudioHdr* pStudioHdr, matrix3x4_t *pBoneToWorld, int boneMask )
|
||||
{
|
||||
static constexpr auto flDebugDuration = 60.f;
|
||||
AUTO_LOCK( m_BoneSetupMutex );
|
||||
|
||||
VPROF_BUDGET( "CBaseAnimating::SetupBones", VPROF_BUDGETGROUP_SERVER_ANIM );
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
Assert( GetModelPtr() );
|
||||
m_pBoneCache = Studio_GetBoneCache(m_boneCacheHandle);
|
||||
|
||||
CStudioHdr *pStudioHdr = GetModelPtr( );
|
||||
if ( m_pBoneCache )
|
||||
{
|
||||
if ( m_pBoneCache->IsValid( gpGlobals->curtime ) && (m_pBoneCache->m_boneMask & boneMask) == boneMask && m_pBoneCache->m_timeValid <= gpGlobals->curtime)
|
||||
{
|
||||
// Msg("%s:%s:%s (%x:%x:%8.4f) cache\n", GetClassname(), GetDebugName(), STRING(GetModelName()), boneMask, pcache->m_boneMask, pcache->m_timeValid );
|
||||
// in memory and still valid, use it!
|
||||
m_pBoneCache->ReadCachedBones(pBoneToWorld);
|
||||
return;
|
||||
}
|
||||
|
||||
// in memory, but missing some of the bone masks
|
||||
if ( (m_pBoneCache->m_boneMask & boneMask) != boneMask )
|
||||
{
|
||||
Studio_DestroyBoneCache( m_boneCacheHandle );
|
||||
m_boneCacheHandle = 0;
|
||||
m_pBoneCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_pBoneCache )
|
||||
{
|
||||
bonecacheparams_t params;
|
||||
params.pStudioHdr = pStudioHdr;
|
||||
params.pBoneToWorld = pBoneToWorld;
|
||||
params.curtime = gpGlobals->curtime;
|
||||
params.boneMask = boneMask;
|
||||
|
||||
m_boneCacheHandle = Studio_CreateBoneCache(params);
|
||||
m_pBoneCache = Studio_GetBoneCache(m_boneCacheHandle);
|
||||
}
|
||||
|
||||
Assert( pStudioHdr );
|
||||
|
||||
if(!pStudioHdr)
|
||||
{
|
||||
Assert(!"CBaseAnimating::GetSkeleton() without a model");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Assert( !IsEFlagSet( EFL_SETTING_UP_BONES ) );
|
||||
|
||||
AddEFlags( EFL_SETTING_UP_BONES );
|
||||
|
@ -1797,8 +1870,8 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
|||
Vector pos[MAXSTUDIOBONES];
|
||||
Quaternion q[MAXSTUDIOBONES];
|
||||
|
||||
// adjust hit boxes based on IK driven offset
|
||||
Vector adjOrigin = GetAbsOrigin() + Vector( 0, 0, m_flEstIkOffset );
|
||||
// Remove IK to respect more the client hitboxes.
|
||||
Vector adjOrigin = GetAbsOrigin();
|
||||
|
||||
if ( CanSkipAnimation() )
|
||||
{
|
||||
|
@ -1825,49 +1898,16 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
|||
// Msg( "%.03f : %s:%s\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
||||
}
|
||||
}
|
||||
|
||||
CBaseAnimating *pParent = dynamic_cast< CBaseAnimating* >( GetMoveParent() );
|
||||
if ( pParent )
|
||||
{
|
||||
// We're doing bone merging, so do special stuff here.
|
||||
CBoneCache *pParentCache = pParent->GetBoneCache();
|
||||
if ( pParentCache )
|
||||
{
|
||||
BuildMatricesWithBoneMerge(
|
||||
pStudioHdr,
|
||||
GetAbsAngles(),
|
||||
adjOrigin,
|
||||
pos,
|
||||
q,
|
||||
pBoneToWorld,
|
||||
pParent,
|
||||
pParentCache );
|
||||
|
||||
RemoveEFlags( EFL_SETTING_UP_BONES );
|
||||
if (ai_setupbones_debug.GetBool())
|
||||
{
|
||||
DrawRawSkeleton( pBoneToWorld, boneMask, true, 0.11 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Studio_BuildMatrices(
|
||||
pStudioHdr,
|
||||
GetAbsAngles(),
|
||||
adjOrigin,
|
||||
pos,
|
||||
q,
|
||||
-1,
|
||||
GetModelScale(), // Scaling
|
||||
pBoneToWorld,
|
||||
boneMask );
|
||||
BuildMatricesWithBoneMerge(pStudioHdr, GetAbsAngles(), adjOrigin, pos, q, pBoneToWorld, boneMask);
|
||||
|
||||
m_pBoneCache->UpdateBones(pBoneToWorld, pStudioHdr->numbones(), gpGlobals->curtime);
|
||||
|
||||
if (ai_setupbones_debug.GetBool())
|
||||
{
|
||||
// Msg("%s:%s:%s (%x)\n", GetClassname(), GetDebugName(), STRING(GetModelName()), boneMask );
|
||||
DrawRawSkeleton( pBoneToWorld, boneMask, true, 0.11 );
|
||||
DrawRawSkeleton( pBoneToWorld, boneMask, true, flDebugDuration );
|
||||
}
|
||||
RemoveEFlags( EFL_SETTING_UP_BONES );
|
||||
}
|
||||
|
@ -2588,51 +2628,33 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
|
|||
CStudioHdr *pStudioHdr = GetModelPtr( );
|
||||
Assert(pStudioHdr);
|
||||
|
||||
CBoneCache *pcache = Studio_GetBoneCache( m_boneCacheHandle );
|
||||
int boneMask = BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT;
|
||||
int boneMask = BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT | BONE_USED_BY_BONE_MERGE;
|
||||
|
||||
// TF queries these bones to position weapons when players are killed
|
||||
#if defined( TF_DLL )
|
||||
boneMask |= BONE_USED_BY_BONE_MERGE;
|
||||
#endif
|
||||
if ( pcache )
|
||||
{
|
||||
if ( pcache->IsValid( gpGlobals->curtime ) && (pcache->m_boneMask & boneMask) == boneMask && pcache->m_timeValid <= gpGlobals->curtime)
|
||||
{
|
||||
// Msg("%s:%s:%s (%x:%x:%8.4f) cache\n", GetClassname(), GetDebugName(), STRING(GetModelName()), boneMask, pcache->m_boneMask, pcache->m_timeValid );
|
||||
// in memory and still valid, use it!
|
||||
return pcache;
|
||||
}
|
||||
// in memory, but missing some of the bone masks
|
||||
if ( (pcache->m_boneMask & boneMask) != boneMask )
|
||||
{
|
||||
Studio_DestroyBoneCache( m_boneCacheHandle );
|
||||
m_boneCacheHandle = 0;
|
||||
pcache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
matrix3x4_t bonetoworld[MAXSTUDIOBONES];
|
||||
SetupBones( bonetoworld, boneMask );
|
||||
SetupBones( GetModelPtr(), bonetoworld, boneMask );
|
||||
|
||||
if ( pcache )
|
||||
{
|
||||
// still in memory but out of date, refresh the bones.
|
||||
pcache->UpdateBones( bonetoworld, pStudioHdr->numbones(), gpGlobals->curtime );
|
||||
}
|
||||
else
|
||||
{
|
||||
bonecacheparams_t params;
|
||||
params.pStudioHdr = pStudioHdr;
|
||||
params.pBoneToWorld = bonetoworld;
|
||||
params.curtime = gpGlobals->curtime;
|
||||
params.boneMask = boneMask;
|
||||
for (auto pChild = FirstMoveChild(); pChild; pChild = pChild->NextMovePeer())
|
||||
{
|
||||
auto pChildAnimating = dynamic_cast<CBaseAnimating*>(pChild);
|
||||
|
||||
m_boneCacheHandle = Studio_CreateBoneCache( params );
|
||||
pcache = Studio_GetBoneCache( m_boneCacheHandle );
|
||||
}
|
||||
Assert(pcache);
|
||||
return pcache;
|
||||
if (!pChildAnimating || !pChildAnimating->GetModelPtr())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("animating: %i %s %s\n", pChildAnimating->entindex(), pChildAnimating->GetDebugName(), pChildAnimating->GetModelName().ToCStr());
|
||||
|
||||
matrix3x4_t childbones[MAXSTUDIOBONES];
|
||||
pChildAnimating->SetupBones(pChildAnimating->GetModelPtr(), childbones, boneMask);
|
||||
}
|
||||
|
||||
Assert(m_pBoneCache);
|
||||
return m_pBoneCache;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2810,7 +2832,12 @@ void CBaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaterni
|
|||
return;
|
||||
}
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, GetPoseParameterArray() );
|
||||
float flPoseParams[MAXSTUDIOPOSEPARAM];
|
||||
float flEncodedParams[MAXSTUDIOBONECTRLS];
|
||||
|
||||
GetPoseParameters( pStudioHdr, flPoseParams );
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, flPoseParams );
|
||||
boneSetup.InitPose( pos, q );
|
||||
|
||||
boneSetup.AccumulatePose( pos, q, GetSequence(), GetCycle(), 1.0, gpGlobals->curtime, m_pIk );
|
||||
|
@ -2825,7 +2852,8 @@ void CBaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaterni
|
|||
{
|
||||
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, NULL );
|
||||
}
|
||||
boneSetup.CalcBoneAdj( pos, q, GetEncodedControllerArray() );
|
||||
GetEncodedControllers( pStudioHdr, flEncodedParams );
|
||||
boneSetup.CalcBoneAdj( pos, q, flEncodedParams );
|
||||
}
|
||||
|
||||
int CBaseAnimating::DrawDebugTextOverlays(void)
|
||||
|
@ -3067,8 +3095,14 @@ void CBaseAnimating::DrawRawSkeleton( matrix3x4_t boneToWorld[], int boneMask, b
|
|||
int i;
|
||||
int r = 255;
|
||||
int g = 255;
|
||||
int b = monocolor ? 255 : 0;
|
||||
|
||||
int b = monocolor ? 255 : 0;
|
||||
|
||||
if (boneMask & 0x00080000)
|
||||
{
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 255;
|
||||
}
|
||||
|
||||
for (i = 0; i < pStudioHdr->numbones(); i++)
|
||||
{
|
||||
|
@ -3080,6 +3114,14 @@ void CBaseAnimating::DrawRawSkeleton( matrix3x4_t boneToWorld[], int boneMask, b
|
|||
{
|
||||
Vector p2;
|
||||
MatrixPosition( boneToWorld[pStudioHdr->pBone( i )->parent], p2 );
|
||||
if (pStudioHdr->pBone(i)->flags & BONE_USED_BY_BONE_MERGE)
|
||||
{
|
||||
r = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = 0;
|
||||
}
|
||||
NDebugOverlay::Line( p1, p2, r, g, b, noDepthTest, duration );
|
||||
}
|
||||
}
|
||||
|
@ -3605,6 +3647,12 @@ CStudioHdr *CBaseAnimating::OnNewModel()
|
|||
{
|
||||
(void) BaseClass::OnNewModel();
|
||||
|
||||
if ( m_pBoneMergeCache )
|
||||
{
|
||||
delete m_pBoneMergeCache;
|
||||
m_pBoneMergeCache = NULL;
|
||||
}
|
||||
|
||||
// TODO: if dynamic, validate m_Sequence and apply queued body group settings?
|
||||
if ( IsDynamicModelLoading() )
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "studio.h"
|
||||
#include "datacache/idatacache.h"
|
||||
#include "tier0/threadtools.h"
|
||||
#include "bone_merge_cache.h"
|
||||
|
||||
class CBasePlayer;
|
||||
struct animevent_t;
|
||||
|
@ -136,7 +137,7 @@ public:
|
|||
virtual void GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask );
|
||||
|
||||
virtual void GetBoneTransform( int iBone, matrix3x4_t &pBoneToWorld );
|
||||
virtual void SetupBones( matrix3x4_t *pBoneToWorld, int boneMask );
|
||||
virtual void SetupBones( CStudioHdr *pStudioHdr, matrix3x4_t *pBoneToWorld, int boneMask );
|
||||
virtual void CalculateIKLocks( float currentTime );
|
||||
virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
|
||||
|
||||
|
@ -160,7 +161,8 @@ public:
|
|||
bool HasPoseParameter( int iSequence, const char *szName );
|
||||
bool HasPoseParameter( int iSequence, int iParameter );
|
||||
float EdgeLimitPoseParameter( int iParameter, float flValue, float flBase = 0.0f );
|
||||
|
||||
virtual void GetPoseParameters(CStudioHdr* pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM]);
|
||||
virtual void GetEncodedControllers(CStudioHdr* pStudioHdr, float encodedControllers[MAXSTUDIOBONECTRLS]);
|
||||
protected:
|
||||
// The modus operandi for pose parameters is that you should not use the const char * version of the functions
|
||||
// in general code -- it causes many many string comparisons, which is slower than you think. Better is to
|
||||
|
@ -326,8 +328,7 @@ public:
|
|||
|
||||
void BuildMatricesWithBoneMerge( const CStudioHdr *pStudioHdr, const QAngle& angles,
|
||||
const Vector& origin, const Vector pos[MAXSTUDIOBONES],
|
||||
const Quaternion q[MAXSTUDIOBONES], matrix3x4_t bonetoworld[MAXSTUDIOBONES],
|
||||
CBaseAnimating *pParent, CBoneCache *pParentCache );
|
||||
const Quaternion q[MAXSTUDIOBONES], matrix3x4_t bonetoworld[MAXSTUDIOBONES], int boneMask );
|
||||
|
||||
void SetFadeDistance( float minFadeDist, float maxFadeDist );
|
||||
|
||||
|
@ -336,10 +337,10 @@ public:
|
|||
inline void ClearBoneCacheFlags( unsigned short fFlag ) { m_fBoneCacheFlags &= ~fFlag; }
|
||||
|
||||
bool PrefetchSequence( int iSequence );
|
||||
virtual void LockStudioHdr();
|
||||
virtual void UnlockStudioHdr();
|
||||
|
||||
private:
|
||||
void LockStudioHdr();
|
||||
void UnlockStudioHdr();
|
||||
|
||||
void StudioFrameAdvanceInternal( CStudioHdr *pStudioHdr, float flInterval );
|
||||
void InputSetLightingOriginRelative( inputdata_t &inputdata );
|
||||
|
@ -422,10 +423,12 @@ protected:
|
|||
public:
|
||||
COutputEvent m_OnIgnite;
|
||||
|
||||
private:
|
||||
public:
|
||||
CStudioHdr *m_pStudioHdr;
|
||||
CThreadFastMutex m_StudioHdrInitLock;
|
||||
CThreadFastMutex m_BoneSetupMutex;
|
||||
CBoneCache *m_pBoneCache;
|
||||
CBoneMergeCache *m_pBoneMergeCache;
|
||||
|
||||
// FIXME: necessary so that cyclers can hack m_bSequenceFinished
|
||||
friend class CFlexCycler;
|
||||
|
|
|
@ -1100,13 +1100,13 @@ void CNPC_Barnacle::LiftRagdoll( float flBiteZOffset )
|
|||
|
||||
// Get the current bone matrix
|
||||
matrix3x4_t pBoneToWorld[MAXSTUDIOBONES];
|
||||
pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
pAnimating->SetupBones( pAnimating->GetModelPtr(), pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
|
||||
// Apply the forces to the ragdoll
|
||||
RagdollApplyAnimationAsVelocity( *(m_hRagdoll->GetRagdoll()), m_pRagdollBones, pBoneToWorld, 0.2 );
|
||||
|
||||
// Store off the current bone matrix for next time
|
||||
pAnimating->SetupBones( m_pRagdollBones, BONE_USED_BY_ANYTHING );
|
||||
pAnimating->SetupBones( pAnimating->GetModelPtr(), m_pRagdollBones, BONE_USED_BY_ANYTHING );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1540,7 +1540,7 @@ You can use this stanza to try to counterplace the constraint on the player's he
|
|||
UpdateTongue();
|
||||
|
||||
// Store off the current bone matrix so we have it next frame
|
||||
pAnimating->SetupBones( m_pRagdollBones, BONE_USED_BY_ANYTHING );
|
||||
pAnimating->SetupBones( pAnimating->GetModelPtr(), m_pRagdollBones, BONE_USED_BY_ANYTHING );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ void CRagdollProp::Spawn( void )
|
|||
}
|
||||
|
||||
matrix3x4_t pBoneToWorld[MAXSTUDIOBONES];
|
||||
BaseClass::SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING ); // FIXME: shouldn't this be a subset of the bones
|
||||
BaseClass::SetupBones( GetModelPtr(), pBoneToWorld, BONE_USED_BY_ANYTHING ); // FIXME: shouldn't this be a subset of the bones
|
||||
// this is useless info after the initial conditions are set
|
||||
SetAbsAngles( vec3_angle );
|
||||
int collisionGroup = (m_spawnflags & SF_RAGDOLLPROP_DEBRIS) ? COLLISION_GROUP_DEBRIS : COLLISION_GROUP_NONE;
|
||||
|
@ -827,7 +827,7 @@ void CRagdollProp::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
|||
// no ragdoll, fall through to base class
|
||||
if ( !m_ragdoll.listCount )
|
||||
{
|
||||
BaseClass::SetupBones( pBoneToWorld, boneMask );
|
||||
BaseClass::SetupBones( GetModelPtr(), pBoneToWorld, boneMask );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1338,10 +1338,10 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
|||
float fPreviousCycle = clamp(pAnimating->GetCycle()-( dt * ( 1 / fSequenceDuration ) ),0.f,1.f);
|
||||
float fCurCycle = pAnimating->GetCycle();
|
||||
// Get current bones positions
|
||||
pAnimating->SetupBones( pBoneToWorldNext, BONE_USED_BY_ANYTHING );
|
||||
pAnimating->SetupBones( pAnimating->GetModelPtr(), pBoneToWorldNext, BONE_USED_BY_ANYTHING );
|
||||
// Get previous bones positions
|
||||
pAnimating->SetCycle( fPreviousCycle );
|
||||
pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
pAnimating->SetupBones( pAnimating->GetModelPtr(), pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
// Restore current cycle
|
||||
pAnimating->SetCycle( fCurCycle );
|
||||
|
||||
|
@ -1579,7 +1579,7 @@ CRagdollProp *CreateServerRagdollAttached( CBaseAnimating *pAnimating, const Vec
|
|||
|
||||
pRagdoll->InitRagdollAnimation();
|
||||
matrix3x4_t pBoneToWorld[MAXSTUDIOBONES];
|
||||
pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
pAnimating->SetupBones( pAnimating->GetModelPtr(), pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
pRagdoll->InitRagdollAttached( pAttached, vecForce, forceBone, pBoneToWorld, pBoneToWorld, 0.1, collisionGroup, pParentEntity, boneAttach, boneOrigin, parentBoneAttach, originAttached );
|
||||
|
||||
return pRagdoll;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
ConVar sv_unlag( "sv_unlag", "1", FCVAR_DEVELOPMENTONLY, "Enables player lag compensation" );
|
||||
ConVar sv_maxunlag( "sv_maxunlag", "1.0", FCVAR_DEVELOPMENTONLY, "Maximum lag compensation in seconds", true, 0.0f, true, 1.0f );
|
||||
ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "1", FCVAR_DEVELOPMENTONLY, "Flushes entity bone cache on lag compensation" );
|
||||
ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "0", FCVAR_DEVELOPMENTONLY, "Flushes entity bone cache on lag compensation" );
|
||||
ConVar sv_unlag_fixstuck( "sv_unlag_fixstuck", "0", FCVAR_DEVELOPMENTONLY, "Disallow backtracking a player for lag compensation if it will cause them to become stuck" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -78,6 +78,7 @@ $Project
|
|||
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "$SRCDIR\game\shared\bone_merge_cache.cpp"
|
||||
$File "$SRCDIR\game\shared\achievement_saverestore.cpp"
|
||||
$File "$SRCDIR\game\shared\achievement_saverestore.h"
|
||||
$File "$SRCDIR\game\shared\achievementmgr.cpp"
|
||||
|
@ -785,6 +786,7 @@ $Project
|
|||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\game\shared\bone_merge_cache.h"
|
||||
$File "$SRCDIR\public\mathlib\amd3dx.h"
|
||||
$File "$SRCDIR\game\shared\ammodef.h"
|
||||
$File "$SRCDIR\game\shared\base_playeranimstate.h"
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
// NVNT start extra includes
|
||||
#include "haptics/haptic_utils.h"
|
||||
#include "studio.h"
|
||||
#include "tier3/tier3.h"
|
||||
#ifdef CLIENT_DLL
|
||||
#include "prediction.h"
|
||||
#endif
|
||||
|
@ -90,6 +92,7 @@ CBaseCombatWeapon::CBaseCombatWeapon() : BASECOMBATWEAPON_DERIVED_FROM()
|
|||
#if !defined( CLIENT_DLL )
|
||||
m_pConstraint = NULL;
|
||||
OnBaseCombatWeaponCreated( this );
|
||||
m_pStudioWorldHdr = NULL;
|
||||
#endif
|
||||
|
||||
m_hWeaponFileInfo = GetInvalidWeaponInfoHandle();
|
||||
|
@ -117,10 +120,76 @@ CBaseCombatWeapon::~CBaseCombatWeapon( void )
|
|||
physenv->DestroyConstraint( m_pConstraint );
|
||||
m_pConstraint = NULL;
|
||||
}
|
||||
OnBaseCombatWeaponDestroyed( this );
|
||||
OnBaseCombatWeaponDestroyed(this);
|
||||
delete m_pStudioWorldHdr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
void CBaseCombatWeapon::LockStudioHdr()
|
||||
{
|
||||
BaseClass::LockStudioHdr();
|
||||
|
||||
AUTO_LOCK( m_StudioHdrInitLock );
|
||||
const auto worldModel = modelinfo->GetModel(m_iWorldModelIndex);
|
||||
if (worldModel)
|
||||
{
|
||||
MDLHandle_t hStudioHdr = modelinfo->GetCacheHandle( worldModel );
|
||||
if ( hStudioHdr != MDLHANDLE_INVALID )
|
||||
{
|
||||
const studiohdr_t *pStudioHdr = mdlcache->LockStudioHdr( hStudioHdr );
|
||||
CStudioHdr *pStudioHdrContainer = NULL;
|
||||
if ( !m_pStudioWorldHdr )
|
||||
{
|
||||
if ( pStudioHdr )
|
||||
{
|
||||
pStudioHdrContainer = new CStudioHdr;
|
||||
pStudioHdrContainer->Init( pStudioHdr, mdlcache );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pStudioHdrContainer = m_pStudioWorldHdr;
|
||||
}
|
||||
|
||||
Assert( ( pStudioHdr == NULL && pStudioHdrContainer == NULL ) || pStudioHdrContainer->GetRenderHdr() == pStudioHdr );
|
||||
|
||||
if ( pStudioHdrContainer && pStudioHdrContainer->GetVirtualModel() )
|
||||
{
|
||||
MDLHandle_t hVirtualModel = VoidPtrToMDLHandle( pStudioHdrContainer->GetRenderHdr()->VirtualModel() );
|
||||
mdlcache->LockStudioHdr( hVirtualModel );
|
||||
}
|
||||
m_pStudioWorldHdr = pStudioHdrContainer; // must be last to ensure virtual model correctly set up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseCombatWeapon::UnlockStudioHdr()
|
||||
{
|
||||
BaseClass::UnlockStudioHdr();
|
||||
|
||||
if ( m_pStudioWorldHdr )
|
||||
{
|
||||
const auto worldModel = modelinfo->GetModel(m_iWorldModelIndex);
|
||||
if (worldModel)
|
||||
{
|
||||
mdlcache->UnlockStudioHdr( modelinfo->GetCacheHandle( worldModel ) );
|
||||
if ( m_pStudioWorldHdr->GetVirtualModel() )
|
||||
{
|
||||
MDLHandle_t hVirtualModel = VoidPtrToMDLHandle( m_pStudioWorldHdr->GetRenderHdr()->VirtualModel() );
|
||||
mdlcache->UnlockStudioHdr( hVirtualModel );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseCombatWeapon::SetupBones(CStudioHdr* pStudioHdr, matrix3x4_t* pBoneToWorld, int boneMask)
|
||||
{
|
||||
// hooked m_pStudioHdr to world model instead (m_pStudioWorldHdr)
|
||||
BaseClass::SetupBones(m_pStudioWorldHdr, pBoneToWorld, boneMask);
|
||||
}
|
||||
#endif
|
||||
|
||||
void CBaseCombatWeapon::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#ifndef COMBATWEAPON_SHARED_H
|
||||
#define COMBATWEAPON_SHARED_H
|
||||
#include "studio.h"
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
@ -162,7 +163,11 @@ public:
|
|||
|
||||
CBaseCombatWeapon();
|
||||
virtual ~CBaseCombatWeapon();
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
virtual void LockStudioHdr();
|
||||
virtual void UnlockStudioHdr();
|
||||
virtual void SetupBones( CStudioHdr* pStudioHdr, matrix3x4_t *pBoneToWorld, int boneMask );
|
||||
#endif
|
||||
virtual bool IsBaseCombatWeapon( void ) const { return true; }
|
||||
virtual CBaseCombatWeapon *MyCombatWeaponPointer( void ) { return this; }
|
||||
|
||||
|
@ -612,9 +617,9 @@ private:
|
|||
bool m_bReloadHudHintDisplayed; // Have we displayed a reload HUD hint since this weapon was deployed?
|
||||
float m_flHudHintPollTime; // When to poll the weapon again for whether it should display a hud hint.
|
||||
float m_flHudHintMinDisplayTime; // if the hint is squelched before this, reset my counter so we'll display it again.
|
||||
|
||||
// Server only
|
||||
#if !defined( CLIENT_DLL )
|
||||
CStudioHdr *m_pStudioWorldHdr;
|
||||
|
||||
// Outputs
|
||||
protected:
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "bone_setup.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "studio.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -27,7 +29,7 @@ CBoneMergeCache::CBoneMergeCache()
|
|||
m_nFollowBoneSetupMask = 0;
|
||||
}
|
||||
|
||||
void CBoneMergeCache::Init( C_BaseAnimating *pOwner )
|
||||
void CBoneMergeCache::Init( CBaseAnimating *pOwner )
|
||||
{
|
||||
m_pOwner = pOwner;
|
||||
m_pFollow = NULL;
|
||||
|
@ -40,7 +42,7 @@ void CBoneMergeCache::Init( C_BaseAnimating *pOwner )
|
|||
void CBoneMergeCache::UpdateCache()
|
||||
{
|
||||
CStudioHdr *pOwnerHdr = m_pOwner ? m_pOwner->GetModelPtr() : NULL;
|
||||
if ( !pOwnerHdr )
|
||||
if ( !pOwnerHdr || !m_pOwner->GetFollowedEntity())
|
||||
{
|
||||
if ( m_pOwnerHdr )
|
||||
{
|
||||
|
@ -56,7 +58,11 @@ void CBoneMergeCache::UpdateCache()
|
|||
return;
|
||||
}
|
||||
|
||||
C_BaseAnimating *pTestFollow = m_pOwner->FindFollowedEntity();
|
||||
#ifdef CLIENT_DLL
|
||||
C_BaseAnimating* pTestFollow = m_pOwner->FindFollowedEntity();
|
||||
#else
|
||||
CBaseAnimating* pTestFollow = dynamic_cast<CBaseAnimating*>(m_pOwner->GetFollowedEntity());
|
||||
#endif
|
||||
CStudioHdr *pTestHdr = (pTestFollow ? pTestFollow->GetModelPtr() : NULL);
|
||||
const studiohdr_t *pTestStudioHDR = (pTestHdr ? pTestHdr->GetRenderHdr() : NULL);
|
||||
if ( pTestFollow != m_pFollow || pTestHdr != m_pFollowHdr || pTestStudioHDR != m_pFollowRenderHdr || pOwnerHdr != m_pOwnerHdr )
|
||||
|
@ -83,7 +89,9 @@ void CBoneMergeCache::UpdateCache()
|
|||
int parentBoneIndex = Studio_BoneIndexByName( m_pFollowHdr, pOwnerBones[i].pszName() );
|
||||
if ( parentBoneIndex < 0 )
|
||||
continue;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
printf("bone attach: (%i - %i) (%s - %s) (%s - %s)\n", m_pFollow->entindex(), m_pOwner->entindex(), m_pFollow->GetDebugName(), m_pOwner->GetDebugName(), m_pFollow->GetModelName(), m_pOwner->GetModelName());
|
||||
#endif
|
||||
// Add a merged bone here.
|
||||
CMergedBone mergedBone;
|
||||
mergedBone.m_iMyBone = i;
|
||||
|
@ -122,7 +130,7 @@ void CBoneMergeCache::UpdateCache()
|
|||
ConVar r_captain_canteen_is_angry ( "r_captain_canteen_is_angry", "1" );
|
||||
#endif
|
||||
|
||||
void CBoneMergeCache::MergeMatchingBones( int boneMask )
|
||||
void CBoneMergeCache::MergeMatchingBones( int boneMask , matrix3x4_t mergedbones[MAXSTUDIOBONES] )
|
||||
{
|
||||
UpdateCache();
|
||||
|
||||
|
@ -130,55 +138,29 @@ void CBoneMergeCache::MergeMatchingBones( int boneMask )
|
|||
if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
|
||||
return;
|
||||
|
||||
// Have the entity we're following setup its bones.
|
||||
bool bWorked = m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
|
||||
// We suspect there's some cases where SetupBones couldn't do its thing, and then this causes Captain Canteen.
|
||||
Assert ( bWorked );
|
||||
if ( !bWorked )
|
||||
{
|
||||
// Usually this means your parent is invisible or gone or whatever.
|
||||
// This routine has no way to tell its caller not to draw itself unfortunately.
|
||||
// But we can shrink all the bones down to zero size.
|
||||
// But it might still spawn particle systems? :-(
|
||||
matrix3x4_t NewBone;
|
||||
MatrixScaleByZero ( NewBone );
|
||||
MatrixSetTranslation ( Vector ( 0.0f, 0.0f, 0.0f ), NewBone );
|
||||
#ifdef STAGING_ONLY
|
||||
if ( r_captain_canteen_is_angry.GetBool() )
|
||||
{
|
||||
// We actually want to see when Captain Canteen happened, and make it really obvious that (a) he was here and (b) this code would have fixed him.
|
||||
float HowAngry = 20.0f; // Leon's getting larger!
|
||||
MatrixSetColumn ( Vector ( HowAngry, 0.0f, 0.0f ), 0, NewBone );
|
||||
MatrixSetColumn ( Vector ( 0.0f, HowAngry, 0.0f ), 1, NewBone );
|
||||
MatrixSetColumn ( Vector ( 0.0f, 0.0f, HowAngry ), 2, NewBone );
|
||||
}
|
||||
matrix3x4_t bones[MAXSTUDIOBONES];
|
||||
// Have the entity we're following setup its bones.
|
||||
#ifdef CLIENT_DLL
|
||||
m_pFollow->SetupBones(bones, MAXSTUDIOBONES, m_nFollowBoneSetupMask, gpGlobals->curtime);
|
||||
#else
|
||||
m_pFollow->SetupBones(m_pFollow->GetModelPtr(), bones, m_nFollowBoneSetupMask);
|
||||
#endif
|
||||
|
||||
for ( int i=0; i < m_MergedBones.Count(); i++ )
|
||||
{
|
||||
int iOwnerBone = m_MergedBones[i].m_iMyBone;
|
||||
|
||||
// Only update bones reference by the bone mask.
|
||||
if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
|
||||
continue;
|
||||
|
||||
m_pOwner->GetBoneForWrite( iOwnerBone ) = NewBone;
|
||||
}
|
||||
}
|
||||
else
|
||||
// Now copy the bone matrices.
|
||||
for ( int i=0; i < m_MergedBones.Count(); i++ )
|
||||
{
|
||||
// Now copy the bone matrices.
|
||||
for ( int i=0; i < m_MergedBones.Count(); i++ )
|
||||
{
|
||||
int iOwnerBone = m_MergedBones[i].m_iMyBone;
|
||||
int iParentBone = m_MergedBones[i].m_iParentBone;
|
||||
int iOwnerBone = m_MergedBones[i].m_iMyBone;
|
||||
int iParentBone = m_MergedBones[i].m_iParentBone;
|
||||
|
||||
// Only update bones reference by the bone mask.
|
||||
if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
|
||||
continue;
|
||||
|
||||
// Only update bones reference by the bone mask.
|
||||
if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
|
||||
continue;
|
||||
|
||||
MatrixCopy( m_pFollow->GetBone( iParentBone ), m_pOwner->GetBoneForWrite( iOwnerBone ) );
|
||||
}
|
||||
#ifdef CLIENT_DLL
|
||||
MatrixCopy( bones[ iParentBone ], mergedbones[ iOwnerBone ] );
|
||||
#else
|
||||
MatrixCopy( bones[ iParentBone ], mergedbones[ iOwnerBone ] );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,8 +237,14 @@ bool CBoneMergeCache::GetAimEntOrigin( Vector *pAbsOrigin, QAngle *pAbsAngles )
|
|||
// all over the place, then this won't get the right results.
|
||||
|
||||
// Get mFollowBone.
|
||||
m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
|
||||
const matrix3x4_t &mFollowBone = m_pFollow->GetBone( m_MergedBones[0].m_iParentBone );
|
||||
matrix3x4_t bones[MAXSTUDIOBONES];
|
||||
// Have the entity we're following setup its bones.
|
||||
#ifdef CLIENT_DLL
|
||||
m_pFollow->SetupBones(bones, MAXSTUDIOBONES, m_nFollowBoneSetupMask, gpGlobals->curtime);
|
||||
#else
|
||||
m_pFollow->SetupBones(m_pFollow->GetModelPtr(), bones, m_nFollowBoneSetupMask);
|
||||
#endif
|
||||
const matrix3x4_t &mFollowBone = bones[ m_MergedBones[0].m_iParentBone ];
|
||||
|
||||
// Get Inverse( mBoneLocal )
|
||||
matrix3x4_t mBoneLocal, mBoneLocalInv;
|
||||
|
@ -280,8 +268,14 @@ bool CBoneMergeCache::GetRootBone( matrix3x4_t &rootBone )
|
|||
return false;
|
||||
|
||||
// Get mFollowBone.
|
||||
m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
|
||||
rootBone = m_pFollow->GetBone( m_MergedBones[0].m_iParentBone );
|
||||
matrix3x4_t bones[MAXSTUDIOBONES];
|
||||
// Have the entity we're following setup its bones.
|
||||
#ifdef CLIENT_DLL
|
||||
m_pFollow->SetupBones(bones, MAXSTUDIOBONES, m_nFollowBoneSetupMask, gpGlobals->curtime);
|
||||
#else
|
||||
m_pFollow->SetupBones(m_pFollow->GetModelPtr(), bones, m_nFollowBoneSetupMask);
|
||||
#endif
|
||||
rootBone = bones[ m_MergedBones[0].m_iParentBone ];
|
||||
return true;
|
||||
}
|
||||
|
|
@ -6,12 +6,21 @@
|
|||
|
||||
#ifndef BONE_MERGE_CACHE_H
|
||||
#define BONE_MERGE_CACHE_H
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "studio.h"
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
class C_BaseAnimating;
|
||||
#ifndef CBaseAnimating
|
||||
#define CBaseAnimating C_BaseAnimating
|
||||
#endif
|
||||
#else
|
||||
class CBaseAnimating;
|
||||
#endif
|
||||
|
||||
class CStudioHdr;
|
||||
|
||||
|
||||
|
@ -24,14 +33,14 @@ public:
|
|||
|
||||
CBoneMergeCache();
|
||||
|
||||
void Init( C_BaseAnimating *pOwner );
|
||||
void Init( CBaseAnimating *pOwner );
|
||||
|
||||
// Updates the lookups that let it merge bones quickly.
|
||||
void UpdateCache();
|
||||
|
||||
// This copies the transform from all bones in the followed entity that have
|
||||
// names that match our bones.
|
||||
void MergeMatchingBones( int boneMask );
|
||||
void MergeMatchingBones( int boneMask, matrix3x4_t mergedbones[MAXSTUDIOBONES] );
|
||||
|
||||
// copy bones instead of matrices
|
||||
void CopyParentToChild( const Vector parentPos[], const Quaternion parentQ[], Vector childPos[], Quaternion childQ[], int boneMask );
|
||||
|
@ -48,11 +57,11 @@ public:
|
|||
private:
|
||||
|
||||
// This is the entity that we're keeping the cache updated for.
|
||||
C_BaseAnimating *m_pOwner;
|
||||
CBaseAnimating *m_pOwner;
|
||||
|
||||
// All the cache data is based off these. When they change, the cache data is regenerated.
|
||||
// These are either all valid pointers or all NULL.
|
||||
C_BaseAnimating *m_pFollow;
|
||||
CBaseAnimating *m_pFollow;
|
||||
CStudioHdr *m_pFollowHdr;
|
||||
const studiohdr_t *m_pFollowRenderHdr;
|
||||
CStudioHdr *m_pOwnerHdr;
|
|
@ -419,7 +419,7 @@ public:
|
|||
float m_timeValid;
|
||||
int m_boneMask;
|
||||
|
||||
private:
|
||||
public:
|
||||
matrix3x4_t *BoneArray();
|
||||
short *StudioToCached();
|
||||
short *CachedToStudio();
|
||||
|
|
Loading…
Reference in a new issue