mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 08:10:32 +02:00
234 lines
8.0 KiB
C++
234 lines
8.0 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
IceTech GPL Source Code
|
|
Copyright (C) 2026 Justin Marshall
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "../Game_local.h"
|
|
#include "RecastNavMesh.h"
|
|
|
|
idRecastNavMesh::idRecastNavMesh( void ) {
|
|
handle = RECAST_NAV_HANDLE_INVALID;
|
|
memset( &syntheticReach, 0, sizeof( syntheticReach ) );
|
|
if ( RecastNavigationManager ) {
|
|
handle = RecastNavigationManager->Alloc();
|
|
}
|
|
}
|
|
|
|
idRecastNavMesh::~idRecastNavMesh( void ) {
|
|
if ( RecastNavigationManager && handle != RECAST_NAV_HANDLE_INVALID ) {
|
|
RecastNavigationManager->Free( handle );
|
|
handle = RECAST_NAV_HANDLE_INVALID;
|
|
}
|
|
}
|
|
|
|
bool idRecastNavMesh::HasManager( void ) const {
|
|
return RecastNavigationManager && handle != RECAST_NAV_HANDLE_INVALID;
|
|
}
|
|
|
|
void idRecastNavMesh::Shutdown( void ) {
|
|
if ( HasManager() ) {
|
|
RecastNavigationManager->Free( handle );
|
|
handle = RecastNavigationManager->Alloc();
|
|
}
|
|
name.Clear();
|
|
memset( &syntheticReach, 0, sizeof( syntheticReach ) );
|
|
}
|
|
|
|
bool idRecastNavMesh::Load( const idStr &mapName, const idStr &fileName, unsigned int mapFileCRC ) {
|
|
if ( !HasManager() ) {
|
|
return false;
|
|
}
|
|
if ( !RecastNavigationManager->Load( handle, mapName, fileName, mapFileCRC ) ) {
|
|
name.Clear();
|
|
return false;
|
|
}
|
|
name = fileName;
|
|
return true;
|
|
}
|
|
|
|
bool idRecastNavMesh::IsLoaded( void ) const {
|
|
return HasManager() && RecastNavigationManager->IsLoaded( handle );
|
|
}
|
|
|
|
int idRecastNavMesh::NumPolys( void ) const {
|
|
return HasManager() ? RecastNavigationManager->NumPolys( handle ) : 0;
|
|
}
|
|
|
|
const idAASSettings *idRecastNavMesh::GetSettings( void ) const {
|
|
return HasManager() ? RecastNavigationManager->GetSettings( handle ) : NULL;
|
|
}
|
|
|
|
idStr idRecastNavMesh::NavFileNameForMapName( const idStr &mapName ) {
|
|
idStr navName = mapName;
|
|
navName += ".navmesh";
|
|
return navName;
|
|
}
|
|
|
|
bool idRecastNavMesh::BuildMapFile( const idStr &mapName, const idStr &aasType ) {
|
|
return RecastNavigationManager && RecastNavigationManager->BuildMapFile( mapName.c_str(), aasType.c_str() );
|
|
}
|
|
|
|
void idRecastNavMesh::Stats( void ) const {
|
|
if ( HasManager() ) {
|
|
RecastNavigationManager->Stats( handle );
|
|
}
|
|
}
|
|
|
|
void idRecastNavMesh::DebugDraw( int drawMode ) const {
|
|
if ( HasManager() ) {
|
|
RecastNavigationManager->DebugDraw( handle, gameRenderWorld, drawMode, gameLocal.msec );
|
|
}
|
|
}
|
|
|
|
int idRecastNavMesh::PointAreaNum( const idVec3 &origin ) const {
|
|
return HasManager() ? RecastNavigationManager->PointAreaNum( handle, origin ) : 0;
|
|
}
|
|
|
|
int idRecastNavMesh::PointReachableAreaNum( const idVec3 &origin, const idBounds &searchBounds, const int areaFlags ) const {
|
|
return HasManager() ? RecastNavigationManager->PointReachableAreaNum( handle, origin, searchBounds, areaFlags ) : 0;
|
|
}
|
|
|
|
int idRecastNavMesh::BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags ) const {
|
|
return HasManager() ? RecastNavigationManager->BoundsReachableAreaNum( handle, bounds, areaFlags ) : 0;
|
|
}
|
|
|
|
void idRecastNavMesh::PushPointIntoAreaNum( int areaNum, idVec3 &origin ) const {
|
|
if ( HasManager() ) {
|
|
RecastNavigationManager->PushPointIntoAreaNum( handle, areaNum, origin );
|
|
}
|
|
}
|
|
|
|
idVec3 idRecastNavMesh::AreaCenter( int areaNum ) const {
|
|
return HasManager() ? RecastNavigationManager->AreaCenter( handle, areaNum ) : vec3_origin;
|
|
}
|
|
|
|
int idRecastNavMesh::AreaFlags( int areaNum ) const {
|
|
return HasManager() ? RecastNavigationManager->AreaFlags( handle, areaNum ) : 0;
|
|
}
|
|
|
|
int idRecastNavMesh::AreaTravelFlags( int areaNum ) const {
|
|
return HasManager() ? RecastNavigationManager->AreaTravelFlags( handle, areaNum ) : TFL_INVALID;
|
|
}
|
|
|
|
bool idRecastNavMesh::Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const {
|
|
return HasManager() && RecastNavigationManager->Trace( handle, trace, start, end );
|
|
}
|
|
|
|
bool idRecastNavMesh::SetAreaState( const idBounds &bounds, const int areaContents, bool disabled ) {
|
|
return HasManager() && RecastNavigationManager->SetAreaState( handle, bounds, areaContents, disabled );
|
|
}
|
|
|
|
aasHandle_t idRecastNavMesh::AddObstacle( const idBounds &bounds ) {
|
|
return HasManager() ? RecastNavigationManager->AddObstacle( handle, bounds ) : -1;
|
|
}
|
|
|
|
void idRecastNavMesh::RemoveObstacle( const aasHandle_t obstacleHandle ) {
|
|
if ( HasManager() ) {
|
|
RecastNavigationManager->RemoveObstacle( handle, obstacleHandle );
|
|
}
|
|
}
|
|
|
|
void idRecastNavMesh::RemoveAllObstacles( void ) {
|
|
if ( HasManager() ) {
|
|
RecastNavigationManager->RemoveAllObstacles( handle );
|
|
}
|
|
}
|
|
|
|
int idRecastNavMesh::TravelTimeToGoalArea( int areaNum, const idVec3 &origin, int goalAreaNum, int travelFlags ) const {
|
|
return HasManager() ? RecastNavigationManager->TravelTimeToGoalArea( handle, areaNum, origin, goalAreaNum, travelFlags ) : 0;
|
|
}
|
|
|
|
bool idRecastNavMesh::RouteToGoalArea( int areaNum, const idVec3 origin, int goalAreaNum, int travelFlags, int &travelTime, idReachability **reach ) const {
|
|
recastPath_t route;
|
|
if ( !HasManager() || !RecastNavigationManager->RouteToGoalArea( handle, areaNum, origin, goalAreaNum, travelFlags, route ) ) {
|
|
travelTime = 0;
|
|
*reach = NULL;
|
|
return false;
|
|
}
|
|
|
|
travelTime = route.travelTime;
|
|
memset( &syntheticReach, 0, sizeof( syntheticReach ) );
|
|
syntheticReach.travelType = TFL_WALK;
|
|
syntheticReach.fromAreaNum = areaNum;
|
|
syntheticReach.toAreaNum = route.moveAreaNum;
|
|
syntheticReach.start = route.moveGoal;
|
|
syntheticReach.end = route.moveGoal;
|
|
syntheticReach.travelTime = travelTime;
|
|
*reach = &syntheticReach;
|
|
return true;
|
|
}
|
|
|
|
bool idRecastNavMesh::PathToGoal( aasPath_t &path, int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags ) const {
|
|
recastPath_t recastPath;
|
|
if ( !HasManager() || !RecastNavigationManager->PathToGoal( handle, recastPath, areaNum, origin, goalAreaNum, goalOrigin, travelFlags ) ) {
|
|
return false;
|
|
}
|
|
|
|
path.type = PATHTYPE_WALK;
|
|
path.moveGoal = recastPath.moveGoal;
|
|
path.moveAreaNum = recastPath.moveAreaNum;
|
|
path.secondaryGoal = recastPath.secondaryGoal;
|
|
path.reachability = NULL;
|
|
return true;
|
|
}
|
|
|
|
bool idRecastNavMesh::PathValid( int areaNum, const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin, int travelFlags, idVec3 &endPos, int &endAreaNum ) const {
|
|
return HasManager() && RecastNavigationManager->PathValid( handle, areaNum, origin, goalAreaNum, goalOrigin, travelFlags, endPos, endAreaNum );
|
|
}
|
|
|
|
bool idRecastNavMesh::FindNearestGoal( const idNAV *owner, aasGoal_t &goal, int areaNum, const idVec3 origin, const idVec3 &target, int travelFlags, aasObstacle_t *queryObstacles, int numObstacles, idNAVCallback &callback ) const {
|
|
int areas[MAX_RECAST_PATH_AREAS];
|
|
int numAreas = 0;
|
|
const int targetArea = PointAreaNum( target );
|
|
if ( targetArea <= 0 || !HasManager() || !RecastNavigationManager->PathAreaList( handle, areaNum, origin, targetArea, target, travelFlags, areas, numAreas, MAX_RECAST_PATH_AREAS ) ) {
|
|
return false;
|
|
}
|
|
|
|
for ( int i = numAreas - 1; i >= 0; i-- ) {
|
|
const int candidateArea = areas[i];
|
|
if ( !callback.AreaIsGoal( owner, candidateArea ) ) {
|
|
continue;
|
|
}
|
|
|
|
const idVec3 candidateOrigin = AreaCenter( candidateArea );
|
|
bool blocked = false;
|
|
for ( int j = 0; j < numObstacles; j++ ) {
|
|
if ( queryObstacles[j].expAbsBounds.ContainsPoint( candidateOrigin ) ) {
|
|
blocked = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( !blocked ) {
|
|
goal.areaNum = candidateArea;
|
|
goal.origin = candidateOrigin;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void idRecastNavMesh::ShowPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const {
|
|
aasPath_t path;
|
|
const int areaNum = PointAreaNum( origin );
|
|
if ( PathToGoal( path, areaNum, origin, goalAreaNum, goalOrigin, TFL_WALK ) ) {
|
|
gameRenderWorld->DebugLine( colorGreen, origin, path.moveGoal, gameLocal.msec );
|
|
gameRenderWorld->DebugArrow( colorYellow, path.moveGoal, goalOrigin, 4.0f, gameLocal.msec );
|
|
}
|
|
}
|
|
|
|
void idRecastNavMesh::ShowArea( const idVec3 &origin ) const {
|
|
const int areaNum = PointAreaNum( origin );
|
|
if ( areaNum <= 0 ) {
|
|
return;
|
|
}
|
|
const idVec3 center = AreaCenter( areaNum );
|
|
gameRenderWorld->DebugBounds( colorCyan, idBounds( idVec3( -8.0f, -8.0f, -4.0f ), idVec3( 8.0f, 8.0f, 4.0f ) ), center, gameLocal.msec );
|
|
}
|