|
|
//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "weapon_ifmbasecamera.h"
#ifdef CLIENT_DLL
#include "view_shared.h"
#include "iviewrender.h"
#include "vgui_controls/controls.h"
#include "vgui/isurface.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
bool ToolFramework_SetupEngineView( Vector &origin, QAngle &angles, float &fov );
#endif
#define INSET_VIEW_FACTOR 0.3f
//-----------------------------------------------------------------------------
// CWeaponIFMBaseCamera tables.
//-----------------------------------------------------------------------------
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponIFMBaseCamera, DT_WeaponIFMBaseCamera ) LINK_ENTITY_TO_CLASS( weapon_ifm_base_camera, CWeaponIFMBaseCamera );
BEGIN_NETWORK_TABLE( CWeaponIFMBaseCamera, DT_WeaponIFMBaseCamera ) #if !defined( CLIENT_DLL )
SendPropFloat( SENDINFO( m_flRenderAspectRatio ), 0, SPROP_NOSCALE ), SendPropFloat( SENDINFO( m_flRenderFOV ), 0, SPROP_NOSCALE ), SendPropFloat( SENDINFO( m_flRenderArmLength ), 0, SPROP_NOSCALE ), SendPropVector( SENDINFO( m_vecRenderPosition ), 0, SPROP_NOSCALE ), SendPropQAngles( SENDINFO( m_angRenderAngles ), 0, SPROP_NOSCALE ), #else
RecvPropFloat( RECVINFO( m_flRenderAspectRatio ) ), RecvPropFloat( RECVINFO( m_flRenderFOV ) ), RecvPropFloat( RECVINFO( m_flRenderArmLength ) ), RecvPropVector( RECVINFO( m_vecRenderPosition ) ), RecvPropQAngles( RECVINFO( m_angRenderAngles ) ), #endif
END_NETWORK_TABLE()
#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CWeaponIFMBaseCamera ) DEFINE_PRED_FIELD( m_flFOV, FIELD_FLOAT, 0 ), DEFINE_PRED_FIELD( m_flArmLength, FIELD_FLOAT, 0 ), DEFINE_PRED_FIELD( m_vecRelativePosition, FIELD_VECTOR, 0 ), DEFINE_PRED_FIELD( m_angRelativeAngles, FIELD_VECTOR, 0 ), DEFINE_PRED_FIELD( m_bFullScreen, FIELD_BOOLEAN, 0 ), END_PREDICTION_DATA()
#endif
#ifdef GAME_DLL
BEGIN_DATADESC( CWeaponIFMBaseCamera ) DEFINE_FIELD( m_flRenderAspectRatio, FIELD_FLOAT ), DEFINE_FIELD( m_flRenderFOV, FIELD_FLOAT ), DEFINE_FIELD( m_flRenderArmLength, FIELD_FLOAT ), DEFINE_FIELD( m_vecRenderPosition, FIELD_VECTOR ), DEFINE_FIELD( m_angRenderAngles, FIELD_VECTOR ), END_DATADESC()
#endif
//-----------------------------------------------------------------------------
// CWeaponIFMBaseCamera implementation.
//-----------------------------------------------------------------------------
CWeaponIFMBaseCamera::CWeaponIFMBaseCamera() { #ifdef CLIENT_DLL
m_flFOV = 75.0f; m_flArmLength = 4; m_vecRelativePosition.Init(); m_angRelativeAngles.Init(); m_bFullScreen = false; m_nScreenWidth = 0; m_nScreenHeight = 0; #endif
}
//-----------------------------------------------------------------------------
//
// Specific methods on the server
//
//-----------------------------------------------------------------------------
#ifdef GAME_DLL
void CWeaponIFMBaseCamera::SetRenderInfo( float flAspectRatio, float flFOV, float flArmLength, const Vector &vecPosition, const QAngle &angles ) { m_flRenderAspectRatio = flAspectRatio; m_flRenderFOV = flFOV; m_flRenderArmLength = flArmLength; m_vecRenderPosition = vecPosition; m_angRenderAngles = angles; }
CON_COMMAND( ifm_basecamera_camerastate, "Set camera state" ) { CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); if ( !pPlayer ) return;
if ( args.ArgC() != 10 ) return; Vector vecPosition; QAngle angAngles; float flAspectRatio = atof( args[1] ); float flFOV = atof( args[2] ); float flArmLength = atof( args[3] ); vecPosition.x = atof( args[4] ); vecPosition.y = atof( args[5] ); vecPosition.z = atof( args[6] ); angAngles.x = atof( args[7] ); angAngles.y = atof( args[8] ); angAngles.z = atof( args[9] );
int nCount = pPlayer->WeaponCount(); for ( int i = 0; i < nCount; ++i ) { CWeaponIFMBaseCamera *pCamera = dynamic_cast<CWeaponIFMBaseCamera*>( pPlayer->GetWeapon( i ) ); if ( !pCamera ) continue;
pCamera->SetRenderInfo( flAspectRatio, flFOV, flArmLength, vecPosition, angAngles ); } }
#endif // GAME_DLL
//-----------------------------------------------------------------------------
//
// Specific methods on the client
//
//-----------------------------------------------------------------------------
#ifdef CLIENT_DLL
//-----------------------------------------------------------------------------
// Sets up the material to draw with
//-----------------------------------------------------------------------------
void CWeaponIFMBaseCamera::OnDataChanged( DataUpdateType_t updateType ) { BaseClass::OnDataChanged( updateType ); if (updateType == DATA_UPDATE_CREATED) { m_FrustumMaterial.Init( "effects/steadycamfrustum", TEXTURE_GROUP_OTHER ); m_FrustumWireframeMaterial.Init( "debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER ); } }
//-----------------------------------------------------------------------------
// Transmits render information
//-----------------------------------------------------------------------------
void CWeaponIFMBaseCamera::TransmitRenderInfo() { float flAspectRatio = (m_nScreenHeight != 0) ? (float)m_nScreenWidth / (float)m_nScreenHeight : 1.0f; float flFOV = m_flFOV;
Vector position; QAngle angles; ComputeAbsCameraTransform( position, angles );
// give the toolsystem a chance to override the view
ToolFramework_SetupEngineView( position, angles, flFOV );
char pBuf[256]; Q_snprintf( pBuf, sizeof(pBuf), "ifm_basecamera_camerastate %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f", flAspectRatio, flFOV, m_flArmLength, position.x, position.y, position.z, angles.x, angles.y, angles.z );
engine->ClientCmd( pBuf ); }
//-----------------------------------------------------------------------------
// Purpose: In 3rd person, draws the cone of the steadycam
//-----------------------------------------------------------------------------
#define FRUSTUM_SIZE 1000
int CWeaponIFMBaseCamera::DrawModel( int flags, const RenderableInstance_t &instance ) { int nRetVal = BaseClass::DrawModel( flags, instance );
CBasePlayer *pPlayer = GetPlayerOwner(); if ( pPlayer && !pPlayer->IsLocalPlayer( this ) ) { // Compute endpoints
float flMaxD = 1.0f / tan( M_PI * m_flFOV / 360.0f ); float ex = flMaxD * FRUSTUM_SIZE; float ey = flMaxD * FRUSTUM_SIZE / m_flRenderAspectRatio;
// Compute basis
Vector vecForward, vecUp, vecRight; AngleVectors( m_angRenderAngles, &vecForward, &vecRight, &vecUp );
Vector vecCenter; VectorMA( m_vecRenderPosition, FRUSTUM_SIZE, vecForward, vecCenter );
Vector vecEndPoint[4]; VectorMA( vecCenter, ex, vecRight, vecEndPoint[0] ); VectorMA( vecEndPoint[0], ey, vecUp, vecEndPoint[0] ); VectorMA( vecEndPoint[0], -2.0f * ex, vecRight, vecEndPoint[1] ); VectorMA( vecEndPoint[1], -2.0f * ey, vecUp, vecEndPoint[2] ); VectorMA( vecEndPoint[2], 2.0f * ex, vecRight, vecEndPoint[3] );
CMatRenderContextPtr pRenderContext( materials ); pRenderContext->Bind( m_FrustumMaterial ); IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
CMeshBuilder meshBuilder; meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 4 ); for ( int i = 0; i < 4; ++i ) { meshBuilder.Position3fv( m_vecRenderPosition.Get().Base() ); meshBuilder.Color4ub( 128, 0, 0, 255 ); meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vecEndPoint[i].Base() ); meshBuilder.Color4ub( 128, 0, 0, 255 ); meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vecEndPoint[(i+1)%4].Base() ); meshBuilder.Color4ub( 128, 0, 0, 255 ); meshBuilder.AdvanceVertex(); }
meshBuilder.End(); pMesh->Draw();
pRenderContext->Bind( m_FrustumWireframeMaterial ); pMesh = pRenderContext->GetDynamicMesh( true ); meshBuilder.Begin( pMesh, MATERIAL_LINES, 8 ); for ( int i = 0; i < 4; ++i ) { meshBuilder.Position3fv( m_vecRenderPosition.Get().Base() ); meshBuilder.Color4ub( 255, 255, 255, 255 ); meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vecEndPoint[i].Base() ); meshBuilder.Color4ub( 255, 255, 255, 255 ); meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vecEndPoint[i].Base() ); meshBuilder.Color4ub( 255, 255, 255, 255 ); meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vecEndPoint[(i+1)%4].Base() ); meshBuilder.Color4ub( 255, 255, 255, 255 ); meshBuilder.AdvanceVertex(); }
meshBuilder.End(); pMesh->Draw(); }
return nRetVal; }
//-----------------------------------------------------------------------------
// Gets the size of the overlay to draw
//-----------------------------------------------------------------------------
void CWeaponIFMBaseCamera::GetViewportSize( int &w, int &h ) { if ( !m_bFullScreen ) { w = m_nScreenWidth * INSET_VIEW_FACTOR; h = m_nScreenHeight * INSET_VIEW_FACTOR; } else { w = m_nScreenWidth; h = m_nScreenHeight; } }
//-----------------------------------------------------------------------------
// Gets the abs orientation of the camera
//-----------------------------------------------------------------------------
void CWeaponIFMBaseCamera::ComputeAbsCameraTransform( Vector &vecAbsOrigin, QAngle &angAbsRotation ) { CBasePlayer *pPlayer = GetPlayerOwner(); if ( !pPlayer ) { vecAbsOrigin.Init(); angAbsRotation.Init(); return; }
float flFOV = m_flFOV;
float flZNear = view->GetZNear(); float flZFar = view->GetZFar(); Vector viewOrigin; QAngle viewAngles; pPlayer->CalcView( viewOrigin, viewAngles, flZNear, flZFar, flFOV );
// Offset the view along the forward direction vector by the arm length
Vector vecForward; AngleVectors( viewAngles, &vecForward ); VectorMA( viewOrigin, m_flArmLength, vecForward, viewOrigin ); // Use player roll
QAngle angles = m_angRelativeAngles; angles.z = viewAngles.z;
// Compute the actual orientation of the view
matrix3x4_t cameraToWorld, overlayToCamera, overlayToWorld; AngleMatrix( vec3_angle, viewOrigin, cameraToWorld ); AngleMatrix( angles, m_vecRelativePosition, overlayToCamera ); ConcatTransforms( cameraToWorld, overlayToCamera, overlayToWorld ); MatrixAngles( overlayToWorld, angAbsRotation, vecAbsOrigin );
// give the toolsystem a chance to override the view
ToolFramework_SetupEngineView( vecAbsOrigin, angAbsRotation, flFOV ); }
//-----------------------------------------------------------------------------
// Gets the bounds of the overlay to draw
//-----------------------------------------------------------------------------
void CWeaponIFMBaseCamera::GetOverlayBounds( int &x, int &y, int &w, int &h ) { const CViewSetup *pViewSetup = view->GetViewSetup(); if ( !m_bFullScreen ) { w = pViewSetup->width * INSET_VIEW_FACTOR; h = pViewSetup->height * INSET_VIEW_FACTOR; x = pViewSetup->x + ( pViewSetup->width - w ) / 2; y = pViewSetup->height - h; } else { w = pViewSetup->width; h = pViewSetup->height; x = pViewSetup->x; y = pViewSetup->y; } }
//-----------------------------------------------------------------------------
// When drawing the model, if drawing the viewmodel, draw an overlay of what's being rendered
//-----------------------------------------------------------------------------
void CWeaponIFMBaseCamera::ViewModelDrawn( int nFlags, CBaseViewModel *pBaseViewModel ) { // NOTE: This is not recursively called because we do not draw viewmodels in the overlay
CViewSetup overlayView = *view->GetViewSetup();
m_nScreenWidth = overlayView.width; m_nScreenHeight = overlayView.height;
GetOverlayBounds( overlayView.x, overlayView.y, overlayView.width, overlayView.height ); overlayView.m_bRenderToSubrectOfLargerScreen = true; overlayView.fov = m_flFOV;
// Compute the location of the camera
ComputeAbsCameraTransform( overlayView.origin, overlayView.angles );
// give the toolsystem a chance to override the view
ToolFramework_SetupEngineView( overlayView.origin, overlayView.angles, overlayView.fov );
view->QueueOverlayRenderView( overlayView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, RENDERVIEW_UNSPECIFIED ); }
//-----------------------------------------------------------------------------
// Purpose: Draw the weapon's crosshair
//-----------------------------------------------------------------------------
void CWeaponIFMBaseCamera::DrawCrosshair( void ) { BaseClass::DrawCrosshair();
int x, y, w, h; GetOverlayBounds( x, y, w, h );
// Draw the targeting zone around the crosshair
int r, g, b, a; GetHud().m_clrYellowish.GetColor( r, g, b, a );
Color light( r, g, b, 160 );
int nBorderSize = 4; vgui::surface()->DrawSetColor( light ); vgui::surface()->DrawFilledRect( x-nBorderSize, y-nBorderSize, x+w+nBorderSize, y ); vgui::surface()->DrawFilledRect( x-nBorderSize, y+h, x+w+nBorderSize, y+h+nBorderSize ); vgui::surface()->DrawFilledRect( x-nBorderSize, y, x, y+h ); vgui::surface()->DrawFilledRect( x+w, y, x+w+nBorderSize, y+h ); }
#endif // CLIENT_DLL
|