aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/bone_merge_cache.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/bone_merge_cache.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/bone_merge_cache.cpp')
-rw-r--r--mp/src/game/client/bone_merge_cache.cpp576
1 files changed, 288 insertions, 288 deletions
diff --git a/mp/src/game/client/bone_merge_cache.cpp b/mp/src/game/client/bone_merge_cache.cpp
index eb954ced..6ef767ea 100644
--- a/mp/src/game/client/bone_merge_cache.cpp
+++ b/mp/src/game/client/bone_merge_cache.cpp
@@ -1,288 +1,288 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "bone_merge_cache.h"
-#include "bone_setup.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-//-----------------------------------------------------------------------------
-// CBoneMergeCache
-//-----------------------------------------------------------------------------
-
-CBoneMergeCache::CBoneMergeCache()
-{
- m_pOwner = NULL;
- m_pFollow = NULL;
- m_pFollowHdr = NULL;
- m_pFollowRenderHdr = NULL;
- m_pOwnerHdr = NULL;
- m_nFollowBoneSetupMask = 0;
-}
-
-void CBoneMergeCache::Init( C_BaseAnimating *pOwner )
-{
- m_pOwner = pOwner;
- m_pFollow = NULL;
- m_pFollowHdr = NULL;
- m_pFollowRenderHdr = NULL;
- m_pOwnerHdr = NULL;
- m_nFollowBoneSetupMask = 0;
-}
-
-void CBoneMergeCache::UpdateCache()
-{
- CStudioHdr *pOwnerHdr = m_pOwner ? m_pOwner->GetModelPtr() : NULL;
- if ( !pOwnerHdr )
- {
- if ( m_pOwnerHdr )
- {
- // Owner's model got swapped out
- m_MergedBones.Purge();
- m_BoneMergeBits.Purge();
- m_pFollow = NULL;
- m_pFollowHdr = NULL;
- m_pFollowRenderHdr = NULL;
- m_pOwnerHdr = NULL;
- m_nFollowBoneSetupMask = 0;
- }
- return;
- }
-
- C_BaseAnimating *pTestFollow = m_pOwner->FindFollowedEntity();
- 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 )
- {
- m_MergedBones.Purge();
- m_BoneMergeBits.Purge();
-
- // Update the cache.
- if ( pTestFollow && pTestHdr && pOwnerHdr )
- {
- m_pFollow = pTestFollow;
- m_pFollowHdr = pTestHdr;
- m_pFollowRenderHdr = pTestStudioHDR;
- m_pOwnerHdr = pOwnerHdr;
-
- m_BoneMergeBits.SetSize( pOwnerHdr->numbones() / 8 + 1 );
- memset( m_BoneMergeBits.Base(), 0, m_BoneMergeBits.Count() );
-
- mstudiobone_t *pOwnerBones = m_pOwnerHdr->pBone( 0 );
-
- m_nFollowBoneSetupMask = BONE_USED_BY_BONE_MERGE;
- for ( int i = 0; i < m_pOwnerHdr->numbones(); i++ )
- {
- int parentBoneIndex = Studio_BoneIndexByName( m_pFollowHdr, pOwnerBones[i].pszName() );
- if ( parentBoneIndex < 0 )
- continue;
-
- // Add a merged bone here.
- CMergedBone mergedBone;
- mergedBone.m_iMyBone = i;
- mergedBone.m_iParentBone = parentBoneIndex;
- m_MergedBones.AddToTail( mergedBone );
-
- m_BoneMergeBits[i>>3] |= ( 1 << ( i & 7 ) );
-
- if ( ( m_pFollowHdr->boneFlags( parentBoneIndex ) & BONE_USED_BY_BONE_MERGE ) == 0 )
- {
- m_nFollowBoneSetupMask = BONE_USED_BY_ANYTHING;
-// Warning("Performance warning: Merge with '%s'. Mark bone '%s' in model '%s' as being used by bone merge in the .qc!\n",
-// pOwnerHdr->pszName(), m_pFollowHdr->pBone( parentBoneIndex )->pszName(), m_pFollowHdr->pszName() );
- }
- }
-
- // No merged bones found? Slam the mask to 0
- if ( !m_MergedBones.Count() )
- {
- m_nFollowBoneSetupMask = 0;
- }
- }
- else
- {
- m_pFollow = NULL;
- m_pFollowHdr = NULL;
- m_pFollowRenderHdr = NULL;
- m_pOwnerHdr = NULL;
- m_nFollowBoneSetupMask = 0;
- }
- }
-}
-
-
-#ifdef STAGING_ONLY
-ConVar r_captain_canteen_is_angry ( "r_captain_canteen_is_angry", "1" );
-#endif
-
-void CBoneMergeCache::MergeMatchingBones( int boneMask )
-{
- UpdateCache();
-
- // If this is set, then all the other cache data is set.
- 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 );
- }
-#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++ )
- {
- 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;
-
- MatrixCopy( m_pFollow->GetBone( iParentBone ), m_pOwner->GetBoneForWrite( iOwnerBone ) );
- }
- }
-}
-
-
- // copy bones instead of matrices
-void CBoneMergeCache::CopyParentToChild( const Vector parentPos[], const Quaternion parentQ[], Vector childPos[], Quaternion childQ[], int boneMask )
-{
- UpdateCache();
-
- // If this is set, then all the other cache data is set.
- if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
- return;
-
- // 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;
-
- if ( m_pOwnerHdr->boneParent( iOwnerBone ) == -1 || m_pFollowHdr->boneParent( iParentBone ) == -1 )
- continue;
-
- // Only update bones reference by the bone mask.
- if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
- continue;
-
- childPos[ iOwnerBone ] = parentPos[ iParentBone ];
- childQ[ iOwnerBone ] = parentQ[ iParentBone ];
- }
-}
-
-void CBoneMergeCache::CopyChildToParent( const Vector childPos[], const Quaternion childQ[], Vector parentPos[], Quaternion parentQ[], int boneMask )
-{
- UpdateCache();
-
- // If this is set, then all the other cache data is set.
- if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
- return;
-
- // 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;
-
- if ( m_pOwnerHdr->boneParent( iOwnerBone ) == -1 || m_pFollowHdr->boneParent( iParentBone ) == -1 )
- continue;
-
- // Only update bones reference by the bone mask.
- if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
- continue;
-
- parentPos[ iParentBone ] = childPos[ iOwnerBone ];
- parentQ[ iParentBone ] = childQ[ iOwnerBone ];
- }
-}
-
-
-bool CBoneMergeCache::GetAimEntOrigin( Vector *pAbsOrigin, QAngle *pAbsAngles )
-{
- UpdateCache();
-
- // If this is set, then all the other cache data is set.
- if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
- return false;
-
- // We want the abs origin such that if we put the entity there, the first merged bone
- // will be aligned. This way the entity will be culled in the correct position.
- //
- // ie: mEntity * mBoneLocal = mFollowBone
- // so: mEntity = mFollowBone * Inverse( mBoneLocal )
- //
- // Note: the code below doesn't take animation into account. If the attached entity animates
- // 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 );
-
- // Get Inverse( mBoneLocal )
- matrix3x4_t mBoneLocal, mBoneLocalInv;
- SetupSingleBoneMatrix( m_pOwnerHdr, m_pOwner->GetSequence(), 0, m_MergedBones[0].m_iMyBone, mBoneLocal );
- MatrixInvert( mBoneLocal, mBoneLocalInv );
-
- // Now calculate mEntity = mFollowBone * Inverse( mBoneLocal )
- matrix3x4_t mEntity;
- ConcatTransforms( mFollowBone, mBoneLocalInv, mEntity );
- MatrixAngles( mEntity, *pAbsAngles, *pAbsOrigin );
-
- return true;
-}
-
-bool CBoneMergeCache::GetRootBone( matrix3x4_t &rootBone )
-{
- UpdateCache();
-
- // If this is set, then all the other cache data is set.
- if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
- return false;
-
- // Get mFollowBone.
- m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
- rootBone = m_pFollow->GetBone( m_MergedBones[0].m_iParentBone );
- return true;
-}
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "bone_merge_cache.h"
+#include "bone_setup.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// CBoneMergeCache
+//-----------------------------------------------------------------------------
+
+CBoneMergeCache::CBoneMergeCache()
+{
+ m_pOwner = NULL;
+ m_pFollow = NULL;
+ m_pFollowHdr = NULL;
+ m_pFollowRenderHdr = NULL;
+ m_pOwnerHdr = NULL;
+ m_nFollowBoneSetupMask = 0;
+}
+
+void CBoneMergeCache::Init( C_BaseAnimating *pOwner )
+{
+ m_pOwner = pOwner;
+ m_pFollow = NULL;
+ m_pFollowHdr = NULL;
+ m_pFollowRenderHdr = NULL;
+ m_pOwnerHdr = NULL;
+ m_nFollowBoneSetupMask = 0;
+}
+
+void CBoneMergeCache::UpdateCache()
+{
+ CStudioHdr *pOwnerHdr = m_pOwner ? m_pOwner->GetModelPtr() : NULL;
+ if ( !pOwnerHdr )
+ {
+ if ( m_pOwnerHdr )
+ {
+ // Owner's model got swapped out
+ m_MergedBones.Purge();
+ m_BoneMergeBits.Purge();
+ m_pFollow = NULL;
+ m_pFollowHdr = NULL;
+ m_pFollowRenderHdr = NULL;
+ m_pOwnerHdr = NULL;
+ m_nFollowBoneSetupMask = 0;
+ }
+ return;
+ }
+
+ C_BaseAnimating *pTestFollow = m_pOwner->FindFollowedEntity();
+ 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 )
+ {
+ m_MergedBones.Purge();
+ m_BoneMergeBits.Purge();
+
+ // Update the cache.
+ if ( pTestFollow && pTestHdr && pOwnerHdr )
+ {
+ m_pFollow = pTestFollow;
+ m_pFollowHdr = pTestHdr;
+ m_pFollowRenderHdr = pTestStudioHDR;
+ m_pOwnerHdr = pOwnerHdr;
+
+ m_BoneMergeBits.SetSize( pOwnerHdr->numbones() / 8 + 1 );
+ memset( m_BoneMergeBits.Base(), 0, m_BoneMergeBits.Count() );
+
+ mstudiobone_t *pOwnerBones = m_pOwnerHdr->pBone( 0 );
+
+ m_nFollowBoneSetupMask = BONE_USED_BY_BONE_MERGE;
+ for ( int i = 0; i < m_pOwnerHdr->numbones(); i++ )
+ {
+ int parentBoneIndex = Studio_BoneIndexByName( m_pFollowHdr, pOwnerBones[i].pszName() );
+ if ( parentBoneIndex < 0 )
+ continue;
+
+ // Add a merged bone here.
+ CMergedBone mergedBone;
+ mergedBone.m_iMyBone = i;
+ mergedBone.m_iParentBone = parentBoneIndex;
+ m_MergedBones.AddToTail( mergedBone );
+
+ m_BoneMergeBits[i>>3] |= ( 1 << ( i & 7 ) );
+
+ if ( ( m_pFollowHdr->boneFlags( parentBoneIndex ) & BONE_USED_BY_BONE_MERGE ) == 0 )
+ {
+ m_nFollowBoneSetupMask = BONE_USED_BY_ANYTHING;
+// Warning("Performance warning: Merge with '%s'. Mark bone '%s' in model '%s' as being used by bone merge in the .qc!\n",
+// pOwnerHdr->pszName(), m_pFollowHdr->pBone( parentBoneIndex )->pszName(), m_pFollowHdr->pszName() );
+ }
+ }
+
+ // No merged bones found? Slam the mask to 0
+ if ( !m_MergedBones.Count() )
+ {
+ m_nFollowBoneSetupMask = 0;
+ }
+ }
+ else
+ {
+ m_pFollow = NULL;
+ m_pFollowHdr = NULL;
+ m_pFollowRenderHdr = NULL;
+ m_pOwnerHdr = NULL;
+ m_nFollowBoneSetupMask = 0;
+ }
+ }
+}
+
+
+#ifdef STAGING_ONLY
+ConVar r_captain_canteen_is_angry ( "r_captain_canteen_is_angry", "1" );
+#endif
+
+void CBoneMergeCache::MergeMatchingBones( int boneMask )
+{
+ UpdateCache();
+
+ // If this is set, then all the other cache data is set.
+ 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 );
+ }
+#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++ )
+ {
+ 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;
+
+ MatrixCopy( m_pFollow->GetBone( iParentBone ), m_pOwner->GetBoneForWrite( iOwnerBone ) );
+ }
+ }
+}
+
+
+ // copy bones instead of matrices
+void CBoneMergeCache::CopyParentToChild( const Vector parentPos[], const Quaternion parentQ[], Vector childPos[], Quaternion childQ[], int boneMask )
+{
+ UpdateCache();
+
+ // If this is set, then all the other cache data is set.
+ if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
+ return;
+
+ // 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;
+
+ if ( m_pOwnerHdr->boneParent( iOwnerBone ) == -1 || m_pFollowHdr->boneParent( iParentBone ) == -1 )
+ continue;
+
+ // Only update bones reference by the bone mask.
+ if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
+ continue;
+
+ childPos[ iOwnerBone ] = parentPos[ iParentBone ];
+ childQ[ iOwnerBone ] = parentQ[ iParentBone ];
+ }
+}
+
+void CBoneMergeCache::CopyChildToParent( const Vector childPos[], const Quaternion childQ[], Vector parentPos[], Quaternion parentQ[], int boneMask )
+{
+ UpdateCache();
+
+ // If this is set, then all the other cache data is set.
+ if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
+ return;
+
+ // 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;
+
+ if ( m_pOwnerHdr->boneParent( iOwnerBone ) == -1 || m_pFollowHdr->boneParent( iParentBone ) == -1 )
+ continue;
+
+ // Only update bones reference by the bone mask.
+ if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
+ continue;
+
+ parentPos[ iParentBone ] = childPos[ iOwnerBone ];
+ parentQ[ iParentBone ] = childQ[ iOwnerBone ];
+ }
+}
+
+
+bool CBoneMergeCache::GetAimEntOrigin( Vector *pAbsOrigin, QAngle *pAbsAngles )
+{
+ UpdateCache();
+
+ // If this is set, then all the other cache data is set.
+ if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
+ return false;
+
+ // We want the abs origin such that if we put the entity there, the first merged bone
+ // will be aligned. This way the entity will be culled in the correct position.
+ //
+ // ie: mEntity * mBoneLocal = mFollowBone
+ // so: mEntity = mFollowBone * Inverse( mBoneLocal )
+ //
+ // Note: the code below doesn't take animation into account. If the attached entity animates
+ // 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 );
+
+ // Get Inverse( mBoneLocal )
+ matrix3x4_t mBoneLocal, mBoneLocalInv;
+ SetupSingleBoneMatrix( m_pOwnerHdr, m_pOwner->GetSequence(), 0, m_MergedBones[0].m_iMyBone, mBoneLocal );
+ MatrixInvert( mBoneLocal, mBoneLocalInv );
+
+ // Now calculate mEntity = mFollowBone * Inverse( mBoneLocal )
+ matrix3x4_t mEntity;
+ ConcatTransforms( mFollowBone, mBoneLocalInv, mEntity );
+ MatrixAngles( mEntity, *pAbsAngles, *pAbsOrigin );
+
+ return true;
+}
+
+bool CBoneMergeCache::GetRootBone( matrix3x4_t &rootBone )
+{
+ UpdateCache();
+
+ // If this is set, then all the other cache data is set.
+ if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
+ return false;
+
+ // Get mFollowBone.
+ m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
+ rootBone = m_pFollow->GetBone( m_MergedBones[0].m_iParentBone );
+ return true;
+}
+
+