Team Fortress 2 Source Code as on 22/4/2020
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.

1213 lines
40 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Loads mesh data from dmx files
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include "studiomdl.h"
  9. #include "movieobjects/dmemodel.h"
  10. #include "movieobjects/dmemesh.h"
  11. #include "movieobjects/dmefaceset.h"
  12. #include "movieobjects/dmematerial.h"
  13. #include "movieobjects/dmeclip.h"
  14. #include "movieobjects/dmechannel.h"
  15. #include "movieobjects/dmeattachment.h"
  16. #include "movieobjects/dmeanimationlist.h"
  17. #include "movieobjects/dmecombinationoperator.h"
  18. void UnifyIndices( s_source_t *psource );
  19. //-----------------------------------------------------------------------------
  20. // Mapping of bone transforms
  21. //-----------------------------------------------------------------------------
  22. struct BoneTransformMap_t
  23. {
  24. // Number of bones
  25. int m_nBoneCount;
  26. // The order in which transforms appear in this list specifies their bone indices
  27. CDmeTransform *m_ppTransforms[MAXSTUDIOSRCBONES];
  28. // BoneRemap[bone index in file] == bone index in studiomdl
  29. int m_pBoneRemap[MAXSTUDIOSRCBONES];
  30. };
  31. //-----------------------------------------------------------------------------
  32. // Index into an s_node_t array for the default root node
  33. //-----------------------------------------------------------------------------
  34. static int s_nDefaultRootNode;
  35. //-----------------------------------------------------------------------------
  36. // Balance/speed data
  37. //-----------------------------------------------------------------------------
  38. static CUtlVector<float> s_Balance;
  39. static CUtlVector<float> s_Speed;
  40. //-----------------------------------------------------------------------------
  41. // List of unique vertices
  42. //-----------------------------------------------------------------------------
  43. struct VertIndices_t
  44. {
  45. int v;
  46. int n;
  47. int t;
  48. int balance;
  49. int speed;
  50. };
  51. static CUtlVector< VertIndices_t > s_UniqueVertices; // A list of the unique vertices in the mesh
  52. // Given the non-unique vertex index, return the unique vertex index
  53. // The indices are absolute indices into s_UniqueVertices
  54. // But as both arrays contain information for all meshes in the DMX
  55. // The proper offset for the desired mesh must be added to the lookup
  56. // into the map but the value returned has the offset already built in
  57. static CUtlVector< int > s_UniqueVerticesMap;
  58. //-----------------------------------------------------------------------------
  59. // Delta state intermediate data [used for positions, normals, etc.]
  60. //-----------------------------------------------------------------------------
  61. struct DeltaIndex_t
  62. {
  63. DeltaIndex_t() : m_nPositionIndex(-1), m_nNormalIndex(-1), m_nNextDelta(-1), m_nWrinkleIndex(-1), m_bInList(false) {}
  64. int m_nPositionIndex; // Index into DeltaState_t::m_PositionDeltas
  65. int m_nNormalIndex; // Index into DeltaState_t::m_NormalDeltas
  66. int m_nWrinkleIndex; // Index into DeltaState_t::m_WrinkleDeltas
  67. int m_nNextDelta; // Index into DeltaState_t::m_DeltaIndices;
  68. bool m_bInList;
  69. };
  70. struct DeltaState_t
  71. {
  72. DeltaState_t() : m_nDeltaCount( 0 ), m_nFirstDelta( -1 ) {}
  73. CUtlString m_Name;
  74. CUtlVector< Vector > m_PositionDeltas;
  75. CUtlVector< Vector > m_NormalDeltas;
  76. CUtlVector< float > m_WrinkleDeltas;
  77. CUtlVector< DeltaIndex_t > m_DeltaIndices;
  78. int m_nDeltaCount;
  79. int m_nFirstDelta;
  80. };
  81. // NOTE: This is a temporary which loses its state once Load_DMX is exited.
  82. static CUtlVector<DeltaState_t> s_DeltaStates;
  83. //-----------------------------------------------------------------------------
  84. // Finds or adds delta states. These pointers are invalidated by calling FindOrAddDeltaState again
  85. //-----------------------------------------------------------------------------
  86. static DeltaState_t* FindOrAddDeltaState( const char *pDeltaStateName, int nBaseStateVertexCount )
  87. {
  88. int nCount = s_DeltaStates.Count();
  89. for ( int i = 0; i < nCount; ++i )
  90. {
  91. if ( !Q_stricmp( s_DeltaStates[i].m_Name, pDeltaStateName ) )
  92. {
  93. MdlWarning( "Unsupported duplicate delta state named \"%s\" in DMX file\n", pDeltaStateName );
  94. s_DeltaStates[i].m_DeltaIndices.EnsureCount( nBaseStateVertexCount );
  95. return &s_DeltaStates[i];
  96. }
  97. }
  98. int j = s_DeltaStates.AddToTail();
  99. s_DeltaStates[j].m_Name = pDeltaStateName;
  100. s_DeltaStates[j].m_DeltaIndices.SetCount( nBaseStateVertexCount );
  101. return &s_DeltaStates[j];
  102. }
  103. //-----------------------------------------------------------------------------
  104. // Loads the vertices from the model
  105. //-----------------------------------------------------------------------------
  106. static bool DefineUniqueVertices( CDmeVertexData *pBindState, int nStartingUniqueCount )
  107. {
  108. const CUtlVector<int> &positionIndices = pBindState->GetVertexIndexData( CDmeVertexData::FIELD_POSITION );
  109. const CUtlVector<int> &normalIndices = pBindState->GetVertexIndexData( CDmeVertexData::FIELD_NORMAL );
  110. const CUtlVector<int> &texcoordIndices = pBindState->GetVertexIndexData( CDmeVertexData::FIELD_TEXCOORD );
  111. const CUtlVector<int> &balanceIndices = pBindState->GetVertexIndexData( CDmeVertexData::FIELD_BALANCE );
  112. const CUtlVector<int> &speedIndices = pBindState->GetVertexIndexData( CDmeVertexData::FIELD_MORPH_SPEED );
  113. int nPositionCount = positionIndices.Count();
  114. int nNormalCount = normalIndices.Count();
  115. int nTexcoordCount = texcoordIndices.Count();
  116. int nBalanceCount = balanceIndices.Count();
  117. int nSpeedCount = speedIndices.Count();
  118. if ( nNormalCount && nPositionCount != nNormalCount )
  119. {
  120. MdlError( "Encountered a mesh with invalid geometry (different number of indices for various data fields)\n" );
  121. return false;
  122. }
  123. if ( nTexcoordCount && nPositionCount != nTexcoordCount )
  124. {
  125. MdlError( "Encountered a mesh with invalid geometry (different number of indices for various data fields)\n" );
  126. return false;
  127. }
  128. if ( nBalanceCount && nPositionCount != nBalanceCount )
  129. {
  130. MdlError( "Encountered a mesh with invalid geometry (different number of indices for various data fields)\n" );
  131. return false;
  132. }
  133. if ( nSpeedCount && nPositionCount != nSpeedCount )
  134. {
  135. MdlError( "Encountered a mesh with invalid geometry (different number of indices for various data fields)\n" );
  136. return false;
  137. }
  138. // Only add unique vertices to the list as in UnifyIndices
  139. for ( int i = 0; i < nPositionCount; ++i )
  140. {
  141. VertIndices_t vert;
  142. vert.v = g_numverts + positionIndices[i];
  143. vert.n = ( nNormalCount > 0 ) ? g_numnormals + normalIndices[i] : -1;
  144. vert.t = ( nTexcoordCount > 0 ) ? g_numtexcoords + texcoordIndices[i] : -1;
  145. vert.balance = s_Balance.Count() + ( ( nBalanceCount > 0 ) ? balanceIndices[i] : 0 );
  146. vert.speed = s_Speed.Count() + ( ( nSpeedCount > 0 ) ? speedIndices[i] : 0 );
  147. bool unique( true );
  148. for ( int j = nStartingUniqueCount; j < s_UniqueVertices.Count(); ++j )
  149. {
  150. const VertIndices_t &tmpVert( s_UniqueVertices[j] );
  151. if ( vert.v != tmpVert.v )
  152. continue;
  153. if ( vert.n != tmpVert.n )
  154. continue;
  155. if ( vert.t != tmpVert.t )
  156. continue;
  157. unique = false;
  158. s_UniqueVerticesMap.AddToTail( j );
  159. break;
  160. }
  161. if ( !unique )
  162. continue;
  163. int k = s_UniqueVertices.AddToTail();
  164. s_UniqueVertices[k] = vert;
  165. s_UniqueVerticesMap.AddToTail( k );
  166. }
  167. return true;
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Loads the vertices from the model
  171. //-----------------------------------------------------------------------------
  172. static bool LoadVertices( CDmeVertexData *pBindState, const matrix3x4_t& mat, float flScale, int nBoneAssign, int *pBoneRemap, int nStartingUniqueCount )
  173. {
  174. if ( nBoneAssign < 0 )
  175. {
  176. nBoneAssign = s_nDefaultRootNode;
  177. }
  178. // Used by the morphing system to set up delta states
  179. DefineUniqueVertices( pBindState, nStartingUniqueCount );
  180. matrix3x4_t normalMat;
  181. MatrixInverseTranspose( mat, normalMat );
  182. const CUtlVector<Vector> &positions = pBindState->GetPositionData( );
  183. const CUtlVector<Vector> &normals = pBindState->GetNormalData( );
  184. const CUtlVector<Vector2D> &texcoords = pBindState->GetTextureCoordData( );
  185. const CUtlVector<float> &balances = pBindState->GetBalanceData( );
  186. const CUtlVector<float> &speeds = pBindState->GetMorphSpeedData( );
  187. int nCount = positions.Count();
  188. int nJointCount = pBindState->HasSkinningData() ? pBindState->JointCount() : 0;
  189. if ( nJointCount > MAXSTUDIOBONEWEIGHTS )
  190. {
  191. MdlError( "Too many bone influences per vertex!\n" );
  192. return false;
  193. }
  194. // Copy positions + bone info
  195. for ( int i = 0; i < nCount; ++i )
  196. {
  197. // NOTE: The transform transforms the positions into the bind space
  198. VectorTransform( positions[i], mat, g_vertex[g_numverts] );
  199. g_vertex[g_numverts] *= flScale;
  200. if ( nJointCount == 0 )
  201. {
  202. g_bone[g_numverts].numbones = 1;
  203. g_bone[g_numverts].bone[0] = pBoneRemap[ nBoneAssign ];
  204. g_bone[g_numverts].weight[0] = 1.0;
  205. }
  206. else
  207. {
  208. const float *pJointWeights = pBindState->GetJointWeightData( i );
  209. const int *pJointIndices = pBindState->GetJointIndexData( i );
  210. float *pWeightBuf = (float*)_alloca( nJointCount * sizeof(float) );
  211. int *pIndexBuf = (int*)_alloca( nJointCount * sizeof(int) );
  212. memcpy( pWeightBuf, pJointWeights, nJointCount * sizeof(float) );
  213. memcpy( pIndexBuf, pJointIndices, nJointCount * sizeof(int) );
  214. int nBoneCount = SortAndBalanceBones( nJointCount, MAXSTUDIOBONEWEIGHTS, pIndexBuf, pWeightBuf );
  215. g_bone[g_numverts].numbones = nBoneCount;
  216. for ( int j = 0; j < nBoneCount; ++j )
  217. {
  218. g_bone[g_numverts].bone[j] = pBoneRemap[ pIndexBuf[j] ];
  219. g_bone[g_numverts].weight[j] = pWeightBuf[j];
  220. }
  221. }
  222. ++g_numverts;
  223. }
  224. // Copy normals
  225. nCount = normals.Count();
  226. if ( nCount + g_numnormals > MAXSTUDIOVERTS )
  227. {
  228. MdlError( "Too many normals in model!\n" );
  229. return false;
  230. }
  231. for ( int i = 0; i < nCount; ++i )
  232. {
  233. VectorRotate( normals[i], normalMat, g_normal[g_numnormals] );
  234. VectorNormalize( g_normal[g_numnormals] );
  235. ++g_numnormals;
  236. }
  237. // Copy texcoords
  238. nCount = texcoords.Count();
  239. if ( nCount + g_numtexcoords > MAXSTUDIOVERTS )
  240. {
  241. MdlError( "Too many texture coordinates in model!\n" );
  242. return false;
  243. }
  244. bool bFlipVCoordinate = pBindState->IsVCoordinateFlipped();
  245. for ( int i = 0; i < nCount; ++i )
  246. {
  247. g_texcoord[g_numtexcoords].x = texcoords[i].x;
  248. g_texcoord[g_numtexcoords].y = bFlipVCoordinate ? 1.0f - texcoords[i].y : texcoords[i].y;
  249. ++g_numtexcoords;
  250. }
  251. // In the event of no speed or balance map, use the same value of 1 for all vertices
  252. if ( balances.Count() )
  253. {
  254. s_Balance.AddMultipleToTail( balances.Count(), balances.Base() );
  255. }
  256. else
  257. {
  258. s_Balance.AddToTail( 1.0f );
  259. }
  260. if ( speeds.Count() )
  261. {
  262. s_Speed.AddMultipleToTail( speeds.Count(), speeds.Base() );
  263. }
  264. else
  265. {
  266. s_Speed.AddToTail( 1.0f );
  267. }
  268. return true;
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Hook delta into delta list
  272. //-----------------------------------------------------------------------------
  273. static void AddToDeltaList( DeltaState_t *pDeltaStateData, int nUniqueVertex )
  274. {
  275. DeltaIndex_t &index = pDeltaStateData->m_DeltaIndices[ nUniqueVertex ];
  276. if ( !index.m_bInList )
  277. {
  278. index.m_nNextDelta = pDeltaStateData->m_nFirstDelta;
  279. pDeltaStateData->m_nFirstDelta = nUniqueVertex;
  280. pDeltaStateData->m_nDeltaCount++;
  281. index.m_bInList = true;
  282. }
  283. }
  284. //-----------------------------------------------------------------------------
  285. // Loads the vertices from the delta state
  286. //-----------------------------------------------------------------------------
  287. static bool LoadDeltaState(
  288. CDmeVertexDeltaData *pDeltaState,
  289. CDmeVertexData *pBindState,
  290. const matrix3x4_t& mat,
  291. float flScale,
  292. int nStartingUniqueVertex,
  293. int nStartingUniqueVertexMap )
  294. {
  295. DeltaState_t *pDeltaStateData = FindOrAddDeltaState( pDeltaState->GetName(), nStartingUniqueVertex + pBindState->VertexCount() );
  296. matrix3x4_t normalMat;
  297. MatrixInverseTranspose( mat, normalMat );
  298. const CUtlVector<Vector> &positions = pDeltaState->GetPositionData( );
  299. const CUtlVector<int> &positionIndices = pDeltaState->GetVertexIndexData( CDmeVertexDataBase::FIELD_POSITION );
  300. const CUtlVector<Vector> &normals = pDeltaState->GetNormalData( );
  301. const CUtlVector<int> &normalIndices = pDeltaState->GetVertexIndexData( CDmeVertexDataBase::FIELD_NORMAL );
  302. const CUtlVector<float> &wrinkle = pDeltaState->GetWrinkleData( );
  303. const CUtlVector<int> &wrinkleIndices = pDeltaState->GetVertexIndexData( CDmeVertexDataBase::FIELD_WRINKLE );
  304. if ( positions.Count() != positionIndices.Count() )
  305. {
  306. MdlError( "DeltaState %s contains a different number of positions + position indices!\n", pDeltaState->GetName() );
  307. return false;
  308. }
  309. if ( normals.Count() != normalIndices.Count() )
  310. {
  311. MdlError( "DeltaState %s contains a different number of normals + normal indices!\n", pDeltaState->GetName() );
  312. return false;
  313. }
  314. if ( wrinkle.Count() != wrinkleIndices.Count() )
  315. {
  316. MdlError( "DeltaState %s contains a different number of wrinkles + wrinkle indices!\n", pDeltaState->GetName() );
  317. return false;
  318. }
  319. // Copy position delta
  320. int nCount = positions.Count();
  321. for ( int i = 0; i < nCount; ++i )
  322. {
  323. Vector vecDelta;
  324. // NOTE NOTE!!: This is VectorRotate, *not* VectorTransform. This is because
  325. // we're transforming a delta, which is basically a direction vector. To
  326. // move it into the new space, we must rotate it
  327. VectorRotate( positions[i], mat, vecDelta );
  328. vecDelta *= flScale;
  329. int nPositionIndex = pDeltaStateData->m_PositionDeltas.AddToTail( vecDelta );
  330. // Indices
  331. const CUtlVector< int > &baseVerts = pBindState->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_POSITION, positionIndices[i] );
  332. int nBaseVertCount = baseVerts.Count();
  333. for ( int k = 0; k < nBaseVertCount; ++k )
  334. {
  335. int nUniqueVertexIndex = s_UniqueVerticesMap[ nStartingUniqueVertexMap + baseVerts[k] ];
  336. AddToDeltaList( pDeltaStateData, nUniqueVertexIndex );
  337. DeltaIndex_t &index = pDeltaStateData->m_DeltaIndices[ nUniqueVertexIndex ];
  338. index.m_nPositionIndex = nPositionIndex;
  339. }
  340. }
  341. // Copy normals
  342. nCount = normals.Count();
  343. for ( int i = 0; i < nCount; ++i )
  344. {
  345. Vector vecDelta;
  346. VectorRotate( normals[i], normalMat, vecDelta );
  347. int nNormalIndex = pDeltaStateData->m_NormalDeltas.AddToTail( vecDelta );
  348. // Indices
  349. const CUtlVector< int > &baseVerts = pBindState->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_NORMAL, normalIndices[i] );
  350. int nBaseVertCount = baseVerts.Count();
  351. for ( int k = 0; k < nBaseVertCount; ++k )
  352. {
  353. int nUniqueVertexIndex = s_UniqueVerticesMap[ nStartingUniqueVertexMap + baseVerts[k] ];
  354. AddToDeltaList( pDeltaStateData, nUniqueVertexIndex );
  355. DeltaIndex_t &index = pDeltaStateData->m_DeltaIndices[ nUniqueVertexIndex ];
  356. index.m_nNormalIndex = nNormalIndex;
  357. }
  358. }
  359. // Copy wrinkle
  360. nCount = wrinkle.Count();
  361. for ( int i = 0; i < nCount; ++i )
  362. {
  363. int nWrinkleIndex = pDeltaStateData->m_WrinkleDeltas.AddToTail( wrinkle[i] );
  364. // Indices
  365. const CUtlVector< int > &baseVerts = pBindState->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_WRINKLE, wrinkleIndices[i] );
  366. int nBaseVertCount = baseVerts.Count();
  367. for ( int k = 0; k < nBaseVertCount; ++k )
  368. {
  369. int nUniqueVertexIndex = s_UniqueVerticesMap[ nStartingUniqueVertexMap + baseVerts[k] ];
  370. AddToDeltaList( pDeltaStateData, nUniqueVertexIndex );
  371. DeltaIndex_t &index = pDeltaStateData->m_DeltaIndices[ nUniqueVertexIndex ];
  372. index.m_nWrinkleIndex = nWrinkleIndex;
  373. }
  374. }
  375. return true;
  376. }
  377. //-----------------------------------------------------------------------------
  378. // Reads the face data from the DMX data
  379. //-----------------------------------------------------------------------------
  380. static void ParseFaceData( CDmeVertexData *pVertexData, int material, int v1, int v2, int v3, int vi, int ni, int ti )
  381. {
  382. s_tmpface_t f;
  383. f.material = material;
  384. int p, n, t;
  385. p = pVertexData->GetPositionIndex(v1); n = pVertexData->GetNormalIndex(v1); t = pVertexData->GetTexCoordIndex(v1);
  386. f.a = ( p >= 0 ) ? vi + p : 0; f.na = ( n >= 0 ) ? ni + n : 0; f.ta = ( t >= 0 ) ? ti + t : 0;
  387. p = pVertexData->GetPositionIndex(v2); n = pVertexData->GetNormalIndex(v2); t = pVertexData->GetTexCoordIndex(v2);
  388. f.b = ( p >= 0 ) ? vi + p : 0; f.nb = ( n >= 0 ) ? ni + n : 0; f.tb = ( t >= 0 ) ? ti + t : 0;
  389. p = pVertexData->GetPositionIndex(v3); n = pVertexData->GetNormalIndex(v3); t = pVertexData->GetTexCoordIndex(v3);
  390. f.c = ( p >= 0 ) ? vi + p : 0; f.nc = ( n >= 0 ) ? ni + n : 0; f.tc = ( t >= 0 ) ? ti + t : 0;
  391. Assert( f.a <= (unsigned long)g_numverts && f.b <= (unsigned long)g_numverts && f.c <= (unsigned long)g_numverts );
  392. Assert( f.na <= (unsigned long)g_numnormals && f.nb <= (unsigned long)g_numnormals && f.nc <= (unsigned long)g_numnormals );
  393. Assert( f.ta <= (unsigned long)g_numtexcoords && f.tb <= (unsigned long)g_numtexcoords && f.tc <= (unsigned long)g_numtexcoords );
  394. Assert( g_numfaces < MAXSTUDIOTRIANGLES-1 );
  395. if ( g_numfaces >= MAXSTUDIOTRIANGLES-1 )
  396. return;
  397. int i = g_numfaces++;
  398. g_face[i] = f;
  399. }
  400. //-----------------------------------------------------------------------------
  401. // Reads the mesh data from the DMX data
  402. //-----------------------------------------------------------------------------
  403. static bool LoadMesh( CDmeMesh *pMesh, CDmeVertexData *pBindState, const matrix3x4_t& mat, float flScale,
  404. int nBoneAssign, int *pBoneRemap, s_source_t *pSource )
  405. {
  406. pMesh->CollapseRedundantNormals( normal_blend );
  407. // Load the vertices
  408. int nStartingVertex = g_numverts;
  409. int nStartingNormal = g_numnormals;
  410. int nStartingTexCoord = g_numtexcoords;
  411. int nStartingUniqueCount = s_UniqueVertices.Count();
  412. int nStartingUniqueMapCount = s_UniqueVerticesMap.Count();
  413. // This defines s_UniqueVertices & s_UniqueVerticesMap
  414. LoadVertices( pBindState, mat, flScale, nBoneAssign, pBoneRemap, nStartingUniqueCount );
  415. // Load the deltas
  416. int nDeltaStateCount = pMesh->DeltaStateCount();
  417. for ( int i = 0; i < nDeltaStateCount; ++i )
  418. {
  419. CDmeVertexDeltaData *pDeltaState = pMesh->GetDeltaState( i );
  420. if ( !LoadDeltaState( pDeltaState, pBindState, mat, flScale, nStartingUniqueCount, nStartingUniqueMapCount ) )
  421. return false;
  422. }
  423. // load the base triangles
  424. int texture;
  425. int material;
  426. char pTextureName[MAX_PATH];
  427. int nFaceSetCount = pMesh->FaceSetCount();
  428. for ( int i = 0; i < nFaceSetCount; ++i )
  429. {
  430. CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  431. CDmeMaterial *pMaterial = pFaceSet->GetMaterial();
  432. // Get the material name
  433. Q_strncpy( pTextureName, pMaterial->GetMaterialName(), sizeof(pTextureName) );
  434. // funky texture overrides (specified with the -t command-line argument)
  435. for ( int j = 0; j < numrep; j++ )
  436. {
  437. if ( sourcetexture[j][0] == '\0' )
  438. {
  439. Q_strncpy( pTextureName, defaulttexture[j], sizeof(pTextureName) );
  440. break;
  441. }
  442. if ( Q_stricmp( pTextureName, sourcetexture[j]) == 0 )
  443. {
  444. Q_strncpy( pTextureName, defaulttexture[j], sizeof(pTextureName) );
  445. break;
  446. }
  447. }
  448. // skip all faces with the null texture on them.
  449. char pPathNoExt[MAX_PATH];
  450. Q_StripExtension( pTextureName, pPathNoExt, sizeof(pPathNoExt) );
  451. if ( !Q_stricmp( pPathNoExt, "null" ) )
  452. continue;
  453. texture = LookupTexture( pTextureName, true );
  454. pSource->texmap[texture] = texture; // hack, make it 1:1
  455. material = UseTextureAsMaterial( texture );
  456. // prepare indices
  457. int nFirstIndex = 0;
  458. int nIndexCount = pFaceSet->NumIndices();
  459. while ( nFirstIndex < nIndexCount )
  460. {
  461. int nVertexCount = pFaceSet->GetNextPolygonVertexCount( nFirstIndex );
  462. if ( nVertexCount >= 3 )
  463. {
  464. int nOutCount = (nVertexCount-2) * 3;
  465. int *pIndices = (int*)_alloca( nOutCount * sizeof(int) );
  466. pMesh->ComputeTriangulatedIndices( pBindState, pFaceSet, nFirstIndex, pIndices, nOutCount );
  467. for ( int ii = 0; ii < nOutCount; ii +=3 )
  468. {
  469. ParseFaceData( pBindState, material, pIndices[ii], pIndices[ii+2], pIndices[ii+1], nStartingVertex, nStartingNormal, nStartingTexCoord );
  470. }
  471. }
  472. nFirstIndex += nVertexCount + 1;
  473. }
  474. }
  475. return true;
  476. }
  477. //-----------------------------------------------------------------------------
  478. // Method used to add mesh data
  479. //-----------------------------------------------------------------------------
  480. struct LoadMeshInfo_t
  481. {
  482. s_source_t *m_pSource;
  483. CDmeModel *m_pModel;
  484. float m_flScale;
  485. int *m_pBoneRemap;
  486. matrix3x4_t m_pBindPose[MAXSTUDIOSRCBONES];
  487. };
  488. static bool LoadMeshes( const LoadMeshInfo_t &info, CDmeDag *pDag, const matrix3x4_t &parentToBindPose, int nBoneAssign )
  489. {
  490. // We want to create an aggregate matrix transforming from this dag to its closest
  491. // parent which actually is an animated joint. This is done so we can autoskin
  492. // meshes to their closest parents if they have not been skinned.
  493. matrix3x4_t dagToBindPose;
  494. CDmeTransform *pDagTransform = pDag->GetTransform();
  495. int nFoundIndex = info.m_pModel->GetJointTransformIndex( pDagTransform );
  496. // Update autoskin to autoskin to non-DmeJoint's if they are children of the DmeModel (i.e. they have no parent bone)
  497. if ( nFoundIndex >= 0 )
  498. {
  499. if ( pDag == info.m_pModel || CastElement< CDmeJoint >( pDag ) )
  500. {
  501. nBoneAssign = nFoundIndex;
  502. }
  503. else
  504. {
  505. for ( int i = 0; i < info.m_pModel->GetChildCount(); ++i )
  506. {
  507. if ( info.m_pModel->GetChild( i ) == pDag )
  508. {
  509. nBoneAssign = nFoundIndex;
  510. break;
  511. }
  512. }
  513. }
  514. }
  515. if ( nFoundIndex >= 0 )
  516. {
  517. ConcatTransforms( parentToBindPose, info.m_pBindPose[nFoundIndex], dagToBindPose );
  518. }
  519. else
  520. {
  521. // NOTE: This isn't particularly kosher; we're using the current pose instead of the bind pose
  522. // because there's no transform in the bind pose
  523. matrix3x4_t dagToParent;
  524. pDagTransform->GetTransform( dagToParent );
  525. ConcatTransforms( parentToBindPose, dagToParent, dagToBindPose );
  526. }
  527. CDmeMesh *pMesh = CastElement< CDmeMesh >( pDag->GetShape() );
  528. if ( pMesh )
  529. {
  530. CDmeVertexData *pBindState = pMesh->FindBaseState( "bind" );
  531. if ( !pBindState )
  532. return false;
  533. if ( !LoadMesh( pMesh, pBindState, dagToBindPose, info.m_flScale, nBoneAssign, info.m_pBoneRemap, info.m_pSource ) )
  534. return false;
  535. }
  536. int nCount = pDag->GetChildCount();
  537. for ( int i = 0; i < nCount; ++i )
  538. {
  539. CDmeDag *pChild = pDag->GetChild( i );
  540. if ( !LoadMeshes( info, pChild, dagToBindPose, nBoneAssign ) )
  541. return false;
  542. }
  543. return true;
  544. }
  545. //-----------------------------------------------------------------------------
  546. // Method used to add mesh data
  547. //-----------------------------------------------------------------------------
  548. static bool LoadMeshes( CDmeModel *pModel, float flScale, int *pBoneRemap, s_source_t *pSource )
  549. {
  550. matrix3x4_t mat;
  551. SetIdentityMatrix( mat );
  552. LoadMeshInfo_t info;
  553. info.m_pModel = pModel;
  554. info.m_flScale = flScale;
  555. info.m_pBoneRemap = pBoneRemap;
  556. info.m_pSource = pSource;
  557. CDmeTransformList *pBindPose = pModel->FindBaseState( "bind" );
  558. int nCount = pBindPose ? pBindPose->GetTransformCount() : pModel->GetJointTransformCount();
  559. for ( int i = 0; i < nCount; ++i )
  560. {
  561. CDmeTransform *pTransform = pBindPose ? pBindPose->GetTransform(i) : pModel->GetJointTransform(i);
  562. matrix3x4_t jointTransform;
  563. pTransform->GetTransform( info.m_pBindPose[i] );
  564. }
  565. int nChildCount = pModel->GetChildCount();
  566. for ( int i = 0; i < nChildCount; ++i )
  567. {
  568. CDmeDag *pChild = pModel->GetChild( i );
  569. if ( !LoadMeshes( info, pChild, mat, -1 ) )
  570. return false;
  571. }
  572. return true;
  573. }
  574. //-----------------------------------------------------------------------------
  575. // Builds s_vertanim_ts
  576. //-----------------------------------------------------------------------------
  577. static void BuildVertexAnimations( s_source_t *pSource )
  578. {
  579. int nCount = s_DeltaStates.Count();
  580. if ( nCount == 0 )
  581. return;
  582. Assert( s_Speed.Count() > 0 );
  583. Assert( s_Balance.Count() > 0 );
  584. Assert( s_UniqueVertices.Count() == numvlist );
  585. s_vertanim_t *pVertAnim = (s_vertanim_t *)_alloca( numvlist * sizeof( s_vertanim_t ) );
  586. for ( int i = 0; i < nCount; ++i )
  587. {
  588. DeltaState_t &state = s_DeltaStates[i];
  589. s_sourceanim_t *pSourceAnim = FindOrAddSourceAnim( pSource, state.m_Name );
  590. pSourceAnim->numframes = 1;
  591. pSourceAnim->startframe = 0;
  592. pSourceAnim->endframe = 0;
  593. pSourceAnim->newStyleVertexAnimations = true;
  594. // Traverse the linked list of unique vertex indices j that has a delta
  595. int nVertAnimCount = 0;
  596. for ( int j = state.m_nFirstDelta; j >= 0; j = state.m_DeltaIndices[j].m_nNextDelta )
  597. {
  598. // The Delta Indices array is a parallel array to s_UniqueVertices
  599. // j is used to index into both
  600. DeltaIndex_t &delta = state.m_DeltaIndices[j];
  601. Assert( delta.m_nPositionIndex >= 0 || delta.m_nNormalIndex >= 0 || delta.m_nWrinkleIndex >= 0 );
  602. VertIndices_t &uniqueVert = s_UniqueVertices[j];
  603. const v_unify_t *pList = v_list[uniqueVert.v];
  604. for( ; pList; pList = pList->next )
  605. {
  606. if ( pList->n != uniqueVert.n || pList->t != uniqueVert.t )
  607. continue;
  608. s_vertanim_t& vertanim = pVertAnim[nVertAnimCount++];
  609. vertanim.vertex = pList - v_listdata;
  610. vertanim.speed = s_Speed[ s_UniqueVertices[j].speed ];
  611. vertanim.side = s_Balance[ s_UniqueVertices[j].balance ];
  612. if ( delta.m_nPositionIndex >= 0 )
  613. {
  614. vertanim.pos = state.m_PositionDeltas[ delta.m_nPositionIndex ];
  615. }
  616. else
  617. {
  618. vertanim.pos = vec3_origin;
  619. }
  620. if ( delta.m_nNormalIndex >= 0 )
  621. {
  622. vertanim.normal = state.m_NormalDeltas[ delta.m_nNormalIndex ];
  623. }
  624. else
  625. {
  626. vertanim.normal = vec3_origin;
  627. }
  628. if ( delta.m_nWrinkleIndex >= 0 )
  629. {
  630. vertanim.wrinkle = state.m_WrinkleDeltas[ delta.m_nWrinkleIndex ];
  631. }
  632. else
  633. {
  634. vertanim.wrinkle = 0.0f;
  635. }
  636. }
  637. }
  638. pSourceAnim->numvanims[0] = nVertAnimCount;
  639. pSourceAnim->vanim[0] = (s_vertanim_t *)kalloc( nVertAnimCount, sizeof( s_vertanim_t ) );
  640. memcpy( pSourceAnim->vanim[0], pVertAnim, nVertAnimCount * sizeof( s_vertanim_t ) );
  641. }
  642. }
  643. //-----------------------------------------------------------------------------
  644. // Loads the skeletal hierarchy from the game model, returns bone count
  645. //-----------------------------------------------------------------------------
  646. static bool AddDagJoint( CDmeModel *pModel, CDmeDag *pDag, s_node_t *pNodes, int nParentIndex, BoneTransformMap_t &boneMap )
  647. {
  648. CDmeTransform *pDmeTransform = pDag->GetTransform();
  649. const char *pTransformName = pDmeTransform->GetName();
  650. int nJointIndex = boneMap.m_nBoneCount++;
  651. if ( nJointIndex >= MAXSTUDIOSRCBONES )
  652. {
  653. MdlWarning( "DMX Model has too many bones [%d, max can be %d]!\n", boneMap.m_nBoneCount, MAXSTUDIOSRCBONES );
  654. return false;
  655. }
  656. boneMap.m_ppTransforms[ nJointIndex ] = pDmeTransform;
  657. int nFoundIndex = 0;
  658. if ( pModel )
  659. {
  660. nFoundIndex = pModel->GetJointTransformIndex( pDmeTransform );
  661. if ( nFoundIndex >= 0 )
  662. {
  663. boneMap.m_pBoneRemap[nFoundIndex] = nJointIndex;
  664. }
  665. }
  666. Q_strncpy( pNodes[ nJointIndex ].name, pTransformName, sizeof( pNodes[ nJointIndex ].name ) );
  667. pNodes[ nJointIndex ].parent = nParentIndex;
  668. // Now deal with children
  669. int nChildCount = pDag->GetChildCount();
  670. for ( int i = 0; i < nChildCount; ++i )
  671. {
  672. CDmeDag *pChild = pDag->GetChild( i );
  673. if ( !pChild )
  674. continue;
  675. int nCurrentBoneCount = boneMap.m_nBoneCount;
  676. if ( !AddDagJoint( pModel, pChild, pNodes, nJointIndex, boneMap ) )
  677. return false;
  678. if ( ( nCurrentBoneCount != boneMap.m_nBoneCount ) && ( nFoundIndex < 0 ) )
  679. {
  680. MdlWarning( "DMX Model has a joint \"%s\" which is not in its joint transform list.\n"
  681. "This joint has children which are in the joint transform list, which is illegal.\n",
  682. pDag->GetName() );
  683. return false;
  684. }
  685. }
  686. return true;
  687. }
  688. //-----------------------------------------------------------------------------
  689. // Main entry point for loading the skeleton
  690. //-----------------------------------------------------------------------------
  691. static int LoadSkeleton( CDmeDag *pRoot, CDmeModel *pModel, s_node_t *pNodes, BoneTransformMap_t &map )
  692. {
  693. // Initialize bone indices
  694. map.m_nBoneCount = 0;
  695. for ( int i = 0; i < MAXSTUDIOSRCBONES; ++i )
  696. {
  697. pNodes[i].name[0] = 0;
  698. pNodes[i].parent = -1;
  699. map.m_pBoneRemap[i] = -1;
  700. map.m_ppTransforms[i] = NULL;
  701. }
  702. // Don't create joints for the the root dag ever.. just deal with the children
  703. int nChildCount = pRoot->GetChildCount();
  704. for ( int i = 0; i < nChildCount; ++i )
  705. {
  706. CDmeDag *pChild = pRoot->GetChild( i );
  707. if ( !pChild )
  708. continue;
  709. if ( !AddDagJoint( pModel, pChild, pNodes, -1, map ) )
  710. return 0;
  711. }
  712. // Add a default identity bone used for autoskinning if no joints are specified
  713. s_nDefaultRootNode = map.m_nBoneCount;
  714. Q_strncpy( pNodes[s_nDefaultRootNode].name, "defaultRoot", sizeof( pNodes[ s_nDefaultRootNode ].name ) );
  715. pNodes[s_nDefaultRootNode].parent = -1;
  716. if ( !pModel )
  717. return map.m_nBoneCount + 1;
  718. // Look for joints listed in the transform list which aren't in the hierarchy
  719. int nInitialBoneCount = pModel->GetJointTransformCount();
  720. for ( int i = 0; i < nInitialBoneCount; ++i )
  721. {
  722. int nIndex = map.m_pBoneRemap[i];
  723. if ( nIndex < 0 )
  724. {
  725. map.m_pBoneRemap[i] = map.m_nBoneCount++;
  726. nIndex = map.m_pBoneRemap[i];
  727. }
  728. if ( pNodes[nIndex].name[0] == 0 )
  729. {
  730. CDmeTransform *pTransform = pModel->GetJointTransform( i );
  731. Q_strncpy( pNodes[ nIndex ].name, pTransform->GetName(), sizeof( pNodes[ nIndex ].name ) );
  732. MdlWarning( "Joint %s specified in the joint transform list but doesn't appear in the dag hierarchy!\n", pTransform->GetName() );
  733. }
  734. }
  735. return map.m_nBoneCount + 1;
  736. }
  737. //-----------------------------------------------------------------------------
  738. // Loads the skeletal hierarchy from the game model, returns bone count
  739. //-----------------------------------------------------------------------------
  740. static void LoadAttachments( CDmeDag *pRoot, CDmeDag *pDag, s_source_t *pSource )
  741. {
  742. CDmeAttachment *pAttachment = CastElement< CDmeAttachment >( pDag->GetShape() );
  743. if ( pAttachment && ( pDag != pRoot ) )
  744. {
  745. int i = pSource->m_Attachments.AddToTail();
  746. s_attachment_t &attachment = pSource->m_Attachments[i];
  747. memset( &attachment, 0, sizeof(s_attachment_t) );
  748. Q_strncpy( attachment.name, pAttachment->GetName(), sizeof( attachment.name ) );
  749. Q_strncpy( attachment.bonename, pDag->GetName(), sizeof( attachment.bonename ) );
  750. SetIdentityMatrix( attachment.local );
  751. if ( pAttachment->m_bIsRigid )
  752. {
  753. attachment.type |= IS_RIGID;
  754. }
  755. if ( pAttachment->m_bIsWorldAligned )
  756. {
  757. attachment.flags |= ATTACHMENT_FLAG_WORLD_ALIGN;
  758. }
  759. }
  760. // Don't create joints for the the root dag ever.. just deal with the children
  761. int nChildCount = pDag->GetChildCount();
  762. for ( int i = 0; i < nChildCount; ++i )
  763. {
  764. CDmeDag *pChild = pDag->GetChild( i );
  765. if ( !pChild )
  766. continue;
  767. LoadAttachments( pRoot, pChild, pSource );
  768. }
  769. }
  770. //-----------------------------------------------------------------------------
  771. // Loads the bind pose
  772. //-----------------------------------------------------------------------------
  773. static void LoadBindPose( CDmeModel *pModel, float flScale, int *pBoneRemap, s_source_t *pSource )
  774. {
  775. s_sourceanim_t *pSourceAnim = FindOrAddSourceAnim( pSource, "BindPose" );
  776. pSourceAnim->startframe = 0;
  777. pSourceAnim->endframe = 0;
  778. pSourceAnim->numframes = 1;
  779. // Default all transforms to identity
  780. pSourceAnim->rawanim[0] = (s_bone_t *)kalloc( pSource->numbones, sizeof(s_bone_t) );
  781. for ( int i = 0; i < pSource->numbones; ++i )
  782. {
  783. pSourceAnim->rawanim[0][i].pos.Init();
  784. pSourceAnim->rawanim[0][i].rot.Init();
  785. }
  786. // Override those bones in the bind pose with the real values
  787. // NOTE: This means that bones that are not in the bind pose are set to identity!
  788. // Is this correct? I think it shouldn't matter, but we may need to fix this.
  789. CDmeTransformList *pBindPose = pModel->FindBaseState( "bind" );
  790. int nCount = pBindPose ? pBindPose->GetTransformCount() : pModel->GetJointTransformCount();
  791. for ( int i = 0; i < nCount; ++i )
  792. {
  793. CDmeTransform *pTransform = pBindPose ? pBindPose->GetTransform(i) : pModel->GetJointTransform(i);
  794. matrix3x4_t jointTransform;
  795. pTransform->GetTransform( jointTransform );
  796. int nActualBoneIndex = pBoneRemap[i];
  797. s_bone_t &bone = pSourceAnim->rawanim[0][nActualBoneIndex];
  798. MatrixAngles( jointTransform, bone.rot, bone.pos );
  799. bone.pos *= flScale;
  800. }
  801. Build_Reference( pSource, "BindPose" );
  802. }
  803. //-----------------------------------------------------------------------------
  804. // Main entry point for loading DMX files
  805. //-----------------------------------------------------------------------------
  806. static void PrepareChannels( CDmeChannelsClip *pAnimation )
  807. {
  808. int nChannelsCount = pAnimation->m_Channels.Count();
  809. for ( int i = 0; i < nChannelsCount; ++i )
  810. {
  811. pAnimation->m_Channels[i]->SetMode( CM_PLAY );
  812. }
  813. }
  814. //-----------------------------------------------------------------------------
  815. // Update channels so they are in position for the next frame
  816. //-----------------------------------------------------------------------------
  817. static void UpdateChannels( CDmeChannelsClip *pAnimation, DmeTime_t clipTime )
  818. {
  819. int nChannelsCount = pAnimation->m_Channels.Count();
  820. DmeTime_t channelTime = pAnimation->ToChildMediaTime( clipTime );
  821. CUtlVector< IDmeOperator* > operators( 0, nChannelsCount );
  822. for ( int i = 0; i < nChannelsCount; ++i )
  823. {
  824. pAnimation->m_Channels[i]->SetCurrentTime( channelTime );
  825. operators.AddToTail( pAnimation->m_Channels[i] );
  826. }
  827. // Recompute the position of the joints
  828. {
  829. CDisableUndoScopeGuard guard;
  830. g_pDmElementFramework->SetOperators( operators );
  831. g_pDmElementFramework->Operate( true );
  832. }
  833. g_pDmElementFramework->BeginEdit();
  834. }
  835. //-----------------------------------------------------------------------------
  836. // Initialize the pose for this frame
  837. //-----------------------------------------------------------------------------
  838. static void ComputeFramePose( s_sourceanim_t *pSourceAnim, int nFrame, float flScale, BoneTransformMap_t& boneMap )
  839. {
  840. pSourceAnim->rawanim[nFrame] = (s_bone_t *)kalloc( boneMap.m_nBoneCount, sizeof( s_bone_t ) );
  841. for ( int i = 0; i < boneMap.m_nBoneCount; ++i )
  842. {
  843. matrix3x4_t jointTransform;
  844. boneMap.m_ppTransforms[i]->GetTransform( jointTransform );
  845. MatrixAngles( jointTransform, pSourceAnim->rawanim[nFrame][i].rot, pSourceAnim->rawanim[nFrame][i].pos );
  846. pSourceAnim->rawanim[nFrame][i].pos *= flScale;
  847. }
  848. }
  849. //-----------------------------------------------------------------------------
  850. // Main entry point for loading animations
  851. //-----------------------------------------------------------------------------
  852. static void LoadAnimations( s_source_t *pSource, CDmeAnimationList *pAnimationList, float flScale, BoneTransformMap_t &boneMap )
  853. {
  854. int nAnimationCount = pAnimationList->GetAnimationCount();
  855. for ( int i = 0; i < nAnimationCount; ++i )
  856. {
  857. CDmeChannelsClip *pAnimation = pAnimationList->GetAnimation( i );
  858. if ( !Q_stricmp( pAnimationList->GetName(), "BindPose" ) )
  859. {
  860. MdlError( "Error: Cannot use \"BindPose\" as an animation name!\n" );
  861. break;
  862. }
  863. s_sourceanim_t *pSourceAnim = FindOrAddSourceAnim( pSource, pAnimation->GetName() );
  864. DmeTime_t nStartTime = pAnimation->GetStartTime();
  865. DmeTime_t nEndTime = pAnimation->GetEndTime();
  866. int nFrameRateVal = pAnimation->GetValue<int>( "frameRate" );
  867. if ( nFrameRateVal <= 0 )
  868. {
  869. nFrameRateVal = 30;
  870. }
  871. DmeFramerate_t nFrameRate = nFrameRateVal;
  872. pSourceAnim->startframe = nStartTime.CurrentFrame( nFrameRate );
  873. pSourceAnim->endframe = nEndTime.CurrentFrame( nFrameRate );
  874. pSourceAnim->numframes = pSourceAnim->endframe - pSourceAnim->startframe + 1;
  875. // Prepare channels for playback
  876. PrepareChannels( pAnimation );
  877. float flOOFrameRate = 1.0f / (float)nFrameRateVal;
  878. DmeTime_t nTime = nStartTime;
  879. int nFrame = 0;
  880. while ( nFrame < pSourceAnim->numframes )
  881. {
  882. int nSecond = nFrame / nFrameRateVal;
  883. int nFraction = nFrame - nSecond * nFrameRateVal;
  884. DmeTime_t t = nStartTime + DmeTime_t( nSecond * 10000 ) + DmeTime_t( (float)nFraction * flOOFrameRate );
  885. // Update the current time
  886. UpdateChannels( pAnimation, t );
  887. // Initialize the pose for this frame
  888. ComputeFramePose( pSourceAnim, nFrame, flScale, boneMap );
  889. ++nFrame;
  890. }
  891. }
  892. }
  893. //-----------------------------------------------------------------------------
  894. // Loads the skeletal hierarchy from the game model, returns bone count
  895. //-----------------------------------------------------------------------------
  896. static void AddFlexKeys( CDmeDag *pRoot, CDmeDag *pDag, CDmeCombinationOperator *pComboOp, s_source_t *pSource )
  897. {
  898. CDmeMesh *pMesh = CastElement< CDmeMesh >( pDag->GetShape() );
  899. if ( pMesh && ( pDag != pRoot ) )
  900. {
  901. int nDeltaStateCount = pMesh->DeltaStateCount();
  902. for ( int i = 0; i < nDeltaStateCount; ++i )
  903. {
  904. CDmeVertexDeltaData *pDeltaState = pMesh->GetDeltaState( i );
  905. AddFlexKey( pSource, pComboOp, pDeltaState->GetName() );
  906. }
  907. }
  908. // Don't create joints for the the root dag ever.. just deal with the children
  909. int nChildCount = pDag->GetChildCount();
  910. for ( int i = 0; i < nChildCount; ++i )
  911. {
  912. CDmeDag *pChild = pDag->GetChild( i );
  913. if ( !pChild )
  914. continue;
  915. AddFlexKeys( pRoot, pChild, pComboOp, pSource );
  916. }
  917. }
  918. //-----------------------------------------------------------------------------
  919. // Loads all auxilliary model info:
  920. //
  921. // * Determine original source files used to generate
  922. // the current DMX file and schedule them for processing.
  923. //-----------------------------------------------------------------------------
  924. void LoadModelInfo( CDmElement *pRoot, char const *pFullPath )
  925. {
  926. // Determine original source files and schedule them for processing
  927. if ( CDmElement *pMakeFile = pRoot->GetValueElement< CDmElement >( "makefile" ) )
  928. {
  929. if ( CDmAttribute *pSources = pMakeFile->GetAttribute( "sources" ) )
  930. {
  931. CDmrElementArray< CDmElement > arrSources( pSources );
  932. for ( int kk = 0; kk < arrSources.Count(); ++ kk )
  933. {
  934. if ( CDmElement *pModelSource = arrSources.Element( kk ) )
  935. {
  936. if ( char const *szName = pModelSource->GetName() )
  937. {
  938. ProcessOriginalContentFile( pFullPath, szName );
  939. }
  940. }
  941. }
  942. }
  943. }
  944. }
  945. //-----------------------------------------------------------------------------
  946. // Main entry point for loading DMX files
  947. //-----------------------------------------------------------------------------
  948. int Load_DMX( s_source_t *pSource )
  949. {
  950. DmFileId_t fileId;
  951. s_DeltaStates.RemoveAll();
  952. s_Balance.RemoveAll();
  953. s_Speed.RemoveAll();
  954. s_UniqueVertices.RemoveAll();
  955. s_UniqueVerticesMap.RemoveAll();
  956. // use the full search tree, including mod hierarchy to find the file
  957. char pFullPath[MAX_PATH];
  958. if ( !GetGlobalFilePath( pSource->filename, pFullPath, sizeof(pFullPath) ) )
  959. return 0;
  960. // When reading, keep the CRLF; this will make ReadFile read it in binary format
  961. // and also append a couple 0s to the end of the buffer.
  962. CDmElement *pRoot;
  963. if ( g_pDataModel->RestoreFromFile( pFullPath, NULL, NULL, &pRoot ) == DMFILEID_INVALID )
  964. return 0;
  965. if ( !g_quiet )
  966. {
  967. Msg( "DMX Model %s\n", pFullPath );
  968. }
  969. // Load model info
  970. LoadModelInfo( pRoot, pFullPath );
  971. // Extract out the skeleton
  972. CDmeDag *pSkeleton = pRoot->GetValueElement< CDmeDag >( "skeleton" );
  973. CDmeModel *pModel = pRoot->GetValueElement< CDmeModel >( "model" );
  974. CDmeCombinationOperator *pCombinationOperator = pRoot->GetValueElement< CDmeCombinationOperator >( "combinationOperator" );
  975. if ( !pSkeleton )
  976. goto dmxError;
  977. // BoneRemap[bone index in file] == bone index in studiomdl
  978. BoneTransformMap_t boneMap;
  979. pSource->numbones = LoadSkeleton( pSkeleton, pModel, pSource->localBone, boneMap );
  980. if ( pSource->numbones == 0 )
  981. goto dmxError;
  982. LoadAttachments( pSkeleton, pSkeleton, pSource );
  983. g_numfaces = 0;
  984. if ( pModel )
  985. {
  986. if ( pCombinationOperator )
  987. {
  988. pCombinationOperator->GenerateWrinkleDeltas( false );
  989. }
  990. LoadBindPose( pModel, g_currentscale, boneMap.m_pBoneRemap, pSource );
  991. if ( !LoadMeshes( pModel, g_currentscale, boneMap.m_pBoneRemap, pSource ) )
  992. goto dmxError;
  993. UnifyIndices( pSource );
  994. BuildVertexAnimations( pSource );
  995. BuildIndividualMeshes( pSource );
  996. }
  997. if ( pCombinationOperator )
  998. {
  999. AddFlexKeys( pModel, pModel, pCombinationOperator, pSource );
  1000. AddCombination( pSource, pCombinationOperator );
  1001. }
  1002. CDmeAnimationList *pAnimationList = pRoot->GetValueElement< CDmeAnimationList >( "animationList" );
  1003. if ( pAnimationList )
  1004. {
  1005. LoadAnimations( pSource, pAnimationList, g_currentscale, boneMap );
  1006. }
  1007. fileId = pRoot->GetFileId();
  1008. g_pDataModel->RemoveFileId( fileId );
  1009. return 1;
  1010. dmxError:
  1011. fileId = pRoot->GetFileId();
  1012. g_pDataModel->RemoveFileId( fileId );
  1013. return 0;
  1014. }