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.

1166 lines
37 KiB

  1. //===== Copyright � 2005-2005, 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 "tier1/callqueue.h"
  13. #include "tier0/vprof.h"
  14. #include "tier0/basetypes.h"
  15. #include "togl/rendermechanism.h"
  16. // NOTE: This has to be the last file included!
  17. #include "tier0/memdbgon.h"
  18. #if !defined(M_PI)
  19. #define M_PI 3.14159265358979323846
  20. #endif
  21. //-----------------------------------------------------------------------------
  22. // Globals
  23. //-----------------------------------------------------------------------------
  24. static bool s_bMaterialsInitialized = false;
  25. static IMaterial *s_pWireframe;
  26. static IMaterial *s_pWireframeIgnoreZ;
  27. static IMaterial *s_pVertexColor;
  28. static IMaterial *s_pVertexColorIgnoreZ;
  29. //-----------------------------------------------------------------------------
  30. // Initializes standard materials
  31. //-----------------------------------------------------------------------------
  32. void InitializeStandardMaterials()
  33. {
  34. LOCAL_THREAD_LOCK();
  35. if ( s_bMaterialsInitialized )
  36. return;
  37. s_bMaterialsInitialized = true;
  38. KeyValues *pVMTKeyValues = new KeyValues( "wireframe" );
  39. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  40. s_pWireframe = g_pMaterialSystem->CreateMaterial( "__utilWireframe", pVMTKeyValues );
  41. s_pWireframe->IncrementReferenceCount();
  42. pVMTKeyValues = new KeyValues( "wireframe" );
  43. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  44. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  45. pVMTKeyValues->SetInt( "$ignorez", 1 );
  46. s_pWireframeIgnoreZ = g_pMaterialSystem->CreateMaterial( "__utilWireframeIgnoreZ", pVMTKeyValues );
  47. s_pWireframeIgnoreZ->IncrementReferenceCount();
  48. pVMTKeyValues = new KeyValues( "unlitgeneric" );
  49. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  50. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  51. s_pVertexColor = g_pMaterialSystem->CreateMaterial( "__utilVertexColor", pVMTKeyValues );
  52. s_pVertexColor->IncrementReferenceCount();
  53. pVMTKeyValues = new KeyValues( "unlitgeneric" );
  54. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  55. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  56. pVMTKeyValues->SetInt( "$ignorez", 1 );
  57. s_pVertexColorIgnoreZ = g_pMaterialSystem->CreateMaterial( "__utilVertexColorIgnoreZ", pVMTKeyValues );
  58. s_pVertexColorIgnoreZ->IncrementReferenceCount();
  59. }
  60. void ShutdownStandardMaterials()
  61. {
  62. if ( !s_bMaterialsInitialized )
  63. return;
  64. s_bMaterialsInitialized = false;
  65. s_pWireframe->DecrementReferenceCount();
  66. s_pWireframe = NULL;
  67. s_pWireframeIgnoreZ->DecrementReferenceCount();
  68. s_pWireframeIgnoreZ = NULL;
  69. s_pVertexColor->DecrementReferenceCount();
  70. s_pVertexColor = NULL;
  71. s_pVertexColorIgnoreZ->DecrementReferenceCount();
  72. s_pVertexColorIgnoreZ = NULL;
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Renders a wireframe sphere
  76. //-----------------------------------------------------------------------------
  77. void RenderWireframeSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer )
  78. {
  79. InitializeStandardMaterials();
  80. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  81. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  82. if ( pCallQueue )
  83. {
  84. pCallQueue->QueueCall( RenderWireframeSphere, RefToVal( vCenter ), flRadius, nTheta, nPhi, c, bZBuffer );
  85. return;
  86. }
  87. // Make one more coordinate because (u,v) is discontinuous.
  88. ++nTheta;
  89. int nVertices = nPhi * nTheta;
  90. int nIndices = ( nTheta - 1 ) * 4 * ( nPhi - 1 );
  91. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  92. CMeshBuilder meshBuilder;
  93. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  94. meshBuilder.Begin( pMesh, MATERIAL_LINES, nVertices, nIndices );
  95. unsigned char chRed = c.r();
  96. unsigned char chGreen = c.g();
  97. unsigned char chBlue = c.b();
  98. unsigned char chAlpha = c.a();
  99. int i, j;
  100. for ( i = 0; i < nPhi; ++i )
  101. {
  102. for ( j = 0; j < nTheta; ++j )
  103. {
  104. float u = j / ( float )( nTheta - 1 );
  105. float v = i / ( float )( nPhi - 1 );
  106. float theta = 2.0f * M_PI * u;
  107. float phi = M_PI * v;
  108. meshBuilder.Position3f( vCenter.x + ( flRadius * sin(phi) * cos(theta) ),
  109. vCenter.y + ( flRadius * sin(phi) * sin(theta) ),
  110. vCenter.z + ( flRadius * cos(phi) ) );
  111. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  112. meshBuilder.AdvanceVertex();
  113. }
  114. }
  115. for ( i = 0; i < nPhi - 1; ++i )
  116. {
  117. for ( j = 0; j < nTheta - 1; ++j )
  118. {
  119. int idx = nTheta * i + j;
  120. meshBuilder.Index( idx );
  121. meshBuilder.AdvanceIndex();
  122. meshBuilder.Index( idx + nTheta );
  123. meshBuilder.AdvanceIndex();
  124. meshBuilder.Index( idx );
  125. meshBuilder.AdvanceIndex();
  126. meshBuilder.Index( idx + 1 );
  127. meshBuilder.AdvanceIndex();
  128. }
  129. }
  130. meshBuilder.End();
  131. pMesh->Draw();
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Draws a sphere
  135. //-----------------------------------------------------------------------------
  136. void RenderSphereInternal( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, IMaterial *pMaterial, bool bInsideOut )
  137. {
  138. InitializeStandardMaterials();
  139. CMatRenderContextPtr pRenderContext( materials );
  140. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  141. if ( pCallQueue )
  142. {
  143. pCallQueue->QueueCall( RenderSphereInternal, RefToVal( vCenter ), flRadius, nTheta, nPhi, c, pMaterial, bInsideOut );
  144. return;
  145. }
  146. unsigned char chRed = c.r();
  147. unsigned char chGreen = c.g();
  148. unsigned char chBlue = c.b();
  149. unsigned char chAlpha = c.a();
  150. // Two extra degenerate triangles per row (except the last one)
  151. int nTriangles = 2 * nTheta * ( nPhi - 1 );
  152. int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
  153. if ( nTriangles == 0 )
  154. return;
  155. pRenderContext->Bind( pMaterial );
  156. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  157. CMeshBuilder meshBuilder;
  158. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nTriangles, nIndices );
  159. // Build the index buffer.
  160. float flOONPhi = 1.0f / (nPhi-1);
  161. float flOONTheta = 1.0f / (nTheta-1);
  162. int i, j;
  163. for ( i = 0; i < nPhi; ++i )
  164. {
  165. for ( j = 0; j < nTheta; ++j )
  166. {
  167. float u = j / ( float )( nTheta - 1 );
  168. float v = i / ( float )( nPhi - 1 );
  169. float theta = 2.0f * M_PI * u;
  170. float phi = M_PI * v;
  171. Vector vecPos;
  172. vecPos.x = flRadius * sin(phi) * cos(theta);
  173. vecPos.y = flRadius * sin(phi) * sin(theta);
  174. vecPos.z = flRadius * cos(phi);
  175. Vector vecNormal = vecPos;
  176. VectorNormalize(vecNormal);
  177. Vector4D vecTangent( -vecPos.y, vecPos.x, 0.0f, 1.0f );
  178. VectorNormalize( vecTangent.AsVector3D() );
  179. vecPos += vCenter;
  180. meshBuilder.Position3f( vecPos.x, vecPos.y, vecPos.z );
  181. meshBuilder.Normal3f( vecNormal.x, vecNormal.y, vecNormal.z );
  182. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  183. meshBuilder.UserData( vecTangent.Base() );
  184. meshBuilder.TexCoord2f( 0, j * flOONTheta, i * flOONPhi );
  185. meshBuilder.AdvanceVertex();
  186. }
  187. }
  188. // Emit the triangle strips.
  189. int idx = 0;
  190. for ( i = 0; i < nPhi - 1; ++i )
  191. {
  192. if ( bInsideOut )
  193. {
  194. for ( j = nTheta-1; j >= 0; --j )
  195. {
  196. idx = nTheta * i + j;
  197. meshBuilder.Index( idx + nTheta );
  198. meshBuilder.AdvanceIndex();
  199. meshBuilder.Index( idx );
  200. meshBuilder.AdvanceIndex();
  201. }
  202. }
  203. else
  204. {
  205. for ( j = 0; j < nTheta; ++j )
  206. {
  207. idx = nTheta * i + j;
  208. meshBuilder.Index( idx + nTheta );
  209. meshBuilder.AdvanceIndex();
  210. meshBuilder.Index( idx );
  211. meshBuilder.AdvanceIndex();
  212. }
  213. // Emit a degenerate triangle to skip to the next row without a connecting triangle
  214. if ( i < nPhi - 2 )
  215. {
  216. meshBuilder.Index( idx );
  217. meshBuilder.AdvanceIndex();
  218. meshBuilder.Index( idx + nTheta + 1 );
  219. meshBuilder.AdvanceIndex();
  220. }
  221. }
  222. }
  223. meshBuilder.End();
  224. pMesh->Draw();
  225. }
  226. void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, IMaterial *pMaterial, bool bInsideOut )
  227. {
  228. RenderSphereInternal( vCenter, flRadius, nTheta, nPhi, c, pMaterial, bInsideOut );
  229. }
  230. void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer, bool bInsideOut )
  231. {
  232. InitializeStandardMaterials();
  233. IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
  234. Color cActual( c.r(), c.g(), c.b(), c.a() );
  235. RenderSphereInternal( vCenter, flRadius, nTheta, nPhi, cActual, pMaterial, bInsideOut );
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Box vertices
  239. //-----------------------------------------------------------------------------
  240. static int s_pBoxFaceIndices[6][4] =
  241. {
  242. { 0, 4, 6, 2 }, // -x
  243. { 5, 1, 3, 7 }, // +x
  244. { 0, 1, 5, 4 }, // -y
  245. { 2, 6, 7, 3 }, // +y
  246. { 0, 2, 3, 1 }, // -z
  247. { 4, 5, 7, 6 } // +z
  248. };
  249. static int s_pBoxFaceIndicesInsideOut[6][4] =
  250. {
  251. { 0, 2, 6, 4 }, // -x
  252. { 5, 7, 3, 1 }, // +x
  253. { 0, 4, 5, 1 }, // -y
  254. { 2, 3, 7, 6 }, // +y
  255. { 0, 1, 3, 2 }, // -z
  256. { 4, 6, 7, 5 } // +z
  257. };
  258. static void GenerateBoxVertices( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Vector pVerts[8] )
  259. {
  260. // Build a rotation matrix from orientation
  261. matrix3x4_t fRotateMatrix;
  262. AngleMatrix( angles, fRotateMatrix );
  263. Vector vecPos;
  264. for ( int i = 0; i < 8; ++i )
  265. {
  266. vecPos[0] = ( i & 0x1 ) ? vMaxs[0] : vMins[0];
  267. vecPos[1] = ( i & 0x2 ) ? vMaxs[1] : vMins[1];
  268. vecPos[2] = ( i & 0x4 ) ? vMaxs[2] : vMins[2];
  269. VectorRotate( vecPos, fRotateMatrix, pVerts[i] );
  270. pVerts[i] += vOrigin;
  271. }
  272. }
  273. //-----------------------------------------------------------------------------
  274. // Renders a wireframe box relative to an origin
  275. //-----------------------------------------------------------------------------
  276. void RenderWireframeBox( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer )
  277. {
  278. InitializeStandardMaterials();
  279. CMatRenderContextPtr pRenderContext( materials );
  280. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  281. if ( pCallQueue )
  282. {
  283. pCallQueue->QueueCall( RenderWireframeBox, RefToVal( vOrigin ), RefToVal( angles ), RefToVal( vMins ), RefToVal( vMaxs ), c, bZBuffer );
  284. return;
  285. }
  286. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  287. Vector p[8];
  288. GenerateBoxVertices( vOrigin, angles, vMins, vMaxs, p );
  289. unsigned char chRed = c.r();
  290. unsigned char chGreen = c.g();
  291. unsigned char chBlue = c.b();
  292. unsigned char chAlpha = c.a();
  293. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  294. CMeshBuilder meshBuilder;
  295. meshBuilder.Begin( pMesh, MATERIAL_LINES, 24 );
  296. // Draw the box
  297. for ( int i = 0; i < 6; i++ )
  298. {
  299. int *pFaceIndex = s_pBoxFaceIndices[i];
  300. for ( int j = 0; j < 4; ++j )
  301. {
  302. meshBuilder.Position3fv( p[pFaceIndex[j]].Base() );
  303. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  304. meshBuilder.AdvanceVertex();
  305. meshBuilder.Position3fv( p[pFaceIndex[ (j == 3) ? 0 : j+1 ] ].Base() );
  306. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  307. meshBuilder.AdvanceVertex();
  308. }
  309. }
  310. meshBuilder.End();
  311. pMesh->Draw();
  312. }
  313. //-----------------------------------------------------------------------------
  314. // Renders a solid box
  315. //-----------------------------------------------------------------------------
  316. void RenderBoxInternal( const Vector& vOrigin, const QAngle& angles, const Vector& vMins, const Vector& vMaxs, Color c, IMaterial *pMaterial, bool bInsideOut )
  317. {
  318. InitializeStandardMaterials();
  319. CMatRenderContextPtr pRenderContext( materials );
  320. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  321. if ( pCallQueue )
  322. {
  323. pCallQueue->QueueCall( RenderBoxInternal, RefToVal( vOrigin ), RefToVal( angles ), RefToVal( vMins ), RefToVal( vMaxs ), c, pMaterial, bInsideOut );
  324. return;
  325. }
  326. pRenderContext->Bind( pMaterial );
  327. Vector p[8];
  328. GenerateBoxVertices( vOrigin, angles, vMins, vMaxs, p );
  329. unsigned char chRed = c.r();
  330. unsigned char chGreen = c.g();
  331. unsigned char chBlue = c.b();
  332. unsigned char chAlpha = c.a();
  333. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  334. CMeshBuilder meshBuilder;
  335. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 12 );
  336. // Draw the box
  337. Vector vecNormal;
  338. for ( int i = 0; i < 6; i++ )
  339. {
  340. vecNormal.Init();
  341. vecNormal[ i/2 ] = ( i & 0x1 ) ? 1.0f : -1.0f;
  342. int *ppFaceIndices = bInsideOut ? s_pBoxFaceIndicesInsideOut[i] : s_pBoxFaceIndices[i];
  343. for ( int j = 1; j < 3; ++j )
  344. {
  345. int i0 = ppFaceIndices[0];
  346. int i1 = ppFaceIndices[j];
  347. int i2 = ppFaceIndices[j+1];
  348. meshBuilder.Position3fv( p[i0].Base() );
  349. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  350. meshBuilder.Normal3fv( vecNormal.Base() );
  351. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  352. meshBuilder.AdvanceVertex();
  353. meshBuilder.Position3fv( p[i2].Base() );
  354. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  355. meshBuilder.Normal3fv( vecNormal.Base() );
  356. meshBuilder.TexCoord2f( 0, 1.0f, ( j == 1 ) ? 1.0f : 0.0f );
  357. meshBuilder.AdvanceVertex();
  358. meshBuilder.Position3fv( p[i1].Base() );
  359. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  360. meshBuilder.Normal3fv( vecNormal.Base() );
  361. meshBuilder.TexCoord2f( 0, ( j == 1 ) ? 0.0f : 1.0f, 1.0f );
  362. meshBuilder.AdvanceVertex();
  363. }
  364. }
  365. meshBuilder.End();
  366. pMesh->Draw();
  367. }
  368. void RenderBox( const Vector& vOrigin, const QAngle& angles, const Vector& vMins, const Vector& vMaxs, Color c, IMaterial *pMaterial, bool bInsideOut )
  369. {
  370. RenderBoxInternal( vOrigin, angles, vMins, vMaxs, c, pMaterial, bInsideOut );
  371. }
  372. void RenderBox( const Vector& vOrigin, const QAngle& angles, const Vector& vMins, const Vector& vMaxs, Color c, bool bZBuffer, bool bInsideOut )
  373. {
  374. InitializeStandardMaterials();
  375. IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
  376. Color cActual( c.r(), c.g(), c.b(), c.a() );
  377. RenderBoxInternal( vOrigin, angles, vMins, vMaxs, cActual, pMaterial, bInsideOut );
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Renders axes, red->x, green->y, blue->z
  381. //-----------------------------------------------------------------------------
  382. void RenderAxesAtOrigin( const Vector &vOrigin, float flScale, bool bZBuffer )
  383. {
  384. RenderAxes( vOrigin, flScale, bZBuffer );
  385. }
  386. void RenderAxes( const Vector &vOrigin, float flScale, bool bZBuffer )
  387. {
  388. InitializeStandardMaterials();
  389. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  390. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  391. if ( pCallQueue )
  392. {
  393. pCallQueue->QueueCall( RenderAxesAtOrigin, RefToVal( vOrigin ), flScale, bZBuffer );
  394. return;
  395. }
  396. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  397. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  398. CMeshBuilder meshBuilder;
  399. meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
  400. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  401. meshBuilder.Color4ub( 255, 0, 0, 255 );
  402. meshBuilder.AdvanceVertex();
  403. meshBuilder.Position3f( vOrigin.x + flScale, vOrigin.y, vOrigin.z );
  404. meshBuilder.Color4ub( 255, 0, 0, 255 );
  405. meshBuilder.AdvanceVertex();
  406. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  407. meshBuilder.Color4ub( 0, 255, 0, 255 );
  408. meshBuilder.AdvanceVertex();
  409. meshBuilder.Position3f( vOrigin.x, vOrigin.y + flScale, vOrigin.z );
  410. meshBuilder.Color4ub( 0, 255, 0, 255 );
  411. meshBuilder.AdvanceVertex();
  412. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  413. meshBuilder.Color4ub( 0, 0, 255, 255 );
  414. meshBuilder.AdvanceVertex();
  415. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z + flScale );
  416. meshBuilder.Color4ub( 0, 0, 255, 255 );
  417. meshBuilder.AdvanceVertex();
  418. meshBuilder.End();
  419. pMesh->Draw();
  420. }
  421. void RenderAxesWithTransform( const matrix3x4_t &transform, float flScale, bool bZBuffer )
  422. {
  423. RenderAxes( transform, flScale, bZBuffer );
  424. }
  425. void RenderAxes( const matrix3x4_t &transform, float flScale, bool bZBuffer )
  426. {
  427. InitializeStandardMaterials();
  428. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  429. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  430. if ( pCallQueue )
  431. {
  432. pCallQueue->QueueCall( RenderAxesWithTransform, RefToVal( transform ), flScale, bZBuffer );
  433. return;
  434. }
  435. Vector xAxis, yAxis, zAxis, vOrigin, temp;
  436. MatrixGetColumn( transform, 0, xAxis );
  437. MatrixGetColumn( transform, 1, yAxis );
  438. MatrixGetColumn( transform, 2, zAxis );
  439. MatrixGetColumn( transform, 3, vOrigin );
  440. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  441. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  442. CMeshBuilder meshBuilder;
  443. meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
  444. meshBuilder.Position3fv( vOrigin.Base() );
  445. meshBuilder.Color4ub( 255, 0, 0, 255 );
  446. meshBuilder.AdvanceVertex();
  447. VectorMA( vOrigin, flScale, xAxis, temp );
  448. meshBuilder.Position3fv( temp.Base() );
  449. meshBuilder.Color4ub( 255, 0, 0, 255 );
  450. meshBuilder.AdvanceVertex();
  451. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  452. meshBuilder.Color4ub( 0, 255, 0, 255 );
  453. meshBuilder.AdvanceVertex();
  454. VectorMA( vOrigin, flScale, yAxis, temp );
  455. meshBuilder.Position3fv( temp.Base() );
  456. meshBuilder.Color4ub( 0, 255, 0, 255 );
  457. meshBuilder.AdvanceVertex();
  458. meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
  459. meshBuilder.Color4ub( 0, 0, 255, 255 );
  460. meshBuilder.AdvanceVertex();
  461. VectorMA( vOrigin, flScale, zAxis, temp );
  462. meshBuilder.Position3fv( temp.Base() );
  463. meshBuilder.Color4ub( 0, 0, 255, 255 );
  464. meshBuilder.AdvanceVertex();
  465. meshBuilder.End();
  466. pMesh->Draw();
  467. }
  468. //-----------------------------------------------------------------------------
  469. // Render a line
  470. //-----------------------------------------------------------------------------
  471. void RenderLine( const Vector& v1, const Vector& v2, Color c, bool bZBuffer )
  472. {
  473. InitializeStandardMaterials();
  474. CMatRenderContextPtr pRenderContext( materials );
  475. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  476. if ( pCallQueue )
  477. {
  478. pCallQueue->QueueCall( RenderLine, RefToVal( v1 ), RefToVal( v2 ), c, bZBuffer );
  479. return;
  480. }
  481. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  482. unsigned char chRed = c.r();
  483. unsigned char chGreen = c.g();
  484. unsigned char chBlue = c.b();
  485. unsigned char chAlpha = c.a();
  486. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  487. CMeshBuilder meshBuilder;
  488. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  489. meshBuilder.Position3fv( v1.Base() );
  490. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  491. meshBuilder.AdvanceVertex();
  492. meshBuilder.Position3fv( v2.Base() );
  493. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  494. meshBuilder.AdvanceVertex();
  495. meshBuilder.End();
  496. pMesh->Draw();
  497. }
  498. // todo: draw a capsule procedurally instead of using these baked-in unit capsule verts
  499. #define CAPSULE_VERTS 74
  500. #define CAPSULE_LINES 117
  501. float g_capsuleVertPositions[CAPSULE_VERTS][3] = {
  502. { -0.01, -0.01, 1.0 }, { 0.51, 0.0, 0.86 }, { 0.44, 0.25, 0.86 }, { 0.25, 0.44, 0.86 }, { -0.01, 0.51, 0.86 }, { -0.26, 0.44, 0.86 }, { -0.45, 0.25, 0.86 }, { -0.51, 0.0, 0.86 }, { -0.45, -0.26, 0.86 },
  503. { -0.26, -0.45, 0.86 }, { -0.01, -0.51, 0.86 }, { 0.25, -0.45, 0.86 }, { 0.44, -0.26, 0.86 }, { 0.86, 0.0, 0.51 }, { 0.75, 0.43, 0.51 }, { 0.43, 0.75, 0.51 }, { -0.01, 0.86, 0.51 }, { -0.44, 0.75, 0.51 },
  504. { -0.76, 0.43, 0.51 }, { -0.87, 0.0, 0.51 }, { -0.76, -0.44, 0.51 }, { -0.44, -0.76, 0.51 }, { -0.01, -0.87, 0.51 }, { 0.43, -0.76, 0.51 }, { 0.75, -0.44, 0.51 }, { 1.0, 0.0, 0.01 }, { 0.86, 0.5, 0.01 },
  505. { 0.49, 0.86, 0.01 }, { -0.01, 1.0, 0.01 }, { -0.51, 0.86, 0.01 }, { -0.87, 0.5, 0.01 }, { -1.0, 0.0, 0.01 }, { -0.87, -0.5, 0.01 }, { -0.51, -0.87, 0.01 }, { -0.01, -1.0, 0.01 }, { 0.49, -0.87, 0.01 },
  506. { 0.86, -0.51, 0.01 }, { 1.0, 0.0, -0.02 }, { 0.86, 0.5, -0.02 }, { 0.49, 0.86, -0.02 }, { -0.01, 1.0, -0.02 }, { -0.51, 0.86, -0.02 }, { -0.87, 0.5, -0.02 }, { -1.0, 0.0, -0.02 }, { -0.87, -0.5, -0.02 },
  507. { -0.51, -0.87, -0.02 },{ -0.01, -1.0, -0.02 }, { 0.49, -0.87, -0.02 }, { 0.86, -0.51, -0.02 }, { 0.86, 0.0, -0.51 }, { 0.75, 0.43, -0.51 }, { 0.43, 0.75, -0.51 }, { -0.01, 0.86, -0.51 }, { -0.44, 0.75, -0.51 },
  508. { -0.76, 0.43, -0.51 }, { -0.87, 0.0, -0.51 }, { -0.76, -0.44, -0.51 },{ -0.44, -0.76, -0.51 },{ -0.01, -0.87, -0.51 },{ 0.43, -0.76, -0.51 }, { 0.75, -0.44, -0.51 }, { 0.51, 0.0, -0.87 }, { 0.44, 0.25, -0.87 },
  509. { 0.25, 0.44, -0.87 }, { -0.01, 0.51, -0.87 }, { -0.26, 0.44, -0.87 }, { -0.45, 0.25, -0.87 }, { -0.51, 0.0, -0.87 }, { -0.45, -0.26, -0.87 },{ -0.26, -0.45, -0.87 },{ -0.01, -0.51, -0.87 },{ 0.25, -0.45, -0.87 },
  510. { 0.44, -0.26, -0.87 }, { 0.0, 0.0, -1.0 },
  511. };
  512. int g_capsuleLineIndices[CAPSULE_LINES] = { -1,
  513. 14, 0, 4, 16, 28, 40, 52, 64, 73, 70, 58, 46, 34, 22, 10, -1,
  514. 14, 0, 1, 13, 25, 37, 49, 61, 73, 67, 55, 43, 31, 19, 7, -1,
  515. 12, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, -1,
  516. 12, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, -1,
  517. 12, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, -1,
  518. 12, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1,
  519. 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -1,
  520. 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1
  521. };
  522. void RenderCapsule( const Vector &vStart, const Vector &vEnd, const float &flRadius, Color c, IMaterial *pMaterial )
  523. {
  524. InitializeStandardMaterials();
  525. CMatRenderContextPtr pRenderContext( materials );
  526. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  527. if ( pCallQueue )
  528. {
  529. pCallQueue->QueueCall( RenderCapsule, RefToVal( vStart ), RefToVal( vEnd ), RefToVal( flRadius ), c, pMaterial );
  530. return;
  531. }
  532. //RenderLine( vStart, vEnd, c, false );
  533. Vector vecCapsuleCoreNormal = ( vStart - vEnd ).Normalized();
  534. matrix3x4_t matCapsuleRotationSpace;
  535. VectorMatrix( Vector(0,0,1), matCapsuleRotationSpace );
  536. matrix3x4_t matCapsuleSpace;
  537. VectorMatrix( vecCapsuleCoreNormal, matCapsuleSpace );
  538. Vector v[CAPSULE_VERTS];
  539. Vector vecLen = (vEnd - vStart);
  540. for ( int i=0; i<CAPSULE_VERTS; i++ )
  541. {
  542. Vector vecCapsuleVert = Vector( g_capsuleVertPositions[i][0], g_capsuleVertPositions[i][1], g_capsuleVertPositions[i][2] );
  543. VectorRotate( vecCapsuleVert, matCapsuleRotationSpace, vecCapsuleVert );
  544. VectorRotate( vecCapsuleVert, matCapsuleSpace, vecCapsuleVert );
  545. vecCapsuleVert *= flRadius;
  546. if ( g_capsuleVertPositions[i][2] > 0 )
  547. {
  548. vecCapsuleVert += vecLen;
  549. }
  550. v[i] = vecCapsuleVert + vStart;
  551. }
  552. unsigned char chRed = c.r();
  553. unsigned char chGreen = c.g();
  554. unsigned char chBlue = c.b();
  555. unsigned char chAlpha = c.a();
  556. pRenderContext->Bind( s_pWireframeIgnoreZ );
  557. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  558. CMeshBuilder meshBuilder;
  559. for ( int i=0; i<CAPSULE_LINES; i++ )
  560. {
  561. if ( g_capsuleLineIndices[i] == -1 )
  562. {
  563. if ( i > 0 )
  564. {
  565. meshBuilder.End( false, true );
  566. if ( i == CAPSULE_LINES - 1 )
  567. break;
  568. }
  569. i++;
  570. meshBuilder.Begin( pMesh, MATERIAL_LINE_LOOP, g_capsuleLineIndices[i] );
  571. i++;
  572. }
  573. meshBuilder.Position3fv (v[g_capsuleLineIndices[i]].Base());
  574. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  575. meshBuilder.AdvanceVertex();
  576. }
  577. }
  578. //-----------------------------------------------------------------------------
  579. // Draws a triangle
  580. //-----------------------------------------------------------------------------
  581. void RenderTriangleInternal( const Vector& p1, const Vector& p2, const Vector& p3, Color c, IMaterial *pMaterial )
  582. {
  583. InitializeStandardMaterials();
  584. CMatRenderContextPtr pRenderContext( materials );
  585. ICallQueue *pCallQueue = pRenderContext->GetCallQueue();
  586. if ( pCallQueue )
  587. {
  588. pCallQueue->QueueCall( RenderTriangleInternal, RefToVal( p1 ), RefToVal( p2 ), RefToVal( p3 ), c, pMaterial );
  589. return;
  590. }
  591. pRenderContext->Bind( pMaterial );
  592. unsigned char chRed = c.r();
  593. unsigned char chGreen = c.g();
  594. unsigned char chBlue = c.b();
  595. unsigned char chAlpha = c.a();
  596. Vector vecNormal;
  597. Vector vecDelta1, vecDelta2;
  598. VectorSubtract( p2, p1, vecDelta1 );
  599. VectorSubtract( p3, p1, vecDelta2 );
  600. CrossProduct( vecDelta1, vecDelta2, vecNormal );
  601. VectorNormalize( vecNormal );
  602. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  603. CMeshBuilder meshBuilder;
  604. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 1 );
  605. meshBuilder.Position3fv( p1.Base() );
  606. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  607. meshBuilder.Normal3fv( vecNormal.Base() );
  608. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  609. meshBuilder.AdvanceVertex();
  610. meshBuilder.Position3fv( p2.Base() );
  611. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  612. meshBuilder.Normal3fv( vecNormal.Base() );
  613. meshBuilder.TexCoord2f( 0, 0.0f, 1.0f );
  614. meshBuilder.AdvanceVertex();
  615. meshBuilder.Position3fv( p3.Base() );
  616. meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
  617. meshBuilder.Normal3fv( vecNormal.Base() );
  618. meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
  619. meshBuilder.AdvanceVertex();
  620. meshBuilder.End();
  621. pMesh->Draw();
  622. }
  623. void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, IMaterial *pMaterial )
  624. {
  625. RenderTriangleInternal( p1, p2, p3, c, pMaterial );
  626. }
  627. void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, bool bZBuffer )
  628. {
  629. InitializeStandardMaterials();
  630. IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
  631. Color cActual( c.r(), c.g(), c.b(), c.a() );
  632. RenderTriangleInternal( p1, p2, p3, cActual, pMaterial );
  633. }
  634. //-----------------------------------------------------------------------------
  635. // Renders an extruded box
  636. //-----------------------------------------------------------------------------
  637. static void DrawAxes( const Vector& origin, Vector* pts, int idx, Color c, CMeshBuilder& meshBuilder )
  638. {
  639. Vector start, temp;
  640. VectorAdd( pts[idx], origin, start );
  641. meshBuilder.Position3fv( start.Base() );
  642. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  643. meshBuilder.AdvanceVertex();
  644. int endidx = (idx & 0x1) ? idx - 1 : idx + 1;
  645. VectorAdd( pts[endidx], origin, temp );
  646. meshBuilder.Position3fv( temp.Base() );
  647. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  648. meshBuilder.AdvanceVertex();
  649. meshBuilder.Position3fv( start.Base() );
  650. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  651. meshBuilder.AdvanceVertex();
  652. endidx = (idx & 0x2) ? idx - 2 : idx + 2;
  653. VectorAdd( pts[endidx], origin, temp );
  654. meshBuilder.Position3fv( temp.Base() );
  655. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  656. meshBuilder.AdvanceVertex();
  657. meshBuilder.Position3fv( start.Base() );
  658. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  659. meshBuilder.AdvanceVertex();
  660. endidx = (idx & 0x4) ? idx - 4 : idx + 4;
  661. VectorAdd( pts[endidx], origin, temp );
  662. meshBuilder.Position3fv( temp.Base() );
  663. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  664. meshBuilder.AdvanceVertex();
  665. }
  666. static void DrawExtrusionFace( const Vector& start, const Vector& end,
  667. Vector* pts, int idx1, int idx2, Color c, CMeshBuilder& meshBuilder )
  668. {
  669. Vector temp;
  670. VectorAdd( pts[idx1], start, temp );
  671. meshBuilder.Position3fv( temp.Base() );
  672. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  673. meshBuilder.AdvanceVertex();
  674. VectorAdd( pts[idx2], start, temp );
  675. meshBuilder.Position3fv( temp.Base() );
  676. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  677. meshBuilder.AdvanceVertex();
  678. meshBuilder.Position3fv( temp.Base() );
  679. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  680. meshBuilder.AdvanceVertex();
  681. VectorAdd( pts[idx2], end, temp );
  682. meshBuilder.Position3fv( temp.Base() );
  683. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  684. meshBuilder.AdvanceVertex();
  685. meshBuilder.Position3fv( temp.Base() );
  686. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  687. meshBuilder.AdvanceVertex();
  688. VectorAdd( pts[idx1], end, temp );
  689. meshBuilder.Position3fv( temp.Base() );
  690. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  691. meshBuilder.AdvanceVertex();
  692. meshBuilder.Position3fv( temp.Base() );
  693. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  694. meshBuilder.AdvanceVertex();
  695. VectorAdd( pts[idx1], start, temp );
  696. meshBuilder.Position3fv( temp.Base() );
  697. meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
  698. meshBuilder.AdvanceVertex();
  699. }
  700. void RenderWireframeSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer )
  701. {
  702. InitializeStandardMaterials();
  703. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  704. pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
  705. Color cActual( c.r(), c.g(), c.b(), c.a() );
  706. // Build a rotation matrix from angles
  707. matrix3x4_t fRotateMatrix;
  708. AngleMatrix( angles, fRotateMatrix );
  709. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  710. CMeshBuilder meshBuilder;
  711. meshBuilder.Begin( pMesh, MATERIAL_LINES, 30 );
  712. Vector vDelta;
  713. VectorSubtract( vEnd, vStart, vDelta );
  714. // Compute the box points, rotated but without the origin added
  715. Vector temp;
  716. Vector pts[8];
  717. float dot[8];
  718. int minidx = 0;
  719. for ( int i = 0; i < 8; ++i )
  720. {
  721. temp.x = (i & 0x1) ? vMaxs[0] : vMins[0];
  722. temp.y = (i & 0x2) ? vMaxs[1] : vMins[1];
  723. temp.z = (i & 0x4) ? vMaxs[2] : vMins[2];
  724. // Rotate the corner point
  725. VectorRotate( temp, fRotateMatrix, pts[i] );
  726. // Find the dot product with dir
  727. dot[i] = DotProduct( pts[i], vDelta );
  728. if ( dot[i] < dot[minidx] )
  729. {
  730. minidx = i;
  731. }
  732. }
  733. // Choose opposite corner
  734. int maxidx = minidx ^ 0x7;
  735. // Draw the start + end axes...
  736. DrawAxes( vStart, pts, minidx, cActual, meshBuilder );
  737. DrawAxes( vEnd, pts, maxidx, cActual, meshBuilder );
  738. // Draw the extrusion faces
  739. for (int j = 0; j < 3; ++j )
  740. {
  741. int dirflag1 = ( 1 << ((j+1)%3) );
  742. int dirflag2 = ( 1 << ((j+2)%3) );
  743. int idx1, idx2, idx3;
  744. idx1 = (minidx & dirflag1) ? minidx - dirflag1 : minidx + dirflag1;
  745. idx2 = (minidx & dirflag2) ? minidx - dirflag2 : minidx + dirflag2;
  746. idx3 = (minidx & dirflag2) ? idx1 - dirflag2 : idx1 + dirflag2;
  747. DrawExtrusionFace( vStart, vEnd, pts, idx1, idx3, cActual, meshBuilder );
  748. DrawExtrusionFace( vStart, vEnd, pts, idx2, idx3, cActual, meshBuilder );
  749. }
  750. meshBuilder.End();
  751. pMesh->Draw();
  752. }
  753. //-----------------------------------------------------------------------------
  754. // Draws a axis-aligned quad
  755. //-----------------------------------------------------------------------------
  756. void RenderQuad( IMaterial *pMaterial, float x, float y, float w, float h,
  757. float z, float s0, float t0, float s1, float t1, const Color& clr )
  758. {
  759. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  760. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  761. CMeshBuilder meshBuilder;
  762. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  763. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  764. meshBuilder.TexCoord2f( 0, s0, t0 );
  765. meshBuilder.Position3f( x, y, z );
  766. meshBuilder.AdvanceVertex();
  767. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  768. meshBuilder.TexCoord2f( 0, s1, t0 );
  769. meshBuilder.Position3f( x + w, y, z );
  770. meshBuilder.AdvanceVertex();
  771. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  772. meshBuilder.TexCoord2f( 0, s1, t1 );
  773. meshBuilder.Position3f( x + w, y + h, z );
  774. meshBuilder.AdvanceVertex();
  775. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
  776. meshBuilder.TexCoord2f( 0, s0, t1 );
  777. meshBuilder.Position3f( x, y + h, z );
  778. meshBuilder.AdvanceVertex();
  779. meshBuilder.End();
  780. pMesh->Draw();
  781. }
  782. //-----------------------------------------------------------------------------
  783. // Renders a screen space quad
  784. //-----------------------------------------------------------------------------
  785. void DrawScreenSpaceRectangle( IMaterial *pMaterial,
  786. int nDestX, int nDestY, int nWidth, int nHeight, // Rect to draw into in screen space
  787. float flSrcTextureX0, float flSrcTextureY0, // which texel you want to appear at destx/y
  788. float flSrcTextureX1, float flSrcTextureY1, // which texel you want to appear at destx+width-1, desty+height-1
  789. int nSrcTextureWidth, int nSrcTextureHeight, // needed for fixup
  790. void *pClientRenderable, // Used to pass to the bind proxies
  791. int nXDice, int nYDice, // Amount to tessellate the mesh
  792. float fDepth ) // what Z value to put in the verts (def 0.0)
  793. {
  794. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  795. if ( ( nWidth <= 0 ) || ( nHeight <= 0 ) || ( nSrcTextureWidth <= 0 ) || ( nSrcTextureHeight <= 0 ) )
  796. return;
  797. pRenderContext->MatrixMode( MATERIAL_VIEW );
  798. pRenderContext->PushMatrix();
  799. pRenderContext->LoadIdentity();
  800. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  801. pRenderContext->PushMatrix();
  802. pRenderContext->LoadIdentity();
  803. pRenderContext->Bind( pMaterial, pClientRenderable );
  804. int xSegments = MAX( nXDice, 1);
  805. int ySegments = MAX( nYDice, 1);
  806. CMeshBuilder meshBuilder;
  807. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  808. meshBuilder.Begin( pMesh, MATERIAL_QUADS, xSegments * ySegments );
  809. int nScreenWidth, nScreenHeight;
  810. pRenderContext->GetRenderTargetDimensions( nScreenWidth, nScreenHeight );
  811. // TOGL now automatically accounts for the half pixel offset between D3D9 vs. GL (including OSX unless using the older OSX togl lib. in which case flOffset = 0.0f)
  812. float flOffset = .5f;
  813. float flLeftX = nDestX - flOffset;
  814. float flRightX = nDestX + nWidth - flOffset;
  815. float flTopY = nDestY - flOffset;
  816. float flBottomY = nDestY + nHeight - flOffset;
  817. float flSubrectWidth = flSrcTextureX1 - flSrcTextureX0;
  818. float flSubrectHeight = flSrcTextureY1 - flSrcTextureY0;
  819. float flTexelsPerPixelX = ( nWidth > 1 ) ? flSubrectWidth / ( nWidth - 1 ) : 0.0f;
  820. float flTexelsPerPixelY = ( nHeight > 1 ) ? flSubrectHeight / ( nHeight - 1 ) : 0.0f;
  821. float flLeftU = flSrcTextureX0 + 0.5f - ( 0.5f * flTexelsPerPixelX );
  822. float flRightU = flSrcTextureX1 + 0.5f + ( 0.5f * flTexelsPerPixelX );
  823. float flTopV = flSrcTextureY0 + 0.5f - ( 0.5f * flTexelsPerPixelY );
  824. float flBottomV = flSrcTextureY1 + 0.5f + ( 0.5f * flTexelsPerPixelY );
  825. float flOOTexWidth = 1.0f / nSrcTextureWidth;
  826. float flOOTexHeight = 1.0f / nSrcTextureHeight;
  827. flLeftU *= flOOTexWidth;
  828. flRightU *= flOOTexWidth;
  829. flTopV *= flOOTexHeight;
  830. flBottomV *= flOOTexHeight;
  831. // Get the current viewport size
  832. int vx, vy, vw, vh;
  833. pRenderContext->GetViewport( vx, vy, vw, vh );
  834. // map from screen pixel coords to -1..1
  835. flRightX = FLerp( -1, 1, 0, vw, flRightX );
  836. flLeftX = FLerp( -1, 1, 0, vw, flLeftX );
  837. flTopY = FLerp( 1, -1, 0, vh ,flTopY );
  838. flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
  839. // Dice the quad up...
  840. if ( ( xSegments > 1 ) || ( ySegments > 1 ) )
  841. {
  842. // Screen height and width of a subrect
  843. float flWidth = (flRightX - flLeftX) / (float) xSegments;
  844. float flHeight = (flTopY - flBottomY) / (float) ySegments;
  845. // UV height and width of a subrect
  846. float flUWidth = (flRightU - flLeftU) / (float) xSegments;
  847. float flVHeight = (flBottomV - flTopV) / (float) ySegments;
  848. for ( int x=0; x < xSegments; x++ )
  849. {
  850. for ( int y=0; y < ySegments; y++ )
  851. {
  852. // Top left
  853. meshBuilder.Position3f( flLeftX + (float) x * flWidth, flTopY - (float) y * flHeight, fDepth );
  854. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  855. meshBuilder.TexCoord2f( 0, flLeftU + (float) x * flUWidth, flTopV + (float) y * flVHeight);
  856. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  857. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  858. meshBuilder.AdvanceVertex();
  859. // Top right (x+1)
  860. meshBuilder.Position3f( flLeftX + (float) (x+1) * flWidth, flTopY - (float) y * flHeight, fDepth );
  861. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  862. meshBuilder.TexCoord2f( 0, flLeftU + (float) (x+1) * flUWidth, flTopV + (float) y * flVHeight);
  863. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  864. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  865. meshBuilder.AdvanceVertex();
  866. // Bottom right (x+1), (y+1)
  867. meshBuilder.Position3f( flLeftX + (float) (x+1) * flWidth, flTopY - (float) (y+1) * flHeight, fDepth );
  868. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  869. meshBuilder.TexCoord2f( 0, flLeftU + (float) (x+1) * flUWidth, flTopV + (float)(y+1) * flVHeight);
  870. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  871. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  872. meshBuilder.AdvanceVertex();
  873. // Bottom left (y+1)
  874. meshBuilder.Position3f( flLeftX + (float) x * flWidth, flTopY - (float) (y+1) * flHeight, fDepth );
  875. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  876. meshBuilder.TexCoord2f( 0, flLeftU + (float) x * flUWidth, flTopV + (float)(y+1) * flVHeight);
  877. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  878. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  879. meshBuilder.AdvanceVertex();
  880. }
  881. }
  882. }
  883. else // just one quad
  884. {
  885. for ( int corner=0; corner<4; corner++ )
  886. {
  887. bool bLeft = (corner==0) || (corner==3);
  888. meshBuilder.Position3f( (bLeft) ? flLeftX : flRightX, (corner & 2) ? flBottomY : flTopY, fDepth );
  889. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  890. meshBuilder.TexCoord2f( 0, (bLeft) ? flLeftU : flRightU, (corner & 2) ? flBottomV : flTopV );
  891. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  892. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  893. meshBuilder.AdvanceVertex();
  894. }
  895. }
  896. meshBuilder.End();
  897. pMesh->Draw();
  898. pRenderContext->MatrixMode( MATERIAL_VIEW );
  899. pRenderContext->PopMatrix();
  900. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  901. pRenderContext->PopMatrix();
  902. }
  903. void DrawNDCSpaceUntexturedPolygon( IMaterial *pMaterial, int nVertexCount, Vector2D *pScreenSpaceCoordinates, void *pClientRenderable )
  904. {
  905. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  906. pRenderContext->MatrixMode( MATERIAL_VIEW );
  907. pRenderContext->PushMatrix();
  908. pRenderContext->LoadIdentity();
  909. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  910. pRenderContext->PushMatrix();
  911. pRenderContext->LoadIdentity();
  912. pRenderContext->Bind( pMaterial, pClientRenderable );
  913. CMeshBuilder meshBuilder;
  914. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  915. meshBuilder.Begin( pMesh, MATERIAL_POLYGON, nVertexCount );
  916. for ( int i = 0; i < nVertexCount; ++ i )
  917. {
  918. meshBuilder.Position3f( pScreenSpaceCoordinates[i].x, pScreenSpaceCoordinates[i].y, 0.0f );
  919. meshBuilder.AdvanceVertex();
  920. }
  921. meshBuilder.End();
  922. pMesh->Draw();
  923. pRenderContext->MatrixMode( MATERIAL_VIEW );
  924. pRenderContext->PopMatrix();
  925. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  926. pRenderContext->PopMatrix();
  927. }