463 lines
9.1 KiB
C++
463 lines
9.1 KiB
C++
|
#include "../../idlib/precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
#include "../Game_local.h"
|
||
|
// RAVEN END
|
||
|
#include "AAS_local.h"
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAAS::Alloc
|
||
|
============
|
||
|
*/
|
||
|
idAAS *idAAS::Alloc( void ) {
|
||
|
// RAVEN BEGIN
|
||
|
// jnewquist: Tag scope and callees to track allocations using "new".
|
||
|
MEM_SCOPED_TAG(tag,MA_AAS);
|
||
|
// RAVEN END
|
||
|
return new idAASLocal;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAAS::idAAS
|
||
|
============
|
||
|
*/
|
||
|
idAAS::~idAAS( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::idAASLocal
|
||
|
============
|
||
|
*/
|
||
|
idAASLocal::idAASLocal( void ) {
|
||
|
file = NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::~idAASLocal
|
||
|
============
|
||
|
*/
|
||
|
idAASLocal::~idAASLocal( void ) {
|
||
|
Shutdown();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::Init
|
||
|
============
|
||
|
*/
|
||
|
bool idAASLocal::Init( const idStr &mapName, unsigned int mapFileCRC ) {
|
||
|
if ( file && mapName.Icmp( file->GetName() ) == 0 && mapFileCRC == file->GetCRC() ) {
|
||
|
gameLocal.Printf( "Keeping %s\n", file->GetName() );
|
||
|
RemoveAllObstacles();
|
||
|
}
|
||
|
else {
|
||
|
Shutdown();
|
||
|
|
||
|
file = AASFileManager->LoadAAS( mapName, mapFileCRC );
|
||
|
if ( !file ) {
|
||
|
common->DWarning( "Couldn't load AAS file: '%s'", mapName.c_str() );
|
||
|
return false;
|
||
|
}
|
||
|
// RAVEN BEGIN
|
||
|
// rhummer: Check if this is a dummy file, since it really has no valid data dump it.
|
||
|
else if ( file->IsDummyFile( mapFileCRC ) ) {
|
||
|
AASFileManager->FreeAAS( file );
|
||
|
file = NULL;
|
||
|
return false;
|
||
|
}
|
||
|
// RAVEN END
|
||
|
SetupRouting();
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::Shutdown
|
||
|
============
|
||
|
*/
|
||
|
void idAASLocal::Shutdown( void ) {
|
||
|
if ( file ) {
|
||
|
ShutdownRouting();
|
||
|
RemoveAllObstacles();
|
||
|
AASFileManager->FreeAAS( file );
|
||
|
file = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::Stats
|
||
|
============
|
||
|
*/
|
||
|
void idAASLocal::Stats( void ) const {
|
||
|
if ( !file ) {
|
||
|
return;
|
||
|
}
|
||
|
common->Printf( "[%s]\n", file->GetName() );
|
||
|
file->PrintInfo();
|
||
|
RoutingStats();
|
||
|
}
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// jscott: added
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::StatsSummary
|
||
|
============
|
||
|
*/
|
||
|
size_t idAASLocal::StatsSummary( void ) const {
|
||
|
|
||
|
int size;
|
||
|
|
||
|
if( !file ) {
|
||
|
|
||
|
return( 0 );
|
||
|
}
|
||
|
|
||
|
size = ( numAreaTravelTimes * sizeof( unsigned short ) )
|
||
|
+ ( areaCacheIndexSize * sizeof( idRoutingCache * ) )
|
||
|
+ ( portalCacheIndexSize * sizeof( idRoutingCache * ) );
|
||
|
|
||
|
return( file->GetMemorySize() + size );
|
||
|
}
|
||
|
// RAVEN END
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::GetSettings
|
||
|
============
|
||
|
*/
|
||
|
const idAASSettings *idAASLocal::GetSettings( void ) const {
|
||
|
if ( !file ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return &file->GetSettings();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::PointAreaNum
|
||
|
============
|
||
|
*/
|
||
|
int idAASLocal::PointAreaNum( const idVec3 &origin ) const {
|
||
|
if ( !file ) {
|
||
|
return 0;
|
||
|
}
|
||
|
return file->PointAreaNum( origin );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::PointReachableAreaNum
|
||
|
============
|
||
|
*/
|
||
|
int idAASLocal::PointReachableAreaNum( const idVec3 &origin, const idBounds &searchBounds, const int areaFlags ) const {
|
||
|
if ( !file ) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return file->PointReachableAreaNum( origin, searchBounds, areaFlags, TFL_INVALID );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::BoundsReachableAreaNum
|
||
|
============
|
||
|
*/
|
||
|
int idAASLocal::BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags ) const {
|
||
|
if ( !file ) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return file->BoundsReachableAreaNum( bounds, areaFlags, TFL_INVALID );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::PushPointIntoAreaNum
|
||
|
============
|
||
|
*/
|
||
|
void idAASLocal::PushPointIntoAreaNum( int areaNum, idVec3 &origin ) const {
|
||
|
if ( !file ) {
|
||
|
return;
|
||
|
}
|
||
|
file->PushPointIntoAreaNum( areaNum, origin );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::AreaCenter
|
||
|
============
|
||
|
*/
|
||
|
idVec3 idAASLocal::AreaCenter( int areaNum ) const {
|
||
|
if ( !file ) {
|
||
|
return vec3_origin;
|
||
|
}
|
||
|
return file->GetArea( areaNum ).center;
|
||
|
}
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: added
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::AreaRadius
|
||
|
============
|
||
|
*/
|
||
|
float idAASLocal::AreaRadius( int areaNum ) const {
|
||
|
if ( !file ) {
|
||
|
return 0;
|
||
|
}
|
||
|
return file->GetArea( areaNum ).bounds.GetRadius();
|
||
|
}
|
||
|
// mcg: added
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::AreaBounds
|
||
|
============
|
||
|
*/
|
||
|
idBounds & idAASLocal::AreaBounds( int areaNum ) const {
|
||
|
return file->GetArea( areaNum ).bounds;
|
||
|
}
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::AreaCeiling
|
||
|
============
|
||
|
*/
|
||
|
float idAASLocal::AreaCeiling( int areaNum ) const {
|
||
|
return file->GetArea( areaNum ).ceiling;
|
||
|
}
|
||
|
// RAVEN END
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::AreaFlags
|
||
|
============
|
||
|
*/
|
||
|
int idAASLocal::AreaFlags( int areaNum ) const {
|
||
|
if ( !file ) {
|
||
|
return 0;
|
||
|
}
|
||
|
return file->GetArea( areaNum ).flags;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::AreaTravelFlags
|
||
|
============
|
||
|
*/
|
||
|
int idAASLocal::AreaTravelFlags( int areaNum ) const {
|
||
|
if ( !file ) {
|
||
|
return 0;
|
||
|
}
|
||
|
return file->GetArea( areaNum ).travelFlags;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::Trace
|
||
|
============
|
||
|
*/
|
||
|
bool idAASLocal::Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const {
|
||
|
if ( !file ) {
|
||
|
trace.fraction = 0.0f;
|
||
|
trace.lastAreaNum = 0;
|
||
|
trace.numAreas = 0;
|
||
|
return true;
|
||
|
}
|
||
|
return file->Trace( trace, start, end );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::GetPlane
|
||
|
============
|
||
|
*/
|
||
|
const idPlane &idAASLocal::GetPlane( int planeNum ) const {
|
||
|
if ( !file ) {
|
||
|
static idPlane dummy;
|
||
|
return dummy;
|
||
|
}
|
||
|
return file->GetPlane( planeNum );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::GetEdgeVertexNumbers
|
||
|
============
|
||
|
*/
|
||
|
void idAASLocal::GetEdgeVertexNumbers( int edgeNum, int verts[2] ) const {
|
||
|
if ( !file ) {
|
||
|
verts[0] = verts[1] = 0;
|
||
|
return;
|
||
|
}
|
||
|
const int *v = file->GetEdge( abs(edgeNum) ).vertexNum;
|
||
|
verts[0] = v[INTSIGNBITSET(edgeNum)];
|
||
|
verts[1] = v[INTSIGNBITNOTSET(edgeNum)];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASLocal::GetEdge
|
||
|
============
|
||
|
*/
|
||
|
void idAASLocal::GetEdge( int edgeNum, idVec3 &start, idVec3 &end ) const {
|
||
|
if ( !file ) {
|
||
|
start.Zero();
|
||
|
end.Zero();
|
||
|
return;
|
||
|
}
|
||
|
const int *v = file->GetEdge( abs(edgeNum) ).vertexNum;
|
||
|
start = file->GetVertex( v[INTSIGNBITSET(edgeNum)] );
|
||
|
end = file->GetVertex( v[INTSIGNBITNOTSET(edgeNum)] );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
idAASCallback
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASCallback::~idAASCallback
|
||
|
============
|
||
|
*/
|
||
|
idAASCallback::~idAASCallback ( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASCallback::Test
|
||
|
============
|
||
|
*/
|
||
|
idAASCallback::testResult_t idAASCallback::Test ( class idAAS *aas, int areaNum, const idVec3& origin, float minDistance, float maxDistance, const idVec3* point, aasGoal_t& goal ) {
|
||
|
// Get AAS file
|
||
|
idAASFile* file = ((idAAS&)*aas).GetFile ( );
|
||
|
if ( !file ) {
|
||
|
return TEST_BADAREA;
|
||
|
}
|
||
|
|
||
|
// Get area for edges
|
||
|
aasArea_t& area = file->GetArea ( areaNum );
|
||
|
|
||
|
if ( ai_debugTactical.GetInteger ( ) > 1 ) {
|
||
|
gameRenderWorld->DebugLine ( colorYellow, area.center, area.center + idVec3(0,0,80.0f), 10000 );
|
||
|
}
|
||
|
|
||
|
// Make sure the area itself is valid
|
||
|
if ( !TestArea ( aas, areaNum, area ) ) {
|
||
|
return TEST_BADAREA;
|
||
|
}
|
||
|
|
||
|
if ( ai_debugTactical.GetInteger ( ) > 1 && point ) {
|
||
|
gameRenderWorld->DebugLine ( colorMagenta, *point, *point + idVec3(0,0,64.0f), 10000 );
|
||
|
}
|
||
|
|
||
|
// Test the original origin first
|
||
|
if ( point && TestPointDistance ( origin, *point, minDistance, maxDistance) && TestPoint ( aas, *point ) ) {
|
||
|
goal.areaNum = areaNum;
|
||
|
goal.origin = *point;
|
||
|
return TEST_OK;
|
||
|
}
|
||
|
|
||
|
if ( ai_debugTactical.GetInteger ( ) > 1 ) {
|
||
|
gameRenderWorld->DebugLine ( colorCyan, area.center, area.center + idVec3(0,0,64.0f), 10000 );
|
||
|
}
|
||
|
|
||
|
// Test the center of the area
|
||
|
if ( TestPointDistance ( origin, area.center, minDistance, maxDistance) && TestPoint ( aas, area.center, area.ceiling ) ) {
|
||
|
goal.areaNum = areaNum;
|
||
|
goal.origin = area.center;
|
||
|
return TEST_OK;
|
||
|
}
|
||
|
|
||
|
// For each face test all available edges
|
||
|
int f;
|
||
|
int e;
|
||
|
for ( f = 0; f < area.numFaces; f ++ ) {
|
||
|
aasFace_t& face = file->GetFace ( abs ( file->GetFaceIndex (area.firstFace + f ) ) );
|
||
|
|
||
|
// for each edge test a point between the center of the edge and the center
|
||
|
for ( e = 0; e < face.numEdges; e ++ ) {
|
||
|
idVec3 edgeCenter = file->EdgeCenter ( abs( file->GetEdgeIndex( face.firstEdge + e ) ) );
|
||
|
idVec3 dir = area.center - edgeCenter;
|
||
|
float dist;
|
||
|
for ( dist = dir.Normalize() - 64.0f; dist > 0.0f; dist -= 64.0f ) {
|
||
|
idVec3 testPoint = edgeCenter + dir * dist;
|
||
|
if ( ai_debugTactical.GetInteger ( ) > 1 ) {
|
||
|
gameRenderWorld->DebugLine ( colorPurple, testPoint, testPoint + idVec3(0,0,64.0f), 10000 );
|
||
|
}
|
||
|
|
||
|
if ( TestPointDistance ( origin, testPoint, minDistance, maxDistance) && TestPoint ( aas, testPoint, area.ceiling ) ) {
|
||
|
goal.areaNum = areaNum;
|
||
|
goal.origin = testPoint;
|
||
|
return TEST_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TEST_BADPOINT;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASCallback::Init
|
||
|
============
|
||
|
*/
|
||
|
bool idAASCallback::TestPointDistance ( const idVec3& origin, const idVec3& point, float minDistance, float maxDistance ) {
|
||
|
float dist = (origin - point).LengthFast ( );
|
||
|
if ( minDistance > 0.0f && dist < minDistance ) {
|
||
|
return false;
|
||
|
}
|
||
|
if ( maxDistance > 0.0f && dist > maxDistance ) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASCallback::Init
|
||
|
============
|
||
|
*/
|
||
|
void idAASCallback::Init ( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASCallback::Finish
|
||
|
============
|
||
|
*/
|
||
|
void idAASCallback::Finish ( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASCallback::TestArea
|
||
|
============
|
||
|
*/
|
||
|
bool idAASCallback::TestArea ( class idAAS *aas, int areaNum, const aasArea_t& area ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
idAASCallback::TestPoint
|
||
|
============
|
||
|
*/
|
||
|
bool idAASCallback::TestPoint ( class idAAS *aas, const idVec3& pos, const float zAllow ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// RAVEN END
|