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

1220 lines
40 KiB

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