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.

1022 lines
33 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmevertexdata.h"
  7. #include "movieobjects_interfaces.h"
  8. #include <limits.h>
  9. #include "tier3/tier3.h"
  10. #include "tier0/dbg.h"
  11. #include "datamodel/dmelementfactoryhelper.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. //-----------------------------------------------------------------------------
  15. // Standard vertex fields
  16. //-----------------------------------------------------------------------------
  17. static char *g_pStandardFieldNames[] =
  18. {
  19. "positions",
  20. "normals",
  21. "tangents",
  22. "textureCoordinates",
  23. "colors",
  24. "jointWeights",
  25. "jointIndices",
  26. "balance",
  27. "speed",
  28. "wrinkle",
  29. "weight"
  30. };
  31. static DmAttributeType_t g_pStandardFieldTypes[] =
  32. {
  33. AT_VECTOR3_ARRAY,
  34. AT_VECTOR3_ARRAY,
  35. AT_VECTOR4_ARRAY,
  36. AT_VECTOR2_ARRAY,
  37. AT_COLOR_ARRAY,
  38. AT_FLOAT_ARRAY,
  39. AT_INT_ARRAY,
  40. AT_FLOAT_ARRAY,
  41. AT_FLOAT_ARRAY,
  42. AT_FLOAT_ARRAY,
  43. AT_FLOAT_ARRAY
  44. };
  45. //-----------------------------------------------------------------------------
  46. // Expose this class to the scene database
  47. //-----------------------------------------------------------------------------
  48. IMPLEMENT_ELEMENT_FACTORY( DmeVertexDataBase, CDmeVertexDataBase );
  49. //-----------------------------------------------------------------------------
  50. // Purpose:
  51. //-----------------------------------------------------------------------------
  52. void CDmeVertexDataBase::OnConstruction()
  53. {
  54. m_nVertexCount = 0;
  55. memset( m_pStandardFieldIndex, 0xFF, sizeof(m_pStandardFieldIndex) );
  56. m_VertexFormat.Init( this, "vertexFormat" );
  57. m_nJointCount.Init( this, "jointCount" );
  58. m_bFlipVCoordinates.Init( this, "flipVCoordinates" );
  59. }
  60. void CDmeVertexDataBase::OnDestruction()
  61. {
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Updates info for fast lookups for well-known fields
  65. //-----------------------------------------------------------------------------
  66. void CDmeVertexDataBase::UpdateStandardFieldInfo( int nFieldIndex, const char *pFieldName, DmAttributeType_t attrType )
  67. {
  68. COMPILE_TIME_ASSERT( ARRAYSIZE(g_pStandardFieldNames) == STANDARD_FIELD_COUNT );
  69. COMPILE_TIME_ASSERT( ARRAYSIZE(g_pStandardFieldTypes) == STANDARD_FIELD_COUNT );
  70. for ( int i = 0; i < STANDARD_FIELD_COUNT; ++i )
  71. {
  72. if ( !Q_stricmp( pFieldName, g_pStandardFieldNames[i] ) )
  73. {
  74. if ( attrType != g_pStandardFieldTypes[i] )
  75. {
  76. Warning( "Standard field %s has incorrect attribute type!\n", pFieldName );
  77. return;
  78. }
  79. m_pStandardFieldIndex[i] = nFieldIndex;
  80. break;
  81. }
  82. }
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Computes information about how to find particular fields
  86. //-----------------------------------------------------------------------------
  87. void CDmeVertexDataBase::ComputeFieldInfo()
  88. {
  89. // Clear existing field info,
  90. // but keep the old names around so field indices remain constant
  91. int nCurrentCount = m_FieldInfo.Count();
  92. for ( int i = 0; i < nCurrentCount; ++i )
  93. {
  94. m_FieldInfo[i].m_pIndexData = NULL;
  95. m_FieldInfo[i].m_pVertexData = NULL;
  96. }
  97. // FIXME: Want to maintain field indices as constants for all time
  98. int nFieldCount = m_VertexFormat.Count();
  99. for ( int i = 0; i < nFieldCount; ++i )
  100. {
  101. const char *pFieldName = m_VertexFormat[i];
  102. int nLen = Q_strlen( pFieldName ) + 21;
  103. char *pIndicesName = (char*)_alloca( nLen );
  104. Q_snprintf( pIndicesName, nLen, "%sIndices", pFieldName );
  105. CDmAttribute *pVerticesArray = GetAttribute( pFieldName );
  106. if ( !pVerticesArray || !IsArrayType( pVerticesArray->GetType() ) )
  107. continue;
  108. CDmAttribute *pIndicesArray = NULL;
  109. if ( Q_stricmp( pFieldName, g_pStandardFieldNames[FIELD_JOINT_WEIGHTS] ) &&
  110. Q_stricmp( pFieldName, g_pStandardFieldNames[FIELD_JOINT_INDICES] ) )
  111. {
  112. pIndicesArray = GetAttribute( pIndicesName );
  113. if ( !pIndicesArray || pIndicesArray->GetType() != AT_INT_ARRAY )
  114. continue;
  115. }
  116. FieldIndex_t nFieldIndex = FindFieldIndex( pFieldName );
  117. if ( nFieldIndex < 0 )
  118. {
  119. nFieldIndex = m_FieldInfo.AddToTail();
  120. m_FieldInfo[nFieldIndex].m_Name = pFieldName;
  121. m_FieldInfo[nFieldIndex].m_bInverseMapDirty = true;
  122. UpdateStandardFieldInfo( nFieldIndex, pFieldName, pVerticesArray->GetType() );
  123. }
  124. m_FieldInfo[nFieldIndex].m_pVertexData = pVerticesArray;
  125. m_FieldInfo[nFieldIndex].m_pIndexData = pIndicesArray;
  126. }
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Computes the vertex count ( min of the index buffers )
  130. //-----------------------------------------------------------------------------
  131. void CDmeVertexDataBase::ComputeVertexCount()
  132. {
  133. int nCount = m_FieldInfo.Count();
  134. if ( nCount == 0 )
  135. {
  136. m_nVertexCount = 0;
  137. return;
  138. }
  139. m_nVertexCount = INT_MAX;
  140. for ( int i = 0; i < nCount; ++i )
  141. {
  142. if ( !m_FieldInfo[i].m_pIndexData )
  143. continue;
  144. CDmrGenericArray array( m_FieldInfo[i].m_pIndexData );
  145. int nFieldCount = array.Count();
  146. if ( nFieldCount < m_nVertexCount )
  147. {
  148. m_nVertexCount = nFieldCount;
  149. }
  150. }
  151. }
  152. //-----------------------------------------------------------------------------
  153. // resolve internal data from changed attributes
  154. //-----------------------------------------------------------------------------
  155. void CDmeVertexDataBase::Resolve()
  156. {
  157. BaseClass::Resolve();
  158. if ( m_VertexFormat.IsDirty() )
  159. {
  160. ComputeFieldInfo();
  161. }
  162. if ( !IsVertexDeltaData() )
  163. {
  164. ComputeVertexCount();
  165. }
  166. // Mark inverse map dirty if necessary
  167. int nCount = m_FieldInfo.Count();
  168. for ( int i = 0; i < nCount; ++i )
  169. {
  170. if ( m_FieldInfo[i].m_pIndexData && m_FieldInfo[i].m_pIndexData->IsFlagSet( FATTRIB_DIRTY ) )
  171. {
  172. m_FieldInfo[i].m_bInverseMapDirty = true;
  173. }
  174. }
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Returns indices into the various fields
  178. //-----------------------------------------------------------------------------
  179. int CDmeVertexDataBase::GetPositionIndex( int nVertexIndex ) const
  180. {
  181. return GetFieldIndex( nVertexIndex, FIELD_POSITION );
  182. }
  183. int CDmeVertexDataBase::GetNormalIndex( int nVertexIndex ) const
  184. {
  185. return GetFieldIndex( nVertexIndex, FIELD_NORMAL );
  186. }
  187. int CDmeVertexDataBase::GetTangentIndex( int nVertexIndex ) const
  188. {
  189. return GetFieldIndex( nVertexIndex, FIELD_TANGENT );
  190. }
  191. int CDmeVertexDataBase::GetTexCoordIndex( int nVertexIndex ) const
  192. {
  193. return GetFieldIndex( nVertexIndex, FIELD_TEXCOORD );
  194. }
  195. int CDmeVertexDataBase::GetColorIndex( int nVertexIndex ) const
  196. {
  197. return GetFieldIndex( nVertexIndex, FIELD_COLOR );
  198. }
  199. int CDmeVertexDataBase::GetBalanceIndex( int nVertexIndex ) const
  200. {
  201. return GetFieldIndex( nVertexIndex, FIELD_BALANCE );
  202. }
  203. int CDmeVertexDataBase::GetMorphSpeedIndex( int nVertexIndex ) const
  204. {
  205. return GetFieldIndex( nVertexIndex, FIELD_MORPH_SPEED );
  206. }
  207. int CDmeVertexDataBase::GetWrinkleIndex( int nVertexIndex ) const
  208. {
  209. return GetFieldIndex( nVertexIndex, FIELD_WRINKLE );
  210. }
  211. int CDmeVertexDataBase::GetWeightIndex( int nVertexIndex ) const
  212. {
  213. return GetFieldIndex( nVertexIndex, FIELD_WEIGHT );
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Vertex accessors
  217. //-----------------------------------------------------------------------------
  218. const Vector& CDmeVertexDataBase::GetPosition( int nIndex ) const
  219. {
  220. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  221. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_POSITION];
  222. if ( nFieldIndex < 0 )
  223. return vec3_origin;
  224. CDmrArrayConst<int> indices( GetIndexData( nFieldIndex ) );
  225. CDmrArrayConst<Vector> vertexData( GetVertexData( nFieldIndex ) );
  226. return vertexData[ indices[nIndex] ];
  227. }
  228. const float *CDmeVertexDataBase::GetJointWeights( int nVertexIndex ) const
  229. {
  230. Assert( IsVertexDeltaData() || nVertexIndex < m_nVertexCount );
  231. FieldIndex_t nPosFieldIndex = m_pStandardFieldIndex[FIELD_POSITION];
  232. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_JOINT_WEIGHTS];
  233. if ( nPosFieldIndex < 0 || nFieldIndex < 0 )
  234. return NULL;
  235. CDmrArrayConst<int> indices = GetIndexData( nPosFieldIndex );
  236. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  237. return &vertexData[ indices[ nVertexIndex ] * m_nJointCount ];
  238. }
  239. //-----------------------------------------------------------------------------
  240. // Same as GetJointWeights except it uses a direct position index instead of
  241. // the vertex index to access the data
  242. //-----------------------------------------------------------------------------
  243. const float *CDmeVertexDataBase::GetJointPositionWeights( int nPositionIndex ) const
  244. {
  245. Assert( !IsVertexDeltaData() );
  246. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_JOINT_WEIGHTS];
  247. if ( nFieldIndex < 0 )
  248. return NULL;
  249. CDmrArrayConst< float > jointWeights = GetVertexData( nFieldIndex );
  250. Assert( nPositionIndex * m_nJointCount < jointWeights.Count() );
  251. return &jointWeights[ nPositionIndex * m_nJointCount ];
  252. }
  253. const int *CDmeVertexDataBase::GetJointIndices( int nVertexIndex ) const
  254. {
  255. Assert( IsVertexDeltaData() || nVertexIndex < m_nVertexCount );
  256. FieldIndex_t nPosFieldIndex = m_pStandardFieldIndex[FIELD_POSITION];
  257. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_JOINT_INDICES];
  258. if ( nPosFieldIndex < 0 || nFieldIndex < 0 )
  259. return NULL;
  260. CDmrArrayConst<int> indices = GetIndexData( nPosFieldIndex );
  261. CDmrArrayConst<int> vertexData = GetVertexData( nFieldIndex );
  262. return &vertexData[ indices[ nVertexIndex ] * m_nJointCount ];
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Same as GetJointIndices except it uses a direct position index instead of
  266. // the vertex index to access the data
  267. //-----------------------------------------------------------------------------
  268. const int *CDmeVertexDataBase::GetJointPositionIndices( int nPositionIndex ) const
  269. {
  270. Assert( !IsVertexDeltaData() );
  271. FieldIndex_t nJointIndicesField = m_pStandardFieldIndex[ FIELD_JOINT_INDICES ];
  272. if ( nJointIndicesField < 0 )
  273. return NULL;
  274. CDmrArrayConst<int> jointIndices = GetVertexData( nJointIndicesField );
  275. Assert( nPositionIndex * m_nJointCount < jointIndices.Count() );
  276. return &jointIndices[ nPositionIndex * m_nJointCount ];
  277. }
  278. const Vector& CDmeVertexDataBase::GetNormal( int nIndex ) const
  279. {
  280. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  281. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_NORMAL];
  282. if ( nFieldIndex < 0 )
  283. return vec3_origin;
  284. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  285. CDmrArrayConst<Vector> vertexData = GetVertexData( nFieldIndex );
  286. return vertexData[ indices[ nIndex ] ];
  287. }
  288. const Vector4D& CDmeVertexDataBase::GetTangent( int nIndex ) const
  289. {
  290. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  291. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_TANGENT];
  292. if ( nFieldIndex < 0 )
  293. return vec4_origin;
  294. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  295. CDmrArrayConst<Vector4D> vertexData = GetVertexData( nFieldIndex );
  296. return vertexData[ indices[ nIndex ] ];
  297. }
  298. const Vector2D& CDmeVertexDataBase::GetTexCoord( int nIndex ) const
  299. {
  300. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  301. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_TEXCOORD];
  302. if ( nFieldIndex < 0 )
  303. return vec2_origin;
  304. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  305. CDmrArrayConst<Vector2D> vertexData = GetVertexData( nFieldIndex );
  306. return vertexData[ indices[ nIndex ] ];
  307. }
  308. static Color s_Black( 0, 0, 0, 255 );
  309. const Color& CDmeVertexDataBase::GetColor( int nIndex ) const
  310. {
  311. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  312. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_COLOR];
  313. if ( nFieldIndex < 0 )
  314. return s_Black;
  315. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  316. CDmrArrayConst<Color> vertexData = GetVertexData( nFieldIndex );
  317. return vertexData[ indices[ nIndex ] ];
  318. }
  319. float CDmeVertexDataBase::GetBalance( int nIndex ) const
  320. {
  321. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  322. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_BALANCE];
  323. if ( nFieldIndex < 0 )
  324. return 0.5f;
  325. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  326. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  327. return vertexData[ indices[ nIndex ] ];
  328. }
  329. float CDmeVertexDataBase::GetMorphSpeed( int nIndex ) const
  330. {
  331. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  332. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_MORPH_SPEED];
  333. if ( nFieldIndex < 0 )
  334. return 1.0f;
  335. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  336. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  337. return vertexData[ indices[ nIndex ] ];
  338. }
  339. float CDmeVertexDataBase::GetWrinkle( int nIndex ) const
  340. {
  341. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  342. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_WRINKLE];
  343. if ( nFieldIndex < 0 )
  344. return 1.0f;
  345. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  346. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  347. return vertexData[ indices[ nIndex ] ];
  348. }
  349. //-----------------------------------------------------------------------------
  350. //
  351. //-----------------------------------------------------------------------------
  352. float CDmeVertexDataBase::GetWeight( int nIndex ) const
  353. {
  354. Assert( IsVertexDeltaData() || nIndex < m_nVertexCount );
  355. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_WEIGHT];
  356. if ( nFieldIndex < 0 )
  357. return 1.0f;
  358. CDmrArrayConst<int> indices = GetIndexData( nFieldIndex );
  359. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  360. return vertexData[ indices[ nIndex ] ];
  361. }
  362. //-----------------------------------------------------------------------------
  363. // Adds a field to the vertex format
  364. //-----------------------------------------------------------------------------
  365. void CDmeVertexDataBase::FindOrAddVertexField( const char *pFieldName )
  366. {
  367. int i;
  368. int nFormatCount = m_VertexFormat.Count();
  369. for ( i = 0; i < nFormatCount; ++i )
  370. {
  371. if ( !Q_stricmp( pFieldName, m_VertexFormat[i] ) )
  372. return;
  373. }
  374. m_VertexFormat.AddToTail( pFieldName );
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Returns the field index of a particular field
  378. //-----------------------------------------------------------------------------
  379. FieldIndex_t CDmeVertexDataBase::CreateField( const char *pFieldName, DmAttributeType_t type )
  380. {
  381. Assert( Q_stricmp( pFieldName, g_pStandardFieldNames[FIELD_JOINT_WEIGHTS] ) );
  382. Assert( Q_stricmp( pFieldName, g_pStandardFieldNames[FIELD_JOINT_INDICES] ) );
  383. if ( !Q_stricmp( pFieldName, g_pStandardFieldNames[FIELD_JOINT_WEIGHTS] ) ||
  384. !Q_stricmp( pFieldName, g_pStandardFieldNames[FIELD_JOINT_INDICES] ) )
  385. {
  386. return -1;
  387. }
  388. AddAttribute( pFieldName, type );
  389. int nLen = Q_strlen( pFieldName ) + 21;
  390. char *pIndicesName = (char*)_alloca( nLen );
  391. Q_snprintf( pIndicesName, nLen, "%sIndices", pFieldName );
  392. AddAttribute( pIndicesName, AT_INT_ARRAY );
  393. FindOrAddVertexField( pFieldName );
  394. // FIXME: Not hugely efficient, is there a better way of doing this?
  395. // Necessary to return a field index for the name
  396. ComputeFieldInfo();
  397. FieldIndex_t nFieldIndex = FindFieldIndex( pFieldName );
  398. if ( !IsVertexDeltaData() && m_nVertexCount > 0 )
  399. {
  400. CDmrArray<int> indices( GetIndexData( nFieldIndex ) );
  401. indices.EnsureCount( m_nVertexCount );
  402. }
  403. return nFieldIndex;
  404. }
  405. //-----------------------------------------------------------------------------
  406. // Creates a field given a file ID
  407. //-----------------------------------------------------------------------------
  408. FieldIndex_t CDmeVertexDataBase::CreateField( StandardFields_t fieldId )
  409. {
  410. return CreateField( g_pStandardFieldNames[fieldId], g_pStandardFieldTypes[fieldId] );
  411. }
  412. //-----------------------------------------------------------------------------
  413. // Use this to create vertex fields for joint weights + indices
  414. //-----------------------------------------------------------------------------
  415. void CDmeVertexDataBase::CreateJointWeightsAndIndices( int nJointCount, FieldIndex_t *pJointWeightsField, FieldIndex_t *pJointIndicesField )
  416. {
  417. m_nJointCount = nJointCount;
  418. AddAttribute( g_pStandardFieldNames[FIELD_JOINT_WEIGHTS], AT_FLOAT_ARRAY );
  419. AddAttribute( g_pStandardFieldNames[FIELD_JOINT_INDICES], AT_INT_ARRAY );
  420. FindOrAddVertexField( g_pStandardFieldNames[FIELD_JOINT_WEIGHTS] );
  421. FindOrAddVertexField( g_pStandardFieldNames[FIELD_JOINT_INDICES] );
  422. // FIXME: Not hugely efficient, is there a better way of doing this?
  423. // Necessary to return a field index for the name
  424. ComputeFieldInfo();
  425. *pJointWeightsField = FindFieldIndex( g_pStandardFieldNames[FIELD_JOINT_WEIGHTS] );
  426. *pJointIndicesField = FindFieldIndex( g_pStandardFieldNames[FIELD_JOINT_INDICES] );
  427. }
  428. //-----------------------------------------------------------------------------
  429. // Adds a new vertex; creates a new entry in all vertex data fields
  430. // Returns the vertex index
  431. //-----------------------------------------------------------------------------
  432. int CDmeVertexDataBase::AddVertexData( FieldIndex_t nFieldIndex, int nCount )
  433. {
  434. CDmrGenericArray array( m_FieldInfo[nFieldIndex].m_pVertexData );
  435. int nDataCount = array.Count();
  436. array.EnsureCount( nDataCount + nCount );
  437. // DmeMeshDeltaData must have the same number of vertices + indices
  438. if ( IsVertexDeltaData() )
  439. {
  440. CDmrArray<int> indices( GetIndexData( nFieldIndex ) );
  441. Assert( nDataCount == indices.Count() );
  442. indices.EnsureCount( nDataCount + nCount );
  443. }
  444. return nDataCount;
  445. }
  446. //-----------------------------------------------------------------------------
  447. // Sets vertex data
  448. //-----------------------------------------------------------------------------
  449. void CDmeVertexDataBase::SetVertexData( FieldIndex_t nFieldIndex, int nFirstVertex, int nCount, DmAttributeType_t valueType, const void *pData )
  450. {
  451. CDmrGenericArray array( m_FieldInfo[nFieldIndex].m_pVertexData );
  452. Assert( nFirstVertex + nCount <= array.Count() );
  453. array.SetMultiple( nFirstVertex, nCount, valueType, pData );
  454. }
  455. void CDmeVertexDataBase::SetVertexIndices( FieldIndex_t nFieldIndex, int nFirstIndex, int nCount, const int *pIndices )
  456. {
  457. CDmrArray<int> array( GetIndexData( nFieldIndex ) );
  458. Assert( nFirstIndex + nCount <= array.Count() );
  459. array.SetMultiple( nFirstIndex, nCount, pIndices );
  460. }
  461. //-----------------------------------------------------------------------------
  462. // Removes all vertex data associated with a particular field
  463. //-----------------------------------------------------------------------------
  464. void CDmeVertexDataBase::RemoveAllVertexData( FieldIndex_t nFieldIndex )
  465. {
  466. CDmrGenericArray array( m_FieldInfo[nFieldIndex].m_pVertexData );
  467. array.RemoveAll();
  468. if ( IsVertexDeltaData() )
  469. {
  470. CDmrArray<int> arrayDelta( m_FieldInfo[nFieldIndex].m_pIndexData );
  471. arrayDelta.RemoveAll();
  472. }
  473. }
  474. //-----------------------------------------------------------------------------
  475. // Returns the field index of a particular field
  476. //-----------------------------------------------------------------------------
  477. FieldIndex_t CDmeVertexDataBase::FindFieldIndex( const char *pFieldName ) const
  478. {
  479. int nCount = m_FieldInfo.Count();
  480. for ( int i = 0; i < nCount; ++i )
  481. {
  482. if ( !Q_stricmp( m_FieldInfo[i].m_Name, pFieldName ) )
  483. return i;
  484. }
  485. return -1;
  486. }
  487. //-----------------------------------------------------------------------------
  488. // Returns well-known vertex data
  489. //-----------------------------------------------------------------------------
  490. static CUtlVector<Vector4D> s_EmptyVector4D;
  491. static CUtlVector<Vector> s_EmptyVector;
  492. static CUtlVector<Vector2D> s_EmptyVector2D;
  493. static CUtlVector<Color> s_EmptyColor;
  494. static CUtlVector<float> s_EmptyFloat;
  495. const CUtlVector<Vector> &CDmeVertexDataBase::GetPositionData( ) const
  496. {
  497. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_POSITION ];
  498. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  499. return s_EmptyVector;
  500. CDmrArrayConst<Vector> vertexData = GetVertexData( nFieldIndex );
  501. return vertexData.Get();
  502. }
  503. const CUtlVector<Vector> &CDmeVertexDataBase::GetNormalData( ) const
  504. {
  505. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_NORMAL ];
  506. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  507. return s_EmptyVector;
  508. CDmrArrayConst<Vector> vertexData = GetVertexData( nFieldIndex );
  509. return vertexData.Get();
  510. }
  511. const CUtlVector<Vector4D> &CDmeVertexDataBase::GetTangentData( ) const
  512. {
  513. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_TANGENT ];
  514. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  515. return s_EmptyVector4D;
  516. CDmrArrayConst<Vector4D> vertexData = GetVertexData( nFieldIndex );
  517. return vertexData.Get();
  518. }
  519. const CUtlVector<Vector2D> &CDmeVertexDataBase::GetTextureCoordData( ) const
  520. {
  521. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_TEXCOORD ];
  522. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  523. return s_EmptyVector2D;
  524. CDmrArrayConst<Vector2D> vertexData = GetVertexData( nFieldIndex );
  525. return vertexData.Get();
  526. }
  527. const CUtlVector<Color> &CDmeVertexDataBase::GetColorData( ) const
  528. {
  529. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_COLOR ];
  530. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  531. return s_EmptyColor;
  532. CDmrArrayConst<Color> vertexData = GetVertexData( nFieldIndex );
  533. return vertexData.Get();
  534. }
  535. const float *CDmeVertexDataBase::GetJointWeightData( int nDataIndex ) const
  536. {
  537. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_JOINT_WEIGHTS];
  538. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  539. return NULL;
  540. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  541. return &vertexData[ nDataIndex * m_nJointCount ];
  542. }
  543. const int *CDmeVertexDataBase::GetJointIndexData( int nDataIndex ) const
  544. {
  545. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[FIELD_JOINT_INDICES];
  546. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  547. return NULL;
  548. CDmrArrayConst<int> vertexData = GetVertexData( nFieldIndex );
  549. return &vertexData.Element( nDataIndex * m_nJointCount );
  550. }
  551. const CUtlVector<float> &CDmeVertexDataBase::GetBalanceData( ) const
  552. {
  553. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_BALANCE ];
  554. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  555. return s_EmptyFloat;
  556. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  557. return vertexData.Get();
  558. }
  559. const CUtlVector<float> &CDmeVertexDataBase::GetMorphSpeedData( ) const
  560. {
  561. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_MORPH_SPEED ];
  562. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  563. return s_EmptyFloat;
  564. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  565. return vertexData.Get();
  566. }
  567. const CUtlVector<float> &CDmeVertexDataBase::GetWrinkleData( ) const
  568. {
  569. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_WRINKLE ];
  570. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  571. return s_EmptyFloat;
  572. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  573. return vertexData.Get();
  574. }
  575. const CUtlVector<float> &CDmeVertexDataBase::GetWeightData( ) const
  576. {
  577. FieldIndex_t nFieldIndex = m_pStandardFieldIndex[ FIELD_WEIGHT ];
  578. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  579. return s_EmptyFloat;
  580. CDmrArrayConst<float> vertexData = GetVertexData( nFieldIndex );
  581. return vertexData.Get();
  582. }
  583. //-----------------------------------------------------------------------------
  584. // Returns well-known index data
  585. //-----------------------------------------------------------------------------
  586. static CUtlVector<int> s_EmptyInt;
  587. const CUtlVector<int> &CDmeVertexDataBase::GetVertexIndexData( FieldIndex_t nFieldIndex ) const
  588. {
  589. if ( nFieldIndex < 0 || nFieldIndex >= m_FieldInfo.Count() )
  590. return s_EmptyInt;
  591. CDmrArrayConst<int> indexData = GetIndexData( nFieldIndex );
  592. return indexData.Get();
  593. }
  594. const CUtlVector<int> &CDmeVertexDataBase::GetVertexIndexData( StandardFields_t fieldId ) const
  595. {
  596. return GetVertexIndexData( m_pStandardFieldIndex[fieldId] );
  597. }
  598. //-----------------------------------------------------------------------------
  599. // Returns an inverse map from vertex data index to vertex index
  600. //-----------------------------------------------------------------------------
  601. const CUtlVector< int > &CDmeVertexDataBase::FindVertexIndicesFromDataIndex( FieldIndex_t nFieldIndex, int nDataIndex )
  602. {
  603. if ( nFieldIndex < 0 )
  604. return s_EmptyInt;
  605. FieldInfo_t &info = m_FieldInfo[nFieldIndex];
  606. if ( info.m_bInverseMapDirty )
  607. {
  608. CDmrArrayConst<int> array( info.m_pIndexData );
  609. CDmrGenericArray vertexArray( info.m_pVertexData );
  610. int nDataCount = vertexArray.Count();
  611. int nCount = array.Count();
  612. // Clear out the utlvectors
  613. info.m_InverseMap.RemoveAll();
  614. info.m_InverseMap.SetCount( nDataCount );
  615. for ( int i = 0; i < nCount; ++i )
  616. {
  617. int nIndex = array[ i ];
  618. info.m_InverseMap[nIndex].AddToTail( i );
  619. }
  620. info.m_bInverseMapDirty = false;
  621. }
  622. return info.m_InverseMap[ nDataIndex ];
  623. }
  624. const CUtlVector< int > &CDmeVertexDataBase::FindVertexIndicesFromDataIndex( StandardFields_t fieldId, int nDataIndex )
  625. {
  626. // NOTE! Wrinkles don't exist in the base state, therefore we use the index to index
  627. // into the TEXCOORD base state fields instead of the wrinkle fields
  628. if ( fieldId == FIELD_WRINKLE )
  629. {
  630. fieldId = FIELD_TEXCOORD;
  631. }
  632. return FindVertexIndicesFromDataIndex( m_pStandardFieldIndex[fieldId], nDataIndex );
  633. }
  634. //-----------------------------------------------------------------------------
  635. // Do we have skinning data?
  636. //-----------------------------------------------------------------------------
  637. bool CDmeVertexDataBase::HasSkinningData() const
  638. {
  639. if ( m_nJointCount == 0 )
  640. return false;
  641. FieldIndex_t nWeightFieldIndex = m_pStandardFieldIndex[FIELD_JOINT_WEIGHTS];
  642. if ( nWeightFieldIndex < 0 )
  643. return false;
  644. FieldIndex_t nIndexFieldIndex = m_pStandardFieldIndex[FIELD_JOINT_INDICES];
  645. if ( nIndexFieldIndex < 0 )
  646. return false;
  647. CDmrArrayConst<float> weightData = GetVertexData( nWeightFieldIndex );
  648. CDmrArrayConst<int> indexData = GetVertexData( nIndexFieldIndex );
  649. return ( weightData.Count() > 0 && indexData.Count() > 0 );
  650. }
  651. //-----------------------------------------------------------------------------
  652. // Do we need tangent data? (Utility method for applications to know if they should call ComputeDefaultTangentData)
  653. //-----------------------------------------------------------------------------
  654. bool CDmeVertexDataBase::NeedsTangentData() const
  655. {
  656. FieldIndex_t posField = m_pStandardFieldIndex[CDmeVertexDataBase::FIELD_POSITION];
  657. FieldIndex_t normalField = m_pStandardFieldIndex[CDmeVertexDataBase::FIELD_NORMAL];
  658. FieldIndex_t uvField = m_pStandardFieldIndex[CDmeVertexDataBase::FIELD_TEXCOORD];
  659. FieldIndex_t tangentField = m_pStandardFieldIndex[CDmeVertexDataBase::FIELD_TANGENT];
  660. return ( posField >= 0 && uvField >= 0 && normalField >= 0 && tangentField < 0 );
  661. }
  662. //-----------------------------------------------------------------------------
  663. //
  664. //-----------------------------------------------------------------------------
  665. int CDmeVertexDataBase::FieldCount() const
  666. {
  667. return m_VertexFormat.Count();
  668. }
  669. //-----------------------------------------------------------------------------
  670. //
  671. //-----------------------------------------------------------------------------
  672. const char *CDmeVertexDataBase::FieldName( int i ) const
  673. {
  674. if ( i < 0 || i >= m_VertexFormat.Count() )
  675. return NULL;
  676. return m_VertexFormat[ i ];
  677. }
  678. //-----------------------------------------------------------------------------
  679. //
  680. //-----------------------------------------------------------------------------
  681. void CDmeVertexDataBase::CopyFrom( CDmeVertexDataBase *pSrc )
  682. {
  683. pSrc->CopyTo( this );
  684. }
  685. //-----------------------------------------------------------------------------
  686. //
  687. //-----------------------------------------------------------------------------
  688. void CDmeVertexDataBase::CopyTo( CDmeVertexDataBase *pDst ) const
  689. {
  690. // Preserve the name of the destination
  691. const CUtlString dstName = pDst->GetName();
  692. CopyAttributesTo( pDst );
  693. pDst->SetName( dstName ); // The Copy really copies everything!
  694. pDst->Resolve();
  695. }
  696. //-----------------------------------------------------------------------------
  697. // Expose this class to the scene database
  698. //-----------------------------------------------------------------------------
  699. IMPLEMENT_ELEMENT_FACTORY( DmeVertexData, CDmeVertexData );
  700. IMPLEMENT_ELEMENT_FACTORY( DmeVertexDeltaData, CDmeVertexDeltaData );
  701. //-----------------------------------------------------------------------------
  702. // Purpose:
  703. //-----------------------------------------------------------------------------
  704. void CDmeVertexData::OnConstruction()
  705. {
  706. }
  707. void CDmeVertexData::OnDestruction()
  708. {
  709. }
  710. void CDmeVertexDeltaData::OnConstruction()
  711. {
  712. m_bCorrected.InitAndSet( this, "corrected", false );
  713. }
  714. void CDmeVertexDeltaData::OnDestruction()
  715. {
  716. }
  717. //-----------------------------------------------------------------------------
  718. // Method to add vertex indices for normal vertex data
  719. //-----------------------------------------------------------------------------
  720. int CDmeVertexData::AddVertexIndices( int nIndexCount )
  721. {
  722. int nFirstVertex = m_nVertexCount;
  723. m_nVertexCount += nIndexCount;
  724. int nCount = m_FieldInfo.Count();
  725. for ( int i = 0; i < nCount; ++i )
  726. {
  727. if ( m_FieldInfo[i].m_pIndexData )
  728. {
  729. CDmrArray<int> indices( m_FieldInfo[i].m_pIndexData );
  730. indices.EnsureCount( m_nVertexCount );
  731. }
  732. }
  733. return nFirstVertex;
  734. }
  735. //-----------------------------------------------------------------------------
  736. // Computes max positional delta length
  737. //-----------------------------------------------------------------------------
  738. float CDmeVertexDeltaData::ComputeMaxDeflection( )
  739. {
  740. float flMaxDeflection = 0.0f;
  741. const CUtlVector<Vector> &pos = GetPositionData();
  742. int nCount = pos.Count();
  743. for ( int i = 0; i < nCount; ++i )
  744. {
  745. float flDeflection = pos[i].Length();
  746. if ( flMaxDeflection < flDeflection )
  747. {
  748. flMaxDeflection = flDeflection;
  749. }
  750. }
  751. return flMaxDeflection;
  752. }
  753. //-----------------------------------------------------------------------------
  754. // Computes wrinkle data from position deltas
  755. //-----------------------------------------------------------------------------
  756. void CDmeVertexDeltaData::GenerateWrinkleDelta( CDmeVertexData *pBindState, float flScale, bool bOverwrite )
  757. {
  758. FieldIndex_t nPosIndex = FindFieldIndex( FIELD_POSITION );
  759. if ( nPosIndex < 0 )
  760. return;
  761. FieldIndex_t nBaseTexCoordIndex = pBindState->FindFieldIndex( FIELD_TEXCOORD );
  762. if ( nBaseTexCoordIndex < 0 )
  763. return;
  764. FieldIndex_t nWrinkleIndex = FindFieldIndex( FIELD_WRINKLE );
  765. if ( nWrinkleIndex < 0 )
  766. {
  767. nWrinkleIndex = CreateField( FIELD_WRINKLE );
  768. }
  769. else if ( !bOverwrite )
  770. return;
  771. RemoveAllVertexData( nWrinkleIndex );
  772. if ( flScale == 0.0f )
  773. return;
  774. const float flMaxDeflection( ComputeMaxDeflection() );
  775. if ( flMaxDeflection == 0.0f )
  776. return;
  777. const double scaledInverseMaxDeflection = static_cast< double >( flScale ) / static_cast< double >( flMaxDeflection );
  778. const CUtlVector<int> &positionIndices = GetVertexIndexData( nPosIndex );
  779. const CUtlVector<Vector> &pos = GetPositionData();
  780. const CUtlVector<int> &baseTexCoordIndices = pBindState->GetVertexIndexData( nBaseTexCoordIndex );
  781. CDmrArrayConst<Vector2D> texData( pBindState->GetVertexData( nBaseTexCoordIndex ) );
  782. int nBaseTexCoordCount = texData.Count();
  783. int nBufSize = ( ( nBaseTexCoordCount + 7 ) >> 3 );
  784. unsigned char *pUsedBits = (unsigned char*)_alloca( nBufSize );
  785. memset( pUsedBits, 0, nBufSize );
  786. int nCount = pos.Count();
  787. for ( int i = 0; i < nCount; ++i )
  788. {
  789. float flWrinkleDelta = static_cast< float >( static_cast< double >( pos[i].Length() ) * scaledInverseMaxDeflection );
  790. Assert( fabs( flWrinkleDelta ) <= fabs( flScale ) );
  791. // NOTE: This will produce bad behavior in cases where two positions share the
  792. // same texcoord, which shouldn't theoretically happen.
  793. const CUtlVector< int > &baseVerts = pBindState->FindVertexIndicesFromDataIndex( FIELD_POSITION, positionIndices[i] );
  794. int nBaseVertCount = baseVerts.Count();
  795. for ( int j = 0; j < nBaseVertCount; ++j )
  796. {
  797. // See if we have a delta for this texcoord...
  798. int nTexCoordIndex = baseTexCoordIndices[ baseVerts[j] ];
  799. if ( pUsedBits[ nTexCoordIndex >> 3 ] & ( 1 << ( nTexCoordIndex & 0x7 ) ) )
  800. continue;
  801. pUsedBits[ nTexCoordIndex >> 3 ] |= 1 << ( nTexCoordIndex & 0x7 );
  802. int nDeltaIndex = AddVertexData( nWrinkleIndex, 1 );
  803. SetVertexIndices( nWrinkleIndex, nDeltaIndex, 1, &nTexCoordIndex );
  804. SetVertexData( nWrinkleIndex, nDeltaIndex, 1, AT_FLOAT, &flWrinkleDelta );
  805. }
  806. }
  807. }
  808. //-----------------------------------------------------------------------------
  809. // Computes weight data from position deltas
  810. //-----------------------------------------------------------------------------
  811. float CDmeVertexDeltaData::GenerateWeightDelta( CDmeVertexData *pBindState )
  812. {
  813. FieldIndex_t nPosIndex = FindFieldIndex( FIELD_POSITION );
  814. if ( nPosIndex < 0 )
  815. return 0.0;
  816. FieldIndex_t nFieldIndex = FindFieldIndex( FIELD_WEIGHT );
  817. if ( nFieldIndex < 0 )
  818. {
  819. nFieldIndex = CreateField( FIELD_WEIGHT );
  820. }
  821. RemoveAllVertexData( nFieldIndex );
  822. const float maxDeflection( static_cast< double >( ComputeMaxDeflection() ) );
  823. if ( maxDeflection == 0.0 )
  824. return maxDeflection;
  825. const CUtlVector<Vector> &pos( GetPositionData() );
  826. const CUtlVector< int > &posIndices( GetVertexIndexData( nPosIndex ) );
  827. float flDeltaDistance;
  828. int nDeltaIndex;
  829. const int nCount = pos.Count();
  830. for ( int i = 0; i < nCount; ++i )
  831. {
  832. flDeltaDistance = pos[ i ].Length();
  833. nDeltaIndex = AddVertexData( nFieldIndex, 1 );
  834. SetVertexData( nFieldIndex, nDeltaIndex, 1, AT_FLOAT, &flDeltaDistance );
  835. }
  836. SetVertexIndices( nFieldIndex, 0, posIndices.Count(), posIndices.Base() );
  837. return maxDeflection;
  838. }