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.

238 lines
7.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "flexrenderdata.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. //-----------------------------------------------------------------------------
  11. // Constructor
  12. //-----------------------------------------------------------------------------
  13. CCachedRenderData::CCachedRenderData() : m_CurrentTag(0), m_pFirstFlexIndex(0),
  14. m_pFirstWorldIndex(0)
  15. {
  16. #ifdef _DEBUG
  17. int i;
  18. float val = VEC_T_NAN;
  19. for( i = 0; i < MAXSTUDIOFLEXVERTS; i++ )
  20. {
  21. m_pFlexVerts[i].m_Position[0] = val;
  22. m_pFlexVerts[i].m_Position[1] = val;
  23. m_pFlexVerts[i].m_Position[2] = val;
  24. m_pFlexVerts[i].m_Normal[0] = val;
  25. m_pFlexVerts[i].m_Normal[1] = val;
  26. m_pFlexVerts[i].m_Normal[2] = val;
  27. m_pThinFlexVerts[i].m_Position[0] = val;
  28. m_pThinFlexVerts[i].m_Position[1] = val;
  29. m_pThinFlexVerts[i].m_Position[2] = val;
  30. m_pThinFlexVerts[i].m_Normal[0] = val;
  31. m_pThinFlexVerts[i].m_Normal[1] = val;
  32. m_pThinFlexVerts[i].m_Normal[2] = val;
  33. m_pFlexVerts[i].m_TangentS[0] = val;
  34. m_pFlexVerts[i].m_TangentS[1] = val;
  35. m_pFlexVerts[i].m_TangentS[2] = val;
  36. m_pFlexVerts[i].m_TangentS[3] = val;
  37. }
  38. #endif
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Call this before rendering the model
  42. //-----------------------------------------------------------------------------
  43. void CCachedRenderData::StartModel()
  44. {
  45. ++m_CurrentTag;
  46. m_IndexCount = 0;
  47. m_FlexVertexCount = 0;
  48. m_ThinFlexVertexCount = 0;
  49. m_WorldVertexCount = 0;
  50. m_pFirstFlexIndex = 0;
  51. m_pFirstThinFlexIndex = 0;
  52. m_pFirstWorldIndex = 0;
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Used to hook ourselves into a particular body part, model, and mesh
  56. //-----------------------------------------------------------------------------
  57. void CCachedRenderData::SetBodyPart( int bodypart )
  58. {
  59. m_Body = bodypart;
  60. m_CacheDict.EnsureCount(m_Body+1);
  61. m_Model = m_Mesh = -1;
  62. m_pFirstFlexIndex = 0;
  63. m_pFirstThinFlexIndex = 0;
  64. m_pFirstWorldIndex = 0;
  65. }
  66. void CCachedRenderData::SetModel( int model )
  67. {
  68. Assert(m_Body >= 0);
  69. m_Model = model;
  70. m_CacheDict[m_Body].EnsureCount(m_Model+1);
  71. m_Mesh = -1;
  72. m_pFirstFlexIndex = 0;
  73. m_pFirstThinFlexIndex = 0;
  74. m_pFirstWorldIndex = 0;
  75. }
  76. void CCachedRenderData::SetMesh( int mesh )
  77. {
  78. Assert((m_Model >= 0) && (m_Body >= 0));
  79. m_Mesh = mesh;
  80. m_CacheDict[m_Body][m_Model].EnsureCount(m_Mesh+1);
  81. // At this point, we should have all 3 defined.
  82. CacheDict_t& dict = m_CacheDict[m_Body][m_Model][m_Mesh];
  83. if (dict.m_Tag == m_CurrentTag)
  84. {
  85. m_pFirstFlexIndex = &m_pFlexIndex[dict.m_FirstIndex];
  86. m_pFirstThinFlexIndex = &m_pThinFlexIndex[dict.m_FirstIndex];
  87. m_pFirstWorldIndex = &m_pWorldIndex[dict.m_FirstIndex];
  88. }
  89. else
  90. {
  91. m_pFirstFlexIndex = 0;
  92. m_pFirstThinFlexIndex = 0;
  93. m_pFirstWorldIndex = 0;
  94. }
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Used to set up a flex computation
  98. //-----------------------------------------------------------------------------
  99. bool CCachedRenderData::IsFlexComputationDone( ) const
  100. {
  101. Assert((m_Model >= 0) && (m_Body >= 0) && (m_Mesh >= 0));
  102. // Lets create the dictionary entry
  103. // If the tags match, that means we're doing the computation twice!!!
  104. CacheDict_t const& dict = m_CacheDict[m_Body][m_Model][m_Mesh];
  105. return (dict.m_FlexTag == m_CurrentTag);
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Used to set up a computation (modifies vertex data)
  109. //-----------------------------------------------------------------------------
  110. void CCachedRenderData::SetupComputation( mstudiomesh_t *pMesh, bool flexComputation )
  111. {
  112. Assert((m_Model >= 0) && (m_Body >= 0) && (m_Mesh >= 0));
  113. // Assert( !m_pFirstIndex );
  114. // Lets create the dictionary entry
  115. // If the tags match, that means we're doing the computation twice!!!
  116. CacheDict_t& dict = m_CacheDict[m_Body][m_Model][m_Mesh];
  117. if (dict.m_Tag != m_CurrentTag)
  118. {
  119. dict.m_FirstIndex = m_IndexCount;
  120. dict.m_IndexCount = pMesh->numvertices;
  121. dict.m_Tag = m_CurrentTag;
  122. m_IndexCount += dict.m_IndexCount;
  123. }
  124. if (flexComputation)
  125. dict.m_FlexTag = m_CurrentTag;
  126. m_pFirstFlexIndex = &m_pFlexIndex[dict.m_FirstIndex];
  127. m_pFirstThinFlexIndex = &m_pThinFlexIndex[dict.m_FirstIndex];
  128. m_pFirstWorldIndex = &m_pWorldIndex[dict.m_FirstIndex];
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Creates a new flexed vertex to be associated with a vertex
  132. //-----------------------------------------------------------------------------
  133. CachedPosNormTan_t* CCachedRenderData::CreateFlexVertex( int vertex )
  134. {
  135. Assert( m_pFirstFlexIndex );
  136. Assert( m_pFirstFlexIndex[vertex].m_Tag != m_CurrentTag );
  137. Assert ( m_FlexVertexCount < MAXSTUDIOFLEXVERTS );
  138. if ( m_FlexVertexCount >= MAXSTUDIOFLEXVERTS )
  139. return NULL;
  140. // Point the flex list to the new flexed vertex
  141. m_pFirstFlexIndex[vertex].m_Tag = m_CurrentTag;
  142. m_pFirstFlexIndex[vertex].m_VertexIndex = m_FlexVertexCount;
  143. // Add a new flexed vert to the flexed vertex list
  144. ++m_FlexVertexCount;
  145. return GetFlexVertex( vertex );
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Creates a new flexed vertex to be associated with a vertex
  149. //-----------------------------------------------------------------------------
  150. CachedPosNorm_t* CCachedRenderData::CreateThinFlexVertex( int vertex )
  151. {
  152. Assert( m_pFirstThinFlexIndex );
  153. Assert( m_pFirstThinFlexIndex[vertex].m_Tag != m_CurrentTag );
  154. Assert ( m_ThinFlexVertexCount < MAXSTUDIOFLEXVERTS );
  155. if ( m_ThinFlexVertexCount >= MAXSTUDIOFLEXVERTS )
  156. return NULL;
  157. // Point the flex list to the new flexed vertex
  158. m_pFirstThinFlexIndex[vertex].m_Tag = m_CurrentTag;
  159. m_pFirstThinFlexIndex[vertex].m_VertexIndex = m_ThinFlexVertexCount;
  160. // Add a new flexed vert to the thin flexed vertex list
  161. ++m_ThinFlexVertexCount;
  162. return GetThinFlexVertex( vertex );
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Re-normalize the surface normals and tangents of the flexed vertices
  166. // No thin ones since they're intended to be deltas, not unit vectors
  167. //-----------------------------------------------------------------------------
  168. void CCachedRenderData::RenormalizeFlexVertices( bool bHasTangentData )
  169. {
  170. int i;
  171. for (i = 0; i < m_FlexVertexCount; i++)
  172. {
  173. m_pFlexVerts[ i ].m_Normal.NormalizeInPlace();
  174. if (bHasTangentData)
  175. {
  176. m_pFlexVerts[ i ].m_TangentS.AsVector3D().NormalizeInPlace();
  177. }
  178. }
  179. }
  180. //-----------------------------------------------------------------------------
  181. // Creates a new flexed vertex to be associated with a vertex
  182. //-----------------------------------------------------------------------------
  183. CachedPosNorm_t* CCachedRenderData::CreateWorldVertex( int vertex )
  184. {
  185. Assert( m_pFirstWorldIndex );
  186. if ( m_pFirstWorldIndex[vertex].m_Tag != m_CurrentTag )
  187. {
  188. // Point the world list to the new world vertex
  189. Assert( m_WorldVertexCount < MAXSTUDIOVERTS );
  190. m_pFirstWorldIndex[vertex].m_Tag = m_CurrentTag;
  191. m_pFirstWorldIndex[vertex].m_VertexIndex = m_WorldVertexCount;
  192. // Add a new world vert to the world vertex list
  193. ++m_WorldVertexCount;
  194. }
  195. return GetWorldVertex( vertex );
  196. }