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.

5016 lines
160 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. // Standard includes
  7. #include <limits.h>
  8. // Valve includes
  9. #include "movieobjects/dmemesh.h"
  10. #include "movieobjects/dmevertexdata.h"
  11. #include "movieobjects/dmefaceset.h"
  12. #include "movieobjects/dmematerial.h"
  13. #include "movieobjects/dmetransform.h"
  14. #include "movieobjects/dmemodel.h"
  15. #include "movieobjects_interfaces.h"
  16. #include "movieobjects/dmecombinationoperator.h"
  17. #include "movieobjects/dmeselection.h"
  18. #include "movieobjects/dmedrawsettings.h"
  19. #include "movieobjects/dmmeshcomp.h"
  20. #include "tier3/tier3.h"
  21. #include "tier1/KeyValues.h"
  22. #include "tier0/dbg.h"
  23. #include "datamodel/dmelementfactoryhelper.h"
  24. #include "materialsystem/imaterialsystem.h"
  25. #include "materialsystem/imorph.h"
  26. #include "materialsystem/imesh.h"
  27. #include "materialsystem/imaterialvar.h"
  28. #include "istudiorender.h"
  29. #include "studio.h"
  30. // memdbgon must be the last include file in a .cpp file!!!
  31. #include "tier0/memdbgon.h"
  32. //-----------------------------------------------------------------------------
  33. // Normal rendering materials
  34. //-----------------------------------------------------------------------------
  35. bool CDmeMesh::s_bNormalMaterialInitialized;
  36. CMaterialReference CDmeMesh::s_NormalMaterial;
  37. CMaterialReference CDmeMesh::s_NormalErrorMaterial;
  38. //-----------------------------------------------------------------------------
  39. // Computes a skin matrix
  40. //-----------------------------------------------------------------------------
  41. static const matrix3x4_t *ComputeSkinMatrix( int nBoneCount, const float *pJointWeight, const int *pJointIndices, const matrix3x4_t *pPoseToWorld, matrix3x4_t &result )
  42. {
  43. float flWeight0, flWeight1, flWeight2, flWeight3;
  44. switch( nBoneCount )
  45. {
  46. default:
  47. case 1:
  48. return &pPoseToWorld[pJointIndices[0]];
  49. case 2:
  50. {
  51. const matrix3x4_t &boneMat0 = pPoseToWorld[pJointIndices[0]];
  52. const matrix3x4_t &boneMat1 = pPoseToWorld[pJointIndices[1]];
  53. flWeight0 = pJointWeight[0];
  54. flWeight1 = pJointWeight[1];
  55. // NOTE: Inlining here seems to make a fair amount of difference
  56. result[0][0] = boneMat0[0][0] * flWeight0 + boneMat1[0][0] * flWeight1;
  57. result[0][1] = boneMat0[0][1] * flWeight0 + boneMat1[0][1] * flWeight1;
  58. result[0][2] = boneMat0[0][2] * flWeight0 + boneMat1[0][2] * flWeight1;
  59. result[0][3] = boneMat0[0][3] * flWeight0 + boneMat1[0][3] * flWeight1;
  60. result[1][0] = boneMat0[1][0] * flWeight0 + boneMat1[1][0] * flWeight1;
  61. result[1][1] = boneMat0[1][1] * flWeight0 + boneMat1[1][1] * flWeight1;
  62. result[1][2] = boneMat0[1][2] * flWeight0 + boneMat1[1][2] * flWeight1;
  63. result[1][3] = boneMat0[1][3] * flWeight0 + boneMat1[1][3] * flWeight1;
  64. result[2][0] = boneMat0[2][0] * flWeight0 + boneMat1[2][0] * flWeight1;
  65. result[2][1] = boneMat0[2][1] * flWeight0 + boneMat1[2][1] * flWeight1;
  66. result[2][2] = boneMat0[2][2] * flWeight0 + boneMat1[2][2] * flWeight1;
  67. result[2][3] = boneMat0[2][3] * flWeight0 + boneMat1[2][3] * flWeight1;
  68. }
  69. return &result;
  70. case 3:
  71. {
  72. const matrix3x4_t &boneMat0 = pPoseToWorld[pJointIndices[0]];
  73. const matrix3x4_t &boneMat1 = pPoseToWorld[pJointIndices[1]];
  74. const matrix3x4_t &boneMat2 = pPoseToWorld[pJointIndices[2]];
  75. flWeight0 = pJointWeight[0];
  76. flWeight1 = pJointWeight[1];
  77. flWeight2 = pJointWeight[2];
  78. result[0][0] = boneMat0[0][0] * flWeight0 + boneMat1[0][0] * flWeight1 + boneMat2[0][0] * flWeight2;
  79. result[0][1] = boneMat0[0][1] * flWeight0 + boneMat1[0][1] * flWeight1 + boneMat2[0][1] * flWeight2;
  80. result[0][2] = boneMat0[0][2] * flWeight0 + boneMat1[0][2] * flWeight1 + boneMat2[0][2] * flWeight2;
  81. result[0][3] = boneMat0[0][3] * flWeight0 + boneMat1[0][3] * flWeight1 + boneMat2[0][3] * flWeight2;
  82. result[1][0] = boneMat0[1][0] * flWeight0 + boneMat1[1][0] * flWeight1 + boneMat2[1][0] * flWeight2;
  83. result[1][1] = boneMat0[1][1] * flWeight0 + boneMat1[1][1] * flWeight1 + boneMat2[1][1] * flWeight2;
  84. result[1][2] = boneMat0[1][2] * flWeight0 + boneMat1[1][2] * flWeight1 + boneMat2[1][2] * flWeight2;
  85. result[1][3] = boneMat0[1][3] * flWeight0 + boneMat1[1][3] * flWeight1 + boneMat2[1][3] * flWeight2;
  86. result[2][0] = boneMat0[2][0] * flWeight0 + boneMat1[2][0] * flWeight1 + boneMat2[2][0] * flWeight2;
  87. result[2][1] = boneMat0[2][1] * flWeight0 + boneMat1[2][1] * flWeight1 + boneMat2[2][1] * flWeight2;
  88. result[2][2] = boneMat0[2][2] * flWeight0 + boneMat1[2][2] * flWeight1 + boneMat2[2][2] * flWeight2;
  89. result[2][3] = boneMat0[2][3] * flWeight0 + boneMat1[2][3] * flWeight1 + boneMat2[2][3] * flWeight2;
  90. }
  91. return &result;
  92. case 4:
  93. {
  94. const matrix3x4_t &boneMat0 = pPoseToWorld[pJointIndices[0]];
  95. const matrix3x4_t &boneMat1 = pPoseToWorld[pJointIndices[1]];
  96. const matrix3x4_t &boneMat2 = pPoseToWorld[pJointIndices[2]];
  97. const matrix3x4_t &boneMat3 = pPoseToWorld[pJointIndices[3]];
  98. flWeight0 = pJointWeight[0];
  99. flWeight1 = pJointWeight[1];
  100. flWeight2 = pJointWeight[2];
  101. flWeight3 = pJointWeight[3];
  102. result[0][0] = boneMat0[0][0] * flWeight0 + boneMat1[0][0] * flWeight1 + boneMat2[0][0] * flWeight2 + boneMat3[0][0] * flWeight3;
  103. result[0][1] = boneMat0[0][1] * flWeight0 + boneMat1[0][1] * flWeight1 + boneMat2[0][1] * flWeight2 + boneMat3[0][1] * flWeight3;
  104. result[0][2] = boneMat0[0][2] * flWeight0 + boneMat1[0][2] * flWeight1 + boneMat2[0][2] * flWeight2 + boneMat3[0][2] * flWeight3;
  105. result[0][3] = boneMat0[0][3] * flWeight0 + boneMat1[0][3] * flWeight1 + boneMat2[0][3] * flWeight2 + boneMat3[0][3] * flWeight3;
  106. result[1][0] = boneMat0[1][0] * flWeight0 + boneMat1[1][0] * flWeight1 + boneMat2[1][0] * flWeight2 + boneMat3[1][0] * flWeight3;
  107. result[1][1] = boneMat0[1][1] * flWeight0 + boneMat1[1][1] * flWeight1 + boneMat2[1][1] * flWeight2 + boneMat3[1][1] * flWeight3;
  108. result[1][2] = boneMat0[1][2] * flWeight0 + boneMat1[1][2] * flWeight1 + boneMat2[1][2] * flWeight2 + boneMat3[1][2] * flWeight3;
  109. result[1][3] = boneMat0[1][3] * flWeight0 + boneMat1[1][3] * flWeight1 + boneMat2[1][3] * flWeight2 + boneMat3[1][3] * flWeight3;
  110. result[2][0] = boneMat0[2][0] * flWeight0 + boneMat1[2][0] * flWeight1 + boneMat2[2][0] * flWeight2 + boneMat3[2][0] * flWeight3;
  111. result[2][1] = boneMat0[2][1] * flWeight0 + boneMat1[2][1] * flWeight1 + boneMat2[2][1] * flWeight2 + boneMat3[2][1] * flWeight3;
  112. result[2][2] = boneMat0[2][2] * flWeight0 + boneMat1[2][2] * flWeight1 + boneMat2[2][2] * flWeight2 + boneMat3[2][2] * flWeight3;
  113. result[2][3] = boneMat0[2][3] * flWeight0 + boneMat1[2][3] * flWeight1 + boneMat2[2][3] * flWeight2 + boneMat3[2][3] * flWeight3;
  114. }
  115. return &result;
  116. }
  117. Assert(0);
  118. return NULL;
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Helper class to deal with software skinning
  122. //-----------------------------------------------------------------------------
  123. class CRenderInfo
  124. {
  125. public:
  126. CRenderInfo( const CDmeVertexData *pBaseState );
  127. void ComputeVertex( int vi, const matrix3x4_t *pPoseToWorld, CDmeMesh::RenderVertexDelta_t *pDelta, Vector *pPosition, Vector *pNormal, Vector4D *pTangent );
  128. void ComputeVertex( int vi, const matrix3x4_t *pPoseToWorld, Vector *pDeltaPosition, int nStride, Vector *pPosition );
  129. void ComputePosition( int posIndex, const matrix3x4_t *pPoseToWorld, Vector *pDeltaPosition, Vector *pPosition );
  130. inline bool HasPositionData() const { return m_bHasPositionData; }
  131. inline bool HasNormalData() const { return m_bHasNormalData; }
  132. inline bool HasTangentData() const { return m_bHasTangentData; }
  133. private:
  134. const CUtlVector<int>& m_PositionIndices;
  135. const CUtlVector<Vector>& m_PositionData;
  136. const CUtlVector<int>& m_NormalIndices;
  137. const CUtlVector<Vector>& m_NormalData;
  138. const CUtlVector<int>& m_TangentIndices;
  139. const CUtlVector<Vector4D>& m_TangentData;
  140. const CDmeVertexData *m_pBaseState;
  141. int m_nJointCount;
  142. bool m_bHasPositionData;
  143. bool m_bHasNormalData;
  144. bool m_bHasTangentData;
  145. bool m_bHasSkinningData;
  146. };
  147. //-----------------------------------------------------------------------------
  148. // Constructor
  149. //-----------------------------------------------------------------------------
  150. CRenderInfo::CRenderInfo( const CDmeVertexData *pBaseState ) :
  151. m_PositionIndices( pBaseState->GetVertexIndexData( CDmeVertexData::FIELD_POSITION ) ),
  152. m_PositionData( pBaseState->GetPositionData() ),
  153. m_NormalIndices( pBaseState->GetVertexIndexData( CDmeVertexData::FIELD_NORMAL ) ),
  154. m_NormalData( pBaseState->GetNormalData() ),
  155. m_TangentIndices( pBaseState->GetVertexIndexData( CDmeVertexData::FIELD_TANGENT ) ),
  156. m_TangentData( pBaseState->GetTangentData() )
  157. {
  158. m_pBaseState = pBaseState;
  159. m_bHasPositionData = m_PositionIndices.Count() > 0;
  160. m_bHasNormalData = m_NormalIndices.Count() > 0;
  161. m_bHasTangentData = m_TangentIndices.Count() > 0;
  162. m_nJointCount = pBaseState->JointCount();
  163. m_bHasSkinningData = pBaseState->HasSkinningData() && m_nJointCount > 0;
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Computes where a vertex is
  167. //-----------------------------------------------------------------------------
  168. void CRenderInfo::ComputeVertex( int vi, const matrix3x4_t *pPoseToWorld, Vector *pDeltaPosition, int nDeltaStride, Vector *pPosition )
  169. {
  170. matrix3x4_t result;
  171. Vector vecMorphPosition, vecMorphNormal;
  172. const matrix3x4_t *pSkinMatrix = pPoseToWorld;
  173. if ( m_bHasSkinningData )
  174. {
  175. const float *pJointWeight = m_pBaseState->GetJointWeights( vi );
  176. const int *pJointIndices = m_pBaseState->GetJointIndices( vi );
  177. pSkinMatrix = ComputeSkinMatrix( m_nJointCount, pJointWeight, pJointIndices, pPoseToWorld, result );
  178. }
  179. int pi = m_PositionIndices[ vi ];
  180. const Vector *pPositionData = &m_PositionData[ pi ];
  181. if ( pDeltaPosition )
  182. {
  183. Vector *pDelta = (Vector*)( (unsigned char *)pDeltaPosition + nDeltaStride * pi );
  184. VectorAdd( *pPositionData, *pDelta, vecMorphPosition );
  185. pPositionData = &vecMorphPosition;
  186. }
  187. VectorTransform( *pPositionData, *pSkinMatrix, *pPosition );
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Computes where a vertex is
  191. //-----------------------------------------------------------------------------
  192. void CRenderInfo::ComputePosition( int posIndex, const matrix3x4_t *pPoseToWorld, Vector *pDeltaPosition, Vector *pPosition )
  193. {
  194. matrix3x4_t result;
  195. Vector vecMorphPosition;
  196. const matrix3x4_t *pSkinMatrix = pPoseToWorld;
  197. if ( m_bHasSkinningData )
  198. {
  199. const float *pJointWeight = m_pBaseState->GetJointPositionWeights( posIndex );
  200. const int *pJointIndices = m_pBaseState->GetJointPositionIndices( posIndex );
  201. pSkinMatrix = ComputeSkinMatrix( m_nJointCount, pJointWeight, pJointIndices, pPoseToWorld, result );
  202. }
  203. const Vector *pPositionData = &m_PositionData[ posIndex ];
  204. if ( pDeltaPosition )
  205. {
  206. VectorAdd( *pPositionData, *( pDeltaPosition + posIndex ), vecMorphPosition );
  207. pPositionData = &vecMorphPosition;
  208. }
  209. VectorTransform( *pPositionData, *pSkinMatrix, *( pPosition + posIndex ) );
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Computes where a vertex is
  213. //-----------------------------------------------------------------------------
  214. void CRenderInfo::ComputeVertex( int vi, const matrix3x4_t *pPoseToWorld, CDmeMesh::RenderVertexDelta_t *pDelta, Vector *pPosition, Vector *pNormal, Vector4D *pTangent )
  215. {
  216. matrix3x4_t result;
  217. Vector vecMorphPosition, vecMorphNormal;
  218. const matrix3x4_t *pSkinMatrix = pPoseToWorld;
  219. if ( m_bHasSkinningData )
  220. {
  221. const float *pJointWeight = m_pBaseState->GetJointWeights( vi );
  222. const int *pJointIndices = m_pBaseState->GetJointIndices( vi );
  223. pSkinMatrix = ComputeSkinMatrix( m_nJointCount, pJointWeight, pJointIndices, pPoseToWorld, result );
  224. }
  225. int pi = m_PositionIndices[ vi ];
  226. const Vector *pPositionData = &m_PositionData[ pi ];
  227. if ( pDelta )
  228. {
  229. VectorAdd( *pPositionData, pDelta[ pi ].m_vecDeltaPosition, vecMorphPosition );
  230. pPositionData = &vecMorphPosition;
  231. }
  232. VectorTransform( *pPositionData, *pSkinMatrix, *pPosition );
  233. if ( m_bHasNormalData )
  234. {
  235. int ni = m_NormalIndices[ vi ];
  236. const Vector *pNormalData = &m_NormalData[ ni ];
  237. if ( pDelta )
  238. {
  239. VectorAdd( *pNormalData, pDelta[ni].m_vecDeltaNormal, vecMorphNormal );
  240. pNormalData = &vecMorphNormal;
  241. }
  242. VectorRotate( *pNormalData, *pSkinMatrix, *pNormal );
  243. VectorNormalize( *pNormal );
  244. }
  245. else
  246. {
  247. pNormal->Init( 0.0f, 0.0f, 1.0f );
  248. }
  249. if ( m_bHasTangentData )
  250. {
  251. const Vector4D &tangentData = m_TangentData[ m_TangentIndices[ vi ] ];
  252. VectorRotate( tangentData.AsVector3D(), *pSkinMatrix, pTangent->AsVector3D() );
  253. VectorNormalize( pTangent->AsVector3D() );
  254. pTangent->w = tangentData.w;
  255. }
  256. else
  257. {
  258. pTangent->Init( 1.0f, 0.0f, 0.0f, 1.0f );
  259. }
  260. }
  261. //-----------------------------------------------------------------------------
  262. // Expose this class to the scene database
  263. //-----------------------------------------------------------------------------
  264. IMPLEMENT_ELEMENT_FACTORY( DmeMesh, CDmeMesh );
  265. //-----------------------------------------------------------------------------
  266. // Purpose:
  267. //-----------------------------------------------------------------------------
  268. void CDmeMesh::OnConstruction()
  269. {
  270. m_BindBaseState.Init( this, "bindState" );
  271. m_CurrentBaseState.Init( this, "currentState" );
  272. m_BaseStates.Init( this, "baseStates", FATTRIB_MUSTCOPY );
  273. m_DeltaStates.Init( this, "deltaStates", FATTRIB_MUSTCOPY | FATTRIB_HAS_CALLBACK );
  274. m_FaceSets.Init( this, "faceSets", FATTRIB_MUSTCOPY );
  275. m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL].Init( this, "deltaStateWeights" );
  276. m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED].Init( this, "deltaStateWeightsLagged" );
  277. }
  278. void CDmeMesh::OnDestruction()
  279. {
  280. if ( g_pMaterialSystem )
  281. {
  282. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  283. int nCount = m_hwFaceSets.Count();
  284. for ( int i = 0; i < nCount; ++i )
  285. {
  286. if ( !m_hwFaceSets[i].m_bBuilt )
  287. continue;
  288. if ( m_hwFaceSets[i].m_pMesh )
  289. {
  290. pRenderContext->DestroyStaticMesh( m_hwFaceSets[i].m_pMesh );
  291. }
  292. }
  293. m_hwFaceSets.RemoveAll();
  294. }
  295. DeleteAttributeVarElementArray( m_BaseStates );
  296. DeleteAttributeVarElementArray( m_DeltaStates );
  297. DeleteAttributeVarElementArray( m_FaceSets );
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Initializes the normal material
  301. //-----------------------------------------------------------------------------
  302. void CDmeMesh::InitializeNormalMaterial()
  303. {
  304. if ( !s_bNormalMaterialInitialized )
  305. {
  306. s_bNormalMaterialInitialized = true;
  307. KeyValues *pVMTKeyValues = new KeyValues( "wireframe" );
  308. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  309. pVMTKeyValues->SetInt( "$decal", 1 );
  310. // pVMTKeyValues->SetInt( "$ignorez", 0 );
  311. s_NormalMaterial.Init( "__DmeMeshNormalMaterial", pVMTKeyValues );
  312. pVMTKeyValues = new KeyValues( "unlitgeneric" );
  313. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  314. s_NormalErrorMaterial.Init( "__DmeMeshNormalErrorMaterial", pVMTKeyValues );
  315. }
  316. }
  317. //-----------------------------------------------------------------------------
  318. // resolve internal data from changed attributes
  319. //-----------------------------------------------------------------------------
  320. void CDmeMesh::OnAttributeChanged( CDmAttribute *pAttribute )
  321. {
  322. BaseClass::OnAttributeChanged( pAttribute );
  323. if ( pAttribute == m_DeltaStates.GetAttribute() )
  324. {
  325. int nDeltaStateCount = m_DeltaStates.Count();
  326. for ( int i = 0; i < MESH_DELTA_WEIGHT_TYPE_COUNT; ++i )
  327. {
  328. // Make sure we have the correct number of weights
  329. int nWeightCount = m_DeltaStateWeights[i].Count();
  330. if ( nWeightCount < nDeltaStateCount )
  331. {
  332. for ( int j = nWeightCount; j < nDeltaStateCount; ++j )
  333. {
  334. m_DeltaStateWeights[i].AddToTail( Vector2D( 0.0f, 0.0f ) );
  335. }
  336. }
  337. else if ( nDeltaStateCount > nWeightCount )
  338. {
  339. m_DeltaStateWeights[i].RemoveMultiple( nWeightCount, nWeightCount - nDeltaStateCount );
  340. }
  341. }
  342. }
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Adds deltas into a delta mesh
  346. //-----------------------------------------------------------------------------
  347. template< class T > bool CDmeMesh::AddVertexDelta(
  348. CDmeVertexData *pBaseState,
  349. void *pVertexData, int nStride, CDmeVertexDataBase::StandardFields_t fieldId, int nIndex, bool bDoLag )
  350. {
  351. CDmeVertexDeltaData *pDeltaState = GetDeltaState( nIndex );
  352. if ( !pBaseState || !pDeltaState )
  353. return false;
  354. const FieldIndex_t nBaseFieldIndex = pBaseState->FindFieldIndex( fieldId == CDmeVertexData::FIELD_WRINKLE ? CDmeVertexData::FIELD_TEXCOORD : fieldId );
  355. const FieldIndex_t nDeltaFieldIndex = pDeltaState->FindFieldIndex( fieldId );
  356. if ( nBaseFieldIndex < 0 || nDeltaFieldIndex < 0 )
  357. return false;
  358. const CDmrArray<int> indices = pDeltaState->GetIndexData( nDeltaFieldIndex );
  359. const CDmrArray<T> delta = pDeltaState->GetVertexData( nDeltaFieldIndex );
  360. const int nDeltaCount = indices.Count();
  361. const float flWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][nIndex].x;
  362. const FieldIndex_t nSpeedFieldIndex = pBaseState->FindFieldIndex( CDmeVertexData::FIELD_MORPH_SPEED );
  363. if ( !bDoLag || nSpeedFieldIndex < 0 )
  364. {
  365. for ( int j = 0; j < nDeltaCount; ++j )
  366. {
  367. int nDataIndex = indices.Get( j );
  368. T* pDeltaData = (T*)( (char*)pVertexData + nStride * nDataIndex );
  369. *pDeltaData += delta.Get( j ) * flWeight;
  370. }
  371. return true;
  372. }
  373. const float flLaggedWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][nIndex].x;
  374. const CDmrArrayConst<int> speedIndices = pBaseState->GetIndexData( nSpeedFieldIndex );
  375. const CDmrArrayConst<float> speedDelta = pBaseState->GetVertexData( nSpeedFieldIndex );
  376. for ( int j = 0; j < nDeltaCount; ++j )
  377. {
  378. int nDataIndex = indices.Get( j );
  379. const CUtlVector<int> &list = pBaseState->FindVertexIndicesFromDataIndex( nBaseFieldIndex, nDataIndex );
  380. Assert( list.Count() > 0 );
  381. // FIXME: Average everything in the list.. shouldn't be necessary though
  382. float flSpeed = speedDelta.Get( speedIndices.Get( list[0] ) );
  383. float flActualWeight = Lerp( flSpeed, flLaggedWeight, flWeight );
  384. T* pDeltaData = (T*)( (char*)pVertexData + nStride * nDataIndex );
  385. *pDeltaData += delta.Get( j ) * flActualWeight;
  386. }
  387. return true;
  388. }
  389. //-----------------------------------------------------------------------------
  390. //
  391. //-----------------------------------------------------------------------------
  392. void CDmeMesh::AddTexCoordDelta( RenderVertexDelta_t *pRenderDelta, float flWeight, CDmeVertexDeltaData *pDeltaState )
  393. {
  394. FieldIndex_t nFieldIndex = pDeltaState->FindFieldIndex( CDmeVertexDeltaData::FIELD_TEXCOORD );
  395. if ( nFieldIndex < 0 )
  396. return;
  397. bool bIsVCoordinateFlipped = pDeltaState->IsVCoordinateFlipped();
  398. const CDmrArray<int> indices = pDeltaState->GetIndexData( nFieldIndex );
  399. const CDmrArray<Vector2D> delta = pDeltaState->GetVertexData( nFieldIndex );
  400. int nDeltaCount = indices.Count();
  401. for ( int j = 0; j < nDeltaCount; ++j )
  402. {
  403. Vector2D uvDelta = delta.Get( j );
  404. if ( bIsVCoordinateFlipped )
  405. {
  406. uvDelta.y = -uvDelta.y;
  407. }
  408. Vector2D &vec2D = pRenderDelta[ indices.Get( j ) ].m_vecDeltaUV;
  409. Vector2DMA( vec2D, flWeight, uvDelta, vec2D );
  410. }
  411. }
  412. //-----------------------------------------------------------------------------
  413. //
  414. //-----------------------------------------------------------------------------
  415. void CDmeMesh::AddColorDelta( RenderVertexDelta_t *pRenderDelta, float flWeight, CDmeVertexDeltaData *pDeltaState )
  416. {
  417. FieldIndex_t nFieldIndex = pDeltaState->FindFieldIndex( CDmeVertexDeltaData::FIELD_COLOR );
  418. if ( nFieldIndex < 0 )
  419. return;
  420. const CDmrArray<int> indices = pDeltaState->GetIndexData( nFieldIndex );
  421. const CDmrArray<Color> delta = pDeltaState->GetVertexData( nFieldIndex );
  422. int nDeltaCount = indices.Count();
  423. for ( int j = 0; j < nDeltaCount; ++j )
  424. {
  425. const Color &srcDeltaColor = delta[ j ];
  426. Vector4D &vecDelta = pRenderDelta[ indices[ j ] ].m_vecDeltaColor;
  427. vecDelta[0] += flWeight * srcDeltaColor.r();
  428. vecDelta[1] += flWeight * srcDeltaColor.g();
  429. vecDelta[2] += flWeight * srcDeltaColor.b();
  430. vecDelta[3] += flWeight * srcDeltaColor.a();
  431. }
  432. }
  433. template< class T > bool CDmeMesh::AddStereoVertexDelta(
  434. CDmeVertexData *pBaseState,
  435. void *pVertexData, int nStride, CDmeVertexDataBase::StandardFields_t fieldId, int nIndex, bool bDoLag )
  436. {
  437. CDmeVertexDeltaData *pDeltaState = GetDeltaState( nIndex );
  438. if ( !pBaseState || !pDeltaState )
  439. return false;
  440. const FieldIndex_t nBaseFieldIndex = pBaseState->FindFieldIndex( fieldId == CDmeVertexData::FIELD_WRINKLE ? CDmeVertexData::FIELD_TEXCOORD : fieldId );
  441. const FieldIndex_t nDeltaFieldIndex = pDeltaState->FindFieldIndex( fieldId );
  442. if ( nBaseFieldIndex < 0 || nDeltaFieldIndex < 0 )
  443. return false;
  444. float flLeftWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][nIndex].x;
  445. float flRightWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][nIndex].y;
  446. const CDmrArray<int> indices = pDeltaState->GetIndexData( nDeltaFieldIndex );
  447. const CDmrArray<T> delta = pDeltaState->GetVertexData( nDeltaFieldIndex );
  448. const CUtlVector<int>& balanceIndices = pBaseState->GetVertexIndexData( CDmeVertexData::FIELD_BALANCE );
  449. const CUtlVector<float> &balanceDelta = pBaseState->GetBalanceData();
  450. const int nDeltaCount = indices.Count();
  451. const FieldIndex_t nSpeedFieldIndex = pBaseState->FindFieldIndex( CDmeVertexData::FIELD_MORPH_SPEED );
  452. if ( !bDoLag || nSpeedFieldIndex < 0 )
  453. {
  454. for ( int j = 0; j < nDeltaCount; ++j )
  455. {
  456. int nDataIndex = indices.Get( j );
  457. const CUtlVector<int> &list = pBaseState->FindVertexIndicesFromDataIndex( nBaseFieldIndex, nDataIndex );
  458. Assert( list.Count() > 0 );
  459. // FIXME: Average everything in the list.. shouldn't be necessary though
  460. float flRightAmount = balanceDelta[ balanceIndices[ list[0] ] ];
  461. float flWeight = Lerp( flRightAmount, flLeftWeight, flRightWeight );
  462. T* pDeltaData = (T*)( (char*)pVertexData + nStride * nDataIndex );
  463. *pDeltaData += delta.Get( j ) * flWeight;
  464. }
  465. return true;
  466. }
  467. float flLeftWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][nIndex].x;
  468. float flRightWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][nIndex].y;
  469. const CDmrArray<int> pSpeedIndices = pBaseState->GetIndexData( nSpeedFieldIndex );
  470. const CDmrArray<float> pSpeedDelta = pBaseState->GetVertexData( nSpeedFieldIndex );
  471. for ( int j = 0; j < nDeltaCount; ++j )
  472. {
  473. int nDataIndex = indices.Get( j );
  474. const CUtlVector<int> &list = pBaseState->FindVertexIndicesFromDataIndex( nBaseFieldIndex, nDataIndex );
  475. Assert( list.Count() > 0 );
  476. // FIXME: Average everything in the list.. shouldn't be necessary though
  477. float flRightAmount = balanceDelta[ balanceIndices[ list[0] ] ];
  478. float flWeight = Lerp( flRightAmount, flLeftWeight, flRightWeight );
  479. float flLaggedWeight = Lerp( flRightAmount, flLeftWeightLagged, flRightWeightLagged );
  480. float flSpeed = pSpeedDelta.Get( pSpeedIndices.Get( list[0] ) );
  481. float flActualWeight = Lerp( flSpeed, flLaggedWeight, flWeight );
  482. T* pDeltaData = (T*)( (char*)pVertexData + nStride * nDataIndex );
  483. *pDeltaData += delta.Get( j ) * flActualWeight;
  484. }
  485. return true;
  486. }
  487. //-----------------------------------------------------------------------------
  488. // Draws the mesh when it uses too many bones
  489. //-----------------------------------------------------------------------------
  490. bool CDmeMesh::BuildDeltaMesh( int nVertices, RenderVertexDelta_t *pRenderDelta )
  491. {
  492. bool bHasWrinkleDelta = false;
  493. memset( pRenderDelta, 0, nVertices * sizeof( RenderVertexDelta_t ) );
  494. int nCount = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL].Count();
  495. Assert( m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL].Count() == m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED].Count() );
  496. CDmeVertexData *pBindState = GetBindBaseState();
  497. const FieldIndex_t nBalanceFieldIndex = pBindState->FindFieldIndex( CDmeVertexDeltaData::FIELD_BALANCE );
  498. const FieldIndex_t nSpeedFieldIndex = pBindState->FindFieldIndex( CDmeVertexDeltaData::FIELD_MORPH_SPEED );
  499. const bool bDoLag = nSpeedFieldIndex >= 0;
  500. if ( nBalanceFieldIndex < 0 )
  501. {
  502. for ( int i = 0; i < nCount; ++i )
  503. {
  504. float flWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].x;
  505. float flLaggedWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].x;
  506. if ( flWeight <= 0.0f && flLaggedWeight <= 0.0f )
  507. continue;
  508. // prepare vertices
  509. CDmeVertexDeltaData *pDeltaState = GetDeltaState(i);
  510. AddVertexDelta<Vector>( pBindState, &pRenderDelta->m_vecDeltaPosition, sizeof(RenderVertexDelta_t), CDmeVertexDeltaData::FIELD_POSITION, i, bDoLag );
  511. AddVertexDelta<Vector>( pBindState, &pRenderDelta->m_vecDeltaNormal, sizeof(RenderVertexDelta_t), CDmeVertexDeltaData::FIELD_NORMAL, i, bDoLag );
  512. AddTexCoordDelta( pRenderDelta, flWeight, pDeltaState );
  513. AddColorDelta( pRenderDelta, flWeight, pDeltaState );
  514. bool bWrinkle = AddVertexDelta<float>( pBindState, &pRenderDelta->m_flDeltaWrinkle, sizeof(RenderVertexDelta_t), CDmeVertexDeltaData::FIELD_WRINKLE, i, bDoLag );
  515. bHasWrinkleDelta = bHasWrinkleDelta || bWrinkle;
  516. }
  517. return bHasWrinkleDelta;
  518. }
  519. for ( int i = 0; i < nCount; ++i )
  520. {
  521. float flLeftWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].x;
  522. float flRightWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].y;
  523. float flLeftWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].x;
  524. float flRightWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].y;
  525. if ( flLeftWeight <= 0.0f && flRightWeight <= 0.0f && flLeftWeightLagged <= 0.0f && flRightWeightLagged <= 0.0f )
  526. continue;
  527. // FIXME: Need to make balanced versions of texcoord + color
  528. bool bWrinkle;
  529. CDmeVertexDeltaData *pDeltaState = GetDeltaState(i);
  530. AddStereoVertexDelta<Vector>( pBindState, &pRenderDelta->m_vecDeltaPosition, sizeof(RenderVertexDelta_t), CDmeVertexDeltaData::FIELD_POSITION, i, bDoLag );
  531. AddStereoVertexDelta<Vector>( pBindState, &pRenderDelta->m_vecDeltaNormal, sizeof(RenderVertexDelta_t), CDmeVertexDeltaData::FIELD_NORMAL, i, bDoLag );
  532. bWrinkle = AddStereoVertexDelta<float>( pBindState, &pRenderDelta->m_flDeltaWrinkle, sizeof(RenderVertexDelta_t), CDmeVertexDeltaData::FIELD_WRINKLE, i, bDoLag);
  533. bHasWrinkleDelta = bHasWrinkleDelta || bWrinkle;
  534. AddTexCoordDelta( pRenderDelta, flLeftWeight, pDeltaState );
  535. AddColorDelta( pRenderDelta, flLeftWeight, pDeltaState );
  536. }
  537. return bHasWrinkleDelta;
  538. }
  539. //-----------------------------------------------------------------------------
  540. // Writes triangulated indices for a face set into a meshbuilder
  541. //-----------------------------------------------------------------------------
  542. void CDmeMesh::WriteTriangluatedIndices( const CDmeVertexData *pBaseState, CDmeFaceSet *pFaceSet, CMeshBuilder &meshBuilder )
  543. {
  544. // prepare indices
  545. int nFirstIndex = 0;
  546. int nIndexCount = pFaceSet->NumIndices();
  547. while ( nFirstIndex < nIndexCount )
  548. {
  549. int nVertexCount = pFaceSet->GetNextPolygonVertexCount( nFirstIndex );
  550. if ( nVertexCount >= 3 )
  551. {
  552. int nOutCount = ( nVertexCount-2 ) * 3;
  553. int *pIndices = (int*)_alloca( nOutCount * sizeof(int) );
  554. ComputeTriangulatedIndices( pBaseState, pFaceSet, nFirstIndex, pIndices, nOutCount );
  555. for ( int ii = 0; ii < nOutCount; ++ii )
  556. {
  557. meshBuilder.FastIndex( pIndices[ii] );
  558. }
  559. }
  560. nFirstIndex += nVertexCount + 1;
  561. }
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Draws the mesh when it uses too many bones
  565. //-----------------------------------------------------------------------------
  566. void CDmeMesh::DrawDynamicMesh( CDmeFaceSet *pFaceSet, matrix3x4_t *pPoseToWorld, bool bHasActiveDeltaStates, CDmeDrawSettings *pDrawSettings /* = NULL */ )
  567. {
  568. CDmeVertexData *pBindBase = GetCurrentBaseState();
  569. if ( !pBindBase )
  570. return;
  571. // NOTE: This is inherently inefficient; we re-skin the *entire* mesh,
  572. // even if it's not being used by the entire model. This is because we can't
  573. // guarantee the various materials from the various face sets use the
  574. // same vertex format (even though they should), and we don't want to
  575. // spend the work to detemine the sub-part of the mesh used by this face set.
  576. // Compute vertex deltas for rendering
  577. const int nVertices = pBindBase->VertexCount();
  578. // NOTE: The Delta Data is actually indexed by the pPositionIndices, pNormalIndices, etc.
  579. // The fact that we're storing one delta per final vertex nVertices
  580. // is a waste of memory and simply implementational convenience.
  581. bool bHasActiveWrinkle = false;
  582. RenderVertexDelta_t *pVertexDelta = (RenderVertexDelta_t*)_alloca( nVertices * sizeof(RenderVertexDelta_t) );
  583. if ( bHasActiveDeltaStates )
  584. {
  585. bHasActiveWrinkle = BuildDeltaMesh( nVertices, pVertexDelta );
  586. }
  587. else
  588. {
  589. pVertexDelta = NULL;
  590. }
  591. CRenderInfo renderInfo( pBindBase );
  592. Assert( renderInfo.HasPositionData() );
  593. // prepare vertices
  594. FieldIndex_t uvField = pBindBase->FindFieldIndex( CDmeVertexData::FIELD_TEXCOORD );
  595. FieldIndex_t colorField = pBindBase->FindFieldIndex( CDmeVertexData::FIELD_COLOR );
  596. bool bHasTexCoords = ( uvField >= 0 );
  597. bool bHasColors = ( colorField >= 0 );
  598. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  599. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  600. const CDmrArrayConst<int> pUVIndices = bHasTexCoords ? pBindBase->GetIndexData( uvField ) : NULL;
  601. if ( bHasActiveWrinkle && bHasTexCoords )
  602. {
  603. // Create the wrinkle flex mesh
  604. IMesh *pFlexDelta = pRenderContext->GetFlexMesh();
  605. int nFlexVertexOffset = 0;
  606. CMeshBuilder meshBuilder;
  607. meshBuilder.Begin( pFlexDelta, MATERIAL_HETEROGENOUS, nVertices, 0, &nFlexVertexOffset );
  608. for ( int j=0; j < nVertices; j++ )
  609. {
  610. // NOTE: The UV indices are also used to index into wrinkle data
  611. int nUVIndex = pUVIndices.Get( j );
  612. meshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  613. meshBuilder.NormalDelta3f( 0.0f, 0.0f, 0.0f );
  614. meshBuilder.Wrinkle1f( pVertexDelta[nUVIndex].m_flDeltaWrinkle );
  615. meshBuilder.AdvanceVertex();
  616. }
  617. meshBuilder.End( false, false );
  618. pMesh->SetFlexMesh( pFlexDelta, nFlexVertexOffset );
  619. }
  620. // build the mesh
  621. int nIndices = pFaceSet->GetTriangulatedIndexCount();
  622. CMeshBuilder meshBuilder;
  623. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertices, nIndices );
  624. const CDmrArrayConst<Vector2D> pUVData = bHasTexCoords ? pBindBase->GetVertexData( uvField ) : NULL;
  625. const CDmrArrayConst<int> pColorIndices = bHasColors ? pBindBase->GetIndexData( colorField ) : NULL;
  626. const CDmrArrayConst<Color> pColorData = bHasColors ? pBindBase->GetVertexData( colorField ) : NULL;
  627. Vector vecPosition, vecNormal;
  628. Vector4D vecTangent;
  629. for ( int vi = 0; vi < nVertices; ++vi )
  630. {
  631. renderInfo.ComputeVertex( vi, pPoseToWorld, pVertexDelta, &vecPosition, &vecNormal, &vecTangent );
  632. meshBuilder.Position3fv( vecPosition.Base() );
  633. meshBuilder.Normal3fv( vecNormal.Base() );
  634. meshBuilder.UserData( vecTangent.Base() );
  635. if ( pUVData.IsValid() )
  636. {
  637. int uvi = pUVIndices.Get( vi );
  638. Vector2D uv = pUVData.Get( uvi );
  639. if ( pBindBase->IsVCoordinateFlipped() )
  640. {
  641. uv.y = 1.0f - uv.y;
  642. }
  643. if ( bHasActiveDeltaStates )
  644. {
  645. uv += pVertexDelta[uvi].m_vecDeltaUV;
  646. }
  647. meshBuilder.TexCoord2fv( 0, uv.Base() );
  648. }
  649. else
  650. {
  651. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  652. }
  653. if ( pColorIndices.IsValid() )
  654. {
  655. int ci = pColorIndices.Get( vi );
  656. int color = pColorData.Get( ci ).GetRawColor();
  657. meshBuilder.Color4ubv( (unsigned char*)&color );
  658. }
  659. else
  660. {
  661. meshBuilder.Color4ub( 255, 255, 255, 255 );
  662. }
  663. meshBuilder.AdvanceVertex();
  664. }
  665. WriteTriangluatedIndices( pBindBase, pFaceSet, meshBuilder );
  666. meshBuilder.End();
  667. pMesh->Draw();
  668. if ( pDrawSettings && pDrawSettings->GetNormals() )
  669. {
  670. RenderNormals( pPoseToWorld, bHasActiveDeltaStates ? pVertexDelta : NULL );
  671. }
  672. }
  673. //-----------------------------------------------------------------------------
  674. // Renders normals
  675. //-----------------------------------------------------------------------------
  676. #define NORMAL_LINE_SIZE 0.25f
  677. void CDmeMesh::RenderNormals( matrix3x4_t *pPoseToWorld, RenderVertexDelta_t *pDelta )
  678. {
  679. CDmeVertexData *pBind = GetBindBaseState();
  680. if ( !pBind )
  681. return;
  682. CRenderInfo renderInfo( pBind );
  683. Assert( renderInfo.HasPositionData() );
  684. if ( !renderInfo.HasNormalData() )
  685. return;
  686. bool bHasTangents = renderInfo.HasTangentData();
  687. // build the mesh
  688. InitializeNormalMaterial();
  689. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  690. pRenderContext->Bind( s_NormalMaterial );
  691. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  692. int nMaxIndices, nMaxVertices;
  693. pRenderContext->GetMaxToRender( pMesh, false, &nMaxVertices, &nMaxIndices );
  694. int nFirstVertex = 0;
  695. int nVerticesRemaining = pBind->VertexCount();;
  696. int nFactor = bHasTangents ? 6 : 2;
  697. while ( nVerticesRemaining > 0 )
  698. {
  699. int nVertices = nVerticesRemaining;
  700. if ( nVertices > nMaxVertices / nFactor )
  701. {
  702. nVertices = nMaxVertices / nFactor;
  703. }
  704. if ( nVertices > nMaxIndices / nFactor )
  705. {
  706. nVertices = nMaxIndices / nFactor;
  707. }
  708. nVerticesRemaining -= nVertices;
  709. CMeshBuilder meshBuilder;
  710. meshBuilder.Begin( pMesh, MATERIAL_LINES, bHasTangents ? nVertices * 3 : nVertices );
  711. Vector vecPosition, vecNormal, vecEndPoint, vecTangentS, vecTangentT;
  712. Vector4D vecTangent;
  713. for ( int vi = nFirstVertex; vi < nVertices; ++vi )
  714. {
  715. renderInfo.ComputeVertex( vi, pPoseToWorld, pDelta, &vecPosition, &vecNormal, &vecTangent );
  716. meshBuilder.Position3fv( vecPosition.Base() );
  717. meshBuilder.Color4ub( 0, 0, 255, 255 );
  718. meshBuilder.AdvanceVertex();
  719. VectorMA( vecPosition, NORMAL_LINE_SIZE, vecNormal, vecEndPoint );
  720. meshBuilder.Position3fv( vecEndPoint.Base() );
  721. meshBuilder.Color4ub( 0, 0, 255, 255 );
  722. meshBuilder.AdvanceVertex();
  723. continue;
  724. if ( !bHasTangents )
  725. continue;
  726. CrossProduct( vecNormal, vecTangent.AsVector3D(), vecTangentT );
  727. VectorNormalize( vecTangentT );
  728. // NOTE: This is the new, desired tangentS morphing behavior
  729. // CrossProduct( vecTangentT, vecNormal, vecTangentS );
  730. VectorCopy( vecTangent.AsVector3D(), vecTangentS );
  731. vecTangentT *= vecTangent.w;
  732. meshBuilder.Position3fv( vecPosition.Base() );
  733. meshBuilder.Color4ub( 255, 0, 0, 255 );
  734. meshBuilder.AdvanceVertex();
  735. VectorMA( vecPosition, NORMAL_LINE_SIZE, vecTangentS, vecEndPoint );
  736. meshBuilder.Position3fv( vecEndPoint.Base() );
  737. meshBuilder.Color4ub( 255, 0, 0, 255 );
  738. meshBuilder.AdvanceVertex();
  739. meshBuilder.Position3fv( vecPosition.Base() );
  740. meshBuilder.Color4ub( 0, 255, 0, 255 );
  741. meshBuilder.AdvanceVertex();
  742. VectorMA( vecPosition, NORMAL_LINE_SIZE, vecTangentT, vecEndPoint );
  743. meshBuilder.Position3fv( vecEndPoint.Base() );
  744. meshBuilder.Color4ub( 0, 255, 0, 255 );
  745. meshBuilder.AdvanceVertex();
  746. }
  747. meshBuilder.End();
  748. pMesh->Draw();
  749. nFirstVertex += nVertices;
  750. }
  751. }
  752. //-----------------------------------------------------------------------------
  753. // Draws the passed DmeFaceSet in wireframe mode
  754. //-----------------------------------------------------------------------------
  755. void CDmeMesh::DrawWireframeFaceSet( CDmeFaceSet *pFaceSet, matrix3x4_t *pPoseToWorld, bool bHasActiveDeltaStates, CDmeDrawSettings *pDrawSettings )
  756. {
  757. CDmeVertexData *pBind = GetBindBaseState();
  758. if ( !pBind )
  759. return;
  760. const FieldIndex_t posField = pBind->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  761. if ( posField < 0 )
  762. return;
  763. const CUtlVector< Vector > &posData( CDmrArrayConst< Vector >( pBind->GetVertexData( posField ) ).Get() );
  764. const int nVertices = posData.Count();
  765. const CUtlVector< int > &posIndices( CDmrArrayConst< int >( pBind->GetIndexData( posField ) ).Get() );
  766. Vector *pDeltaVertices = bHasActiveDeltaStates ? pDeltaVertices = reinterpret_cast< Vector * >( alloca( nVertices * sizeof( Vector ) ) ) : NULL;
  767. if ( bHasActiveDeltaStates )
  768. {
  769. memset( pDeltaVertices, 0, sizeof( Vector ) * nVertices );
  770. const int nCount = m_DeltaStateWeights[ MESH_DELTA_WEIGHT_NORMAL ].Count();
  771. const FieldIndex_t nBalanceFieldIndex = pBind->FindFieldIndex( CDmeVertexDeltaData::FIELD_BALANCE );
  772. const FieldIndex_t nSpeedFieldIndex = pBind->FindFieldIndex( CDmeVertexDeltaData::FIELD_MORPH_SPEED );
  773. const bool bDoLag = ( nSpeedFieldIndex >= 0 );
  774. if ( nBalanceFieldIndex < 0 )
  775. {
  776. for ( int i = 0; i < nCount; ++i )
  777. {
  778. float flWeight = m_DeltaStateWeights[ MESH_DELTA_WEIGHT_NORMAL ][ i ].x;
  779. float flLaggedWeight = m_DeltaStateWeights[ MESH_DELTA_WEIGHT_LAGGED ][ i ].x;
  780. if ( flWeight <= 0.0f && ( !bDoLag || flLaggedWeight <= 0.0f ) )
  781. continue;
  782. AddVertexDelta< Vector >( pBind, pDeltaVertices, sizeof( Vector ), CDmeVertexDeltaData::FIELD_POSITION, i, bDoLag );
  783. }
  784. }
  785. else
  786. {
  787. for ( int i = 0; i < nCount; ++i )
  788. {
  789. float flLeftWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].x;
  790. float flRightWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].y;
  791. float flLeftWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].x;
  792. float flRightWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].y;
  793. if ( flLeftWeight <= 0.0f && flRightWeight <= 0.0f && ( !bDoLag || ( flLeftWeightLagged <= 0.0f && flRightWeightLagged <= 0.0f ) ) )
  794. continue;
  795. AddStereoVertexDelta< Vector >( pBind, pDeltaVertices, sizeof( Vector ), CDmeVertexDeltaData::FIELD_POSITION, i, bDoLag );
  796. }
  797. }
  798. }
  799. Vector *pVertices = reinterpret_cast< Vector * >( alloca( nVertices * sizeof( Vector ) ) );
  800. CRenderInfo renderInfo( pBind );
  801. Assert( renderInfo.HasPositionData() );
  802. for ( int pi = 0; pi < nVertices; ++pi )
  803. {
  804. renderInfo.ComputePosition( pi, pPoseToWorld, pDeltaVertices, pVertices );
  805. }
  806. InitializeNormalMaterial();
  807. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  808. pRenderContext->Bind( s_NormalMaterial );
  809. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  810. // build the mesh
  811. CMeshBuilder meshBuilder;
  812. // Draw the polygons in the face set
  813. const int nFaceSetIndices = pFaceSet->NumIndices();
  814. const int *pFaceSetIndices = pFaceSet->GetIndices();
  815. int vR = 0;
  816. int vG = 0;
  817. int vB = 0;
  818. if ( pDrawSettings )
  819. {
  820. const Color &vColor = pDrawSettings->GetColor();
  821. vR = vColor.r();
  822. vG = vColor.g();
  823. vB = vColor.b();
  824. }
  825. int nFaceIndices;
  826. for ( int i = 0; i < nFaceSetIndices; )
  827. {
  828. nFaceIndices = pFaceSet->GetNextPolygonVertexCount( i );
  829. meshBuilder.Begin( pMesh, MATERIAL_LINES, nFaceIndices );
  830. for ( int j = 0; j < nFaceIndices; ++j )
  831. {
  832. Assert( i < nFaceSetIndices );
  833. int vIndex0 = posIndices[ pFaceSetIndices[ i + j ] ];
  834. Assert( vIndex0 < nVertices );
  835. meshBuilder.Position3fv( reinterpret_cast< float * >( pVertices + vIndex0 ) );
  836. meshBuilder.Color3ub( vR, vG, vB );
  837. meshBuilder.AdvanceVertex();
  838. int vIndex1 = posIndices[ pFaceSetIndices[ i + ( ( j + 1 ) % nFaceIndices ) ] ];
  839. Assert( vIndex1 < nVertices );
  840. meshBuilder.Position3fv( reinterpret_cast< float * >( pVertices + vIndex1) );
  841. meshBuilder.Color3ub( vR, vG, vB );
  842. meshBuilder.AdvanceVertex();
  843. }
  844. meshBuilder.End();
  845. i += nFaceIndices + 1;
  846. }
  847. pMesh->Draw();
  848. }
  849. //-----------------------------------------------------------------------------
  850. // Do we have active delta state data?
  851. //-----------------------------------------------------------------------------
  852. bool CDmeMesh::HasActiveDeltaStates() const
  853. {
  854. for ( int t = 0; t < MESH_DELTA_WEIGHT_TYPE_COUNT; ++t )
  855. {
  856. int nCount = m_DeltaStateWeights[t].Count();
  857. for ( int i = 0; i < nCount; ++i )
  858. {
  859. if ( m_DeltaStateWeights[t][i].x != 0.0f || m_DeltaStateWeights[t][i].y != 0.0f )
  860. return true;
  861. }
  862. }
  863. return false;
  864. }
  865. //-----------------------------------------------------------------------------
  866. // Draws the mesh
  867. //-----------------------------------------------------------------------------
  868. void CDmeMesh::Draw( const matrix3x4_t &shapeToWorld, CDmeDrawSettings *pDrawSettings /* = NULL */ )
  869. {
  870. const CDmeVertexData *pBind = GetBindBaseState();
  871. if ( !pBind || !g_pMaterialSystem || !g_pMDLCache || !g_pStudioRender )
  872. return;
  873. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  874. const bool bHasActiveDeltaStates = HasActiveDeltaStates();
  875. const bool bDrawNormals = pDrawSettings ? pDrawSettings->GetNormals() : false;
  876. const CDmeDrawSettings::DrawType_t drawType = pDrawSettings ? pDrawSettings->GetDrawType() : CDmeDrawSettings::DRAW_SMOOTH;
  877. const bool bShaded = ( drawType == CDmeDrawSettings::DRAW_SMOOTH || drawType == CDmeDrawSettings::DRAW_FLAT );
  878. const bool bWireframe = ( drawType == CDmeDrawSettings::DRAW_WIREFRAME );
  879. // const bool bBoundingBox = ( drawType == CDmeDrawSettings::DRAW_BOUNDINGBOX );
  880. const bool bSoftwareSkinning = bHasActiveDeltaStates | bDrawNormals | bWireframe;
  881. matrix3x4_t *pPoseToWorld = CDmeModel::SetupModelRenderState( shapeToWorld, pBind->HasSkinningData(), bSoftwareSkinning );
  882. pRenderContext->SetNumBoneWeights( pPoseToWorld ? 0 : pBind->JointCount() );
  883. int nFaceSets = FaceSetCount();
  884. m_hwFaceSets.EnsureCount( nFaceSets );
  885. const bool bindMaterial = pDrawSettings ? !pDrawSettings->IsAMaterialBound() : true;
  886. for ( int fi = 0; fi < nFaceSets; ++fi )
  887. {
  888. CDmeFaceSet *pFaceSet = GetFaceSet( fi );
  889. if ( bWireframe )
  890. {
  891. DrawWireframeFaceSet( pFaceSet, pPoseToWorld, bHasActiveDeltaStates, pDrawSettings );
  892. continue;
  893. }
  894. if ( bindMaterial )
  895. {
  896. pRenderContext->Bind( pFaceSet->GetMaterial()->GetCachedMTL() );
  897. }
  898. if ( pPoseToWorld || ( bShaded && bSoftwareSkinning ) )
  899. {
  900. DrawDynamicMesh( pFaceSet, pPoseToWorld, bHasActiveDeltaStates, pDrawSettings );
  901. continue;
  902. }
  903. // TODO: figure out how to tell the mesh when the faceset's indices change
  904. if ( !m_hwFaceSets[fi].m_bBuilt )
  905. {
  906. m_hwFaceSets[fi].m_pMesh = CreateHwMesh( pFaceSet );
  907. m_hwFaceSets[fi].m_bBuilt = true;
  908. }
  909. if ( m_hwFaceSets[fi].m_pMesh )
  910. {
  911. m_hwFaceSets[fi].m_pMesh->Draw();
  912. }
  913. }
  914. pRenderContext->SetNumBoneWeights( 0 );
  915. CDmeModel::CleanupModelRenderState();
  916. }
  917. //-----------------------------------------------------------------------------
  918. // Face sets
  919. //-----------------------------------------------------------------------------
  920. int CDmeMesh::FaceSetCount() const
  921. {
  922. return m_FaceSets.Count();
  923. }
  924. CDmeFaceSet *CDmeMesh::GetFaceSet( int faceSetIndex )
  925. {
  926. return m_FaceSets[ faceSetIndex ];
  927. }
  928. const CDmeFaceSet *CDmeMesh::GetFaceSet( int faceSetIndex ) const
  929. {
  930. return m_FaceSets[ faceSetIndex ];
  931. }
  932. void CDmeMesh::AddFaceSet( CDmeFaceSet *faceSet )
  933. {
  934. m_FaceSets.AddToTail( faceSet );
  935. }
  936. void CDmeMesh::RemoveFaceSet( int faceSetIndex )
  937. {
  938. m_FaceSets.Remove( faceSetIndex );
  939. }
  940. //-----------------------------------------------------------------------------
  941. // Find a base state by name
  942. //-----------------------------------------------------------------------------
  943. CDmeVertexData *CDmeMesh::FindBaseState( const char *pStateName ) const
  944. {
  945. const int nBaseStateCount = BaseStateCount();
  946. for ( int i = 0; i < nBaseStateCount; ++i )
  947. {
  948. CDmeVertexData *pBaseState = GetBaseState( i );
  949. if ( !Q_stricmp( pStateName, pBaseState->GetName() ) )
  950. return pBaseState;
  951. }
  952. return NULL;
  953. }
  954. //-----------------------------------------------------------------------------
  955. // Find a base state by name, add a new one if not found
  956. //-----------------------------------------------------------------------------
  957. CDmeVertexData *CDmeMesh::FindOrCreateBaseState( const char *pStateName )
  958. {
  959. CDmeVertexData *pBaseState = FindBaseState( pStateName );
  960. if ( pBaseState )
  961. return pBaseState;
  962. pBaseState = CreateElement< CDmeVertexData >( pStateName, GetFileId() );
  963. m_BaseStates.AddToTail( pBaseState );
  964. return pBaseState;
  965. }
  966. //-----------------------------------------------------------------------------
  967. // Remove a base state by name
  968. //-----------------------------------------------------------------------------
  969. bool CDmeMesh::DeleteBaseState( const char *pStateName )
  970. {
  971. const int nBaseStateCount = BaseStateCount();
  972. for ( int i = 0; i < nBaseStateCount; ++i )
  973. {
  974. const CDmeVertexData *pBaseState = GetBaseState( i );
  975. if ( !Q_stricmp( pStateName, pBaseState->GetName() ) )
  976. {
  977. m_BaseStates.Remove( i );
  978. g_pDataModel->DestroyElement( pBaseState->GetHandle() );
  979. // TODO: Fix up all dependent states
  980. return true;
  981. }
  982. }
  983. return false;
  984. }
  985. //-----------------------------------------------------------------------------
  986. // Selects a particular base state to be current state
  987. //-----------------------------------------------------------------------------
  988. void CDmeMesh::SetCurrentBaseState( const char *pStateName )
  989. {
  990. m_CurrentBaseState = FindBaseState( pStateName );
  991. }
  992. //-----------------------------------------------------------------------------
  993. // Selects a particular base state to be current state
  994. //-----------------------------------------------------------------------------
  995. CDmeVertexData *CDmeMesh::GetCurrentBaseState()
  996. {
  997. return m_CurrentBaseState;
  998. }
  999. //-----------------------------------------------------------------------------
  1000. // Selects a particular base state to be current state
  1001. //-----------------------------------------------------------------------------
  1002. const CDmeVertexData *CDmeMesh::GetCurrentBaseState() const
  1003. {
  1004. return m_CurrentBaseState;
  1005. }
  1006. //-----------------------------------------------------------------------------
  1007. //
  1008. //-----------------------------------------------------------------------------
  1009. bool CDmeMesh::SetBindBaseState( CDmeVertexData *pBaseState )
  1010. {
  1011. if ( !pBaseState )
  1012. return false;
  1013. CDmeVertexData *pCheckState = FindBaseState( pBaseState->GetName() );
  1014. if ( pCheckState != pBaseState )
  1015. return false;
  1016. return true;
  1017. }
  1018. //-----------------------------------------------------------------------------
  1019. //
  1020. //-----------------------------------------------------------------------------
  1021. CDmeVertexData *CDmeMesh::GetBindBaseState()
  1022. {
  1023. if ( m_BindBaseState.GetElement() )
  1024. return m_BindBaseState;
  1025. // Backwards compatibility
  1026. return FindBaseState( "bind" );
  1027. }
  1028. //-----------------------------------------------------------------------------
  1029. //
  1030. //-----------------------------------------------------------------------------
  1031. const CDmeVertexData *CDmeMesh::GetBindBaseState() const
  1032. {
  1033. if ( m_BindBaseState.GetElement() )
  1034. return m_BindBaseState;
  1035. // Backwards compatibility
  1036. return FindBaseState( "bind" );
  1037. }
  1038. //-----------------------------------------------------------------------------
  1039. // Delta states
  1040. //-----------------------------------------------------------------------------
  1041. int CDmeMesh::DeltaStateCount() const
  1042. {
  1043. return m_DeltaStates.Count();
  1044. }
  1045. //-----------------------------------------------------------------------------
  1046. // Returns the delta
  1047. //-----------------------------------------------------------------------------
  1048. CDmeVertexDeltaData *CDmeMesh::GetDeltaState( int nDeltaIndex ) const
  1049. {
  1050. if ( nDeltaIndex < 0 || nDeltaIndex >= m_DeltaStates.Count() )
  1051. return NULL;
  1052. return m_DeltaStates[ nDeltaIndex ];
  1053. }
  1054. //-----------------------------------------------------------------------------
  1055. // Finds a delta state by name. If it isn't found, return NULL
  1056. //-----------------------------------------------------------------------------
  1057. CDmeVertexDeltaData *CDmeMesh::FindDeltaState( const char *pDeltaName ) const
  1058. {
  1059. return GetDeltaState( FindDeltaStateIndex( pDeltaName ) );
  1060. }
  1061. //-----------------------------------------------------------------------------
  1062. //
  1063. //-----------------------------------------------------------------------------
  1064. int SortDeltaNameFunc( const void *a, const void *b )
  1065. {
  1066. return Q_strcmp( *( const char ** )( a ), *( const char ** )( b ) );
  1067. }
  1068. //-----------------------------------------------------------------------------
  1069. // If the name doe
  1070. //-----------------------------------------------------------------------------
  1071. const char *SortDeltaName( const char *pInDeltaName, char *pOutDeltaName, int nOutDeltaNameBufLen )
  1072. {
  1073. if ( !pInDeltaName || !strchr( pInDeltaName, '_' ) )
  1074. return pInDeltaName;
  1075. char **ppDeltaNames = reinterpret_cast< char ** >( stackalloc( nOutDeltaNameBufLen * sizeof( char * ) ) );
  1076. memset( ppDeltaNames, 0, nOutDeltaNameBufLen * sizeof( char * ) );
  1077. const char *pStart = pInDeltaName;
  1078. int nDimensionCount = 0;
  1079. while ( pStart )
  1080. {
  1081. const char *pUnderBar = strchr( pStart, '_' );
  1082. const int nControlNameBufLen = ( pUnderBar ? pUnderBar - pStart : Q_strlen( pStart ) ) + 1;
  1083. if ( nControlNameBufLen )
  1084. {
  1085. ppDeltaNames[ nDimensionCount ] = reinterpret_cast< char * >( stackalloc( nControlNameBufLen * sizeof( char ) ) );
  1086. Q_strncpy( ppDeltaNames[ nDimensionCount ], pStart, nControlNameBufLen );
  1087. ++nDimensionCount;
  1088. }
  1089. pStart = pUnderBar;
  1090. if ( pStart )
  1091. {
  1092. ++pStart;
  1093. }
  1094. }
  1095. // This should only happen if the input name is all _'s
  1096. if ( nDimensionCount <= 0 )
  1097. return pInDeltaName;
  1098. qsort( ppDeltaNames, nDimensionCount, sizeof( char * ), SortDeltaNameFunc );
  1099. char *pDst = pOutDeltaName;
  1100. for ( int i = 0; i < nDimensionCount; ++i )
  1101. {
  1102. if ( i != 0 )
  1103. {
  1104. Q_strncpy( pDst, "_", nOutDeltaNameBufLen );
  1105. ++pDst;
  1106. --nOutDeltaNameBufLen;
  1107. }
  1108. const int nControlNameLen = Q_strlen( ppDeltaNames[ i ] );
  1109. Q_strncpy( pDst, ppDeltaNames[ i ], nOutDeltaNameBufLen );
  1110. pDst += nControlNameLen;
  1111. nOutDeltaNameBufLen -= nControlNameLen;
  1112. }
  1113. return pOutDeltaName;
  1114. }
  1115. //-----------------------------------------------------------------------------
  1116. //
  1117. //-----------------------------------------------------------------------------
  1118. CDmeVertexDeltaData *CDmeMesh::FindOrCreateDeltaState( const char *pInDeltaName )
  1119. {
  1120. CDmeVertexDeltaData *pDeltaState = FindDeltaState( pInDeltaName );
  1121. if ( pDeltaState )
  1122. return pDeltaState;
  1123. const int nDeltaNameBufLen = Q_strlen( pInDeltaName ) + 1;
  1124. char *pDeltaNameBuf = reinterpret_cast< char * >( stackalloc( nDeltaNameBufLen * sizeof( char ) ) );
  1125. const char *pDeltaName = SortDeltaName( pInDeltaName, pDeltaNameBuf, nDeltaNameBufLen );
  1126. pDeltaState = CreateElement< CDmeVertexDeltaData >( pDeltaName, GetFileId() );
  1127. if ( pDeltaState )
  1128. {
  1129. m_DeltaStates.AddToTail( pDeltaState );
  1130. }
  1131. return pDeltaState;
  1132. }
  1133. //-----------------------------------------------------------------------------
  1134. // Finds a delta state index by comparing names, if it can't be found
  1135. // searches for all permutations of the delta name
  1136. //-----------------------------------------------------------------------------
  1137. int CDmeMesh::FindDeltaStateIndex( const char *pInDeltaName ) const
  1138. {
  1139. const char *pDeltaName = pInDeltaName;
  1140. if ( strchr( pInDeltaName, '_' ) )
  1141. {
  1142. const int nDeltaNameBufLen = Q_strlen( pInDeltaName ) + 1;
  1143. char *pDeltaNameBuf = reinterpret_cast< char * >( stackalloc( nDeltaNameBufLen * sizeof( char ) ) );
  1144. pDeltaName = SortDeltaName( pInDeltaName, pDeltaNameBuf, nDeltaNameBufLen );
  1145. }
  1146. int dn = DeltaStateCount();
  1147. for ( int di = 0; di < dn; ++di )
  1148. {
  1149. CDmeVertexDeltaData *pDeltaState = GetDeltaState( di );
  1150. if ( !Q_stricmp( pDeltaName, pDeltaState->GetName() ) )
  1151. return di;
  1152. }
  1153. return -1;
  1154. }
  1155. //-----------------------------------------------------------------------------
  1156. //
  1157. //-----------------------------------------------------------------------------
  1158. void CDmeMesh::SetDeltaStateWeight( int nDeltaIndex, MeshDeltaWeightType_t type, float flMorphWeight )
  1159. {
  1160. if ( nDeltaIndex < m_DeltaStateWeights[type].Count() )
  1161. {
  1162. m_DeltaStateWeights[type].Set( nDeltaIndex, Vector2D( flMorphWeight, flMorphWeight ) );
  1163. }
  1164. }
  1165. //-----------------------------------------------------------------------------
  1166. //
  1167. //-----------------------------------------------------------------------------
  1168. void CDmeMesh::SetDeltaStateWeight( int nDeltaIndex, MeshDeltaWeightType_t type, float flLeftWeight, float flRightWeight )
  1169. {
  1170. if ( nDeltaIndex < m_DeltaStateWeights[type].Count() )
  1171. {
  1172. m_DeltaStateWeights[type].Set( nDeltaIndex, Vector2D( flLeftWeight, flRightWeight ) );
  1173. }
  1174. }
  1175. //-----------------------------------------------------------------------------
  1176. // Determines the appropriate vertex format for hardware meshes
  1177. //-----------------------------------------------------------------------------
  1178. VertexFormat_t CDmeMesh::ComputeHwMeshVertexFormat( void )
  1179. {
  1180. bool bIsDX7 = !g_pMaterialSystemHardwareConfig->SupportsVertexAndPixelShaders();
  1181. VertexFormat_t vertexFormat = VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL | VERTEX_TEXCOORD_SIZE(0,2) | VERTEX_BONEWEIGHT(2) | VERTEX_BONE_INDEX
  1182. | ( bIsDX7 ? 0 : VERTEX_USERDATA_SIZE(4) );
  1183. // FIXME: set VERTEX_FORMAT_COMPRESSED if there are no artifacts and if it saves enough memory (use 'mem_dumpvballocs')
  1184. // vertexFormat |= VERTEX_FORMAT_COMPRESSED;
  1185. // FIXME: check for and strip unused vertex elements (see 'bHasNormals', etc, in CreateHwMesh below)
  1186. return vertexFormat;
  1187. }
  1188. //-----------------------------------------------------------------------------
  1189. // Builds a hardware mesh
  1190. //-----------------------------------------------------------------------------
  1191. IMesh *CDmeMesh::CreateHwMesh( CDmeFaceSet *pFaceSet )
  1192. {
  1193. const CDmeVertexData *pBind = GetBindBaseState();
  1194. if ( !pBind )
  1195. return NULL;
  1196. // NOTE: This is memory inefficient. We create a copy of all vertices
  1197. // for each face set, even if those vertices aren't used by the face set
  1198. // Mostly chose to do this for code simplicity, although it also is faster to generate meshes
  1199. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1200. VertexFormat_t vertexFormat = ComputeHwMeshVertexFormat( );
  1201. IMesh *pMesh = pRenderContext->CreateStaticMesh( vertexFormat, "dmemesh" );
  1202. CMeshBuilder meshBuilder;
  1203. // prepare vertices
  1204. FieldIndex_t posField = pBind->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  1205. FieldIndex_t normalField = pBind->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  1206. FieldIndex_t tangentField = pBind->FindFieldIndex( CDmeVertexData::FIELD_TANGENT );
  1207. FieldIndex_t uvField = pBind->FindFieldIndex( CDmeVertexData::FIELD_TEXCOORD );
  1208. FieldIndex_t colorField = pBind->FindFieldIndex( CDmeVertexData::FIELD_COLOR );
  1209. Assert( posField >= 0 );
  1210. bool bHasNormals = ( normalField >= 0 );
  1211. bool bHasTangent = ( tangentField >= 0 );
  1212. bool bHasTexCoords = ( uvField >= 0 );
  1213. bool bHasColors = ( colorField >= 0 );
  1214. // build the mesh
  1215. int nIndices = pFaceSet->GetTriangulatedIndexCount();
  1216. int nVertices = pBind->VertexCount();
  1217. int nJointCount = pBind->JointCount();
  1218. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertices, nIndices );
  1219. const CDmrArrayConst<int> pPositionIndices = pBind->GetIndexData( posField );
  1220. const CDmrArrayConst<Vector> pPositionData = pBind->GetVertexData( posField );
  1221. const CDmrArrayConst<int> pNormalIndices = bHasNormals ? pBind->GetIndexData( normalField ) : NULL;
  1222. const CDmrArrayConst<Vector> pNormalData = bHasNormals ? pBind->GetVertexData( normalField ) : NULL;
  1223. const CDmrArrayConst<int> pTangentIndices = bHasTangent ? pBind->GetIndexData( tangentField ) : NULL;
  1224. const CDmrArrayConst<Vector4D> pTangentData = bHasTangent ? pBind->GetVertexData( tangentField ) : NULL;
  1225. const CDmrArrayConst<int> pUVIndices = bHasTexCoords ? pBind->GetIndexData( uvField ) : NULL;
  1226. const CDmrArrayConst<Vector2D> pUVData = bHasTexCoords ? pBind->GetVertexData( uvField ) : NULL;
  1227. const CDmrArrayConst<int> pColorIndices = bHasColors ? pBind->GetIndexData( colorField ) : NULL;
  1228. const CDmrArrayConst<Color> pColorData = bHasColors ? pBind->GetVertexData( colorField ) : NULL;
  1229. Vector4D defaultTangentS( 1.0f, 0.0f, 0.0f, 1.0f );
  1230. for ( int vi = 0; vi < nVertices; ++vi )
  1231. {
  1232. meshBuilder.Position3fv( pPositionData.Get( pPositionIndices.Get( vi ) ).Base() );
  1233. if ( pNormalData.IsValid() )
  1234. {
  1235. meshBuilder.Normal3fv( pNormalData.Get( pNormalIndices.Get( vi ) ).Base() );
  1236. }
  1237. else
  1238. {
  1239. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  1240. }
  1241. if ( pTangentData.IsValid() )
  1242. {
  1243. meshBuilder.UserData( pTangentData.Get( pTangentIndices.Get( vi ) ).Base() );
  1244. }
  1245. else
  1246. {
  1247. meshBuilder.UserData( defaultTangentS.Base() );
  1248. }
  1249. if ( pUVData.IsValid() )
  1250. {
  1251. const Vector2D &uv = pUVData.Get( pUVIndices.Get( vi ) );
  1252. if ( !pBind->IsVCoordinateFlipped() )
  1253. {
  1254. meshBuilder.TexCoord2fv( 0, uv.Base() );
  1255. }
  1256. else
  1257. {
  1258. meshBuilder.TexCoord2f( 0, uv.x, 1.0f - uv.y );
  1259. }
  1260. }
  1261. else
  1262. {
  1263. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  1264. }
  1265. if ( pColorIndices.IsValid() )
  1266. {
  1267. int color = pColorData.Get( pColorIndices.Get( vi ) ).GetRawColor();
  1268. meshBuilder.Color4ubv( (unsigned char*)&color );
  1269. }
  1270. else
  1271. {
  1272. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1273. }
  1274. // FIXME: Note that this will break once we exceeed the max joint count
  1275. // that the hardware can handle
  1276. const float *pJointWeight = pBind->GetJointWeights( vi );
  1277. const int *pJointIndices = pBind->GetJointIndices( vi );
  1278. for ( int i = 0; i < nJointCount; ++i )
  1279. {
  1280. meshBuilder.BoneWeight( i, pJointWeight[i] );
  1281. meshBuilder.BoneMatrix( i, pJointIndices[i] );
  1282. }
  1283. for ( int i = nJointCount; i < 4; ++i )
  1284. {
  1285. meshBuilder.BoneWeight( i, ( i == 0 ) ? 1.0f : 0.0f );
  1286. meshBuilder.BoneMatrix( i, 0 );
  1287. }
  1288. meshBuilder.AdvanceVertex();
  1289. }
  1290. // prepare indices
  1291. int nFirstIndex = 0;
  1292. int nIndexCount = pFaceSet->NumIndices();
  1293. while ( nFirstIndex < nIndexCount )
  1294. {
  1295. int nVertexCount = pFaceSet->GetNextPolygonVertexCount( nFirstIndex );
  1296. if ( nVertexCount >= 3 )
  1297. {
  1298. int nOutCount = ( nVertexCount-2 ) * 3;
  1299. int *pIndices = (int*)_alloca( nOutCount * sizeof(int) );
  1300. ComputeTriangulatedIndices( pBind, pFaceSet, nFirstIndex, pIndices, nOutCount );
  1301. for ( int ii = 0; ii < nOutCount; ++ii )
  1302. {
  1303. meshBuilder.FastIndex( pIndices[ii] );
  1304. }
  1305. }
  1306. nFirstIndex += nVertexCount + 1;
  1307. }
  1308. meshBuilder.End();
  1309. return pMesh;
  1310. }
  1311. //-----------------------------------------------------------------------------
  1312. // Compute triangulated indices
  1313. //-----------------------------------------------------------------------------
  1314. void CDmeMesh::ComputeTriangulatedIndices( const CDmeVertexData *pBaseState, CDmeFaceSet *pFaceSet, int nFirstIndex, int *pIndices, int nOutCount )
  1315. {
  1316. // FIXME: Come up with a more efficient way of computing this
  1317. // This involves a bunch of recomputation of distances
  1318. float flMinDistance = FLT_MAX;
  1319. int nMinIndex = 0;
  1320. int nVertexCount = pFaceSet->GetNextPolygonVertexCount( nFirstIndex );
  1321. // Optimization for quads + triangles.. it's totally symmetric
  1322. int nLoopCount = nVertexCount;
  1323. if ( nVertexCount <= 3 )
  1324. {
  1325. nLoopCount = 0;
  1326. }
  1327. else if ( nVertexCount == 4 )
  1328. {
  1329. nLoopCount = 2;
  1330. }
  1331. for ( int i = 0; i < nLoopCount; ++i )
  1332. {
  1333. float flDistance = 0.0f;
  1334. const Vector &vecCenter = pBaseState->GetPosition( pFaceSet->GetIndex( nFirstIndex+i ) );
  1335. for ( int j = 2; j < nVertexCount-1; ++j )
  1336. {
  1337. int vi = ( i + j ) % nVertexCount;
  1338. const Vector &vecEdge = pBaseState->GetPosition( pFaceSet->GetIndex( nFirstIndex+vi ) );
  1339. flDistance += vecEdge.DistTo( vecCenter );
  1340. }
  1341. if ( flDistance < flMinDistance )
  1342. {
  1343. nMinIndex = i;
  1344. flMinDistance = flDistance;
  1345. }
  1346. }
  1347. // Compute the triangulation indices
  1348. Assert( nOutCount == ( nVertexCount - 2 ) * 3 );
  1349. int nOutIndex = 0;
  1350. for ( int i = 1; i < nVertexCount - 1; ++i )
  1351. {
  1352. pIndices[nOutIndex++] = pFaceSet->GetIndex( nFirstIndex + nMinIndex );
  1353. pIndices[nOutIndex++] = pFaceSet->GetIndex( nFirstIndex + ((nMinIndex + i) % nVertexCount) );
  1354. pIndices[nOutIndex++] = pFaceSet->GetIndex( nFirstIndex + ((nMinIndex + i + 1) % nVertexCount) );
  1355. }
  1356. }
  1357. //-----------------------------------------------------------------------------
  1358. // Build a map from vertex index to a list of triangles that share the vert.
  1359. //-----------------------------------------------------------------------------
  1360. void CDmeMesh::BuildTriangleMap( const CDmeVertexData *pBaseState, CDmeFaceSet* pFaceSet, CUtlVector<Triangle_t>& triangles, CUtlVector< CUtlVector<int> >* pVertToTriMap )
  1361. {
  1362. // prepare indices
  1363. int nFirstIndex = 0;
  1364. int nIndexCount = pFaceSet->NumIndices();
  1365. while ( nFirstIndex < nIndexCount )
  1366. {
  1367. int nVertexCount = pFaceSet->GetNextPolygonVertexCount( nFirstIndex );
  1368. if ( nVertexCount >= 3 )
  1369. {
  1370. int nOutCount = ( nVertexCount-2 ) * 3;
  1371. int *pIndices = (int*)_alloca( nOutCount * sizeof(int) );
  1372. ComputeTriangulatedIndices( pBaseState, pFaceSet, nFirstIndex, pIndices, nOutCount );
  1373. for ( int ii = 0; ii < nOutCount; ii += 3 )
  1374. {
  1375. int t = triangles.AddToTail();
  1376. Triangle_t& triangle = triangles[t];
  1377. triangle.m_nIndex[0] = pIndices[ii];
  1378. triangle.m_nIndex[1] = pIndices[ii+1];
  1379. triangle.m_nIndex[2] = pIndices[ii+2];
  1380. if ( pVertToTriMap )
  1381. {
  1382. (*pVertToTriMap)[ pIndices[ii] ].AddToTail( t );
  1383. (*pVertToTriMap)[ pIndices[ii+1] ].AddToTail( t );
  1384. (*pVertToTriMap)[ pIndices[ii+2] ].AddToTail( t );
  1385. }
  1386. }
  1387. }
  1388. nFirstIndex += nVertexCount + 1;
  1389. }
  1390. }
  1391. //-----------------------------------------------------------------------------
  1392. // Computes tangent space data for triangles
  1393. //-----------------------------------------------------------------------------
  1394. void CDmeMesh::ComputeTriangleTangets( const CDmeVertexData *pVertexData, CUtlVector<Triangle_t>& triangles )
  1395. {
  1396. // Calculate the tangent space for each triangle.
  1397. int nTriangleCount = triangles.Count();
  1398. for ( int triID = 0; triID < nTriangleCount; triID++ )
  1399. {
  1400. Triangle_t &triangle = triangles[triID];
  1401. const Vector &p0 = pVertexData->GetPosition( triangle.m_nIndex[0] );
  1402. const Vector &p1 = pVertexData->GetPosition( triangle.m_nIndex[1] );
  1403. const Vector &p2 = pVertexData->GetPosition( triangle.m_nIndex[2] );
  1404. const Vector2D &t0 = pVertexData->GetTexCoord( triangle.m_nIndex[0] );
  1405. const Vector2D &t1 = pVertexData->GetTexCoord( triangle.m_nIndex[1] );
  1406. const Vector2D &t2 = pVertexData->GetTexCoord( triangle.m_nIndex[2] );
  1407. CalcTriangleTangentSpace( p0, p1, p2, t0, t1, t2, triangle.m_vecTangentS, triangle.m_vecTangentT );
  1408. }
  1409. }
  1410. //-----------------------------------------------------------------------------
  1411. // Build a map from vertex index to a list of triangles that share the vert.
  1412. //-----------------------------------------------------------------------------
  1413. void CDmeMesh::ComputeAverageTangent( CDmeVertexData *pVertexData, bool bSmoothTangents, CUtlVector< CUtlVector<int> >& vertToTriMap, CUtlVector<Triangle_t>& triangles )
  1414. {
  1415. FieldIndex_t posField = pVertexData->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  1416. FieldIndex_t normalField = pVertexData->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  1417. FieldIndex_t tangentField = pVertexData->FindFieldIndex( CDmeVertexData::FIELD_TANGENT );
  1418. const CDmrArray<int> pPositionIndices = pVertexData->GetIndexData( posField );
  1419. const CDmrArray<Vector> pPositionData = pVertexData->GetVertexData( posField );
  1420. const CDmrArray<int> pNormalIndices = pVertexData->GetIndexData( normalField );
  1421. const CDmrArray<Vector> pNormalData = pVertexData->GetVertexData( normalField );
  1422. // calculate an average tangent space for each vertex.
  1423. int nVertexCount = pVertexData->VertexCount();
  1424. Vector4D finalSVect;
  1425. for( int vertID = 0; vertID < nVertexCount; vertID++ )
  1426. {
  1427. CUtlVector<int> &triangleList = vertToTriMap[vertID];
  1428. Vector sVect, tVect;
  1429. sVect.Init( 0.0f, 0.0f, 0.0f );
  1430. tVect.Init( 0.0f, 0.0f, 0.0f );
  1431. int nTriangleCount = triangleList.Count();
  1432. for ( int triID = 0; triID < nTriangleCount; triID++ )
  1433. {
  1434. Triangle_t &tri = triangles[ triangleList[triID] ];
  1435. sVect += tri.m_vecTangentS;
  1436. tVect += tri.m_vecTangentT;
  1437. }
  1438. // In the case of zbrush, everything needs to be treated as smooth.
  1439. if ( bSmoothTangents )
  1440. {
  1441. const Vector &vertPos1 = pPositionData.Get( pPositionIndices.Get( vertID ) );
  1442. for( int vertID2 = 0; vertID2 < nVertexCount; vertID2++ )
  1443. {
  1444. if ( vertID2 == vertID )
  1445. continue;
  1446. const Vector &vertPos2 = pPositionData.Get( pPositionIndices.Get( vertID2 ) );
  1447. if ( vertPos1 != vertPos2 )
  1448. continue;
  1449. CUtlVector<int> &triangleList2 = vertToTriMap[vertID2];
  1450. int nTriangleCount2 = triangleList2.Count();
  1451. for ( int triID2 = 0; triID2 < nTriangleCount2; triID2++ )
  1452. {
  1453. Triangle_t &tri2 = triangles[ triangleList2[triID2] ];
  1454. sVect += tri2.m_vecTangentS;
  1455. tVect += tri2.m_vecTangentT;
  1456. }
  1457. }
  1458. }
  1459. // make an orthonormal system.
  1460. // need to check if we are left or right handed.
  1461. Vector tmpVect;
  1462. CrossProduct( sVect, tVect, tmpVect );
  1463. const Vector &normal = pNormalData.Get( pNormalIndices.Get( vertID ) );
  1464. bool bLeftHanded = DotProduct( tmpVect, normal ) < 0.0f;
  1465. if ( !bLeftHanded )
  1466. {
  1467. CrossProduct( normal, sVect, tVect );
  1468. CrossProduct( tVect, normal, sVect );
  1469. VectorNormalize( sVect );
  1470. VectorNormalize( tVect );
  1471. finalSVect[0] = sVect[0];
  1472. finalSVect[1] = sVect[1];
  1473. finalSVect[2] = sVect[2];
  1474. finalSVect[3] = 1.0f;
  1475. }
  1476. else
  1477. {
  1478. CrossProduct( sVect, normal, tVect );
  1479. CrossProduct( normal, tVect, sVect );
  1480. VectorNormalize( sVect );
  1481. VectorNormalize( tVect );
  1482. finalSVect[0] = sVect[0];
  1483. finalSVect[1] = sVect[1];
  1484. finalSVect[2] = sVect[2];
  1485. finalSVect[3] = -1.0f;
  1486. }
  1487. pVertexData->SetVertexData( tangentField, vertID, 1, AT_VECTOR4, &finalSVect );
  1488. pVertexData->SetVertexIndices( tangentField, vertID, 1, &vertID );
  1489. }
  1490. }
  1491. //-----------------------------------------------------------------------------
  1492. // Builds a map from vertex index to all triangles that use it
  1493. //-----------------------------------------------------------------------------
  1494. void CDmeMesh::BuildVertToTriMap( const CDmeVertexData *pVertexData, CUtlVector<Triangle_t> &triangles, CUtlVector< CUtlVector<int> > &vertToTriMap )
  1495. {
  1496. vertToTriMap.AddMultipleToTail( pVertexData->VertexCount() );
  1497. int nCount = FaceSetCount();
  1498. for ( int i = 0; i < nCount; ++i )
  1499. {
  1500. CDmeFaceSet *pFaceSet = GetFaceSet( i );
  1501. BuildTriangleMap( pVertexData, pFaceSet, triangles, &vertToTriMap );
  1502. }
  1503. }
  1504. //-----------------------------------------------------------------------------
  1505. // Compute a default per-vertex tangent given normal data + uv data
  1506. //-----------------------------------------------------------------------------
  1507. void CDmeMesh::ComputeDefaultTangentData( CDmeVertexData *pVertexData, bool bSmoothTangents )
  1508. {
  1509. if ( !pVertexData )
  1510. return;
  1511. // Need to have valid pos, uv, and normal to perform this operation
  1512. FieldIndex_t posField = pVertexData->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  1513. FieldIndex_t normalField = pVertexData->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  1514. FieldIndex_t uvField = pVertexData->FindFieldIndex( CDmeVertexData::FIELD_TEXCOORD );
  1515. if ( posField < 0 || uvField < 0 || normalField < 0 )
  1516. return;
  1517. // FIXME: Need to do a pass to make sure no vertex is referenced by
  1518. // multiple facesets that have different materials in them.
  1519. // In that case, we need to add extra copies of that vertex and modify
  1520. // the face set data to refer to the new vertices
  1521. // Build a map from vertex to a list of triangles that share the vert.
  1522. CUtlVector<Triangle_t> triangles( 0, 1024 );
  1523. CUtlVector< CUtlVector<int> > vertToTriMap;
  1524. vertToTriMap.AddMultipleToTail( pVertexData->VertexCount() );
  1525. int nCount = FaceSetCount();
  1526. for ( int i = 0; i < nCount; ++i )
  1527. {
  1528. CDmeFaceSet *pFaceSet = GetFaceSet( i );
  1529. BuildTriangleMap( pVertexData, pFaceSet, triangles, &vertToTriMap );
  1530. }
  1531. ComputeTriangleTangets( pVertexData, triangles );
  1532. // FIXME: We could do a pass to determine the unique combinations of
  1533. // position + tangent indices in the vertex data. We only need to have
  1534. // a unique tangent for each of these unique vertices. For simplicity
  1535. // (and speed), I'll assume all tangents are unique per vertex.
  1536. FieldIndex_t tangent = pVertexData->CreateField<Vector4D>( "tangents" );
  1537. pVertexData->RemoveAllVertexData( tangent );
  1538. pVertexData->AddVertexData( tangent, pVertexData->VertexCount() );
  1539. ComputeAverageTangent( pVertexData, bSmoothTangents, vertToTriMap, triangles );
  1540. }
  1541. //-----------------------------------------------------------------------------
  1542. // Compute a default per-vertex tangent given normal data + uv data for all vertex data referenced by this mesh
  1543. //-----------------------------------------------------------------------------
  1544. void CDmeMesh::ComputeDefaultTangentData( bool bSmoothTangents )
  1545. {
  1546. const int nBaseStateCount = m_BaseStates.Count();
  1547. for ( int i = 0; i < nBaseStateCount; ++i )
  1548. {
  1549. if ( m_BaseStates[i] && m_BaseStates[i]->NeedsTangentData() )
  1550. {
  1551. ComputeDefaultTangentData( m_BaseStates[i], bSmoothTangents );
  1552. }
  1553. }
  1554. }
  1555. //-----------------------------------------------------------------------------
  1556. // Utility method to compute default tangent data on all meshes in the sub-dag hierarchy
  1557. //-----------------------------------------------------------------------------
  1558. void ComputeDefaultTangentData( CDmeDag *pDag, bool bSmoothTangents )
  1559. {
  1560. if ( !pDag )
  1561. return;
  1562. CDmeMesh *pMesh = CastElement< CDmeMesh >( pDag->GetShape() );
  1563. if ( pMesh )
  1564. {
  1565. pMesh->ComputeDefaultTangentData( bSmoothTangents );
  1566. }
  1567. int nChildCount = pDag->GetChildCount();
  1568. for ( int i = 0; i < nChildCount; ++i )
  1569. {
  1570. ComputeDefaultTangentData( pDag->GetChild( i ), bSmoothTangents );
  1571. }
  1572. }
  1573. //-----------------------------------------------------------------------------
  1574. // Compute the dimensionality of the delta state (how many inputs affect it)
  1575. //-----------------------------------------------------------------------------
  1576. int CDmeMesh::ComputeDeltaStateDimensionality( int nDeltaIndex )
  1577. {
  1578. CDmeVertexDeltaData *pDeltaState = GetDeltaState( nDeltaIndex );
  1579. const char *pDeltaStateName = pDeltaState->GetName();
  1580. const char *pUnderBar = pDeltaStateName;
  1581. int nDimensions = 0;
  1582. while ( pUnderBar )
  1583. {
  1584. ++nDimensions;
  1585. pUnderBar = strchr( pUnderBar, '_' );
  1586. if ( pUnderBar )
  1587. {
  1588. ++pUnderBar;
  1589. }
  1590. }
  1591. return nDimensions;
  1592. }
  1593. //-----------------------------------------------------------------------------
  1594. // Computes the aggregate position for all vertices after applying a set of delta states
  1595. //-----------------------------------------------------------------------------
  1596. void CDmeMesh::AddDelta( CDmeVertexData *pBaseState, Vector *pDeltaPosition, int nDeltaStateIndex, CDmeVertexData::StandardFields_t fieldId )
  1597. {
  1598. CDmeVertexDeltaData *pDeltaState = GetDeltaState( nDeltaStateIndex );
  1599. FieldIndex_t nFieldIndex = pDeltaState->FindFieldIndex( fieldId );
  1600. if ( nFieldIndex < 0 )
  1601. return;
  1602. if ( pBaseState->FindFieldIndex( CDmeVertexData::FIELD_BALANCE ) != -1 )
  1603. {
  1604. AddStereoVertexDelta<Vector>( pBaseState, pDeltaPosition, sizeof(Vector), fieldId, nDeltaStateIndex, true );
  1605. }
  1606. else
  1607. {
  1608. AddVertexDelta<Vector>( pBaseState, pDeltaPosition, sizeof(Vector), fieldId, nDeltaStateIndex, true );
  1609. }
  1610. }
  1611. //-----------------------------------------------------------------------------
  1612. // Computes correctly averaged vertex normals from position data
  1613. //-----------------------------------------------------------------------------
  1614. void CDmeMesh::ComputeNormalsFromPositions(
  1615. CDmeVertexData *pBase,
  1616. const Vector *pPosition,
  1617. const CUtlVector<Triangle_t> &triangles,
  1618. int nNormalCount,
  1619. Vector *pNormals )
  1620. {
  1621. Assert( nNormalCount == pBase->GetNormalData().Count() );
  1622. int *pNormalsAdded = (int*)_alloca( nNormalCount * sizeof(int) );
  1623. memset( pNormalsAdded, 0, nNormalCount * sizeof(int) );
  1624. memset( pNormals, 0, nNormalCount * sizeof(Vector) );
  1625. const CUtlVector<int> &positionIndices = pBase->GetVertexIndexData( CDmeVertexData::FIELD_POSITION );
  1626. const CUtlVector<int> &normalIndices = pBase->GetVertexIndexData( CDmeVertexData::FIELD_NORMAL );
  1627. int nTriangleCount = triangles.Count();
  1628. for ( int i = 0; i < nTriangleCount; ++i )
  1629. {
  1630. const Triangle_t &tri = triangles[i];
  1631. int p1 = positionIndices[ tri.m_nIndex[0] ];
  1632. int p2 = positionIndices[ tri.m_nIndex[1] ];
  1633. int p3 = positionIndices[ tri.m_nIndex[2] ];
  1634. int n1 = normalIndices[ tri.m_nIndex[0] ];
  1635. int n2 = normalIndices[ tri.m_nIndex[1] ];
  1636. int n3 = normalIndices[ tri.m_nIndex[2] ];
  1637. Vector vecDelta, vecDelta2, vecNormal;
  1638. VectorSubtract( pPosition[p2], pPosition[p1], vecDelta );
  1639. VectorSubtract( pPosition[p3], pPosition[p1], vecDelta2 );
  1640. CrossProduct( vecDelta, vecDelta2, vecNormal );
  1641. VectorNormalize( vecNormal );
  1642. pNormals[n1] += vecNormal;
  1643. pNormals[n2] += vecNormal;
  1644. pNormals[n3] += vecNormal;
  1645. ++pNormalsAdded[n1]; ++pNormalsAdded[n2]; ++pNormalsAdded[n3];
  1646. }
  1647. for ( int i = 0; i < nNormalCount; ++i )
  1648. {
  1649. if ( pNormalsAdded[i] > 0 )
  1650. {
  1651. pNormals[i] /= pNormalsAdded[i];
  1652. VectorNormalize( pNormals[i] );
  1653. }
  1654. else
  1655. {
  1656. pNormals[i].Init( 0, 1, 0 );
  1657. }
  1658. }
  1659. }
  1660. //-----------------------------------------------------------------------------
  1661. // Converts pose-space normals into deltas appropriate for correction delta states
  1662. //-----------------------------------------------------------------------------
  1663. void CDmeMesh::ComputeCorrectedNormalsFromActualNormals( const CUtlVector<int> &deltaStateList, int nNormalCount, Vector *pNormals )
  1664. {
  1665. CDmeVertexData *pBind = GetBindBaseState();
  1666. if ( !pBind )
  1667. return;
  1668. Assert( nNormalCount == pBind->GetNormalData().Count() );
  1669. // Subtract out all other normal contributions
  1670. Vector *pUncorrectedNormals = (Vector*)_alloca( nNormalCount * sizeof(Vector) );
  1671. memcpy( pUncorrectedNormals, pBind->GetNormalData().Base(), nNormalCount * sizeof( Vector ) );
  1672. int nDeltaStateCount = deltaStateList.Count();
  1673. for ( int i = 0; i < nDeltaStateCount; ++i )
  1674. {
  1675. AddDelta( pBind, pUncorrectedNormals, deltaStateList[i], CDmeVertexData::FIELD_NORMAL );
  1676. }
  1677. for ( int i = 0; i < nNormalCount; ++i )
  1678. {
  1679. pNormals[i] -= pUncorrectedNormals[i];
  1680. }
  1681. }
  1682. //-----------------------------------------------------------------------------
  1683. // Copies the corrected normal data into a delta state
  1684. //-----------------------------------------------------------------------------
  1685. void CDmeMesh::SetDeltaNormalData( int nDeltaIndex, int nNormalCount, Vector *pNormals )
  1686. {
  1687. // pNormals represents the correct normal delta state for this combination
  1688. // Copy it into the delta state for this combination.
  1689. // Use tolerance to deal with precision errors introduced by the various computations
  1690. CDmeVertexDeltaData *pDeltaState = GetDeltaState( nDeltaIndex );
  1691. FieldIndex_t nNormalField = pDeltaState->FindFieldIndex( CDmeVertexDeltaData::FIELD_NORMAL );
  1692. if ( nNormalField >= 0 )
  1693. {
  1694. pDeltaState->RemoveAllVertexData( nNormalField );
  1695. }
  1696. else
  1697. {
  1698. nNormalField = pDeltaState->CreateField( CDmeVertexDeltaData::FIELD_NORMAL );
  1699. }
  1700. for ( int i = 0; i < nNormalCount; ++i )
  1701. {
  1702. if ( pNormals[i].LengthSqr() < 1e-4 )
  1703. continue;
  1704. int nNormalIndex = pDeltaState->AddVertexData( nNormalField, 1 );
  1705. pDeltaState->SetVertexData( nNormalField, nNormalIndex, 1, AT_VECTOR3, &pNormals[i] );
  1706. pDeltaState->SetVertexIndices( nNormalField, nNormalIndex, 1, &i );
  1707. }
  1708. }
  1709. //-----------------------------------------------------------------------------
  1710. // Discovers the atomic controls used by the various delta states
  1711. //-----------------------------------------------------------------------------
  1712. static int DeltaStateUsageLessFunc( const int * lhs, const int * rhs )
  1713. {
  1714. return *lhs - *rhs;
  1715. }
  1716. //-----------------------------------------------------------------------------
  1717. //
  1718. //-----------------------------------------------------------------------------
  1719. void CDmeMesh::BuildAtomicControlLists( int nCount, DeltaComputation_t *pInfo, CUtlVector< CUtlVector< int > > &deltaStateUsage )
  1720. {
  1721. CUtlVector< CUtlString > atomicControls;
  1722. deltaStateUsage.SetCount( nCount );
  1723. // Build a list of atomic controls
  1724. int nCurrentDelta;
  1725. for ( nCurrentDelta = 0; nCurrentDelta < nCount; ++nCurrentDelta )
  1726. {
  1727. if ( pInfo[nCurrentDelta].m_nDimensionality != 1 )
  1728. break;
  1729. int j = atomicControls.AddToTail( GetDeltaState( pInfo[nCurrentDelta].m_nDeltaIndex )->GetName() );
  1730. deltaStateUsage[ nCurrentDelta ].AddToTail( j );
  1731. }
  1732. for ( ; nCurrentDelta < nCount; ++nCurrentDelta )
  1733. {
  1734. CDmeVertexDeltaData *pDeltaState = GetDeltaState( pInfo[nCurrentDelta].m_nDeltaIndex );
  1735. int nLen = Q_strlen( pDeltaState->GetName() );
  1736. char *pTempBuf = (char*)_alloca( nLen + 1 );
  1737. memcpy( pTempBuf, pDeltaState->GetName(), nLen+1 );
  1738. char *pNext;
  1739. for ( char *pUnderBar = pTempBuf; pUnderBar; pUnderBar = pNext )
  1740. {
  1741. pNext = strchr( pUnderBar, '_' );
  1742. if ( pNext )
  1743. {
  1744. *pNext = 0;
  1745. ++pNext;
  1746. }
  1747. // Find this name in the list of strings
  1748. int j;
  1749. int nControlCount = atomicControls.Count();
  1750. for ( j = 0; j < nControlCount; ++j )
  1751. {
  1752. if ( !Q_stricmp( pUnderBar, atomicControls[j] ) )
  1753. break;
  1754. }
  1755. if ( j == nControlCount )
  1756. {
  1757. j = atomicControls.AddToTail( pUnderBar );
  1758. }
  1759. deltaStateUsage[ nCurrentDelta ].AddToTail( j );
  1760. }
  1761. deltaStateUsage[ nCurrentDelta ].Sort( DeltaStateUsageLessFunc );
  1762. }
  1763. }
  1764. //-----------------------------------------------------------------------------
  1765. // Construct list of all n-1 -> 1 dimensional delta states
  1766. // that will be active when this delta state is active
  1767. //-----------------------------------------------------------------------------
  1768. void CDmeMesh::ComputeDependentDeltaStateList( CUtlVector< DeltaComputation_t > &compList )
  1769. {
  1770. if ( compList.Count() == 0 )
  1771. {
  1772. ComputeDeltaStateComputationList( compList );
  1773. }
  1774. CUtlVector< CUtlVector< int > > deltaStateUsage;
  1775. const int nCount( compList.Count() );
  1776. BuildAtomicControlLists( nCount, compList.Base(), deltaStateUsage );
  1777. // Now build up a list of dependent delta states based on usage
  1778. // NOTE: Usage is sorted in ascending order.
  1779. for ( int i = 1; i < nCount; ++i )
  1780. {
  1781. int nUsageCount1 = deltaStateUsage[i].Count();
  1782. for ( int j = 0; j < i; ++j )
  1783. {
  1784. // At the point they have the same dimensionality, no more need to check
  1785. if ( compList[j].m_nDimensionality == compList[i].m_nDimensionality )
  1786. break;
  1787. int ii = 0;
  1788. bool bSubsetFound = true;
  1789. int nUsageCount2 = deltaStateUsage[j].Count();
  1790. for ( int ji = 0; ji < nUsageCount2; ++ji )
  1791. {
  1792. for ( bSubsetFound = false; ii < nUsageCount1; ++ii )
  1793. {
  1794. if ( deltaStateUsage[j][ji] == deltaStateUsage[i][ii] )
  1795. {
  1796. ++ii;
  1797. bSubsetFound = true;
  1798. break;
  1799. }
  1800. if ( deltaStateUsage[j][ji] < deltaStateUsage[i][ii] )
  1801. break;
  1802. }
  1803. if ( !bSubsetFound )
  1804. break;
  1805. }
  1806. if ( bSubsetFound )
  1807. {
  1808. compList[i].m_DependentDeltas.AddToTail( compList[j].m_nDeltaIndex );
  1809. }
  1810. }
  1811. }
  1812. }
  1813. //-----------------------------------------------------------------------------
  1814. // Sorts DeltaComputation_t's by dimensionality
  1815. //-----------------------------------------------------------------------------
  1816. int CDmeMesh::DeltaStateLessFunc( const void * lhs, const void * rhs )
  1817. {
  1818. DeltaComputation_t &info1 = *(DeltaComputation_t*)lhs;
  1819. DeltaComputation_t &info2 = *(DeltaComputation_t*)rhs;
  1820. return info1.m_nDimensionality - info2.m_nDimensionality;
  1821. }
  1822. //-----------------------------------------------------------------------------
  1823. // Generates a sorted list in order of dimensionality of the delta states
  1824. // NOTE: This assumes a naming scheme where delta state names have _ that separate control names
  1825. //-----------------------------------------------------------------------------
  1826. void CDmeMesh::ComputeDeltaStateComputationList( CUtlVector< DeltaComputation_t > &compList )
  1827. {
  1828. // Do all combinations in order of dimensionality, lowest dimension first
  1829. const int nCount = DeltaStateCount();
  1830. compList.EnsureCount( nCount ); // Resets the CUtlVector
  1831. for ( int i = 0; i < nCount; ++i )
  1832. {
  1833. compList[i].m_nDeltaIndex = i;
  1834. compList[i].m_nDimensionality = ComputeDeltaStateDimensionality( i );
  1835. }
  1836. qsort( compList.Base(), nCount, sizeof(DeltaComputation_t), DeltaStateLessFunc );
  1837. }
  1838. //-----------------------------------------------------------------------------
  1839. // Computes normal deltas for all delta states based on position deltas
  1840. // NOTE: This assumes a naming scheme where delta state names have _ that separate control names
  1841. //-----------------------------------------------------------------------------
  1842. void CDmeMesh::ComputeDeltaStateNormals()
  1843. {
  1844. CDmeVertexData *pBind = GetBindBaseState();
  1845. if ( !pBind )
  1846. return;
  1847. const FieldIndex_t nBindNormalIndex = pBind->CreateField( CDmeVertexData::FIELD_NORMAL );
  1848. const CUtlVector< Vector > &basePosData = pBind->GetPositionData();
  1849. const int nPosCount = basePosData.Count();
  1850. // Build a map from vertex to a list of triangles that share the vert.
  1851. CUtlVector< Triangle_t > triangles( 0, 1024 );
  1852. CUtlVector< CUtlVector<int> > vertToTriMap;
  1853. vertToTriMap.AddMultipleToTail( pBind->VertexCount() );
  1854. const int nFaceSetCount = FaceSetCount();
  1855. for ( int i = 0; i < nFaceSetCount; ++i )
  1856. {
  1857. CDmeFaceSet *pFaceSet = GetFaceSet( i );
  1858. BuildTriangleMap( pBind, pFaceSet, triangles, &vertToTriMap );
  1859. }
  1860. // Temporary storage for normals
  1861. Vector *pNormals = reinterpret_cast< Vector * >( alloca( nPosCount * sizeof( Vector ) ) );
  1862. // Make all of the normals in the bind pose smooth
  1863. {
  1864. const CUtlVector< int > &basePosIndices = pBind->GetVertexIndexData( CDmeVertexData::FIELD_POSITION );
  1865. pBind->SetVertexIndices( nBindNormalIndex, 0, basePosIndices.Count(), basePosIndices.Base() );
  1866. pBind->RemoveAllVertexData( nBindNormalIndex );
  1867. pBind->AddVertexData( nBindNormalIndex, nPosCount );
  1868. ComputeNormalsFromPositions( pBind, basePosData.Base(), triangles, nPosCount, pNormals );
  1869. pBind->SetVertexData( nBindNormalIndex, 0, nPosCount, AT_VECTOR3, pNormals );
  1870. // Fix up the current state to have smooth normals if current is not bind
  1871. CDmeVertexData *pCurrent = GetCurrentBaseState();
  1872. if ( pCurrent != pBind )
  1873. {
  1874. const FieldIndex_t nCurrentNormalIndex = pCurrent->CreateField( CDmeVertexData::FIELD_NORMAL );
  1875. pCurrent->SetVertexIndices( nCurrentNormalIndex, 0, basePosIndices.Count(), basePosIndices.Base() );
  1876. pCurrent->RemoveAllVertexData( nCurrentNormalIndex );
  1877. pCurrent->AddVertexData( nCurrentNormalIndex, nPosCount );
  1878. const CUtlVector< Vector > &currPosData = pCurrent->GetPositionData();
  1879. ComputeNormalsFromPositions( pCurrent, currPosData.Base(), triangles, nPosCount, pNormals );
  1880. pCurrent->SetVertexData( nCurrentNormalIndex, 0, nPosCount, AT_VECTOR3, pNormals );
  1881. }
  1882. }
  1883. // Temporary storage for the positions
  1884. Vector *pPosData = reinterpret_cast< Vector * >( alloca( nPosCount * sizeof( Vector ) ) );
  1885. // Compute the dependent delta state list like thing
  1886. CUtlVector< DeltaComputation_t > computationOrder;
  1887. ComputeDependentDeltaStateList( computationOrder );
  1888. const int nDeltaStateCount = computationOrder.Count();
  1889. for ( int i = 0; i < nDeltaStateCount; ++i )
  1890. {
  1891. const DeltaComputation_t &deltaComputation = computationOrder[ i ];
  1892. memcpy( pPosData, basePosData.Base(), nPosCount * sizeof( Vector ) );
  1893. const CUtlVector< int > &depDeltas = deltaComputation.m_DependentDeltas;
  1894. const int nDepStateCount = depDeltas.Count();
  1895. for ( int j = 0; j < nDepStateCount; ++j )
  1896. {
  1897. AddDelta( GetDeltaState( depDeltas[ j ] ), pPosData, nPosCount, CDmeVertexData::FIELD_POSITION );
  1898. }
  1899. AddDelta( GetDeltaState( deltaComputation.m_nDeltaIndex ), pPosData, nPosCount, CDmeVertexData::FIELD_POSITION );
  1900. ComputeNormalsFromPositions( pBind, pPosData, triangles, nPosCount, pNormals );
  1901. SetDeltaNormalDataFromActualNormals( computationOrder[ i ].m_nDeltaIndex, depDeltas, nPosCount, pNormals );
  1902. }
  1903. }
  1904. //-----------------------------------------------------------------------------
  1905. // Computes normal deltas for all delta states based on position deltas
  1906. // NOTE: This assumes a naming scheme where delta state names have _ that separate control names
  1907. //-----------------------------------------------------------------------------
  1908. void CDmeMesh::SetDeltaNormalDataFromActualNormals( int nDeltaIndex, const CUtlVector<int> &deltaStateList, int nNormalCount, Vector *pNormals )
  1909. {
  1910. // Store off the current state values
  1911. CUtlVector< Vector2D > deltaStateWeights[MESH_DELTA_WEIGHT_TYPE_COUNT];
  1912. for ( int i = 0; i < MESH_DELTA_WEIGHT_TYPE_COUNT; ++i )
  1913. {
  1914. deltaStateWeights[i] = m_DeltaStateWeights[i].Get();
  1915. // Turn on the current weights to all be 1 to get max effect of morphs
  1916. int nCount = m_DeltaStateWeights[i].Count();
  1917. for ( int j = 0; j < nCount; ++j )
  1918. {
  1919. m_DeltaStateWeights[i].Set( j, Vector2D( 1.0f, 1.0f ) );
  1920. }
  1921. }
  1922. ComputeCorrectedNormalsFromActualNormals( deltaStateList, nNormalCount, pNormals );
  1923. // Finally, store the corrected normals into the delta state
  1924. SetDeltaNormalData( nDeltaIndex, nNormalCount, pNormals );
  1925. // Restore weights to their current value
  1926. for ( int i = 0; i < MESH_DELTA_WEIGHT_TYPE_COUNT; ++i )
  1927. {
  1928. m_DeltaStateWeights[i] = deltaStateWeights[i];
  1929. }
  1930. }
  1931. //-----------------------------------------------------------------------------
  1932. // A recursive algorithm to compute nCk, i.e. the number of order independent
  1933. // Combinations without any repeats of k items taking n at a time
  1934. // The size of the returned array is:
  1935. //
  1936. // n!
  1937. // -------------
  1938. // k! ( n - r )!
  1939. //
  1940. // e.g. 4C4 = { 0 1 2 3 }
  1941. // e.g. 3C4 = { 0 1 2 }, { 0 1 3 }, { 0 2 3 }, { 1 2 3 }
  1942. // e.g. 2C4 = { 0 1 }, { 0 2 }, { 0 3 }, { 1 2 }, { 1 3 }, { 2 3 }
  1943. // e.g. 1C4 = { 0 }, { 1 }, { 2 }, { 3 }
  1944. //
  1945. // It's recursive and meant to be called by the user with just n, k and combos
  1946. // the other default arguments are for the recursive steps
  1947. //-----------------------------------------------------------------------------
  1948. void CDmeMesh::Combinations(
  1949. int n,
  1950. int k,
  1951. CUtlVector< CUtlVector< int > > &combos,
  1952. int *pTmpArray,
  1953. int start,
  1954. int currentK )
  1955. {
  1956. if ( !pTmpArray )
  1957. {
  1958. pTmpArray = reinterpret_cast< int * >( alloca( k * sizeof( int ) ) );
  1959. memset( pTmpArray, 0, k * sizeof( int ) );
  1960. }
  1961. if ( currentK >= k )
  1962. {
  1963. combos[ combos.AddToTail() ].CopyArray( pTmpArray, k );
  1964. return;
  1965. }
  1966. for ( int i( start ); i < n; ++i )
  1967. {
  1968. pTmpArray[ currentK ] = i;
  1969. Combinations( n, k, combos, pTmpArray, i + 1, currentK + 1 );
  1970. }
  1971. }
  1972. //-----------------------------------------------------------------------------
  1973. // Takes an incoming Delta state, splits it's name '_' and then finds the
  1974. // control delta (a state without a '_' in its name) and adds the index
  1975. // of that control delta to the referenced array
  1976. //
  1977. // Returns true if all of the control states exist, false otherwise
  1978. //-----------------------------------------------------------------------------
  1979. bool CDmeMesh::GetControlDeltaIndices(
  1980. CDmeVertexDeltaData *pDeltaState,
  1981. CUtlVector< int > &controlDeltaIndices ) const
  1982. {
  1983. Assert( pDeltaState );
  1984. return GetControlDeltaIndices( pDeltaState->GetName(), controlDeltaIndices );
  1985. }
  1986. //-----------------------------------------------------------------------------
  1987. // Same as above but just uses the name of a delta
  1988. //-----------------------------------------------------------------------------
  1989. bool CDmeMesh::GetControlDeltaIndices(
  1990. const char *pDeltaStateName,
  1991. CUtlVector< int > &controlDeltaIndices ) const
  1992. {
  1993. Assert( pDeltaStateName );
  1994. controlDeltaIndices.RemoveAll();
  1995. const int nDeltaStateName( Q_strlen( pDeltaStateName ) );
  1996. char *pTmpBuf( reinterpret_cast< char * >( alloca( nDeltaStateName + 1 ) ) );
  1997. Q_strncpy( pTmpBuf, pDeltaStateName, nDeltaStateName + 1 );
  1998. char *pNext;
  1999. for ( char *pCurr = pTmpBuf; pCurr; pCurr = pNext )
  2000. {
  2001. pNext = strchr( pCurr, '_' );
  2002. if ( pNext )
  2003. {
  2004. *pNext = '\0';
  2005. ++pNext;
  2006. }
  2007. if ( Q_strlen( pCurr ) )
  2008. {
  2009. const int controlDeltaIndex( FindDeltaStateIndex( pCurr ) );
  2010. if ( controlDeltaIndex >= 0 )
  2011. {
  2012. controlDeltaIndices.AddToTail( controlDeltaIndex );
  2013. }
  2014. else
  2015. {
  2016. controlDeltaIndices.RemoveAll();
  2017. return false;
  2018. }
  2019. }
  2020. }
  2021. return true;
  2022. }
  2023. //-----------------------------------------------------------------------------
  2024. // Builds a list of all of the underlying control delta indices for each
  2025. // delta state in the mesh
  2026. //
  2027. // e.g. Say the delta states are (in this order): A, B, C, A_C, A_B_C
  2028. //
  2029. // Will build: {
  2030. // { 0 },
  2031. // { 1 },
  2032. // { 2 },
  2033. // { 0, 2 },
  2034. // { 0, 1, 2 }
  2035. // }
  2036. //
  2037. // Returns true if all of the control states exist, false otherwise
  2038. //-----------------------------------------------------------------------------
  2039. bool CDmeMesh::BuildCompleteDeltaStateControlList(
  2040. CUtlVector< CUtlVector< int > > &deltaStateControlList ) const
  2041. {
  2042. deltaStateControlList.RemoveAll();
  2043. CUtlVector< int > tmpControlDeltaIndices;
  2044. const int nDeltas( m_DeltaStates.Count() );
  2045. for ( int i = 0; i < nDeltas; ++i )
  2046. {
  2047. if ( !GetControlDeltaIndices( m_DeltaStates[ i ], tmpControlDeltaIndices ) )
  2048. return false;
  2049. deltaStateControlList[ deltaStateControlList.AddToTail() ].CopyArray( tmpControlDeltaIndices.Base(), tmpControlDeltaIndices.Count() );
  2050. }
  2051. return true;
  2052. }
  2053. //-----------------------------------------------------------------------------
  2054. // Searches controlList for a sub array that has exactly the same indices as
  2055. // controlIndices. The order of the indices do not have to match but all of
  2056. // them must be present and no extras can be present.
  2057. // It assumes that the controlList is in the same order as m_deltaStates
  2058. //-----------------------------------------------------------------------------
  2059. int CDmeMesh::FindDeltaIndexFromControlIndices(
  2060. const CUtlVector< int > &controlIndices,
  2061. const CUtlVector< CUtlVector< int > > &controlList ) const
  2062. {
  2063. const int nControlIndices( controlIndices.Count() );
  2064. const int nControlList( controlList.Count() );
  2065. int nControlListIndices;
  2066. int foundCount;
  2067. for ( int i = 0; i < nControlList; ++i )
  2068. {
  2069. const CUtlVector< int > &controlListIndices( controlList[ i ] );
  2070. nControlListIndices = controlListIndices.Count();
  2071. if ( nControlListIndices == nControlIndices )
  2072. {
  2073. foundCount = 0;
  2074. for ( int j( 0 ); j < nControlListIndices; ++j )
  2075. {
  2076. for ( int k( 0 ); k < nControlIndices; ++k )
  2077. {
  2078. if ( controlListIndices[ j ] == controlIndices[ k ] )
  2079. {
  2080. ++foundCount;
  2081. break;
  2082. }
  2083. }
  2084. }
  2085. if ( foundCount == nControlIndices )
  2086. return i;
  2087. }
  2088. }
  2089. return -1;
  2090. }
  2091. //-----------------------------------------------------------------------------
  2092. // Builds a list of all of the required underlying deltas that make up this
  2093. // state whether that do not exist. All of the control deltas must exist
  2094. // though (Deltas without '_' in their name).
  2095. //
  2096. // e.g. Say only Delta states A, B, C, D, A_B_C_D exist and A_B_C_D is
  2097. // passed in. This function will return:
  2098. //
  2099. // A_B_C, A_B_D, A_C_D, B_C_D, A_B, A_C, A_D, B_C, B_D, C_D
  2100. //
  2101. // Returns true if all of the control states exist, false otherwise
  2102. //-----------------------------------------------------------------------------
  2103. bool CDmeMesh::BuildMissingDependentDeltaList(
  2104. CDmeVertexDeltaData *pDeltaState,
  2105. CUtlVector< int > &controlIndices,
  2106. CUtlVector< CUtlVector< int > > &dependentStates ) const
  2107. {
  2108. dependentStates.RemoveAll();
  2109. CUtlVector< CUtlVector< int > > deltaStateControlList;
  2110. BuildCompleteDeltaStateControlList( deltaStateControlList );
  2111. if ( !GetControlDeltaIndices( pDeltaState, controlIndices ) )
  2112. return false;
  2113. const int nControlIndices( controlIndices.Count() );
  2114. CUtlVector< int > comboControls;
  2115. for ( int i( nControlIndices - 1 ); i > 0; --i )
  2116. {
  2117. CUtlVector< CUtlVector< int > > combos;
  2118. Combinations( nControlIndices, i, combos );
  2119. const int nCombos( combos.Count() );
  2120. for ( int j( 0 ); j < nCombos; ++j )
  2121. {
  2122. const CUtlVector< int > &comboIndices( combos[ j ] );
  2123. const int nComboIndices( comboIndices.Count() );
  2124. if ( comboIndices.Count() )
  2125. {
  2126. comboControls.RemoveAll();
  2127. comboControls.EnsureCapacity( nComboIndices );
  2128. for ( int k( 0 ); k < nComboIndices; ++k )
  2129. {
  2130. comboControls.AddToTail( controlIndices[ comboIndices[ k ] ] );
  2131. }
  2132. if ( FindDeltaIndexFromControlIndices( comboControls, deltaStateControlList) < 0 )
  2133. {
  2134. dependentStates[ dependentStates.AddToTail() ].CopyArray( comboControls.Base(), comboControls.Count() );
  2135. }
  2136. }
  2137. }
  2138. }
  2139. return true;
  2140. }
  2141. //-----------------------------------------------------------------------------
  2142. //
  2143. //-----------------------------------------------------------------------------
  2144. template < class T_t >
  2145. int CDmeMesh::GenerateCompleteDataForDelta(
  2146. const CDmeVertexDeltaData *pDelta,
  2147. T_t *pFullData,
  2148. int nFullData,
  2149. CDmeVertexData::StandardFields_t standardField )
  2150. {
  2151. memset( pFullData, 0, nFullData * sizeof( T_t ) );
  2152. const FieldIndex_t fIndex( pDelta->FindFieldIndex( standardField ) );
  2153. if ( fIndex >= 0 )
  2154. {
  2155. CDmrArrayConst< T_t > fDataArray( pDelta->GetVertexData( fIndex ) );
  2156. const CUtlVector< T_t > &fData( fDataArray.Get() );
  2157. const CUtlVector< int > &fIndexData( pDelta->GetVertexIndexData( fIndex ) );
  2158. const int nIndexData( fIndexData.Count() );
  2159. Assert( nIndexData <= nFullData );
  2160. int index;
  2161. int i( 0 );
  2162. for ( int j( 0 ); j < nIndexData; ++j )
  2163. {
  2164. index = fIndexData[ j ];
  2165. while ( index > i )
  2166. {
  2167. ++i;
  2168. }
  2169. Assert( i < nFullData );
  2170. pFullData[ i ] = fData[ j ];
  2171. }
  2172. return nIndexData;
  2173. }
  2174. return 0;
  2175. }
  2176. //-----------------------------------------------------------------------------
  2177. //
  2178. //-----------------------------------------------------------------------------
  2179. template < class T_t >
  2180. void CDmeMesh::AddDelta(
  2181. const CDmeVertexDeltaData *pDelta,
  2182. T_t *pFullData,
  2183. int nFullData,
  2184. FieldIndex_t fieldIndex,
  2185. float weight,
  2186. const CDmeSingleIndexedComponent *pMask )
  2187. {
  2188. if ( fieldIndex >= 0 )
  2189. {
  2190. CDmrArrayConst< T_t > fDataArray( pDelta->GetVertexData( fieldIndex ) );
  2191. const CUtlVector< T_t > &fData( fDataArray.Get() );
  2192. const CUtlVector< int > &fIndexData( pDelta->GetVertexIndexData( fieldIndex ) );
  2193. const int nIndexData( fIndexData.Count() );
  2194. T_t t;
  2195. Assert( nIndexData <= nFullData );
  2196. int index;
  2197. int i( 0 );
  2198. if ( pMask )
  2199. {
  2200. float cWeight;
  2201. for ( int j( 0 ); j < nIndexData; ++j )
  2202. {
  2203. index = fIndexData[ j ];
  2204. if ( !pMask->GetWeight( index, cWeight ) )
  2205. continue;
  2206. while ( index > i )
  2207. {
  2208. ++i;
  2209. }
  2210. Assert( i < nFullData );
  2211. t = fData[ j ];
  2212. t *= ( weight * cWeight );
  2213. pFullData[ i ] += t;
  2214. }
  2215. }
  2216. else
  2217. {
  2218. for ( int j( 0 ); j < nIndexData; ++j )
  2219. {
  2220. index = fIndexData[ j ];
  2221. while ( index > i )
  2222. {
  2223. ++i;
  2224. }
  2225. Assert( i < nFullData );
  2226. t = fData[ j ];
  2227. t *= weight;
  2228. pFullData[ i ] += t;
  2229. }
  2230. }
  2231. }
  2232. }
  2233. template void CDmeMesh::AddDelta< float >( const CDmeVertexDeltaData *, float *, int, FieldIndex_t, float, const CDmeSingleIndexedComponent * );
  2234. template void CDmeMesh::AddDelta< Vector2D >( const CDmeVertexDeltaData *, Vector2D *, int, FieldIndex_t, float, const CDmeSingleIndexedComponent * );
  2235. template void CDmeMesh::AddDelta< Vector >( const CDmeVertexDeltaData *, Vector *, int, FieldIndex_t, float, const CDmeSingleIndexedComponent * );
  2236. //-----------------------------------------------------------------------------
  2237. //
  2238. //-----------------------------------------------------------------------------
  2239. template < class T_t >
  2240. void CDmeMesh::AddDelta(
  2241. const CDmeVertexDeltaData *pDelta,
  2242. T_t *pFullData,
  2243. int nFullData,
  2244. CDmeVertexData::StandardFields_t standardField,
  2245. float weight,
  2246. const CDmeSingleIndexedComponent *pMask )
  2247. {
  2248. const FieldIndex_t fIndex( pDelta->FindFieldIndex( standardField ) );
  2249. AddDelta( pDelta, pFullData, nFullData, fIndex, weight, pMask );
  2250. }
  2251. template void CDmeMesh::AddDelta< float >( const CDmeVertexDeltaData *, float *, int, CDmeVertexData::StandardFields_t, float, const CDmeSingleIndexedComponent * );
  2252. template void CDmeMesh::AddDelta< Vector2D >( const CDmeVertexDeltaData *, Vector2D *, int, CDmeVertexData::StandardFields_t, float, const CDmeSingleIndexedComponent * );
  2253. template void CDmeMesh::AddDelta< Vector >( const CDmeVertexDeltaData *, Vector *, int, CDmeVertexData::StandardFields_t, float, const CDmeSingleIndexedComponent * );
  2254. //-----------------------------------------------------------------------------
  2255. //
  2256. //-----------------------------------------------------------------------------
  2257. void CDmeMesh::ComputeAllCorrectedPositionsFromActualPositions()
  2258. {
  2259. const CDmeVertexData *pBase = GetBindBaseState();
  2260. if ( !pBase )
  2261. return;
  2262. CUtlVector< DeltaComputation_t > deltaList;
  2263. ComputeDependentDeltaStateList( deltaList );
  2264. const int nDeltas( deltaList.Count() );
  2265. const int nPositions( pBase->GetPositionData().Count() );
  2266. Vector *pPositions( reinterpret_cast< Vector * >( alloca( nPositions * sizeof( Vector ) ) ) );
  2267. int *pIndices( reinterpret_cast< int * >( alloca( nPositions * sizeof( int ) ) ) );
  2268. int pCount;
  2269. for ( int i = 0; i < nDeltas; ++i )
  2270. {
  2271. const DeltaComputation_t &deltaComputation( deltaList[ i ] );
  2272. CDmeVertexDeltaData *pDelta( m_DeltaStates[ deltaComputation.m_nDeltaIndex ] );
  2273. if ( !pDelta->GetValue< bool >( "corrected" ) )
  2274. {
  2275. const FieldIndex_t pIndex( pDelta->FindFieldIndex( CDmeVertexDeltaData::FIELD_POSITION ) );
  2276. if ( pIndex < 0 )
  2277. continue;
  2278. GenerateCompleteDataForDelta( pDelta, pPositions, nPositions, CDmeVertexData::FIELD_POSITION );
  2279. const CUtlVector< int > &dependentDeltas( deltaComputation.m_DependentDeltas );
  2280. const int nDependentDeltas( dependentDeltas.Count() );
  2281. for ( int j( 0 ); j < nDependentDeltas; ++j )
  2282. {
  2283. const CDmeVertexDeltaData *pDependentDelta( m_DeltaStates[ dependentDeltas[ j ] ] );
  2284. const CUtlVector< Vector > &dPositions( pDependentDelta->GetPositionData() );
  2285. const CUtlVector<int> &dIndices( pDependentDelta->GetVertexIndexData( CDmeVertexData::FIELD_POSITION ) );
  2286. Assert( dPositions.Count() == dIndices.Count() );
  2287. const int nIndices( dIndices.Count() );
  2288. int index;
  2289. int k( 0 );
  2290. for ( int l( 0 ); l < nIndices; ++l )
  2291. {
  2292. index = dIndices[ l ];
  2293. while ( index > k )
  2294. {
  2295. ++k;
  2296. }
  2297. Assert( k < nPositions );
  2298. pPositions[ k ] -= dPositions[ l ];
  2299. }
  2300. }
  2301. pCount = 0;
  2302. for ( int j( 0 ); j < nPositions; ++j )
  2303. {
  2304. const Vector &v( pPositions[ j ] );
  2305. // Kind of a magic number but it's because of 16 bit compression of the delta values
  2306. if ( fabs( v.x ) >= ( 1 / 4096.0f ) || fabs( v.y ) >= ( 1 / 4096.0f ) || fabs( v.z ) >= ( 1 / 4096.0f ) )
  2307. {
  2308. pPositions[ pCount ] = v;
  2309. pIndices[ pCount ] = j;
  2310. ++pCount;
  2311. }
  2312. }
  2313. pDelta->RemoveAllVertexData( pIndex );
  2314. if ( pCount )
  2315. {
  2316. pDelta->AddVertexData( pIndex, pCount );
  2317. pDelta->SetVertexData( pIndex, 0, pCount, AT_VECTOR3, pPositions );
  2318. pDelta->SetVertexIndices( pIndex, 0, pCount, pIndices );
  2319. }
  2320. pDelta->SetValue( "corrected", true );
  2321. }
  2322. }
  2323. }
  2324. //-----------------------------------------------------------------------------
  2325. // There's no guarantee that fields are added in any order, nor that only
  2326. // standard fields exist...
  2327. //-----------------------------------------------------------------------------
  2328. template < class T_t >
  2329. void CDmeMesh::AddCorrectedDelta(
  2330. CDmrArray< T_t > &baseDataArray,
  2331. const CUtlVector< int > &baseIndices,
  2332. const DeltaComputation_t &deltaComputation,
  2333. const char *pFieldName,
  2334. float weight,
  2335. const CDmeSingleIndexedComponent *pMask )
  2336. {
  2337. const CUtlVector< T_t > &baseData( baseDataArray.Get() );
  2338. const int nData( baseData.Count() );
  2339. T_t *pData( reinterpret_cast< T_t * >( alloca( nData * sizeof( T_t ) ) ) );
  2340. Q_memcpy( pData, baseData.Base(), nData * sizeof( T_t ) );
  2341. CDmeVertexDeltaData *pDelta( GetDeltaState( deltaComputation.m_nDeltaIndex ) );
  2342. const int deltaFieldIndex( pDelta->FindFieldIndex( pFieldName ) );
  2343. if ( deltaFieldIndex < 0 )
  2344. return;
  2345. AddDelta( pDelta, pData, nData, deltaFieldIndex, weight, pMask );
  2346. const CUtlVector< int > &depDeltas( deltaComputation.m_DependentDeltas );
  2347. const int nDepDeltas( depDeltas.Count() );
  2348. for ( int j( 0 ); j < nDepDeltas; ++j )
  2349. {
  2350. pDelta = GetDeltaState( depDeltas[ j ] );
  2351. int depFieldIndex = pDelta->FindFieldIndex( pFieldName );
  2352. if ( depFieldIndex < 0 )
  2353. continue;
  2354. AddDelta( pDelta, pData, nData, depFieldIndex, weight, pMask );
  2355. }
  2356. baseDataArray.CopyArray( pData, nData );
  2357. }
  2358. //-----------------------------------------------------------------------------
  2359. //
  2360. //-----------------------------------------------------------------------------
  2361. template < class T_t >
  2362. void CDmeMesh::AddCorrectedDelta(
  2363. CUtlVector< T_t > &baseData,
  2364. const CUtlVector< int > &baseIndices,
  2365. const DeltaComputation_t &deltaComputation,
  2366. const char *pFieldName,
  2367. float weight,
  2368. const CDmeSingleIndexedComponent *pMask )
  2369. {
  2370. const int nData( baseData.Count() );
  2371. CDmeVertexDeltaData *pDelta( GetDeltaState( deltaComputation.m_nDeltaIndex ) );
  2372. const int deltaFieldIndex( pDelta->FindFieldIndex( pFieldName ) );
  2373. if ( deltaFieldIndex < 0 )
  2374. return;
  2375. AddDelta( pDelta, baseData.Base(), nData, deltaFieldIndex, weight, pMask );
  2376. const CUtlVector< int > &depDeltas( deltaComputation.m_DependentDeltas );
  2377. const int nDepDeltas( depDeltas.Count() );
  2378. for ( int j( 0 ); j < nDepDeltas; ++j )
  2379. {
  2380. pDelta = GetDeltaState( depDeltas[ j ] );
  2381. int depFieldIndex = pDelta->FindFieldIndex( pFieldName );
  2382. if ( depFieldIndex < 0 )
  2383. continue;
  2384. AddDelta( pDelta, baseData.Base(), nData, depFieldIndex, weight, pMask );
  2385. }
  2386. }
  2387. //-----------------------------------------------------------------------------
  2388. // There's no guarantee that fields are added in any order, nor that only
  2389. // standard fields exist...
  2390. //-----------------------------------------------------------------------------
  2391. template < class T_t >
  2392. void CDmeMesh::AddRawDelta(
  2393. CDmeVertexDeltaData *pDelta,
  2394. CDmrArray< T_t > &baseDataArray,
  2395. FieldIndex_t nDeltaFieldIndex,
  2396. float weight,
  2397. const CDmeSingleIndexedComponent *pMask )
  2398. {
  2399. if ( !pDelta || nDeltaFieldIndex < 0 )
  2400. return;
  2401. const CUtlVector< T_t > &baseData( baseDataArray.Get() );
  2402. const int nData( baseData.Count() );
  2403. T_t *pData( reinterpret_cast< T_t * >( alloca( nData * sizeof( T_t ) ) ) );
  2404. Q_memcpy( pData, baseData.Base(), nData * sizeof( T_t ) );
  2405. AddDelta( pDelta, pData, nData, nDeltaFieldIndex, weight, pMask );
  2406. baseDataArray.CopyArray( pData, nData );
  2407. }
  2408. //-----------------------------------------------------------------------------
  2409. //
  2410. //-----------------------------------------------------------------------------
  2411. template < class T_t >
  2412. void CDmeMesh::AddRawDelta(
  2413. CDmeVertexDeltaData *pDelta,
  2414. CUtlVector< T_t > &baseData,
  2415. FieldIndex_t nDeltaFieldIndex,
  2416. float weight,
  2417. const CDmeSingleIndexedComponent *pMask )
  2418. {
  2419. if ( !pDelta || nDeltaFieldIndex < 0 )
  2420. return;
  2421. const int nData( baseData.Count() );
  2422. AddDelta( pDelta, baseData.Base(), nData, nDeltaFieldIndex, weight, pMask );
  2423. }
  2424. //-----------------------------------------------------------------------------
  2425. // Sets the specified base state to the specified delta
  2426. // If no delta is specified then the current state is copied from the bind state
  2427. // If no base state is specified then the current base state is used
  2428. // The specified base state or the current base state cannot be the bind state
  2429. //-----------------------------------------------------------------------------
  2430. bool CDmeMesh::SetBaseStateToDelta( const CDmeVertexDeltaData *pDelta, CDmeVertexData *pPassedBase /* = NULL */ )
  2431. {
  2432. CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  2433. const CDmeVertexData *pBind = GetBindBaseState();
  2434. if ( !pBase || !pBind || pBase == pBind )
  2435. return false;
  2436. pBind->CopyTo( pBase );
  2437. if ( !pDelta )
  2438. return true;
  2439. // This should be cached and recomputed only when states are added
  2440. CUtlVector< DeltaComputation_t > compList;
  2441. ComputeDependentDeltaStateList( compList );
  2442. const int nDeltas( compList.Count() );
  2443. for ( int i = 0; i < nDeltas; ++i )
  2444. {
  2445. if ( pDelta != GetDeltaState( compList[ i ].m_nDeltaIndex ) )
  2446. continue;
  2447. const int nBaseField( pBase->FieldCount() );
  2448. const int nDeltaField( pDelta->FieldCount() );
  2449. for ( int j( 0 ); j < nBaseField; ++j )
  2450. {
  2451. const CUtlString &baseFieldName( pBase->FieldName( j ) );
  2452. for ( int k( 0 ); k < nDeltaField; ++k )
  2453. {
  2454. const CUtlString &deltaFieldName( pDelta->FieldName( k ) );
  2455. if ( baseFieldName != deltaFieldName )
  2456. continue;
  2457. const FieldIndex_t baseFieldIndex( pBase->FindFieldIndex( baseFieldName ) );
  2458. const FieldIndex_t deltaFieldIndex( pDelta->FindFieldIndex( deltaFieldName ) );
  2459. if ( baseFieldIndex < 0 || deltaFieldIndex < 0 )
  2460. break;
  2461. CDmAttribute *pBaseData( pBase->GetVertexData( baseFieldIndex ) );
  2462. const CDmAttribute *pDeltaData( pDelta->GetVertexData( deltaFieldIndex ) );
  2463. if ( pBaseData->GetType() != pDeltaData->GetType() )
  2464. break;
  2465. const CUtlVector< int > &baseIndices( pBase->GetVertexIndexData( baseFieldIndex ) );
  2466. switch ( pBaseData->GetType() )
  2467. {
  2468. case AT_FLOAT_ARRAY:
  2469. AddCorrectedDelta( CDmrArray< float >( pBaseData ), baseIndices, compList[ i ], baseFieldName );
  2470. break;
  2471. case AT_COLOR_ARRAY:
  2472. AddCorrectedDelta( CDmrArray< Vector >( pBaseData ), baseIndices, compList[ i ], baseFieldName );
  2473. break;
  2474. case AT_VECTOR2_ARRAY:
  2475. AddCorrectedDelta( CDmrArray< Vector2D >( pBaseData ), baseIndices, compList[ i ], baseFieldName );
  2476. break;
  2477. case AT_VECTOR3_ARRAY:
  2478. AddCorrectedDelta( CDmrArray< Vector >( pBaseData ), baseIndices, compList[ i ], baseFieldName );
  2479. break;
  2480. default:
  2481. break;
  2482. }
  2483. break;
  2484. }
  2485. }
  2486. }
  2487. return true;
  2488. }
  2489. //-----------------------------------------------------------------------------
  2490. //
  2491. //-----------------------------------------------------------------------------
  2492. void CDmeMesh::SelectVerticesFromDelta(
  2493. CDmeVertexDeltaData *pDelta,
  2494. CDmeSingleIndexedComponent *pSelection )
  2495. {
  2496. if ( !pSelection )
  2497. return;
  2498. pSelection->Clear();
  2499. if ( !pDelta )
  2500. return;
  2501. const FieldIndex_t pField( pDelta->FindFieldIndex( CDmeVertexData::FIELD_POSITION ) );
  2502. if ( pField < 0 )
  2503. return;
  2504. const CUtlVector< int > &pIndicies( pDelta->GetVertexIndexData( CDmeVertexData::FIELD_POSITION ) );
  2505. pSelection->AddComponents( pIndicies );
  2506. }
  2507. //-----------------------------------------------------------------------------
  2508. //
  2509. //-----------------------------------------------------------------------------
  2510. void CDmeMesh::SelectAllVertices( CDmeSingleIndexedComponent *pSelection, CDmeVertexData *pPassedBase /* = NULL */ )
  2511. {
  2512. const CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  2513. if ( !pBase )
  2514. {
  2515. pBase = GetBindBaseState();
  2516. }
  2517. if ( !pBase )
  2518. return;
  2519. if ( !pSelection )
  2520. return;
  2521. pSelection->Clear();
  2522. const FieldIndex_t pField( pBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION ) );
  2523. if ( pField < 0 )
  2524. return;
  2525. CUtlVector< int > indices;
  2526. indices.EnsureCount( CDmrArrayConst< Vector >( pBase->GetVertexData( pField ) ).Count() );
  2527. const int nIndices = indices.Count();
  2528. for ( int i = 0; i < nIndices; ++i )
  2529. {
  2530. indices[ i ] = i;
  2531. }
  2532. pSelection->AddComponents( indices );
  2533. }
  2534. //-----------------------------------------------------------------------------
  2535. //
  2536. //-----------------------------------------------------------------------------
  2537. void CDmeMesh::SelectHalfVertices( SelectHalfType_t selectHalfType, CDmeSingleIndexedComponent *pSelection, CDmeVertexData *pPassedBase /* = NULL */ )
  2538. {
  2539. const CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  2540. if ( !pBase )
  2541. {
  2542. pBase = GetBindBaseState();
  2543. }
  2544. if ( !pBase )
  2545. return;
  2546. if ( !pSelection )
  2547. return;
  2548. pSelection->Clear();
  2549. const FieldIndex_t pField( pBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION ) );
  2550. if ( pField < 0 )
  2551. return;
  2552. const CDmrArrayConst< Vector > pos( pBase->GetVertexData( pField ) );
  2553. const int nPosCount = pos.Count();
  2554. CUtlVector< int > indices;
  2555. indices.EnsureCapacity( nPosCount );
  2556. if ( selectHalfType == kRight )
  2557. {
  2558. for ( int i = 0; i < nPosCount; ++i )
  2559. {
  2560. if ( pos[ i ].x <= 0.0f )
  2561. {
  2562. indices.AddToTail( i );
  2563. }
  2564. }
  2565. }
  2566. else
  2567. {
  2568. for ( int i = 0; i < nPosCount; ++i )
  2569. {
  2570. if ( pos[ i ].x >= 0.0f )
  2571. {
  2572. indices.AddToTail( i );
  2573. }
  2574. }
  2575. }
  2576. pSelection->AddComponents( indices );
  2577. }
  2578. //-----------------------------------------------------------------------------
  2579. //
  2580. //-----------------------------------------------------------------------------
  2581. bool CDmeMesh::CreateDeltaFieldFromBaseField(
  2582. CDmeVertexData::StandardFields_t nStandardFieldIndex,
  2583. const CDmrArrayConst< float > &baseArray,
  2584. const CDmrArrayConst< float > &bindArray,
  2585. CDmeVertexDeltaData *pDelta )
  2586. {
  2587. const int nData( baseArray.Count() );
  2588. if ( nData != bindArray.Count() )
  2589. return false;
  2590. const float *pBaseData( baseArray.Get().Base() );
  2591. const float *pBindData( bindArray.Get().Base() );
  2592. float *pData( reinterpret_cast< float * >( nData * sizeof( float ) ) );
  2593. Q_memcpy( pData, pBaseData, nData * sizeof( float ) );
  2594. int *pIndices( reinterpret_cast< int * >( nData * sizeof( int ) ) );
  2595. float v;
  2596. int nDeltaCount( 0 );
  2597. for ( int i = 0; i < nData; ++i )
  2598. {
  2599. v = pBaseData[ i ] - pBindData[ i ];
  2600. // Kind of a magic number but it's because of 16 bit compression of the delta values
  2601. if ( fabs( v ) >= ( 1 / 4096.0f ) )
  2602. {
  2603. pData[ nDeltaCount ] = v;
  2604. pIndices[ nDeltaCount ] = i;
  2605. ++nDeltaCount;
  2606. }
  2607. }
  2608. if ( nDeltaCount <= 0 )
  2609. return true;
  2610. FieldIndex_t fieldIndex( pDelta->CreateField( nStandardFieldIndex ) );
  2611. if ( fieldIndex < 0 )
  2612. return false;
  2613. pDelta->AddVertexData( fieldIndex, nDeltaCount );
  2614. pDelta->SetVertexData( fieldIndex, 0, nDeltaCount, AT_FLOAT, pData );
  2615. pDelta->SetVertexIndices( fieldIndex, 0, nDeltaCount, pIndices );
  2616. return true;
  2617. }
  2618. //-----------------------------------------------------------------------------
  2619. //
  2620. //-----------------------------------------------------------------------------
  2621. bool CDmeMesh::CreateDeltaFieldFromBaseField(
  2622. CDmeVertexData::StandardFields_t nStandardFieldIndex,
  2623. const CDmrArrayConst< Vector2D > &baseArray,
  2624. const CDmrArrayConst< Vector2D > &bindArray,
  2625. CDmeVertexDeltaData *pDelta )
  2626. {
  2627. const int nData( baseArray.Count() );
  2628. if ( nData != bindArray.Count() )
  2629. return false;
  2630. const Vector2D *pBaseData( baseArray.Get().Base() );
  2631. const Vector2D *pBindData( bindArray.Get().Base() );
  2632. Vector2D *pData( reinterpret_cast< Vector2D * >( nData * sizeof( Vector2D ) ) );
  2633. Q_memcpy( pData, pBaseData, nData * sizeof( Vector2D ) );
  2634. int *pIndices( reinterpret_cast< int * >( nData * sizeof( int ) ) );
  2635. Vector2D v;
  2636. int nDeltaCount( 0 );
  2637. for ( int i = 0; i < nData; ++i )
  2638. {
  2639. v = pBaseData[ i ] - pBindData[ i ];
  2640. // Kind of a magic number but it's because of 16 bit compression of the delta values
  2641. if ( fabs( v.x ) >= ( 1 / 4096.0f ) || fabs( v.y ) >= ( 1 / 4096.0f ) )
  2642. {
  2643. pData[ nDeltaCount ] = v;
  2644. pIndices[ nDeltaCount ] = i;
  2645. ++nDeltaCount;
  2646. }
  2647. }
  2648. if ( nDeltaCount <= 0 )
  2649. return true;
  2650. FieldIndex_t fieldIndex( pDelta->CreateField( nStandardFieldIndex ) );
  2651. if ( fieldIndex < 0 )
  2652. return false;
  2653. pDelta->AddVertexData( fieldIndex, nDeltaCount );
  2654. pDelta->SetVertexData( fieldIndex, 0, nDeltaCount, AT_VECTOR2, pData );
  2655. pDelta->SetVertexIndices( fieldIndex, 0, nDeltaCount, pIndices );
  2656. return true;
  2657. }
  2658. //-----------------------------------------------------------------------------
  2659. //
  2660. //-----------------------------------------------------------------------------
  2661. bool CDmeMesh::CreateDeltaFieldFromBaseField(
  2662. CDmeVertexData::StandardFields_t nStandardFieldIndex,
  2663. const CDmrArrayConst< Vector > &baseArray,
  2664. const CDmrArrayConst< Vector > &bindArray,
  2665. CDmeVertexDeltaData *pDelta )
  2666. {
  2667. const int nData( baseArray.Count() );
  2668. if ( nData != bindArray.Count() )
  2669. return false;
  2670. const Vector *pBaseData( baseArray.Get().Base() );
  2671. const Vector *pBindData( bindArray.Get().Base() );
  2672. Vector *pData( reinterpret_cast< Vector * >( alloca( nData * sizeof( Vector ) ) ) );
  2673. Q_memcpy( pData, pBaseData, nData * sizeof( Vector ) );
  2674. int *pIndices( reinterpret_cast< int * >( alloca( nData * sizeof( int ) ) ) );
  2675. Vector v;
  2676. int nDeltaCount( 0 );
  2677. for ( int i = 0; i < nData; ++i )
  2678. {
  2679. v = pBaseData[ i ] - pBindData[ i ];
  2680. // Kind of a magic number but it's because of 16 bit compression of the delta values
  2681. if ( fabs( v.x ) >= ( 1 / 4096.0f ) || fabs( v.y ) >= ( 1 / 4096.0f ) || fabs( v.z ) >= ( 1 / 4096.0f ) )
  2682. {
  2683. pData[ nDeltaCount ] = v;
  2684. pIndices[ nDeltaCount ] = i;
  2685. ++nDeltaCount;
  2686. }
  2687. }
  2688. if ( nDeltaCount <= 0 )
  2689. return true;
  2690. FieldIndex_t fieldIndex( pDelta->CreateField( nStandardFieldIndex ) );
  2691. if ( fieldIndex < 0 )
  2692. return false;
  2693. pDelta->AddVertexData( fieldIndex, nDeltaCount );
  2694. pDelta->SetVertexData( fieldIndex, 0, nDeltaCount, AT_VECTOR3, pData );
  2695. pDelta->SetVertexIndices( fieldIndex, 0, nDeltaCount, pIndices );
  2696. return true;
  2697. }
  2698. //-----------------------------------------------------------------------------
  2699. // Creates a delta from the difference between the bind base state and the
  2700. // specified base state. If pBaseName is NULL the current base state is used
  2701. //-----------------------------------------------------------------------------
  2702. CDmeVertexDeltaData *CDmeMesh::ModifyOrCreateDeltaStateFromBaseState( const char *pDeltaName, CDmeVertexData *pPassedBase /* = NULL */, bool absolute /* = false */ )
  2703. {
  2704. // Find All States Which Have This Guy
  2705. CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  2706. if ( !pBase )
  2707. return NULL;
  2708. CDmeVertexData *pBind = GetBindBaseState();
  2709. if ( !pBind )
  2710. return NULL;
  2711. // It's ok if pBase == pBind
  2712. CUtlVector< int > superiorDeltaStates;
  2713. ComputeSuperiorDeltaStateList( pDeltaName, superiorDeltaStates );
  2714. const int nSuperior = superiorDeltaStates.Count();
  2715. if ( nSuperior > 0 )
  2716. {
  2717. UniqueId_t id;
  2718. char idBuf[ MAX_PATH ];
  2719. CDmeVertexData *pTmpBaseState = NULL;
  2720. do
  2721. {
  2722. CreateUniqueId( &id );
  2723. UniqueIdToString( id, idBuf, sizeof( idBuf ) );
  2724. pTmpBaseState = FindBaseState( idBuf );
  2725. } while( pTmpBaseState != NULL );
  2726. pTmpBaseState = FindOrCreateBaseState( idBuf );
  2727. if ( !pTmpBaseState )
  2728. return NULL;
  2729. for ( int i = 0; i < nSuperior; ++i )
  2730. {
  2731. Assert( superiorDeltaStates[ i ] < DeltaStateCount() );
  2732. CDmeVertexDeltaData *pSuperiorDelta = GetDeltaState( superiorDeltaStates[ i ] );
  2733. if ( pSuperiorDelta->GetValue< bool >( "corrected" ) )
  2734. {
  2735. // Only fiddle with states that are "corrected"
  2736. if ( !SetBaseStateToDelta( pSuperiorDelta, pTmpBaseState ) )
  2737. return NULL;
  2738. if ( !ModifyOrCreateDeltaStateFromBaseState( CUtlString( pSuperiorDelta->GetName() ), pTmpBaseState, true ) )
  2739. return NULL;
  2740. }
  2741. }
  2742. DeleteBaseState( idBuf );
  2743. }
  2744. ResetDeltaState( pDeltaName );
  2745. CDmeVertexDeltaData *pDelta = FindOrCreateDeltaState( pDeltaName );
  2746. if ( !pDelta )
  2747. return NULL;
  2748. CDmeVertexData::StandardFields_t deltaFields[] =
  2749. {
  2750. CDmeVertexData::FIELD_POSITION,
  2751. CDmeVertexData::FIELD_NORMAL,
  2752. CDmeVertexData::FIELD_WRINKLE
  2753. };
  2754. for ( int i = 0; i < sizeof( deltaFields ) / sizeof( deltaFields[ 0 ] ); ++i )
  2755. {
  2756. CDmeVertexData::StandardFields_t standardFieldIndex( deltaFields[ i ] );
  2757. const FieldIndex_t baseFieldIndex( pBase->FindFieldIndex( standardFieldIndex ) );
  2758. const FieldIndex_t bindFieldIndex( pBind->FindFieldIndex( standardFieldIndex ) );
  2759. if ( baseFieldIndex < 0 || bindFieldIndex < 0 )
  2760. continue;
  2761. CDmAttribute *pBaseData( pBase->GetVertexData( baseFieldIndex ) );
  2762. CDmAttribute *pBindData( pBind->GetVertexData( bindFieldIndex ) );
  2763. if ( pBaseData->GetType() != pBindData->GetType() )
  2764. continue;
  2765. switch ( pBaseData->GetType() )
  2766. {
  2767. case AT_FLOAT_ARRAY:
  2768. CreateDeltaFieldFromBaseField( standardFieldIndex, CDmrArrayConst< float >( pBaseData ), CDmrArrayConst< float >( pBindData ), pDelta );
  2769. break;
  2770. case AT_COLOR_ARRAY:
  2771. CreateDeltaFieldFromBaseField( standardFieldIndex, CDmrArrayConst< Vector >( pBaseData ), CDmrArrayConst< Vector >( pBindData ), pDelta );
  2772. break;
  2773. case AT_VECTOR2_ARRAY:
  2774. CreateDeltaFieldFromBaseField( standardFieldIndex, CDmrArrayConst< Vector2D >( pBaseData ), CDmrArrayConst< Vector2D >( pBindData ), pDelta );
  2775. break;
  2776. case AT_VECTOR3_ARRAY:
  2777. CreateDeltaFieldFromBaseField( standardFieldIndex, CDmrArrayConst< Vector >( pBaseData ), CDmrArrayConst< Vector >( pBindData ), pDelta );
  2778. break;
  2779. default:
  2780. break;
  2781. }
  2782. }
  2783. if ( !strchr( pDelta->GetName(), '_' ) )
  2784. {
  2785. const static UtlSymId_t symTargets = g_pDataModel->GetSymbol( "targets" );
  2786. CDmeCombinationOperator *pCombo( FindReferringElement< CDmeCombinationOperator >( this, symTargets ) );
  2787. if ( pCombo )
  2788. {
  2789. pCombo->FindOrCreateControl( pDelta->GetName(), false, true );
  2790. }
  2791. }
  2792. if ( !absolute )
  2793. {
  2794. ComputeAllCorrectedPositionsFromActualPositions();
  2795. }
  2796. return pDelta;
  2797. }
  2798. //-----------------------------------------------------------------------------
  2799. // TODO: Uncorrect all superior states and then correct them afterwards
  2800. //-----------------------------------------------------------------------------
  2801. bool CDmeMesh::DeleteDeltaState( const char *pDeltaName )
  2802. {
  2803. const int nDeltaIndex = FindDeltaStateIndex( pDeltaName );
  2804. if ( nDeltaIndex < 0 )
  2805. return false;
  2806. Assert( m_DeltaStates.Count() == m_DeltaStateWeights[ MESH_DELTA_WEIGHT_NORMAL ].Count() );
  2807. Assert( m_DeltaStates.Count() == m_DeltaStateWeights[ MESH_DELTA_WEIGHT_LAGGED ].Count() );
  2808. CDmeVertexDeltaData *pDelta( m_DeltaStates[ nDeltaIndex ] );
  2809. if ( !pDelta )
  2810. return false;
  2811. m_DeltaStates.Remove( nDeltaIndex );
  2812. m_DeltaStateWeights[ MESH_DELTA_WEIGHT_NORMAL ].Remove( nDeltaIndex );
  2813. m_DeltaStateWeights[ MESH_DELTA_WEIGHT_LAGGED ].Remove( nDeltaIndex );
  2814. g_pDataModel->DestroyElement( pDelta->GetHandle() );
  2815. const static UtlSymId_t symTargets = g_pDataModel->GetSymbol( "targets" );
  2816. CDmeCombinationOperator *pCombo( FindReferringElement< CDmeCombinationOperator >( this, symTargets ) );
  2817. if ( pCombo )
  2818. {
  2819. pCombo->Purge();
  2820. }
  2821. return true;
  2822. }
  2823. //-----------------------------------------------------------------------------
  2824. // TODO: Uncorrect all superior states and then correct them afterwards
  2825. //-----------------------------------------------------------------------------
  2826. bool CDmeMesh::ResetDeltaState( const char *pDeltaName )
  2827. {
  2828. const int nDeltaIndex = FindDeltaStateIndex( pDeltaName );
  2829. if ( nDeltaIndex < 0 )
  2830. return false;
  2831. CDmeVertexDeltaData *pOldDelta = m_DeltaStates[ nDeltaIndex ];
  2832. CDmeVertexDeltaData *pNewDelta = CreateElement< CDmeVertexDeltaData >( pOldDelta->GetName(), GetFileId() );
  2833. if ( !pNewDelta )
  2834. return false;
  2835. m_DeltaStates.Set( nDeltaIndex, pNewDelta );
  2836. g_pDataModel->DestroyElement( pOldDelta->GetHandle() );
  2837. return true;
  2838. }
  2839. //-----------------------------------------------------------------------------
  2840. //
  2841. //-----------------------------------------------------------------------------
  2842. class CSelectionHelper
  2843. {
  2844. public:
  2845. class CVert
  2846. {
  2847. public:
  2848. int m_index;
  2849. int m_count;
  2850. float m_weight;
  2851. };
  2852. void AddVert( int vIndex, float weight = 1.0f );
  2853. int AddToSelection( CDmeSingleIndexedComponent *pSelection ) const;
  2854. int RemoveFromSelection( CDmeSingleIndexedComponent *pSelection, bool bAllowEmpty ) const;
  2855. protected:
  2856. CUtlVector< CVert > m_verts;
  2857. int BinarySearch( int component ) const;
  2858. };
  2859. //-----------------------------------------------------------------------------
  2860. //
  2861. //-----------------------------------------------------------------------------
  2862. void CSelectionHelper::AddVert( int vIndex, float weight /* = 1.0f */ )
  2863. {
  2864. // Find the vertex, add it if necessary
  2865. const int index = BinarySearch( vIndex );
  2866. if ( index == m_verts.Count() )
  2867. {
  2868. // New Add to end
  2869. CVert &v( m_verts[ m_verts.AddToTail() ] );
  2870. v.m_index = vIndex;
  2871. v.m_count = 1;
  2872. v.m_weight = weight;
  2873. }
  2874. else if ( vIndex == m_verts[ index ].m_index )
  2875. {
  2876. // Existing, increment
  2877. CVert &v( m_verts[ index ] );
  2878. Assert( v.m_index == vIndex );
  2879. v.m_count += 1;
  2880. v.m_weight += weight;
  2881. }
  2882. else
  2883. {
  2884. // New insert before index
  2885. CVert &v( m_verts[ m_verts.InsertBefore( index ) ] );
  2886. v.m_index = vIndex;
  2887. v.m_count = 1;
  2888. v.m_weight = weight;
  2889. }
  2890. }
  2891. //-----------------------------------------------------------------------------
  2892. //
  2893. //-----------------------------------------------------------------------------
  2894. int CSelectionHelper::AddToSelection( CDmeSingleIndexedComponent *pSelection ) const
  2895. {
  2896. const int nVerts = m_verts.Count();
  2897. for ( int i = 0; i < nVerts; ++i )
  2898. {
  2899. const CVert &v( m_verts[ i ] );
  2900. Assert( !pSelection->HasComponent( v.m_index ) );
  2901. pSelection->AddComponent( v.m_index, v.m_weight / static_cast< float >( v.m_count ) );
  2902. }
  2903. return nVerts;
  2904. }
  2905. //-----------------------------------------------------------------------------
  2906. //
  2907. //-----------------------------------------------------------------------------
  2908. int CSelectionHelper::RemoveFromSelection( CDmeSingleIndexedComponent *pSelection, bool bAllowEmpty ) const
  2909. {
  2910. const int nVerts = m_verts.Count();
  2911. int nVertsRemovedCount = 0;
  2912. for ( int i = 0; i < nVerts; ++i )
  2913. {
  2914. const CVert &v( m_verts[ i ] );
  2915. if ( bAllowEmpty || pSelection->Count() > 1 )
  2916. {
  2917. pSelection->RemoveComponent( v.m_index );
  2918. ++nVertsRemovedCount;
  2919. }
  2920. }
  2921. return nVertsRemovedCount;
  2922. }
  2923. //-----------------------------------------------------------------------------
  2924. // Searches for the component in the sorted component list and returns the
  2925. // index if it's found or if it's not found, returns the index at which it
  2926. // should be inserted to maintain the sorted order of the component list
  2927. //-----------------------------------------------------------------------------
  2928. int CSelectionHelper::BinarySearch( int vIndex ) const
  2929. {
  2930. const int nVerts( m_verts.Count() );
  2931. int left( 0 );
  2932. int right( nVerts - 1 );
  2933. int mid;
  2934. while ( left <= right )
  2935. {
  2936. mid = ( left + right ) >> 1; // floor( ( left + right ) / 2.0 )
  2937. if ( vIndex > m_verts[ mid ].m_index )
  2938. {
  2939. left = mid + 1;
  2940. }
  2941. else if ( vIndex < m_verts[ mid ].m_index )
  2942. {
  2943. right = mid - 1;
  2944. }
  2945. else
  2946. {
  2947. return mid;
  2948. }
  2949. }
  2950. return left;
  2951. }
  2952. //-----------------------------------------------------------------------------
  2953. //
  2954. //-----------------------------------------------------------------------------
  2955. void CDmeMesh::GrowSelection( int nSize, CDmeSingleIndexedComponent *pSelection, CDmMeshComp *pPassedMeshComp )
  2956. {
  2957. if ( nSize <= 0 || !pSelection )
  2958. return;
  2959. CUtlVector< int > sIndices;
  2960. CUtlVector< float > sWeights;
  2961. pSelection->GetComponents( sIndices, sWeights );
  2962. const int nVertices = sIndices.Count();
  2963. CDmMeshComp *pMeshComp = pPassedMeshComp ? pPassedMeshComp : new CDmMeshComp( this );
  2964. CUtlVector< CDmMeshComp::CVert * > neighbours;
  2965. CSelectionHelper sHelper;
  2966. for ( int i = 0; i < nVertices; ++i )
  2967. {
  2968. const int nNeighbours = pMeshComp->FindNeighbouringVerts( sIndices[ i ], neighbours );
  2969. for ( int j = 0; j < nNeighbours; ++j )
  2970. {
  2971. CDmMeshComp::CVert *pNeighbour = neighbours[ j ];
  2972. Assert( pNeighbour );
  2973. if ( pNeighbour )
  2974. {
  2975. const int vIndex = pNeighbour->PositionIndex();
  2976. if ( !pSelection->HasComponent( vIndex ) )
  2977. {
  2978. sHelper.AddVert( vIndex, sWeights[ i ] );
  2979. }
  2980. }
  2981. }
  2982. }
  2983. if ( sHelper.AddToSelection( pSelection ) > 0 )
  2984. {
  2985. GrowSelection( nSize - 1, pSelection, pMeshComp );
  2986. }
  2987. if ( pMeshComp != pPassedMeshComp )
  2988. {
  2989. delete pMeshComp;
  2990. }
  2991. }
  2992. //-----------------------------------------------------------------------------
  2993. //
  2994. //-----------------------------------------------------------------------------
  2995. void CDmeMesh::ShrinkSelection( int nSize, CDmeSingleIndexedComponent *pSelection, CDmMeshComp *pPassedMeshComp )
  2996. {
  2997. if ( nSize <= 0 || !pSelection )
  2998. return;
  2999. CUtlVector< int > sIndices;
  3000. CUtlVector< float > sWeights;
  3001. pSelection->GetComponents( sIndices, sWeights );
  3002. const int nVertices = sIndices.Count();
  3003. CDmMeshComp *pMeshComp = pPassedMeshComp ? pPassedMeshComp : new CDmMeshComp( this );
  3004. CUtlVector< CDmMeshComp::CVert * > neighbours;
  3005. CSelectionHelper sHelper;
  3006. for ( int i = 0; i < nVertices; ++i )
  3007. {
  3008. bool hasSelectedNeighbour = false;
  3009. bool hasUnselectedNeighbour = false;
  3010. const int vIndex = sIndices[ i ];
  3011. const int nNeighbours = pMeshComp->FindNeighbouringVerts( vIndex, neighbours );
  3012. for ( int j = 0; j < nNeighbours; ++j )
  3013. {
  3014. const int nvIndex = neighbours[ j ]->PositionIndex();
  3015. if ( pSelection->HasComponent( nvIndex ) )
  3016. {
  3017. hasSelectedNeighbour = true;
  3018. if ( hasUnselectedNeighbour )
  3019. {
  3020. sHelper.AddVert( vIndex );
  3021. break;
  3022. }
  3023. }
  3024. else
  3025. {
  3026. hasUnselectedNeighbour = true;
  3027. if ( hasSelectedNeighbour )
  3028. {
  3029. sHelper.AddVert( vIndex );
  3030. break;
  3031. }
  3032. }
  3033. }
  3034. }
  3035. if ( sHelper.RemoveFromSelection( pSelection, false ) > 0 )
  3036. {
  3037. ShrinkSelection( nSize - 1, pSelection, pMeshComp );
  3038. }
  3039. if ( pMeshComp != pPassedMeshComp )
  3040. {
  3041. delete pMeshComp;
  3042. }
  3043. }
  3044. CDmeSingleIndexedComponent *CDmeMesh::FeatherSelection(
  3045. float falloffDistance,
  3046. Falloff_t falloffType,
  3047. Distance_t distanceType,
  3048. CDmeSingleIndexedComponent *pSelection,
  3049. CDmMeshComp *pPassedMeshComp )
  3050. {
  3051. switch ( falloffType )
  3052. {
  3053. case SMOOTH:
  3054. return FeatherSelection< SMOOTH >( falloffDistance, distanceType, pSelection, pPassedMeshComp );
  3055. case SPIKE:
  3056. return FeatherSelection< SPIKE >( falloffDistance, distanceType, pSelection, pPassedMeshComp );
  3057. case DOME:
  3058. return FeatherSelection< DOME >( falloffDistance, distanceType, pSelection, pPassedMeshComp );
  3059. default:
  3060. return FeatherSelection< LINEAR >( falloffDistance, distanceType, pSelection, pPassedMeshComp );
  3061. }
  3062. }
  3063. //-----------------------------------------------------------------------------
  3064. //
  3065. //-----------------------------------------------------------------------------
  3066. template < int T >
  3067. CDmeSingleIndexedComponent *CDmeMesh::FeatherSelection(
  3068. float fDistance, Distance_t distanceType,
  3069. CDmeSingleIndexedComponent *pSelection, CDmMeshComp *pPassedMeshComp )
  3070. {
  3071. // TODO: Support feathering inward instead of just outward
  3072. if ( fDistance <= 0.0f || !pSelection )
  3073. return NULL;
  3074. // Make a new CDmeSingleIndexedComponent to do all of the dirty work
  3075. CDmeSingleIndexedComponent *pNewSelection = CreateElement< CDmeSingleIndexedComponent >( "feather", pSelection->GetFileId() );
  3076. pSelection->CopyAttributesTo( pNewSelection );
  3077. CDmMeshComp *pMeshComp = pPassedMeshComp ? pPassedMeshComp : new CDmMeshComp( this );
  3078. CDmeVertexData *pBase = pMeshComp->BaseState();
  3079. if ( distanceType == DIST_RELATIVE )
  3080. {
  3081. Vector vCenter;
  3082. float flRadius;
  3083. GetBoundingSphere( vCenter, flRadius, pBase, pSelection );
  3084. fDistance *= flRadius;
  3085. }
  3086. const CUtlVector< Vector > &positions( pBase->GetPositionData() );
  3087. const int nPositions = positions.Count();
  3088. if ( !pBase )
  3089. return NULL;
  3090. CUtlVector< int > sIndices;
  3091. int insideCount = 0;
  3092. CFalloff< T > falloff;
  3093. do
  3094. {
  3095. insideCount = 0;
  3096. CUtlVector< CDmMeshComp::CVert * > neighbours;
  3097. CSelectionHelper sHelper;
  3098. pNewSelection->GetComponents( sIndices );
  3099. int nVertices = sIndices.Count();
  3100. for ( int i = 0; i < nVertices; ++i )
  3101. {
  3102. const int nNeighbours = pMeshComp->FindNeighbouringVerts( sIndices[ i ], neighbours );
  3103. for ( int j = 0; j < nNeighbours; ++j )
  3104. {
  3105. const int vIndex = neighbours[ j ]->PositionIndex();
  3106. if ( pNewSelection->HasComponent( vIndex ) )
  3107. continue;
  3108. const int closestVert = ClosestSelectedVertex( vIndex, pSelection, pBase );
  3109. if ( closestVert < 0 || closestVert >= nPositions )
  3110. continue;
  3111. const float vDistance = positions[ vIndex ].DistTo( positions[ closestVert ] );
  3112. if ( vDistance <= fDistance )
  3113. {
  3114. sHelper.AddVert( vIndex, falloff( vDistance / fDistance ) );
  3115. ++insideCount;
  3116. }
  3117. }
  3118. }
  3119. sHelper.AddToSelection( pNewSelection );
  3120. } while ( insideCount > 0 );
  3121. return pNewSelection;
  3122. }
  3123. //-----------------------------------------------------------------------------
  3124. // Add the specified delta, scaled by the weight value to the DmeVertexData
  3125. // base state specified. Optionally the add can be masked by a specified
  3126. // weight map.
  3127. //
  3128. // If a DmeVertexData is not explicitly specified, the current state of the
  3129. // mesh is modified unless it's the bind state. The bind state will never
  3130. // be modified even if it is explicitly specified.
  3131. //
  3132. // Only the delta specified is added. No dependent states are added.
  3133. //-----------------------------------------------------------------------------
  3134. bool CDmeMesh::AddMaskedDelta(
  3135. CDmeVertexDeltaData *pDelta,
  3136. CDmeVertexData *pDst /* = NULL */,
  3137. float weight /* = 1.0f */,
  3138. const CDmeSingleIndexedComponent *pMask /* = NULL */ )
  3139. {
  3140. CDmeVertexData *pBase = pDst ? pDst : GetCurrentBaseState();
  3141. if ( !pBase || pBase == GetBindBaseState() )
  3142. return false;
  3143. bool retVal = true;
  3144. const int nBaseField( pBase->FieldCount() );
  3145. const int nDeltaField( pDelta->FieldCount() );
  3146. // Try to add every field of the base state
  3147. for ( int j( 0 ); j < nBaseField; ++j )
  3148. {
  3149. const CUtlString &baseFieldName( pBase->FieldName( j ) );
  3150. // Find the corresponding field in the delta
  3151. for ( int k( 0 ); k < nDeltaField; ++k )
  3152. {
  3153. const CUtlString &deltaFieldName( pDelta->FieldName( k ) );
  3154. if ( baseFieldName != deltaFieldName )
  3155. continue;
  3156. const FieldIndex_t baseFieldIndex( pBase->FindFieldIndex( baseFieldName ) );
  3157. const FieldIndex_t deltaFieldIndex( pDelta->FindFieldIndex( deltaFieldName ) );
  3158. if ( baseFieldIndex < 0 || deltaFieldIndex < 0 )
  3159. break;
  3160. CDmAttribute *pBaseData( pBase->GetVertexData( baseFieldIndex ) );
  3161. CDmAttribute *pDeltaData( pDelta->GetVertexData( deltaFieldIndex ) );
  3162. if ( pBaseData->GetType() != pDeltaData->GetType() )
  3163. break;
  3164. switch ( pBaseData->GetType() )
  3165. {
  3166. case AT_FLOAT_ARRAY:
  3167. AddRawDelta( pDelta, CDmrArray< float >( pBaseData ), baseFieldIndex, weight, pMask );
  3168. break;
  3169. case AT_COLOR_ARRAY:
  3170. // TODO: Color is missing some algebraic operators
  3171. // AddRawDelta( pDelta, CDmrArray< Color >( pBaseData ), baseFieldIndex, weight, pMask );
  3172. break;
  3173. case AT_VECTOR2_ARRAY:
  3174. AddRawDelta( pDelta, CDmrArray< Vector2D >( pBaseData ), baseFieldIndex, weight, pMask );
  3175. break;
  3176. case AT_VECTOR3_ARRAY:
  3177. AddRawDelta( pDelta, CDmrArray< Vector >( pBaseData ), baseFieldIndex, weight, pMask );
  3178. break;
  3179. default:
  3180. break;
  3181. }
  3182. break;
  3183. }
  3184. }
  3185. return retVal;
  3186. }
  3187. //-----------------------------------------------------------------------------
  3188. // Add the specified delta, scaled by the weight value to the DmeVertexData
  3189. // base state specified. Optionally the add can be masked by a specified
  3190. // weight map.
  3191. //
  3192. // If a DmeVertexData is not explicitly specified, the current state of the
  3193. // mesh is modified unless it's the bind state. The bind state will never
  3194. // be modified even if it is explicitly specified.
  3195. //
  3196. // Only the delta specified is added. No dependent states are added.
  3197. //-----------------------------------------------------------------------------
  3198. bool CDmeMesh::AddCorrectedMaskedDelta(
  3199. CDmeVertexDeltaData *pDelta,
  3200. CDmeVertexData *pDst /* = NULL */,
  3201. float weight /* = 1.0f */,
  3202. const CDmeSingleIndexedComponent *pMask /* = NULL */ )
  3203. {
  3204. CDmeVertexData *pBase = pDst ? pDst : GetCurrentBaseState();
  3205. if ( !pBase || pBase == GetBindBaseState() )
  3206. return false;
  3207. bool retVal = true;
  3208. const int nBaseField( pBase->FieldCount() );
  3209. const int nDeltaField( pDelta->FieldCount() );
  3210. // This should be cached and recomputed only when states are added
  3211. CUtlVector< DeltaComputation_t > compList;
  3212. ComputeDependentDeltaStateList( compList );
  3213. const int nDeltas( compList.Count() );
  3214. for ( int i = 0; i < nDeltas; ++i )
  3215. {
  3216. if ( pDelta != GetDeltaState( compList[ i ].m_nDeltaIndex ) )
  3217. continue;
  3218. // Try to add every field of the base state
  3219. for ( int j( 0 ); j < nBaseField; ++j )
  3220. {
  3221. const CUtlString &baseFieldName( pBase->FieldName( j ) );
  3222. // Find the corresponding field in the delta
  3223. for ( int k( 0 ); k < nDeltaField; ++k )
  3224. {
  3225. const CUtlString &deltaFieldName( pDelta->FieldName( k ) );
  3226. if ( baseFieldName != deltaFieldName )
  3227. continue;
  3228. const FieldIndex_t baseFieldIndex( pBase->FindFieldIndex( baseFieldName ) );
  3229. const FieldIndex_t deltaFieldIndex( pDelta->FindFieldIndex( deltaFieldName ) );
  3230. if ( baseFieldIndex < 0 || deltaFieldIndex < 0 )
  3231. break;
  3232. CDmAttribute *pBaseData( pBase->GetVertexData( baseFieldIndex ) );
  3233. CDmAttribute *pDeltaData( pDelta->GetVertexData( deltaFieldIndex ) );
  3234. if ( pBaseData->GetType() != pDeltaData->GetType() )
  3235. break;
  3236. const CUtlVector< int > &baseIndices( pBase->GetVertexIndexData( baseFieldIndex ) );
  3237. switch ( pBaseData->GetType() )
  3238. {
  3239. case AT_FLOAT_ARRAY:
  3240. AddCorrectedDelta( CDmrArray< float >( pBaseData ), baseIndices, compList[ i ], baseFieldName, weight, pMask );
  3241. break;
  3242. case AT_COLOR_ARRAY:
  3243. AddCorrectedDelta( CDmrArray< Vector >( pBaseData ), baseIndices, compList[ i ], baseFieldName, weight, pMask );
  3244. break;
  3245. case AT_VECTOR2_ARRAY:
  3246. AddCorrectedDelta( CDmrArray< Vector2D >( pBaseData ), baseIndices, compList[ i ], baseFieldName, weight, pMask );
  3247. break;
  3248. case AT_VECTOR3_ARRAY:
  3249. AddCorrectedDelta( CDmrArray< Vector >( pBaseData ), baseIndices, compList[ i ], baseFieldName, weight, pMask );
  3250. break;
  3251. default:
  3252. break;
  3253. }
  3254. break;
  3255. }
  3256. }
  3257. }
  3258. return retVal;
  3259. }
  3260. //-----------------------------------------------------------------------------
  3261. // Interpolates between two arrays of values and stores the result in a
  3262. // CDmrArray.
  3263. //
  3264. // result = ( ( 1 - weight ) * a ) + ( weight * b )
  3265. //
  3266. //-----------------------------------------------------------------------------
  3267. template< class T_t >
  3268. bool CDmeMesh::InterpMaskedData(
  3269. CDmrArray< T_t > &aData,
  3270. const CUtlVector< T_t > &bData,
  3271. float weight,
  3272. const CDmeSingleIndexedComponent *pMask ) const
  3273. {
  3274. const int nDst = aData.Count();
  3275. if ( bData.Count() != nDst )
  3276. return false;
  3277. // The wacky way of writing these expression is because Vector4D is missing operators
  3278. // And this probably works better because of fewer temporaries
  3279. T_t a;
  3280. T_t b;
  3281. if ( pMask )
  3282. {
  3283. // With a weight mask
  3284. float vWeight;
  3285. for ( int i = 0; i < nDst; ++i )
  3286. {
  3287. if ( pMask->GetWeight( i, vWeight ) )
  3288. {
  3289. vWeight *= weight; // Specifically not clamping
  3290. a = aData.Get( i );
  3291. a *= ( 1.0f - vWeight );
  3292. b = bData[ i ];
  3293. b *= vWeight;
  3294. b += a;
  3295. aData.Set( i, b );
  3296. }
  3297. }
  3298. }
  3299. else
  3300. {
  3301. // Without a weight mask
  3302. const float oneMinusWeight( 1.0f - weight );
  3303. for ( int i = 0; i < nDst; ++i )
  3304. {
  3305. a = aData.Get( i );
  3306. a *= oneMinusWeight;
  3307. b = bData[ i ];
  3308. b *= weight;
  3309. b += a;
  3310. aData.Set( i, b );
  3311. }
  3312. }
  3313. return true;
  3314. }
  3315. //-----------------------------------------------------------------------------
  3316. // Interpolates between two CDmeVertexData's
  3317. //
  3318. // paData = ( ( 1 - weight ) * a ) + ( weight * b )
  3319. //-----------------------------------------------------------------------------
  3320. bool CDmeMesh::InterpMaskedData(
  3321. CDmeVertexData *paData,
  3322. const CDmeVertexData *pbData,
  3323. float weight,
  3324. const CDmeSingleIndexedComponent *pMask ) const
  3325. {
  3326. if ( !paData || !pbData || paData == pbData )
  3327. return false;
  3328. const int naField = paData->FieldCount();
  3329. const int nbField = pbData->FieldCount();
  3330. for ( int i = 0; i < naField; ++i )
  3331. {
  3332. const CUtlString &aFieldName( paData->FieldName( i ) );
  3333. for ( int j = 0; j < nbField; ++j )
  3334. {
  3335. const CUtlString &bFieldName( pbData->FieldName( j ) );
  3336. if ( aFieldName != bFieldName )
  3337. continue;
  3338. const FieldIndex_t aFieldIndex( paData->FindFieldIndex( aFieldName ) );
  3339. const FieldIndex_t bFieldIndex( pbData->FindFieldIndex( bFieldName ) );
  3340. if ( aFieldIndex < 0 || bFieldIndex < 0 )
  3341. break;
  3342. CDmAttribute *paAttr( paData->GetVertexData( aFieldIndex ) );
  3343. const CDmAttribute *pbAttr( pbData->GetVertexData( bFieldIndex ) );
  3344. if ( paAttr->GetType() != pbAttr->GetType() )
  3345. break;
  3346. if ( paData->GetVertexIndexData( aFieldIndex ).Count() != pbData->GetVertexIndexData( bFieldIndex ).Count() )
  3347. break;
  3348. switch ( paAttr->GetType() )
  3349. {
  3350. case AT_FLOAT_ARRAY:
  3351. InterpMaskedData( CDmrArray< float >( paAttr ), CDmrArrayConst< float >( pbAttr ).Get(), weight, pMask );
  3352. break;
  3353. case AT_COLOR_ARRAY:
  3354. InterpMaskedData( CDmrArray< Vector4D >( paAttr ), CDmrArrayConst< Vector4D >( pbAttr ).Get(), weight, pMask );
  3355. break;
  3356. case AT_VECTOR2_ARRAY:
  3357. InterpMaskedData( CDmrArray< Vector2D >( paAttr ), CDmrArrayConst< Vector2D >( pbAttr ).Get(), weight, pMask );
  3358. break;
  3359. case AT_VECTOR3_ARRAY:
  3360. InterpMaskedData( CDmrArray< Vector >( paAttr ), CDmrArrayConst< Vector >( pbAttr ).Get(), weight, pMask );
  3361. break;
  3362. default:
  3363. break;
  3364. }
  3365. break;
  3366. }
  3367. }
  3368. return true;
  3369. }
  3370. //-----------------------------------------------------------------------------
  3371. // Interpolates between the specified VertexData and the specified Delta
  3372. // If pBase is NULL it will become the current state
  3373. // If pDelta is NULL then the state to interpolate to will be the bind state
  3374. //-----------------------------------------------------------------------------
  3375. bool CDmeMesh::InterpMaskedDelta(
  3376. CDmeVertexDeltaData *pDelta,
  3377. CDmeVertexData *pDst /* = NULL */,
  3378. float weight /*= 1.0f */,
  3379. const CDmeSingleIndexedComponent *pMask /*= NULL */ )
  3380. {
  3381. CDmeVertexData *pDstBase = pDst ? pDst : GetCurrentBaseState();
  3382. CDmeVertexData *pBind = GetBindBaseState();
  3383. if ( !pDstBase || !pBind || pDstBase == pBind )
  3384. return false;
  3385. if ( pDelta == NULL )
  3386. {
  3387. // Interpolate between specified state and bind state
  3388. return InterpMaskedData( pDstBase, pBind, weight, pMask );
  3389. }
  3390. // This should be cached and recomputed only when states are added
  3391. CUtlVector< DeltaComputation_t > compList;
  3392. ComputeDependentDeltaStateList( compList );
  3393. bool retVal = false;
  3394. const int nDeltas( compList.Count() );
  3395. for ( int i = 0; i < nDeltas; ++i )
  3396. {
  3397. if ( pDelta != GetDeltaState( compList[ i ].m_nDeltaIndex ) )
  3398. continue;
  3399. retVal = true;
  3400. const int nBaseField( pDstBase->FieldCount() );
  3401. const int nBindField( pBind->FieldCount() );
  3402. const int nDeltaField( pDelta->FieldCount() );
  3403. CUtlVector< float > floatData;
  3404. CUtlVector< Vector2D > vector2DData;
  3405. CUtlVector< Vector > vectorData;
  3406. CUtlVector< Vector4D > vector4DData;
  3407. for ( int j( 0 ); j < nBaseField; ++j )
  3408. {
  3409. const CUtlString &baseFieldName( pDstBase->FieldName( j ) );
  3410. for ( int k = 0; k < nBindField; ++k )
  3411. {
  3412. const CUtlString &bindFieldName( pBind->FieldName( k ) );
  3413. if ( baseFieldName != bindFieldName )
  3414. continue;
  3415. for ( int l = 0; l < nDeltaField; ++l )
  3416. {
  3417. const CUtlString &deltaFieldName( pDelta->FieldName( l ) );
  3418. if ( bindFieldName != deltaFieldName )
  3419. continue;
  3420. const FieldIndex_t baseFieldIndex( pDstBase->FindFieldIndex( baseFieldName ) );
  3421. const FieldIndex_t bindFieldIndex( pBind->FindFieldIndex( bindFieldName ) );
  3422. const FieldIndex_t deltaFieldIndex( pDelta->FindFieldIndex( deltaFieldName ) );
  3423. if ( baseFieldIndex < 0 || bindFieldIndex < 0 || deltaFieldIndex < 0 )
  3424. break;
  3425. CDmAttribute *pDstBaseData( pDstBase->GetVertexData( baseFieldIndex ) );
  3426. CDmAttribute *pBindData( pBind->GetVertexData( bindFieldIndex ) );
  3427. CDmAttribute *pDeltaData( pDelta->GetVertexData( deltaFieldIndex ) );
  3428. if ( pDstBaseData->GetType() != pBindData->GetType() || pBindData->GetType() != pDeltaData->GetType() )
  3429. break;
  3430. const CUtlVector< int > &bindIndices( pBind->GetVertexIndexData( bindFieldIndex ) );
  3431. switch ( pDstBaseData->GetType() )
  3432. {
  3433. case AT_FLOAT_ARRAY:
  3434. floatData = CDmrArrayConst< float >( pBindData ).Get();
  3435. AddCorrectedDelta( floatData, bindIndices, compList[ i ], baseFieldName );
  3436. InterpMaskedData( CDmrArray< float >( pDstBaseData ), floatData, weight, pMask );
  3437. break;
  3438. case AT_COLOR_ARRAY:
  3439. vector4DData = CDmrArrayConst< Vector4D >( pBindData ).Get();
  3440. AddCorrectedDelta( vector4DData, bindIndices, compList[ i ], baseFieldName );
  3441. InterpMaskedData( CDmrArray< Vector4D >( pDstBaseData ), vector4DData, weight, pMask );
  3442. break;
  3443. case AT_VECTOR2_ARRAY:
  3444. vector2DData = CDmrArrayConst< Vector2D >( pBindData ).Get();
  3445. AddCorrectedDelta( vector2DData, bindIndices, compList[ i ], baseFieldName );
  3446. InterpMaskedData( CDmrArray< Vector2D >( pDstBaseData ), vector2DData, weight, pMask );
  3447. break;
  3448. case AT_VECTOR3_ARRAY:
  3449. vectorData = CDmrArrayConst< Vector >( pBindData ).Get();
  3450. AddCorrectedDelta( vectorData, bindIndices, compList[ i ], baseFieldName );
  3451. InterpMaskedData( CDmrArray< Vector >( pDstBaseData ), vectorData, weight, pMask );
  3452. break;
  3453. default:
  3454. break;
  3455. }
  3456. break;
  3457. }
  3458. }
  3459. }
  3460. }
  3461. return retVal;
  3462. }
  3463. //-----------------------------------------------------------------------------
  3464. // Returns the index of the closest selected vertex in the mesh to vIndex
  3465. // -1 on failure
  3466. //-----------------------------------------------------------------------------
  3467. int CDmeMesh::ClosestSelectedVertex( int vIndex, CDmeSingleIndexedComponent *pSelection, const CDmeVertexData *pPassedBase /* = NULL */ ) const
  3468. {
  3469. const CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  3470. if ( !pBase )
  3471. return -1;
  3472. const CUtlVector< Vector > &positions( pBase->GetPositionData() );
  3473. if ( vIndex >= positions.Count() )
  3474. return -1;
  3475. const Vector &p( positions[ vIndex ] );
  3476. CUtlVector< int > verts;
  3477. pSelection->GetComponents( verts );
  3478. const int nVerts = verts.Count();
  3479. if ( nVerts <= 0 )
  3480. return -1;
  3481. float minSqDist = p.DistToSqr( positions[ verts[ 0 ] ] );
  3482. float tmpSqDist;
  3483. int retVal = verts[ 0 ];
  3484. for ( int i = 1; i < nVerts; ++i )
  3485. {
  3486. tmpSqDist = p.DistToSqr( positions[ verts[ i ] ] );
  3487. if ( tmpSqDist < minSqDist )
  3488. {
  3489. minSqDist = tmpSqDist;
  3490. retVal = verts[ i ];
  3491. }
  3492. }
  3493. return retVal;
  3494. }
  3495. //-----------------------------------------------------------------------------
  3496. //
  3497. //-----------------------------------------------------------------------------
  3498. float CDmeMesh::DistanceBetween( int vIndex0, int vIndex1, const CDmeVertexData *pPassedBase /*= NULL */ ) const
  3499. {
  3500. const CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  3501. if ( !pBase )
  3502. return 0.0f;
  3503. const CUtlVector< Vector > &positions( pBase->GetPositionData() );
  3504. const int nPositions = positions.Count();
  3505. if ( vIndex0 >= nPositions || vIndex1 >= nPositions )
  3506. return 0.0f;
  3507. return positions[ vIndex0 ].DistTo( positions[ vIndex1 ] );
  3508. }
  3509. //-----------------------------------------------------------------------------
  3510. // Sorts DeltaComputation_t's by dimensionality
  3511. //-----------------------------------------------------------------------------
  3512. int ControlIndexLessFunc( const void *lhs, const void *rhs )
  3513. {
  3514. const int &lVal = *reinterpret_cast< const int * >( lhs );
  3515. const int &rVal = *reinterpret_cast< const int * >( rhs );
  3516. return lVal - rVal;
  3517. }
  3518. //-----------------------------------------------------------------------------
  3519. // This will compute a list of delta states that are superior to the passed
  3520. // delta state name (which has the form of <NAME>[_<NAME>]..., i.e. controls
  3521. // separated by underscores. The states will be returned in order from
  3522. // most superior to least superior. Since the deltas need to be broken down
  3523. // by the control deltas, if any control delta doesn't exist it will return false.
  3524. //
  3525. // A superior delta state is defined as a delta which has this delta as
  3526. // a dependent (or inferior) delta.
  3527. //
  3528. // Given the network of:
  3529. //
  3530. // A, B, C
  3531. // A_B, A_C, B_C
  3532. // A_B_C
  3533. //
  3534. // A_B_C is superior to A, B, A_B, A_C & B_C
  3535. // A_B is superior to A, B & C
  3536. // A_C is superior to A, B & C
  3537. // B_C is superior to A, B & C
  3538. //
  3539. // Input Output
  3540. // ------- --------------------
  3541. // A A_B_C, A_B, A_C, B_C
  3542. // B A_B_C, A_B, A_C, B_C
  3543. // C A_B_C, A_B, A_C, B_C
  3544. // A_B A_B_C
  3545. // A_C A_B_C
  3546. // B_C A_B_C
  3547. // A_B_C
  3548. //-----------------------------------------------------------------------------
  3549. bool CDmeMesh::ComputeSuperiorDeltaStateList( const char *pInferiorDeltaName, CUtlVector< int > &superiorDeltaStates )
  3550. {
  3551. // TODO: Compute this data only when the deltas are added, removed or renamed
  3552. CUtlVector< DeltaComputation_t > compList;
  3553. ComputeDeltaStateComputationList( compList );
  3554. // Typically the passed delta won't be in the list yet, but it could be, that's ok
  3555. // Treat it like it isn't to be sure.
  3556. CUtlVector< int > inferiorIndices;
  3557. if ( !GetControlDeltaIndices( pInferiorDeltaName, inferiorIndices ) )
  3558. return false;
  3559. const int nInferiorIndices = inferiorIndices.Count();
  3560. qsort( inferiorIndices.Base(), nInferiorIndices, sizeof( int ), ControlIndexLessFunc );
  3561. CUtlVector< int > superiorIndices;
  3562. int nSuperiorIndices;
  3563. CDmeVertexDeltaData *pSuperiorDelta;
  3564. for ( int i = compList.Count() - 1; i >= 0; --i )
  3565. {
  3566. const DeltaComputation_t &deltaComp = compList[ i ];
  3567. // For a delta to be superior, it has to have more control inputs than the specified delta
  3568. // compList is sorted in order of dimensionality, so safe to abort
  3569. if ( nInferiorIndices >= deltaComp.m_nDimensionality )
  3570. break;
  3571. pSuperiorDelta = GetDeltaState( deltaComp.m_nDeltaIndex );
  3572. if ( !pSuperiorDelta )
  3573. continue;
  3574. if ( !GetControlDeltaIndices( pSuperiorDelta, superiorIndices ) )
  3575. continue;
  3576. nSuperiorIndices = superiorIndices.Count();
  3577. qsort( superiorIndices.Base(), nSuperiorIndices, sizeof( int ), ControlIndexLessFunc );
  3578. int nFound = 0;
  3579. int si = 0;
  3580. for ( int ii = 0; ii < nInferiorIndices; ++ii )
  3581. {
  3582. const int &iIndex = inferiorIndices[ ii ];
  3583. while ( si < nSuperiorIndices && iIndex != superiorIndices[ si ] )
  3584. {
  3585. ++si;
  3586. }
  3587. if ( si < nSuperiorIndices )
  3588. {
  3589. ++nFound;
  3590. }
  3591. }
  3592. if ( nFound == nInferiorIndices )
  3593. {
  3594. superiorDeltaStates.AddToTail( deltaComp.m_nDeltaIndex );
  3595. }
  3596. }
  3597. return true;
  3598. }
  3599. //-----------------------------------------------------------------------------
  3600. // Removes the passed base state from the list of base states in the mesh
  3601. // if it exists in the list of base states in the mesh, but doesn't delete
  3602. // the element itself
  3603. //-----------------------------------------------------------------------------
  3604. bool CDmeMesh::RemoveBaseState( CDmeVertexData *pBase )
  3605. {
  3606. const int nBaseStates = m_BaseStates.Count();
  3607. for ( int i = 0; i < nBaseStates; ++i )
  3608. {
  3609. if ( m_BaseStates[ i ] == pBase )
  3610. {
  3611. return true;
  3612. }
  3613. }
  3614. return false;
  3615. }
  3616. //-----------------------------------------------------------------------------
  3617. // Adds an existing element to the list of base states of the mesh if it
  3618. // isn't already one of the base states
  3619. //-----------------------------------------------------------------------------
  3620. CDmeVertexData *CDmeMesh::FindOrAddBaseState( CDmeVertexData *pBase )
  3621. {
  3622. const int nBaseStates = m_BaseStates.Count();
  3623. for ( int i = 0; i < nBaseStates; ++i )
  3624. {
  3625. if ( m_BaseStates[ i ] == pBase )
  3626. {
  3627. return pBase;
  3628. }
  3629. }
  3630. return m_BaseStates[ m_BaseStates.AddToTail( pBase ) ];
  3631. }
  3632. //-----------------------------------------------------------------------------
  3633. // TODO: Current state is insufficient as long as the current state isn't
  3634. // created from the current delta weights
  3635. //-----------------------------------------------------------------------------
  3636. void CDmeMesh::GetBoundingSphere(
  3637. Vector &c, float &r,
  3638. CDmeVertexData *pPassedBase /* = NULL */, CDmeSingleIndexedComponent *pPassedSelection /* = NULL */ ) const
  3639. {
  3640. c.Zero();
  3641. r = 0.0f;
  3642. const CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  3643. if ( !pBase )
  3644. return;
  3645. const FieldIndex_t pIndex = pBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  3646. if ( pIndex < 0 )
  3647. return;
  3648. const CUtlVector< Vector > &pData( pBase->GetPositionData() );
  3649. const int nPositions = pData.Count();
  3650. if ( pPassedSelection )
  3651. {
  3652. const int nSelectionCount = pPassedSelection->Count();
  3653. int nIndex;
  3654. float fWeight;
  3655. for ( int i = 0; i < nSelectionCount; ++i )
  3656. {
  3657. pPassedSelection->GetComponent( i, nIndex, fWeight );
  3658. c += pData[ nIndex ];
  3659. }
  3660. c /= static_cast< float >( nSelectionCount );
  3661. float sqDist;
  3662. for ( int i = 0; i < nSelectionCount; ++i )
  3663. {
  3664. for ( int iPos = 0; iPos < nPositions; ++iPos )
  3665. {
  3666. sqDist = c.DistToSqr( pData[ iPos ] );
  3667. if ( sqDist > r )
  3668. {
  3669. r = sqDist;
  3670. }
  3671. }
  3672. }
  3673. }
  3674. else
  3675. {
  3676. for ( int i = 0; i < nPositions; ++i )
  3677. {
  3678. c += pData[ i ];
  3679. }
  3680. c /= static_cast< float >( nPositions );
  3681. float sqDist;
  3682. for ( int i = 0; i < nPositions; ++i )
  3683. {
  3684. for ( int iPos = 0; iPos < nPositions; ++iPos )
  3685. {
  3686. sqDist = c.DistToSqr( pData[iPos] );
  3687. if ( sqDist > r )
  3688. {
  3689. r = sqDist;
  3690. }
  3691. }
  3692. }
  3693. }
  3694. r = sqrt( r );
  3695. }
  3696. //-----------------------------------------------------------------------------
  3697. //
  3698. //-----------------------------------------------------------------------------
  3699. void CDmeMesh::GetBoundingBox( Vector &min, Vector &max, CDmeVertexData *pPassedBase /* = NULL */, CDmeSingleIndexedComponent *pPassedSelection /* = NULL */ ) const
  3700. {
  3701. min.Zero();
  3702. max.Zero();
  3703. const CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  3704. if ( !pBase )
  3705. return;
  3706. const FieldIndex_t pIndex = pBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  3707. if ( pIndex < 0 )
  3708. return;
  3709. const CUtlVector< Vector > &pData( pBase->GetPositionData() );
  3710. const int nPositions = pData.Count();
  3711. if ( pPassedSelection )
  3712. {
  3713. const int nSelectionCount = pPassedSelection->Count();
  3714. if ( nSelectionCount > 0 )
  3715. {
  3716. int nIndex;
  3717. float fWeight;
  3718. pPassedSelection->GetComponent( 0, nIndex, fWeight );
  3719. min = pData[ nIndex ];
  3720. max = min;
  3721. for ( int i = 1; i < nSelectionCount; ++i )
  3722. {
  3723. pPassedSelection->GetComponent( i, nIndex, fWeight );
  3724. const Vector &p = pData[ nIndex ];
  3725. if ( p.x < min.x )
  3726. {
  3727. min.x = p.x;
  3728. }
  3729. else if ( p.x > max.x )
  3730. {
  3731. max.x = p.x;
  3732. }
  3733. if ( p.y < min.y )
  3734. {
  3735. min.y = p.y;
  3736. }
  3737. else if ( p.y > max.y )
  3738. {
  3739. max.y = p.y;
  3740. }
  3741. if ( p.z < min.z )
  3742. {
  3743. min.z = p.z;
  3744. }
  3745. else if ( p.z > max.z )
  3746. {
  3747. max.z = p.z;
  3748. }
  3749. }
  3750. }
  3751. }
  3752. else
  3753. {
  3754. if ( nPositions > 0 )
  3755. {
  3756. min = pData[ 0 ];
  3757. max = min;
  3758. for ( int i = 1; i < nPositions; ++i )
  3759. {
  3760. const Vector &p = pData[ i ];
  3761. if ( p.x < min.x )
  3762. {
  3763. min.x = p.x;
  3764. }
  3765. else if ( p.x > max.x )
  3766. {
  3767. max.x = p.x;
  3768. }
  3769. if ( p.y < min.y )
  3770. {
  3771. min.y = p.y;
  3772. }
  3773. else if ( p.y > max.y )
  3774. {
  3775. max.y = p.y;
  3776. }
  3777. if ( p.z < min.z )
  3778. {
  3779. min.z = p.z;
  3780. }
  3781. else if ( p.z > max.z )
  3782. {
  3783. max.z = p.z;
  3784. }
  3785. }
  3786. }
  3787. }
  3788. }
  3789. //-----------------------------------------------------------------------------
  3790. //
  3791. //-----------------------------------------------------------------------------
  3792. template < class T_t >
  3793. bool CDmeMesh::SetBaseDataToDeltas(
  3794. CDmeVertexData *pBase,
  3795. CDmeVertexData::StandardFields_t nStandardField, CDmrArrayConst< T_t > &srcData, CDmrArray< T_t > &dstData, bool bDoStereo, bool bDoLag )
  3796. {
  3797. const int nDataCount = dstData.Count();
  3798. if ( srcData.Count() != nDataCount )
  3799. return false;
  3800. // Create the temp buffer for the data
  3801. T_t *pData = reinterpret_cast< T_t * >( alloca( nDataCount * sizeof( T_t ) ) );
  3802. // Copy the data from the src base state
  3803. memcpy( pData, srcData.Base(), nDataCount * sizeof( T_t ) );
  3804. const int nCount = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL].Count();
  3805. Assert( m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL].Count() == m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED].Count() );
  3806. if ( bDoStereo )
  3807. {
  3808. for ( int i = 0; i < nCount; ++i )
  3809. {
  3810. float flLeftWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].x;
  3811. float flRightWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].y;
  3812. float flLeftWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].x;
  3813. float flRightWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].y;
  3814. if ( flLeftWeight <= 0.0f && flRightWeight <= 0.0f && ( !bDoLag || ( flLeftWeightLagged <= 0.0f && flRightWeightLagged <= 0.0f ) ) )
  3815. continue;
  3816. AddStereoVertexDelta< T_t >( pBase, pData, sizeof( T_t ), nStandardField, i, bDoLag );
  3817. }
  3818. }
  3819. else
  3820. {
  3821. for ( int i = 0; i < nCount; ++i )
  3822. {
  3823. float flWeight = m_DeltaStateWeights[MESH_DELTA_WEIGHT_NORMAL][i].x;
  3824. float flWeightLagged = m_DeltaStateWeights[MESH_DELTA_WEIGHT_LAGGED][i].x;
  3825. if ( flWeight < 0.0f && ( !bDoLag || flWeightLagged <= 0.0f ) )
  3826. continue;
  3827. AddVertexDelta< T_t >( pBase, pData, sizeof( T_t ), nStandardField, i, bDoLag );
  3828. }
  3829. }
  3830. dstData.SetMultiple( 0, nDataCount, pData );
  3831. return true;
  3832. }
  3833. //-----------------------------------------------------------------------------
  3834. // Sets the specified based state to the version of the mesh specified by the
  3835. // current weighted deltas
  3836. // It's ok to modify the bind state... if you know what you're doing
  3837. //-----------------------------------------------------------------------------
  3838. bool CDmeMesh::SetBaseStateToDeltas( CDmeVertexData *pPassedBase /*= NULL */ )
  3839. {
  3840. CDmeVertexData *pBind = GetBindBaseState();
  3841. CDmeVertexData *pBase = pPassedBase ? pPassedBase : GetCurrentBaseState();
  3842. if ( !pBind || !pBase )
  3843. return false;
  3844. CDmeVertexData::StandardFields_t deltaFields[] =
  3845. {
  3846. CDmeVertexData::FIELD_POSITION,
  3847. CDmeVertexData::FIELD_NORMAL,
  3848. CDmeVertexData::FIELD_WRINKLE
  3849. };
  3850. const bool bDoStereo = ( pBind->FindFieldIndex( CDmeVertexDeltaData::FIELD_BALANCE ) >= 0 );
  3851. for ( int i = 0; i < sizeof( deltaFields ) / sizeof( deltaFields[ 0 ] ); ++i )
  3852. {
  3853. const CDmeVertexDeltaData::StandardFields_t nStandardField = deltaFields[ i ];
  3854. const int nSrcField = pBind->FindFieldIndex( nStandardField );
  3855. const int nDstField = pBase->FindFieldIndex( nStandardField );
  3856. if ( nSrcField < 0 || nDstField < 0 )
  3857. continue;
  3858. const CDmAttribute *pSrcAttr = pBind->GetVertexData( nSrcField );
  3859. CDmAttribute *pDstAttr = pBase->GetVertexData( nDstField );
  3860. if ( !pSrcAttr || !pDstAttr || pSrcAttr->GetType() != pDstAttr->GetType() )
  3861. continue;
  3862. switch ( pDstAttr->GetType() )
  3863. {
  3864. case AT_FLOAT_ARRAY:
  3865. SetBaseDataToDeltas( pBind, nStandardField, CDmrArrayConst< float >( pSrcAttr ), CDmrArray< float >( pDstAttr ), bDoStereo, false );
  3866. break;
  3867. case AT_VECTOR3_ARRAY:
  3868. SetBaseDataToDeltas( pBind, nStandardField, CDmrArrayConst< Vector >( pSrcAttr ), CDmrArray< Vector >( pDstAttr ), bDoStereo, false );
  3869. break;
  3870. default:
  3871. Assert( 0 );
  3872. break;
  3873. }
  3874. }
  3875. return true;
  3876. }
  3877. //-----------------------------------------------------------------------------
  3878. // Replace all instances of a material with a different material
  3879. //-----------------------------------------------------------------------------
  3880. void CDmeMesh::ReplaceMaterial( const char *pOldMaterialName, const char *pNewMaterialName )
  3881. {
  3882. char pOldFixedName[MAX_PATH];
  3883. char pNewFixedName[MAX_PATH];
  3884. char pFixedName[MAX_PATH];
  3885. if ( pOldMaterialName )
  3886. {
  3887. V_FixupPathName( pOldFixedName, sizeof(pOldFixedName), pOldMaterialName );
  3888. }
  3889. V_FixupPathName( pNewFixedName, sizeof(pNewFixedName), pNewMaterialName );
  3890. V_FixSlashes( pNewFixedName, '/' );
  3891. CDmeMaterial *pReplacementMaterial = NULL;
  3892. int nCount = m_FaceSets.Count();
  3893. for ( int i = 0; i < nCount; ++i )
  3894. {
  3895. CDmeFaceSet *pFaceSet = m_FaceSets[i];
  3896. CDmeMaterial *pMaterial = pFaceSet->GetMaterial();
  3897. if ( pOldMaterialName )
  3898. {
  3899. const char *pMaterialName = pMaterial->GetMaterialName();
  3900. V_FixupPathName( pFixedName, sizeof(pFixedName), pMaterialName );
  3901. if ( Q_stricmp( pFixedName, pOldFixedName ) )
  3902. continue;
  3903. }
  3904. if ( !pReplacementMaterial )
  3905. {
  3906. pReplacementMaterial = CreateElement< CDmeMaterial >( pMaterial->GetName(), pMaterial->GetFileId() );
  3907. pReplacementMaterial->SetMaterial( pNewFixedName );
  3908. }
  3909. pFaceSet->SetMaterial( pReplacementMaterial );
  3910. }
  3911. }
  3912. //-----------------------------------------------------------------------------
  3913. // Cleans up delta data that is referring to normals which have been merged out
  3914. //-----------------------------------------------------------------------------
  3915. static void CollapseRedundantDeltaNormals( CDmeVertexDeltaData *pDmeDelta, const CUtlVector< int > &normalMap )
  3916. {
  3917. if ( !pDmeDelta )
  3918. return;
  3919. FieldIndex_t nNormalFieldIndex = pDmeDelta->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  3920. if ( nNormalFieldIndex < 0 )
  3921. return; // No normal deltas
  3922. const CUtlVector< Vector > &oldNormalData = pDmeDelta->GetNormalData();
  3923. const CUtlVector< int > &oldNormalIndices = pDmeDelta->GetVertexIndexData( nNormalFieldIndex );
  3924. Assert( oldNormalData.Count() == oldNormalIndices.Count() );
  3925. CUtlVector< bool > done;
  3926. done.SetCount( normalMap.Count() );
  3927. Q_memset( done.Base(), 0, done.Count() * sizeof( bool ) );
  3928. CUtlVector< Vector > newNormalData;
  3929. CUtlVector< int > newNormalIndices;
  3930. for ( int i = 0; i < oldNormalIndices.Count(); ++i )
  3931. {
  3932. const int nNewIndex = normalMap[ oldNormalIndices[i] ];
  3933. if ( nNewIndex < 0 || done[ nNewIndex ] )
  3934. continue;
  3935. done[ nNewIndex ] = true;
  3936. newNormalData.AddToTail( oldNormalData[i] );
  3937. newNormalIndices.AddToTail( nNewIndex );
  3938. }
  3939. pDmeDelta->RemoveAllVertexData( nNormalFieldIndex );
  3940. nNormalFieldIndex = pDmeDelta->CreateField( CDmeVertexDeltaData::FIELD_NORMAL );
  3941. pDmeDelta->AddVertexData( nNormalFieldIndex, newNormalData.Count() );
  3942. pDmeDelta->SetVertexData( nNormalFieldIndex, 0, newNormalData.Count(), AT_VECTOR3, newNormalData.Base() );
  3943. pDmeDelta->SetVertexIndices( nNormalFieldIndex, 0, newNormalIndices.Count(), newNormalIndices.Base() );
  3944. }
  3945. //-----------------------------------------------------------------------------
  3946. // Remove redundant normals from a DMX Mesh
  3947. // Looks at all of the normals around each position vertex and merges normals
  3948. // which are numerically similar (within flNormalBlend which by default in
  3949. // studiomdl is within 2 degrees) around that vertex
  3950. //
  3951. // If this would result in more normals being created, then don't do anything
  3952. // return false.
  3953. //-----------------------------------------------------------------------------
  3954. static bool CollapseRedundantBaseNormals( CDmeVertexData *pDmeVertexData, CUtlVector< int > &normalMap, float flNormalBlend )
  3955. {
  3956. if ( !pDmeVertexData )
  3957. return false;
  3958. FieldIndex_t nPositionFieldIndex = pDmeVertexData->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  3959. FieldIndex_t nNormalFieldIndex = pDmeVertexData->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  3960. if ( nPositionFieldIndex < 0 || nNormalFieldIndex < 0 )
  3961. return false;
  3962. const CUtlVector< Vector > &oldNormalData = pDmeVertexData->GetNormalData();
  3963. const CUtlVector< int > &oldNormalIndices = pDmeVertexData->GetVertexIndexData( nNormalFieldIndex );
  3964. CUtlVector< Vector > newNormalData;
  3965. CUtlVector< int > newNormalIndices;
  3966. newNormalIndices.SetCount( oldNormalIndices.Count() );
  3967. for ( int i = 0; i < newNormalIndices.Count(); ++i )
  3968. {
  3969. newNormalIndices[i] = -1;
  3970. }
  3971. const int nPositionDataCount = pDmeVertexData->GetPositionData().Count();
  3972. for ( int i = 0; i < nPositionDataCount; ++i )
  3973. {
  3974. int nNewNormalDataIndex = newNormalData.Count();
  3975. const CUtlVector< int > &vertexIndices = pDmeVertexData->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_POSITION, i );
  3976. for ( int j = 0; j < vertexIndices.Count(); ++j )
  3977. {
  3978. bool bUnique = true;
  3979. const int nVertexIndex = vertexIndices[j];
  3980. const Vector &vNormal = oldNormalData[ oldNormalIndices[ vertexIndices[j] ] ];
  3981. for ( int k = nNewNormalDataIndex; k < newNormalData.Count(); ++k )
  3982. {
  3983. if ( DotProduct( vNormal, newNormalData[k] ) > flNormalBlend )
  3984. {
  3985. newNormalIndices[ nVertexIndex ] = k;
  3986. bUnique = false;
  3987. break;
  3988. }
  3989. }
  3990. if ( !bUnique )
  3991. continue;
  3992. newNormalIndices[ nVertexIndex ] = newNormalData.AddToTail( vNormal );
  3993. }
  3994. }
  3995. for ( int i = 0; i < newNormalIndices.Count(); ++i )
  3996. {
  3997. if ( newNormalIndices[i] == -1 )
  3998. {
  3999. newNormalIndices[i] = newNormalData.AddToTail( oldNormalData[ oldNormalIndices[i] ] );
  4000. }
  4001. }
  4002. // If it's the same or more don't do anything
  4003. if ( newNormalData.Count() >= oldNormalData.Count() )
  4004. return false;
  4005. normalMap.SetCount( oldNormalData.Count() );
  4006. for ( int i = 0; i < normalMap.Count(); ++i )
  4007. {
  4008. normalMap[i] = -1;
  4009. }
  4010. Assert( newNormalIndices.Count() == oldNormalIndices.Count() );
  4011. for ( int i = 0; i < oldNormalIndices.Count(); ++i )
  4012. {
  4013. if ( normalMap[ oldNormalIndices[i] ] == -1 )
  4014. {
  4015. normalMap[ oldNormalIndices[i] ] = newNormalIndices[i];
  4016. }
  4017. else
  4018. {
  4019. Assert( normalMap[ oldNormalIndices[i] ] == newNormalIndices[i] );
  4020. }
  4021. }
  4022. pDmeVertexData->RemoveAllVertexData( nNormalFieldIndex );
  4023. nNormalFieldIndex = pDmeVertexData->CreateField( CDmeVertexDeltaData::FIELD_NORMAL );
  4024. pDmeVertexData->AddVertexData( nNormalFieldIndex, newNormalData.Count() );
  4025. pDmeVertexData->SetVertexData( nNormalFieldIndex, 0, newNormalData.Count(), AT_VECTOR3, newNormalData.Base() );
  4026. pDmeVertexData->SetVertexIndices( nNormalFieldIndex, 0, newNormalIndices.Count(), newNormalIndices.Base() );
  4027. return true;
  4028. }
  4029. //-----------------------------------------------------------------------------
  4030. // Collapse all normals with the same numerical value into the same normal
  4031. //-----------------------------------------------------------------------------
  4032. static bool CollapseRedundantBaseNormalsAggressive( CDmeVertexData *pDmeVertexData, float flNormalBlend )
  4033. {
  4034. if ( !pDmeVertexData )
  4035. return false;
  4036. FieldIndex_t nNormalFieldIndex = pDmeVertexData->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  4037. if ( nNormalFieldIndex < 0 )
  4038. return false;
  4039. const CUtlVector< Vector > &oldNormalData = pDmeVertexData->GetNormalData();
  4040. const CUtlVector< int > &oldNormalIndices = pDmeVertexData->GetVertexIndexData( nNormalFieldIndex );
  4041. CUtlVector< int > normalMap;
  4042. normalMap.SetCount( oldNormalData.Count() );
  4043. CUtlVector< Vector > newNormalData;
  4044. for ( int i = 0; i < oldNormalData.Count(); ++i )
  4045. {
  4046. bool bUnique = true;
  4047. const Vector &vNormal = oldNormalData[ i ];
  4048. for ( int j = 0; j < newNormalData.Count(); ++j )
  4049. {
  4050. if ( DotProduct( vNormal, newNormalData[j] ) > flNormalBlend )
  4051. {
  4052. normalMap[ i ] = j;
  4053. bUnique = false;
  4054. break;
  4055. }
  4056. }
  4057. if ( !bUnique )
  4058. continue;
  4059. normalMap[ i ] = newNormalData.AddToTail( vNormal );
  4060. }
  4061. // If it's the same then don't do anything.
  4062. if ( newNormalData.Count() >= oldNormalData.Count() )
  4063. return false;
  4064. CUtlVector< int > newNormalIndices;
  4065. newNormalIndices.SetCount( oldNormalIndices.Count() );
  4066. for ( int i = 0; i < oldNormalIndices.Count(); ++i )
  4067. {
  4068. newNormalIndices[i] = normalMap[ oldNormalIndices[i] ];
  4069. }
  4070. pDmeVertexData->RemoveAllVertexData( nNormalFieldIndex );
  4071. nNormalFieldIndex = pDmeVertexData->CreateField( CDmeVertexDeltaData::FIELD_NORMAL );
  4072. pDmeVertexData->AddVertexData( nNormalFieldIndex, newNormalData.Count() );
  4073. pDmeVertexData->SetVertexData( nNormalFieldIndex, 0, newNormalData.Count(), AT_VECTOR3, newNormalData.Base() );
  4074. pDmeVertexData->SetVertexIndices( nNormalFieldIndex, 0, newNormalIndices.Count(), newNormalIndices.Base() );
  4075. return true;
  4076. }
  4077. //-----------------------------------------------------------------------------
  4078. //
  4079. //-----------------------------------------------------------------------------
  4080. void CDmeMesh::NormalizeNormals()
  4081. {
  4082. Vector vNormal;
  4083. for ( int i = 0; i < this->BaseStateCount(); ++i )
  4084. {
  4085. CDmeVertexData *pDmeVertexData = GetBaseState( i );
  4086. if ( !pDmeVertexData )
  4087. continue;
  4088. FieldIndex_t nNormalIndex = pDmeVertexData->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  4089. if ( nNormalIndex < 0 )
  4090. continue;
  4091. CDmAttribute *pDmNormalAttr = pDmeVertexData->GetVertexData( nNormalIndex );
  4092. if ( !pDmNormalAttr )
  4093. continue;
  4094. CDmrArray< Vector > normalData( pDmNormalAttr );
  4095. for ( int j = 0; j < normalData.Count(); ++j )
  4096. {
  4097. vNormal = normalData.Get( j );
  4098. VectorNormalize( vNormal );
  4099. normalData.Set( j, vNormal );
  4100. }
  4101. }
  4102. }
  4103. //-----------------------------------------------------------------------------
  4104. //
  4105. //-----------------------------------------------------------------------------
  4106. void CDmeMesh::CollapseRedundantNormals( float flNormalBlend )
  4107. {
  4108. NormalizeNormals();
  4109. CDmeVertexData *pDmeBind = GetBindBaseState();
  4110. if ( !pDmeBind )
  4111. return;
  4112. CUtlVector< int > normalMap;
  4113. const int nDeltaStateCount = DeltaStateCount();
  4114. if ( nDeltaStateCount <= 0 )
  4115. {
  4116. // No deltas
  4117. if ( CollapseRedundantBaseNormalsAggressive( pDmeBind, flNormalBlend ) )
  4118. {
  4119. // Collapse any other states
  4120. for ( int i = 0; i < BaseStateCount(); ++i )
  4121. {
  4122. CDmeVertexData *pDmeVertexData = GetBaseState( i );
  4123. if ( !pDmeVertexData || pDmeVertexData == pDmeBind )
  4124. continue;
  4125. CollapseRedundantBaseNormalsAggressive( pDmeVertexData, flNormalBlend );
  4126. }
  4127. }
  4128. }
  4129. else
  4130. {
  4131. // Collapse the base state
  4132. if ( CollapseRedundantBaseNormals( pDmeBind, normalMap, flNormalBlend ) )
  4133. {
  4134. // Collapse any delta states using the baseState normal map
  4135. for ( int i = 0; i < DeltaStateCount(); ++i )
  4136. {
  4137. CDmeVertexDeltaData *pDmeDeltaData = GetDeltaState( i );
  4138. if ( !pDmeDeltaData )
  4139. continue;
  4140. CollapseRedundantDeltaNormals( pDmeDeltaData, normalMap );
  4141. }
  4142. // Collapse any other states
  4143. for ( int i = 0; i < BaseStateCount(); ++i )
  4144. {
  4145. CDmeVertexData *pDmeVertexData = GetBaseState( i );
  4146. if ( !pDmeVertexData || pDmeVertexData == pDmeBind )
  4147. continue;
  4148. CollapseRedundantBaseNormals( pDmeVertexData, normalMap, flNormalBlend );
  4149. }
  4150. }
  4151. }
  4152. }