diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/c_sprite.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-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.cpp | 1000 |
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 ¶ms, 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 ¶ms, 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 ); +} |