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.

389 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "studiorender.h"
  7. #include "studiorendercontext.h"
  8. #include "materialsystem/imaterialsystem.h"
  9. #include "materialsystem/imaterialsystemhardwareconfig.h"
  10. #include "materialsystem/imaterial.h"
  11. #include "materialsystem/imaterialvar.h"
  12. #include "materialsystem/imesh.h"
  13. #include "optimize.h"
  14. #include "mathlib/vmatrix.h"
  15. #include "tier0/vprof.h"
  16. #include "tier1/strtools.h"
  17. #include "tier1/KeyValues.h"
  18. #include "tier0/memalloc.h"
  19. #include "convar.h"
  20. #include "materialsystem/itexture.h"
  21. #include "tier2/tier2.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include "tier0/memdbgon.h"
  24. static ConVar r_studio_stats( "r_studio_stats", "0", FCVAR_CHEAT );
  25. inline float TriangleArea( const Vector &v0, const Vector &v1, const Vector &v2 )
  26. {
  27. Vector vecEdge0, vecEdge1, vecCross;
  28. VectorSubtract( v1, v0, vecEdge0 );
  29. VectorSubtract( v2, v0, vecEdge1 );
  30. CrossProduct( vecEdge0, vecEdge1, vecCross );
  31. return ( VectorLength( vecCross ) * 0.5f );
  32. }
  33. void CStudioRender::R_GatherStats( studiomeshgroup_t *pGroup, CMeshBuilder &MeshBuilder, IMesh *pMesh, IMaterial *pMaterial )
  34. {
  35. int nCount = 0;
  36. float flSurfaceArea = 0.0f;
  37. float flTriSurfaceArea = 0.0f;
  38. float flTextureSurfaceArea = 0.0f;
  39. int nFrontFacing = 0;
  40. CUtlVector< Vector > Positions;
  41. CUtlVector< Vector2D > TextureCoords;
  42. CUtlVector< short > Indexes;
  43. CUtlVector< float > TriAreas;
  44. CUtlVector< float > TextureAreas;
  45. int nTextureWidth = 0;
  46. int nTextureHeight = 0;
  47. IMaterialVar **pMaterialVar = pMaterial->GetShaderParams();
  48. for( int i = 0; i < pMaterial->ShaderParamCount(); i++ )
  49. {
  50. if ( pMaterialVar[ i ]->IsTexture() == false )
  51. {
  52. continue;
  53. }
  54. ITexture *pTexture = pMaterialVar[ i ]->GetTextureValue();
  55. if ( pTexture == NULL )
  56. {
  57. continue;
  58. }
  59. int nWidth = pTexture->GetActualWidth();
  60. if ( nWidth > nTextureWidth )
  61. {
  62. nTextureWidth = nWidth;
  63. }
  64. int nHeight = pTexture->GetActualHeight();
  65. if ( nHeight > nTextureHeight )
  66. {
  67. nTextureHeight = nHeight;
  68. }
  69. }
  70. Vector2D vTextureSize( nTextureWidth, nTextureHeight );
  71. VMatrix m_ViewMatrix, m_ProjectionMatrix, m_ViewProjectionMatrix;
  72. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  73. pRenderContext->GetMatrix( MATERIAL_VIEW, &m_ViewMatrix );
  74. pRenderContext->GetMatrix( MATERIAL_PROJECTION, &m_ProjectionMatrix );
  75. MatrixMultiply( m_ProjectionMatrix, m_ViewMatrix, m_ViewProjectionMatrix );
  76. Positions.EnsureCapacity( MeshBuilder.VertexCount() );
  77. Positions.SetCount( MeshBuilder.VertexCount() );
  78. TextureCoords.EnsureCapacity( MeshBuilder.VertexCount() );
  79. TextureCoords.SetCount( MeshBuilder.VertexCount() );
  80. for( int i = 0; i < MeshBuilder.VertexCount(); i++ )
  81. {
  82. MeshBuilder.SelectVertex( i );
  83. Positions[ i ] = *( const Vector * )MeshBuilder.Position();
  84. TextureCoords[ i ] = ( *( const Vector2D * )MeshBuilder.TexCoord( 0 ) ) * vTextureSize;
  85. }
  86. int nNumIndexes = 0;
  87. for (int j = 0; j < pGroup->m_NumStrips; ++j)
  88. {
  89. OptimizedModel::StripHeader_t *pStrip = &pGroup->m_pStripData[ j ];
  90. nNumIndexes += pStrip->numIndices;
  91. }
  92. Indexes.EnsureCapacity( nNumIndexes );
  93. Indexes.SetCount( nNumIndexes );
  94. TriAreas.EnsureCapacity( nNumIndexes / 3 );
  95. TriAreas.SetCount( nNumIndexes / 3 );
  96. TextureAreas.EnsureCapacity( nNumIndexes / 3 );
  97. TextureAreas.SetCount( nNumIndexes / 3 );
  98. for (int j = 0; j < pGroup->m_NumStrips; ++j)
  99. {
  100. OptimizedModel::StripHeader_t *pStrip = &pGroup->m_pStripData[ j ];
  101. for( int i = 0; i < pStrip->numIndices; i += 3 )
  102. {
  103. Indexes[ pStrip->indexOffset + i ] = pGroup->m_pIndices[ pStrip->indexOffset + i ];
  104. Indexes[ pStrip->indexOffset + i + 1 ] = pGroup->m_pIndices[ pStrip->indexOffset + i + 1 ];
  105. Indexes[ pStrip->indexOffset + i + 2 ] = pGroup->m_pIndices[ pStrip->indexOffset + i + 2 ];
  106. TriAreas[ ( pStrip->indexOffset + i ) / 3 ] = 0.0f;
  107. TextureAreas[ ( pStrip->indexOffset + i ) / 3 ] = 0.0f;
  108. }
  109. }
  110. const float UNIFORM_SCREEN_WIDTH = 1600.0f;
  111. const float UNIFORM_SCREEN_HEIGHT = 1200.0f;
  112. for (int j = 0; j < pGroup->m_NumStrips; ++j)
  113. {
  114. OptimizedModel::StripHeader_t *pStrip = &pGroup->m_pStripData[ j ];
  115. for( int i = 0; i < pStrip->numIndices; i += 3 )
  116. {
  117. int nIndex1 = pGroup->m_pIndices[ pStrip->indexOffset + i ];
  118. int nIndex2 = pGroup->m_pIndices[ pStrip->indexOffset + i + 1 ];
  119. int nIndex3 = pGroup->m_pIndices[ pStrip->indexOffset + i + 2 ];
  120. MeshBuilder.SelectVertex( nIndex1 );
  121. const float *pPos1 = MeshBuilder.Position();
  122. MeshBuilder.SelectVertex( nIndex2 );
  123. const float *pPos2 = MeshBuilder.Position();
  124. MeshBuilder.SelectVertex( nIndex3 );
  125. const float *pPos3 = MeshBuilder.Position();
  126. float flTriArea = TriangleArea( *( const Vector * )( pPos1 ), *( const Vector * )( pPos2 ), *( const Vector * )( pPos3 ) );
  127. flSurfaceArea += flTriArea;
  128. Vector V1View, V2View, V3View;
  129. m_ViewProjectionMatrix.V3Mul( *( const Vector * )( pPos1 ), V1View );
  130. m_ViewProjectionMatrix.V3Mul( *( const Vector * )( pPos2 ), V2View );
  131. m_ViewProjectionMatrix.V3Mul( *( const Vector * )( pPos3 ), V3View );
  132. Vector vNormal;
  133. float flIntercept;
  134. ComputeTrianglePlane( V1View, V2View, V3View, vNormal, flIntercept );
  135. V1View = ( V1View * 0.5f ) + Vector( 0.5f, 0.5f, 0.5f );
  136. V1View *= Vector( UNIFORM_SCREEN_WIDTH, UNIFORM_SCREEN_HEIGHT, 1.0f );
  137. V2View = ( V2View * 0.5f ) + Vector( 0.5f, 0.5f, 0.5f );
  138. V2View *= Vector( UNIFORM_SCREEN_WIDTH, UNIFORM_SCREEN_HEIGHT, 1.0f );
  139. V3View = ( V3View * 0.5f ) + Vector( 0.5f, 0.5f, 0.5f );
  140. V3View *= Vector( UNIFORM_SCREEN_WIDTH, UNIFORM_SCREEN_HEIGHT, 1.0f );
  141. flTriArea = -TriArea2D( V1View, V2View, V3View );
  142. if ( flTriArea > 0.0f )
  143. {
  144. nFrontFacing++;
  145. flTriSurfaceArea += flTriArea;
  146. TriAreas[ ( pStrip->indexOffset + i ) / 3 ] = flTriArea;
  147. Vector2D TexV1 = TextureCoords[ nIndex1 ];
  148. Vector2D TexV2 = TextureCoords[ nIndex2 ];
  149. Vector2D TexV3 = TextureCoords[ nIndex3 ];
  150. flTriArea = fabs( TriArea2D( TexV1, TexV2, TexV3 ) );
  151. flTextureSurfaceArea += flTriArea;
  152. TextureAreas[ ( pStrip->indexOffset + i ) / 3 ] = flTriArea;
  153. }
  154. }
  155. nCount += pStrip->numIndices;
  156. }
  157. // Msg( "%d / %d / %g / %g ||| %d / %g\n", MeshBuilder.VertexCount(), nCount, flSurfaceArea, flTriSurfaceArea, nFrontFacing, flTriSurfaceArea / (float)nFrontFacing );
  158. for( int i = 0; i < MeshBuilder.VertexCount(); i++ )
  159. {
  160. MeshBuilder.SelectVertex( i );
  161. MeshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  162. }
  163. MeshBuilder.End();
  164. pMesh->MarkAsDrawn();
  165. pMaterial = materials->FindMaterial( "debug/modelstats", TEXTURE_GROUP_OTHER );
  166. pRenderContext->Bind( pMaterial );
  167. int nRenderCount = -1;
  168. for (int j = 0; j < pGroup->m_NumStrips; ++j)
  169. {
  170. OptimizedModel::StripHeader_t *pStrip = &pGroup->m_pStripData[ j ];
  171. for( int i = 0; i < pStrip->numIndices; i += 3 )
  172. {
  173. if ( nRenderCount >= 10000 || nRenderCount == -1 )
  174. {
  175. if ( nRenderCount >= 0 )
  176. {
  177. MeshBuilder.End( false, true );
  178. }
  179. pMesh = pRenderContext->GetDynamicMeshEx( false );
  180. nRenderCount = 0;
  181. if ( nFrontFacing > 10000 )
  182. {
  183. MeshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 10000 );
  184. nFrontFacing -= 10000;
  185. }
  186. else
  187. {
  188. MeshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nFrontFacing );
  189. }
  190. }
  191. int nIndex1 = Indexes[ pStrip->indexOffset + i ];
  192. int nIndex2 = Indexes[ pStrip->indexOffset + i + 1 ];
  193. int nIndex3 = Indexes[ pStrip->indexOffset + i + 2 ];
  194. float flArea = TriAreas[ ( pStrip->indexOffset + i ) / 3 ];
  195. if ( flArea > 0.0f )
  196. {
  197. Vector vColor;
  198. if ( r_studio_stats.GetInt() == 1 )
  199. {
  200. if ( flArea < 20.0f )
  201. {
  202. vColor.Init( 1.0f, 0.0f, 0.0f );
  203. }
  204. else if ( flArea < 50.0f )
  205. {
  206. vColor.Init( 1.0f, 0.565f, 0.0f );
  207. }
  208. else if ( flArea < 100.0f )
  209. {
  210. vColor.Init( 1.0f, 0.871f, 0.0f );
  211. }
  212. else if ( flArea < 200.0f )
  213. {
  214. vColor.Init( 0.701f, 1.0f, 0.0f );
  215. }
  216. else
  217. {
  218. vColor.Init( 0.0f, 1.0f, 0.0f );
  219. }
  220. }
  221. else
  222. {
  223. float flArea = TextureAreas[ ( pStrip->indexOffset + i ) / 3 ] / TriAreas[ ( pStrip->indexOffset + i ) / 3 ];
  224. if ( flArea >= 16.0f )
  225. {
  226. vColor.Init( 1.0f, 0.0f, 0.0f );
  227. }
  228. else if ( flArea >= 8.0f )
  229. {
  230. vColor.Init( 1.0f, 0.565f, 0.0f );
  231. }
  232. else if ( flArea >= 4.0f )
  233. {
  234. vColor.Init( 1.0f, 0.871f, 0.0f );
  235. }
  236. else if ( flArea >= 2.0f )
  237. {
  238. vColor.Init( 0.701f, 1.0f, 0.0f );
  239. }
  240. else if ( flArea >= 1.0f )
  241. {
  242. vColor.Init( 0.0f, 1.0f, 0.0f );
  243. }
  244. else
  245. {
  246. vColor.Init( 0.0f, 0.871f, 1.0f );
  247. }
  248. }
  249. MeshBuilder.Position3fv( Positions[ nIndex1 ].Base() );
  250. MeshBuilder.Color3fv( vColor.Base() );
  251. MeshBuilder.AdvanceVertex();
  252. MeshBuilder.Position3fv( Positions[ nIndex2 ].Base() );
  253. MeshBuilder.Color3fv( vColor.Base() );
  254. MeshBuilder.AdvanceVertex();
  255. MeshBuilder.Position3fv( Positions[ nIndex3 ].Base() );
  256. MeshBuilder.Color3fv( vColor.Base() );
  257. MeshBuilder.AdvanceVertex();
  258. nRenderCount++;
  259. }
  260. }
  261. }
  262. if ( nRenderCount >= 0 )
  263. {
  264. MeshBuilder.End( false, true );
  265. }
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Main model rendering entry point
  269. //-----------------------------------------------------------------------------
  270. void CStudioRender::ModelStats( const DrawModelInfo_t& info, const StudioRenderContext_t &rc,
  271. matrix3x4_t *pBoneToWorld, const FlexWeights_t &flex, int flags )
  272. {
  273. StudioRenderContext_t StatsRC = rc;
  274. StatsRC.m_Config.m_bStatsMode = true;
  275. m_pRC = const_cast< StudioRenderContext_t* >( &StatsRC );
  276. m_pFlexWeights = flex.m_pFlexWeights;
  277. m_pFlexDelayedWeights = flex.m_pFlexDelayedWeights;
  278. m_pBoneToWorld = pBoneToWorld;
  279. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  280. // Disable flex if we're told to...
  281. bool flexConfig = m_pRC->m_Config.bFlex;
  282. if (flags & STUDIORENDER_DRAW_NO_FLEXES)
  283. {
  284. m_pRC->m_Config.bFlex = false;
  285. }
  286. // Enable wireframe if we're told to...
  287. bool bWireframe = m_pRC->m_Config.bWireframe;
  288. if ( flags & STUDIORENDER_DRAW_WIREFRAME )
  289. {
  290. m_pRC->m_Config.bWireframe = true;
  291. }
  292. int boneMask = BONE_USED_BY_VERTEX_AT_LOD( info.m_Lod );
  293. // Preserve the matrices if we're skinning
  294. pRenderContext->MatrixMode( MATERIAL_MODEL );
  295. pRenderContext->PushMatrix();
  296. pRenderContext->LoadIdentity();
  297. m_VertexCache.StartModel();
  298. m_pStudioHdr = info.m_pStudioHdr;
  299. m_pStudioMeshes = info.m_pHardwareData->m_pLODs[info.m_Lod].m_pMeshData;
  300. // Bone to world must be set before calling drawmodel; it uses that here
  301. ComputePoseToWorld( m_PoseToWorld, m_pStudioHdr, boneMask, m_pRC->m_ViewOrigin, pBoneToWorld );
  302. R_StudioRenderModel( pRenderContext, info.m_Skin, info.m_Body, info.m_HitboxSet, info.m_pClientEntity,
  303. info.m_pHardwareData->m_pLODs[info.m_Lod].ppMaterials,
  304. info.m_pHardwareData->m_pLODs[info.m_Lod].pMaterialFlags, flags, boneMask, info.m_Lod, info.m_pColorMeshes);
  305. // Restore the matrices if we're skinning
  306. pRenderContext->MatrixMode( MATERIAL_MODEL );
  307. pRenderContext->PopMatrix();
  308. // Restore the configs
  309. m_pRC->m_Config.bFlex = flexConfig;
  310. m_pRC->m_Config.bWireframe = bWireframe;
  311. #ifdef REPORT_FLEX_STATS
  312. GetFlexStats();
  313. #endif
  314. StatsRC.m_Config.m_bStatsMode = false;
  315. pRenderContext->SetNumBoneWeights( 0 );
  316. m_pRC = NULL;
  317. m_pBoneToWorld = NULL;
  318. m_pFlexWeights = NULL;
  319. m_pFlexDelayedWeights = NULL;
  320. }