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.

467 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
  9. #include "iscratchpad3d.h"
  10. #include "mathlib/mathlib.h"
  11. #include "ScratchPadUtils.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. // --------------------------------------------------------------------------------------------------------------------- //
  15. // CScratchPadGraph implementation.
  16. // --------------------------------------------------------------------------------------------------------------------- //
  17. CScratchPadGraph::CScratchPadGraph()
  18. {
  19. m_pPad = NULL;
  20. }
  21. void CScratchPadGraph::Init(
  22. IScratchPad3D *pPad,
  23. Vector vTimeAxis,
  24. float flInchesPerSecond,
  25. Vector vTimeLineColor,
  26. float flTimeOrigin,
  27. float flTimeLabelEveryNSeconds,
  28. Vector vValueAxis,
  29. float flInchesPerValue,
  30. Vector vValueLineColor,
  31. float flValueOrigin
  32. )
  33. {
  34. m_pPad = pPad;
  35. m_vTimeAxis = vTimeAxis;
  36. m_flInchesPerSecond = flInchesPerSecond;
  37. m_vValueAxis = vValueAxis;
  38. m_flInchesPerValue = flInchesPerValue;
  39. m_flTimeLabelEveryNSeconds = flTimeLabelEveryNSeconds;
  40. m_vTimeLineColor = vTimeLineColor;
  41. m_vValueLineColor = vValueLineColor;
  42. m_flTimeOrigin = flTimeOrigin;
  43. m_flValueOrigin = flValueOrigin;
  44. m_nTimeLabelsDrawn = 0;
  45. m_flHighestTime = flTimeOrigin;
  46. m_flHighestValue = flValueOrigin;
  47. }
  48. bool CScratchPadGraph::IsInitted() const
  49. {
  50. return m_pPad != NULL;
  51. }
  52. CScratchPadGraph::LineID CScratchPadGraph::AddLine( Vector vColor )
  53. {
  54. CScratchPadGraph::CLineInfo info;
  55. info.m_bFirst = true;
  56. info.m_vColor = vColor;
  57. return m_LineInfos.AddToTail( info );
  58. }
  59. void CScratchPadGraph::AddSample( LineID iLine, float flTime, float flValue )
  60. {
  61. CScratchPadGraph::CLineInfo *pInfo = &m_LineInfos[iLine];
  62. UpdateTicksAndStuff( flTime, flValue );
  63. if ( !pInfo->m_bFirst )
  64. {
  65. // Draw a line from the last value to the current one.
  66. Vector vStart = GetSamplePosition( pInfo->m_flLastTime, pInfo->m_flLastValue );
  67. Vector vEnd = GetSamplePosition( flTime, flValue );
  68. m_pPad->DrawLine(
  69. CSPVert( vStart, pInfo->m_vColor ),
  70. CSPVert( vEnd, pInfo->m_vColor )
  71. );
  72. }
  73. pInfo->m_flLastTime = flTime;
  74. pInfo->m_flLastValue = flValue;
  75. pInfo->m_bFirst = false;
  76. }
  77. void CScratchPadGraph::AddVerticalLine( float flTime, float flMinValue, float flMaxValue, const CSPColor &vColor )
  78. {
  79. Vector v1 = GetSamplePosition( flTime, flMinValue );
  80. Vector v2 = GetSamplePosition( flTime, flMaxValue );
  81. m_pPad->DrawLine(
  82. CSPVert( v1, vColor ),
  83. CSPVert( v2, vColor ) );
  84. }
  85. void CScratchPadGraph::UpdateTicksAndStuff( float flTime, float flValue )
  86. {
  87. if ( flTime > m_flHighestTime )
  88. {
  89. // Update the left part of the time axis.
  90. Vector vStart = GetSamplePosition( m_flHighestTime, m_flValueOrigin );
  91. Vector vEnd = GetSamplePosition( flTime, m_flValueOrigin );
  92. m_pPad->DrawLine(
  93. CSPVert( vStart, m_vTimeLineColor ),
  94. CSPVert( vEnd, m_vTimeLineColor )
  95. );
  96. m_flHighestTime = flTime;
  97. }
  98. if ( flValue > m_flHighestValue )
  99. {
  100. // Update the left part of the time axis.
  101. Vector vStart = GetSamplePosition( m_flTimeOrigin, m_flHighestValue );
  102. Vector vEnd = GetSamplePosition( m_flTimeOrigin, flValue );
  103. m_pPad->DrawLine(
  104. CSPVert( vStart, m_vValueLineColor ),
  105. CSPVert( vEnd, m_vValueLineColor )
  106. );
  107. // Extend the lines attached to the time labels.
  108. for ( int i=0; i < m_nTimeLabelsDrawn; i++ )
  109. {
  110. float flTimeLabel = m_flTimeOrigin + m_nTimeLabelsDrawn * m_flTimeLabelEveryNSeconds;
  111. m_pPad->DrawLine(
  112. CSPVert((const Vector&) GetSamplePosition( flTimeLabel, m_flHighestValue )),
  113. CSPVert((const Vector&) GetSamplePosition( flTimeLabel, flValue ) )
  114. );
  115. }
  116. m_flHighestValue = flValue;
  117. }
  118. // More text labels?
  119. int iHighestTextLabel = (int)ceil( (flTime - m_flTimeOrigin) / m_flTimeLabelEveryNSeconds + 0.5f );
  120. while ( m_nTimeLabelsDrawn < iHighestTextLabel )
  121. {
  122. CTextParams params;
  123. float flTimeLabel = m_flTimeOrigin + m_nTimeLabelsDrawn * m_flTimeLabelEveryNSeconds;
  124. params.m_bSolidBackground = true;
  125. params.m_vPos = GetSamplePosition( flTimeLabel, m_flValueOrigin-5 );
  126. params.m_bTwoSided = true;
  127. char str[512];
  128. Q_snprintf( str, sizeof( str ), "time: %.2f", flTimeLabel );
  129. m_pPad->DrawText( str, params );
  130. // Now draw the vertical line for the value..
  131. m_pPad->DrawLine(
  132. CSPVert( (const Vector&)GetSamplePosition( flTimeLabel, m_flValueOrigin ) ),
  133. CSPVert( (const Vector&)GetSamplePosition( flTimeLabel, m_flHighestValue ) )
  134. );
  135. m_nTimeLabelsDrawn++;
  136. }
  137. }
  138. Vector CScratchPadGraph::GetSamplePosition( float flTime, float flValue )
  139. {
  140. Vector vRet =
  141. m_vTimeAxis * ((flTime - m_flTimeOrigin) * m_flInchesPerSecond) +
  142. m_vValueAxis * ((flValue - m_flValueOrigin) * m_flInchesPerValue);
  143. return vRet;
  144. }
  145. // --------------------------------------------------------------------------------------------------------------------- //
  146. // Global functions.
  147. // --------------------------------------------------------------------------------------------------------------------- //
  148. void ScratchPad_DrawLitCone(
  149. IScratchPad3D *pPad,
  150. const Vector &vBaseCenter,
  151. const Vector &vTip,
  152. const Vector &vBrightColor,
  153. const Vector &vDarkColor,
  154. const Vector &vLightDir,
  155. float baseWidth,
  156. int nSegments )
  157. {
  158. // Make orthogonal vectors.
  159. Vector vDir = vTip - vBaseCenter;
  160. VectorNormalize( vDir );
  161. Vector vRight, vUp;
  162. VectorVectors( vDir, vRight, vUp );
  163. vRight *= baseWidth;
  164. vUp *= baseWidth;
  165. // Setup the top and bottom caps.
  166. CSPVertList bottomCap, tri;
  167. bottomCap.m_Verts.SetSize( nSegments );
  168. tri.m_Verts.SetSize( 3 );
  169. float flDot = -vLightDir.Dot( vDir );
  170. Vector topColor, bottomColor;
  171. VectorLerp( vDarkColor, vBrightColor, RemapVal( -flDot, -1, 1, 0, 1 ), bottomColor );
  172. // Draw each quad.
  173. Vector vPrevBottom = vBaseCenter + vRight;
  174. for ( int i=0; i < nSegments; i++ )
  175. {
  176. float flAngle = (float)(i+1) * M_PI * 2.0 / nSegments;
  177. Vector vOffset = vRight * cos( flAngle ) + vUp * sin( flAngle );
  178. Vector vCurBottom = vBaseCenter + vOffset;
  179. const Vector &v1 = vTip;
  180. const Vector &v2 = vPrevBottom;
  181. const Vector &v3 = vCurBottom;
  182. Vector vFaceNormal = (v2 - v1).Cross( v3 - v1 );
  183. VectorNormalize( vFaceNormal );
  184. // Now light it.
  185. flDot = -vLightDir.Dot( vFaceNormal );
  186. Vector vColor;
  187. VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), vColor );
  188. // Draw the quad.
  189. tri.m_Verts[0] = CSPVert( v1, vColor );
  190. tri.m_Verts[1] = CSPVert( v2, vColor );
  191. tri.m_Verts[2] = CSPVert( v3, vColor );
  192. pPad->DrawPolygon( tri );
  193. bottomCap.m_Verts[i] = CSPVert( vCurBottom, bottomColor );
  194. }
  195. pPad->DrawPolygon( bottomCap );
  196. }
  197. void ScratchPad_DrawLitCylinder(
  198. IScratchPad3D *pPad,
  199. const Vector &v1,
  200. const Vector &v2,
  201. const Vector &vBrightColor,
  202. const Vector &vDarkColor,
  203. const Vector &vLightDir,
  204. float width,
  205. int nSegments )
  206. {
  207. // Make orthogonal vectors.
  208. Vector vDir = v2 - v1;
  209. VectorNormalize( vDir );
  210. Vector vRight, vUp;
  211. VectorVectors( vDir, vRight, vUp );
  212. vRight *= width;
  213. vUp *= width;
  214. // Setup the top and bottom caps.
  215. CSPVertList topCap, bottomCap, quad;
  216. topCap.m_Verts.SetSize( nSegments );
  217. bottomCap.m_Verts.SetSize( nSegments );
  218. quad.m_Verts.SetSize( 4 );
  219. float flDot = -vLightDir.Dot( vDir );
  220. Vector topColor, bottomColor;
  221. VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), topColor );
  222. VectorLerp( vDarkColor, vBrightColor, RemapVal( -flDot, -1, 1, 0, 1 ), bottomColor );
  223. // Draw each quad.
  224. Vector vPrevTop = v1 + vRight;
  225. Vector vPrevBottom = v2 + vRight;
  226. for ( int i=0; i < nSegments; i++ )
  227. {
  228. float flAngle = (float)(i+1) * M_PI * 2.0 / nSegments;
  229. Vector vOffset = vRight * cos( flAngle ) + vUp * sin( flAngle );
  230. Vector vCurTop = v1 + vOffset;
  231. Vector vCurBottom = v2 + vOffset;
  232. // Now light it.
  233. VectorNormalize( vOffset );
  234. flDot = -vLightDir.Dot( vOffset );
  235. Vector vColor;
  236. VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), vColor );
  237. // Draw the quad.
  238. quad.m_Verts[0] = CSPVert( vPrevTop, vColor );
  239. quad.m_Verts[1] = CSPVert( vPrevBottom, vColor );
  240. quad.m_Verts[2] = CSPVert( vCurBottom, vColor );
  241. quad.m_Verts[3] = CSPVert( vCurTop, vColor );
  242. pPad->DrawPolygon( quad );
  243. topCap.m_Verts[i] = CSPVert( vCurTop, topColor );
  244. bottomCap.m_Verts[i] = CSPVert( vCurBottom, bottomColor );
  245. }
  246. pPad->DrawPolygon( topCap );
  247. pPad->DrawPolygon( bottomCap );
  248. }
  249. void ScratchPad_DrawArrow(
  250. IScratchPad3D *pPad,
  251. const Vector &vPos,
  252. const Vector &vDirection,
  253. const Vector &vColor,
  254. float flLength,
  255. float flLineWidth,
  256. float flHeadWidth,
  257. int nCylinderSegments,
  258. int nHeadSegments,
  259. float flArrowHeadPercentage
  260. )
  261. {
  262. Vector vNormDir = vDirection;
  263. VectorNormalize( vNormDir );
  264. Vector vConeBase = vPos + vNormDir * (flLength * ( 1 - flArrowHeadPercentage ) );
  265. Vector vConeEnd = vPos + vNormDir * flLength;
  266. Vector vLightDir( -1, -1, -1 );
  267. VectorNormalize( vLightDir ); // could precalculate this
  268. pPad->SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Solid );
  269. pPad->SetRenderState( IScratchPad3D::RS_ZRead, true );
  270. ScratchPad_DrawLitCylinder( pPad, vPos, vConeBase, vColor, vColor*0.25f, vLightDir, flLineWidth, nCylinderSegments );
  271. ScratchPad_DrawLitCone( pPad, vConeBase, vConeEnd, vColor, vColor*0.25f, vLightDir, flHeadWidth, nHeadSegments );
  272. }
  273. void ScratchPad_DrawArrowSimple(
  274. IScratchPad3D *pPad,
  275. const Vector &vPos,
  276. const Vector &vDirection,
  277. const Vector &vColor,
  278. float flLength )
  279. {
  280. ScratchPad_DrawArrow(
  281. pPad,
  282. vPos,
  283. vDirection,
  284. vColor,
  285. flLength,
  286. flLength * 1.0/15,
  287. flLength * 3.0/15,
  288. 4,
  289. 4 );
  290. }
  291. void ScratchPad_DrawSphere(
  292. IScratchPad3D *pPad,
  293. const Vector &vCenter,
  294. float flRadius,
  295. const Vector &vColor,
  296. int nSubDivs )
  297. {
  298. CUtlVector<Vector> prevPoints;
  299. prevPoints.SetSize( nSubDivs );
  300. // For each vertical slice.. (the top and bottom ones are just a single point).
  301. for ( int iSlice=0; iSlice < nSubDivs; iSlice++ )
  302. {
  303. float flHalfSliceAngle = M_PI * (float)iSlice / (nSubDivs - 1);
  304. if ( iSlice == 0 )
  305. {
  306. prevPoints[0] = vCenter + Vector( 0, 0, flRadius );
  307. for ( int z=1; z < prevPoints.Count(); z++ )
  308. prevPoints[z] = prevPoints[0];
  309. }
  310. else
  311. {
  312. for ( int iSubPt=0; iSubPt < nSubDivs; iSubPt++ )
  313. {
  314. float flHalfAngle = M_PI * (float)iSubPt / (nSubDivs - 1);
  315. float flAngle = flHalfAngle * 2;
  316. Vector pt;
  317. if ( iSlice == (nSubDivs - 1) )
  318. {
  319. pt = vCenter - Vector( 0, 0, flRadius );
  320. }
  321. else
  322. {
  323. pt.x = cos( flAngle ) * sin( flHalfSliceAngle );
  324. pt.y = sin( flAngle ) * sin( flHalfSliceAngle );
  325. pt.z = cos( flHalfSliceAngle );
  326. pt *= flRadius;
  327. pt += vCenter;
  328. }
  329. pPad->DrawLine( CSPVert( pt, vColor ), CSPVert( prevPoints[iSubPt], vColor ) );
  330. prevPoints[iSubPt] = pt;
  331. }
  332. if ( iSlice != (nSubDivs - 1) )
  333. {
  334. for ( int i=0; i < nSubDivs; i++ )
  335. pPad->DrawLine( CSPVert( prevPoints[i], vColor ), CSPVert( prevPoints[(i+1)%nSubDivs], vColor ) );
  336. }
  337. }
  338. }
  339. }
  340. void ScratchPad_DrawAABB(
  341. IScratchPad3D *pPad,
  342. const Vector &vMins,
  343. const Vector &vMaxs,
  344. const Vector &vColor )
  345. {
  346. int vertOrder[4][2] = {{0,0},{1,0},{1,1},{0,1}};
  347. const Vector *vecs[2] = {&vMins, &vMaxs};
  348. Vector vTop, vBottom, vPrevTop, vPrevBottom;
  349. vTop.z = vPrevTop.z = vMaxs.z;
  350. vBottom.z = vPrevBottom.z = vMins.z;
  351. vPrevTop.x = vPrevBottom.x = vecs[vertOrder[3][0]]->x;
  352. vPrevTop.y = vPrevBottom.y = vecs[vertOrder[3][1]]->y;
  353. for ( int i=0; i < 4; i++ )
  354. {
  355. vTop.x = vBottom.x = vecs[vertOrder[i][0]]->x;
  356. vTop.y = vBottom.y = vecs[vertOrder[i][1]]->y;
  357. // Draw the top line.
  358. pPad->DrawLine( CSPVert( vPrevTop, vColor ), CSPVert( vTop, vColor ) );
  359. pPad->DrawLine( CSPVert( vPrevBottom, vColor ), CSPVert( vBottom, vColor ) );
  360. pPad->DrawLine( CSPVert( vTop, vColor ), CSPVert( vBottom, vColor ) );
  361. vPrevTop = vTop;
  362. vPrevBottom = vBottom;
  363. }
  364. }
  365. #endif // !_STATIC_LINKED || _SHARED_LIB