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.

916 lines
28 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: A set of utilities to render standard shapes
  4. //
  5. //===========================================================================//
  6. #include "tier2/renderutils.h"
  7. #include "tier2/tier2.h"
  8. #include "tier1/KeyValues.h"
  9. #include "materialsystem/imaterialsystem.h"
  10. #include "materialsystem/imesh.h"
  11. #include "materialsystem/imaterial.h"
  12. #include "tier0/vprof.h"
  13. #include "tier0/basetypes.h"
  14. #include "togl/rendermechanism.h"
  15. #if !defined(M_PI)
  16. #define M_PI 3.14159265358979323846
  17. #endif
  18. //-----------------------------------------------------------------------------
  19. // Globals
  20. //-----------------------------------------------------------------------------
  21. static bool s_bMaterialsInitialized = false;
  22. static IMaterial *s_pWireframe;
  23. static IMaterial *s_pWireframeIgnoreZ;
  24. static IMaterial *s_pVertexColor;
  25. static IMaterial *s_pVertexColorIgnoreZ;
  26. //-----------------------------------------------------------------------------
  27. // Initializes standard materials
  28. //-----------------------------------------------------------------------------
  29. void InitializeStandardMaterials()
  30. {
  31. if ( s_bMaterialsInitialized )
  32. return;
  33. s_bMaterialsInitialized = true;
  34. KeyValues *pVMTKeyValues = new KeyValues( "wireframe" );
  35. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  36. s_pWireframe = g_pMaterialSystem->CreateMaterial( "__utilWireframe", pVMTKeyValues );
  37. pVMTKeyValues = new KeyValues( "wireframe" );
  38. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  39. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  40. pVMTKeyValues->SetInt( "$ignorez", 1 );
  41. s_pWireframeIgnoreZ = g_pMaterialSystem->CreateMaterial( "__utilWireframeIgnoreZ", pVMTKeyValues );
  42. pVMTKeyValues = new KeyValues( "unlitgeneric" );
  43. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  44. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  45. s_pVertexColor = g_pMaterialSystem->CreateMaterial( "__utilVertexColor", pVMTKeyValues );
  46. pVMTKeyValues = new KeyValues( "unlitgeneric" );
  47. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  48. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  49. pVMTKeyValues->SetInt( "$ignorez", 1 );
  50. s_pVertexColorIgnoreZ = g_pMaterialSystem->CreateMaterial( "__utilVertexColorIgnoreZ", pVMTKeyValues );
  51. }
  52. void ShutdownStandardMaterials()
  53. {
  54. if ( !s_bMaterialsInitialized )
  55. return;
  56. s_bMaterialsInitialized = false;
  57. s_pWireframe->DecrementReferenceCount();
  58. s_pWireframe = NULL;
  59. s_pWireframeIgnoreZ->DecrementReferenceCount();
  60. s_pWireframeIgnoreZ = NULL;
  61. s_pVertexColor->DecrementReferenceCount();
  62. s_pVertexColor = NULL;
  63. s_pVertexColorIgnoreZ->DecrementReferenceCount();
  64. s_pVertexColorIgnoreZ = NULL;
  65. }
  66. //-----------------------------------------------------------------------------
  67. // Renders a wireframe sphere
  68. //-----------------------------------------------------------------------------
  69. void RenderWireframeSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer )
  70. {
  71. InitializeStandardMaterials();
  72. // Make one more coordinate because (u,v) is discontinuous.
  73. ++nTheta;
  74. int nVertices = nPhi * nTheta;
  75. int nIndices = ( nTheta - 1 ) * 4 * ( nPhi - 1 );
  76. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  77. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  78. CMeshBuilder meshBuilder;
  79. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  80. meshBuilder.Begin( pMesh, MATERIAL_LINES, nVertices, nIndices );
  81. unsigned char chRed = c.r();
  82. unsigned char chGreen = c.g();
  83. unsigned char chBlue = c.b();
  84. unsigned char chAlpha = c.a();
  85. int i, j;
  86. for ( i = 0; i < nPhi; ++i )
  87. {
  88. for ( j = 0; j < nTheta; ++j )
  89. {
  90. float u = j / ( float )( nTheta - 1 );
  91. float v = i / ( float )( nPhi - 1 );
  92. float theta = 2.0f * M_PI * u;
  93. float phi = M_PI * v;
  94. meshBuilder.Position3f( vCenter.x + ( flRadius * sin(phi) * cos(theta) ),
  95. vCenter.y + ( flRadius * sin(phi) * sin(theta) ),
  96. vCenter.z + ( flRadius * cos(phi) ) );
  97. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  98. meshBuilder.AdvanceVertex();
  99. }
  100. }
  101. for ( i = 0; i < nPhi - 1; ++i )
  102. {
  103. for ( j = 0; j < nTheta - 1; ++j )
  104. {
  105. int idx = nTheta * i + j;
  106. meshBuilder.Index( idx );
  107. meshBuilder.AdvanceIndex();
  108. meshBuilder.Index( idx + nTheta );
  109. meshBuilder.AdvanceIndex();
  110. meshBuilder.Index( idx );
  111. meshBuilder.AdvanceIndex();
  112. meshBuilder.Index( idx + 1 );
  113. meshBuilder.AdvanceIndex();
  114. }
  115. }
  116. meshBuilder.End();
  117. pMesh->Draw();
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Draws a sphere
  121. //-----------------------------------------------------------------------------
  122. void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, IMaterial *pMaterial )
  123. {
  124. InitializeStandardMaterials();
  125. CMatRenderContextPtr pRenderContext( materials );
  126. unsigned char chRed = c.r();
  127. unsigned char chGreen = c.g();
  128. unsigned char chBlue = c.b();
  129. unsigned char chAlpha = c.a();
  130. // Two extra degenerate triangles per row (except the last one)
  131. int nTriangles = 2 * nTheta * ( nPhi - 1 );
  132. int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
  133. if ( nTriangles == 0 )
  134. return;
  135. pRenderContext->Bind( pMaterial );
  136. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  137. CMeshBuilder meshBuilder;
  138. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nTriangles, nIndices );
  139. // Build the index buffer.
  140. float flOONPhi = 1.0f / (nPhi-1);
  141. float flOONTheta = 1.0f / (nTheta-1);
  142. int i, j;
  143. for ( i = 0; i < nPhi; ++i )
  144. {
  145. for ( j = 0; j < nTheta; ++j )
  146. {
  147. float u = j / ( float )( nTheta - 1 );
  148. float v = i / ( float )( nPhi - 1 );
  149. float theta = 2.0f * M_PI * u;
  150. float phi = M_PI * v;
  151. Vector vecPos;
  152. vecPos.x = flRadius * sin(phi) * cos(theta);
  153. vecPos.y = flRadius * sin(phi) * sin(theta);
  154. vecPos.z = flRadius * cos(phi);
  155. Vector vecNormal = vecPos;
  156. VectorNormalize(vecNormal);
  157. vecPos += vCenter;
  158. meshBuilder.Position3f( vecPos.x, vecPos.y, vecPos.z );
  159. meshBuilder.Normal3f( vecNormal.x, vecNormal.y, vecNormal.z );
  160. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  161. meshBuilder.TexCoord2f( 0, j * flOONTheta, i * flOONPhi );
  162. meshBuilder.AdvanceVertex();
  163. }
  164. }
  165. // Emit the triangle strips.
  166. int idx = 0;
  167. for ( i = 0; i < nPhi - 1; ++i )
  168. {
  169. for ( j = 0; j < nTheta; ++j )
  170. {
  171. idx = nTheta * i + j;
  172. meshBuilder.Index( idx + nTheta );
  173. meshBuilder.AdvanceIndex();
  174. meshBuilder.Index( idx );
  175. meshBuilder.AdvanceIndex();
  176. }
  177. // Emit a degenerate triangle to skip to the next row without a connecting triangle
  178. if ( i < nPhi - 2 )
  179. {
  180. meshBuilder.Index( idx );
  181. meshBuilder.AdvanceIndex();
  182. meshBuilder.Index( idx + nTheta + 1 );
  183. meshBuilder.AdvanceIndex();
  184. }
  185. }
  186. meshBuilder.End();
  187. pMesh->Draw();
  188. }
  189. void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer )
  190. {
  191. IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
  192. Color cActual( c.r(), c.g(), c.b(), c.a() );
  193. RenderSphere( vCenter, flRadius, nTheta, nPhi, cActual, pMaterial );
  194. }
  195. //-----------------------------------------------------------------------------
  196. // Box vertices
  197. //-----------------------------------------------------------------------------
  198. static int s_pBoxFaceIndices[6][4] =
  199. {
  200. { 0, 4, 6, 2 }, // -x
  201. { 5, 1, 3, 7 }, // +x
  202. { 0, 1, 5, 4 }, // -y
  203. { 2, 6, 7, 3 }, // +y
  204. { 0, 2, 3, 1 }, // -z
  205. { 4, 5, 7, 6 } // +z
  206. };
  207. static int s_pBoxFaceIndicesInsideOut[6][4] =
  208. {
  209. { 0, 2, 6, 4 }, // -x
  210. { 5, 7, 3, 1 }, // +x
  211. { 0, 4, 5, 1 }, // -y
  212. { 2, 3, 7, 6 }, // +y
  213. { 0, 1, 3, 2 }, // -z
  214. { 4, 6, 7, 5 } // +z
  215. };
  216. static void GenerateBoxVertices( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Vector pVerts[8] )
  217. {
  218. // Build a rotation matrix from orientation
  219. matrix3x4_t fRotateMatrix;
  220. AngleMatrix( angles, fRotateMatrix );
  221. Vector vecPos;
  222. for ( int i = 0; i < 8; ++i )
  223. {
  224. vecPos[0] = ( i & 0x1 ) ? vMaxs[0] : vMins[0];
  225. vecPos[1] = ( i & 0x2 ) ? vMaxs[1] : vMins[1];
  226. vecPos[2] = ( i & 0x4 ) ? vMaxs[2] : vMins[2];
  227. VectorRotate( vecPos, fRotateMatrix, pVerts[i] );
  228. pVerts[i] += vOrigin;
  229. }
  230. }
  231. //-----------------------------------------------------------------------------
  232. // Renders a wireframe box relative to an origin
  233. //-----------------------------------------------------------------------------
  234. void RenderWireframeBox( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer )
  235. {
  236. InitializeStandardMaterials();
  237. CMatRenderContextPtr pRenderContext( materials );
  238. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  239. Vector p[8];
  240. GenerateBoxVertices( vOrigin, angles, vMins, vMaxs, p );
  241. unsigned char chRed = c.r();
  242. unsigned char chGreen = c.g();
  243. unsigned char chBlue = c.b();
  244. unsigned char chAlpha = c.a();
  245. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  246. CMeshBuilder meshBuilder;
  247. meshBuilder.Begin( pMesh, MATERIAL_LINES, 24 );
  248. // Draw the box
  249. for ( int i = 0; i < 6; i++ )
  250. {
  251. int *pFaceIndex = s_pBoxFaceIndices[i];
  252. for ( int j = 0; j < 4; ++j )
  253. {
  254. meshBuilder.Position3fv( p[pFaceIndex[j]].Base() );
  255. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  256. meshBuilder.AdvanceVertex();
  257. meshBuilder.Position3fv( p[pFaceIndex[ (j == 3) ? 0 : j+1 ] ].Base() );
  258. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  259. meshBuilder.AdvanceVertex();
  260. }
  261. }
  262. meshBuilder.End();
  263. pMesh->Draw();
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Renders a solid box
  267. //-----------------------------------------------------------------------------
  268. void RenderBox( const Vector& vOrigin, const QAngle& angles, const Vector& vMins, const Vector& vMaxs, Color c, IMaterial *pMaterial, bool bInsideOut )
  269. {
  270. InitializeStandardMaterials();
  271. CMatRenderContextPtr pRenderContext( materials );
  272. pRenderContext->Bind( pMaterial );
  273. Vector p[8];
  274. GenerateBoxVertices( vOrigin, angles, vMins, vMaxs, p );
  275. unsigned char chRed = c.r();
  276. unsigned char chGreen = c.g();
  277. unsigned char chBlue = c.b();
  278. unsigned char chAlpha = c.a();
  279. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  280. CMeshBuilder meshBuilder;
  281. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 12 );
  282. // Draw the box
  283. Vector vecNormal;
  284. for ( int i = 0; i < 6; i++ )
  285. {
  286. vecNormal.Init();
  287. vecNormal[ i/2 ] = ( i & 0x1 ) ? 1.0f : -1.0f;
  288. int *ppFaceIndices = bInsideOut ? s_pBoxFaceIndicesInsideOut[i] : s_pBoxFaceIndices[i];
  289. for ( int j = 1; j < 3; ++j )
  290. {
  291. int i0 = ppFaceIndices[0];
  292. int i1 = ppFaceIndices[j];
  293. int i2 = ppFaceIndices[j+1];
  294. meshBuilder.Position3fv( p[i0].Base() );
  295. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  296. meshBuilder.Normal3fv( vecNormal.Base() );
  297. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  298. meshBuilder.AdvanceVertex();
  299. meshBuilder.Position3fv( p[i2].Base() );
  300. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  301. meshBuilder.Normal3fv( vecNormal.Base() );
  302. meshBuilder.TexCoord2f( 0, 1.0f, ( j == 1 ) ? 1.0f : 0.0f );
  303. meshBuilder.AdvanceVertex();
  304. meshBuilder.Position3fv( p[i1].Base() );
  305. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  306. meshBuilder.Normal3fv( vecNormal.Base() );
  307. meshBuilder.TexCoord2f( 0, ( j == 1 ) ? 0.0f : 1.0f, 1.0f );
  308. meshBuilder.AdvanceVertex();
  309. }
  310. }
  311. meshBuilder.End();
  312. pMesh->Draw();
  313. }
  314. void RenderBox( const Vector& vOrigin, const QAngle& angles, const Vector& vMins, const Vector& vMaxs, Color c, bool bZBuffer, bool bInsideOut )
  315. {
  316. IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
  317. Color cActual( c.r(), c.g(), c.b(), c.a() );
  318. RenderBox( vOrigin, angles, vMins, vMaxs, cActual, pMaterial, bInsideOut );
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Renders axes, red->x, green->y, blue->z
  322. //-----------------------------------------------------------------------------
  323. void RenderAxes( const Vector &vOrigin, float flScale, bool bZBuffer )
  324. {
  325. InitializeStandardMaterials();
  326. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  327. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  328. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  329. CMeshBuilder meshBuilder;
  330. meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
  331. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  332. meshBuilder.Color4ub( 255, 0, 0, 255 );
  333. meshBuilder.AdvanceVertex();
  334. meshBuilder.Position3f( vOrigin.x + flScale, vOrigin.y, vOrigin.z );
  335. meshBuilder.Color4ub( 255, 0, 0, 255 );
  336. meshBuilder.AdvanceVertex();
  337. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  338. meshBuilder.Color4ub( 0, 255, 0, 255 );
  339. meshBuilder.AdvanceVertex();
  340. meshBuilder.Position3f( vOrigin.x, vOrigin.y + flScale, vOrigin.z );
  341. meshBuilder.Color4ub( 0, 255, 0, 255 );
  342. meshBuilder.AdvanceVertex();
  343. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  344. meshBuilder.Color4ub( 0, 0, 255, 255 );
  345. meshBuilder.AdvanceVertex();
  346. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z + flScale );
  347. meshBuilder.Color4ub( 0, 0, 255, 255 );
  348. meshBuilder.AdvanceVertex();
  349. meshBuilder.End();
  350. pMesh->Draw();
  351. }
  352. void RenderAxes( const matrix3x4_t &transform, float flScale, bool bZBuffer )
  353. {
  354. InitializeStandardMaterials();
  355. Vector xAxis, yAxis, zAxis, vOrigin, temp;
  356. MatrixGetColumn( transform, 0, xAxis );
  357. MatrixGetColumn( transform, 1, yAxis );
  358. MatrixGetColumn( transform, 2, zAxis );
  359. MatrixGetColumn( transform, 3, vOrigin );
  360. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  361. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  362. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  363. CMeshBuilder meshBuilder;
  364. meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
  365. meshBuilder.Position3fv( vOrigin.Base() );
  366. meshBuilder.Color4ub( 255, 0, 0, 255 );
  367. meshBuilder.AdvanceVertex();
  368. VectorMA( vOrigin, flScale, xAxis, temp );
  369. meshBuilder.Position3fv( temp.Base() );
  370. meshBuilder.Color4ub( 255, 0, 0, 255 );
  371. meshBuilder.AdvanceVertex();
  372. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  373. meshBuilder.Color4ub( 0, 255, 0, 255 );
  374. meshBuilder.AdvanceVertex();
  375. VectorMA( vOrigin, flScale, yAxis, temp );
  376. meshBuilder.Position3fv( temp.Base() );
  377. meshBuilder.Color4ub( 0, 255, 0, 255 );
  378. meshBuilder.AdvanceVertex();
  379. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  380. meshBuilder.Color4ub( 0, 0, 255, 255 );
  381. meshBuilder.AdvanceVertex();
  382. VectorMA( vOrigin, flScale, zAxis, temp );
  383. meshBuilder.Position3fv( temp.Base() );
  384. meshBuilder.Color4ub( 0, 0, 255, 255 );
  385. meshBuilder.AdvanceVertex();
  386. meshBuilder.End();
  387. pMesh->Draw();
  388. }
  389. //-----------------------------------------------------------------------------
  390. // Render a line
  391. //-----------------------------------------------------------------------------
  392. void RenderLine( const Vector& v1, const Vector& v2, Color c, bool bZBuffer )
  393. {
  394. InitializeStandardMaterials();
  395. CMatRenderContextPtr pRenderContext( materials );
  396. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  397. unsigned char chRed = c.r();
  398. unsigned char chGreen = c.g();
  399. unsigned char chBlue = c.b();
  400. unsigned char chAlpha = c.a();
  401. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  402. CMeshBuilder meshBuilder;
  403. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  404. meshBuilder.Position3fv( v1.Base() );
  405. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  406. meshBuilder.AdvanceVertex();
  407. meshBuilder.Position3fv( v2.Base() );
  408. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  409. meshBuilder.AdvanceVertex();
  410. meshBuilder.End();
  411. pMesh->Draw();
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Draws a triangle
  415. //-----------------------------------------------------------------------------
  416. void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, IMaterial *pMaterial )
  417. {
  418. InitializeStandardMaterials();
  419. CMatRenderContextPtr pRenderContext( materials );
  420. pRenderContext->Bind( pMaterial );
  421. unsigned char chRed = c.r();
  422. unsigned char chGreen = c.g();
  423. unsigned char chBlue = c.b();
  424. unsigned char chAlpha = c.a();
  425. Vector vecNormal;
  426. Vector vecDelta1, vecDelta2;
  427. VectorSubtract( p2, p1, vecDelta1 );
  428. VectorSubtract( p3, p1, vecDelta2 );
  429. CrossProduct( vecDelta1, vecDelta2, vecNormal );
  430. VectorNormalize( vecNormal );
  431. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  432. CMeshBuilder meshBuilder;
  433. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 1 );
  434. meshBuilder.Position3fv( p1.Base() );
  435. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  436. meshBuilder.Normal3fv( vecNormal.Base() );
  437. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  438. meshBuilder.AdvanceVertex();
  439. meshBuilder.Position3fv( p2.Base() );
  440. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  441. meshBuilder.Normal3fv( vecNormal.Base() );
  442. meshBuilder.TexCoord2f( 0, 0.0f, 1.0f );
  443. meshBuilder.AdvanceVertex();
  444. meshBuilder.Position3fv( p3.Base() );
  445. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  446. meshBuilder.Normal3fv( vecNormal.Base() );
  447. meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
  448. meshBuilder.AdvanceVertex();
  449. meshBuilder.End();
  450. pMesh->Draw();
  451. }
  452. void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, bool bZBuffer )
  453. {
  454. IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
  455. Color cActual( c.r(), c.g(), c.b(), c.a() );
  456. RenderTriangle( p1, p2, p3, cActual, pMaterial );
  457. }
  458. //-----------------------------------------------------------------------------
  459. // Renders an extruded box
  460. //-----------------------------------------------------------------------------
  461. static void DrawAxes( const Vector& origin, Vector* pts, int idx, Color c, CMeshBuilder& meshBuilder )
  462. {
  463. Vector start, temp;
  464. VectorAdd( pts[idx], origin, start );
  465. meshBuilder.Position3fv( start.Base() );
  466. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  467. meshBuilder.AdvanceVertex();
  468. int endidx = (idx & 0x1) ? idx - 1 : idx + 1;
  469. VectorAdd( pts[endidx], origin, temp );
  470. meshBuilder.Position3fv( temp.Base() );
  471. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  472. meshBuilder.AdvanceVertex();
  473. meshBuilder.Position3fv( start.Base() );
  474. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  475. meshBuilder.AdvanceVertex();
  476. endidx = (idx & 0x2) ? idx - 2 : idx + 2;
  477. VectorAdd( pts[endidx], origin, temp );
  478. meshBuilder.Position3fv( temp.Base() );
  479. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  480. meshBuilder.AdvanceVertex();
  481. meshBuilder.Position3fv( start.Base() );
  482. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  483. meshBuilder.AdvanceVertex();
  484. endidx = (idx & 0x4) ? idx - 4 : idx + 4;
  485. VectorAdd( pts[endidx], origin, temp );
  486. meshBuilder.Position3fv( temp.Base() );
  487. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  488. meshBuilder.AdvanceVertex();
  489. }
  490. static void DrawExtrusionFace( const Vector& start, const Vector& end,
  491. Vector* pts, int idx1, int idx2, Color c, CMeshBuilder& meshBuilder )
  492. {
  493. Vector temp;
  494. VectorAdd( pts[idx1], start, temp );
  495. meshBuilder.Position3fv( temp.Base() );
  496. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  497. meshBuilder.AdvanceVertex();
  498. VectorAdd( pts[idx2], start, temp );
  499. meshBuilder.Position3fv( temp.Base() );
  500. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  501. meshBuilder.AdvanceVertex();
  502. meshBuilder.Position3fv( temp.Base() );
  503. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  504. meshBuilder.AdvanceVertex();
  505. VectorAdd( pts[idx2], end, temp );
  506. meshBuilder.Position3fv( temp.Base() );
  507. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  508. meshBuilder.AdvanceVertex();
  509. meshBuilder.Position3fv( temp.Base() );
  510. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  511. meshBuilder.AdvanceVertex();
  512. VectorAdd( pts[idx1], end, temp );
  513. meshBuilder.Position3fv( temp.Base() );
  514. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  515. meshBuilder.AdvanceVertex();
  516. meshBuilder.Position3fv( temp.Base() );
  517. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  518. meshBuilder.AdvanceVertex();
  519. VectorAdd( pts[idx1], start, temp );
  520. meshBuilder.Position3fv( temp.Base() );
  521. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  522. meshBuilder.AdvanceVertex();
  523. }
  524. void RenderWireframeSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer )
  525. {
  526. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  527. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  528. Color cActual( c.r(), c.g(), c.b(), c.a() );
  529. // Build a rotation matrix from angles
  530. matrix3x4_t fRotateMatrix;
  531. AngleMatrix( angles, fRotateMatrix );
  532. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  533. CMeshBuilder meshBuilder;
  534. meshBuilder.Begin( pMesh, MATERIAL_LINES, 30 );
  535. Vector vDelta;
  536. VectorSubtract( vEnd, vStart, vDelta );
  537. // Compute the box points, rotated but without the origin added
  538. Vector temp;
  539. Vector pts[8];
  540. float dot[8];
  541. int minidx = 0;
  542. for ( int i = 0; i < 8; ++i )
  543. {
  544. temp.x = (i & 0x1) ? vMaxs[0] : vMins[0];
  545. temp.y = (i & 0x2) ? vMaxs[1] : vMins[1];
  546. temp.z = (i & 0x4) ? vMaxs[2] : vMins[2];
  547. // Rotate the corner point
  548. VectorRotate( temp, fRotateMatrix, pts[i] );
  549. // Find the dot product with dir
  550. dot[i] = DotProduct( pts[i], vDelta );
  551. if ( dot[i] < dot[minidx] )
  552. {
  553. minidx = i;
  554. }
  555. }
  556. // Choose opposite corner
  557. int maxidx = minidx ^ 0x7;
  558. // Draw the start + end axes...
  559. DrawAxes( vStart, pts, minidx, cActual, meshBuilder );
  560. DrawAxes( vEnd, pts, maxidx, cActual, meshBuilder );
  561. // Draw the extrusion faces
  562. for (int j = 0; j < 3; ++j )
  563. {
  564. int dirflag1 = ( 1 << ((j+1)%3) );
  565. int dirflag2 = ( 1 << ((j+2)%3) );
  566. int idx1, idx2, idx3;
  567. idx1 = (minidx & dirflag1) ? minidx - dirflag1 : minidx + dirflag1;
  568. idx2 = (minidx & dirflag2) ? minidx - dirflag2 : minidx + dirflag2;
  569. idx3 = (minidx & dirflag2) ? idx1 - dirflag2 : idx1 + dirflag2;
  570. DrawExtrusionFace( vStart, vEnd, pts, idx1, idx3, cActual, meshBuilder );
  571. DrawExtrusionFace( vStart, vEnd, pts, idx2, idx3, cActual, meshBuilder );
  572. }
  573. meshBuilder.End();
  574. pMesh->Draw();
  575. }
  576. //-----------------------------------------------------------------------------
  577. // Draws a axis-aligned quad
  578. //-----------------------------------------------------------------------------
  579. void RenderQuad( IMaterial *pMaterial, float x, float y, float w, float h,
  580. float z, float s0, float t0, float s1, float t1, const Color& clr )
  581. {
  582. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  583. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  584. CMeshBuilder meshBuilder;
  585. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  586. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  587. meshBuilder.TexCoord2f( 0, s0, t0 );
  588. meshBuilder.Position3f( x, y, z );
  589. meshBuilder.AdvanceVertex();
  590. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  591. meshBuilder.TexCoord2f( 0, s1, t0 );
  592. meshBuilder.Position3f( x + w, y, z );
  593. meshBuilder.AdvanceVertex();
  594. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  595. meshBuilder.TexCoord2f( 0, s1, t1 );
  596. meshBuilder.Position3f( x + w, y + h, z );
  597. meshBuilder.AdvanceVertex();
  598. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  599. meshBuilder.TexCoord2f( 0, s0, t1 );
  600. meshBuilder.Position3f( x, y + h, z );
  601. meshBuilder.AdvanceVertex();
  602. meshBuilder.End();
  603. pMesh->Draw();
  604. }
  605. //-----------------------------------------------------------------------------
  606. // Renders a screen space quad
  607. //-----------------------------------------------------------------------------
  608. void DrawScreenSpaceRectangle( IMaterial *pMaterial,
  609. int nDestX, int nDestY, int nWidth, int nHeight, // Rect to draw into in screen space
  610. float flSrcTextureX0, float flSrcTextureY0, // which texel you want to appear at destx/y
  611. float flSrcTextureX1, float flSrcTextureY1, // which texel you want to appear at destx+width-1, desty+height-1
  612. int nSrcTextureWidth, int nSrcTextureHeight, // needed for fixup
  613. void *pClientRenderable, // Used to pass to the bind proxies
  614. int nXDice, int nYDice, // Amount to tessellate the mesh
  615. float fDepth ) // what Z value to put in the verts (def 0.0)
  616. {
  617. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  618. if ( ( nWidth <= 0 ) || ( nHeight <= 0 ) )
  619. return;
  620. tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s", __FUNCTION__ );
  621. pRenderContext->MatrixMode( MATERIAL_VIEW );
  622. pRenderContext->PushMatrix();
  623. pRenderContext->LoadIdentity();
  624. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  625. pRenderContext->PushMatrix();
  626. pRenderContext->LoadIdentity();
  627. pRenderContext->Bind( pMaterial, pClientRenderable );
  628. int xSegments = max( nXDice, 1);
  629. int ySegments = max( nYDice, 1);
  630. CMeshBuilder meshBuilder;
  631. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  632. meshBuilder.Begin( pMesh, MATERIAL_QUADS, xSegments * ySegments );
  633. int nScreenWidth, nScreenHeight;
  634. pRenderContext->GetRenderTargetDimensions( nScreenWidth, nScreenHeight );
  635. float flOffset = 0.5f;
  636. float flLeftX = nDestX - flOffset;
  637. float flRightX = nDestX + nWidth - flOffset;
  638. float flTopY = nDestY - flOffset;
  639. float flBottomY = nDestY + nHeight - flOffset;
  640. float flSubrectWidth = flSrcTextureX1 - flSrcTextureX0;
  641. float flSubrectHeight = flSrcTextureY1 - flSrcTextureY0;
  642. float flTexelsPerPixelX = ( nWidth > 1 ) ? flSubrectWidth / ( nWidth - 1 ) : 0.0f;
  643. float flTexelsPerPixelY = ( nHeight > 1 ) ? flSubrectHeight / ( nHeight - 1 ) : 0.0f;
  644. float flLeftU = flSrcTextureX0 + 0.5f - ( 0.5f * flTexelsPerPixelX );
  645. float flRightU = flSrcTextureX1 + 0.5f + ( 0.5f * flTexelsPerPixelX );
  646. float flTopV = flSrcTextureY0 + 0.5f - ( 0.5f * flTexelsPerPixelY );
  647. float flBottomV = flSrcTextureY1 + 0.5f + ( 0.5f * flTexelsPerPixelY );
  648. float flOOTexWidth = 1.0f / nSrcTextureWidth;
  649. float flOOTexHeight = 1.0f / nSrcTextureHeight;
  650. flLeftU *= flOOTexWidth;
  651. flRightU *= flOOTexWidth;
  652. flTopV *= flOOTexHeight;
  653. flBottomV *= flOOTexHeight;
  654. // Get the current viewport size
  655. int vx, vy, vw, vh;
  656. pRenderContext->GetViewport( vx, vy, vw, vh );
  657. // map from screen pixel coords to -1..1
  658. flRightX = FLerp( -1, 1, 0, vw, flRightX );
  659. flLeftX = FLerp( -1, 1, 0, vw, flLeftX );
  660. flTopY = FLerp( 1, -1, 0, vh ,flTopY );
  661. flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
  662. // Dice the quad up...
  663. if ( ( xSegments > 1 ) || ( ySegments > 1 ) )
  664. {
  665. // Screen height and width of a subrect
  666. float flWidth = (flRightX - flLeftX) / (float) xSegments;
  667. float flHeight = (flTopY - flBottomY) / (float) ySegments;
  668. // UV height and width of a subrect
  669. float flUWidth = (flRightU - flLeftU) / (float) xSegments;
  670. float flVHeight = (flBottomV - flTopV) / (float) ySegments;
  671. for ( int x=0; x < xSegments; x++ )
  672. {
  673. for ( int y=0; y < ySegments; y++ )
  674. {
  675. // Top left
  676. meshBuilder.Position3f( flLeftX + (float) x * flWidth, flTopY - (float) y * flHeight, fDepth );
  677. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  678. meshBuilder.TexCoord2f( 0, flLeftU + (float) x * flUWidth, flTopV + (float) y * flVHeight);
  679. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  680. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  681. meshBuilder.AdvanceVertex();
  682. // Top right (x+1)
  683. meshBuilder.Position3f( flLeftX + (float) (x+1) * flWidth, flTopY - (float) y * flHeight, fDepth );
  684. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  685. meshBuilder.TexCoord2f( 0, flLeftU + (float) (x+1) * flUWidth, flTopV + (float) y * flVHeight);
  686. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  687. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  688. meshBuilder.AdvanceVertex();
  689. // Bottom right (x+1), (y+1)
  690. meshBuilder.Position3f( flLeftX + (float) (x+1) * flWidth, flTopY - (float) (y+1) * flHeight, fDepth );
  691. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  692. meshBuilder.TexCoord2f( 0, flLeftU + (float) (x+1) * flUWidth, flTopV + (float)(y+1) * flVHeight);
  693. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  694. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  695. meshBuilder.AdvanceVertex();
  696. // Bottom left (y+1)
  697. meshBuilder.Position3f( flLeftX + (float) x * flWidth, flTopY - (float) (y+1) * flHeight, fDepth );
  698. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  699. meshBuilder.TexCoord2f( 0, flLeftU + (float) x * flUWidth, flTopV + (float)(y+1) * flVHeight);
  700. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  701. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  702. meshBuilder.AdvanceVertex();
  703. }
  704. }
  705. }
  706. else // just one quad
  707. {
  708. for ( int corner=0; corner<4; corner++ )
  709. {
  710. bool bLeft = (corner==0) || (corner==3);
  711. meshBuilder.Position3f( (bLeft) ? flLeftX : flRightX, (corner & 2) ? flBottomY : flTopY, fDepth );
  712. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  713. meshBuilder.TexCoord2f( 0, (bLeft) ? flLeftU : flRightU, (corner & 2) ? flBottomV : flTopV );
  714. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  715. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  716. meshBuilder.AdvanceVertex();
  717. }
  718. }
  719. meshBuilder.End();
  720. pMesh->Draw();
  721. pRenderContext->MatrixMode( MATERIAL_VIEW );
  722. pRenderContext->PopMatrix();
  723. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  724. pRenderContext->PopMatrix();
  725. }