mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-20 04:26:03 +08:00
Added original SDK code for Alien Swarm.
This commit is contained in:
501
game/client/c_sprite.cpp
Normal file
501
game/client/c_sprite.cpp
Normal file
@ -0,0 +1,501 @@
|
||||
//===== Copyright <20> 1996-2005, 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 )
|
||||
{
|
||||
if ( g_pClientLeafSystem->IsRenderingWithViewModels( ent->RenderHandle() ) )
|
||||
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 = ToBaseViewModel( 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;
|
||||
}
|
||||
|
||||
color24 c = GetRenderColor();
|
||||
|
||||
// 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 = GetRenderFX() ? true : false;
|
||||
state.m_Color.SetColor( c.r, c.g, c.b, GetRenderBrightness() );
|
||||
|
||||
msg->SetPtr( "sprite", &state );
|
||||
}
|
Reference in New Issue
Block a user