initial
This commit is contained in:
52
fow/_vpc_/manifest_fow/win32/manifest.txt
Normal file
52
fow/_vpc_/manifest_fow/win32/manifest.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
// ----------------------------------------- //
|
||||
// File generated by VPC //
|
||||
// ----------------------------------------- //
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\fow\fow.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\fow\fow.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\fow\fow.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\fow\fow_2dplane.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\fow\fow_2dplane.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\fow\fow_2dplane.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\fow\fow_horizontalslice.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\fow\fow_horizontalslice.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\fow\fow_horizontalslice.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\fow\fow_lineoccluder.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\fow\fow_lineoccluder.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\fow\fow_lineoccluder.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\fow\fow_radiusoccluder.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\fow\fow_radiusoccluder.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\fow\fow_radiusoccluder.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\fow\fow_trisoup.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\fow\fow_trisoup.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\fow\fow_trisoup.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\fow\fow_viewer.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\fow\fow_viewer.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\fow\fow_viewer.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
1773
fow/fow.cpp
Normal file
1773
fow/fow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
43
fow/fow.vpc
Normal file
43
fow/fow.vpc
Normal file
@@ -0,0 +1,43 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// FOW.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR ".."
|
||||
$Macro OUTLIBDIR "$SRCDIR\lib\public"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,$SRCDIR\utils\common,$SRCDIR\public\fow"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "FoWLib"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "fow.cpp"
|
||||
$File "fow_2dplane.cpp"
|
||||
$File "fow_horizontalslice.cpp"
|
||||
$File "fow_lineoccluder.cpp"
|
||||
$File "fow_radiusoccluder.cpp"
|
||||
$File "fow_trisoup.cpp"
|
||||
$File "fow_viewer.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "..\public\fow\fow.h"
|
||||
$File "fow_2dplane.h"
|
||||
$File "fow_horizontalslice.h"
|
||||
$File "fow_lineoccluder.h"
|
||||
$File "fow_radiusoccluder.h"
|
||||
$File "fow_trisoup.h"
|
||||
$File "fow_viewer.h"
|
||||
}
|
||||
}
|
||||
13
fow/fow.vpc.vpc_cache
Normal file
13
fow/fow.vpc.vpc_cache
Normal file
@@ -0,0 +1,13 @@
|
||||
"vpc_cache"
|
||||
{
|
||||
"CacheVersion" "1"
|
||||
"win32"
|
||||
{
|
||||
"CRCFile" "fow.vcxproj.vpc_crc"
|
||||
"OutputFiles"
|
||||
{
|
||||
"0" "fow.vcxproj"
|
||||
"1" "fow.vcxproj.filters"
|
||||
}
|
||||
}
|
||||
}
|
||||
156
fow/fow_2dplane.cpp
Normal file
156
fow/fow_2dplane.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "fow_2dplane.h"
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct the plane from the given line segment
|
||||
// Input : bx - starting x coord
|
||||
// by - starting y coord
|
||||
// ex - ending x coord
|
||||
// ey - ending y coord
|
||||
//-----------------------------------------------------------------------------
|
||||
CFOW_2DPlane::CFOW_2DPlane( float bx, float by, float ex, float ey )
|
||||
{
|
||||
Init( bx, by, ex, ey );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct the plane from the given point and normal
|
||||
// Input : x - point on plane
|
||||
// y - point on plane
|
||||
// vNormal - normal of the plane
|
||||
//-----------------------------------------------------------------------------
|
||||
CFOW_2DPlane::CFOW_2DPlane( float x, float y, Vector2D &vNormal )
|
||||
{
|
||||
Init( x, y, vNormal );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct the plane from the given distance and normal
|
||||
// Input : flDistance - distance for the plane
|
||||
// vNormal - normal of the plane
|
||||
//-----------------------------------------------------------------------------
|
||||
CFOW_2DPlane::CFOW_2DPlane( float flDistance, Vector2D &vNormal )
|
||||
{
|
||||
m_flDistance = flDistance;
|
||||
m_vNormal = vNormal;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: init routine to generate the plane from the given line segment
|
||||
// Input : bx - starting x coord
|
||||
// by - starting y coord
|
||||
// ex - ending x coord
|
||||
// ey - ending y coord
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFOW_2DPlane::Init( float bx, float by, float ex, float ey )
|
||||
{
|
||||
float nx = ( ex - bx );
|
||||
float ny = ( ey - by );
|
||||
float flLen = ( float )sqrt( nx * nx + ny * ny );
|
||||
Vector2D vNormal;
|
||||
|
||||
nx /= flLen;
|
||||
ny /= flLen;
|
||||
|
||||
vNormal.x = ny;
|
||||
vNormal.y = -nx;
|
||||
Init( bx, by, vNormal );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: init routine to generate the plane from the given point and normal
|
||||
// Input : x - point on plane
|
||||
// y - point on plane
|
||||
// vNormal - normal of the plane
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFOW_2DPlane::Init( float x, float y, Vector2D &vNormal )
|
||||
{
|
||||
m_vNormal = vNormal;
|
||||
|
||||
m_flDistance = ( x * m_vNormal.x + y * m_vNormal.y );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns true if the point is in front of the plane
|
||||
// Input : px - point to check
|
||||
// py - point to check
|
||||
// Output : returns true if the point is in front of the plane
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CFOW_2DPlane::PointInFront( float px, float py )
|
||||
{
|
||||
return ( DistanceFrom( px, py ) >= 0.0f );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the distance the point is from the plane
|
||||
// Input : px - point to check
|
||||
// py - point to check
|
||||
// Output : returns the distance the point is from the plane
|
||||
//-----------------------------------------------------------------------------
|
||||
float CFOW_2DPlane::DistanceFrom( float px, float py )
|
||||
{
|
||||
float d = ( px * m_vNormal.x + py * m_vNormal.y );
|
||||
|
||||
return d - m_flDistance;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: finds the fraction from the starting point towards the normal along the line formed with ending point
|
||||
// Input : bx - starting x coord of the line segment
|
||||
// by - starting y coord of the line segment
|
||||
// ex - ending x coord of the line segment
|
||||
// ey - ending y coord of the line segment
|
||||
// Output : returns the distance along the line segment the plane from the starting coord
|
||||
//-----------------------------------------------------------------------------
|
||||
float CFOW_2DPlane::DistanceFromLineStart( float bx, float by, float ex, float ey )
|
||||
{
|
||||
Vector2D vPointA( bx, by );
|
||||
Vector2D vPointB( ex, ey );
|
||||
Vector2D vDiff( vPointB - vPointA );
|
||||
Vector2D vNormal = vDiff;
|
||||
float flLen = ( float )sqrt( vDiff.x * vDiff.x + vDiff.y * vDiff.y );
|
||||
|
||||
vNormal /= flLen;
|
||||
|
||||
float t = -( m_vNormal.Dot( vPointA ) - m_flDistance ) / m_vNormal.Dot( vNormal );
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: finds the fraction from the starting point towards the normal along the line formed with ending point
|
||||
// Input : bx - starting x coord of the line segment
|
||||
// by - starting y coord of the line segment
|
||||
// ex - ending x coord of the line segment
|
||||
// ey - ending y coord of the line segment
|
||||
// Output : returns the distance along the line segment the plane from the starting coord
|
||||
//-----------------------------------------------------------------------------
|
||||
float CFOW_2DPlane::DistanceFromRay( float bx, float by, float dx, float dy )
|
||||
{
|
||||
Vector2D vPointA( bx, by );
|
||||
Vector2D vNormal( dx, dy );
|
||||
float flNormalDiff = m_vNormal.Dot( vNormal );
|
||||
|
||||
if ( flNormalDiff == 0.0f )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float t = -( m_vNormal.Dot( vPointA ) - m_flDistance ) / flNormalDiff;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#include <tier0/memdbgoff.h>
|
||||
53
fow/fow_2dplane.h
Normal file
53
fow/fow_2dplane.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: 2d plane routines for Fog of War
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef FOW_2DPLANE_H
|
||||
#define FOW_2DPLANE_H
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
class CFOW_2DPlane
|
||||
{
|
||||
public:
|
||||
CFOW_2DPlane( void ) { }
|
||||
// construct the plane from the given line segment
|
||||
CFOW_2DPlane( float bx, float by, float ex, float ey );
|
||||
// construct the plane from the given point and normal
|
||||
CFOW_2DPlane( float x, float y, Vector2D &vNormal );
|
||||
|
||||
CFOW_2DPlane( float flDistance, Vector2D &vNormal );
|
||||
|
||||
// init routine to generate the plane from the given line segment
|
||||
void Init( float bx, float by, float ex, float ey );
|
||||
// init routine to generate the plane from the given point and normal
|
||||
void Init( float x, float y, Vector2D &vNormal );
|
||||
|
||||
// returns the normal of the plane
|
||||
inline Vector2D &GetNormal( void ) { return m_vNormal; }
|
||||
|
||||
//
|
||||
inline float GetDistance( ) { return m_flDistance; }
|
||||
|
||||
|
||||
// returns true if the point is in front of the plane
|
||||
bool PointInFront( float px, float py );
|
||||
// returns the distance the point is from the plane
|
||||
float DistanceFrom( float px, float py );
|
||||
// finds the fraction from the starting point towards the normal along the line formed with ending point
|
||||
float DistanceFromLineStart( float bx, float by, float ex, float ey );
|
||||
// finds the fraction from the starting point towards the normal along the line formed with ending point
|
||||
float DistanceFromRay( float bx, float by, float dx, float dy );
|
||||
|
||||
private:
|
||||
Vector2D m_vNormal; // the normal of the plane
|
||||
float m_flDistance; // the plane distance
|
||||
};
|
||||
|
||||
#endif // FOW_2DPLANE_H
|
||||
107
fow/fow_horizontalslice.cpp
Normal file
107
fow/fow_horizontalslice.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "fow.h"
|
||||
#include "fow_horizontalslice.h"
|
||||
#include "fow_viewer.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: empty constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CFoW_HorizontalSlice::CFoW_HorizontalSlice( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: clears the sphere tree of all line occluders
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_HorizontalSlice::Clear( void )
|
||||
{
|
||||
m_SphereTree.Purge();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: adds a line occluder to the sphere tree
|
||||
// Input : pLineOccluder - the occluder to add
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_HorizontalSlice::AddHorizontalOccluder( CFoW_LineOccluder *pLineOccluder )
|
||||
{
|
||||
Vector2D start = pLineOccluder->GetStart();
|
||||
Vector2D end = pLineOccluder->GetEnd();
|
||||
Vector2D diff = ( end - start );
|
||||
Sphere_t bounds;
|
||||
|
||||
bounds.x = ( start.x + end.x ) / 2.0f;
|
||||
bounds.y = ( start.y + end.y ) / 2.0f;
|
||||
bounds.z = 0.0f;
|
||||
bounds.w = sqrt( ( diff.x * diff.x ) + ( diff.y * diff.y ) );
|
||||
|
||||
|
||||
m_SphereTree.Insert( (void *)pLineOccluder, &bounds );
|
||||
|
||||
|
||||
#if 0
|
||||
Sphere_t TestSphere( -320, -1088, 0.0f, 592.77820 );
|
||||
|
||||
Vector vDiff = TestSphere.AsVector3D() - bounds.AsVector3D();
|
||||
float flLen = vDiff.Length();
|
||||
|
||||
if ( flLen <= ( bounds.w + TestSphere.w ) )
|
||||
{
|
||||
Msg( "here" );
|
||||
|
||||
CFoW_LineOccluder *FixedPointerArray[ FOW_MAX_LINE_OCCLUDERS_TO_CHECK ];
|
||||
CUtlVector< void * > FoundOccluders( ( void ** )FixedPointerArray, FOW_MAX_LINE_OCCLUDERS_TO_CHECK );
|
||||
int RealCount = m_SphereTree.IntersectWithSphere( TestSphere, true, FoundOccluders, FOW_MAX_LINE_OCCLUDERS_TO_CHECK );
|
||||
|
||||
bool bFound = false;
|
||||
|
||||
for ( int i = 0; i < FoundOccluders.Count(); i++ )
|
||||
{
|
||||
if ( FixedPointerArray[ i ] == pLineOccluder )
|
||||
{
|
||||
bFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bFound == true )
|
||||
{
|
||||
Msg( "We found it!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "WE LOST IT!!!?" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: tests the viewer against all line occluders that are near the viewer
|
||||
// Input : pFoW - the main FoW object
|
||||
// pViewer - the viewer to obstruct
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_HorizontalSlice::ObstructViewer( CFoW *pFoW, CFoW_Viewer *pViewer )
|
||||
{
|
||||
Sphere_t TestSphere( pViewer->GetLocation().x, pViewer->GetLocation().y, 0.0f, pViewer->GetSize() );
|
||||
CFoW_LineOccluder *FixedPointerArray[ FOW_MAX_LINE_OCCLUDERS_TO_CHECK ];
|
||||
CUtlVector< void * > FoundOccluders( ( void ** )FixedPointerArray, FOW_MAX_LINE_OCCLUDERS_TO_CHECK );
|
||||
|
||||
int RealCount = m_SphereTree.IntersectWithSphere( TestSphere, true, FoundOccluders, FOW_MAX_LINE_OCCLUDERS_TO_CHECK );
|
||||
if ( RealCount > FOW_MAX_LINE_OCCLUDERS_TO_CHECK )
|
||||
{
|
||||
// we overflowed, what should we do?
|
||||
}
|
||||
// Msg( "Slice Counts: %d / %d\n", FoundOccluders.Count(), RealCount );
|
||||
|
||||
for ( int i = 0; i < FoundOccluders.Count(); i++ )
|
||||
{
|
||||
FixedPointerArray[ i ]->ObstructViewer( pFoW, pViewer );
|
||||
}
|
||||
}
|
||||
|
||||
#include <tier0/memdbgoff.h>
|
||||
39
fow/fow_horizontalslice.h
Normal file
39
fow/fow_horizontalslice.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: used to cross section maps ( i.e. displacements ) to do fast occlusion against
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef FOW_HORIZONTALSLICE_H
|
||||
#define FOW_HORIZONTALSLICE_H
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "utlspheretree.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "fow_lineoccluder.h"
|
||||
|
||||
class CFoW;
|
||||
class CFoW_Viewer;
|
||||
|
||||
class CFoW_HorizontalSlice
|
||||
{
|
||||
public:
|
||||
CFoW_HorizontalSlice( void );
|
||||
|
||||
// clears the sphere tree of all line occluders
|
||||
void Clear( void );
|
||||
// adds a line occluder to the sphere tree
|
||||
void AddHorizontalOccluder( CFoW_LineOccluder *pLineOccluder );
|
||||
|
||||
// tests the viewer against all line occluders that are near the viewer
|
||||
void ObstructViewer( CFoW *pFoW, CFoW_Viewer *pViewer );
|
||||
|
||||
private:
|
||||
CUtlSphereTree m_SphereTree; // spherical tree to quickly find line occulders near a given point
|
||||
};
|
||||
|
||||
#endif // FOW_HORIZONTALSLICE_H
|
||||
238
fow/fow_lineoccluder.cpp
Normal file
238
fow/fow_lineoccluder.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
#include "fow.h"
|
||||
#include "fow_lineoccluder.h"
|
||||
#include "fow_viewer.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct a line accluder from the given points. the normal is supplied, though if it doesn't match up with the points, then the points are swapped.
|
||||
// Input : bx - starting x coord
|
||||
// by - starting y coord
|
||||
// ex - ending x coord
|
||||
// ey - ending y coord
|
||||
// vNormal - the normal coming from a pre-existing plane from which the line was formed
|
||||
// nSlinceNum - the slice this occluder belongs to
|
||||
//-----------------------------------------------------------------------------
|
||||
CFoW_LineOccluder::CFoW_LineOccluder( float bx, float by, float ex, float ey, Vector2D &vNormal, int nSliceNum )
|
||||
{
|
||||
m_vStart.Init( bx, by );
|
||||
m_vEnd.Init( ex, ey );
|
||||
m_Plane.Init( bx, by, ex, ey );
|
||||
|
||||
if ( fabs( m_Plane.GetNormal().x - vNormal.x ) < 0.1f && fabs( m_Plane.GetNormal().y - vNormal.y ) < 0.1f )
|
||||
{
|
||||
m_vStart.Init( ex, ey );
|
||||
m_vEnd.Init( bx, by );
|
||||
m_Plane.Init( ex, ey, bx, by );
|
||||
}
|
||||
|
||||
m_nSliceNum = nSliceNum;
|
||||
}
|
||||
|
||||
|
||||
CFoW_LineOccluder::CFoW_LineOccluder( Vector2D &vStart, Vector2D &vEnd, CFOW_2DPlane &Plane, int nSliceNum )
|
||||
{
|
||||
m_vStart = vStart;
|
||||
m_vEnd = vEnd;
|
||||
m_Plane = Plane;
|
||||
m_nSliceNum = nSliceNum;
|
||||
}
|
||||
|
||||
// #define SLOW_PATH 1
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: determine the occlusion of this line for the viewer
|
||||
// Input : pFoW - the main FoW object
|
||||
// pViewer - the viewer to obstruct
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_LineOccluder::ObstructViewer( CFoW *pFoW, CFoW_Viewer *pViewer )
|
||||
{
|
||||
int nUnits = pViewer->GetRadiusUnits();
|
||||
int *pVisibility = pViewer->GetVisibilityRadius();
|
||||
|
||||
Vector vCenterLocation = pViewer->GetRealLocation(); // we don't want to use the grid centered location, as the z is not centered
|
||||
float distance = m_Plane.DistanceFrom( vCenterLocation.x, vCenterLocation.y );
|
||||
if ( distance < 0.0f )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SLOW_PATH
|
||||
float flDegreeAmount = 360.0 / pViewer->GetRadiusUnits();
|
||||
CFOW_2DPlane Edge1, Edge2;
|
||||
|
||||
Edge1.Init( vCenterLocation.x, vCenterLocation.y, m_vStart.x, m_vStart.y );
|
||||
Edge2.Init( m_vEnd.x, m_vEnd.y, vCenterLocation.x, vCenterLocation.y );
|
||||
|
||||
float flCurrentDegree = 0.0f;
|
||||
for ( int i = 0; i < nUnits; i++, flCurrentDegree += flDegreeAmount )
|
||||
{
|
||||
Vector Location = pViewer->GetLocation();
|
||||
|
||||
Location.x += cos( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
|
||||
Location.y += sin( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
|
||||
|
||||
float flDistance = m_Plane.DistanceFromLineStart( vCenterLocation.x, vCenterLocation.y, Location.x, Location.y );
|
||||
// flDistance *= pViewer->GetSize();
|
||||
if ( flDistance >= 0.0f )
|
||||
{
|
||||
// distance += Viewer->GetSize();
|
||||
flDistance *= flDistance;
|
||||
if ( flDistance >= 0.0f && flDistance < pVisibility[ i ] )
|
||||
{
|
||||
if ( Edge1.PointInFront( Location.x, Location.y ) && Edge2.PointInFront( Location.x, Location.y ) )
|
||||
{
|
||||
pVisibility[ i ] = flDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
const Vector2D vStraight( 0.0f, 1.0f );
|
||||
|
||||
Vector2D P1( m_vStart.x - vCenterLocation.x, m_vStart.y - vCenterLocation.y );
|
||||
P1.NormalizeInPlace();
|
||||
Vector2D P2( m_vEnd.x - vCenterLocation.x, m_vEnd.y - vCenterLocation.y );
|
||||
P2.NormalizeInPlace();
|
||||
#if 0
|
||||
|
||||
float flCurrentDegree = 0.0f;
|
||||
for ( int i = 0; i < nUnits; i++, flCurrentDegree += flDegreeAmount )
|
||||
{
|
||||
Vector Location = pViewer->GetLocation();
|
||||
|
||||
Location.x += cos( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
|
||||
Location.y += sin( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
|
||||
|
||||
float flDistance = m_Plane.DistanceFromLineStart( vCenterLocation.x, vCenterLocation.y, Location.x, Location.y );
|
||||
// flDistance *= pViewer->GetSize();
|
||||
if ( flDistance >= 0.0f )
|
||||
{
|
||||
// distance += Viewer->GetSize();
|
||||
flDistance *= flDistance;
|
||||
if ( flDistance >= 0.0f && flDistance < pVisibility[ i ] )
|
||||
{
|
||||
if ( Edge1.PointInFront( Location.x, Location.y ) && Edge2.PointInFront( Location.x, Location.y ) )
|
||||
{
|
||||
pVisibility[ i ] = flDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( fabs( P1.Dot( P2 ) ) > 0.99995f )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float flDot1 = vStraight.Dot( P1 );
|
||||
float flPos = acos( flDot1 );
|
||||
if ( P1.x < 0.0f )
|
||||
{
|
||||
flPos = 2.0f * M_PI_F - flPos;
|
||||
}
|
||||
float flDot2 = vStraight.Dot( P2 );
|
||||
float flNeg = acos( flDot2 );
|
||||
if ( P2.x < 0.0f )
|
||||
{
|
||||
flNeg = 2.0f * M_PI_F - flNeg;
|
||||
}
|
||||
|
||||
if ( fabs( flPos - flNeg ) > M_PI_F )
|
||||
{
|
||||
if ( flPos < flNeg )
|
||||
{
|
||||
flPos += M_PI_F * 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
flNeg += M_PI_F * 2.0f;
|
||||
}
|
||||
}
|
||||
// float flAng1 = RAD2DEG( flPos );
|
||||
// float flAng2 = RAD2DEG( flNeg );
|
||||
|
||||
float flCurrentDegree, flFinishDegree;
|
||||
int nStartIndex;
|
||||
if ( flPos < flNeg )
|
||||
{
|
||||
flCurrentDegree = flPos;
|
||||
flFinishDegree = flNeg;
|
||||
}
|
||||
else
|
||||
{
|
||||
flCurrentDegree = flNeg;
|
||||
flFinishDegree = flPos;
|
||||
}
|
||||
|
||||
/* if ( ( flFinishDegree - flCurrentDegree ) > M_PI_F )
|
||||
{
|
||||
float flTemp = flCurrentDegree;
|
||||
flCurrentDegree = flFinishDegree;
|
||||
flFinishDegree = flTemp + ( 2.0f * M_PI_F );
|
||||
}
|
||||
*/
|
||||
nUnits = pViewer->GetRadiusUnits();
|
||||
|
||||
float flDegreeAmount = 2.0f * M_PI_F / nUnits;
|
||||
nStartIndex = ( int )( flCurrentDegree / flDegreeAmount ) % nUnits;
|
||||
if ( nStartIndex < 0 )
|
||||
{
|
||||
nStartIndex += nUnits;
|
||||
}
|
||||
|
||||
// Vector vViewerLoc = pViewer->GetLocation();
|
||||
// float flViewerRadius = pViewer->GetSize();
|
||||
// float flMaxDistance = ( m_vStart - m_vEnd ).LengthSqr() + ( 60.0f * 60.0f );
|
||||
|
||||
#if 1
|
||||
for ( int i = nStartIndex; flCurrentDegree < flFinishDegree; i++, flCurrentDegree += flDegreeAmount )
|
||||
{
|
||||
Vector2D vDelta;
|
||||
|
||||
if ( i >= nUnits )
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
vDelta.x = TableSin( flCurrentDegree );
|
||||
vDelta.y = TableCos( flCurrentDegree );
|
||||
|
||||
#if 0
|
||||
float flDistance = m_Plane.DistanceFromRay( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
|
||||
Vector2D vFinal = vCenterLocation.AsVector2D() + ( vDelta * flDistance );
|
||||
float flDist1 = ( vFinal - m_vStart ).LengthSqr();
|
||||
float flDist2 = ( vFinal - m_vEnd ).LengthSqr();
|
||||
if ( flDistance >= 0.0f && ( flDist1 + flDist2 ) < flMaxDistance )
|
||||
#else
|
||||
// vDelta = ( vDelta * pViewer->GetSize() ) + vCenterLocation.AsVector2D();
|
||||
// float flDistance = m_Plane.DistanceFromLineStart( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
|
||||
float flDistance = m_Plane.DistanceFromRay( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
|
||||
if ( flDistance >= 0.0f )
|
||||
#endif
|
||||
|
||||
{
|
||||
flDistance *= flDistance;
|
||||
if ( flDistance < pVisibility[ i ] )
|
||||
{
|
||||
pVisibility[ i ] = flDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
int nStart = ( 0.0f / 4.0f ) * nUnits;
|
||||
int nEnd = ( 1.0f / 4.0f ) * nUnits;
|
||||
for( ; nStart < nEnd; nStart++ )
|
||||
{
|
||||
pVisibility[ nStart ] /= 5.0f;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <tier0/memdbgoff.h>
|
||||
49
fow/fow_lineoccluder.h
Normal file
49
fow/fow_lineoccluder.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: 2d line occlusion for Fog of War
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef FOW_LINEOCCLUDER_H
|
||||
#define FOW_LINEOCCLUDER_H
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
#include "fow_2dplane.h"
|
||||
|
||||
class CFoW;
|
||||
class CFoW_Viewer;
|
||||
|
||||
class CFoW_LineOccluder
|
||||
{
|
||||
public:
|
||||
// construct a line occluder from the given points. the normal is supplied, though if it doesn't match up with the points, then the points are swapped.
|
||||
CFoW_LineOccluder( float bx, float by, float ex, float ey, Vector2D &vNormal, int nSliceNum );
|
||||
|
||||
CFoW_LineOccluder( Vector2D &vStart, Vector2D &vEnd, CFOW_2DPlane &Plane, int nSliceNum );
|
||||
|
||||
// get the starting point as determined by the normal
|
||||
inline Vector2D &GetStart( void ) { return m_vStart; }
|
||||
// get the ending point as determined by the normal
|
||||
inline Vector2D &GetEnd( void ) { return m_vEnd; }
|
||||
// get the plane normal
|
||||
inline Vector2D GetPlaneNormal( void ) { return m_Plane.GetNormal(); }
|
||||
// get the plane normal
|
||||
inline float GetPlaneDistance( void ) { return m_Plane.GetDistance(); }
|
||||
// get the slice index this occluder belongs to
|
||||
inline int GetSliceNum( void ) { return m_nSliceNum; }
|
||||
|
||||
// determine the occlusion of this line for the viewer
|
||||
void ObstructViewer( CFoW *pFoW, CFoW_Viewer *pViewer );
|
||||
|
||||
private:
|
||||
Vector2D m_vStart; // the starting point as determined by the normal
|
||||
Vector2D m_vEnd; // the ending point as determined by the normal
|
||||
CFOW_2DPlane m_Plane; // the plane that is formed
|
||||
int m_nSliceNum; // the slice index of this occluder
|
||||
};
|
||||
|
||||
#endif // FOW_LINEOCCLUDER_H
|
||||
462
fow/fow_radiusoccluder.cpp
Normal file
462
fow/fow_radiusoccluder.cpp
Normal file
@@ -0,0 +1,462 @@
|
||||
#include "fow.h"
|
||||
#include "fow_radiusoccluder.h"
|
||||
#include "fow_viewer.h"
|
||||
#include "fow_2dplane.h"
|
||||
#include "engine/IVDebugOverlay.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
|
||||
extern IVDebugOverlay *debugoverlay;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor to init this occluder with the id
|
||||
// Input : nID - the id of this occluder
|
||||
//-----------------------------------------------------------------------------
|
||||
CFoW_RadiusOccluder::CFoW_RadiusOccluder( int nID )
|
||||
{
|
||||
m_nID = nID;
|
||||
m_flRadius = 0.0f;
|
||||
m_vLocation.Zero();
|
||||
m_nHeightGroup = 0;
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: update the radius of this occluder
|
||||
// Input : flRadius - the new radius size
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_RadiusOccluder::UpdateSize( float flRadius )
|
||||
{
|
||||
m_flRadius = flRadius;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: update the location of this occluder
|
||||
// Input : vLocation - the new location
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_RadiusOccluder::UpdateLocation( Vector &vLocation )
|
||||
{
|
||||
m_vLocation = vLocation;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: update the height group of this occluder
|
||||
// Input : nHeightGroup - the new height group
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_RadiusOccluder::UpdateHeightGroup( uint8 nHeightGroup )
|
||||
{
|
||||
m_nHeightGroup = nHeightGroup;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: is the occluder within range of the viewer?
|
||||
// Input : pViewer - the viewer to check against
|
||||
// Output : returns true if the two circles intersect
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CFoW_RadiusOccluder::IsInRange( CFoW_Viewer *pViewer )
|
||||
{
|
||||
if ( m_bEnabled == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector vDiff = pViewer->GetLocation() - m_vLocation;
|
||||
float flLen = sqrt( ( vDiff.x * vDiff.x ) + ( vDiff.y * vDiff.y ) );
|
||||
|
||||
return ( flLen <= m_flRadius + pViewer->GetSize() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: obstruct the viewer by updating the local viewer grid
|
||||
// Input : pFoW - the main FoW object
|
||||
// pViewer - the viewer to obstruct
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_RadiusOccluder::ObstructViewerGrid( CFoW *pFoW, CFoW_Viewer *pViewer )
|
||||
{
|
||||
if ( m_bEnabled == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vViewerLoc = pViewer->GetLocation();
|
||||
float flViewerRadius = pViewer->GetSize();
|
||||
Vector vDelta = ( vViewerLoc - m_vLocation );
|
||||
|
||||
vDelta.z = 0.0f;
|
||||
float flLength = vDelta.Length();
|
||||
|
||||
if ( flLength > ( flViewerRadius + m_flRadius ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if ( length <= m_flRadius || length > ViewerRadius )
|
||||
if ( flLength <= m_flRadius )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float flAngle = ( float )atan2( vDelta.y, vDelta.x );
|
||||
float flTangentLen = sqrt( flLength * flLength - m_flRadius * m_flRadius );
|
||||
float flTangentAngle = ( float )asin( m_flRadius / flLength );
|
||||
|
||||
// compute the two tangent angles
|
||||
float flPos = flAngle + flTangentAngle;
|
||||
float flNeg = flAngle - flTangentAngle;
|
||||
|
||||
float x[ 6 ], y[ 6 ];
|
||||
|
||||
// compute the two tangent points
|
||||
x[ 0 ] = -( float )cos( flPos ) * flTangentLen + vViewerLoc.x;
|
||||
y[ 0 ] = -( float )sin( flPos ) * flTangentLen + vViewerLoc.y;
|
||||
x[ 5 ] = -( float )cos( flNeg ) * flTangentLen + vViewerLoc.x;
|
||||
y[ 5 ] = -( float )sin( flNeg ) * flTangentLen + vViewerLoc.y;
|
||||
|
||||
// extend the tangent points to the viewer's edge
|
||||
x[ 1 ] = -( float )cos( flPos ) * flViewerRadius + vViewerLoc.x;
|
||||
y[ 1 ] = -( float )sin( flPos ) * flViewerRadius + vViewerLoc.y;
|
||||
x[ 4 ] = -( float )cos( flNeg ) * flViewerRadius + vViewerLoc.x;
|
||||
y[ 4 ] = -( float )sin( flNeg ) * flViewerRadius + vViewerLoc.y;
|
||||
|
||||
// compute the forward direction of the viewer's intersection through this blocker
|
||||
float fx = -vDelta.x / flLength;
|
||||
float fy = -vDelta.y / flLength;
|
||||
|
||||
// compute half the length between the viewer's tangent edges
|
||||
float dx2 = x[ 4 ] - x[ 1 ];
|
||||
float dy2 = y[ 4 ] - y[ 1 ];
|
||||
float flHalflen = ( dx2 * dx2 + dy2 * dy2 ) / 4;
|
||||
|
||||
// compute the side of the triangle that forms from viewer's radius to half way across the viewer's tangent edges
|
||||
float flLen2 = ( float )sqrt( flViewerRadius * flViewerRadius - flHalflen );
|
||||
flLen2 = flViewerRadius - flLen2;
|
||||
|
||||
// compute the box extents to encompass the circle's bounds
|
||||
x[ 2 ] = x[ 1 ] + ( fx * flLen2 );
|
||||
y[ 2 ] = y[ 1 ] + ( fy * flLen2 );
|
||||
x[ 3 ] = x[ 4 ] + ( fx * flLen2 );
|
||||
y[ 3 ] = y[ 4 ] + ( fy * flLen2 );
|
||||
|
||||
CFOW_2DPlane Planes[ 6 ];
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
Planes[ i ].Init( x[ i ], y[ i ], x[ ( i + 1 ) % 6 ], y[ ( i + 1 ) % 6 ] );
|
||||
}
|
||||
|
||||
float flMinX = x[ 0 ], flMinY = y[ 0 ], flMaxX = x[ 0 ], flMaxY = y[ 0 ];
|
||||
|
||||
for ( int i = 1; i < 6; i++ )
|
||||
{
|
||||
if ( x[ i ] < flMinX )
|
||||
{
|
||||
flMinX = x[ i ];
|
||||
}
|
||||
if ( x[ i ] > flMaxX )
|
||||
{
|
||||
flMaxX = x[ i ];
|
||||
}
|
||||
if ( y[ i ] < flMinY )
|
||||
{
|
||||
flMinY = y[ i ];
|
||||
}
|
||||
if ( y[i] > flMaxY )
|
||||
{
|
||||
flMaxY = y[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
float px, py, flStart_py, ex, ey;
|
||||
int nGridX, nGridY, nStartGridY;
|
||||
Vector2D vViewerStart, vViewerEnd;
|
||||
int nGridSize = pFoW->GetHorizontalGridSize();
|
||||
|
||||
pViewer->GetStartPosition( vViewerStart );
|
||||
pViewer->GetEndPosition( vViewerEnd );
|
||||
|
||||
if ( flMinX > vViewerStart.x )
|
||||
{
|
||||
nGridX = ( int )( flMinX - vViewerStart.x ) / nGridSize;
|
||||
px = vViewerStart.x + ( int )( nGridSize * nGridX );
|
||||
}
|
||||
else
|
||||
{
|
||||
px = vViewerStart.x;
|
||||
nGridX = 0;
|
||||
}
|
||||
if ( flMaxX < vViewerEnd.x )
|
||||
{
|
||||
ex = flMaxX;
|
||||
}
|
||||
else
|
||||
{
|
||||
ex = vViewerEnd.x;
|
||||
}
|
||||
|
||||
if ( flMinY > vViewerStart.y )
|
||||
{
|
||||
nStartGridY = ( int )( flMinY - vViewerStart.y ) / nGridSize;
|
||||
flStart_py = vViewerStart.y + ( int )( nGridSize * nStartGridY );
|
||||
}
|
||||
else
|
||||
{
|
||||
nStartGridY = 0;
|
||||
flStart_py = vViewerStart.y;
|
||||
}
|
||||
if ( flMaxY < vViewerEnd.y )
|
||||
{
|
||||
ey = flMaxY;
|
||||
}
|
||||
else
|
||||
{
|
||||
ey = vViewerEnd.y;
|
||||
}
|
||||
|
||||
byte *pLocalVisibility = pViewer->GetVisibility();
|
||||
int nLocalGridUnits = pViewer->GetGridUnits();
|
||||
|
||||
// offset to center of grid
|
||||
px += nGridSize / 2;
|
||||
flStart_py += nGridSize / 2;
|
||||
|
||||
for ( ; px < ex; px += nGridSize, nGridX++)
|
||||
{
|
||||
for ( nGridY = nStartGridY, py = flStart_py; py < ey; py += nGridSize, nGridY++ )
|
||||
{
|
||||
byte *pPos = pLocalVisibility + ( nGridX * nLocalGridUnits ) + nGridY;
|
||||
|
||||
if ( ( ( *pPos ) & FOW_VG_IS_VISIBLE ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int i;
|
||||
for ( i = 0; i < 6; i++ )
|
||||
{
|
||||
#if 0
|
||||
// we don't need to check the bounding planes - these would be used to construct a stencil buffer though
|
||||
if ( i == 1 || i == 2 || i == 3 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ( !Planes[ i ].PointInFront( px, py ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == 6 )
|
||||
{
|
||||
( *pPos ) &= ~FOW_VG_IS_VISIBLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #define SLOW_PATH 1
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: obstruct the viewer by updating the depth circle
|
||||
// Input : pFoW - the main FoW object
|
||||
// pViewer - the viewer to obstruct
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_RadiusOccluder::ObstructViewerRadius( CFoW *pFoW, CFoW_Viewer *pViewer )
|
||||
{
|
||||
if ( m_bEnabled == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_flRadius <= 1.0f )
|
||||
{
|
||||
Warning( "FoW: Occluder %d has invalid radius\n", m_nID );
|
||||
return;
|
||||
}
|
||||
|
||||
int nViewerHeightGroup = pViewer->GetHeightGroup();
|
||||
if ( nViewerHeightGroup >= 1 && m_nHeightGroup >= 1 && m_nHeightGroup < nViewerHeightGroup )
|
||||
{ // both the viewer and the occluder have height groups and this occluder is under the viewer, then don't obstruct
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vViewerLoc = pViewer->GetLocation();
|
||||
float flViewerRadius = pViewer->GetSize();
|
||||
Vector vDelta = ( vViewerLoc - m_vLocation );
|
||||
|
||||
vDelta.z = 0.0f;
|
||||
float flLength = vDelta.Length();
|
||||
|
||||
if ( flLength > ( flViewerRadius + m_flRadius ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if ( length <= m_flRadius || length > ViewerRadius )
|
||||
if ( flLength <= m_flRadius )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float flAngle = ( float )atan2( vDelta.x, vDelta.y ) + DEG2RAD( 180.0f );
|
||||
float flTangentLen = sqrt( flLength * flLength - m_flRadius * m_flRadius );
|
||||
float flTangentAngle = ( float )asin( m_flRadius / flLength );
|
||||
|
||||
// compute the two tangent angles
|
||||
float flPos = flAngle + flTangentAngle;
|
||||
float flNeg = flAngle - flTangentAngle;
|
||||
|
||||
float x[ 6 ], y[ 6 ];
|
||||
|
||||
// compute the two tangent points
|
||||
#ifdef SLOW_PATH
|
||||
x[ 0 ] = ( float )sin( flPos ) * flTangentLen + vViewerLoc.x;
|
||||
y[ 0 ] = ( float )cos( flPos ) * flTangentLen + vViewerLoc.y;
|
||||
x[ 5 ] = ( float )sin( flNeg ) * flTangentLen + vViewerLoc.x;
|
||||
y[ 5 ] = ( float )cos( flNeg ) * flTangentLen + vViewerLoc.y;
|
||||
#else
|
||||
x[ 0 ] = ( float )TableSin( flPos ) * flTangentLen + vViewerLoc.x;
|
||||
y[ 0 ] = ( float )TableCos( flPos ) * flTangentLen + vViewerLoc.y;
|
||||
x[ 5 ] = ( float )TableSin( flNeg ) * flTangentLen + vViewerLoc.x;
|
||||
y[ 5 ] = ( float )TableCos( flNeg ) * flTangentLen + vViewerLoc.y;
|
||||
#endif
|
||||
|
||||
// Msg( "%g, %g\n", RAD2DEG( flPos ), RAD2DEG( flNeg ) );
|
||||
|
||||
CFOW_2DPlane Plane;
|
||||
|
||||
Plane.Init( x[ 5 ], y[ 5 ], x[ 0 ], y[ 0 ] );
|
||||
|
||||
int nUnits = pViewer->GetRadiusUnits();
|
||||
int *pVisibility = pViewer->GetVisibilityRadius();
|
||||
|
||||
Vector vCenterLocation = vViewerLoc;
|
||||
float flDistance = Plane.DistanceFrom( vCenterLocation.x, vCenterLocation.y );
|
||||
if ( flDistance < 0.0f )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SLOW_PATH
|
||||
CFOW_2DPlane Edge1, Edge2;
|
||||
|
||||
Edge1.Init( vCenterLocation.x, vCenterLocation.y, x[ 0 ], y[ 0 ] );
|
||||
Edge2.Init( x[ 5 ], y[ 5 ], vCenterLocation.x, vCenterLocation.y );
|
||||
|
||||
float flDegreeAmount = 360.0f / nUnits;
|
||||
|
||||
float flCurrentDegree = 0.0f;
|
||||
for ( int i = 0; i < nUnits; i++, flCurrentDegree += flDegreeAmount )
|
||||
{
|
||||
Vector vLocation = vViewerLoc;
|
||||
Vector vDelta;
|
||||
|
||||
vDelta.x = sin( DEG2RAD( flCurrentDegree ) );
|
||||
vDelta.y = cos( DEG2RAD( flCurrentDegree ) );
|
||||
|
||||
vLocation += vDelta * flViewerRadius;
|
||||
|
||||
float flDistance = Plane.DistanceFromRay( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
|
||||
if ( flDistance >= 0.0f )
|
||||
{
|
||||
flDistance *= flDistance;
|
||||
if ( flDistance >= 0.0f && flDistance < pVisibility[ i ] )
|
||||
{
|
||||
if ( Edge1.PointInFront( vLocation.x, vLocation.y ) && Edge2.PointInFront( vLocation.x, vLocation.y ) )
|
||||
{
|
||||
pVisibility[ i ] = flDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
float flCurrentDegree, flFinishDegree;
|
||||
int nStartIndex;
|
||||
|
||||
if ( flPos < flNeg )
|
||||
{
|
||||
flCurrentDegree = flPos;
|
||||
flFinishDegree = flNeg;
|
||||
}
|
||||
else
|
||||
{
|
||||
flCurrentDegree = flNeg;
|
||||
flFinishDegree = flPos;
|
||||
}
|
||||
|
||||
float flDegreeAmount = 2.0f * M_PI_F / nUnits;
|
||||
nStartIndex = ( int )( flCurrentDegree / flDegreeAmount ) % nUnits;
|
||||
if ( nStartIndex < 0 )
|
||||
{
|
||||
nStartIndex += nUnits;
|
||||
}
|
||||
|
||||
float flHorizontalGridSize = pFoW->GetHorizontalGridSize();
|
||||
|
||||
for ( int i = nStartIndex; flCurrentDegree < flFinishDegree; i++, flCurrentDegree += flDegreeAmount )
|
||||
{
|
||||
Vector vDelta;
|
||||
|
||||
if ( i >= nUnits )
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
vDelta.x = TableSin( flCurrentDegree );
|
||||
vDelta.y = TableCos( flCurrentDegree );
|
||||
|
||||
float flDistance = Plane.DistanceFromRay( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
|
||||
if ( flDistance >= 0.0f )
|
||||
{
|
||||
flDistance += flHorizontalGridSize * 1.1f; // back off a bit
|
||||
|
||||
flDistance *= flDistance;
|
||||
if ( flDistance < pVisibility[ i ] )
|
||||
{
|
||||
pVisibility[ i ] = flDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_RadiusOccluder::DrawDebugInfo( Vector &vLocation, float flViewRadius, unsigned nFlags )
|
||||
{
|
||||
if ( ( nFlags & FOW_DEBUG_SHOW_OCCLUDERS ) == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vDiff = vLocation - m_vLocation;
|
||||
|
||||
if ( vDiff.Length2D() > flViewRadius + m_flRadius )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( nFlags & FOW_DEBUG_SHOW_OCCLUDERS ) != 0 )
|
||||
{
|
||||
debugoverlay->AddSphereOverlay( m_vLocation, m_flRadius, 10, 10, 255, 0, 0, 127, FOW_DEBUG_VIEW_TIME );
|
||||
debugoverlay->AddBoxOverlay( m_vLocation, Vector( -16.0f, -16.0f, -16.0f ), Vector( 16.0f, 16.0f, 16.0f ), QAngle( 0, 0, 0 ), 255, 0, 0, 127, FOW_DEBUG_VIEW_TIME );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include <tier0/memdbgoff.h>
|
||||
63
fow/fow_radiusoccluder.h
Normal file
63
fow/fow_radiusoccluder.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: radius occlusion for Fog of War
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef FOW_RADIUSOCCLUDER_H
|
||||
#define FOW_RADIUSOCCLUDER_H
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
class CFoW;
|
||||
class CFoW_Viewer;
|
||||
|
||||
class CFoW_RadiusOccluder
|
||||
{
|
||||
public:
|
||||
// constructor to init this occluder with the id
|
||||
CFoW_RadiusOccluder( int nID );
|
||||
|
||||
// update the radius of this occluder
|
||||
void UpdateSize( float flRadius );
|
||||
// update the location of this occluder
|
||||
void UpdateLocation( Vector &vLocation );
|
||||
// update the height group of this occluder
|
||||
void UpdateHeightGroup( uint8 nHeightGroup );
|
||||
|
||||
// get the radius of this occluder
|
||||
inline float GetSize( void ) { return m_flRadius; }
|
||||
// get the location of this occluder
|
||||
inline Vector &GetLocation( void ) { return m_vLocation; }
|
||||
//
|
||||
inline uint8 GetHeightGroup( void ) { return m_nHeightGroup; }
|
||||
|
||||
//
|
||||
inline bool IsEnabled( ) { return m_bEnabled; }
|
||||
//
|
||||
inline void SetEnable( bool bEnable ) { m_bEnabled = bEnable; }
|
||||
|
||||
// is the occluder within range of the viewer?
|
||||
bool IsInRange( CFoW_Viewer *pViewer );
|
||||
|
||||
// obstruct the viewer by updating the local viewer grid
|
||||
void ObstructViewerGrid( CFoW *pFoW, CFoW_Viewer *pViewer );
|
||||
// obstruct the viewer by updating the depth circle
|
||||
void ObstructViewerRadius( CFoW *pFoW, CFoW_Viewer *pViewer );
|
||||
|
||||
//
|
||||
void DrawDebugInfo( Vector &vLocation, float flViewRadius, unsigned nFlags );
|
||||
|
||||
private:
|
||||
int m_nID; // the id of this occluder
|
||||
float m_flRadius; // the radius of this occluder
|
||||
Vector m_vLocation; // the location of this occluder
|
||||
bool m_bEnabled;
|
||||
uint8 m_nHeightGroup; // the height group this occluder belongs to
|
||||
};
|
||||
|
||||
#endif // FOW_RADIUSOCCLUDER_H
|
||||
206
fow/fow_trisoup.cpp
Normal file
206
fow/fow_trisoup.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
#include "fow.h"
|
||||
#include "fow_trisoup.h"
|
||||
#include "fow_lineoccluder.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor to init this collection with the id
|
||||
// Input : nID - unused
|
||||
//-----------------------------------------------------------------------------
|
||||
CFoW_TriSoupCollection::CFoW_TriSoupCollection( unsigned nID )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destructor to dealloc the occluders
|
||||
//-----------------------------------------------------------------------------
|
||||
CFoW_TriSoupCollection::~CFoW_TriSoupCollection( void )
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: clears all entries from the collection ( useful for hammer editing only )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_TriSoupCollection::Clear( void )
|
||||
{
|
||||
m_Occluders.PurgeAndDeleteElements();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: adds a tri to the collection. this is immediately split up into the horizontal slices. very slow!
|
||||
// Input : pFoW - the main FoW object
|
||||
// vPointA - a point on the tri
|
||||
// vPointB - a point on the tri
|
||||
// vPointC - a point on the tri
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_TriSoupCollection::AddTri( CFoW *pFoW, Vector &vPointA, Vector &vPointB, Vector &vPointC )
|
||||
{
|
||||
Vector vVerts[ 3 ], vOutVerts[ 8 ];
|
||||
int nBottomZ;
|
||||
int nGridSize;
|
||||
int nGridUnits;
|
||||
Vector vNormal, vTestNormal;
|
||||
float flIntercept;
|
||||
float *pflVerticalLevels;
|
||||
|
||||
vVerts[ 0 ] = vPointA;
|
||||
vVerts[ 1 ] = vPointB;
|
||||
vVerts[ 2 ] = vPointC;
|
||||
|
||||
pFoW->GetVerticalGridInfo( nBottomZ, nGridSize, nGridUnits, &pflVerticalLevels );
|
||||
|
||||
ComputeTrianglePlane( vPointA, vPointB, vPointC, vNormal, flIntercept );
|
||||
vTestNormal = vNormal;
|
||||
vTestNormal.z = 0.0f;
|
||||
vTestNormal.NormalizeInPlace();
|
||||
Vector2D vTestNormal2( vTestNormal.x, vTestNormal.y );
|
||||
|
||||
for ( int i = 0; i < nGridUnits; i++ )
|
||||
{
|
||||
nBottomZ = pflVerticalLevels[ i ] + 16.0f;
|
||||
|
||||
int nCount = HorizontalSplitTri( vVerts, 3, vOutVerts, nBottomZ, 0.0f );
|
||||
if ( nCount == 2 )
|
||||
{
|
||||
CFoW_LineOccluder *pOccluder = new CFoW_LineOccluder( vOutVerts[ 0 ].x, vOutVerts[ 0 ].y, vOutVerts[ 1 ].x, vOutVerts[ 1 ].y, vTestNormal2, i );
|
||||
m_Occluders.AddToTail( pOccluder );
|
||||
pFoW->AddTriSoupOccluder( pOccluder, i );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: adds all occluders back into the visibility tree
|
||||
// Input : pFoW - the main FoW object
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_TriSoupCollection::RepopulateOccluders( CFoW *pFoW )
|
||||
{
|
||||
for ( int i = 0; i < m_Occluders.Count(); i++ )
|
||||
{
|
||||
pFoW->AddTriSoupOccluder( m_Occluders[ i ], m_Occluders[ i ]->GetSliceNum() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void CFoW_TriSoupCollection::ObstructViewer( CFoW *FoW, CFoW_Viewer *Viewer )
|
||||
{
|
||||
for ( int i = 0; i < m_Occluders.Count(); i++ )
|
||||
{
|
||||
m_Occluders[ i ].ObstructViewer( FoW, Viewer );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: clip a poly to the horizontal plane and return the poly on the front side of the plane
|
||||
// Input : *pInVerts - input polygon
|
||||
// nVertCount - # verts in input poly
|
||||
// *pOutVerts - destination poly
|
||||
// flDist - plane constant
|
||||
// flOnPlaneEpsilon - the fudge factor for determining if a point is within the plane edge
|
||||
// Output : int - # verts in output poly
|
||||
//-----------------------------------------------------------------------------
|
||||
int CFoW_TriSoupCollection::HorizontalSplitTri( Vector *pInVerts, int nVertCount, Vector *pOutVerts, float flDist, float flOnPlaneEpsilon )
|
||||
{
|
||||
vec_t *pDists = ( vec_t * )stackalloc( sizeof( vec_t ) * nVertCount * 4 ); //4x vertcount should cover all cases
|
||||
int *pSides = ( int * )stackalloc( sizeof( vec_t ) * nVertCount * 4 );
|
||||
int nCounts[ 3 ];
|
||||
vec_t flDot;
|
||||
int i, j;
|
||||
Vector vMid = vec3_origin;
|
||||
int nOutCount;
|
||||
Vector vNormal( 0.0f, 0.0f, 1.0f );
|
||||
|
||||
nCounts[ 0 ] = nCounts[ 1 ] = nCounts[ 2 ] = 0;
|
||||
|
||||
// determine sides for each point
|
||||
for ( i = 0; i < nVertCount; i++ )
|
||||
{
|
||||
flDot = DotProduct( pInVerts[ i ], vNormal ) - flDist;
|
||||
pDists[ i ] = flDot;
|
||||
if ( flDot > flOnPlaneEpsilon )
|
||||
{
|
||||
pSides[ i ] = SIDE_FRONT;
|
||||
}
|
||||
else if ( flDot < -flOnPlaneEpsilon )
|
||||
{
|
||||
pSides[ i ] = SIDE_BACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSides[ i ] = SIDE_ON;
|
||||
}
|
||||
nCounts[ pSides[ i ] ]++;
|
||||
}
|
||||
pSides[ i ] = pSides[ 0 ];
|
||||
pDists[ i ] = pDists[ 0 ];
|
||||
|
||||
if ( !nCounts[ SIDE_FRONT ] )
|
||||
{ // if this has 2 sides that are side_on, then this should be a tri coming soon with the same two sides that are on, but with one on side_back
|
||||
return 0;
|
||||
}
|
||||
|
||||
nOutCount = 0;
|
||||
for ( i = 0; i < nVertCount; i++ )
|
||||
{
|
||||
int nCurrent = ( i + 0 ) % nVertCount;
|
||||
int nNext = ( i + 1 ) % nVertCount;
|
||||
|
||||
Vector &p1 = pInVerts[ nCurrent ];
|
||||
|
||||
if ( pSides[ nCurrent ] == SIDE_ON )
|
||||
{
|
||||
VectorCopy( p1, pOutVerts[ nOutCount ] );
|
||||
nOutCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( pSides[ nCurrent ] == SIDE_FRONT )
|
||||
{
|
||||
// VectorCopy( p1, outVerts[outCount]);
|
||||
// outCount++;
|
||||
}
|
||||
|
||||
if ( pSides[ nNext ] == SIDE_ON || pSides[ nNext ] == pSides[ nCurrent ] )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// generate a split point
|
||||
Vector &p2 = pInVerts[ nNext ];
|
||||
|
||||
flDot = pDists[ nCurrent ] / ( pDists[ nCurrent ] - pDists[ nNext ] );
|
||||
for ( j = 0; j < 3; j++ )
|
||||
{ // avoid round off error when possible
|
||||
if ( vNormal[ j ] == 1 )
|
||||
{
|
||||
vMid[ j ] = flDist;
|
||||
}
|
||||
else if ( vNormal[ j ] == -1 )
|
||||
{
|
||||
vMid[ j ] = -flDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
vMid[ j ] = p1[ j ] + flDot * ( p2[ j ] - p1[ j ] );
|
||||
}
|
||||
}
|
||||
|
||||
VectorCopy ( vMid, pOutVerts[ nOutCount ] );
|
||||
nOutCount++;
|
||||
}
|
||||
|
||||
return nOutCount;
|
||||
}
|
||||
|
||||
#include <tier0/memdbgoff.h>
|
||||
|
||||
52
fow/fow_trisoup.h
Normal file
52
fow/fow_trisoup.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: stores all line occlusions ( horizontal slices ) for the tri soup for the Fog of War
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef FOW_TRISOUP_H
|
||||
#define FOW_TRISOUP_H
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
class CFoW;
|
||||
class CFoW_Viewer;
|
||||
class CFoW_LineOccluder;
|
||||
|
||||
class CFoW_TriSoupCollection
|
||||
{
|
||||
public:
|
||||
// constructor to init this collection with the id
|
||||
CFoW_TriSoupCollection( unsigned nID );
|
||||
// destructor to dealloc the occluders
|
||||
~CFoW_TriSoupCollection( void );
|
||||
|
||||
// clears all entries from the collection ( useful for hammer editing only )
|
||||
void Clear( void );
|
||||
// adds a tri to the collection. this is immediately split up into the horizontal slices. very slow!
|
||||
void AddTri( CFoW *pFoW, Vector &vPointA, Vector &vPointB, Vector &vPointC );
|
||||
|
||||
// adds all occluders back into the visibility tree
|
||||
void RepopulateOccluders( CFoW *pFoW );
|
||||
|
||||
// void ObstructViewer( CFoW *FoW, CFoW_Viewer *Viewer );
|
||||
|
||||
//
|
||||
int GetNumOccluders( ) { return m_Occluders.Count(); }
|
||||
|
||||
//
|
||||
CFoW_LineOccluder *GetOccluder( int nIndex ) { return m_Occluders[ nIndex ]; }
|
||||
|
||||
private:
|
||||
// attempt to split the tri horizontally given the distance / offset from z 0.0
|
||||
int HorizontalSplitTri( Vector *pInVerts, int nVertCount, Vector *pOutVerts, float flDist, float flOnPlaneEpsilon );
|
||||
|
||||
CUtlVector< CFoW_LineOccluder * > m_Occluders;
|
||||
};
|
||||
|
||||
#endif // FOW_TRISOUP_H
|
||||
367
fow/fow_viewer.cpp
Normal file
367
fow/fow_viewer.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
#include "fow_viewer.h"
|
||||
#include "fow_radiusoccluder.h"
|
||||
#include "fow_lineoccluder.h"
|
||||
#include "fow_horizontalslice.h"
|
||||
#include "fow.h"
|
||||
#include "engine/IVDebugOverlay.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
|
||||
extern IVDebugOverlay *debugoverlay;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor to init this viewer with the id and temp
|
||||
// Input : nID - the id of this viewer
|
||||
// nViewerTeam - the team this viewer is on
|
||||
//-----------------------------------------------------------------------------
|
||||
CFoW_Viewer::CFoW_Viewer( int nID, unsigned nViewerTeam )
|
||||
{
|
||||
m_nID = nID;
|
||||
m_nViewerTeam = nViewerTeam;
|
||||
m_vLocation.Init();
|
||||
m_flRadius = 0.0f;
|
||||
m_pVisibility = NULL;
|
||||
|
||||
m_pVisibilityRadius = NULL;
|
||||
m_nRadiusUnits = 0;
|
||||
m_nHeightGroup = 0;
|
||||
|
||||
m_nAllocatedMemory = 0;
|
||||
|
||||
m_bDirty = true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destructor to free up the local vis grids
|
||||
//-----------------------------------------------------------------------------
|
||||
CFoW_Viewer::~CFoW_Viewer( void )
|
||||
{
|
||||
if ( m_pVisibility )
|
||||
{
|
||||
free( m_pVisibility );
|
||||
m_pVisibility = NULL;
|
||||
}
|
||||
|
||||
if ( m_pVisibilityRadius )
|
||||
{
|
||||
free( m_pVisibilityRadius );
|
||||
m_pVisibilityRadius = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: update the radius of the viewer. this will realloc the local vis grids
|
||||
// Input : pFoW - the main FoW object
|
||||
// flRadius - the new radius
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::UpdateSize( CFoW *pFoW, float flRadius )
|
||||
{
|
||||
m_flRadius = flRadius;
|
||||
|
||||
if ( m_pVisibility )
|
||||
{
|
||||
free( m_pVisibility );
|
||||
}
|
||||
|
||||
if ( m_pVisibilityRadius )
|
||||
{
|
||||
free( m_pVisibilityRadius );
|
||||
}
|
||||
|
||||
m_nAllocatedMemory = 0;
|
||||
|
||||
int nGridSize = pFoW->GetHorizontalGridSize();
|
||||
|
||||
m_nGridUnits = ( ( m_flRadius * 2 ) + nGridSize - 1 ) / nGridSize;
|
||||
m_nGridUnits |= 1; // always make it odd, so that we have a true center
|
||||
m_pVisibility = ( byte * )malloc( sizeof( m_pVisibility[ 0 ] ) * m_nGridUnits * m_nGridUnits );
|
||||
m_nAllocatedMemory += sizeof( m_pVisibility[ 0 ] ) * m_nGridUnits * m_nGridUnits;
|
||||
|
||||
m_nRadiusUnits = ( ( 2 * M_PI * m_flRadius ) + nGridSize - 1 ) / nGridSize;
|
||||
// m_nRadiusUnits = 360;
|
||||
m_pVisibilityRadius = ( int * )malloc( sizeof( m_pVisibilityRadius[ 0 ] ) * m_nRadiusUnits );
|
||||
m_nAllocatedMemory += sizeof( m_pVisibilityRadius[ 0 ] ) * m_nRadiusUnits;
|
||||
|
||||
m_pVisibilityTable = pFoW->FindRadiusTable( flRadius );
|
||||
|
||||
m_bDirty = true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: update the location of the viewer
|
||||
// Input : vLocation - the new location
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CFoW_Viewer::UpdateLocation( CFoW *pFoW, const Vector &vLocation, Vector *pvOldLocation )
|
||||
{
|
||||
Vector vNewLocation = vLocation;
|
||||
|
||||
m_vRealLocation = vLocation;
|
||||
|
||||
pFoW->CenterCoordToGrid( vNewLocation );
|
||||
|
||||
if ( vNewLocation.x != m_vLocation.x || vNewLocation.y != m_vLocation.y )
|
||||
{ // we've moved to a new grid center
|
||||
m_bDirty = true;
|
||||
if ( pvOldLocation != NULL )
|
||||
{
|
||||
*pvOldLocation = m_vLocation;
|
||||
}
|
||||
m_vLocation = vNewLocation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: update the height group of this viewer
|
||||
// Input : nHeightGroup - the new height group
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::UpdateHeightGroup( uint8 nHeightGroup )
|
||||
{
|
||||
if ( m_nHeightGroup != nHeightGroup )
|
||||
{
|
||||
m_bDirty = true;
|
||||
}
|
||||
|
||||
m_nHeightGroup = nHeightGroup;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get the upper left coords of this viewer
|
||||
// Output : vResults - the upper left location of this viewer
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::GetStartPosition( Vector2D &vResults )
|
||||
{
|
||||
vResults.x = m_vLocation.x - m_flRadius;
|
||||
vResults.y = m_vLocation.y - m_flRadius;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get the lower right coords of this viewer
|
||||
// Output : vResults - the lower right of this viewer
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::GetEndPosition( Vector2D &vResults )
|
||||
{
|
||||
vResults.x = m_vLocation.x + m_flRadius;
|
||||
vResults.y = m_vLocation.y + m_flRadius;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: calculate the localized visibility against all occluders.
|
||||
// Input : pFoW - the main FoW object
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::CalcLocalizedVisibility( CFoW *pFoW )
|
||||
{
|
||||
if ( m_bDirty == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// DefaultViewingArea( pFoW );
|
||||
DefaultViewingRadius( pFoW );
|
||||
|
||||
pFoW->ObstructOccludersNearViewer( m_nID );
|
||||
|
||||
#if 0
|
||||
int NumOccluders = FoW->GetNumOccluders();
|
||||
|
||||
for ( int i = 0; i < NumOccluders; i++ )
|
||||
{
|
||||
CFoW_RadiusOccluder *Occluder = FoW->GetOccluder( i );
|
||||
|
||||
if ( !Occluder )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Occluder->IsInRange( this ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Occluder->ObstructViewer( FoW, this );
|
||||
}
|
||||
#endif
|
||||
|
||||
int nSliceIndex = pFoW->GetHorizontalSlice( m_vLocation.z );
|
||||
if ( nSliceIndex != -1 )
|
||||
{
|
||||
pFoW->GetSlice( nSliceIndex )->ObstructViewer( pFoW, this );
|
||||
}
|
||||
|
||||
ResolveRadius( pFoW );
|
||||
|
||||
m_bDirty = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: clear the localized visibility grid to just the raw radius
|
||||
// Input : pFoW - the main FoW object
|
||||
//-----------------------------------------------------------------------------
|
||||
// use this FOW_VG_DEFAULT_VISIBLE
|
||||
void CFoW_Viewer::DefaultViewingArea( CFoW *pFoW )
|
||||
{
|
||||
memset( m_pVisibility, 0, sizeof( m_pVisibility[ 0 ] ) * m_nGridUnits * m_nGridUnits );
|
||||
|
||||
int nGridSize = pFoW->GetHorizontalGridSize();
|
||||
int nOffset = ( m_nGridUnits / 2 ) * nGridSize;
|
||||
byte *pVisibility = m_pVisibility;
|
||||
int nRadius2 = m_flRadius * m_flRadius;
|
||||
|
||||
for ( int x = 0, xPos = -nOffset; x < m_nGridUnits; x++, xPos += nGridSize )
|
||||
{
|
||||
for ( int y = 0, yPos = -nOffset; y < m_nGridUnits; y++, yPos += nGridSize, pVisibility++ )
|
||||
{
|
||||
if ( ( ( xPos * xPos ) + ( yPos * yPos ) ) <= nRadius2 )
|
||||
{
|
||||
*pVisibility = FOW_VG_IS_VISIBLE | FOW_VG_DEFAULT_VISIBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pVisibility = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: clear the localized radius grid to the maximum distance
|
||||
// Input : pFoW - the main FoW object
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::DefaultViewingRadius( CFoW *pFoW )
|
||||
{
|
||||
int nRadius2 = m_flRadius * m_flRadius;
|
||||
|
||||
for ( int i = 0; i < m_nRadiusUnits; i++ )
|
||||
{
|
||||
m_pVisibilityRadius[ i ] = nRadius2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::DrawDebugInfo( Vector &vLocation, float flViewRadius, unsigned nFlags )
|
||||
{
|
||||
if ( ( nFlags & ( FOW_DEBUG_SHOW_VIEWERS_TEAM_0 | FOW_DEBUG_SHOW_VIEWERS_TEAM_1 ) ) == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vDiff = vLocation - m_vLocation;
|
||||
|
||||
if ( vDiff.Length2D() > flViewRadius + m_flRadius )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( nFlags & FOW_DEBUG_SHOW_VIEWERS_TEAM_0 ) != 0 )
|
||||
{
|
||||
debugoverlay->AddSphereOverlay( m_vLocation, m_flRadius, 10, 10, 0, 255, 0, 127, FOW_DEBUG_VIEW_TIME );
|
||||
debugoverlay->AddBoxOverlay( m_vLocation, Vector( -16.0f, -16.0f, -16.0f ), Vector( 16.0f, 16.0f, 16.0f ), QAngle( 0, 0, 0 ), 0, 255, 0, 127, FOW_DEBUG_VIEW_TIME );
|
||||
}
|
||||
|
||||
if ( ( nFlags & FOW_DEBUG_SHOW_VIEWERS_TEAM_1 ) != 0 )
|
||||
{
|
||||
debugoverlay->AddSphereOverlay( m_vLocation, m_flRadius, 10, 10, 0, 0, 255, 127, FOW_DEBUG_VIEW_TIME );
|
||||
debugoverlay->AddBoxOverlay( m_vLocation, Vector( -16.0f, -16.0f, -16.0f ), Vector( 16.0f, 16.0f, 16.0f ), QAngle( 0, 0, 0 ), 0, 0, 255, 127, FOW_DEBUG_VIEW_TIME );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: turn the radius grid into the localized visibility grid
|
||||
// Input : pFoW - the main FoW object
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFoW_Viewer::ResolveRadius( CFoW *pFoW )
|
||||
{
|
||||
#if 0
|
||||
int nGridSize = pFoW->GetHorizontalGridSize();
|
||||
int nHalfGridSize = nGridSize / 2;
|
||||
byte *pVisibility = m_pVisibility;
|
||||
|
||||
// int Radius2 = m_flRadius * m_flRadius;
|
||||
|
||||
for ( int x = 0, xPos = -m_flRadius + nHalfGridSize; x < m_nGridUnits; x++, xPos += nGridSize )
|
||||
{
|
||||
for ( int y = 0, yPos = -m_flRadius + nHalfGridSize; y < m_nGridUnits; y++, yPos += nGridSize, pVisibility++ )
|
||||
{
|
||||
float flDist = sqrt( ( float )( ( xPos * xPos ) + ( yPos * yPos ) ) );
|
||||
if ( flDist > m_flRadius )
|
||||
{
|
||||
*pVisibility = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
float nx = xPos / flDist;
|
||||
float ny = yPos / flDist;
|
||||
|
||||
float flAngle = ( 0 * nx ) + ( 1 * ny );
|
||||
float flRealAngle = RAD2DEG( acos( flAngle ) );
|
||||
|
||||
flAngle = -flAngle + 1;
|
||||
if ( nx < 0.0f )
|
||||
{
|
||||
flAngle = 4 - flAngle;
|
||||
flRealAngle = 360 - flRealAngle;
|
||||
}
|
||||
flAngle /= 4.0f;
|
||||
flAngle *= m_nRadiusUnits;
|
||||
flRealAngle = ( flRealAngle / 360.0f ) * m_nRadiusUnits;
|
||||
|
||||
if ( flDist <= m_pVisibilityRadius[ ( int )flRealAngle ] )
|
||||
{
|
||||
*pVisibility = FOW_VG_IS_VISIBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pVisibility = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
int nGridSize = pFoW->GetHorizontalGridSize();
|
||||
int nOffset = ( m_nGridUnits / 2 ) * nGridSize;
|
||||
byte *pVisibility = m_pVisibility;
|
||||
int *pVisibilityTable = m_pVisibilityTable;
|
||||
|
||||
for ( int x = 0, xPos = -nOffset; x < m_nGridUnits; x++, xPos += nGridSize )
|
||||
{
|
||||
for ( int y = 0, yPos = -nOffset; y < m_nGridUnits; y++, yPos += nGridSize, pVisibility++, pVisibilityTable++ )
|
||||
{
|
||||
if ( ( *pVisibilityTable ) == -1 )
|
||||
{
|
||||
*pVisibility = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
float flDist = ( ( xPos * xPos ) + ( yPos * yPos ) );
|
||||
if ( flDist <= m_pVisibilityRadius[ *pVisibilityTable ] )
|
||||
{
|
||||
*pVisibility = FOW_VG_IS_VISIBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pVisibility = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <tier0/memdbgoff.h>
|
||||
91
fow/fow_viewer.h
Normal file
91
fow/fow_viewer.h
Normal file
@@ -0,0 +1,91 @@
|
||||
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: a localized viewer for the Fog of War
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef FOW_VIEWER_H
|
||||
#define FOW_VIEWER_H
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
class CFoW;
|
||||
|
||||
class CFoW_Viewer
|
||||
{
|
||||
public:
|
||||
// constructor to init this viewer with the id and temp
|
||||
CFoW_Viewer( int nID, unsigned nViewerTeam );
|
||||
// destructor to free up the local vis grids
|
||||
~CFoW_Viewer( void );
|
||||
|
||||
// update the radius of the viewer. this will realloc the local vis grids
|
||||
void UpdateSize( CFoW *pFoW, float flRadius );
|
||||
// update the location of the viewer
|
||||
bool UpdateLocation( CFoW *pFoW, const Vector &vLocation, Vector *pvOldLocation );
|
||||
// update the height group of this viewer
|
||||
void UpdateHeightGroup( uint8 nHeightGroup );
|
||||
|
||||
//
|
||||
inline void Dirty( ) { m_bDirty = true; }
|
||||
//
|
||||
inline bool IsDirty( ) { return m_bDirty; }
|
||||
// get the team the viewer is on
|
||||
inline unsigned GetTeam( void ) { return m_nViewerTeam; }
|
||||
// get the radius of the viewer
|
||||
inline float GetSize( void ) { return m_flRadius; }
|
||||
// get the grid-centered location of the viewer
|
||||
inline Vector &GetLocation( void ) { return m_vLocation; }
|
||||
// get the real location of the viewer
|
||||
inline Vector &GetRealLocation( void ) { return m_vRealLocation; }
|
||||
// get the height group of the viewer
|
||||
inline uint8 GetHeightGroup( void ) { return m_nHeightGroup; }
|
||||
// get the grid units of the local vis. ( diameter / horizontal grid size ) rounded up
|
||||
inline int GetGridUnits( void ) { return m_nGridUnits; }
|
||||
// get the local visibility grid
|
||||
inline byte *GetVisibility( void ) { return m_pVisibility; }
|
||||
// get the visibility radius grid
|
||||
inline int *GetVisibilityRadius( void ) { return m_pVisibilityRadius; }
|
||||
// get the grid units of the radius grid ( circumference / horizontal grid size ) rounded up
|
||||
inline int GetRadiusUnits( void ) { return m_nRadiusUnits; }
|
||||
// get the upper left coords of this viewer
|
||||
void GetStartPosition( Vector2D &vResults );
|
||||
// get the lower right coords of this viewer
|
||||
void GetEndPosition( Vector2D &vResults );
|
||||
|
||||
// calculate the localized visibility against all occluders.
|
||||
void CalcLocalizedVisibility( CFoW *pFoW );
|
||||
// clear the localized radius grid to the maximum distance
|
||||
void DefaultViewingRadius( CFoW *pFoW );
|
||||
|
||||
//
|
||||
void DrawDebugInfo( Vector &vLocation, float flViewRadius, unsigned nFlags );
|
||||
//
|
||||
size_t GetAllocatedMemory( ) { return m_nAllocatedMemory; }
|
||||
|
||||
private:
|
||||
// clear the localized visibility grid to just the raw radius
|
||||
void DefaultViewingArea( CFoW *pFoW );
|
||||
// turn the radius grid into the localized visibility grid
|
||||
void ResolveRadius( CFoW *pFoW );
|
||||
|
||||
int m_nID; // the id of this viewer
|
||||
unsigned m_nViewerTeam; // the team this viewer belongs to
|
||||
float m_flRadius; // the radius of this viewer
|
||||
Vector m_vLocation; // the grid location of this viewer
|
||||
Vector m_vRealLocation; // the real location of this viewer
|
||||
byte *m_pVisibility; // the localized visibility grid
|
||||
int m_nGridUnits; // the grid units ( diameter / horizontal grid size ) rounded up
|
||||
int *m_pVisibilityRadius; // the localized visibility depth circle
|
||||
int m_nRadiusUnits; // the grid units of the radius grid ( circumference / horizontal grid size ) rounded up
|
||||
int *m_pVisibilityTable; // the visibility table to go from grid to radius
|
||||
bool m_bDirty; //
|
||||
uint8 m_nHeightGroup; // the height group this viewer belongs to
|
||||
size_t m_nAllocatedMemory; //
|
||||
};
|
||||
|
||||
#endif // FOW_VIEWER_H
|
||||
Reference in New Issue
Block a user