diff options
Diffstat (limited to 'tier2/beamsegdraw.cpp')
| -rw-r--r-- | tier2/beamsegdraw.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/tier2/beamsegdraw.cpp b/tier2/beamsegdraw.cpp new file mode 100644 index 0000000..fca4471 --- /dev/null +++ b/tier2/beamsegdraw.cpp @@ -0,0 +1,235 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "tier2/beamsegdraw.h" +#include "materialsystem/imaterialvar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// +// CBeamSegDraw implementation. +// +//----------------------------------------------------------------------------- +void CBeamSegDraw::Start( IMatRenderContext *pRenderContext, int nSegs, IMaterial *pMaterial, CMeshBuilder *pMeshBuilder, int nMeshVertCount ) +{ + m_pRenderContext = pRenderContext; + Assert( nSegs >= 2 ); + + m_nSegsDrawn = 0; + m_nTotalSegs = nSegs; + + if ( pMeshBuilder ) + { + m_pMeshBuilder = pMeshBuilder; + m_nMeshVertCount = nMeshVertCount; + } + else + { + m_pMeshBuilder = NULL; + m_nMeshVertCount = 0; + + IMesh *pMesh = m_pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial ); + m_Mesh.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, (nSegs-1) * 2 ); + } +} + +inline void CBeamSegDraw::ComputeNormal( const Vector &vecCameraPos, const Vector &vStartPos, const Vector &vNextPos, Vector *pNormal ) +{ + // vTangentY = line vector for beam + Vector vTangentY; + VectorSubtract( vStartPos, vNextPos, vTangentY ); + + // vDirToBeam = vector from viewer origin to beam + Vector vDirToBeam; + VectorSubtract( vStartPos, vecCameraPos, vDirToBeam ); + + // Get a vector that is perpendicular to us and perpendicular to the beam. + // This is used to fatten the beam. + CrossProduct( vTangentY, vDirToBeam, *pNormal ); + VectorNormalizeFast( *pNormal ); +} + +inline void CBeamSegDraw::SpecifySeg( const Vector &vecCameraPos, const Vector &vNormal ) +{ + // SUCKY: Need to do a fair amount more work to get the tangent owing to the averaged normal + Vector vDirToBeam, vTangentY; + VectorSubtract( m_Seg.m_vPos, vecCameraPos, vDirToBeam ); + CrossProduct( vDirToBeam, vNormal, vTangentY ); + VectorNormalizeFast( vTangentY ); + + // Build the endpoints. + Vector vPoint1, vPoint2; + VectorMA( m_Seg.m_vPos, m_Seg.m_flWidth*0.5f, vNormal, vPoint1 ); + VectorMA( m_Seg.m_vPos, -m_Seg.m_flWidth*0.5f, vNormal, vPoint2 ); + + if ( m_pMeshBuilder ) + { + // Specify the points. + m_pMeshBuilder->Position3fv( vPoint1.Base() ); + m_pMeshBuilder->Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha ); + m_pMeshBuilder->TexCoord2f( 0, 0, m_Seg.m_flTexCoord ); + m_pMeshBuilder->TexCoord2f( 1, 0, m_Seg.m_flTexCoord ); + m_pMeshBuilder->TangentS3fv( vNormal.Base() ); + m_pMeshBuilder->TangentT3fv( vTangentY.Base() ); + m_pMeshBuilder->AdvanceVertex(); + + m_pMeshBuilder->Position3fv( vPoint2.Base() ); + m_pMeshBuilder->Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha ); + m_pMeshBuilder->TexCoord2f( 0, 1, m_Seg.m_flTexCoord ); + m_pMeshBuilder->TexCoord2f( 1, 1, m_Seg.m_flTexCoord ); + m_pMeshBuilder->TangentS3fv( vNormal.Base() ); + m_pMeshBuilder->TangentT3fv( vTangentY.Base() ); + m_pMeshBuilder->AdvanceVertex(); + + if ( m_nSegsDrawn > 1 ) + { + int nBase = ( ( m_nSegsDrawn - 2 ) * 2 ) + m_nMeshVertCount; + + m_pMeshBuilder->FastIndex( nBase ); + m_pMeshBuilder->FastIndex( nBase + 1 ); + m_pMeshBuilder->FastIndex( nBase + 2 ); + m_pMeshBuilder->FastIndex( nBase + 1 ); + m_pMeshBuilder->FastIndex( nBase + 3 ); + m_pMeshBuilder->FastIndex( nBase + 2 ); + } + } + else + { + // Specify the points. + m_Mesh.Position3fv( vPoint1.Base() ); + m_Mesh.Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha ); + m_Mesh.TexCoord2f( 0, 0, m_Seg.m_flTexCoord ); + m_Mesh.TexCoord2f( 1, 0, m_Seg.m_flTexCoord ); + m_Mesh.TangentS3fv( vNormal.Base() ); + m_Mesh.TangentT3fv( vTangentY.Base() ); + m_Mesh.AdvanceVertex(); + + m_Mesh.Position3fv( vPoint2.Base() ); + m_Mesh.Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha ); + m_Mesh.TexCoord2f( 0, 1, m_Seg.m_flTexCoord ); + m_Mesh.TexCoord2f( 1, 1, m_Seg.m_flTexCoord ); + m_Mesh.TangentS3fv( vNormal.Base() ); + m_Mesh.TangentT3fv( vTangentY.Base() ); + m_Mesh.AdvanceVertex(); + } +} + +void CBeamSegDraw::NextSeg( BeamSeg_t *pSeg ) +{ + Vector vecCameraPos; + m_pRenderContext->GetWorldSpaceCameraPosition( &vecCameraPos ); + + if ( m_nSegsDrawn > 0 ) + { + // Get a vector that is perpendicular to us and perpendicular to the beam. + // This is used to fatten the beam. + Vector vNormal, vAveNormal; + ComputeNormal( vecCameraPos, m_Seg.m_vPos, pSeg->m_vPos, &vNormal ); + + if ( m_nSegsDrawn > 1 ) + { + // Average this with the previous normal + VectorAdd( vNormal, m_vNormalLast, vAveNormal ); + vAveNormal *= 0.5f; + VectorNormalizeFast( vAveNormal ); + } + else + { + vAveNormal = vNormal; + } + + m_vNormalLast = vNormal; + SpecifySeg( vecCameraPos, vAveNormal ); + } + + m_Seg = *pSeg; + ++m_nSegsDrawn; + + if( m_nSegsDrawn == m_nTotalSegs ) + { + SpecifySeg( vecCameraPos, m_vNormalLast ); + } +} + +void CBeamSegDraw::End() +{ + if ( m_pMeshBuilder ) + { + m_pMeshBuilder = NULL; + return; + } + + m_Mesh.End( false, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBeamSegDrawArbitrary::SetNormal( const Vector &normal ) +{ + m_vNormalLast = normal; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBeamSegDrawArbitrary::NextSeg( BeamSeg_t *pSeg ) +{ + if ( m_nSegsDrawn > 0 ) + { + Vector segDir = ( m_PrevSeg.m_vPos - pSeg->m_vPos ); + VectorNormalize( segDir ); + + Vector normal = CrossProduct( segDir, m_vNormalLast ); + SpecifySeg( normal ); + } + + m_PrevSeg = m_Seg; + m_Seg = *pSeg; + ++m_nSegsDrawn; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &vNextPos - +//----------------------------------------------------------------------------- +void CBeamSegDrawArbitrary::SpecifySeg( const Vector &vNormal ) +{ + // Build the endpoints. + Vector vPoint1, vPoint2; + Vector vDelta; + VectorMultiply( vNormal, m_Seg.m_flWidth*0.5f, vDelta ); + VectorAdd( m_Seg.m_vPos, vDelta, vPoint1 ); + VectorSubtract( m_Seg.m_vPos, vDelta, vPoint2 ); + + // Specify the points. + Assert( IsFinite(m_Seg.m_vColor.x) && IsFinite(m_Seg.m_vColor.y) && IsFinite(m_Seg.m_vColor.z) && IsFinite(m_Seg.m_flAlpha) ); + 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) ); + 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) ); + + unsigned char r = FastFToC( m_Seg.m_vColor.x ); + unsigned char g = FastFToC( m_Seg.m_vColor.y ); + unsigned char b = FastFToC( m_Seg.m_vColor.z ); + unsigned char a = FastFToC( m_Seg.m_flAlpha ); + m_Mesh.Position3fv( vPoint1.Base() ); + m_Mesh.Color4ub( r, g, b, a ); + m_Mesh.TexCoord2f( 0, 0, m_Seg.m_flTexCoord ); + m_Mesh.TexCoord2f( 1, 0, m_Seg.m_flTexCoord ); + m_Mesh.AdvanceVertex(); + + m_Mesh.Position3fv( vPoint2.Base() ); + m_Mesh.Color4ub( r, g, b, a ); + m_Mesh.TexCoord2f( 0, 1, m_Seg.m_flTexCoord ); + m_Mesh.TexCoord2f( 1, 1, m_Seg.m_flTexCoord ); + m_Mesh.AdvanceVertex(); +} |