Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

351 lines
20 KiB

//========= Copyright © Valve Corporation, All rights reserved. ============//
#include "mathlib/femodeldesc.h"
#include "mathlib/femodel.h"
#include "tier1/heapsort.h"
#include "tier1/fmtstr.h"
template < typename T >
inline CLockedResource< T > CloneArrayWithMarkers( CResourceStream *pStream, const T *pArray, uint nCount, const char *pName )
{
// create the marker for the start of the array
CFmtStr beginMsg( "Begin of %s, %d byte aligned, here: <", pName, VALIGNOF( T ) );
// align the marker so that it ends aligned, right before the array data
int nBeginMsgLength = beginMsg.Length( );
int nPreAlign = ( -int( pStream->GetTotalSize() + nBeginMsgLength ) ) & ( VALIGNOF( T ) - 1 );
V_memset( pStream->AllocateBytes( nPreAlign ), '-', nPreAlign );
void *pPrefixData = pStream->AllocateBytes( nBeginMsgLength );
Assert( !( ( uintp( pPrefixData ) + nBeginMsgLength ) & ( VALIGNOF( T ) - 1 ) ) );
V_memcpy( pPrefixData, beginMsg.Get(), nBeginMsgLength );
// write out the array
CLockedResource< T > result = CloneArray( pStream, pArray, nCount );
// add the end marker
pStream->WriteString( CFmtStr( "> End of %s, %d bytes total.", pName, nCount * sizeof( T ) ) );
return result;
}
#if 0//def _DEBUG
#define CloneArray( STREAM, ARRAY, COUNT ) CloneArrayWithMarkers( (STREAM), (ARRAY), (COUNT), #ARRAY );
#endif
CLockedResource< PhysFeModelDesc_t > Clone( CFeModel *pFeModel, CResourceStream *pStream )
{
CLockedResource< PhysFeModelDesc_t > pFx = pStream->Allocate< PhysFeModelDesc_t >( );
uint nDynamicNodes = pFeModel->m_nNodeCount - pFeModel->m_nStaticNodes;
pFx->m_flLocalForce = pFeModel->m_flLocalForce;
pFx->m_flLocalRotation = pFeModel->m_flLocalRotation;
pFx->m_nStaticNodeFlags = pFeModel->m_nStaticNodeFlags;
pFx->m_nDynamicNodeFlags = pFeModel->m_nDynamicNodeFlags;
pFx->m_nNodeCount = pFeModel->m_nNodeCount;
pFx->m_nStaticNodes = pFeModel->m_nStaticNodes;
pFx->m_nRotLockStaticNodes = pFeModel->m_nRotLockStaticNodes;
pFx->m_nSimdTriCount1 = pFeModel->m_nSimdTriCount[ 1 ];
pFx->m_nSimdTriCount2 = pFeModel->m_nSimdTriCount[ 2 ];
pFx->m_nSimdQuadCount1 = pFeModel->m_nSimdQuadCount[ 1 ];
pFx->m_nSimdQuadCount2 = pFeModel->m_nSimdQuadCount[ 2 ];
pFx->m_nQuadCount1 = pFeModel->m_nQuadCount[ 1 ];
pFx->m_nQuadCount2 = pFeModel->m_nQuadCount[ 2 ];
pFx->m_nFitMatrixCount1 = pFeModel->m_nFitMatrixCount[ 1 ];
pFx->m_nFitMatrixCount2 = pFeModel->m_nFitMatrixCount[ 2 ];
pFx->m_nSimdFitMatrixCount1 = pFeModel->m_nSimdFitMatrixCount[ 1 ];
pFx->m_nSimdFitMatrixCount2 = pFeModel->m_nSimdFitMatrixCount[ 2 ];
pFx->m_nRopeCount = pFeModel->m_nRopeCount;
pFx->m_nTreeDepth = pFeModel->m_nTreeDepth;
pFx->m_flDefaultSurfaceStretch = pFeModel->m_flDefaultSurfaceStretch;
pFx->m_flDefaultThreadStretch = pFeModel->m_flDefaultThreadStretch;
pFx->m_flDefaultGravityScale = pFeModel->m_flDefaultGravityScale;
pFx->m_flDefaultVelAirDrag = pFeModel->m_flDefaultVelAirDrag;
pFx->m_flDefaultExpAirDrag = pFeModel->m_flDefaultExpAirDrag;
pFx->m_flDefaultVelQuadAirDrag = pFeModel->m_flDefaultVelQuadAirDrag;
pFx->m_flDefaultExpQuadAirDrag = pFeModel->m_flDefaultExpQuadAirDrag;
pFx->m_flDefaultVelRodAirDrag = pFeModel->m_flDefaultVelRodAirDrag;
pFx->m_flDefaultExpRodAirDrag = pFeModel->m_flDefaultExpRodAirDrag;
pFx->m_flQuadVelocitySmoothRate = pFeModel->m_flQuadVelocitySmoothRate;
pFx->m_flRodVelocitySmoothRate = pFeModel->m_flRodVelocitySmoothRate;
pFx->m_flAddWorldCollisionRadius = pFeModel->m_flAddWorldCollisionRadius;
pFx->m_nQuadVelocitySmoothIterations = pFeModel->m_nQuadVelocitySmoothIterations;
pFx->m_nRodVelocitySmoothIterations = pFeModel->m_nRodVelocitySmoothIterations;
pFx->m_flDefaultVolumetricSolveAmount = pFeModel->m_flDefaultVolumetricSolveAmount;
pFx->m_flWindage = pFeModel->m_flWindage;
pFx->m_flWindDrag = pFeModel->m_flWindDrag;
pFx->m_SimdQuads = CloneArray( pStream, pFeModel->m_pSimdQuads, pFeModel->m_nSimdQuadCount[ 0 ] );
pFx->m_SimdTris = CloneArray( pStream, pFeModel->m_pSimdTris, pFeModel->m_nSimdTriCount[ 0 ] );
pFx->m_SimdRods = CloneArray( pStream, pFeModel->m_pSimdRods, pFeModel->m_nSimdRodCount );
pFx->m_SimdNodeBases = CloneArray( pStream, pFeModel->m_pSimdNodeBases, pFeModel->m_nSimdNodeBaseCount );
pFx->m_SimdFitMatrices = CloneArray( pStream, pFeModel->m_pSimdFitMatrices, pFeModel->m_nSimdFitMatrixCount[ 0 ] );
pFx->m_FitMatrices = CloneArray( pStream, pFeModel->m_pFitMatrices, pFeModel->m_nFitMatrixCount[ 0 ] );
pFx->m_Quads = CloneArray( pStream, pFeModel->m_pQuads, pFeModel->m_nQuadCount[ 0 ] );
pFx->m_CtrlOffsets = CloneArray( pStream, pFeModel->m_pCtrlOffsets, pFeModel->m_nCtrlOffsets );
pFx->m_CtrlOsOffsets = CloneArray( pStream, pFeModel->m_pCtrlOsOffsets, pFeModel->m_nCtrlOsOffsets );
pFx->m_Rods = CloneArray( pStream, pFeModel->m_pRods, pFeModel->m_nRodCount );
pFx->m_AxialEdges = CloneArray( pStream, pFeModel->m_pAxialEdges, pFeModel->m_nAxialEdgeCount );
pFx->m_Ropes = CloneArray( pStream, pFeModel->m_pRopes, pFeModel->m_nRopeIndexCount );
pFx->m_NodeBases = CloneArray( pStream, pFeModel->m_pNodeBases, pFeModel->m_nNodeBaseCount );
pFx->m_SpringIntegrator = CloneArray( pStream, pFeModel->m_pSpringIntegrator, pFeModel->m_nSpringIntegratorCount );
pFx->m_SimdSpringIntegrator = CloneArray( pStream, pFeModel->m_pSimdSpringIntegrator, pFeModel->m_nSimdSpringIntegratorCount );
pFx->m_InitPose = CloneArray( pStream, pFeModel->m_pInitPose, pFeModel->m_nCtrlCount );
pFx->m_FollowNodes = CloneArray( pStream, pFeModel->m_pFollowNodes, pFeModel->m_nFollowNodeCount );
pFx->m_CollisionSpheres = CloneArray( pStream, pFeModel->m_pCollisionSpheres, pFeModel->m_nCollisionSpheres[ 0 ] );
pFx->m_CollisionPlanes = CloneArray( pStream, pFeModel->m_pCollisionPlanes, pFeModel->m_nCollisionPlanes );
pFx->m_NodeCollisionRadii = CloneArray( pStream, pFeModel->m_pNodeCollisionRadii, nDynamicNodes );
pFx->m_LocalRotation = CloneArray( pStream, pFeModel->m_pLocalRotation, nDynamicNodes );
pFx->m_LocalForce = CloneArray( pStream, pFeModel->m_pLocalForce, nDynamicNodes );
pFx->m_FitWeights = CloneArray( pStream, pFeModel->m_pFitWeights, pFeModel->m_nFitWeightCount );
pFx->m_nCollisionSphereInclusiveCount = pFeModel->m_nCollisionSpheres[ 1 ];
pFx->m_WorldCollisionParams = CloneArray( pStream, pFeModel->m_pWorldCollisionParams, pFeModel->m_nWorldCollisionParamCount );
pFx->m_TaperedCapsuleStretches = CloneArray( pStream, pFeModel->m_pTaperedCapsuleStretches, pFeModel->m_nTaperedCapsuleStretchCount );
pFx->m_TaperedCapsuleRigids = CloneArray( pStream, pFeModel->m_pTaperedCapsuleRigids, pFeModel->m_nTaperedCapsuleRigidCount );
pFx->m_SphereRigids = CloneArray( pStream, pFeModel->m_pSphereRigids, pFeModel->m_nSphereRigidCount );
pFx->m_TreeChildren = CloneArray( pStream, pFeModel->m_pTreeChildren, nDynamicNodes - 1 );
pFx->m_TreeParents = CloneArray( pStream, pFeModel->m_pTreeParents, nDynamicNodes + nDynamicNodes - 1 );
pFx->m_TreeCollisionMasks = CloneArray( pStream, pFeModel->m_pTreeCollisionMasks, nDynamicNodes + nDynamicNodes - 1 );
pFx->m_WorldCollisionNodes = CloneArray( pStream, pFeModel->m_pWorldCollisionNodes, pFeModel->m_nWorldCollisionNodeCount );
pFx->m_FreeNodes = CloneArray( pStream, pFeModel->m_pFreeNodes, pFeModel->m_nFreeNodeCount );
pFx->m_ReverseOffsets = CloneArray( pStream, pFeModel->m_pReverseOffsets, pFeModel->m_nReverseOffsetCount );
if ( pFeModel->m_pLegacyStretchForce )
{
pFx->m_LegacyStretchForce = CloneArray( pStream, pFeModel->m_pLegacyStretchForce, pFeModel->m_nNodeCount );
}
if ( pFeModel->m_pNodeIntegrator )
{
pFx->m_NodeIntegrator = CloneArray( pStream, pFeModel->m_pNodeIntegrator, pFeModel->m_nNodeCount );
}
pFx->m_NodeInvMasses = CloneArray( pStream, pFeModel->m_pNodeInvMasses, pFeModel->m_nNodeCount );
if ( pFeModel->m_pCtrlHash )
{
pFx->m_CtrlHash = CloneArray( pStream, pFeModel->m_pCtrlHash, pFeModel->m_nCtrlCount );
}
if ( pFeModel->m_pCtrlName )
{
pFx->m_CtrlName = pStream->Allocate< CResourceString >( pFeModel->m_nCtrlCount );
for ( uint i = 0; i < pFeModel->m_nCtrlCount; ++i )
{
pFx->m_CtrlName[ i ] = pStream->WriteString( pFeModel->m_pCtrlName[ i ] );
}
}
return pFx;
}
void Clone( const PhysFeModelDesc_t *pFeDesc, intp nOffsetBytes, char **pCtrlNames, CFeModel *pFeModel )
{
pFeModel->m_nDynamicNodeFlags = pFeDesc->m_nDynamicNodeFlags;
pFeModel->m_nStaticNodeFlags = pFeDesc->m_nStaticNodeFlags;
pFeModel->m_flLocalForce = pFeDesc->m_flLocalForce;
pFeModel->m_flLocalRotation = pFeDesc->m_flLocalRotation;
pFeModel->m_nAxialEdgeCount = pFeDesc->m_AxialEdges.Count();
pFeModel->m_nCtrlCount = pFeDesc->m_CtrlHash.Count();
pFeModel->m_nNodeCount = pFeDesc->m_nNodeCount;
pFeModel->m_nStaticNodes = pFeDesc->m_nStaticNodes;
pFeModel->m_nRotLockStaticNodes = pFeDesc->m_nRotLockStaticNodes;
AssertDbg( pFeModel->m_nRotLockStaticNodes <= pFeModel->m_nStaticNodes );
pFeModel->m_nTreeDepth = pFeDesc->m_nTreeDepth;
// no scalar data
pFeModel->m_nQuadCount[ 0 ] = 0;
pFeModel->m_nQuadCount[ 1 ] = 0;
pFeModel->m_nQuadCount[ 2 ] = 0;
pFeModel->m_nTriCount[ 0 ] = 0;
pFeModel->m_nTriCount[ 1 ] = 0;
pFeModel->m_nTriCount[ 2 ] = 0;
pFeModel->m_nSimdQuadCount[ 0 ] = pFeDesc->m_SimdQuads.Count();
pFeModel->m_nSimdQuadCount[ 1 ] = pFeDesc->m_nSimdQuadCount1;
pFeModel->m_nSimdQuadCount[ 2 ] = pFeDesc->m_nSimdQuadCount2;
pFeModel->m_nSimdTriCount[ 0 ] = pFeDesc->m_SimdTris.Count();
pFeModel->m_nSimdTriCount[ 1 ] = pFeDesc->m_nSimdTriCount1;
pFeModel->m_nSimdTriCount[ 2 ] = pFeDesc->m_nSimdTriCount2;
pFeModel->m_nQuadCount[ 0 ] = pFeDesc->m_Quads.Count();
pFeModel->m_nQuadCount[ 1 ] = pFeDesc->m_nQuadCount1;
pFeModel->m_nQuadCount[ 2 ] = pFeDesc->m_nQuadCount2;
pFeModel->m_nFitMatrixCount[ 0 ] = pFeDesc->m_FitMatrices.Count();
pFeModel->m_nFitMatrixCount[ 1 ] = pFeDesc->m_nFitMatrixCount1;
pFeModel->m_nFitMatrixCount[ 2 ] = pFeDesc->m_nFitMatrixCount2;
pFeModel->m_nSimdFitMatrixCount[ 0 ] = pFeDesc->m_SimdFitMatrices.Count();
pFeModel->m_nSimdFitMatrixCount[ 1 ] = pFeDesc->m_nSimdFitMatrixCount1;
pFeModel->m_nSimdFitMatrixCount[ 2 ] = pFeDesc->m_nSimdFitMatrixCount2;
pFeModel->m_flDefaultSurfaceStretch = pFeDesc->m_flDefaultSurfaceStretch;
pFeModel->m_flDefaultThreadStretch = pFeDesc->m_flDefaultThreadStretch;
pFeModel->m_flDefaultGravityScale = pFeDesc->m_flDefaultGravityScale;
pFeModel->m_flDefaultVelAirDrag = pFeDesc->m_flDefaultVelAirDrag;
pFeModel->m_flDefaultExpAirDrag = pFeDesc->m_flDefaultExpAirDrag;
pFeModel->m_flDefaultVelQuadAirDrag = pFeDesc->m_flDefaultVelQuadAirDrag;
pFeModel->m_flDefaultExpQuadAirDrag = pFeDesc->m_flDefaultExpQuadAirDrag;
pFeModel->m_flDefaultVelRodAirDrag = pFeDesc->m_flDefaultVelRodAirDrag;
pFeModel->m_flDefaultExpRodAirDrag = pFeDesc->m_flDefaultExpRodAirDrag;
pFeModel->m_flQuadVelocitySmoothRate = pFeDesc->m_flQuadVelocitySmoothRate;
pFeModel->m_flRodVelocitySmoothRate = pFeDesc->m_flRodVelocitySmoothRate;
pFeModel->m_nQuadVelocitySmoothIterations = pFeDesc->m_nQuadVelocitySmoothIterations;
pFeModel->m_nRodVelocitySmoothIterations = pFeDesc->m_nRodVelocitySmoothIterations;
pFeModel->m_flAddWorldCollisionRadius = pFeDesc->m_flAddWorldCollisionRadius;
pFeModel->m_flDefaultVolumetricSolveAmount = pFeDesc->m_flDefaultVolumetricSolveAmount;
pFeModel->m_nFitWeightCount = pFeDesc->m_FitWeights.Count();
pFeModel->m_nReverseOffsetCount = pFeDesc->m_ReverseOffsets.Count();
pFeModel->m_flWindage = pFeDesc->m_flWindage;
pFeModel->m_flWindDrag = pFeDesc->m_flWindDrag;
pFeModel->m_nRodCount = pFeDesc->m_Rods.Count();
pFeModel->m_nSimdRodCount = pFeDesc->m_SimdRods.Count();
pFeModel->m_nFollowNodeCount = pFeDesc->m_FollowNodes.Count();
pFeModel->m_nCtrlOffsets = pFeDesc->m_CtrlOffsets.Count();
pFeModel->m_nCtrlOsOffsets = pFeDesc->m_CtrlOsOffsets.Count();
pFeModel->m_nSpringIntegratorCount = pFeDesc->m_SpringIntegrator.Count();
pFeModel->m_nSimdSpringIntegratorCount = pFeDesc->m_SimdSpringIntegrator.Count();
pFeModel->m_nWorldCollisionParamCount = pFeDesc->m_WorldCollisionParams.Count();
pFeModel->m_nWorldCollisionNodeCount = pFeDesc->m_WorldCollisionNodes.Count();
pFeModel->m_nFreeNodeCount = pFeDesc->m_FreeNodes.Count();
pFeModel->m_nTaperedCapsuleStretchCount = pFeDesc->m_TaperedCapsuleStretches.Count();
pFeModel->m_nTaperedCapsuleRigidCount = pFeDesc->m_TaperedCapsuleRigids.Count();
pFeModel->m_nSphereRigidCount = pFeDesc->m_SphereRigids.Count();
pFeModel->m_pSimdQuads = ConstCastOffsetPointer( pFeDesc->m_SimdQuads.Base(), nOffsetBytes );
pFeModel->m_pQuads = ConstCastOffsetPointer( pFeDesc->m_Quads.Base(), nOffsetBytes );
pFeModel->m_pSimdTris = ConstCastOffsetPointer( pFeDesc->m_SimdTris.Base(), nOffsetBytes );
pFeModel->m_pTris = NULL;
pFeModel->m_pRods = ConstCastOffsetPointer( pFeDesc->m_Rods.Base(), nOffsetBytes );;
pFeModel->m_pSimdRods = ConstCastOffsetPointer( pFeDesc->m_SimdRods.Base(), nOffsetBytes );
pFeModel->m_pAxialEdges = ConstCastOffsetPointer( pFeDesc->m_AxialEdges.Base(), nOffsetBytes );
pFeModel->m_pNodeToCtrl = NULL;
pFeModel->m_pCtrlToNode = NULL;
pFeModel->m_pCtrlHash = ConstCastOffsetPointer( pFeDesc->m_CtrlHash.Base(), nOffsetBytes );
pFeModel->m_pRopes = ConstCastOffsetPointer( pFeDesc->m_Ropes.Base(), nOffsetBytes );
pFeModel->m_pNodeBases = ConstCastOffsetPointer( pFeDesc->m_NodeBases.Base(), nOffsetBytes );
pFeModel->m_pSimdNodeBases = ConstCastOffsetPointer( pFeDesc->m_SimdNodeBases.Base(), nOffsetBytes );
pFeModel->m_pNodeIntegrator = ConstCastOffsetPointer( pFeDesc->m_NodeIntegrator.Base(), nOffsetBytes );
pFeModel->m_pSpringIntegrator = ConstCastOffsetPointer( pFeDesc->m_SpringIntegrator.Base(), nOffsetBytes );
pFeModel->m_pSimdSpringIntegrator = ConstCastOffsetPointer( pFeDesc->m_SimdSpringIntegrator.Base(), nOffsetBytes );
pFeModel->m_pCtrlOffsets = ConstCastOffsetPointer( pFeDesc->m_CtrlOffsets.Base(), nOffsetBytes );
pFeModel->m_pCtrlOsOffsets = ConstCastOffsetPointer( pFeDesc->m_CtrlOsOffsets.Base(), nOffsetBytes );
pFeModel->m_pFollowNodes = ConstCastOffsetPointer( pFeDesc->m_FollowNodes.Base(), nOffsetBytes );
pFeModel->m_pNodeCollisionRadii = ConstCastOffsetPointer( pFeDesc->m_NodeCollisionRadii.Base(), nOffsetBytes );
pFeModel->m_pLocalRotation = ConstCastOffsetPointer( pFeDesc->m_LocalRotation.Base(), nOffsetBytes );
pFeModel->m_pLocalForce = ConstCastOffsetPointer( pFeDesc->m_LocalForce.Base(), nOffsetBytes );
pFeModel->m_pCollisionSpheres = ConstCastOffsetPointer( pFeDesc->m_CollisionSpheres.Base(), nOffsetBytes );
pFeModel->m_pCollisionPlanes = ConstCastOffsetPointer( pFeDesc->m_CollisionPlanes.Base(), nOffsetBytes );
pFeModel->m_pWorldCollisionNodes = ConstCastOffsetPointer( pFeDesc->m_WorldCollisionNodes.Base(), nOffsetBytes );
pFeModel->m_pWorldCollisionParams = ConstCastOffsetPointer( pFeDesc->m_WorldCollisionParams.Base(), nOffsetBytes );
pFeModel->m_pLegacyStretchForce = ConstCastOffsetPointer( pFeDesc->m_LegacyStretchForce.Base(), nOffsetBytes );
pFeModel->m_pTaperedCapsuleStretches = ConstCastOffsetPointer( pFeDesc->m_TaperedCapsuleStretches.Base(), nOffsetBytes );
pFeModel->m_pTaperedCapsuleRigids = ConstCastOffsetPointer( pFeDesc->m_TaperedCapsuleRigids.Base(), nOffsetBytes );
pFeModel->m_pSphereRigids = ConstCastOffsetPointer( pFeDesc->m_SphereRigids.Base(), nOffsetBytes );
pFeModel->m_pFreeNodes = ConstCastOffsetPointer( pFeDesc->m_FreeNodes.Base(), nOffsetBytes );
pFeModel->m_pFitMatrices = ConstCastOffsetPointer( pFeDesc->m_FitMatrices.Base(), nOffsetBytes );
pFeModel->m_pSimdFitMatrices = ConstCastOffsetPointer( pFeDesc->m_SimdFitMatrices.Base(), nOffsetBytes );
pFeModel->m_pFitWeights = ConstCastOffsetPointer( pFeDesc->m_FitWeights.Base(), nOffsetBytes );
pFeModel->m_pReverseOffsets = ConstCastOffsetPointer( pFeDesc->m_ReverseOffsets.Base(), nOffsetBytes );
AssertDbg( pFeModel->m_pWorldCollisionParams ? pFeModel->m_pWorldCollisionParams[ pFeModel->m_nWorldCollisionParamCount - 1 ].nListEnd == pFeModel->m_nWorldCollisionNodeCount : !pFeModel->m_pWorldCollisionNodes && !pFeModel->m_nWorldCollisionParamCount && !pFeModel->m_nWorldCollisionNodeCount );
pFeModel->m_nRopeCount = pFeDesc->m_nRopeCount;
pFeModel->m_nRopeIndexCount = pFeDesc->m_Ropes.Count();
pFeModel->m_nNodeBaseCount = pFeDesc->m_NodeBases.Count();
pFeModel->m_nSimdNodeBaseCount = pFeDesc->m_SimdNodeBases.Count();
pFeModel->m_nCollisionSpheres[ 0 ] = pFeDesc->m_CollisionSpheres.Count();
pFeModel->m_nCollisionSpheres[ 1 ] = pFeDesc->m_nCollisionSphereInclusiveCount;
pFeModel->m_nCollisionPlanes = pFeDesc->m_CollisionPlanes.Count();
Assert( pFeDesc->m_TreeChildren.Count() == 0 || pFeDesc->m_TreeChildren.Count() == ( int )pFeDesc->GetDynamicNodeCount() - 1 );
pFeModel->m_pTreeChildren = ConstCastOffsetPointer( pFeDesc->m_TreeChildren.Base(), nOffsetBytes );
Assert( pFeDesc->m_TreeParents.Count() == 0 || pFeDesc->m_TreeParents.Count() == 2 * ( int )pFeDesc->GetDynamicNodeCount() - 1 );
pFeModel->m_pTreeParents = ConstCastOffsetPointer( pFeDesc->m_TreeParents.Base(), nOffsetBytes );
Assert( pFeDesc->m_TreeParents.Count() == pFeDesc->m_TreeCollisionMasks.Count() );
pFeModel->m_pTreeCollisionMasks = ConstCastOffsetPointer( pFeDesc->m_TreeCollisionMasks.Base(), nOffsetBytes );
Assert( pFeDesc->m_NodeInvMasses.Count() == 0 || pFeDesc->m_NodeInvMasses.Count() == pFeDesc->m_nNodeCount );
pFeModel->m_pNodeInvMasses = pFeDesc->m_NodeInvMasses.Count() ? ConstCastOffsetPointer( pFeDesc->m_NodeInvMasses.Base(), nOffsetBytes ) : NULL;
if ( pFeDesc->m_CtrlName.IsEmpty() || !pCtrlNames )
{
pFeModel->m_pCtrlName = NULL;
}
else
{
pFeModel->m_pCtrlName = const_cast< const char ** >( pCtrlNames ); //ConstCastOffsetPointer( pFeDesc->m_CtrlName.Base( ), nOffsetBytes );
for ( int i = 0; i < pFeModel->m_nCtrlCount; ++i )
{
const CResourceString &name = pFeDesc->m_CtrlName[ i ];
if ( name.IsNull() )
{
pFeModel->m_pCtrlName[ i ] = "";
}
else
{
pFeModel->m_pCtrlName[ i ] = ConstCastOffsetPointer( name.GetPtr(), nOffsetBytes );
}
}
}
AssertDbg( pFeDesc->m_InitPose.Count() == pFeModel->m_nCtrlCount );
pFeModel->m_pInitPose = ConstCastOffsetPointer( pFeDesc->m_InitPose.Base(), nOffsetBytes );
}
void SetIdentityPerm( CUtlVector< uint > &perm, uint nCount )
{
perm.SetCount( nCount );
for ( uint i = 0; i < nCount; ++i )
perm[ i ] = i;
}
struct CtrlHashFunctor_t
{
const CFeModel *m_pFeModel;
CtrlHashFunctor_t( const CFeModel *pFeModel ) : m_pFeModel( pFeModel ){}
bool operator( )( int nLeft, int nRight ) const
{
return m_pFeModel->m_pCtrlHash[ nLeft ] < m_pFeModel->m_pCtrlHash[ nRight ];
}
};
CFeModelReplaceContext::CFeModelReplaceContext( const CFeModel *pOld, const CFeModel *pNew )
{
m_pOld = pOld;
m_pNew = pNew;
m_OldToNewNode.SetCount( pOld->m_nNodeCount ); m_OldToNewNode.FillWithValue( -1 );
m_OldToNewCtrl.SetCount( pOld->m_nCtrlCount ); m_OldToNewCtrl.FillWithValue( -1 );
m_NewToOldNode.SetCount( pNew->m_nNodeCount ); m_NewToOldNode.FillWithValue( -1 );
m_NewToOldCtrl.SetCount( pNew->m_nCtrlCount ); m_NewToOldCtrl.FillWithValue( -1 );
CUtlVector< uint > oldCtrlIndex, newCtrlIndex;
SetIdentityPerm( oldCtrlIndex, pOld->m_nCtrlCount );
SetIdentityPerm( newCtrlIndex, pNew->m_nCtrlCount );
HeapSort( oldCtrlIndex, CtrlHashFunctor_t( pOld ) );
HeapSort( newCtrlIndex, CtrlHashFunctor_t( pNew ) );
for ( uint nOld = 0, nNew = 0; nOld < pOld->m_nCtrlCount && nNew < pNew->m_nCtrlCount; )
{
uint nOldCtrl = oldCtrlIndex[ nOld ], nNewCtrl = newCtrlIndex[ nNew ];
uint nOldCtrlHash = pOld->m_pCtrlHash[ nOldCtrl ], nNewCtrlHash = pNew->m_pCtrlHash[ nNewCtrl ];
if ( nOldCtrlHash == nNewCtrlHash )
{
// we found a match!
m_OldToNewCtrl[ nOldCtrl ] = nNewCtrl;
m_NewToOldCtrl[ nNewCtrl ] = nOldCtrl;
uint nOldNode = pOld->CtrlToNode( nOldCtrl );
uint nNewNode = pNew->CtrlToNode( nNewCtrl );
if ( nOldNode < pOld->m_nNodeCount && nNewNode < pNew->m_nNodeCount )
{
// there's a match in nodes
m_NewToOldNode[ nNewNode ] = nOldNode;
m_OldToNewNode[ nOldNode ] = nNewNode;
}
nOld++;
nNew++;
}
else if ( nOldCtrlHash < nNewCtrlHash )
{
AssertDbg( m_OldToNewCtrl[ nOldCtrl ] == -1 );
nOld++;
}
else
{
AssertDbg( m_NewToOldCtrl[ nNewCtrl ] == -1 );
nNew++;
}
}
}