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

330 lines
10 KiB

  1. //========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef FLEXRENDERDATA_H
  8. #define FLEXRENDERDATA_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "mathlib/vector.h"
  13. #include "mathlib/ssemath.h"
  14. #include "utlvector.h"
  15. #include "studio.h"
  16. //-----------------------------------------------------------------------------
  17. // forward declarations
  18. //-----------------------------------------------------------------------------
  19. struct mstudiomesh_t;
  20. //-----------------------------------------------------------------------------
  21. // Used by flex vertex data cache
  22. //-----------------------------------------------------------------------------
  23. struct CachedPosNormTan_t
  24. {
  25. Vector4D m_Position;
  26. Vector4D m_Normal;
  27. Vector4D m_TangentS;
  28. CachedPosNormTan_t() {}
  29. CachedPosNormTan_t( CachedPosNormTan_t const& src )
  30. {
  31. Vector4DCopy( src.m_Position, m_Position );
  32. Vector4DCopy( src.m_Normal, m_Normal );
  33. Vector4DCopy( src.m_TangentS, m_TangentS );
  34. Assert( m_TangentS.w == 1.0f || m_TangentS.w == -1.0f );
  35. }
  36. };
  37. //-----------------------------------------------------------------------------
  38. // Used by world (decal) vertex data cache
  39. //-----------------------------------------------------------------------------
  40. struct CachedPosNorm_t
  41. {
  42. Vector4DAligned m_Position;
  43. Vector4DAligned m_Normal;
  44. CachedPosNorm_t() {}
  45. CachedPosNorm_t( CachedPosNorm_t const& src )
  46. {
  47. Vector4DCopy( src.m_Position, m_Position );
  48. Vector4DCopy( src.m_Normal, m_Normal );
  49. }
  50. };
  51. //-----------------------------------------------------------------------------
  52. // Stores flex vertex data and world (decal) vertex data for the lifetime of the model rendering
  53. //-----------------------------------------------------------------------------
  54. class CCachedRenderData
  55. {
  56. public:
  57. // Constructor
  58. CCachedRenderData();
  59. // Call this when we start to render a new model
  60. void StartModel();
  61. // Used to hook ourselves into a particular body part, model, and mesh
  62. void SetBodyPart( int bodypart );
  63. void SetModel( int model );
  64. void SetMesh( int mesh );
  65. // For faster setup in the decal code
  66. void SetBodyModelMesh( int body, int model, int mesh );
  67. // Used to set up a flex computation
  68. bool IsFlexComputationDone( ) const;
  69. // Used to set up a computation (for world or flex data)
  70. void SetupComputation( mstudiomesh_t *pMesh, bool flexComputation = false );
  71. // Is a particular vertex flexed?
  72. bool IsVertexFlexed( int vertex ) const;
  73. bool IsThinVertexFlexed( int vertex ) const;
  74. // Checks to see if the vertex is defined
  75. bool IsVertexPositionCached( int vertex ) const;
  76. // Gets a flexed vertex
  77. CachedPosNormTan_t* GetFlexVertex( int vertex );
  78. // Gets a flexed vertex
  79. CachedPosNorm_t* GetThinFlexVertex( int vertex );
  80. // Creates a new flexed vertex to be associated with a vertex
  81. CachedPosNormTan_t* CreateFlexVertex( int vertex );
  82. // Creates a new flexed vertex to be associated with a vertex
  83. CachedPosNorm_t* CreateThinFlexVertex( int vertex );
  84. // Renormalizes the normals and tangents of the flex verts
  85. void RenormalizeFlexVertices( bool bHasTangentData, bool bQuadList );
  86. // Gets a decal vertex
  87. CachedPosNorm_t* GetWorldVertex( int vertex );
  88. // Creates a new decal vertex to be associated with a vertex
  89. CachedPosNorm_t* CreateWorldVertex( int vertex );
  90. template< class T >
  91. void ComputeFlexedVertex_StreamOffset( studiohdr_t *pStudioHdr, mstudioflex_t *pflex, T *pvanim, int vertCount, float w1, float w2, float w3, float w4 );
  92. void ComputeFlexedVertex_StreamOffset_Optimized( studiohdr_t *pStudioHdr, mstudioflex_t *pflex, mstudiovertanim_t *pvanim, int vertCount, float w1, float w2, float w3, float w4);
  93. void ComputeFlexedVertexWrinkle_StreamOffset_Optimized( studiohdr_t *pStudioHdr, mstudioflex_t *pflex, mstudiovertanim_wrinkle_t *pvanim, int vertCount, float w1, float w2, float w3, float w4);
  94. private:
  95. // Used to create the flex render data. maps
  96. struct CacheIndex_t
  97. {
  98. unsigned short m_Tag;
  99. unsigned short m_VertexIndex;
  100. };
  101. // A dictionary for the cached data
  102. struct CacheDict_t
  103. {
  104. unsigned short m_FirstIndex;
  105. unsigned short m_IndexCount;
  106. unsigned short m_Tag;
  107. unsigned short m_FlexTag;
  108. CacheDict_t() : m_Tag(0), m_FlexTag(0) {}
  109. };
  110. typedef CUtlVector< CacheDict_t > CacheMeshDict_t;
  111. typedef CUtlVector< CacheMeshDict_t > CacheModelDict_t;
  112. typedef CUtlVector< CacheModelDict_t > CacheBodyPartDict_t;
  113. // Flex data, allocated for the lifespan of rendering
  114. // Can't use UtlVector due to alignment issues
  115. int m_FlexVertexCount;
  116. CachedPosNormTan_t m_pFlexVerts[MAXSTUDIOFLEXVERTS+1];
  117. // Flex data, allocated for the lifespan of rendering
  118. // Can't use UtlVector due to alignment issues
  119. int m_ThinFlexVertexCount;
  120. CachedPosNorm_t m_pThinFlexVerts[MAXSTUDIOFLEXVERTS+1];
  121. // World data, allocated for the lifespan of rendering
  122. // Can't use UtlVector due to alignment issues
  123. int m_WorldVertexCount;
  124. CachedPosNorm_t m_pWorldVerts[MAXSTUDIOVERTS+1];
  125. // Maps actual mesh vertices into flex cache + world cache indices
  126. int m_IndexCount;
  127. CacheIndex_t m_pFlexIndex[MAXSTUDIOVERTS+1];
  128. CacheIndex_t m_pThinFlexIndex[MAXSTUDIOVERTS+1];
  129. CacheIndex_t m_pWorldIndex[MAXSTUDIOVERTS+1];
  130. CacheBodyPartDict_t m_CacheDict;
  131. // The flex tag
  132. unsigned short m_CurrentTag;
  133. // the current body, model, and mesh
  134. int m_Body;
  135. int m_Model;
  136. int m_Mesh;
  137. // mapping for the current mesh to flex data
  138. CacheIndex_t* m_pFirstFlexIndex;
  139. CacheIndex_t* m_pFirstThinFlexIndex;
  140. CacheIndex_t* m_pFirstWorldIndex;
  141. friend class CStudioRender;
  142. };
  143. //-----------------------------------------------------------------------------
  144. // Checks to see if the vertex is defined
  145. //-----------------------------------------------------------------------------
  146. inline bool CCachedRenderData::IsVertexFlexed( int vertex ) const
  147. {
  148. return (m_pFirstFlexIndex && (m_pFirstFlexIndex[vertex].m_Tag == m_CurrentTag));
  149. }
  150. inline bool CCachedRenderData::IsThinVertexFlexed( int vertex ) const
  151. {
  152. return (m_pFirstThinFlexIndex && (m_pFirstThinFlexIndex[vertex].m_Tag == m_CurrentTag));
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Gets an existing flexed vertex associated with a vertex
  156. //-----------------------------------------------------------------------------
  157. inline CachedPosNormTan_t* CCachedRenderData::GetFlexVertex( int vertex )
  158. {
  159. Assert( m_pFirstFlexIndex );
  160. Assert( m_pFirstFlexIndex[vertex].m_Tag == m_CurrentTag );
  161. return &m_pFlexVerts[ m_pFirstFlexIndex[vertex].m_VertexIndex ];
  162. }
  163. inline CachedPosNorm_t* CCachedRenderData::GetThinFlexVertex( int vertex )
  164. {
  165. Assert( m_pFirstThinFlexIndex );
  166. Assert( m_pFirstThinFlexIndex[vertex].m_Tag == m_CurrentTag );
  167. return &m_pThinFlexVerts[ m_pFirstThinFlexIndex[vertex].m_VertexIndex ];
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Checks to see if the vertex is defined
  171. //-----------------------------------------------------------------------------
  172. inline bool CCachedRenderData::IsVertexPositionCached( int vertex ) const
  173. {
  174. return (m_pFirstWorldIndex && (m_pFirstWorldIndex[vertex].m_Tag == m_CurrentTag));
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Gets an existing world vertex associated with a vertex
  178. //-----------------------------------------------------------------------------
  179. inline CachedPosNorm_t* CCachedRenderData::GetWorldVertex( int vertex )
  180. {
  181. Assert( m_pFirstWorldIndex );
  182. Assert( m_pFirstWorldIndex[vertex].m_Tag == m_CurrentTag );
  183. return &m_pWorldVerts[ m_pFirstWorldIndex[vertex].m_VertexIndex ];
  184. }
  185. //-----------------------------------------------------------------------------
  186. // For faster setup in the decal code
  187. //-----------------------------------------------------------------------------
  188. inline void CCachedRenderData::SetBodyModelMesh( int body, int model, int mesh)
  189. {
  190. m_Body = body;
  191. m_Model = model;
  192. m_Mesh = mesh;
  193. // At this point, we should have all 3 defined.
  194. CacheDict_t& dict = m_CacheDict[m_Body][m_Model][m_Mesh];
  195. if (dict.m_Tag == m_CurrentTag)
  196. {
  197. m_pFirstFlexIndex = &m_pFlexIndex[dict.m_FirstIndex];
  198. m_pFirstThinFlexIndex = &m_pThinFlexIndex[dict.m_FirstIndex];
  199. m_pFirstWorldIndex = &m_pWorldIndex[dict.m_FirstIndex];
  200. }
  201. else
  202. {
  203. m_pFirstFlexIndex = 0;
  204. m_pFirstThinFlexIndex = 0;
  205. m_pFirstWorldIndex = 0;
  206. }
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Purpose:
  210. //
  211. // ** Only execute this function if device supports stream offset **
  212. //
  213. // Input : pmesh - pointer to a studio mesh
  214. // lod - integer lod (0 is most detailed)
  215. // Output : none
  216. //-----------------------------------------------------------------------------
  217. template< class T >
  218. void CCachedRenderData::ComputeFlexedVertex_StreamOffset( studiohdr_t *pStudioHdr, mstudioflex_t *pflex,
  219. T *pvanim, int vertCount, float w1, float w2, float w3, float w4 )
  220. {
  221. float w12 = w1 - w2;
  222. float w34 = w3 - w4;
  223. float flVertAnimFixedPointScale = pStudioHdr->VertAnimFixedPointScale();
  224. CachedPosNorm_t *pFlexedVertex = NULL;
  225. for (int j = 0; j < pflex->numverts; j++)
  226. {
  227. int n = pvanim[j].index;
  228. // only flex the indices that are (still) part of this mesh at this lod
  229. if ( n >= vertCount )
  230. continue;
  231. float s = pvanim[j].speed;
  232. float b = pvanim[j].side;
  233. Vector4DAligned vPosition, vNormal;
  234. pvanim[j].GetDeltaFixed4DAligned( &vPosition, flVertAnimFixedPointScale );
  235. pvanim[j].GetNDeltaFixed4DAligned( &vNormal, flVertAnimFixedPointScale );
  236. if ( !IsThinVertexFlexed(n) )
  237. {
  238. // Add a new flexed vert to the flexed vertex list
  239. pFlexedVertex = CreateThinFlexVertex(n);
  240. Assert( pFlexedVertex != NULL);
  241. pFlexedVertex->m_Position.InitZero();
  242. pFlexedVertex->m_Normal.InitZero();
  243. }
  244. else
  245. {
  246. pFlexedVertex = GetThinFlexVertex(n);
  247. }
  248. s *= 1.0f / 255.0f;
  249. b *= 1.0f / 255.0f;
  250. float wa = w2 + w12 * s;
  251. float wb = w4 + w34 * s;
  252. float w = wa + ( wb - wa ) * b;
  253. Vector4DWeightMAD( w, vPosition, pFlexedVertex->m_Position, vNormal, pFlexedVertex->m_Normal );
  254. }
  255. }
  256. #endif // FLEXRENDERDATA_H