|
|
//========= Copyright � 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose: this is the only public access point to the Fog of War routines
//
// $NoKeywords: $
//=====================================================================================//
#ifndef FOW_H
#define FOW_H
#if defined( COMPILER_MSVC )
#pragma once
#endif
#include "utlvector.h"
#include "utlmap.h"
#include "utlspheretree.h"
class CFoW_RadiusOccluder; class CFoW_Viewer; class CFoW_TriSoupCollection; class CFoW_LineOccluder; class CFoW_HorizontalSlice; class IFileSystem; class CPhysCollide; class IPhysicsCollision;
// maximum number of unique visible sides / teams
#define MAX_FOW_TEAMS 2
// fow does maximum amount of safety checks for data coming into it
#define FOW_SAFETY_DANCE 1
// bit pattern for Visibility Grid
#define FOW_VG_MAX_HEIGHT_GROUP 0x07 // only support height groups from 0 to 7
#define FOW_VG_UNUSED 0x08 // unused
#define FOW_VG_DEFAULT_VISIBLE 0x10 // future optimization to mark default viewing radius
#define FOW_VG_IS_VISIBLE 0x20 // cell is currently visible
#define FOW_VG_WAS_VISIBLE 0x40 // cell has been visible at one point in the past
#define FOW_VG_INVALID 0x80 // invalid cell location
// debug flags
#define FOW_DEBUG_SHOW_VIEWERS_TEAM_0 0x00000001
#define FOW_DEBUG_SHOW_OCCLUDERS 0x00000002
#define FOW_DEBUG_SHOW_GRID 0x00000004
#define FOW_DEBUG_SHOW_VIEWERS_TEAM_1 0x00000008
#define FOW_DEBUG_VIEW_TIME ( 1.0f / 15.0f )
//#define FOW_DEBUG_VIEW_TIME ( 0 )
// fow limits
#define FOW_MAX_VIEWERS_TO_CHECK 100
#define FOW_MAX_RADIUS_OCCLUDERS_TO_CHECK 400
#define FOW_MAX_LINE_OCCLUDERS_TO_CHECK 400
#define FOW_OVER_VISIBILITY 1.5f // keeps around a fully visibile area a bit longer
#define FOW_FADE_DELAY 0.25f; // helps control flickering on edge cases when viewers are moving
class CFoW { public: CFoW( ); ~CFoW( );
// setup
// Frees all memory
void ClearState( ); // Sets the number of viewer teams
void SetNumberOfTeams( int nCount ); // Sets the world mins/maxs and how big the grid sizes should be
void SetSize( Vector &vWorldMins, Vector &vWorldMaxs, int nHorizontalGridSize, int nVerticalGridSize = -1 ); //
void SetCustomVerticalLevels( float *pflHeightLevels, int nCount ); // Sets the visibility degree fade rate ( in seconds )
void SetDegreeFadeRate( float flDegreeFadeRate ) { m_flDegreeFadeRate = flDegreeFadeRate; }
// fow system info
// are we initialized?
bool IsInitialized( ) { return m_bInitialized; } // get the world size of the FoW
void GetSize( Vector &vWorldMins, Vector &vWorldMaxs ); // get the horizontal grid size
inline int GetHorizontalGridSize( ) { return m_nHorizontalGridSize; } //
int GetXGridUnits( ) { return m_nGridXUnits; } //
int GetYGridUnits( ) { return m_nGridYUnits; } // get the lower vertical coord, the grid size, and grid units
void GetVerticalGridInfo( int &nBottomZ, int &nGridSize, int &nGridUnits, float **pVerticalLevels ); // snap the x/y coordinates to the grid
void SnapCoordsToGrid( Vector &vIn, Vector &vOut, bool bGoLower ); // return how visible a cell is ( 0.0 = not currently visible, 1.0 = fully visible )
float LookupVisibilityDegree( int nXLoc, int nYLoc, int nTeam ); // creates or returns a grid to radius table
int *FindRadiusTable( float flRadius ); //
void CenterCoordToGrid( Vector &vCoords );
// debug info
//
void SetDebugVisibility( bool bVisible ); //
void EnableDebugFlags( unsigned nFlags ); //
void DisableDebugFlags( unsigned nFlags ); //
void DrawDebugInfo( Vector &vLocation, float flViewRadius ); //
void PrintStats( );
// viewers
// adds a new viewer to the system
int AddViewer( unsigned nViewerTeam ); // removes a viewer from the system
void RemoveViewer( int nID ); // updates the viewer's location
void UpdateViewerLocation( int nID, const Vector &vLocation ); // updates the viewer's seeing radius
void UpdateViewerSize( int nID, float flRadius ); // updates the viewer's seeing radius
void UpdateViewerHeightGroup( int nID, uint8 nHeightGroup );
// radius occluders
// adds a new radius occluder to the system
int AddOccluder( bool nPermanent ); // removes an occluder from the system
void RemoveOccluder( int nID ); void EnableOccluder( int nID, bool bEnable ); // returns the total number of radius occluders
inline int GetNumOccluders() { return m_Occluders.Count(); } // get access to the radius occluder object
inline CFoW_RadiusOccluder *GetOccluder( int nIndex ) { return m_Occluders[ nIndex ]; } // update an occluder's location
void UpdateOccluderLocation( int nID, Vector &vLocation ); // update an occluder's size
void UpdateOccluderSize( int nID, float flRadius ); // updates the occluder's height group
void UpdateOccluderHeightGroup( int nID, uint8 nHeightGroup ); // internal function called by viewers to radius occlude nearby objects
void ObstructOccludersNearViewer( int nViewerID );
// world occlusion
void SetWorldCollision( CPhysCollide *pCollideable, IPhysicsCollision *pPhysCollision );
// tri soup ( line ) occluders
// adds a tri soup collection to the system
int AddTriSoup( ); // removes a tri soup collection from the system
void RemoveTriSoup( int nID ); // clears all entries from the collection ( useful for hammer editing only )
void ClearTriSoup( int nID ); // adds a tri to the collection. this is immediately split up into the horizontal slices. very slow!
void AddTri( int nID, Vector &vPointA, Vector &vPointB, Vector &vPointC ); //
int GetNumTriSoups( ) { return m_TriSoupCollection.Count(); } // get access to a tri soup collection object
CFoW_TriSoupCollection *GetTriSoup( int nID ); // add a line occulder from a horizontal slice
void AddTriSoupOccluder( CFoW_LineOccluder *pOccluder, int nSliceNum );
// horizontal slices ( from tri soups )
// get the slice index given the vertical position
int GetHorizontalSlice( float flZPos ); //
float GetSliceZPosition( int nIndex ) { return m_pVerticalLevels[ nIndex ]; } // get access to the slice object
inline CFoW_HorizontalSlice *GetSlice( int nIndex ) { return m_pHorizontalSlices[ nIndex ]; }
// visibility
// solve the visibility for all teams and all viewers - slow!
void SolveVisibility( float flFrameTime ); // Purpose: returns the visibility info of a location to a team
uint8 GetLocationInfo( unsigned nViewerTeam, const Vector &vLocation ); // Purpose: returns the visibility degree of a location to a team
float GetLocationVisibilityDegree( unsigned nViewerTeam, const Vector &vLocation, float flRadius = 0.0f ); // given the coords and an offset to move BACK, finds the grid location
void GetGridUnits( const Vector &vCoords, float flXOffset, float flYOffset, bool bGoLower, int &nGridX, int &nGridY );
// debug
// Generates a vmf file based upon the current viewers and occluders
void GenerateVMF( IFileSystem *pFileSystem, const char *pszFileName );
private: // adds an occluder to the sphere tree
void InsertViewerIntoTree( int nIndex ); // removes an occluder from the sphere tree
void RemoveViewerFromTree( int nIndex, Vector *pvOldLocation = NULL ); //
void DirtyViewers( Vector &vLocation, float flRadius ); // adds all occluders back into the visibility tree
void RepopulateOccluders( ); // adds an occluder to the sphere tree
void InsertOccluderIntoTree( int nIndex ); // removes an occluder from the sphere tree
void RemoveOccluderFromTree( int nIndex ); // defaults the viewing grids
void PrepVisibility( ); // updates the viewer grids
void UpdateVisibleAmounts( float flFrameTime ); // given the coords and an offset to move BACK, finds the grid index
int GetGridIndex( const Vector &vCoords, float flXOffset, float flYOffset, bool bGoLower ); // merge a local viewer's visibility to the global grid
void MergeViewerVisibility( int nID );
private: bool m_bInitialized; // fow system is ready
int m_nNumberOfTeams; // number of teams
Vector m_vWorldMins; // world mins
Vector m_vWorldMaxs; // world maxs
float m_flDegreeFadeRate; // fade in rate for visibility degree
int m_nHorizontalGridSize; // the horizontal ( x y ) grid size
int m_nVerticalGridSize; // the vertical ( z ) grid size
int m_nGridXUnits; // number of X grid pieces ( world X size / horizontal grid size ) rounded up
int m_nGridYUnits; // number of Y grid pieces ( world Y size / horizontal grid size ) rounded up
int m_nTotalHorizontalUnits; // X * Y grid pieces
int m_nGridZUnits; // number of Z grid pieces ( world Z size / vertical grid size ) rounded up
float32 *m_pVisibilityGridDegree[ MAX_FOW_TEAMS ]; // the degree of visibility ( 0.0 = not visible, 1.0 = visible )
float32 *m_pVisibilityFadeTimer[ MAX_FOW_TEAMS ]; // the delay before visibility starts to fade
uint8 *m_pVisibilityGridFlags[ MAX_FOW_TEAMS ]; // flags to indicate visibility status
CFoW_HorizontalSlice **m_pHorizontalSlices; // horizontal line occluder slices from tri soups
float32 *m_pVerticalLevels;
CUtlVector< CFoW_Viewer * > m_Viewers; // the list of all viewers
CUtlVector< CFoW_RadiusOccluder * > m_Occluders; // the list of all radius occluders
CUtlSphereTree m_ViewerTree; // sphere tree for quick finding of nearby viewers
CUtlSphereTree m_OccluderTree; // sphere tree for quick finding of nearby radius occluders
CUtlVector< CFoW_TriSoupCollection * > m_TriSoupCollection; // the list of all tri soups
CUtlMap< float, int * > m_RadiusTables; // the cached visibility tables to go from grid to radius
// debug info
bool m_bDebugVisible; unsigned m_nDebugFlags; size_t m_nHorizontalGridAllocationSize; size_t m_nVerticalGridAllocationSize; size_t m_nRadiusTableSize;
friend void PrepVisibilityThreaded( CFoW *pFoW ); };
#endif // FOW_H
|