//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //===========================================================================// #include "cbase.h" #include "view_shared.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" class C_FuncReflectiveGlass : public C_BaseEntity { public: DECLARE_CLASS( C_FuncReflectiveGlass, C_BaseEntity ); DECLARE_CLIENTCLASS(); // C_BaseEntity. public: C_FuncReflectiveGlass(); virtual ~C_FuncReflectiveGlass(); virtual bool ShouldDraw(); C_FuncReflectiveGlass *m_pNext; }; IMPLEMENT_CLIENTCLASS_DT( C_FuncReflectiveGlass, DT_FuncReflectiveGlass, CFuncReflectiveGlass ) END_RECV_TABLE() //----------------------------------------------------------------------------- // Globals //----------------------------------------------------------------------------- C_EntityClassList g_ReflectiveGlassList; template<> C_FuncReflectiveGlass *C_EntityClassList::m_pClassList = NULL; C_FuncReflectiveGlass* GetReflectiveGlassList() { return g_ReflectiveGlassList.m_pClassList; } //----------------------------------------------------------------------------- // Constructor, destructor //----------------------------------------------------------------------------- C_FuncReflectiveGlass::C_FuncReflectiveGlass() { g_ReflectiveGlassList.Insert( this ); } C_FuncReflectiveGlass::~C_FuncReflectiveGlass() { g_ReflectiveGlassList.Remove( this ); } bool C_FuncReflectiveGlass::ShouldDraw() { return true; } //----------------------------------------------------------------------------- // Do we have reflective glass in view? //----------------------------------------------------------------------------- bool IsReflectiveGlassInView( const CViewSetup& view, cplane_t &plane ) { // Early out if no cameras C_FuncReflectiveGlass *pReflectiveGlass = GetReflectiveGlassList(); if ( !pReflectiveGlass ) return false; Frustum_t frustum; GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum ); cplane_t localPlane; Vector vecOrigin, vecWorld, vecDelta, vecForward; AngleVectors( view.angles, &vecForward, NULL, NULL ); for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext ) { if ( pReflectiveGlass->IsDormant() ) continue; Vector vecMins, vecMaxs; pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs ); if ( R_CullBox( vecMins, vecMaxs, frustum ) ) continue; const model_t *pModel = pReflectiveGlass->GetModel(); const matrix3x4_t& mat = pReflectiveGlass->EntityToWorldTransform(); int nCount = modelinfo->GetBrushModelPlaneCount( pModel ); for ( int i = 0; i < nCount; ++i ) { modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin ); MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space VectorTransform( vecOrigin, mat, vecWorld ); if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane continue; VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull if ( vecDelta.Dot( plane.normal ) >= 0 ) continue; return true; } } return false; }