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.

235 lines
7.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "tier2/beamsegdraw.h"
  8. #include "materialsystem/imaterialvar.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. //-----------------------------------------------------------------------------
  12. //
  13. // CBeamSegDraw implementation.
  14. //
  15. //-----------------------------------------------------------------------------
  16. void CBeamSegDraw::Start( IMatRenderContext *pRenderContext, int nSegs, IMaterial *pMaterial, CMeshBuilder *pMeshBuilder, int nMeshVertCount )
  17. {
  18. m_pRenderContext = pRenderContext;
  19. Assert( nSegs >= 2 );
  20. m_nSegsDrawn = 0;
  21. m_nTotalSegs = nSegs;
  22. if ( pMeshBuilder )
  23. {
  24. m_pMeshBuilder = pMeshBuilder;
  25. m_nMeshVertCount = nMeshVertCount;
  26. }
  27. else
  28. {
  29. m_pMeshBuilder = NULL;
  30. m_nMeshVertCount = 0;
  31. IMesh *pMesh = m_pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  32. m_Mesh.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, (nSegs-1) * 2 );
  33. }
  34. }
  35. inline void CBeamSegDraw::ComputeNormal( const Vector &vecCameraPos, const Vector &vStartPos, const Vector &vNextPos, Vector *pNormal )
  36. {
  37. // vTangentY = line vector for beam
  38. Vector vTangentY;
  39. VectorSubtract( vStartPos, vNextPos, vTangentY );
  40. // vDirToBeam = vector from viewer origin to beam
  41. Vector vDirToBeam;
  42. VectorSubtract( vStartPos, vecCameraPos, vDirToBeam );
  43. // Get a vector that is perpendicular to us and perpendicular to the beam.
  44. // This is used to fatten the beam.
  45. CrossProduct( vTangentY, vDirToBeam, *pNormal );
  46. VectorNormalizeFast( *pNormal );
  47. }
  48. inline void CBeamSegDraw::SpecifySeg( const Vector &vecCameraPos, const Vector &vNormal )
  49. {
  50. // SUCKY: Need to do a fair amount more work to get the tangent owing to the averaged normal
  51. Vector vDirToBeam, vTangentY;
  52. VectorSubtract( m_Seg.m_vPos, vecCameraPos, vDirToBeam );
  53. CrossProduct( vDirToBeam, vNormal, vTangentY );
  54. VectorNormalizeFast( vTangentY );
  55. // Build the endpoints.
  56. Vector vPoint1, vPoint2;
  57. VectorMA( m_Seg.m_vPos, m_Seg.m_flWidth*0.5f, vNormal, vPoint1 );
  58. VectorMA( m_Seg.m_vPos, -m_Seg.m_flWidth*0.5f, vNormal, vPoint2 );
  59. if ( m_pMeshBuilder )
  60. {
  61. // Specify the points.
  62. m_pMeshBuilder->Position3fv( vPoint1.Base() );
  63. m_pMeshBuilder->Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
  64. m_pMeshBuilder->TexCoord2f( 0, 0, m_Seg.m_flTexCoord );
  65. m_pMeshBuilder->TexCoord2f( 1, 0, m_Seg.m_flTexCoord );
  66. m_pMeshBuilder->TangentS3fv( vNormal.Base() );
  67. m_pMeshBuilder->TangentT3fv( vTangentY.Base() );
  68. m_pMeshBuilder->AdvanceVertex();
  69. m_pMeshBuilder->Position3fv( vPoint2.Base() );
  70. m_pMeshBuilder->Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
  71. m_pMeshBuilder->TexCoord2f( 0, 1, m_Seg.m_flTexCoord );
  72. m_pMeshBuilder->TexCoord2f( 1, 1, m_Seg.m_flTexCoord );
  73. m_pMeshBuilder->TangentS3fv( vNormal.Base() );
  74. m_pMeshBuilder->TangentT3fv( vTangentY.Base() );
  75. m_pMeshBuilder->AdvanceVertex();
  76. if ( m_nSegsDrawn > 1 )
  77. {
  78. int nBase = ( ( m_nSegsDrawn - 2 ) * 2 ) + m_nMeshVertCount;
  79. m_pMeshBuilder->FastIndex( nBase );
  80. m_pMeshBuilder->FastIndex( nBase + 1 );
  81. m_pMeshBuilder->FastIndex( nBase + 2 );
  82. m_pMeshBuilder->FastIndex( nBase + 1 );
  83. m_pMeshBuilder->FastIndex( nBase + 3 );
  84. m_pMeshBuilder->FastIndex( nBase + 2 );
  85. }
  86. }
  87. else
  88. {
  89. // Specify the points.
  90. m_Mesh.Position3fv( vPoint1.Base() );
  91. m_Mesh.Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
  92. m_Mesh.TexCoord2f( 0, 0, m_Seg.m_flTexCoord );
  93. m_Mesh.TexCoord2f( 1, 0, m_Seg.m_flTexCoord );
  94. m_Mesh.TangentS3fv( vNormal.Base() );
  95. m_Mesh.TangentT3fv( vTangentY.Base() );
  96. m_Mesh.AdvanceVertex();
  97. m_Mesh.Position3fv( vPoint2.Base() );
  98. m_Mesh.Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
  99. m_Mesh.TexCoord2f( 0, 1, m_Seg.m_flTexCoord );
  100. m_Mesh.TexCoord2f( 1, 1, m_Seg.m_flTexCoord );
  101. m_Mesh.TangentS3fv( vNormal.Base() );
  102. m_Mesh.TangentT3fv( vTangentY.Base() );
  103. m_Mesh.AdvanceVertex();
  104. }
  105. }
  106. void CBeamSegDraw::NextSeg( BeamSeg_t *pSeg )
  107. {
  108. Vector vecCameraPos;
  109. m_pRenderContext->GetWorldSpaceCameraPosition( &vecCameraPos );
  110. if ( m_nSegsDrawn > 0 )
  111. {
  112. // Get a vector that is perpendicular to us and perpendicular to the beam.
  113. // This is used to fatten the beam.
  114. Vector vNormal, vAveNormal;
  115. ComputeNormal( vecCameraPos, m_Seg.m_vPos, pSeg->m_vPos, &vNormal );
  116. if ( m_nSegsDrawn > 1 )
  117. {
  118. // Average this with the previous normal
  119. VectorAdd( vNormal, m_vNormalLast, vAveNormal );
  120. vAveNormal *= 0.5f;
  121. VectorNormalizeFast( vAveNormal );
  122. }
  123. else
  124. {
  125. vAveNormal = vNormal;
  126. }
  127. m_vNormalLast = vNormal;
  128. SpecifySeg( vecCameraPos, vAveNormal );
  129. }
  130. m_Seg = *pSeg;
  131. ++m_nSegsDrawn;
  132. if( m_nSegsDrawn == m_nTotalSegs )
  133. {
  134. SpecifySeg( vecCameraPos, m_vNormalLast );
  135. }
  136. }
  137. void CBeamSegDraw::End()
  138. {
  139. if ( m_pMeshBuilder )
  140. {
  141. m_pMeshBuilder = NULL;
  142. return;
  143. }
  144. m_Mesh.End( false, true );
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Purpose:
  148. //-----------------------------------------------------------------------------
  149. void CBeamSegDrawArbitrary::SetNormal( const Vector &normal )
  150. {
  151. m_vNormalLast = normal;
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Purpose:
  155. //-----------------------------------------------------------------------------
  156. void CBeamSegDrawArbitrary::NextSeg( BeamSeg_t *pSeg )
  157. {
  158. if ( m_nSegsDrawn > 0 )
  159. {
  160. Vector segDir = ( m_PrevSeg.m_vPos - pSeg->m_vPos );
  161. VectorNormalize( segDir );
  162. Vector normal = CrossProduct( segDir, m_vNormalLast );
  163. SpecifySeg( normal );
  164. }
  165. m_PrevSeg = m_Seg;
  166. m_Seg = *pSeg;
  167. ++m_nSegsDrawn;
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. // Input : &vNextPos -
  172. //-----------------------------------------------------------------------------
  173. void CBeamSegDrawArbitrary::SpecifySeg( const Vector &vNormal )
  174. {
  175. // Build the endpoints.
  176. Vector vPoint1, vPoint2;
  177. Vector vDelta;
  178. VectorMultiply( vNormal, m_Seg.m_flWidth*0.5f, vDelta );
  179. VectorAdd( m_Seg.m_vPos, vDelta, vPoint1 );
  180. VectorSubtract( m_Seg.m_vPos, vDelta, vPoint2 );
  181. // Specify the points.
  182. Assert( IsFinite(m_Seg.m_vColor.x) && IsFinite(m_Seg.m_vColor.y) && IsFinite(m_Seg.m_vColor.z) && IsFinite(m_Seg.m_flAlpha) );
  183. Assert( (m_Seg.m_vColor.x >= 0.0) && (m_Seg.m_vColor.y >= 0.0) && (m_Seg.m_vColor.z >= 0.0) && (m_Seg.m_flAlpha >= 0.0) );
  184. Assert( (m_Seg.m_vColor.x <= 1.0) && (m_Seg.m_vColor.y <= 1.0) && (m_Seg.m_vColor.z <= 1.0) && (m_Seg.m_flAlpha <= 1.0) );
  185. unsigned char r = FastFToC( m_Seg.m_vColor.x );
  186. unsigned char g = FastFToC( m_Seg.m_vColor.y );
  187. unsigned char b = FastFToC( m_Seg.m_vColor.z );
  188. unsigned char a = FastFToC( m_Seg.m_flAlpha );
  189. m_Mesh.Position3fv( vPoint1.Base() );
  190. m_Mesh.Color4ub( r, g, b, a );
  191. m_Mesh.TexCoord2f( 0, 0, m_Seg.m_flTexCoord );
  192. m_Mesh.TexCoord2f( 1, 0, m_Seg.m_flTexCoord );
  193. m_Mesh.AdvanceVertex();
  194. m_Mesh.Position3fv( vPoint2.Base() );
  195. m_Mesh.Color4ub( r, g, b, a );
  196. m_Mesh.TexCoord2f( 0, 1, m_Seg.m_flTexCoord );
  197. m_Mesh.TexCoord2f( 1, 1, m_Seg.m_flTexCoord );
  198. m_Mesh.AdvanceVertex();
  199. }