|
|
//====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
//
// Dme version of a skeletal model (gets compiled into a MDL)
//
//=============================================================================
#include "movieobjects/dmemodel.h"
#include "movieobjects_interfaces.h"
#include "datamodel/dmelementfactoryhelper.h"
#include "datacache/imdlcache.h"
#include "materialsystem/imaterialsystem.h"
#include "tier2/tier2.h"
#include "studio.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "movieobjects/dmemesh.h"
#include "movieobjects/dmechannel.h"
#include "movieobjects/dmelog.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeModel, CDmeModel );
//-----------------------------------------------------------------------------
// Stack of DmeModels currently being rendered. Used to set up render state
//-----------------------------------------------------------------------------
CUtlStack< CDmeModel * > CDmeModel::s_ModelStack; static CUtlVector< matrix3x4_t > s_PoseToWorld;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDmeModel::OnConstruction() { m_JointList.Init( this, "jointList" ); m_BaseStates.Init( this, "baseStates" ); m_UpAxis.InitAndSet( this, "upAxis", "Y" ); m_eAxisSystem.InitAndCreate( this, "axisSystem" ); // Defaults to Y up
}
void CDmeModel::OnDestruction() { }
//-----------------------------------------------------------------------------
// Add joint
//-----------------------------------------------------------------------------
int CDmeModel::AddJoint( CDmeDag *pJoint ) { const int nIndex = GetJointIndex( pJoint ); if ( nIndex >= 0 ) return nIndex;
return m_JointList.AddToTail( pJoint ); }
//-----------------------------------------------------------------------------
// Add joint
//-----------------------------------------------------------------------------
CDmeJoint *CDmeModel::AddJoint( const char *pJointName, CDmeDag *pParent ) { CDmeJoint *pJoint = CreateElement< CDmeJoint >( pJointName, GetFileId() ); CDmeTransform *pTransform = pJoint->GetTransform(); pTransform->SetName( pJointName );
if ( !pParent ) { pParent = this; } pParent->AddChild( pJoint ); m_JointList.AddToTail( pJoint );
return pJoint; }
//-----------------------------------------------------------------------------
// Returns the number of joint transforms we know about
//-----------------------------------------------------------------------------
int CDmeModel::GetJointCount() const { return m_JointList.Count(); }
//-----------------------------------------------------------------------------
// Determines joint transform index given a joint transform
//-----------------------------------------------------------------------------
int CDmeModel::GetJointIndex( CDmeDag *pJoint ) const { const int nJointCount = m_JointList.Count(); for ( int i = 0; i < nJointCount; ++i ) { if ( pJoint == m_JointList[ i ] ) { return i; } }
return -1; }
//-----------------------------------------------------------------------------
// Determines joint transform index given a joint name
//-----------------------------------------------------------------------------
int CDmeModel::GetJointIndex( const char *pJointName ) const { const int nJointCount = m_JointList.Count(); for ( int i = 0; i < nJointCount; ++i ) { if ( !V_strcmp( pJointName, m_JointList[ i ]->GetName() ) ) { return i; } }
return -1; }
//-----------------------------------------------------------------------------
// Determines joint transform index given a joint name hash
//-----------------------------------------------------------------------------
int CDmeModel::GetJointIndex( CUtlStringToken nJointNameHash ) const { const int nJointCount = m_JointList.Count(); for ( int i = 0; i < nJointCount; ++i ) { if ( MakeStringToken( m_JointList[ i ]->GetName() ) == nJointNameHash ) { return i; } }
return -1; }
//-----------------------------------------------------------------------------
// Returns the DmeDag for the specified joint index
//-----------------------------------------------------------------------------
CDmeDag *CDmeModel::GetJoint( int nIndex ) { return m_JointList[ nIndex ]; }
const CDmeDag *CDmeModel::GetJoint( int nIndex ) const { return m_JointList[ nIndex ]; }
//-----------------------------------------------------------------------------
// Determines joint transform index given a joint name
//-----------------------------------------------------------------------------
CDmeTransform *CDmeModel::GetJointTransform( int nIndex ) { return m_JointList[ nIndex ]->GetTransform(); }
const CDmeTransform *CDmeModel::GetJointTransform( int nIndex ) const { return m_JointList[ nIndex ]->GetTransform(); }
//-----------------------------------------------------------------------------
// Finds a base state by name, returns NULL if not found
//-----------------------------------------------------------------------------
CDmeTransformList *CDmeModel::FindBaseState( const char *pBaseStateName ) { int nCount = m_BaseStates.Count(); for ( int i = 0; i < nCount; ++i ) { if ( !V_stricmp( m_BaseStates[i]->GetName(), pBaseStateName ) ) return m_BaseStates[i]; } return NULL; }
//-----------------------------------------------------------------------------
// Captures the current joint transforms into a base state
//-----------------------------------------------------------------------------
void CDmeModel::CaptureJointsToBaseState( const char *pBaseStateName ) { CDmeTransformList *pTransformList = FindBaseState( pBaseStateName ); if ( !pTransformList ) { pTransformList = CreateElement<CDmeTransformList>( pBaseStateName, GetFileId() ); m_BaseStates.AddToTail( pTransformList ); }
// Make the transform list have the correct number of elements
const int nJointCount = m_JointList.Count(); const int nCurrentCount = pTransformList->GetTransformCount(); if ( nJointCount > nCurrentCount ) { for ( int i = nCurrentCount; i < nJointCount; ++i ) { CDmeTransform *pTransform = CreateElement<CDmeTransform>( m_JointList[i]->GetName(), pTransformList->GetFileId() ); pTransformList->m_Transforms.AddToTail( pTransform ); } } else if ( nJointCount < nCurrentCount ) { pTransformList->m_Transforms.RemoveMultiple( nJointCount, nCurrentCount - nJointCount ); }
// Copy the state over
for ( int i = 0; i < nJointCount; ++i ) { matrix3x4_t mat;
CDmeDag *pDmeDag = m_JointList[i]; if ( !pDmeDag ) { char szTmpBuf0[ 38 ]; UniqueIdToString( GetId(), szTmpBuf0, ARRAYSIZE( szTmpBuf0 ) ); Warning( "DmeModel::CaptureJointsToBaseState( %s ): DmeModel %s[%s].jointList[ %d ] is NULL\n", pBaseStateName, GetName(), szTmpBuf0, i ); continue; }
CDmeTransform *pDmeTransform = pDmeDag->GetTransform(); if ( !pDmeTransform ) { char szTmpBuf0[ 38 ]; UniqueIdToString( GetId(), szTmpBuf0, ARRAYSIZE( szTmpBuf0 ) ); char szTmpBuf1[ 38 ]; UniqueIdToString( pDmeDag->GetId(), szTmpBuf1, ARRAYSIZE( szTmpBuf1 ) ); Warning( "DmeModel::CaptureJointsToBaseState( %s ) - DmeModel %s[%s].jointList[ %d ].transform ( %s[%s].transform ) is NULL\n", pBaseStateName, GetName(), szTmpBuf0, i, pDmeDag->GetName(), szTmpBuf1 ); continue; }
pDmeTransform->GetTransform( mat ); pTransformList->SetTransform( i, mat ); } }
//-----------------------------------------------------------------------------
// Sets the joint transforms to the values in the specified base state, if it exists
//-----------------------------------------------------------------------------
void CDmeModel::PushBaseStateToJoints( const char *pBaseStateName ) { CDmeTransformList *pTransformList = FindBaseState( pBaseStateName ); if ( !pTransformList ) return;
for ( int ii = 0; ii < pTransformList->GetTransformCount(); ++ii ) { CDmeTransform *pSrcDmeTransform = pTransformList->GetTransform( ii ); CDmeDag *pDmeJoint = GetJoint( ii );
if ( !pSrcDmeTransform || !pDmeJoint ) continue;
CDmeTransform *pDstDmeTransform = pDmeJoint->GetTransform(); if ( !pDstDmeTransform ) continue;
pDstDmeTransform->SetPosition( pSrcDmeTransform->GetPosition() ); pDstDmeTransform->SetOrientation( pSrcDmeTransform->GetOrientation() ); } }
//-----------------------------------------------------------------------------
// Loads up joint transforms for this model
//-----------------------------------------------------------------------------
void CDmeModel::LoadJointTransform( CDmeDag *pJoint, CDmeTransformList *pBindPose, const matrix3x4_t &parentToWorld, const matrix3x4_t &parentToBindPose, bool bSetHardwareState ) { // Determines joint transform index; no index, no traversing lower in the hierarchy
const int nJointIndex = GetJointIndex( pJoint ); if ( nJointIndex < 0 ) return;
// FIXME: Sucky search here necessary to find bone matrix index
matrix3x4_t jointToWorld, jointToParent; pJoint->GetTransform()->GetTransform( jointToParent ); ConcatTransforms( parentToWorld, jointToParent, jointToWorld );
matrix3x4_t bindJointToParent, bindPoseToJoint, bindPoseToWorld, jointToBindPose; if ( pBindPose ) { if ( nJointIndex >= pBindPose->GetTransformCount() ) { Warning( "Model is in an invalid state! There are different numbers of bones in the bind pose and joint transform list!\n" ); return; } pBindPose->GetTransform( nJointIndex )->GetTransform( bindJointToParent ); } else { MatrixCopy( jointToParent, bindJointToParent ); } ConcatTransforms( parentToBindPose, bindJointToParent, jointToBindPose );
MatrixInvert( jointToBindPose, bindPoseToJoint ); ConcatTransforms( jointToWorld, bindPoseToJoint, bindPoseToWorld );
if ( bSetHardwareState ) { CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); pRenderContext->LoadBoneMatrix( nJointIndex, bindPoseToWorld ); } MatrixCopy( bindPoseToWorld, s_PoseToWorld[ nJointIndex ] );
int nChildCount = pJoint->GetChildCount(); for ( int i = 0; i < nChildCount; ++i ) { CDmeDag *pChildJoint = pJoint->GetChild(i); if ( !pChildJoint ) continue;
LoadJointTransform( pChildJoint, pBindPose, jointToWorld, jointToBindPose, bSetHardwareState ); } }
//-----------------------------------------------------------------------------
// Sets up the render state for the model
//-----------------------------------------------------------------------------
CDmeModel::SetupBoneRetval_t CDmeModel::SetupBoneMatrixState( const matrix3x4_t& shapeToWorld, bool bForceSoftwareSkin ) { const int nJointCount = m_JointList.Count(); if ( nJointCount <= 0 ) return NO_SKIN_DATA;
int nBoneBatchCount = g_pMaterialSystemHardwareConfig->MaxVertexShaderBlendMatrices(); bool bSetHardwareState = ( nJointCount <= nBoneBatchCount ) && !bForceSoftwareSkin;
s_PoseToWorld.EnsureCount( nJointCount );
// Finds a base state by name, returns NULL if not found
CDmeTransformList *pBindPose = FindBaseState( "bind" );
matrix3x4_t parentToBindPose; SetIdentityMatrix( parentToBindPose );
int nChildCount = GetChildCount(); for ( int i = 0; i < nChildCount; ++i ) { CDmeDag *pChildJoint = GetChild(i); if ( !pChildJoint ) continue;
LoadJointTransform( pChildJoint, pBindPose, shapeToWorld, parentToBindPose, bSetHardwareState ); }
return bSetHardwareState ? BONES_SET_UP : TOO_MANY_BONES; }
matrix3x4_t *CDmeModel::SetupModelRenderState( const matrix3x4_t& shapeToWorld, bool bHasSkinningData, bool bForceSoftwareSkin ) { CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); if ( bHasSkinningData && ( s_ModelStack.Count() > 0 ) ) { SetupBoneRetval_t retVal = s_ModelStack.Top()->SetupBoneMatrixState( shapeToWorld, bForceSoftwareSkin ); if ( retVal == TOO_MANY_BONES ) { pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->LoadIdentity( ); return s_PoseToWorld.Base(); } if ( retVal != NO_SKIN_DATA ) return NULL; }
if ( bForceSoftwareSkin ) { pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->LoadIdentity( ); s_PoseToWorld.EnsureCount( 1 ); MatrixCopy( shapeToWorld, s_PoseToWorld[0] ); return s_PoseToWorld.Base(); }
pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->LoadMatrix( shapeToWorld ); return NULL; }
void CDmeModel::CleanupModelRenderState() { CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->LoadIdentity(); }
//-----------------------------------------------------------------------------
// Recursively render the Dag hierarchy
//-----------------------------------------------------------------------------
void CDmeModel::Draw( CDmeDrawSettings *pDrawSettings /* = NULL */ ) { s_ModelStack.Push( this ); BaseClass::Draw( pDrawSettings ); s_ModelStack.Pop( ); }
//-----------------------------------------------------------------------------
// Set if Z is the up axis of the model
//-----------------------------------------------------------------------------
void CDmeModel::ZUp( bool bZUp ) { if ( bZUp ) { // Z up is technically ambiguous, but only Maya created SMD Z Up files, everything else assumes Z up is Valve engine Z up
SetAxisSystem( CDmeAxisSystem::AS_VALVE_ENGINE ); } else { SetAxisSystem( CDmeAxisSystem::AS_MAYA_YUP ); } }
//-----------------------------------------------------------------------------
// Returns the matrix that moves DmeModel data to engine space
//-----------------------------------------------------------------------------
void CDmeModel::GetModelToEngineMat( matrix3x4_t &modelToEngineMat ) { CDmeDag::DmeToEngineMatrix( modelToEngineMat, IsZUp() ); }
//-----------------------------------------------------------------------------
// Returns the matrix that moves engine data to DmeModel space
//-----------------------------------------------------------------------------
void CDmeModel::GetEngineToModelMat( matrix3x4_t &engineToModelMat ) { CDmeDag::EngineToDmeMatrix( engineToModelMat, IsZUp() ); }
//-----------------------------------------------------------------------------
// Returns true if the data under the DmeModel is AS_VALVE_ENGINE_SPACE ( Up: Z, Fwd: X, Left: Y )
// Returns false otherwise, NOTE: false doesn't imply any other axis system, examine m_eAxisSystem to see
//-----------------------------------------------------------------------------
bool CDmeModel::IsZUp() const { Assert( m_eAxisSystem.GetElement() );
if ( m_eAxisSystem.GetElement()->IsEqual( CDmeAxisSystem::AS_VALVE_ENGINE ) ) return true;
if ( m_eAxisSystem.GetElement()->IsEqual( CDmeAxisSystem::AS_MAYA_YUP ) ) return false;
AssertMsg( false, "CDmeModel::IsZUp() called, but axis system is neither AS_VALVE_ENGINE or AS_MAYA_YUP, cannot represent via true/false, ambiguous state" );
return false; }
//-----------------------------------------------------------------------------
// Replace all instances of a material with a different material
//-----------------------------------------------------------------------------
void CDmeModel::ReplaceMaterial( CDmeDag *pDag, const char *pOldMaterialName, const char *pNewMaterialName ) { if ( !pDag ) return;
CDmeMesh *pMesh = CastElement< CDmeMesh >( pDag->GetShape() ); if ( pMesh ) { pMesh->ReplaceMaterial( pOldMaterialName, pNewMaterialName ); }
int nCount = pDag->GetChildCount(); for ( int i = 0; i < nCount; ++i ) { CDmeDag *pChild = pDag->GetChild( i ); ReplaceMaterial( pChild, pOldMaterialName, pNewMaterialName ); } }
void CDmeModel::ReplaceMaterial( const char *pOldMaterialName, const char *pNewMaterialName ) { ReplaceMaterial( this, pOldMaterialName, pNewMaterialName ); }
//-----------------------------------------------------------------------------
// Gets the joint with the specified name
//-----------------------------------------------------------------------------
CDmeDag *CDmeModel::GetJoint( const char *pJointName ) { CDmeDag *pJoint = NULL;
const int nJointCount = m_JointList.Count(); for ( int i = 0; i < nJointCount; ++i ) { pJoint = m_JointList[ i ]; if ( !pJoint ) continue;
if ( !V_stricmp( pJointName, pJoint->GetName() ) ) return pJoint; }
return NULL; }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeModel::ReskinMeshes( const int *pJointTransformIndexRemap ) { ReskinMeshes( this, pJointTransformIndexRemap ); }
//-----------------------------------------------------------------------------
// Reskin meshes based on bone collapse
//-----------------------------------------------------------------------------
void CDmeModel::ReskinMeshes( CDmeDag *pDag, const int *pJointTransformIndexRemap ) { if ( !pDag ) return;
CDmeMesh *pMesh = CastElement< CDmeMesh >( pDag->GetShape() ); if ( pMesh ) { pMesh->Reskin( pJointTransformIndexRemap ); }
int nCount = pDag->GetChildCount(); for ( int i = 0; i < nCount; ++i ) { CDmeDag *pChild = pDag->GetChild( i ); ReskinMeshes( pChild, pJointTransformIndexRemap ); } }
//-----------------------------------------------------------------------------
// Remove joints
//-----------------------------------------------------------------------------
void CDmeModel::RemoveJoints( int nNewJointCount, const int *pInvJointRemap ) { const int nOldJointTransformCount = m_JointList.Count();
const int nSizeInBytes = nNewJointCount * sizeof(CDmeTransform*); CDmeDag **ppJoints = (CDmeDag**)stackalloc( nSizeInBytes ); for ( int i = 0; i < nNewJointCount; ++i ) { ppJoints[i] = m_JointList[ pInvJointRemap[i] ]; }
m_JointList.RemoveAll(); for ( int i = 0; i < nNewJointCount; ++i ) { m_JointList.AddToTail( ppJoints[i] ); }
CUtlVectorFixedGrowable< CDmeTransform*, 256 > transforms;
const int nCount = m_BaseStates.Count(); for ( int i = 0; i < nCount; ++i ) { CDmeTransformList *pList = m_BaseStates[i]; int nTransformCount = pList->GetTransformCount(); transforms.SetCount( nTransformCount ); int nStateJointCount = nNewJointCount; for ( int j = 0; j < nNewJointCount; ++j ) { transforms[j] = pList->GetTransform( pInvJointRemap[j] ); } for ( int j = nOldJointTransformCount; j < nTransformCount; ++j ) { transforms[ nStateJointCount++ ] = pList->GetTransform( j ); }
pList->m_Transforms.RemoveAll(); for ( int j = 0; j < nStateJointCount; ++j ) { pList->m_Transforms.AddToTail( transforms[ j ] ); } } }
//-----------------------------------------------------------------------------
// Updates all base states by adding missing joints
//-----------------------------------------------------------------------------
void CDmeModel::UpdateBaseStates() { const int nJointCount = m_JointList.Count();
for ( int i = 0; i < m_BaseStates.Count(); ++i ) { CDmeTransformList *pTransformList = m_BaseStates[i]; if ( !pTransformList ) continue;
// Make the transform list have the correct number of elements
const int nCurrentCount = pTransformList->GetTransformCount();
if ( nJointCount < nCurrentCount ) { pTransformList->m_Transforms.RemoveMultiple( nJointCount, nCurrentCount - nJointCount ); return; } else if ( nJointCount == nCurrentCount ) { return; }
Assert( nJointCount > nCurrentCount );
for ( int i = nCurrentCount; i < nJointCount; ++i ) { CDmeTransform *pTransform = CreateElement<CDmeTransform>( m_JointList[i]->GetName(), pTransformList->GetFileId() ); pTransformList->m_Transforms.AddToTail( pTransform );
matrix3x4_t mat; CDmeDag *pDmeDag = m_JointList[i]; if ( !pDmeDag ) continue;
CDmeTransform *pDmeTransform = pDmeDag->GetTransform(); if ( !pDmeTransform ) continue;
pDmeTransform->GetTransform( mat ); pTransformList->SetTransform( i, mat ); } } }
//-----------------------------------------------------------------------------
// Removes all children from this joint, moving shapes to be
//-----------------------------------------------------------------------------
void CDmeModel::RemoveAllChildren( CDmeDag *pDag, CDmeDag *pSubtreeRoot, const matrix3x4_t &jointToSubtreeRoot ) { if ( !pDag ) return;
CDmeTransform *pDagTransform = pDag->GetTransform(); matrix3x4_t curToSubtreeRoot, dagToParent; pDagTransform->GetTransform( dagToParent ); ConcatTransforms( jointToSubtreeRoot, dagToParent, curToSubtreeRoot );
if ( !CastElement< CDmeJoint >( pDag ) ) { pSubtreeRoot->AddChild( pDag ); pDagTransform->SetTransform( curToSubtreeRoot ); }
int nCount = pDag->GetChildCount(); for ( int i = 0; i < nCount; ++i ) { RemoveAllChildren( pDag->GetChild(i), pSubtreeRoot, curToSubtreeRoot ); }
pDag->RemoveAllChildren(); }
void CDmeModel::RemoveAllChildren( CDmeDag *pSubtreeRoot ) { matrix3x4_t root; SetIdentityMatrix( root );
int nCount = pSubtreeRoot->GetChildCount(); for ( int i = 0; i < nCount; ++i ) { CDmeDag *pChild = pSubtreeRoot->GetChild(i); if ( !CastElement< CDmeJoint >( pChild ) ) continue; RemoveAllChildren( pChild, pSubtreeRoot, root ); }
// Regetting the child count, as it has changed from the RemoveAllChildren calls
nCount = pSubtreeRoot->GetChildCount(); for ( int i = nCount; --i >= 0; ) { if ( !CastElement< CDmeJoint >( pSubtreeRoot->GetChild(i) ) ) continue;
pSubtreeRoot->RemoveChild( i ); } }
//-----------------------------------------------------------------------------
// Collapses all joints below the specified joint name, reskinning any meshes
// referring to collapsed joints to use the specified joint instead
//-----------------------------------------------------------------------------
void CDmeModel::CollapseJoints( const char *pJointName ) { CDmeDag *pJoint = GetJoint( pJointName ); if ( !pJoint ) return;
// Determine which joints must be collapsed
CDmeDag *pParent; const int nCount = m_JointList.Count(); bool *pIsCollapsed = (bool*)stackalloc( nCount * sizeof(bool) ); for ( int i = 0; i < nCount; ++i ) { CDmeDag *pTestJoint = m_JointList[ i ]; if ( !pTestJoint ) continue;
pIsCollapsed[i] = ( pJoint->FindChild( pParent, pTestJoint ) >= 0 ); }
// Build remap indices
int nNewJointCount = 0; int nCollapseJointIndex = 0; int* pJointRemap = (int*)stackalloc( nCount * sizeof(int) ); int* pInvJointRemap = (int*)stackalloc( nCount * sizeof(int) ); for ( int i = 0; i < nCount; ++i ) { if ( pIsCollapsed[i] ) { pJointRemap[i] = -1; continue; }
if ( pJoint == m_JointList[i] ) { nCollapseJointIndex = nNewJointCount; } pInvJointRemap[nNewJointCount] = i; pJointRemap[i] = nNewJointCount++; }
for ( int i = 0; i < nCount; ++i ) { if ( pJointRemap[i] < 0 ) { pJointRemap[i] = nCollapseJointIndex; } }
// Reskin meshes
ReskinMeshes( this, pJointRemap );
// Fixup joint transform + base state lists
RemoveJoints( nNewJointCount, pInvJointRemap );
// Remove all children from this node
RemoveAllChildren( pJoint );
stackfree( pIsCollapsed ); stackfree( pJointRemap ); stackfree( pInvJointRemap ); }
//-----------------------------------------------------------------------------
// Returns the matrix & quaternion to reorient
//-----------------------------------------------------------------------------
void CDmeModel::GetReorientData( matrix3x4_t &m, Quaternion &q, bool bMakeZUp ) { // YUP_ACTIVE: FIXME
if ( bMakeZUp ) { static const matrix3x4_t mYtoZ( 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f );
m = mYtoZ;
matrix3x4a_t mA; CDmeAxisSystem::GetConversionMatrix( mA, CDmeAxisSystem::AS_MAYA_YUP, CDmeAxisSystem::AS_VALVE_ENGINE ); Assert( MatricesAreEqual( mYtoZ, mA ) ); } else { static const matrix3x4_t mZtoY( 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f ); m = mZtoY;
matrix3x4a_t mA; CDmeAxisSystem::GetConversionMatrix( mA, CDmeAxisSystem::AS_VALVE_ENGINE, CDmeAxisSystem::AS_MAYA_YUP ); Assert( MatricesAreEqual( mZtoY, mA, 1.0e-4 ) ); }
MatrixQuaternion( m, q ); }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeModel::ReorientDmeAnimation( CDmeDag *pDmeDag, const matrix3x4_t &mOrient, const Quaternion &qOrient ) { if ( !pDmeDag ) return;
CUtlVector< CDmeChannel * > dmeChannelList;
if ( !FindReferringElements( dmeChannelList, pDmeDag->GetTransform(), g_pDataModel->GetSymbol( "toElement" ) ) || dmeChannelList.Count() < 0 ) return;
const int nDmeChannelCount = dmeChannelList.Count(); for ( int i = 0; i < nDmeChannelCount; ++i ) { CDmeChannel *pDmeChannel = dmeChannelList[ i ]; if ( !pDmeChannel ) continue;
CDmeLog *pDmeLog = pDmeChannel->GetLog(); if ( !pDmeLog ) continue;
const int nLogLayerCount = pDmeLog->GetNumLayers(); for ( int j = 0; j < nLogLayerCount; ++j ) { CDmeLogLayer *pDmeLogLayer = pDmeLog->GetLayer( j );
CDmeVector3LogLayer *pDmeVector3LogLayer = CastElement< CDmeVector3LogLayer >( pDmeLogLayer ); if ( pDmeVector3LogLayer ) { RotatePositionLog( pDmeVector3LogLayer, mOrient ); continue; }
CDmeQuaternionLogLayer *pDmeQuaternionLogLayer = CastElement< CDmeQuaternionLogLayer >( pDmeLogLayer ); if ( pDmeQuaternionLogLayer ) { RotateOrientationLog( pDmeQuaternionLogLayer, mOrient, true ); continue; } } } }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeModel::ReorientDmeTransform( CDmeTransform *pDmeTransform, const matrix3x4_t &mOrient, const Quaternion &qOrient ) { if ( !pDmeTransform ) return;
Vector vTmp; VectorRotate( pDmeTransform->GetPosition(), mOrient, vTmp ); pDmeTransform->SetPosition( vTmp );
Quaternion qTmp; QuaternionMult( qOrient, pDmeTransform->GetOrientation(), qTmp ); pDmeTransform->SetOrientation( qTmp ); }
//-----------------------------------------------------------------------------
// Changes the orientation of the vertices and normals of a CDmeMesh using
// the given transform.
//-----------------------------------------------------------------------------
void CDmeModel::ReorientDmeMesh( CDmeMesh *pDmeMesh, matrix3x4_t absMat ) { CDisableUndoScopeGuard();
CDmeVertexData *pDmeVertexData = pDmeMesh->GetBindBaseState();
FieldIndex_t nFieldPosIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_POSITION ); FieldIndex_t nFieldNormIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_NORMAL ); if ( nFieldPosIndex >= 0 && nFieldNormIndex > 0 ) { CDmAttribute *pDmPositionAttr = pDmeVertexData->GetVertexData( nFieldPosIndex ); CDmAttribute *pDmNormalAttr = pDmeVertexData->GetVertexData( nFieldNormIndex );
CDmrArray< Vector > positions( pDmPositionAttr ); CDmrArray< Vector > normals( pDmNormalAttr );
CUtlVector<Vector> newPositions;
matrix3x4_t normalMat; MatrixInverseTranspose( absMat, normalMat );
for ( int i = 0; i < positions.Count(); ++i ) { Vector newPosition;
VectorTransform( positions[i], absMat, newPosition ); positions.Set( i, newPosition ); }
for ( int i = 0; i < normals.Count(); ++i ) { Vector normalizedNormal; Vector newNormal;
VectorCopy( normals[i], normalizedNormal ); VectorNormalize( normalizedNormal ); VectorRotate( normalizedNormal, normalMat, newNormal ); normals.Set( i, newNormal ); }
} }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeModel::ReorientDmeModelChildren( CDmeModel *pDmeModel, const matrix3x4_t &mOrient, const Quaternion &qOrient ) { if ( !pDmeModel ) return;
CDmeTransformList *pDmeTransformList = pDmeModel->FindBaseState( "bind" ); const int nTransformCount = pDmeTransformList ? pDmeTransformList->GetTransformCount() : 0;
const int nChildCount = pDmeModel->GetChildCount(); for ( int i = 0; i < nChildCount; ++i ) { CDmeDag *pDmeDag = pDmeModel->GetChild( i ); if ( !pDmeDag ) continue;
ReorientDmeTransform( pDmeDag->GetTransform(), mOrient, qOrient );
if ( pDmeTransformList ) { int nJointIndex = pDmeModel->GetJointIndex( pDmeDag ); if ( nJointIndex >= 0 && nJointIndex < nTransformCount ) { ReorientDmeTransform( pDmeTransformList->GetTransform( nJointIndex ), mOrient, qOrient ); } }
ReorientDmeAnimation( pDmeDag, mOrient, qOrient ); } }
//-----------------------------------------------------------------------------
// Changes the orientation of a given CDmeDag's mesh data and those of any
// children the CDmeDag has.
//-----------------------------------------------------------------------------
void CDmeModel::ReorientChildDmeMeshes_R( CDmeDag *pDmeDag ) { // Reorient the Dag's shape
CDmeMesh *pDmeMesh = CastElement< CDmeMesh >( pDmeDag->GetShape() );
if ( pDmeMesh ) { matrix3x4_t absMat; pDmeDag->GetAbsTransform( absMat );
ReorientDmeMesh( pDmeMesh, absMat ); }
// Recurse all child CDmeDags and
const int nChildCount = pDmeDag->GetChildCount(); for ( int i = 0; i < nChildCount; ++i ) { ReorientChildDmeMeshes_R( pDmeDag->GetChild( i ) ); } }
//-----------------------------------------------------------------------------
// Walks through the immediate children of this DmeModel and bakes the world
// space transform of any DmeMesh into its vertices and then sets the transform
// of that mesh to the identity. Currently only called by hammer import and
// hammer <-> modo in modo via ReorientToEngineSpace & ReorientToDCCToolSpace
// dmeutils to convert DmeMesh to CMesh uses ReorientToValveEngineSpace
// which does not call FreezeChildMeshes. FreezeChildMeshes is also not a
// complete implementation as it doesn't take into account deltas on meshes
//-----------------------------------------------------------------------------
void CDmeModel::FreezeChildMeshes() { const int nChildCount = GetChildCount(); for ( int i = 0; i < nChildCount; ++i ) { CDmeDag *pDmeDag = GetChild( i ); if ( !pDmeDag ) continue;
ReorientChildDmeMeshes_R( pDmeDag );
// Zero out the rotation since ReorientChildDmeMeshes_R bakes it into the mesh
CDmeTransform *pTransform = pDmeDag->GetTransform(); if ( pTransform ) { Quaternion qZero; qZero.Init(); pTransform->SetOrientation( qZero ); } } }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CDmeModel::SetAxisSystem( CDmeAxisSystem::PredefinedAxisSystem ePredefAxisSystem ) { if ( !m_eAxisSystem.GetElement() ) return false;
return m_eAxisSystem.GetElement()->Init( ePredefAxisSystem ); }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CDmeModel::SetAxisSystem( CDmeAxisSystem::Axis_t eUpAxis, CDmeAxisSystem::ForwardParity_t eForwardParity, CDmeAxisSystem::CoordSys_t eCoordSys /* = CDmeAxisSystem::AS_RIGHT_HANDED */ ) { if ( !m_eAxisSystem.GetElement() ) return false;
return m_eAxisSystem.GetElement()->Init( eUpAxis, eForwardParity, eCoordSys ); }
//-----------------------------------------------------------------------------
// This expects the app has handled undo
//-----------------------------------------------------------------------------
bool CDmeModel::ConvertToAxisSystem( CDmeAxisSystem::PredefinedAxisSystem eToPredefinedAxisSystem ) { if ( !m_eAxisSystem.GetElement() ) return false;
CDmeAxisSystem::Axis_t eToUpAxis; CDmeAxisSystem::ForwardParity_t eToForwardParity; CDmeAxisSystem::CoordSys_t eToCoordSys;
if ( !CDmeAxisSystem::GetPredefinedAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys, eToPredefinedAxisSystem ) ) return false;
return ConvertToAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys ); }
//-----------------------------------------------------------------------------
// This expects the app has handled undo
//-----------------------------------------------------------------------------
bool CDmeModel::ConvertToAxisSystem( CDmeAxisSystem::Axis_t eToUpAxis, CDmeAxisSystem::ForwardParity_t eToForwardParity, CDmeAxisSystem::CoordSys_t eToCoordSys /* = CDmeAxisSystem::AS_RIGHT_HANDED */ ) { if ( !m_eAxisSystem.GetElement() ) return false;
if ( !CDmeAxisSystem::IsValid( eToUpAxis, eToForwardParity, eToCoordSys ) ) return false;
const CDmeAxisSystem *pFromDmeAxisSystem = m_eAxisSystem.GetElement();
Assert( pFromDmeAxisSystem->IsValid() );
const CDmeAxisSystem::Axis_t eFromUpAxis = pFromDmeAxisSystem->GetUpAxis(); const CDmeAxisSystem::ForwardParity_t eFromForwardParity = pFromDmeAxisSystem->GetForwardParity(); const CDmeAxisSystem::CoordSys_t eFromCoordSys = pFromDmeAxisSystem->GetCoordSys();
Assert( CDmeAxisSystem::IsValid( eToUpAxis, eToForwardParity, eToCoordSys ) );
if ( eFromUpAxis == eToUpAxis && eFromForwardParity == eToForwardParity && eFromCoordSys == eToCoordSys ) { // No change needed
return true; }
matrix3x4a_t mConversion = g_MatrixIdentity; CDmeAxisSystem::GetConversionMatrix( mConversion, eFromUpAxis, eFromForwardParity, eFromCoordSys, eToUpAxis, eToForwardParity, eToCoordSys ); const Quaternion qConversion = MatrixQuaternion( mConversion );
ReorientDmeModelChildren( this, mConversion, qConversion );
m_UpAxis.Set( "axisSystem" );
return SetAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys ); }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CDmeModel::GetConversionMatrix( matrix3x4a_t &mConversion, CDmeAxisSystem::PredefinedAxisSystem eToPredefinedAxisSystem ) { const CDmeAxisSystem *pFromDmeAxisSystem = m_eAxisSystem.GetElement();
Assert( pFromDmeAxisSystem->IsValid() );
const CDmeAxisSystem::Axis_t eFromUpAxis = pFromDmeAxisSystem->GetUpAxis(); const CDmeAxisSystem::ForwardParity_t eFromForwardParity = pFromDmeAxisSystem->GetForwardParity(); const CDmeAxisSystem::CoordSys_t eFromCoordSys = pFromDmeAxisSystem->GetCoordSys();
CDmeAxisSystem::Axis_t eToUpAxis; CDmeAxisSystem::ForwardParity_t eToForwardParity; CDmeAxisSystem::CoordSys_t eToCoordSys;
if ( !CDmeAxisSystem::GetPredefinedAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys, eToPredefinedAxisSystem ) ) return false;
CDmeAxisSystem::GetConversionMatrix( mConversion, eFromUpAxis, eFromForwardParity, eFromCoordSys, eToUpAxis, eToForwardParity, eToCoordSys );
return true; }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeModel::TransformScene( const Vector &vScale /*= Vector( 1.0f, 1.0f, 1.0f )*/, const Vector &vTranslate /*= vec3_origin*/, const DegreeEuler &eRotation /*= DegreeEuler( 0.0f, 0.0f, 0.0f )*/, float flEps /*= 1.0e-4 */ ) { if ( !VectorsAreEqual( vScale, Vector( 1.0f, 1.0f, 1.0f ), flEps ) ) { ScaleScene( vScale ); }
if ( !VectorsAreEqual( vTranslate, vec3_origin, flEps ) || !DegreeEulersAreEqual( eRotation, DegreeEuler( 0.0f, 0.0f, 0.0f ), flEps ) ) { matrix3x4a_t mTransform; AngleMatrix( RadianEuler( eRotation ), vTranslate, mTransform );
matrix3x4a_t mIdentity; SetIdentityMatrix( mIdentity );
matrix3x4a_t mDag; CDmeTransform *pDmeModelTransform = GetTransform(); pDmeModelTransform->GetTransform( mDag );
if ( MatricesAreEqual( mDag, mIdentity, flEps ) ) { // DmeModel is just a group, leave it alone, put transform on all children
const int nChildCount = GetChildCount(); for ( int i = 0; i < nChildCount; ++i ) { CDmeDag *pDmeDagChild = GetChild( i ); CDmeTransform *pDmeTransform = pDmeDagChild->GetTransform(); pDmeTransform->GetTransform( mDag ); pDmeTransform->SetTransform( ConcatTransforms( mTransform, mDag ) ); } } else { // DmeModel has transformation data of its own... put transform on it
pDmeModelTransform->SetTransform( ConcatTransforms( mTransform, mDag ) ); } }
CaptureJointsToBaseState( "bind" ); }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeModel::ScaleScene( const Vector &vScale ) { CUtlStack< CDmeDag * > depthFirstStack; depthFirstStack.Push( this );
while ( depthFirstStack.Count() > 0 ) { CDmeDag *pDmeDag = depthFirstStack.Top(); depthFirstStack.Pop();
if ( !pDmeDag ) continue;
const int nChildCount = pDmeDag->GetChildCount(); for ( int i = nChildCount + 1; i >= 0; --i ) { depthFirstStack.Push( pDmeDag->GetChild( i ) ); }
CDmeTransform *pDmeTransform = pDmeDag->GetTransform(); Vector vLocalPos = pDmeTransform->GetPosition(); vLocalPos.x *= vScale.x; vLocalPos.y *= vScale.y; vLocalPos.z *= vScale.z; pDmeTransform->SetPosition( vLocalPos );
matrix3x4a_t mScale; SetScaleMatrix( vScale, mScale );
matrix3x4a_t mScaleInvTranspose; MatrixInverseTranspose( mScale, mScaleInvTranspose );
CDmeMesh *pDmeMesh = CastElement< CDmeMesh >( pDmeDag->GetShape() ); if ( pDmeMesh ) { CUtlVector< CDmeVertexDataBase * > vertexDataList;
const int nStateCount = pDmeMesh->BaseStateCount(); for ( int i = 0; i < nStateCount; ++i ) { CDmeVertexDataBase *pDmeVertexData = pDmeMesh->GetBaseState( i ); if ( pDmeVertexData ) { vertexDataList.AddToTail( pDmeVertexData ); } }
// TODO: See if delta data needs to be scaled differently, positions shouldn't but normals might
const int nDeltaStateCount = pDmeMesh->DeltaStateCount(); for ( int i = 0; i < nDeltaStateCount; ++i ) { CDmeVertexDataBase *pDmeVertexData = pDmeMesh->GetDeltaState( i ); if ( pDmeVertexData ) { vertexDataList.AddToTail( pDmeVertexData ); } }
const int nVertexDataCount = vertexDataList.Count(); for ( int i = 0; i < nVertexDataCount; ++i ) { CDmeVertexDataBase *pDmeVertexData = vertexDataList[i];
const FieldIndex_t nPosFieldIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_POSITION ); if ( nPosFieldIndex >= 0 ) { CDmrArray< Vector > vertexData = pDmeVertexData->GetVertexData( nPosFieldIndex );
const int nDataCount = vertexData.Count(); for ( int j = 0; j < nDataCount; ++j ) { vertexData.Set( j, VectorTransform( vertexData.Get( j ), mScale ) ); } }
const FieldIndex_t nNormalFieldIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_NORMAL ); if ( nPosFieldIndex >= 0 ) { CDmrArray< Vector > vertexData = pDmeVertexData->GetVertexData( nNormalFieldIndex );
const int nDataCount = vertexData.Count(); for ( int j = 0; j < nDataCount; ++j ) { vertexData.Set( j, VectorTransform( vertexData.Get( j ), mScaleInvTranspose ).Normalized() ); } } } } } }
#if 0
//-----------------------------------------------------------------------------
// temp function for validation of code changes, used by CompareDmeDag_R
//-----------------------------------------------------------------------------
static bool CompareDmeMeshes( CDmeMesh *pDmeMeshA, CDmeMesh *pDmeMeshB ) { if ( !pDmeMeshA && !pDmeMeshB ) return true;
if ( !pDmeMeshA || !pDmeMeshB ) return false;
pDmeMeshA->Resolve(); pDmeMeshB->Resolve();
if ( pDmeMeshA->BaseStateCount() != pDmeMeshB->BaseStateCount() ) { AssertMsg( 0, "DmeMesh BaseStateCount mismatch: %s:%d vs %s:%d\n", pDmeMeshA->GetName(), pDmeMeshA->BaseStateCount(), pDmeMeshB->GetName(), pDmeMeshB->BaseStateCount() ); return false; }
CDmeVertexData *pDmeVertexDataA = pDmeMeshA->GetBindBaseState(); CDmeVertexData *pDmeVertexDataB = pDmeMeshB->GetBindBaseState();
if ( !pDmeVertexDataA && !pDmeVertexDataB ) return true; // No vertex data in bind base state... not really a good state but they are the same
if ( !pDmeVertexDataA || !pDmeVertexDataB ) { AssertMsg( 0, "DmeMesh one NULL BindBaseState: %s:0x%p vs %s:0x%p\n", pDmeMeshA->GetName(), pDmeVertexDataA, pDmeMeshB->GetName(), pDmeVertexDataB ); return false; }
pDmeVertexDataA->Resolve(); pDmeVertexDataB->Resolve();
const CUtlVector< Vector > &posDataA = pDmeVertexDataA->GetPositionData(); const CUtlVector< Vector > &posDataB = pDmeVertexDataB->GetPositionData();
if ( posDataA.Count() != posDataB.Count() ) { AssertMsg( 0, "DmeMesh posData count mismatch: %s:%d vs %s:%d\n", pDmeMeshA->GetName(), posDataA.Count(), pDmeMeshB->GetName(), posDataB.Count() ); return false; }
for ( int i = 0; i < posDataA.Count(); ++i ) { if ( !VectorsAreEqual( posDataA[i], posDataB[i] ) ) { AssertMsg( 0, "DmeMesh posData vector mismatch: %d %s:< %6.2f %6.2f %6.2f > vs %s:< %6.2f %6.2f %6.2f >\n", i, pDmeMeshA->GetName(), posDataA[i].x, posDataA[i].y, posDataA[i].z, pDmeMeshB->GetName(), posDataB[i].x, posDataB[i].y, posDataB[i].z ); return false; } }
const CUtlVector< Vector > &normalDataA = pDmeVertexDataA->GetNormalData(); const CUtlVector< Vector > &normalDataB = pDmeVertexDataB->GetNormalData();
if ( normalDataA.Count() != normalDataB.Count() ) { AssertMsg( 0, "DmeMesh normalData count mismatch: %s:%d vs %s:%d\n", pDmeMeshA->GetName(), normalDataA.Count(), pDmeMeshB->GetName(), normalDataB.Count() ); return false; }
for ( int i = 0; i < normalDataA.Count(); ++i ) { if ( !VectorsAreEqual( normalDataA[i], normalDataB[i] ) ) { AssertMsg( 0, "DmeMesh normalData vector mismatch: %d %s:< %6.2f %6.2f %6.2f > vs %s:< %6.2f %6.2f %6.2f >\n", i, pDmeMeshA->GetName(), normalDataA[i].x, normalDataA[i].y, normalDataA[i].z, pDmeMeshB->GetName(), normalDataB[i].x, normalDataB[i].y, normalDataB[i].z ); return false; } }
return true; }
//-----------------------------------------------------------------------------
// temp function for validation of code changes, used by CompareDmeDag_R
//-----------------------------------------------------------------------------
static bool CompareDmeDag_R( CDmeDag *pDmeDagA, CDmeDag *pDmeDagB ) { // Both NULL, Ok
if ( !pDmeDagA && !pDmeDagB ) return true;
// Only one NULL, bad
if ( !pDmeDagA || !pDmeDagB ) { AssertMsg( 0, "One Dag NULL, the other isn't: 0x%p vs 0x%p\n", pDmeDagA, pDmeDagB ); return false; }
// Names don't match, bad
if ( V_strcmp( pDmeDagA->GetName(), pDmeDagB->GetName() ) ) { AssertMsg( 0, "Shape name mismatch: %s vs %s\n", pDmeDagA->GetName(), pDmeDagB->GetName() ); return false; }
// Transforms don't match, bad
CDmeTransform *pDmeTransformA = pDmeDagA->GetTransform(); CDmeTransform *pDmeTransformB = pDmeDagB->GetTransform();
if ( pDmeTransformA && pDmeTransformB ) { matrix3x4a_t mA; pDmeTransformA->GetTransform( mA );
matrix3x4a_t mB; pDmeTransformB->GetTransform( mB );
if ( !MatricesAreEqual( mA, mB ) ) { AssertMsg( 0, "Matrix mismatch" ); return false; } } else if ( pDmeTransformA || pDmeTransformB ) { AssertMsg( 0, "One DmeTransform NULL, the other isn't: %s 0x%p vs %s 0x%p \n", pDmeDagA->GetName(), pDmeTransformA, pDmeDagB->GetName(), pDmeTransformB ); return false; }
// Compare shapes, if they exist
CDmeShape *pDmeShapeA = pDmeDagA->GetShape(); CDmeShape *pDmeShapeB = pDmeDagB->GetShape();
if ( pDmeShapeA && pDmeShapeB ) { if ( pDmeShapeA->GetType() != pDmeShapeB->GetType() ) { AssertMsg( 0, "Shape type mismatch: %s vs %s\n", pDmeShapeA->GetTypeString(), pDmeShapeB->GetTypeString() ); return false; }
if ( pDmeShapeA->IsA( CDmeMesh::GetStaticTypeSymbol() ) ) { if ( !CompareDmeMeshes( CastElement< CDmeMesh >( pDmeShapeA ), CastElement< CDmeMesh >( pDmeShapeB ) ) ) { AssertMsg( 0, "Mesh Mismatch: %s vs %s\n", pDmeShapeA->GetName(), pDmeShapeB->GetName() ); return false; } } } else if ( pDmeShapeA || pDmeShapeB ) { AssertMsg( 0, "One Shape NULL, the other isn't: 0x%p vs 0x%p\n", pDmeShapeA, pDmeShapeB ); return false; }
// Child count don't match, bad
const int nChildCountA = pDmeDagA->GetChildCount(); const int nChildCountB = pDmeDagB->GetChildCount();
if ( nChildCountA != nChildCountB ) return false;
// Compare their children
for ( int i = 0; i < nChildCountA; ++i ) { if ( !CompareDmeDag_R( pDmeDagA->GetChild( i ), pDmeDagB->GetChild( i ) ) ) return false; }
return true; }
//-----------------------------------------------------------------------------
// temp function for validation of code changes, used by CompareDmeDag_R
//-----------------------------------------------------------------------------
static void ResolveDmeDagHierarchy_R( CDmeDag *pDmeDag ) { if ( !pDmeDag ) return;
pDmeDag->Resolve(); CDmeShape *pDmeShape = pDmeDag->GetShape();
if ( pDmeShape ) { pDmeShape->Resolve();
CDmeMesh *pDmeMesh = CastElement< CDmeMesh >( pDmeShape ); if ( pDmeMesh ) { pDmeMesh->Resolve(); for ( int i = 0; i < pDmeMesh->BaseStateCount(); ++i ) { CDmeVertexData *pDmeVertexData = pDmeMesh->GetBaseState( i ); if ( pDmeVertexData ) { pDmeVertexData->Resolve(); } } } }
for ( int i = 0; i < pDmeDag->GetChildCount(); ++i ) { ResolveDmeDagHierarchy_R( pDmeDag->GetChild( i ) ); } } #endif // 0
|