source-engine/game/client/portal/C_PortalGhostRenderable.cpp
2022-04-16 12:05:19 +03:00

378 lines
9.4 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "C_PortalGhostRenderable.h"
#include "PortalRender.h"
#include "c_portal_player.h"
#include "model_types.h"
C_PortalGhostRenderable::C_PortalGhostRenderable( C_Prop_Portal *pOwningPortal, C_BaseEntity *pGhostSource, RenderGroup_t sourceRenderGroup, const VMatrix &matGhostTransform, float *pSharedRenderClipPlane, bool bLocalPlayer )
: m_pGhostedRenderable( pGhostSource ),
m_matGhostTransform( matGhostTransform ),
m_pSharedRenderClipPlane( pSharedRenderClipPlane ),
m_bLocalPlayer( bLocalPlayer ),
m_pOwningPortal( pOwningPortal )
{
m_bSourceIsBaseAnimating = (dynamic_cast<C_BaseAnimating *>(pGhostSource) != NULL);
cl_entitylist->AddNonNetworkableEntity( GetIClientUnknown() );
g_pClientLeafSystem->AddRenderable( this, sourceRenderGroup );
}
C_PortalGhostRenderable::~C_PortalGhostRenderable( void )
{
m_pGhostedRenderable = NULL;
g_pClientLeafSystem->RemoveRenderable( RenderHandle() );
cl_entitylist->RemoveEntity( GetIClientUnknown()->GetRefEHandle() );
DestroyModelInstance();
}
void C_PortalGhostRenderable::PerFrameUpdate( void )
{
if( m_pGhostedRenderable )
{
SetModelName( m_pGhostedRenderable->GetModelName() );
SetModelIndex( m_pGhostedRenderable->GetModelIndex() );
SetEffects( m_pGhostedRenderable->GetEffects() | EF_NOINTERP );
m_flAnimTime = m_pGhostedRenderable->m_flAnimTime;
if( m_bSourceIsBaseAnimating )
{
C_BaseAnimating *pSource = (C_BaseAnimating *)m_pGhostedRenderable;
SetCycle( pSource->GetCycle() );
SetSequence( pSource->GetSequence() );
m_nBody = pSource->m_nBody;
m_nSkin = pSource->m_nSkin;
}
}
// Set position and angles relative to the object it's ghosting
Vector ptNewOrigin = m_matGhostTransform * m_pGhostedRenderable->GetAbsOrigin();
QAngle qNewAngles = TransformAnglesToWorldSpace( m_pGhostedRenderable->GetAbsAngles(), m_matGhostTransform.As3x4() );
SetAbsOrigin( ptNewOrigin );
SetAbsAngles( qNewAngles );
AddEffects( EF_NOINTERP );
RemoveFromInterpolationList();
g_pClientLeafSystem->RenderableChanged( RenderHandle() );
}
Vector const& C_PortalGhostRenderable::GetRenderOrigin( void )
{
if( m_pGhostedRenderable == NULL )
return m_ReferencedReturns.vRenderOrigin;
m_ReferencedReturns.vRenderOrigin = m_matGhostTransform * m_pGhostedRenderable->GetRenderOrigin();
return m_ReferencedReturns.vRenderOrigin;
}
QAngle const& C_PortalGhostRenderable::GetRenderAngles( void )
{
if( m_pGhostedRenderable == NULL )
return m_ReferencedReturns.qRenderAngle;
m_ReferencedReturns.qRenderAngle = TransformAnglesToWorldSpace( m_pGhostedRenderable->GetRenderAngles(), m_matGhostTransform.As3x4() );
return m_ReferencedReturns.qRenderAngle;
}
bool C_PortalGhostRenderable::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
{
if( m_pGhostedRenderable == NULL )
return false;
int nModelIndex = 0;
CBaseCombatWeapon *pParent = dynamic_cast<CBaseCombatWeapon*>( m_pGhostedRenderable );
if ( pParent )
{
nModelIndex = pParent->GetModelIndex();
pParent->SetModelIndex( pParent->GetWorldModelIndex() );
}
if( m_pGhostedRenderable->SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime ) )
{
if( pBoneToWorldOut )
{
for( int i = 0; i != nMaxBones; ++i ) //FIXME: nMaxBones is most definitely greater than the actual number of bone transforms actually used, find the subset somehow
{
pBoneToWorldOut[i] = (m_matGhostTransform * pBoneToWorldOut[i]).As3x4();
}
}
return true;
}
if ( pParent )
{
pParent->SetModelIndex( nModelIndex );
}
return false;
}
void C_PortalGhostRenderable::GetRenderBounds( Vector& mins, Vector& maxs )
{
if( m_pGhostedRenderable == NULL )
{
mins = maxs = vec3_origin;
return;
}
m_pGhostedRenderable->GetRenderBounds( mins, maxs );
}
void C_PortalGhostRenderable::GetRenderBoundsWorldspace( Vector& mins, Vector& maxs )
{
if( m_pGhostedRenderable == NULL )
{
mins = maxs = vec3_origin;
return;
}
m_pGhostedRenderable->GetRenderBoundsWorldspace( mins, maxs );
TransformAABB( m_matGhostTransform.As3x4(), mins, maxs, mins, maxs );
}
void C_PortalGhostRenderable::GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType )
{
m_pGhostedRenderable->GetShadowRenderBounds( mins, maxs, shadowType );
TransformAABB( m_matGhostTransform.As3x4(), mins, maxs, mins, maxs );
}
/*bool C_PortalGhostRenderable::GetShadowCastDistance( float *pDist, ShadowType_t shadowType ) const
{
if( m_pGhostedRenderable == NULL )
return false;
return m_pGhostedRenderable->GetShadowCastDistance( pDist, shadowType );
}
bool C_PortalGhostRenderable::GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const
{
if( m_pGhostedRenderable == NULL )
return false;
if( m_pGhostedRenderable->GetShadowCastDirection( pDirection, shadowType ) )
{
if( pDirection )
*pDirection = m_matGhostTransform.ApplyRotation( *pDirection );
return true;
}
return false;
}*/
const matrix3x4_t & C_PortalGhostRenderable::RenderableToWorldTransform()
{
if( m_pGhostedRenderable == NULL )
return m_ReferencedReturns.matRenderableToWorldTransform;
ConcatTransforms( m_matGhostTransform.As3x4(), m_pGhostedRenderable->RenderableToWorldTransform(), m_ReferencedReturns.matRenderableToWorldTransform );
return m_ReferencedReturns.matRenderableToWorldTransform;
}
bool C_PortalGhostRenderable::GetAttachment( int number, Vector &origin, QAngle &angles )
{
if( m_pGhostedRenderable == NULL )
return false;
if( m_pGhostedRenderable->GetAttachment( number, origin, angles ) )
{
origin = m_matGhostTransform * origin;
angles = TransformAnglesToWorldSpace( angles, m_matGhostTransform.As3x4() );
return true;
}
return false;
}
bool C_PortalGhostRenderable::GetAttachment( int number, matrix3x4_t &matrix )
{
if( m_pGhostedRenderable == NULL )
return false;
if( m_pGhostedRenderable->GetAttachment( number, matrix ) )
{
ConcatTransforms( m_matGhostTransform.As3x4(), matrix, matrix );
return true;
}
return false;
}
bool C_PortalGhostRenderable::GetAttachment( int number, Vector &origin )
{
if( m_pGhostedRenderable == NULL )
return false;
if( m_pGhostedRenderable->GetAttachment( number, origin ) )
{
origin = m_matGhostTransform * origin;
return true;
}
return false;
}
bool C_PortalGhostRenderable::GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel )
{
if( m_pGhostedRenderable == NULL )
return false;
Vector ghostVel;
if( m_pGhostedRenderable->GetAttachmentVelocity( number, ghostVel, angleVel ) )
{
Vector3DMultiply( m_matGhostTransform, ghostVel, originVel );
Vector3DMultiply( m_matGhostTransform, *(Vector*)( &angleVel ), *(Vector*)( &angleVel ) );
return true;
}
return false;
}
int C_PortalGhostRenderable::DrawModel( int flags )
{
if( m_bSourceIsBaseAnimating )
{
if( m_bLocalPlayer )
{
C_Portal_Player *pPlayer = C_Portal_Player::GetLocalPlayer();
if ( !pPlayer->IsAlive() )
{
// Dead player uses a ragdoll to draw, so don't ghost the dead entity
return 0;
}
else if( g_pPortalRender->GetViewRecursionLevel() == 0 )
{
if( pPlayer->m_bEyePositionIsTransformedByPortal )
return 0;
}
else if( g_pPortalRender->GetViewRecursionLevel() == 1 )
{
if( !pPlayer->m_bEyePositionIsTransformedByPortal )
return 0;
}
}
return C_BaseAnimating::DrawModel( flags );
}
else
{
DrawBrushModelMode_t mode = DBM_DRAW_ALL;
if ( flags & STUDIO_TWOPASS )
{
mode = ( flags & STUDIO_TRANSPARENCY ) ? DBM_DRAW_TRANSLUCENT_ONLY : DBM_DRAW_OPAQUE_ONLY;
}
render->DrawBrushModelEx( m_pGhostedRenderable,
(model_t *)m_pGhostedRenderable->GetModel(),
GetRenderOrigin(),
GetRenderAngles(),
mode );
return 1;
}
return 0;
}
ModelInstanceHandle_t C_PortalGhostRenderable::GetModelInstance()
{
if ( m_pGhostedRenderable )
return m_pGhostedRenderable->GetModelInstance();
return BaseClass::GetModelInstance();
}
bool C_PortalGhostRenderable::IsTransparent( void )
{
if( m_pGhostedRenderable == NULL )
return false;
return m_pGhostedRenderable->IsTransparent();
}
bool C_PortalGhostRenderable::UsesPowerOfTwoFrameBufferTexture()
{
if( m_pGhostedRenderable == NULL )
return false;
return m_pGhostedRenderable->UsesPowerOfTwoFrameBufferTexture();
}
/*const model_t* C_PortalGhostRenderable::GetModel( ) const
{
if( m_pGhostedRenderable == NULL )
return NULL;
return m_pGhostedRenderable->GetModel();
}
int C_PortalGhostRenderable::GetBody()
{
if( m_pGhostedRenderable == NULL )
return 0;
return m_pGhostedRenderable->GetBody();
}*/
void C_PortalGhostRenderable::GetColorModulation( float* color )
{
if( m_pGhostedRenderable == NULL )
return;
return m_pGhostedRenderable->GetColorModulation( color );
}
/*ShadowType_t C_PortalGhostRenderable::ShadowCastType()
{
if( m_pGhostedRenderable == NULL )
return SHADOWS_NONE;
return m_pGhostedRenderable->ShadowCastType();
}*/
int C_PortalGhostRenderable::LookupAttachment( const char *pAttachmentName )
{
if( m_pGhostedRenderable == NULL )
return -1;
return m_pGhostedRenderable->LookupAttachment( pAttachmentName );
}
/*int C_PortalGhostRenderable::GetSkin()
{
if( m_pGhostedRenderable == NULL )
return -1;
return m_pGhostedRenderable->GetSkin();
}
bool C_PortalGhostRenderable::IsTwoPass( void )
{
if( m_pGhostedRenderable == NULL )
return false;
return m_pGhostedRenderable->IsTwoPass();
}*/