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.

768 lines
27 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Utility functions for using debug overlays to visualize information
  4. // in the world. Uses the IVDebugOverlay interface.
  5. //
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "debugoverlay_shared.h"
  9. #include "gamerules.h"
  10. #include "mathlib/mathlib.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. #define MAX_OVERLAY_DIST_SQR 90000000
  14. //-----------------------------------------------------------------------------
  15. // Purpose: Local player on the server or client
  16. //-----------------------------------------------------------------------------
  17. CBasePlayer *GetLocalPlayer( void )
  18. {
  19. #if defined( CLIENT_DLL)
  20. return C_BasePlayer::GetLocalPlayer( 0 ); // Use the first splitscreen player for culling. This avoids a per-call Assert.
  21. #else
  22. return UTIL_GetListenServerHost();
  23. #endif
  24. }
  25. //-----------------------------------------------------------------------------
  26. // Purpose: Debug player by index
  27. //-----------------------------------------------------------------------------
  28. CBasePlayer *GetDebugPlayer( void )
  29. {
  30. #if defined( CLIENT_DLL )
  31. //NOTENOTE: This doesn't necessarily make sense on the client
  32. return GetLocalPlayer();
  33. #else
  34. return UTIL_PlayerByIndex(CBaseEntity::m_nDebugPlayer);
  35. #endif
  36. }
  37. //-----------------------------------------------------------------------------
  38. // Purpose: Draw a capsule
  39. //-----------------------------------------------------------------------------
  40. void NDebugOverlay::Capsule(const Vector &vStart, const Vector &vEnd, const float &flRadius, int r, int g, int b, int a, float flDuration)
  41. {
  42. if ( debugoverlay )
  43. {
  44. debugoverlay->AddCapsuleOverlay( vStart, vEnd, flRadius, r, g, b, a, flDuration );
  45. }
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Purpose: Draw a box with no orientation
  49. //-----------------------------------------------------------------------------
  50. void NDebugOverlay::Box(const Vector &origin, const Vector &mins, const Vector &maxs, int r, int g, int b, int a, float flDuration)
  51. {
  52. BoxAngles( origin, mins, maxs, vec3_angle, r, g, b, a, flDuration );
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Purpose: Draw box oriented to a Vector direction
  56. //-----------------------------------------------------------------------------
  57. void NDebugOverlay::BoxDirection(const Vector &origin, const Vector &mins, const Vector &maxs, const Vector &orientation, int r, int g, int b, int a, float duration)
  58. {
  59. // convert forward vector to angles
  60. QAngle f_angles = vec3_angle;
  61. f_angles.y = UTIL_VecToYaw( orientation );
  62. BoxAngles( origin, mins, maxs, f_angles, r, g, b, a, duration );
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Draw box oriented to a QAngle direction
  66. //-----------------------------------------------------------------------------
  67. void NDebugOverlay::BoxAngles(const Vector &origin, const Vector &mins, const Vector &maxs, const QAngle &angles, int r, int g, int b, int a, float duration)
  68. {
  69. if ( debugoverlay )
  70. {
  71. debugoverlay->AddBoxOverlay( origin, mins, maxs, angles, r, g, b, a, duration );
  72. }
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Purpose: Draws a swept box
  76. //-----------------------------------------------------------------------------
  77. void NDebugOverlay::SweptBox( const Vector& start, const Vector& end, const Vector& mins, const Vector& maxs, const QAngle & angles, int r, int g, int b, int a, float flDuration)
  78. {
  79. if ( debugoverlay )
  80. {
  81. debugoverlay->AddSweptBoxOverlay( start, end, mins, maxs, angles, r, g, b, a, flDuration );
  82. }
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Purpose: Draws a box around an entity
  86. //-----------------------------------------------------------------------------
  87. void NDebugOverlay::EntityBounds( const CBaseEntity *pEntity, int r, int g, int b, int a, float flDuration )
  88. {
  89. const CCollisionProperty *pCollide = pEntity->CollisionProp();
  90. BoxAngles( pCollide->GetCollisionOrigin(), pCollide->OBBMins(), pCollide->OBBMaxs(), pCollide->GetCollisionAngles(), r, g, b, a, flDuration );
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Purpose: Find the players view position and forward position
  94. //-----------------------------------------------------------------------------
  95. static bool GetPlayerView( Vector &vecPosition, Vector &vecForward )
  96. {
  97. CBasePlayer *player = GetLocalPlayer();
  98. if ( !player )
  99. {
  100. vecPosition = vecForward = Vector( 0, 0, 0 );
  101. return false;
  102. }
  103. player->EyePositionAndVectors( &vecPosition, &vecForward, NULL, NULL );
  104. return true;
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose: Draws a line from one position to another
  108. //-----------------------------------------------------------------------------
  109. void NDebugOverlay::Line( const Vector &origin, const Vector &target, int r, int g, int b, bool noDepthTest, float duration )
  110. {
  111. // --------------------------------------------------------------
  112. // Clip the line before sending so we
  113. // don't overflow the client message buffer
  114. // --------------------------------------------------------------
  115. CBasePlayer *player = GetLocalPlayer();
  116. if ( player == NULL )
  117. return;
  118. /*
  119. Assert( GameRules() );
  120. if ( !GameRules()->IsTopDown() )
  121. {
  122. // Clip line that is far away
  123. if (((player->GetAbsOrigin() - origin).LengthSqr() > MAX_OVERLAY_DIST_SQR) &&
  124. ((player->GetAbsOrigin() - target).LengthSqr() > MAX_OVERLAY_DIST_SQR) )
  125. return;
  126. // Clip line that is behind the client
  127. Vector clientForward;
  128. player->EyeVectors( &clientForward );
  129. Vector toOrigin = origin - player->GetAbsOrigin();
  130. Vector toTarget = target - player->GetAbsOrigin();
  131. float dotOrigin = DotProduct(clientForward,toOrigin);
  132. float dotTarget = DotProduct(clientForward,toTarget);
  133. if (dotOrigin < 0 && dotTarget < 0)
  134. return;
  135. }
  136. */
  137. if ( debugoverlay )
  138. {
  139. debugoverlay->AddLineOverlay( origin, target, r, g, b, noDepthTest, duration );
  140. }
  141. }
  142. //-----------------------------------------------------------------------------
  143. // Purpose: Draw triangle
  144. //-----------------------------------------------------------------------------
  145. void NDebugOverlay::Triangle( const Vector &p1, const Vector &p2, const Vector &p3, int r, int g, int b, int a, bool noDepthTest, float duration )
  146. {
  147. Vector clipOrigin, clipForward;
  148. if ( !GetPlayerView( clipOrigin, clipForward ) )
  149. return;
  150. Assert( GameRules() );
  151. if ( !GameRules()->IsTopDown() )
  152. {
  153. // Clip triangles that are far away
  154. Vector to1 = p1 - clipOrigin;
  155. Vector to2 = p2 - clipOrigin;
  156. Vector to3 = p3 - clipOrigin;
  157. if ((to1.LengthSqr() > MAX_OVERLAY_DIST_SQR) &&
  158. (to2.LengthSqr() > MAX_OVERLAY_DIST_SQR) &&
  159. (to3.LengthSqr() > MAX_OVERLAY_DIST_SQR))
  160. {
  161. return;
  162. }
  163. // Clip triangles that are behind the client
  164. float dot1 = DotProduct(clipForward, to1);
  165. float dot2 = DotProduct(clipForward, to2);
  166. float dot3 = DotProduct(clipForward, to3);
  167. if (dot1 < 0 && dot2 < 0 && dot3 < 0)
  168. return;
  169. }
  170. if ( debugoverlay )
  171. {
  172. debugoverlay->AddTriangleOverlay( p1, p2, p3, r, g, b, a, noDepthTest, duration );
  173. }
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Purpose: Draw entity text overlay
  177. //-----------------------------------------------------------------------------
  178. void NDebugOverlay::EntityText( int entityID, int text_offset, const char *text, float duration, int r, int g, int b, int a )
  179. {
  180. if ( debugoverlay )
  181. {
  182. debugoverlay->AddEntityTextOverlay( entityID, text_offset, duration,
  183. (int)clamp(r * 255.f,0.f,255.f), (int)clamp(g * 255.f,0.f,255.f), (int)clamp(b * 255.f,0.f,255.f),
  184. (int)clamp(a * 255.f,0.f,255.f), text );
  185. }
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Purpose: Draw entity text overlay at a specific position
  189. //-----------------------------------------------------------------------------
  190. void NDebugOverlay::EntityTextAtPosition( const Vector &origin, int text_offset, const char *text, float duration, int r, int g, int b, int a )
  191. {
  192. if ( debugoverlay )
  193. {
  194. debugoverlay->AddTextOverlayRGB( origin, text_offset, duration, r, g, b, a, "%s", text );
  195. }
  196. }
  197. //-----------------------------------------------------------------------------
  198. // Purpose: Add grid overlay
  199. //-----------------------------------------------------------------------------
  200. void NDebugOverlay::Grid( const Vector &vPosition )
  201. {
  202. if ( debugoverlay )
  203. {
  204. debugoverlay->AddGridOverlay( vPosition );
  205. }
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Purpose: Draw debug text at a position
  209. //-----------------------------------------------------------------------------
  210. void NDebugOverlay::Text( const Vector &origin, const char *text, bool bViewCheck, float duration )
  211. {
  212. Vector clipOrigin, clipForward;
  213. if ( !GetPlayerView( clipOrigin, clipForward ) )
  214. return;
  215. Assert( GameRules() );
  216. if ( !GameRules()->IsTopDown() )
  217. {
  218. // Clip text that is far away
  219. if ( ( clipOrigin - origin ).LengthSqr() > MAX_OVERLAY_DIST_SQR )
  220. return;
  221. // Clip text that is behind the client
  222. Vector toText = origin - clipOrigin;
  223. float dotPr = DotProduct( clipForward, toText );
  224. if (dotPr < 0)
  225. return;
  226. // Clip text that is obscured
  227. if (bViewCheck)
  228. {
  229. trace_t tr;
  230. UTIL_TraceLine( clipOrigin, origin, MASK_OPAQUE, NULL, COLLISION_GROUP_NONE, &tr);
  231. if ((tr.endpos - origin).Length() > 10)
  232. return;
  233. }
  234. }
  235. if ( debugoverlay )
  236. {
  237. debugoverlay->AddTextOverlay( origin, duration, "%s", text );
  238. }
  239. }
  240. //-----------------------------------------------------------------------------
  241. // Purpose: Add debug overlay text with screen position
  242. //-----------------------------------------------------------------------------
  243. void NDebugOverlay::ScreenText( float flXpos, float flYpos, const char *text, int r, int g, int b, int a, float duration )
  244. {
  245. if ( debugoverlay )
  246. {
  247. debugoverlay->AddScreenTextOverlay( flXpos, flYpos, duration, r, g, b, a, text );
  248. }
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose: Draw a colored 3D cross of the given hull size at the given position
  252. //-----------------------------------------------------------------------------
  253. void NDebugOverlay::Cross3D(const Vector &position, const Vector &mins, const Vector &maxs, int r, int g, int b, bool noDepthTest, float fDuration )
  254. {
  255. Vector start = mins + position;
  256. Vector end = maxs + position;
  257. Line(start,end, r, g, b, noDepthTest,fDuration);
  258. start.x += (maxs.x - mins.x);
  259. end.x -= (maxs.x - mins.x);
  260. Line(start,end, r, g, b, noDepthTest,fDuration);
  261. start.y += (maxs.y - mins.y);
  262. end.y -= (maxs.y - mins.y);
  263. Line(start,end, r, g, b, noDepthTest,fDuration);
  264. start.x -= (maxs.x - mins.x);
  265. end.x += (maxs.x - mins.x);
  266. Line(start,end, r, g, b, noDepthTest,fDuration);
  267. }
  268. //-----------------------------------------------------------------------------
  269. // Purpose: Draw a colored 3D cross of the given size at the given position
  270. //-----------------------------------------------------------------------------
  271. void NDebugOverlay::Cross3D(const Vector &position, float size, int r, int g, int b, bool noDepthTest, float flDuration )
  272. {
  273. Line( position + Vector(size,0,0), position - Vector(size,0,0), r, g, b, noDepthTest, flDuration );
  274. Line( position + Vector(0,size,0), position - Vector(0,size,0), r, g, b, noDepthTest, flDuration );
  275. Line( position + Vector(0,0,size), position - Vector(0,0,size), r, g, b, noDepthTest, flDuration );
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Purpose: Draw an oriented, colored 3D cross of the given size at the given position (via a vector)
  279. //-----------------------------------------------------------------------------
  280. void NDebugOverlay::Cross3DOriented( const Vector &position, const QAngle &angles, float size, int r, int g, int b, bool noDepthTest, float flDuration )
  281. {
  282. Vector forward, right, up;
  283. AngleVectors( angles, &forward, &right, &up );
  284. forward *= size;
  285. right *= size;
  286. up *= size;
  287. Line( position + right, position - right, r, g, b, noDepthTest, flDuration );
  288. Line( position + forward, position - forward, r, g, b, noDepthTest, flDuration );
  289. Line( position + up, position - up, r, g, b, noDepthTest, flDuration );
  290. }
  291. //-----------------------------------------------------------------------------
  292. // Purpose: Draw an oriented, colored 3D cross of the given size at the given position (via a matrix)
  293. //-----------------------------------------------------------------------------
  294. void NDebugOverlay::Cross3DOriented( const matrix3x4_t &m, float size, int c, bool noDepthTest, float flDuration )
  295. {
  296. Vector forward, left, up, position;
  297. MatrixGetColumn( m, 0, forward );
  298. MatrixGetColumn( m, 1, left );
  299. MatrixGetColumn( m, 2, up );
  300. MatrixGetColumn( m, 3, position );
  301. forward *= size;
  302. left *= size;
  303. up *= size;
  304. Line( position + left, position - left, 0, c, 0, noDepthTest, flDuration );
  305. Line( position + forward, position - forward, c, 0, 0, noDepthTest, flDuration );
  306. Line( position + up, position - up, 0, 0, c, noDepthTest, flDuration );
  307. }
  308. //--------------------------------------------------------------------------------
  309. // Purpose : Draw tick marks between start and end position of the given distance
  310. // with text every tickTextDist steps apart.
  311. //--------------------------------------------------------------------------------
  312. void NDebugOverlay::DrawTickMarkedLine(const Vector &startPos, const Vector &endPos, float tickDist, int tickTextDist, int r, int g, int b, bool noDepthTest, float duration )
  313. {
  314. CBasePlayer* pPlayer = GetDebugPlayer();
  315. if ( !pPlayer )
  316. return;
  317. Vector lineDir = (endPos - startPos);
  318. float lineDist = VectorNormalize( lineDir );
  319. int numTicks = lineDist/tickDist;
  320. Vector vBodyDir;
  321. #if defined( CLIENT_DLL )
  322. AngleVectors( pPlayer->LocalEyeAngles(), &vBodyDir );
  323. #else
  324. vBodyDir = pPlayer->BodyDirection2D( );
  325. #endif
  326. Vector upVec = 4*vBodyDir;
  327. Vector sideDir;
  328. Vector tickPos = startPos;
  329. int tickTextCnt = 0;
  330. CrossProduct(lineDir, upVec, sideDir);
  331. // First draw the line
  332. Line(startPos, endPos, r,g,b,noDepthTest,duration);
  333. // Now draw the ticks
  334. for (int i=0;i<numTicks+1;i++)
  335. {
  336. // Draw tick mark
  337. Vector tickLeft = tickPos - sideDir;
  338. Vector tickRight = tickPos + sideDir;
  339. // Draw tick mark text
  340. if (tickTextCnt == tickTextDist)
  341. {
  342. char text[25];
  343. Q_snprintf(text,sizeof(text),"%i",i);
  344. Vector textPos = tickLeft + Vector(0,0,8);
  345. Line(tickLeft, tickRight, 255,255,255,noDepthTest,duration);
  346. Text( textPos, text, true, 0 );
  347. tickTextCnt = 0;
  348. }
  349. else
  350. {
  351. Line(tickLeft, tickRight, r,g,b,noDepthTest,duration);
  352. }
  353. tickTextCnt++;
  354. tickPos = tickPos + (tickDist * lineDir);
  355. }
  356. }
  357. //------------------------------------------------------------------------------
  358. // Purpose : Draw crosshair on ground where player is looking
  359. //------------------------------------------------------------------------------
  360. void NDebugOverlay::DrawGroundCrossHairOverlay( void )
  361. {
  362. CBasePlayer* pPlayer = GetDebugPlayer();
  363. if ( !pPlayer )
  364. return;
  365. // Trace a line to where player is looking
  366. Vector vForward;
  367. Vector vSource = pPlayer->EyePosition();
  368. pPlayer->EyeVectors( &vForward );
  369. trace_t tr;
  370. UTIL_TraceLine ( vSource, vSource + vForward * 2048, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr);
  371. float dotPr = DotProduct(Vector(0,0,1),tr.plane.normal);
  372. if (tr.fraction != 1.0 && dotPr > 0.5)
  373. {
  374. tr.endpos.z += 1;
  375. float scale = 6;
  376. Vector startPos = tr.endpos + Vector (-scale,0,0);
  377. Vector endPos = tr.endpos + Vector ( scale,0,0);
  378. Line(startPos, endPos, 255, 0, 0,false,0);
  379. startPos = tr.endpos + Vector (0,-scale,0);
  380. endPos = tr.endpos + Vector (0, scale,0);
  381. Line(startPos, endPos, 255, 0, 0,false,0);
  382. }
  383. }
  384. //--------------------------------------------------------------------------------
  385. // Purpose : Draw a horizontal arrow pointing in the specified direction
  386. //--------------------------------------------------------------------------------
  387. void NDebugOverlay::HorzArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration)
  388. {
  389. Vector lineDir = (endPos - startPos);
  390. VectorNormalize( lineDir );
  391. Vector upVec = Vector( 0, 0, 1 );
  392. Vector sideDir;
  393. float radius = width / 2.0;
  394. CrossProduct(lineDir, upVec, sideDir);
  395. Vector p1 = startPos - sideDir * radius;
  396. Vector p2 = endPos - lineDir * width - sideDir * radius;
  397. Vector p3 = endPos - lineDir * width - sideDir * width;
  398. Vector p4 = endPos;
  399. Vector p5 = endPos - lineDir * width + sideDir * width;
  400. Vector p6 = endPos - lineDir * width + sideDir * radius;
  401. Vector p7 = startPos + sideDir * radius;
  402. // Outline the arrow
  403. Line(p1, p2, r,g,b,noDepthTest,flDuration);
  404. Line(p2, p3, r,g,b,noDepthTest,flDuration);
  405. Line(p3, p4, r,g,b,noDepthTest,flDuration);
  406. Line(p4, p5, r,g,b,noDepthTest,flDuration);
  407. Line(p5, p6, r,g,b,noDepthTest,flDuration);
  408. Line(p6, p7, r,g,b,noDepthTest,flDuration);
  409. if ( a > 0 )
  410. {
  411. // Fill us in with triangles
  412. Triangle( p5, p4, p3, r, g, b, a, noDepthTest, flDuration ); // Tip
  413. Triangle( p1, p7, p6, r, g, b, a, noDepthTest, flDuration ); // Shaft
  414. Triangle( p6, p2, p1, r, g, b, a, noDepthTest, flDuration );
  415. // And backfaces
  416. Triangle( p3, p4, p5, r, g, b, a, noDepthTest, flDuration ); // Tip
  417. Triangle( p6, p7, p1, r, g, b, a, noDepthTest, flDuration ); // Shaft
  418. Triangle( p1, p2, p6, r, g, b, a, noDepthTest, flDuration );
  419. }
  420. }
  421. //-----------------------------------------------------------------------------
  422. // Purpose : Draw a horizontal arrow pointing in the specified direction by yaw value
  423. //-----------------------------------------------------------------------------
  424. void NDebugOverlay::YawArrow( const Vector &startPos, float yaw, float length, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration)
  425. {
  426. Vector forward = UTIL_YawToVector( yaw );
  427. HorzArrow( startPos, startPos + forward * length, width, r, g, b, a, noDepthTest, flDuration );
  428. }
  429. //--------------------------------------------------------------------------------
  430. // Purpose : Draw a vertical arrow at a position
  431. //--------------------------------------------------------------------------------
  432. void NDebugOverlay::VertArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration)
  433. {
  434. Vector lineDir = (endPos - startPos);
  435. VectorNormalize( lineDir );
  436. Vector upVec;
  437. Vector sideDir;
  438. float radius = width / 2.0;
  439. VectorVectors( lineDir, sideDir, upVec );
  440. Vector p1 = startPos - upVec * radius;
  441. Vector p2 = endPos - lineDir * width - upVec * radius;
  442. Vector p3 = endPos - lineDir * width - upVec * width;
  443. Vector p4 = endPos;
  444. Vector p5 = endPos - lineDir * width + upVec * width;
  445. Vector p6 = endPos - lineDir * width + upVec * radius;
  446. Vector p7 = startPos + upVec * radius;
  447. // Outline the arrow
  448. Line(p1, p2, r,g,b,noDepthTest,flDuration);
  449. Line(p2, p3, r,g,b,noDepthTest,flDuration);
  450. Line(p3, p4, r,g,b,noDepthTest,flDuration);
  451. Line(p4, p5, r,g,b,noDepthTest,flDuration);
  452. Line(p5, p6, r,g,b,noDepthTest,flDuration);
  453. Line(p6, p7, r,g,b,noDepthTest,flDuration);
  454. if ( a > 0 )
  455. {
  456. // Fill us in with triangles
  457. Triangle( p5, p4, p3, r, g, b, a, noDepthTest, flDuration ); // Tip
  458. Triangle( p1, p7, p6, r, g, b, a, noDepthTest, flDuration ); // Shaft
  459. Triangle( p6, p2, p1, r, g, b, a, noDepthTest, flDuration );
  460. // And backfaces
  461. Triangle( p3, p4, p5, r, g, b, a, noDepthTest, flDuration ); // Tip
  462. Triangle( p6, p7, p1, r, g, b, a, noDepthTest, flDuration ); // Shaft
  463. Triangle( p1, p2, p6, r, g, b, a, noDepthTest, flDuration );
  464. }
  465. }
  466. //-----------------------------------------------------------------------------
  467. // Purpose: Draw an axis
  468. //-----------------------------------------------------------------------------
  469. void NDebugOverlay::Axis( const Vector &position, const QAngle &angles, float size, bool noDepthTest, float flDuration )
  470. {
  471. Vector xvec, yvec, zvec;
  472. AngleVectors( angles, &xvec, &yvec, &zvec );
  473. xvec = position + (size * xvec);
  474. yvec = position - (size * yvec); // Left is positive
  475. zvec = position + (size * zvec);
  476. Line( position, xvec, 255, 0, 0, noDepthTest, flDuration );
  477. Line( position, yvec, 0, 255, 0, noDepthTest, flDuration );
  478. Line( position, zvec, 0, 0, 255, noDepthTest, flDuration );
  479. }
  480. //-----------------------------------------------------------------------------
  481. // Purpose: Draw circles to suggest a sphere
  482. //-----------------------------------------------------------------------------
  483. void NDebugOverlay::Sphere( const Vector &center, float radius, int r, int g, int b, bool noDepthTest, float flDuration )
  484. {
  485. Vector edge, lastEdge;
  486. float axisSize = radius;
  487. Line( center + Vector( 0, 0, -axisSize ), center + Vector( 0, 0, axisSize ), r, g, b, noDepthTest, flDuration );
  488. Line( center + Vector( 0, -axisSize, 0 ), center + Vector( 0, axisSize, 0 ), r, g, b, noDepthTest, flDuration );
  489. Line( center + Vector( -axisSize, 0, 0 ), center + Vector( axisSize, 0, 0 ), r, g, b, noDepthTest, flDuration );
  490. lastEdge = Vector( radius + center.x, center.y, center.z );
  491. float angle;
  492. for( angle=0.0f; angle <= 360.0f; angle += 22.5f )
  493. {
  494. edge.x = radius * cosf( angle / 180.0f * M_PI ) + center.x;
  495. edge.y = center.y;
  496. edge.z = radius * sinf( angle / 180.0f * M_PI ) + center.z;
  497. Line( edge, lastEdge, r, g, b, noDepthTest, flDuration );
  498. lastEdge = edge;
  499. }
  500. lastEdge = Vector( center.x, radius + center.y, center.z );
  501. for( angle=0.0f; angle <= 360.0f; angle += 22.5f )
  502. {
  503. edge.x = center.x;
  504. edge.y = radius * cosf( angle / 180.0f * M_PI ) + center.y;
  505. edge.z = radius * sinf( angle / 180.0f * M_PI ) + center.z;
  506. Line( edge, lastEdge, r, g, b, noDepthTest, flDuration );
  507. lastEdge = edge;
  508. }
  509. lastEdge = Vector( center.x, radius + center.y, center.z );
  510. for( angle=0.0f; angle <= 360.0f; angle += 22.5f )
  511. {
  512. edge.x = radius * cosf( angle / 180.0f * M_PI ) + center.x;
  513. edge.y = radius * sinf( angle / 180.0f * M_PI ) + center.y;
  514. edge.z = center.z;
  515. Line( edge, lastEdge, r, g, b, noDepthTest, flDuration );
  516. lastEdge = edge;
  517. }
  518. }
  519. //-----------------------------------------------------------------------------
  520. // Purpose: Draw a circle whose center is at a position, facing the camera
  521. //-----------------------------------------------------------------------------
  522. void NDebugOverlay::Circle( const Vector &position, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration )
  523. {
  524. CBasePlayer *player = GetLocalPlayer();
  525. if ( player == NULL )
  526. return;
  527. Vector clientForward;
  528. player->EyeVectors( &clientForward );
  529. QAngle vecAngles;
  530. VectorAngles( clientForward, vecAngles );
  531. Circle( position, vecAngles, radius, r, g, b, a, bNoDepthTest, flDuration );
  532. }
  533. //-----------------------------------------------------------------------------
  534. // Purpose: Draw a circle whose center is at a position and is facing a specified direction
  535. //-----------------------------------------------------------------------------
  536. void NDebugOverlay::Circle( const Vector &position, const QAngle &angles, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration )
  537. {
  538. // Setup our transform matrix
  539. matrix3x4_t xform;
  540. AngleMatrix( angles, position, xform );
  541. Vector xAxis, yAxis;
  542. // default draws circle in the y/z plane
  543. MatrixGetColumn( xform, 2, xAxis );
  544. MatrixGetColumn( xform, 1, yAxis );
  545. Circle( position, xAxis, yAxis, radius, r, g, b, a, bNoDepthTest, flDuration );
  546. }
  547. void NDebugOverlay::Circle( const Vector &position, const Vector &xAxis, const Vector &yAxis, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration )
  548. {
  549. const unsigned int nSegments = 16;
  550. const float flRadStep = (M_PI*2.0f) / (float) nSegments;
  551. Vector vecLastPosition;
  552. // Find our first position
  553. // Retained for triangle fanning
  554. Vector vecStart = position + xAxis * radius;
  555. Vector vecPosition = vecStart;
  556. // Draw out each segment (fanning triangles if we have an alpha amount)
  557. for ( int i = 1; i <= nSegments; i++ )
  558. {
  559. // Store off our last position
  560. vecLastPosition = vecPosition;
  561. // Calculate the new one
  562. float flSin, flCos;
  563. SinCos( flRadStep*i, &flSin, &flCos );
  564. vecPosition = position + (xAxis * flCos * radius) + (yAxis * flSin * radius);
  565. // Draw the line
  566. Line( vecLastPosition, vecPosition, r, g, b, bNoDepthTest, flDuration );
  567. // If we have an alpha value, then draw the fan
  568. if ( a && i > 1 )
  569. {
  570. debugoverlay->AddTriangleOverlay( vecStart, vecLastPosition, vecPosition, r, g, b, a, bNoDepthTest, flDuration );
  571. }
  572. }
  573. }
  574. void NDebugOverlay::Sphere( const Vector &position, const QAngle &angles, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration )
  575. {
  576. // Setup our transform matrix
  577. matrix3x4_t xform;
  578. AngleMatrix( angles, position, xform );
  579. Vector xAxis, yAxis, zAxis;
  580. // default draws circle in the y/z plane
  581. MatrixGetColumn( xform, 0, xAxis );
  582. MatrixGetColumn( xform, 1, yAxis );
  583. MatrixGetColumn( xform, 2, zAxis );
  584. Circle( position, xAxis, yAxis, radius, r, g, b, a, bNoDepthTest, flDuration ); // xy plane
  585. Circle( position, yAxis, zAxis, radius, r, g, b, a, bNoDepthTest, flDuration ); // yz plane
  586. Circle( position, xAxis, zAxis, radius, r, g, b, a, bNoDepthTest, flDuration ); // xz plane
  587. }
  588. #define NUM_CONE_LINES 8
  589. #define NUM_CONE_CIRCLES 3
  590. void NDebugOverlay::Cone( const Vector & position, const Vector & axis, float angleRadians, float length, int r, int g, int b, int a, bool bNoDepthTest, float flDuration )
  591. {
  592. //draw lines down the length of the cone.
  593. float radiusStep = ( M_PI * 2.0f ) / NUM_CONE_LINES;
  594. float sinHalfAngle = sinf( angleRadians * 0.5f );
  595. float finalRadius = sinHalfAngle * length;
  596. QAngle vecAngles;
  597. VectorAngles( axis, vecAngles );
  598. matrix3x4_t xform;
  599. AngleMatrix( vecAngles, position, xform );
  600. Vector sideAxis, upAxis;
  601. // default draws circle in the y/z plane
  602. MatrixGetColumn( xform, 2, sideAxis );
  603. MatrixGetColumn( xform, 1, upAxis );
  604. Vector coneEnd = position + ( axis * length );
  605. for( int lineNum = 0; lineNum < NUM_CONE_LINES; ++lineNum )
  606. {
  607. float flSin, flCos;
  608. SinCos( radiusStep * lineNum, & flSin, & flCos );
  609. Vector circlePos = coneEnd + ( sideAxis * flCos * finalRadius ) + ( upAxis * flSin * finalRadius );
  610. Line( position, circlePos, r, g, b, bNoDepthTest, flDuration );
  611. }
  612. // draw three cicles around the cone.
  613. float lengthStep = length / NUM_CONE_CIRCLES;
  614. for( int circNum = 0; circNum < NUM_CONE_CIRCLES; ++circNum )
  615. {
  616. float segLength = lengthStep * ( circNum + 1 );
  617. Vector circPos = position + ( axis * segLength );
  618. float circRad = sinHalfAngle * segLength;
  619. Circle( circPos, sideAxis, upAxis, circRad, r, g, b, 0, bNoDepthTest, flDuration );
  620. }
  621. }
  622. //-----------------------------------------------------------------------------
  623. // Purpose: Draw a cross whose center is at a position, facing the camera
  624. //-----------------------------------------------------------------------------
  625. void NDebugOverlay::Cross( const Vector &position, float radius, int r, int g, int b, bool bNoDepthTest, float flDuration )
  626. {
  627. CBasePlayer *player = GetLocalPlayer();
  628. if ( player == NULL )
  629. return;
  630. Vector clientForward;
  631. Vector clientRight;
  632. Vector clientUp;
  633. player->EyeVectors( &clientForward, &clientRight, &clientUp );
  634. Line( position - radius * clientRight, position + radius * clientRight, r, g, b, bNoDepthTest, flDuration );
  635. Line( position - radius * clientUp, position + radius * clientUp, r, g, b, bNoDepthTest, flDuration );
  636. }
  637. void NDebugOverlay::PurgeTextOverlays()
  638. {
  639. if ( debugoverlay )
  640. {
  641. debugoverlay->PurgeTextOverlays();
  642. }
  643. }