aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/c_sprite.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/c_sprite.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/c_sprite.cpp')
-rw-r--r--mp/src/game/client/c_sprite.cpp1000
1 files changed, 500 insertions, 500 deletions
diff --git a/mp/src/game/client/c_sprite.cpp b/mp/src/game/client/c_sprite.cpp
index 6cedec12..9146eefc 100644
--- a/mp/src/game/client/c_sprite.cpp
+++ b/mp/src/game/client/c_sprite.cpp
@@ -1,500 +1,500 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//===========================================================================//
-#include "cbase.h"
-#include "c_sprite.h"
-#include "model_types.h"
-#include "iviewrender.h"
-#include "view.h"
-#include "enginesprite.h"
-#include "engine/ivmodelinfo.h"
-#include "util_shared.h"
-#include "tier0/vprof.h"
-#include "materialsystem/imaterial.h"
-#include "materialsystem/imaterialvar.h"
-#include "view_shared.h"
-#include "viewrender.h"
-#include "tier1/KeyValues.h"
-#include "toolframework/itoolframework.h"
-#include "toolframework_client.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-ConVar r_drawsprites( "r_drawsprites", "1", FCVAR_CHEAT );
-
-//-----------------------------------------------------------------------------
-// Purpose: Generic sprite model renderer
-// Input : *baseentity -
-// *psprite -
-// fscale -
-// frame -
-// rendermode -
-// r -
-// g -
-// b -
-// a -
-// forward -
-// right -
-// up -
-//-----------------------------------------------------------------------------
-static unsigned int s_nHDRColorScaleCache = 0;
-void DrawSpriteModel( IClientEntity *baseentity, CEngineSprite *psprite, const Vector &origin, float fscale, float frame,
- int rendermode, int r, int g, int b, int a, const Vector& forward, const Vector& right, const Vector& up, float flHDRColorScale )
-{
- float scale;
- IMaterial *material;
-
- // don't even bother culling, because it's just a single
- // polygon without a surface cache
- if ( fscale > 0 )
- scale = fscale;
- else
- scale = 1.0f;
-
- if ( rendermode == kRenderNormal )
- {
- render->SetBlend( 1.0f );
- }
-
- material = psprite->GetMaterial( (RenderMode_t)rendermode, frame );
- if ( !material )
- return;
-
- CMatRenderContextPtr pRenderContext( materials );
-
- if ( ShouldDrawInWireFrameMode() || r_drawsprites.GetInt() == 2 )
- {
- IMaterial *pMaterial = materials->FindMaterial( "debug/debugspritewireframe", TEXTURE_GROUP_OTHER );
- pRenderContext->Bind( pMaterial, NULL );
- }
- else
- {
- pRenderContext->Bind( material, (IClientRenderable*)baseentity );
- }
-
- unsigned char color[4];
- color[0] = r;
- color[1] = g;
- color[2] = b;
- color[3] = a;
-
- IMaterialVar *pHDRColorScaleVar = material->FindVarFast( "$HDRCOLORSCALE", &s_nHDRColorScaleCache );
- if( pHDRColorScaleVar )
- {
- pHDRColorScaleVar->SetVecValue( flHDRColorScale, flHDRColorScale, flHDRColorScale );
- }
-
- Vector point;
- IMesh* pMesh = pRenderContext->GetDynamicMesh();
-
- CMeshBuilder meshBuilder;
- meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
-
- Vector vec_a;
- Vector vec_b;
- Vector vec_c;
- Vector vec_d;
-
- // isolate common terms
- VectorMA( origin, psprite->GetDown() * scale, up, vec_a );
- VectorScale( right, psprite->GetLeft() * scale, vec_b );
- VectorMA( origin, psprite->GetUp() * scale, up, vec_c );
- VectorScale( right, psprite->GetRight() * scale, vec_d );
-
- float flMinU, flMinV, flMaxU, flMaxV;
- psprite->GetTexCoordRange( &flMinU, &flMinV, &flMaxU, &flMaxV );
-
- meshBuilder.Color4ubv( color );
- meshBuilder.TexCoord2f( 0, flMinU, flMaxV );
- VectorAdd( vec_a, vec_b, point );
- meshBuilder.Position3fv( point.Base() );
- meshBuilder.AdvanceVertex();
-
- meshBuilder.Color4ubv( color );
- meshBuilder.TexCoord2f( 0, flMinU, flMinV );
- VectorAdd( vec_c, vec_b, point );
- meshBuilder.Position3fv( point.Base() );
- meshBuilder.AdvanceVertex();
-
- meshBuilder.Color4ubv( color );
- meshBuilder.TexCoord2f( 0, flMaxU, flMinV );
- VectorAdd( vec_c, vec_d, point );
- meshBuilder.Position3fv( point.Base() );
- meshBuilder.AdvanceVertex();
-
- meshBuilder.Color4ubv( color );
- meshBuilder.TexCoord2f( 0, flMaxU, flMaxV );
- VectorAdd( vec_a, vec_d, point );
- meshBuilder.Position3fv( point.Base() );
- meshBuilder.AdvanceVertex();
-
- meshBuilder.End();
- pMesh->Draw();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Determine glow brightness/scale based on distance to render origin and trace results
-// Input : entorigin -
-// rendermode -
-// renderfx -
-// alpha -
-// pscale - Pointer to the value for scale, will be changed based on distance and rendermode.
-//-----------------------------------------------------------------------------
-float StandardGlowBlend( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle, int rendermode, int renderfx, int alpha, float *pscale )
-{
- float dist;
- float brightness;
-
- brightness = PixelVisibility_FractionVisible( params, queryHandle );
- if ( brightness <= 0.0f )
- {
- return 0.0f;
- }
- dist = GlowSightDistance( params.position, false );
- if ( dist <= 0.0f )
- {
- return 0.0f;
- }
-
- if ( renderfx == kRenderFxNoDissipation )
- {
- return (float)alpha * (1.0f/255.0f) * brightness;
- }
-
- // UNDONE: Tweak these magic numbers (1200 - distance at full brightness)
- float fadeOut = (1200.0f*1200.0f) / (dist*dist);
- fadeOut = clamp( fadeOut, 0.0f, 1.0f );
-
- if (rendermode != kRenderWorldGlow)
- {
- // Make the glow fixed size in screen space, taking into consideration the scale setting.
- if ( *pscale == 0.0f )
- {
- *pscale = 1.0f;
- }
-
- *pscale *= dist * (1.0f/200.0f);
- }
-
- return fadeOut * brightness;
-}
-
-static float SpriteAspect( CEngineSprite *pSprite )
-{
- if ( pSprite )
- {
- float x = fabsf(pSprite->GetRight() - pSprite->GetLeft());
- float y = fabsf(pSprite->GetDown() - pSprite->GetUp());
- if ( y != 0 && x != 0 )
- {
- return x / y;
- }
- }
-
- return 1.0f;
-}
-
-float C_SpriteRenderer::GlowBlend( CEngineSprite *psprite, const Vector& entorigin, int rendermode, int renderfx, int alpha, float *pscale )
-{
- pixelvis_queryparams_t params;
- float aspect = SpriteAspect(psprite);
- params.Init( entorigin, PIXELVIS_DEFAULT_PROXY_SIZE, aspect );
- return StandardGlowBlend( params, &m_queryHandle, rendermode, renderfx, alpha, pscale );
-}
-
-// since sprites can network down a glow proxy size, handle that here
-float CSprite::GlowBlend( CEngineSprite *psprite, const Vector& entorigin, int rendermode, int renderfx, int alpha, float *pscale )
-{
- pixelvis_queryparams_t params;
- float aspect = SpriteAspect(psprite);
- params.Init( entorigin, m_flGlowProxySize, aspect );
- return StandardGlowBlend( params, &m_queryHandle, rendermode, renderfx, alpha, pscale );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Determine sprite orientation axes
-// Input : type -
-// forward -
-// right -
-// up -
-//-----------------------------------------------------------------------------
-void C_SpriteRenderer::GetSpriteAxes( SPRITETYPE type,
- const Vector& origin,
- const QAngle& angles,
- Vector& forward,
- Vector& right,
- Vector& up )
-{
- int i;
- float dot, angle, sr, cr;
- Vector tvec;
-
- // Automatically roll parallel sprites if requested
- if ( angles[2] != 0 && type == SPR_VP_PARALLEL )
- {
- type = SPR_VP_PARALLEL_ORIENTED;
- }
-
- switch( type )
- {
- case SPR_FACING_UPRIGHT:
- {
- // generate the sprite's axes, with vup straight up in worldspace, and
- // r_spritedesc.vright perpendicular to modelorg.
- // This will not work if the view direction is very close to straight up or
- // down, because the cross product will be between two nearly parallel
- // vectors and starts to approach an undefined state, so we don't draw if
- // the two vectors are less than 1 degree apart
- tvec[0] = -origin[0];
- tvec[1] = -origin[1];
- tvec[2] = -origin[2];
- VectorNormalize (tvec);
- dot = tvec[2]; // same as DotProduct (tvec, r_spritedesc.vup) because
- // r_spritedesc.vup is 0, 0, 1
- if ((dot > 0.999848f) || (dot < -0.999848f)) // cos(1 degree) = 0.999848
- return;
- up[0] = 0;
- up[1] = 0;
- up[2] = 1;
- right[0] = tvec[1];
- // CrossProduct(r_spritedesc.vup, -modelorg,
- right[1] = -tvec[0];
- // r_spritedesc.vright)
- right[2] = 0;
- VectorNormalize (right);
- forward[0] = -right[1];
- forward[1] = right[0];
- forward[2] = 0;
- // CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
- // r_spritedesc.vpn)
- }
- break;
-
- case SPR_VP_PARALLEL:
- {
- // generate the sprite's axes, completely parallel to the viewplane. There
- // are no problem situations, because the sprite is always in the same
- // position relative to the viewer
- for (i=0 ; i<3 ; i++)
- {
- up[i] = CurrentViewUp()[i];
- right[i] = CurrentViewRight()[i];
- forward[i] = CurrentViewForward()[i];
- }
- }
- break;
-
- case SPR_VP_PARALLEL_UPRIGHT:
- {
- // generate the sprite's axes, with g_vecVUp straight up in worldspace, and
- // r_spritedesc.vright parallel to the viewplane.
- // This will not work if the view direction is very close to straight up or
- // down, because the cross product will be between two nearly parallel
- // vectors and starts to approach an undefined state, so we don't draw if
- // the two vectors are less than 1 degree apart
- dot = CurrentViewForward()[2]; // same as DotProduct (vpn, r_spritedesc.g_vecVUp) because
- // r_spritedesc.vup is 0, 0, 1
- if ((dot > 0.999848f) || (dot < -0.999848f)) // cos(1 degree) = 0.999848
- return;
- up[0] = 0;
- up[1] = 0;
- up[2] = 1;
- right[0] = CurrentViewForward()[1];
- // CrossProduct (r_spritedesc.vup, vpn,
- right[1] = -CurrentViewForward()[0]; // r_spritedesc.vright)
- right[2] = 0;
- VectorNormalize (right);
- forward[0] = -right[1];
- forward[1] = right[0];
- forward[2] = 0;
- // CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
- // r_spritedesc.vpn)
- }
- break;
-
- case SPR_ORIENTED:
- {
- // generate the sprite's axes, according to the sprite's world orientation
- AngleVectors( angles, &forward, &right, &up );
- }
- break;
-
- case SPR_VP_PARALLEL_ORIENTED:
- {
- // generate the sprite's axes, parallel to the viewplane, but rotated in
- // that plane around the center according to the sprite entity's roll
- // angle. So vpn stays the same, but vright and vup rotate
- angle = angles[ROLL] * (M_PI*2.0f/360.0f);
- SinCos( angle, &sr, &cr );
-
- for (i=0 ; i<3 ; i++)
- {
- forward[i] = CurrentViewForward()[i];
- right[i] = CurrentViewRight()[i] * cr + CurrentViewUp()[i] * sr;
- up[i] = CurrentViewRight()[i] * -sr + CurrentViewUp()[i] * cr;
- }
- }
- break;
-
- default:
- Warning( "GetSpriteAxes: Bad sprite type %d\n", type );
- break;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : int
-//-----------------------------------------------------------------------------
-int C_SpriteRenderer::DrawSprite(
- IClientEntity *entity,
- const model_t *model,
- const Vector& origin,
- const QAngle& angles,
- float frame,
- IClientEntity *attachedto,
- int attachmentindex,
- int rendermode,
- int renderfx,
- int alpha,
- int r,
- int g,
- int b,
- float scale,
- float flHDRColorScale
- )
-{
- VPROF_BUDGET( "C_SpriteRenderer::DrawSprite", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
-
- if ( !r_drawsprites.GetBool() || !model || modelinfo->GetModelType( model ) != mod_sprite )
- {
- return 0;
- }
-
- // Get extra data
- CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData( model );
- if ( !psprite )
- {
- return 0;
- }
-
- Vector effect_origin;
- VectorCopy( origin, effect_origin );
-
- // Use attachment point
- if ( attachedto )
- {
- C_BaseEntity *ent = attachedto->GetBaseEntity();
- if ( ent )
- {
- // don't draw viewmodel effects in reflections
- if ( CurrentViewID() == VIEW_REFLECTION )
- {
- int group = ent->GetRenderGroup();
- if ( group == RENDER_GROUP_VIEW_MODEL_TRANSLUCENT || group == RENDER_GROUP_VIEW_MODEL_OPAQUE )
- return 0;
- }
- QAngle temp;
- ent->GetAttachment( attachmentindex, effect_origin, temp );
- }
- }
-
- if ( rendermode != kRenderNormal )
- {
- float blend = render->GetBlend();
-
- // kRenderGlow and kRenderWorldGlow have a special blending function
- if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
- {
- blend *= GlowBlend( psprite, effect_origin, rendermode, renderfx, alpha, &scale );
-
- // Fade out the sprite depending on distance from the view origin.
- r *= blend;
- g *= blend;
- b *= blend;
- }
-
- render->SetBlend( blend );
- if ( blend <= 0.0f )
- {
- return 0;
- }
- }
-
- // Get orthonormal basis
- Vector forward, right, up;
- GetSpriteAxes( (SPRITETYPE)psprite->GetOrientation(), origin, angles, forward, right, up );
-
- // Draw
- DrawSpriteModel(
- entity,
- psprite,
- effect_origin,
- scale,
- frame,
- rendermode,
- r,
- g,
- b,
- alpha,
- forward, right, up, flHDRColorScale );
-
- return 1;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CSprite::GetToolRecordingState( KeyValues *msg )
-{
- if ( !ToolsEnabled() )
- return;
-
- VPROF_BUDGET( "CSprite::GetToolRecordingState", VPROF_BUDGETGROUP_TOOLS );
-
- BaseClass::GetToolRecordingState( msg );
-
- // Use attachment point
- if ( m_hAttachedToEntity )
- {
- C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity();
- if ( ent )
- {
- BaseEntityRecordingState_t *pState = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" );
-
- // override position if we're driven by an attachment
- QAngle temp;
- pState->m_vecRenderOrigin = GetAbsOrigin();
- ent->GetAttachment( m_nAttachment, pState->m_vecRenderOrigin, temp );
-
- // override viewmodel if we're driven by an attachment
- bool bViewModel = dynamic_cast< C_BaseViewModel* >( ent ) != NULL;
- msg->SetInt( "viewmodel", bViewModel );
- }
- }
-
- float renderscale = GetRenderScale();
- if ( m_bWorldSpaceScale )
- {
- CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() );
- float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() );
- renderscale /= flMinSize;
- }
-
- // sprite params
- static SpriteRecordingState_t state;
- state.m_flRenderScale = renderscale;
- state.m_flFrame = m_flFrame;
- state.m_flProxyRadius = m_flGlowProxySize;
- state.m_nRenderMode = GetRenderMode();
- state.m_nRenderFX = m_nRenderFX;
- state.m_Color.SetColor( m_clrRender.GetR(), m_clrRender.GetG(), m_clrRender.GetB(), GetRenderBrightness() );
-
- msg->SetPtr( "sprite", &state );
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+#include "cbase.h"
+#include "c_sprite.h"
+#include "model_types.h"
+#include "iviewrender.h"
+#include "view.h"
+#include "enginesprite.h"
+#include "engine/ivmodelinfo.h"
+#include "util_shared.h"
+#include "tier0/vprof.h"
+#include "materialsystem/imaterial.h"
+#include "materialsystem/imaterialvar.h"
+#include "view_shared.h"
+#include "viewrender.h"
+#include "tier1/KeyValues.h"
+#include "toolframework/itoolframework.h"
+#include "toolframework_client.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+ConVar r_drawsprites( "r_drawsprites", "1", FCVAR_CHEAT );
+
+//-----------------------------------------------------------------------------
+// Purpose: Generic sprite model renderer
+// Input : *baseentity -
+// *psprite -
+// fscale -
+// frame -
+// rendermode -
+// r -
+// g -
+// b -
+// a -
+// forward -
+// right -
+// up -
+//-----------------------------------------------------------------------------
+static unsigned int s_nHDRColorScaleCache = 0;
+void DrawSpriteModel( IClientEntity *baseentity, CEngineSprite *psprite, const Vector &origin, float fscale, float frame,
+ int rendermode, int r, int g, int b, int a, const Vector& forward, const Vector& right, const Vector& up, float flHDRColorScale )
+{
+ float scale;
+ IMaterial *material;
+
+ // don't even bother culling, because it's just a single
+ // polygon without a surface cache
+ if ( fscale > 0 )
+ scale = fscale;
+ else
+ scale = 1.0f;
+
+ if ( rendermode == kRenderNormal )
+ {
+ render->SetBlend( 1.0f );
+ }
+
+ material = psprite->GetMaterial( (RenderMode_t)rendermode, frame );
+ if ( !material )
+ return;
+
+ CMatRenderContextPtr pRenderContext( materials );
+
+ if ( ShouldDrawInWireFrameMode() || r_drawsprites.GetInt() == 2 )
+ {
+ IMaterial *pMaterial = materials->FindMaterial( "debug/debugspritewireframe", TEXTURE_GROUP_OTHER );
+ pRenderContext->Bind( pMaterial, NULL );
+ }
+ else
+ {
+ pRenderContext->Bind( material, (IClientRenderable*)baseentity );
+ }
+
+ unsigned char color[4];
+ color[0] = r;
+ color[1] = g;
+ color[2] = b;
+ color[3] = a;
+
+ IMaterialVar *pHDRColorScaleVar = material->FindVarFast( "$HDRCOLORSCALE", &s_nHDRColorScaleCache );
+ if( pHDRColorScaleVar )
+ {
+ pHDRColorScaleVar->SetVecValue( flHDRColorScale, flHDRColorScale, flHDRColorScale );
+ }
+
+ Vector point;
+ IMesh* pMesh = pRenderContext->GetDynamicMesh();
+
+ CMeshBuilder meshBuilder;
+ meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
+
+ Vector vec_a;
+ Vector vec_b;
+ Vector vec_c;
+ Vector vec_d;
+
+ // isolate common terms
+ VectorMA( origin, psprite->GetDown() * scale, up, vec_a );
+ VectorScale( right, psprite->GetLeft() * scale, vec_b );
+ VectorMA( origin, psprite->GetUp() * scale, up, vec_c );
+ VectorScale( right, psprite->GetRight() * scale, vec_d );
+
+ float flMinU, flMinV, flMaxU, flMaxV;
+ psprite->GetTexCoordRange( &flMinU, &flMinV, &flMaxU, &flMaxV );
+
+ meshBuilder.Color4ubv( color );
+ meshBuilder.TexCoord2f( 0, flMinU, flMaxV );
+ VectorAdd( vec_a, vec_b, point );
+ meshBuilder.Position3fv( point.Base() );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color4ubv( color );
+ meshBuilder.TexCoord2f( 0, flMinU, flMinV );
+ VectorAdd( vec_c, vec_b, point );
+ meshBuilder.Position3fv( point.Base() );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color4ubv( color );
+ meshBuilder.TexCoord2f( 0, flMaxU, flMinV );
+ VectorAdd( vec_c, vec_d, point );
+ meshBuilder.Position3fv( point.Base() );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color4ubv( color );
+ meshBuilder.TexCoord2f( 0, flMaxU, flMaxV );
+ VectorAdd( vec_a, vec_d, point );
+ meshBuilder.Position3fv( point.Base() );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.End();
+ pMesh->Draw();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Determine glow brightness/scale based on distance to render origin and trace results
+// Input : entorigin -
+// rendermode -
+// renderfx -
+// alpha -
+// pscale - Pointer to the value for scale, will be changed based on distance and rendermode.
+//-----------------------------------------------------------------------------
+float StandardGlowBlend( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle, int rendermode, int renderfx, int alpha, float *pscale )
+{
+ float dist;
+ float brightness;
+
+ brightness = PixelVisibility_FractionVisible( params, queryHandle );
+ if ( brightness <= 0.0f )
+ {
+ return 0.0f;
+ }
+ dist = GlowSightDistance( params.position, false );
+ if ( dist <= 0.0f )
+ {
+ return 0.0f;
+ }
+
+ if ( renderfx == kRenderFxNoDissipation )
+ {
+ return (float)alpha * (1.0f/255.0f) * brightness;
+ }
+
+ // UNDONE: Tweak these magic numbers (1200 - distance at full brightness)
+ float fadeOut = (1200.0f*1200.0f) / (dist*dist);
+ fadeOut = clamp( fadeOut, 0.0f, 1.0f );
+
+ if (rendermode != kRenderWorldGlow)
+ {
+ // Make the glow fixed size in screen space, taking into consideration the scale setting.
+ if ( *pscale == 0.0f )
+ {
+ *pscale = 1.0f;
+ }
+
+ *pscale *= dist * (1.0f/200.0f);
+ }
+
+ return fadeOut * brightness;
+}
+
+static float SpriteAspect( CEngineSprite *pSprite )
+{
+ if ( pSprite )
+ {
+ float x = fabsf(pSprite->GetRight() - pSprite->GetLeft());
+ float y = fabsf(pSprite->GetDown() - pSprite->GetUp());
+ if ( y != 0 && x != 0 )
+ {
+ return x / y;
+ }
+ }
+
+ return 1.0f;
+}
+
+float C_SpriteRenderer::GlowBlend( CEngineSprite *psprite, const Vector& entorigin, int rendermode, int renderfx, int alpha, float *pscale )
+{
+ pixelvis_queryparams_t params;
+ float aspect = SpriteAspect(psprite);
+ params.Init( entorigin, PIXELVIS_DEFAULT_PROXY_SIZE, aspect );
+ return StandardGlowBlend( params, &m_queryHandle, rendermode, renderfx, alpha, pscale );
+}
+
+// since sprites can network down a glow proxy size, handle that here
+float CSprite::GlowBlend( CEngineSprite *psprite, const Vector& entorigin, int rendermode, int renderfx, int alpha, float *pscale )
+{
+ pixelvis_queryparams_t params;
+ float aspect = SpriteAspect(psprite);
+ params.Init( entorigin, m_flGlowProxySize, aspect );
+ return StandardGlowBlend( params, &m_queryHandle, rendermode, renderfx, alpha, pscale );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Determine sprite orientation axes
+// Input : type -
+// forward -
+// right -
+// up -
+//-----------------------------------------------------------------------------
+void C_SpriteRenderer::GetSpriteAxes( SPRITETYPE type,
+ const Vector& origin,
+ const QAngle& angles,
+ Vector& forward,
+ Vector& right,
+ Vector& up )
+{
+ int i;
+ float dot, angle, sr, cr;
+ Vector tvec;
+
+ // Automatically roll parallel sprites if requested
+ if ( angles[2] != 0 && type == SPR_VP_PARALLEL )
+ {
+ type = SPR_VP_PARALLEL_ORIENTED;
+ }
+
+ switch( type )
+ {
+ case SPR_FACING_UPRIGHT:
+ {
+ // generate the sprite's axes, with vup straight up in worldspace, and
+ // r_spritedesc.vright perpendicular to modelorg.
+ // This will not work if the view direction is very close to straight up or
+ // down, because the cross product will be between two nearly parallel
+ // vectors and starts to approach an undefined state, so we don't draw if
+ // the two vectors are less than 1 degree apart
+ tvec[0] = -origin[0];
+ tvec[1] = -origin[1];
+ tvec[2] = -origin[2];
+ VectorNormalize (tvec);
+ dot = tvec[2]; // same as DotProduct (tvec, r_spritedesc.vup) because
+ // r_spritedesc.vup is 0, 0, 1
+ if ((dot > 0.999848f) || (dot < -0.999848f)) // cos(1 degree) = 0.999848
+ return;
+ up[0] = 0;
+ up[1] = 0;
+ up[2] = 1;
+ right[0] = tvec[1];
+ // CrossProduct(r_spritedesc.vup, -modelorg,
+ right[1] = -tvec[0];
+ // r_spritedesc.vright)
+ right[2] = 0;
+ VectorNormalize (right);
+ forward[0] = -right[1];
+ forward[1] = right[0];
+ forward[2] = 0;
+ // CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
+ // r_spritedesc.vpn)
+ }
+ break;
+
+ case SPR_VP_PARALLEL:
+ {
+ // generate the sprite's axes, completely parallel to the viewplane. There
+ // are no problem situations, because the sprite is always in the same
+ // position relative to the viewer
+ for (i=0 ; i<3 ; i++)
+ {
+ up[i] = CurrentViewUp()[i];
+ right[i] = CurrentViewRight()[i];
+ forward[i] = CurrentViewForward()[i];
+ }
+ }
+ break;
+
+ case SPR_VP_PARALLEL_UPRIGHT:
+ {
+ // generate the sprite's axes, with g_vecVUp straight up in worldspace, and
+ // r_spritedesc.vright parallel to the viewplane.
+ // This will not work if the view direction is very close to straight up or
+ // down, because the cross product will be between two nearly parallel
+ // vectors and starts to approach an undefined state, so we don't draw if
+ // the two vectors are less than 1 degree apart
+ dot = CurrentViewForward()[2]; // same as DotProduct (vpn, r_spritedesc.g_vecVUp) because
+ // r_spritedesc.vup is 0, 0, 1
+ if ((dot > 0.999848f) || (dot < -0.999848f)) // cos(1 degree) = 0.999848
+ return;
+ up[0] = 0;
+ up[1] = 0;
+ up[2] = 1;
+ right[0] = CurrentViewForward()[1];
+ // CrossProduct (r_spritedesc.vup, vpn,
+ right[1] = -CurrentViewForward()[0]; // r_spritedesc.vright)
+ right[2] = 0;
+ VectorNormalize (right);
+ forward[0] = -right[1];
+ forward[1] = right[0];
+ forward[2] = 0;
+ // CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
+ // r_spritedesc.vpn)
+ }
+ break;
+
+ case SPR_ORIENTED:
+ {
+ // generate the sprite's axes, according to the sprite's world orientation
+ AngleVectors( angles, &forward, &right, &up );
+ }
+ break;
+
+ case SPR_VP_PARALLEL_ORIENTED:
+ {
+ // generate the sprite's axes, parallel to the viewplane, but rotated in
+ // that plane around the center according to the sprite entity's roll
+ // angle. So vpn stays the same, but vright and vup rotate
+ angle = angles[ROLL] * (M_PI*2.0f/360.0f);
+ SinCos( angle, &sr, &cr );
+
+ for (i=0 ; i<3 ; i++)
+ {
+ forward[i] = CurrentViewForward()[i];
+ right[i] = CurrentViewRight()[i] * cr + CurrentViewUp()[i] * sr;
+ up[i] = CurrentViewRight()[i] * -sr + CurrentViewUp()[i] * cr;
+ }
+ }
+ break;
+
+ default:
+ Warning( "GetSpriteAxes: Bad sprite type %d\n", type );
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : int
+//-----------------------------------------------------------------------------
+int C_SpriteRenderer::DrawSprite(
+ IClientEntity *entity,
+ const model_t *model,
+ const Vector& origin,
+ const QAngle& angles,
+ float frame,
+ IClientEntity *attachedto,
+ int attachmentindex,
+ int rendermode,
+ int renderfx,
+ int alpha,
+ int r,
+ int g,
+ int b,
+ float scale,
+ float flHDRColorScale
+ )
+{
+ VPROF_BUDGET( "C_SpriteRenderer::DrawSprite", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
+
+ if ( !r_drawsprites.GetBool() || !model || modelinfo->GetModelType( model ) != mod_sprite )
+ {
+ return 0;
+ }
+
+ // Get extra data
+ CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData( model );
+ if ( !psprite )
+ {
+ return 0;
+ }
+
+ Vector effect_origin;
+ VectorCopy( origin, effect_origin );
+
+ // Use attachment point
+ if ( attachedto )
+ {
+ C_BaseEntity *ent = attachedto->GetBaseEntity();
+ if ( ent )
+ {
+ // don't draw viewmodel effects in reflections
+ if ( CurrentViewID() == VIEW_REFLECTION )
+ {
+ int group = ent->GetRenderGroup();
+ if ( group == RENDER_GROUP_VIEW_MODEL_TRANSLUCENT || group == RENDER_GROUP_VIEW_MODEL_OPAQUE )
+ return 0;
+ }
+ QAngle temp;
+ ent->GetAttachment( attachmentindex, effect_origin, temp );
+ }
+ }
+
+ if ( rendermode != kRenderNormal )
+ {
+ float blend = render->GetBlend();
+
+ // kRenderGlow and kRenderWorldGlow have a special blending function
+ if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
+ {
+ blend *= GlowBlend( psprite, effect_origin, rendermode, renderfx, alpha, &scale );
+
+ // Fade out the sprite depending on distance from the view origin.
+ r *= blend;
+ g *= blend;
+ b *= blend;
+ }
+
+ render->SetBlend( blend );
+ if ( blend <= 0.0f )
+ {
+ return 0;
+ }
+ }
+
+ // Get orthonormal basis
+ Vector forward, right, up;
+ GetSpriteAxes( (SPRITETYPE)psprite->GetOrientation(), origin, angles, forward, right, up );
+
+ // Draw
+ DrawSpriteModel(
+ entity,
+ psprite,
+ effect_origin,
+ scale,
+ frame,
+ rendermode,
+ r,
+ g,
+ b,
+ alpha,
+ forward, right, up, flHDRColorScale );
+
+ return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CSprite::GetToolRecordingState( KeyValues *msg )
+{
+ if ( !ToolsEnabled() )
+ return;
+
+ VPROF_BUDGET( "CSprite::GetToolRecordingState", VPROF_BUDGETGROUP_TOOLS );
+
+ BaseClass::GetToolRecordingState( msg );
+
+ // Use attachment point
+ if ( m_hAttachedToEntity )
+ {
+ C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity();
+ if ( ent )
+ {
+ BaseEntityRecordingState_t *pState = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" );
+
+ // override position if we're driven by an attachment
+ QAngle temp;
+ pState->m_vecRenderOrigin = GetAbsOrigin();
+ ent->GetAttachment( m_nAttachment, pState->m_vecRenderOrigin, temp );
+
+ // override viewmodel if we're driven by an attachment
+ bool bViewModel = dynamic_cast< C_BaseViewModel* >( ent ) != NULL;
+ msg->SetInt( "viewmodel", bViewModel );
+ }
+ }
+
+ float renderscale = GetRenderScale();
+ if ( m_bWorldSpaceScale )
+ {
+ CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() );
+ float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() );
+ renderscale /= flMinSize;
+ }
+
+ // sprite params
+ static SpriteRecordingState_t state;
+ state.m_flRenderScale = renderscale;
+ state.m_flFrame = m_flFrame;
+ state.m_flProxyRadius = m_flGlowProxySize;
+ state.m_nRenderMode = GetRenderMode();
+ state.m_nRenderFX = m_nRenderFX;
+ state.m_Color.SetColor( m_clrRender.GetR(), m_clrRender.GetG(), m_clrRender.GetB(), GetRenderBrightness() );
+
+ msg->SetPtr( "sprite", &state );
+}