mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-29 23:15:56 -04:00
Added sharedPathfinding library
This commit is contained in:
@@ -16,6 +16,7 @@ add_subdirectory(sharedMessageDispatch)
|
||||
add_subdirectory(sharedNetwork)
|
||||
add_subdirectory(sharedNetworkMessages)
|
||||
add_subdirectory(sharedObject)
|
||||
add_subdirectory(sharedPathfinding)
|
||||
add_subdirectory(sharedRandom)
|
||||
add_subdirectory(sharedSkillSystem)
|
||||
add_subdirectory(sharedSynchronization)
|
||||
|
||||
@@ -323,6 +323,7 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSkillSystem/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedTerrain/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedUtility/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include
|
||||
|
||||
@@ -716,9 +716,11 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedUtility/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localizationArchive/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
|
||||
)
|
||||
|
||||
+2
@@ -11,6 +11,8 @@
|
||||
#include "sharedMathArchive/TransformArchive.h"
|
||||
#include "sharedFoundation/MemoryBlockManager.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace SceneChannelMessagesNamespace
|
||||
|
||||
@@ -180,10 +180,12 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedPathfinding/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSynchronization/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedTerrain/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedUtility/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "sharedObject/PortalPropertyTemplate.h"
|
||||
#include "sharedObject/PortalPropertyTemplateList.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(sharedPathfinding)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
|
||||
|
||||
add_subdirectory(src)
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ConfigSharedPathfinding.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/DynamicPathGraph.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/DynamicPathNode.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FirstSharedPathfinding.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/PathEdge.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/PathGraph.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/PathGraphIterator.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/PathNode.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/PathSearch.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Pathfinding.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/PathfindingEnums.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/SetupSharedPathfinding.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/SimplePathGraph.h"
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
set(SHARED_SOURCES
|
||||
shared/ConfigSharedPathfinding.cpp
|
||||
shared/ConfigSharedPathfinding.h
|
||||
shared/DynamicPathGraph.cpp
|
||||
shared/DynamicPathGraph.h
|
||||
shared/DynamicPathNode.cpp
|
||||
shared/DynamicPathNode.h
|
||||
shared/FirstSharedPathfinding.h
|
||||
shared/PathEdge.cpp
|
||||
shared/PathEdge.h
|
||||
shared/Pathfinding.cpp
|
||||
shared/PathfindingEnums.h
|
||||
shared/Pathfinding.h
|
||||
shared/PathGraph.cpp
|
||||
shared/PathGraph.h
|
||||
shared/PathGraphIterator.cpp
|
||||
shared/PathGraphIterator.h
|
||||
shared/PathNode.cpp
|
||||
shared/PathNode.h
|
||||
shared/PathSearch.cpp
|
||||
shared/PathSearch.h
|
||||
shared/SetupSharedPathfinding.cpp
|
||||
shared/SetupSharedPathfinding.h
|
||||
shared/SimplePathGraph.cpp
|
||||
shared/SimplePathGraph.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
win32/FirstSharedPathfinding.cpp
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
|
||||
else()
|
||||
set(PLATFORM_SOURCES "")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shared
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCollision/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedObject/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
)
|
||||
|
||||
add_library(sharedPathfinding STATIC
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigSharedPathfinding.cpp
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
// copyright 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "ConfigSharedPathfinding.h"
|
||||
|
||||
#include "sharedDebug/DebugFlags.h"
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
|
||||
#define KEY_INT(a,b) (ms_ ## a = ConfigFile::getKeyInt("SharedPathfinding", #a, b))
|
||||
#define KEY_BOOL(a,b) {ms_ ## a = ConfigFile::getKeyBool("SharedPathfinding", #a, b); DebugFlags::registerFlag(ms_ ## a, "SharedPathfinding", #a);}
|
||||
#define KEY_FLOAT(a,b) (ms_ ## a = ConfigFile::getKeyFloat("SharedPathfinding", #a, b))
|
||||
#define KEY_STRING(a,b) (ms_ ## a = ConfigFile::getKeyString("SharedPathfinding", #a, b))
|
||||
|
||||
bool ConfigSharedPathfinding::ms_autoCreateBuildingPathNodes = false;
|
||||
bool ConfigSharedPathfinding::ms_useCityRegions = true;
|
||||
bool ConfigSharedPathfinding::ms_jitterCityWaypoints = false;
|
||||
bool ConfigSharedPathfinding::ms_enableDirtyBoxes = false;
|
||||
bool ConfigSharedPathfinding::ms_enablePathScrubber = false;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void ConfigSharedPathfinding::install ()
|
||||
{
|
||||
KEY_BOOL(autoCreateBuildingPathNodes,false);
|
||||
KEY_BOOL(useCityRegions,true);
|
||||
KEY_BOOL(jitterCityWaypoints,false);
|
||||
KEY_BOOL(enableDirtyBoxes,false);
|
||||
KEY_BOOL(enablePathScrubber,false);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,64 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigSharedPathfinding.h
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
// copyright 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_ConfigSharedPathfinding_H
|
||||
#define INCLUDED_ConfigSharedPathfinding_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class ConfigSharedPathfinding
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
|
||||
static bool getAutoCreateBuildingPathNodes();
|
||||
static bool getUseCityRegions();
|
||||
static bool getJitterCityWaypoints();
|
||||
static bool getEnableDirtyBoxes();
|
||||
static bool getEnablePathScrubber();
|
||||
|
||||
private:
|
||||
|
||||
static bool ms_autoCreateBuildingPathNodes;
|
||||
static bool ms_useCityRegions;
|
||||
static bool ms_jitterCityWaypoints;
|
||||
static bool ms_enableDirtyBoxes;
|
||||
static bool ms_enablePathScrubber;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
inline bool ConfigSharedPathfinding::getAutoCreateBuildingPathNodes()
|
||||
{
|
||||
return ms_autoCreateBuildingPathNodes;
|
||||
}
|
||||
|
||||
inline bool ConfigSharedPathfinding::getUseCityRegions()
|
||||
{
|
||||
return ms_useCityRegions;
|
||||
}
|
||||
|
||||
inline bool ConfigSharedPathfinding::getJitterCityWaypoints()
|
||||
{
|
||||
return ms_jitterCityWaypoints;
|
||||
}
|
||||
|
||||
inline bool ConfigSharedPathfinding::getEnableDirtyBoxes()
|
||||
{
|
||||
return ms_enableDirtyBoxes;
|
||||
}
|
||||
|
||||
inline bool ConfigSharedPathfinding::getEnablePathScrubber()
|
||||
{
|
||||
return ms_enablePathScrubber;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,344 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DynamicPathGraph.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/DynamicPathGraph.h"
|
||||
|
||||
#include "sharedCollision/CollisionWorld.h"
|
||||
#include "sharedObject/CellProperty.h"
|
||||
#include "sharedPathfinding/DynamicPathNode.h"
|
||||
|
||||
DynamicPathGraph::DynamicPathGraph ( PathGraphType type )
|
||||
: PathGraph(type),
|
||||
m_nodeList( new NodeList() ),
|
||||
m_dirtyNodes( new IndexList() ),
|
||||
m_liveNodeCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
DynamicPathGraph::~DynamicPathGraph()
|
||||
{
|
||||
clear();
|
||||
|
||||
delete m_nodeList;
|
||||
m_nodeList = NULL;
|
||||
|
||||
delete m_dirtyNodes;
|
||||
m_dirtyNodes = NULL;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void DynamicPathGraph::clear ( void )
|
||||
{
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
delete m_nodeList->at(i);
|
||||
}
|
||||
|
||||
m_nodeList->clear();
|
||||
}
|
||||
|
||||
// ----------
|
||||
// PathGraph interface
|
||||
|
||||
int DynamicPathGraph::getNodeCount ( void ) const
|
||||
{
|
||||
return m_nodeList->size();
|
||||
}
|
||||
|
||||
int DynamicPathGraph::getLiveNodeCount ( void ) const
|
||||
{
|
||||
return m_liveNodeCount;
|
||||
}
|
||||
|
||||
PathNode * DynamicPathGraph::getNode ( int nodeIndex )
|
||||
{
|
||||
return _getNode(nodeIndex);
|
||||
}
|
||||
|
||||
PathNode const * DynamicPathGraph::getNode ( int nodeIndex ) const
|
||||
{
|
||||
return _getNode(nodeIndex);
|
||||
}
|
||||
|
||||
int DynamicPathGraph::getEdgeCount ( int nodeIndex ) const
|
||||
{
|
||||
DynamicPathNode const * node = _getNode(nodeIndex);
|
||||
|
||||
if(node == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return node->getEdgeCount();
|
||||
}
|
||||
}
|
||||
|
||||
PathEdge * DynamicPathGraph::getEdge ( int nodeIndex, int edgeIndex )
|
||||
{
|
||||
DynamicPathNode * node = _getNode(nodeIndex);
|
||||
|
||||
if(node != NULL)
|
||||
{
|
||||
return node->getEdge(edgeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PathEdge const * DynamicPathGraph::getEdge ( int nodeIndex, int edgeIndex ) const
|
||||
{
|
||||
DynamicPathNode const * node = _getNode(nodeIndex);
|
||||
|
||||
if(node != NULL)
|
||||
{
|
||||
return node->getEdge(edgeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int DynamicPathGraph::addNode ( DynamicPathNode * newNode )
|
||||
{
|
||||
if(newNode == NULL) return -1;
|
||||
|
||||
int listSize = m_nodeList->size();
|
||||
|
||||
int nodeIndex = -1;
|
||||
|
||||
if(m_liveNodeCount < listSize)
|
||||
{
|
||||
for(int i = 0; i < listSize; i++)
|
||||
{
|
||||
if(m_nodeList->at(i) == NULL)
|
||||
{
|
||||
nodeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nodeList->resize(listSize + 1);
|
||||
nodeIndex = listSize;
|
||||
}
|
||||
|
||||
FATAL(nodeIndex == -1,("DynamicPathGraph::addNode - Couldn't add the new node to the node list\n"));
|
||||
|
||||
m_nodeList->at(nodeIndex) = newNode;
|
||||
|
||||
newNode->setIndex(nodeIndex);
|
||||
newNode->setGraph(this);
|
||||
|
||||
m_liveNodeCount++;
|
||||
|
||||
return nodeIndex;
|
||||
}
|
||||
|
||||
void DynamicPathGraph::removeNode ( int nodeIndex )
|
||||
{
|
||||
if(nodeIndex == -1) return;
|
||||
|
||||
DynamicPathNode * node = _getNode(nodeIndex);
|
||||
|
||||
if(node != NULL)
|
||||
{
|
||||
unlinkNode(nodeIndex);
|
||||
|
||||
m_nodeList->at(nodeIndex) = NULL;
|
||||
|
||||
delete node;
|
||||
|
||||
m_liveNodeCount--;
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicPathGraph::moveNode ( int nodeIndex, Vector const & newPosition )
|
||||
{
|
||||
DynamicPathNode * node = _getNode(nodeIndex);
|
||||
|
||||
if(node != NULL)
|
||||
{
|
||||
node->setPosition_p(newPosition);
|
||||
|
||||
m_dirtyNodes->push_back(nodeIndex);
|
||||
|
||||
//@todo - HACK - force cleaning after move
|
||||
|
||||
clean();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DynamicPathGraph::update ( void )
|
||||
{
|
||||
if(isDirty())
|
||||
{
|
||||
clean();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DynamicPathGraph::isDirty ( void ) const
|
||||
{
|
||||
return !m_dirtyNodes->empty();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void DynamicPathGraph::clean ( void )
|
||||
{
|
||||
// Clean all dirty nodes
|
||||
|
||||
/* nothing to do here yet */
|
||||
|
||||
// All dirty nodes are now clean but unlinked. Relink them.
|
||||
|
||||
int dirtyCount = m_dirtyNodes->size();
|
||||
|
||||
for(int i = 0; i < dirtyCount; i++)
|
||||
{
|
||||
int dirtyIndex = m_dirtyNodes->at(i);
|
||||
|
||||
relinkNode(dirtyIndex);
|
||||
}
|
||||
|
||||
// Done.
|
||||
|
||||
m_dirtyNodes->clear();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DynamicPathGraph::unlinkNode ( int nodeIndex )
|
||||
{
|
||||
DynamicPathNode * node = _getNode(nodeIndex);
|
||||
|
||||
if(node == NULL) return;
|
||||
|
||||
// ----------
|
||||
|
||||
int edgeCount = node->getEdgeCount();
|
||||
|
||||
for(int i = 0; i < edgeCount; i++)
|
||||
{
|
||||
int neighborIndex = node->getNeighbor(i);
|
||||
|
||||
DynamicPathNode * neighborNode = _getNode(neighborIndex);
|
||||
|
||||
if(neighborNode) neighborNode->_removeEdge(nodeIndex);
|
||||
}
|
||||
|
||||
node->clearEdges();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DynamicPathGraph::relinkNode ( int nodeIndex )
|
||||
{
|
||||
DynamicPathNode * nodeA = _getNode(nodeIndex);
|
||||
|
||||
if(nodeA == NULL) return;
|
||||
|
||||
// ----------
|
||||
|
||||
unlinkNode(nodeIndex);
|
||||
|
||||
int listSize = m_nodeList->size();
|
||||
|
||||
int i;
|
||||
|
||||
for(i = 0; i < listSize; i++)
|
||||
{
|
||||
DynamicPathNode * nodeB = _getNode(i);
|
||||
|
||||
if(nodeB == NULL) continue;
|
||||
if(nodeA == nodeB) continue;
|
||||
|
||||
Vector const & posA = nodeA->getPosition_p();
|
||||
Vector const & posB = nodeB->getPosition_p();
|
||||
|
||||
// Only try and link nodes that are within 40 meters of each other
|
||||
|
||||
if(posA.magnitudeBetweenSquared(posB) < (40.0f * 40.0f))
|
||||
{
|
||||
if(CollisionWorld::canMove( CellProperty::getWorldCellProperty(), posA, posB, 0.5f, true, true, false) == CMR_MoveOK)
|
||||
{
|
||||
nodeA->addEdge( nodeB->getIndex() );
|
||||
nodeB->addEdge( nodeA->getIndex() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// nodes can't be connected
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
// Linking done, prune redundant edges
|
||||
|
||||
nodeA->markRedundantEdges();
|
||||
nodeA->removeMarkedEdges();
|
||||
|
||||
// this has to be done in two passes, otherwise node A's neighbor list could be changing
|
||||
// as we prune edges.
|
||||
|
||||
std::vector<int> neighborList;
|
||||
|
||||
int edgeCount = nodeA->getEdgeCount();
|
||||
|
||||
for(i = 0; i < edgeCount; i++)
|
||||
{
|
||||
neighborList.push_back( nodeA->getNeighbor(i) );
|
||||
}
|
||||
|
||||
for(i = 0; i < edgeCount; i++)
|
||||
{
|
||||
DynamicPathNode * neighborNode = _getNode(neighborList[i]);
|
||||
|
||||
if(neighborNode != NULL)
|
||||
{
|
||||
neighborNode->markRedundantEdges();
|
||||
neighborNode->removeMarkedEdges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DynamicPathNode * DynamicPathGraph::_getNode ( int nodeIndex )
|
||||
{
|
||||
if(nodeIndex == -1) return NULL;
|
||||
|
||||
return m_nodeList->at(nodeIndex);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
DynamicPathNode const * DynamicPathGraph::_getNode ( int nodeIndex ) const
|
||||
{
|
||||
if(nodeIndex == -1) return NULL;
|
||||
|
||||
return m_nodeList->at(nodeIndex);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DynamicPathGraph.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DynamicPathGraph_H
|
||||
#define INCLUDED_DynamicPathGraph_H
|
||||
|
||||
#include "sharedPathfinding/PathGraph.h"
|
||||
|
||||
#include "sharedMath/Vector.h"
|
||||
|
||||
class DynamicPathNode;
|
||||
|
||||
// ======================================================================
|
||||
// Dynamic path graph, used for graphs where we need to be able to add
|
||||
// and remove nodes on the fly (such as city graphs)
|
||||
|
||||
// DynamicPathGraph uses a sparse array to store its nodes. Calling
|
||||
// getNode with a nodeIndex in [0,nodeCount) may return NULL. If you
|
||||
// want to know the number of live nodes in the graph, call getLiveNodeCount.
|
||||
|
||||
class DynamicPathGraph : public PathGraph
|
||||
{
|
||||
public:
|
||||
|
||||
DynamicPathGraph ( PathGraphType type = PGT_None );
|
||||
|
||||
virtual ~DynamicPathGraph();
|
||||
|
||||
// ----------
|
||||
// PathGraph interface
|
||||
|
||||
virtual int getNodeCount ( void ) const;
|
||||
virtual PathNode * getNode ( int nodeIndex );
|
||||
virtual PathNode const * getNode ( int nodeIndex ) const;
|
||||
|
||||
virtual int getEdgeCount ( int nodeIndex ) const;
|
||||
virtual PathEdge * getEdge ( int nodeIndex, int edgeIndex );
|
||||
virtual PathEdge const * getEdge ( int nodeIndex, int edgeIndex ) const;
|
||||
|
||||
// ----------
|
||||
|
||||
virtual int addNode ( DynamicPathNode * newNode );
|
||||
virtual void removeNode ( int nodeIndex );
|
||||
|
||||
virtual void moveNode ( int nodeIndex, Vector const & newPosition );
|
||||
|
||||
virtual void update ( void );
|
||||
|
||||
virtual bool isDirty ( void ) const;
|
||||
virtual void clean ( void );
|
||||
|
||||
virtual void clear ( void );
|
||||
|
||||
virtual void unlinkNode ( int nodeIndex );
|
||||
virtual void relinkNode ( int nodeIndex );
|
||||
|
||||
virtual int getLiveNodeCount( void ) const;
|
||||
|
||||
protected:
|
||||
|
||||
friend class DynamicPathNode;
|
||||
|
||||
DynamicPathNode * _getNode ( int nodeIndex );
|
||||
DynamicPathNode const * _getNode ( int nodeIndex ) const;
|
||||
|
||||
typedef stdvector<DynamicPathNode *>::fwd NodeList;
|
||||
typedef stdvector<int>::fwd IndexList;
|
||||
|
||||
NodeList * m_nodeList;
|
||||
IndexList * m_dirtyNodes;
|
||||
int m_liveNodeCount;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DynamicPathNode.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/DynamicPathNode.h"
|
||||
|
||||
#include "sharedPathfinding/PathEdge.h"
|
||||
#include "sharedPathfinding/DynamicPathGraph.h"
|
||||
|
||||
static float angleBetween ( Vector const & A, Vector const & B, Vector const & C )
|
||||
{
|
||||
Vector dA = (B-A);
|
||||
Vector dB = (C-A);
|
||||
|
||||
IGNORE_RETURN(dA.normalize());
|
||||
IGNORE_RETURN(dB.normalize());
|
||||
|
||||
float dot = dA.dot(dB);
|
||||
|
||||
return acos(dot);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
DynamicPathNode::DynamicPathNode ( void )
|
||||
: PathNode(),
|
||||
m_edges()
|
||||
{
|
||||
}
|
||||
|
||||
DynamicPathNode::DynamicPathNode ( Vector const & position_p )
|
||||
: PathNode( position_p ),
|
||||
m_edges()
|
||||
{
|
||||
}
|
||||
|
||||
DynamicPathNode::~DynamicPathNode()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int DynamicPathNode::getEdgeCount ( void ) const
|
||||
{
|
||||
return m_edges.size();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
PathEdge * DynamicPathNode::getEdge ( int whichEdge )
|
||||
{
|
||||
return &m_edges[whichEdge];
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
PathEdge const * DynamicPathNode::getEdge ( int whichEdge ) const
|
||||
{
|
||||
return &m_edges[whichEdge];
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
int DynamicPathNode::getNeighbor ( int whichEdge ) const
|
||||
{
|
||||
return m_edges[whichEdge].getIndexB();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DynamicPathNode::hasEdge ( int nodeIndex ) const
|
||||
{
|
||||
int edgeCount = m_edges.size();
|
||||
|
||||
for(int i = 0; i < edgeCount; i++)
|
||||
{
|
||||
if(m_edges[i].getIndexB() == nodeIndex)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
bool DynamicPathNode::addEdge ( int nodeIndex )
|
||||
{
|
||||
if(!hasEdge(nodeIndex))
|
||||
{
|
||||
m_edges.push_back( PathEdge( m_index, nodeIndex ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
bool DynamicPathNode::removeEdge ( int nodeIndex )
|
||||
{
|
||||
DynamicPathNode * neighbor = _getGraph()->_getNode(nodeIndex);
|
||||
|
||||
if(neighbor == NULL) return false;
|
||||
|
||||
if(!_removeEdge(nodeIndex)) return false;
|
||||
|
||||
return neighbor->_removeEdge( getIndex() );
|
||||
}
|
||||
|
||||
bool DynamicPathNode::_removeEdge ( int nodeIndex )
|
||||
{
|
||||
int edgeIndex = -1;
|
||||
|
||||
int edgeCount = m_edges.size();
|
||||
|
||||
for(int i = 0; i < edgeCount; i++)
|
||||
{
|
||||
if(m_edges[i].getIndexB() == nodeIndex)
|
||||
{
|
||||
edgeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(edgeIndex != -1)
|
||||
{
|
||||
m_edges.erase( m_edges.begin() + edgeIndex );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void DynamicPathNode::clearEdges ( void )
|
||||
{
|
||||
m_edges.clear();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DynamicPathNode::clearEdgeMarks ( void ) const
|
||||
{
|
||||
int edgeCount = getEdgeCount();
|
||||
|
||||
for(int i = 0; i < edgeCount; i++)
|
||||
{
|
||||
getEdge(i)->clearMarks();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int DynamicPathNode::markRedundantEdges ( void ) const
|
||||
{
|
||||
clearEdgeMarks();
|
||||
|
||||
float angleTolerance = (20.0f / 360.0f) * (2.0f * PI);
|
||||
|
||||
int edgeCount = getEdgeCount();
|
||||
int markCount = 0;
|
||||
|
||||
for(int i = 0; i < edgeCount - 1; i++)
|
||||
{
|
||||
for(int j = i+1; j < edgeCount; j++)
|
||||
{
|
||||
PathEdge const * edgeA = getEdge(i);
|
||||
PathEdge const * edgeB = getEdge(j);
|
||||
|
||||
if(edgeA == NULL) continue;
|
||||
if(edgeB == NULL) continue;
|
||||
|
||||
int iA = edgeA->getIndexA();
|
||||
int iB = edgeA->getIndexB();
|
||||
int iC = edgeB->getIndexB();
|
||||
|
||||
if(getGraph()->getNode(iA)->getType() == PNT_CityBuilding) continue;
|
||||
if(getGraph()->getNode(iB)->getType() == PNT_CityBuilding) continue;
|
||||
if(getGraph()->getNode(iC)->getType() == PNT_CityBuilding) continue;
|
||||
|
||||
Vector A = getGraph()->getNode(iA)->getPosition_p();
|
||||
Vector B = getGraph()->getNode(iB)->getPosition_p();
|
||||
Vector C = getGraph()->getNode(iC)->getPosition_p();
|
||||
|
||||
if(angleBetween(A,B,C) < angleTolerance)
|
||||
{
|
||||
float magAB = (B-A).magnitudeSquared();
|
||||
float magAC = (C-A).magnitudeSquared();
|
||||
|
||||
if(magAB > magAC)
|
||||
{
|
||||
// The A-B edge is longer, so mark edgeA as redundant.
|
||||
|
||||
if(edgeA->getMark(0) != 1)
|
||||
{
|
||||
edgeA->setMark(0,1);
|
||||
markCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The A-C edge is longer, so mark edgeB as redundant.
|
||||
|
||||
if(edgeB->getMark(0) != 1)
|
||||
{
|
||||
edgeB->setMark(0,1);
|
||||
markCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return markCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// not the most efficient way to do this, but it should be OK.
|
||||
|
||||
int DynamicPathNode::removeMarkedEdges ( void )
|
||||
{
|
||||
int removeCount = 0;
|
||||
|
||||
bool removed = true;
|
||||
|
||||
while(removed)
|
||||
{
|
||||
removed = false;
|
||||
|
||||
int edgeCount = getEdgeCount();
|
||||
|
||||
for(int i = 0; i < edgeCount; i++)
|
||||
{
|
||||
PathEdge * edge = getEdge(i);
|
||||
|
||||
if(edge && (edge->getMark(0) != -1))
|
||||
{
|
||||
if(removeEdge(edge->getIndexB()))
|
||||
{
|
||||
removeCount++;
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return removeCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DynamicPathGraph * DynamicPathNode::_getGraph ( void )
|
||||
{
|
||||
return safe_cast< DynamicPathGraph * >( getGraph() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DynamicPathNode.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DynamicPathNode_H
|
||||
#define INCLUDED_DynamicPathNode_H
|
||||
|
||||
#include "sharedMath/Vector.h"
|
||||
#include "sharedPathfinding/PathNode.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class PathEdge;
|
||||
class DynamicPathGraph;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class DynamicPathNode : public PathNode
|
||||
{
|
||||
public:
|
||||
|
||||
DynamicPathNode ( void );
|
||||
|
||||
DynamicPathNode ( Vector const & position_p );
|
||||
|
||||
virtual ~DynamicPathNode();
|
||||
|
||||
// ----------
|
||||
|
||||
int getEdgeCount ( void ) const;
|
||||
PathEdge * getEdge ( int whichEdge );
|
||||
PathEdge const * getEdge ( int whichEdge ) const;
|
||||
|
||||
int getNeighbor ( int whichEdge ) const;
|
||||
|
||||
bool hasEdge ( int nodeIndex ) const;
|
||||
bool addEdge ( int nodeIndex );
|
||||
bool removeEdge ( int nodeIndex );
|
||||
void clearEdges ( void );
|
||||
|
||||
protected:
|
||||
|
||||
friend class DynamicPathGraph;
|
||||
|
||||
virtual void clearEdgeMarks ( void ) const;
|
||||
virtual int markRedundantEdges ( void ) const;
|
||||
virtual int removeMarkedEdges ( void );
|
||||
|
||||
bool _removeEdge ( int nodeIndex );
|
||||
|
||||
DynamicPathGraph * _getGraph ( void );
|
||||
|
||||
// ----------
|
||||
|
||||
typedef std::vector<PathEdge> EdgeList;
|
||||
|
||||
EdgeList m_edges;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstSharedPathfinding.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_FirstSharedPathfinding_H
|
||||
#define INCLUDED_FirstSharedPathfinding_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathEdge.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/PathEdge.h"
|
||||
|
||||
#include "sharedFile/Iff.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
PathEdge::PathEdge()
|
||||
: m_indexA(-1),
|
||||
m_indexB(-1),
|
||||
m_laneWidthRight(0.0f),
|
||||
m_laneWidthLeft(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
PathEdge::PathEdge ( int indexA, int indexB )
|
||||
: m_indexA(indexA),
|
||||
m_indexB(indexB),
|
||||
m_laneWidthRight(0.0f),
|
||||
m_laneWidthLeft(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
PathEdge::~PathEdge()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathEdge::read_0000 ( Iff & iff )
|
||||
{
|
||||
m_indexA = iff.read_int32();
|
||||
m_indexB = iff.read_int32();
|
||||
m_laneWidthRight = iff.read_float();
|
||||
m_laneWidthLeft = iff.read_float();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathEdge::write ( Iff & iff ) const
|
||||
{
|
||||
iff.insertChunkData( m_indexA );
|
||||
iff.insertChunkData( m_indexB );
|
||||
iff.insertChunkData( m_laneWidthRight );
|
||||
iff.insertChunkData( m_laneWidthLeft );
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,149 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathEdge.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PathEdge_H
|
||||
#define INCLUDED_PathEdge_H
|
||||
|
||||
class PathEdge;
|
||||
|
||||
class Iff;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class PathEdge
|
||||
{
|
||||
public:
|
||||
|
||||
PathEdge ( void );
|
||||
|
||||
PathEdge ( int indexA, int indexB );
|
||||
|
||||
virtual ~PathEdge();
|
||||
|
||||
// ----------
|
||||
|
||||
bool operator < ( PathEdge const & edge ) const;
|
||||
bool operator == ( PathEdge const & edge ) const;
|
||||
|
||||
int getIndexA ( void ) const;
|
||||
int getIndexB ( void ) const;
|
||||
|
||||
void setIndexA ( int newIndex );
|
||||
void setIndexB ( int newIndex );
|
||||
|
||||
void read_old ( Iff & iff );
|
||||
void read_0000 ( Iff & iff );
|
||||
|
||||
void write ( Iff & iff ) const;
|
||||
|
||||
// ----------
|
||||
|
||||
int getUserId ( void ) const;
|
||||
void setUserId ( int newId ) const;
|
||||
|
||||
int getMark ( int whichMark ) const;
|
||||
void setMark ( int whichMark, int newValue ) const;
|
||||
void clearMarks ( void ) const;
|
||||
|
||||
protected:
|
||||
|
||||
int m_indexA;
|
||||
int m_indexB;
|
||||
|
||||
float m_laneWidthRight; // [1]
|
||||
float m_laneWidthLeft;
|
||||
|
||||
// These are used to speed up some algorithms. They're not persisted.
|
||||
|
||||
mutable int m_userId;
|
||||
mutable int m_marks[4];
|
||||
};
|
||||
|
||||
// [1] - The lane widths indicate how far to the left or the right of
|
||||
// the edge a creature moving along the edge can stray without hitting
|
||||
// anything.
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool PathEdge::operator < ( PathEdge const & edge ) const
|
||||
{
|
||||
if( m_indexA == edge.m_indexA )
|
||||
{
|
||||
return m_indexB < edge.m_indexB;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_indexA < edge.m_indexA;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool PathEdge::operator == ( PathEdge const & edge ) const
|
||||
{
|
||||
return (m_indexA == edge.m_indexA) && (m_indexB == edge.m_indexB);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathEdge::getIndexA ( void ) const
|
||||
{
|
||||
return m_indexA;
|
||||
}
|
||||
|
||||
inline int PathEdge::getIndexB ( void ) const
|
||||
{
|
||||
return m_indexB;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline void PathEdge::setIndexA ( int newIndex )
|
||||
{
|
||||
m_indexA = newIndex;
|
||||
}
|
||||
|
||||
inline void PathEdge::setIndexB( int newIndex )
|
||||
{
|
||||
m_indexB = newIndex;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathEdge::getUserId ( void ) const
|
||||
{
|
||||
return m_userId;
|
||||
}
|
||||
|
||||
inline void PathEdge::setUserId ( int newId ) const
|
||||
{
|
||||
m_userId = newId;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathEdge::getMark ( int whichMark ) const
|
||||
{
|
||||
return m_marks[whichMark];
|
||||
}
|
||||
|
||||
inline void PathEdge::setMark ( int whichMark, int newMark ) const
|
||||
{
|
||||
m_marks[whichMark] = newMark;
|
||||
}
|
||||
|
||||
inline void PathEdge::clearMarks ( void ) const
|
||||
{
|
||||
m_marks[0] = -1;
|
||||
m_marks[1] = -1;
|
||||
m_marks[2] = -1;
|
||||
m_marks[3] = -1;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathGraph.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/PathGraph.h"
|
||||
|
||||
#include "sharedPathfinding/PathNode.h"
|
||||
#include "sharedPathfinding/PathEdge.h"
|
||||
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
typedef std::stack<PathNode *, std::vector<PathNode *> > PathNodeStack;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
PathGraph::PathGraph ( PathGraphType type )
|
||||
: m_type(type),
|
||||
m_partCount(-1),
|
||||
m_searchLock(false)
|
||||
{
|
||||
}
|
||||
|
||||
PathGraph::~PathGraph()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PathNode * PathGraph::getNeighbor ( int nodeIndex, int edgeIndex )
|
||||
{
|
||||
PathEdge * edge = getEdge(nodeIndex,edgeIndex);
|
||||
|
||||
int neighborIndex = edge->getIndexB();
|
||||
|
||||
return getNode(neighborIndex);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
PathNode const * PathGraph::getNeighbor ( int nodeIndex, int edgeIndex ) const
|
||||
{
|
||||
PathEdge const * edge = getEdge(nodeIndex,edgeIndex);
|
||||
|
||||
int neighborIndex = edge->getIndexB();
|
||||
|
||||
return getNode(neighborIndex);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathGraph::drawDebugShapes ( DebugShapeRenderer * ) const
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int PathGraph::findNode ( PathNodeType type, int key ) const
|
||||
{
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
PathNode const * node = getNode(i);
|
||||
|
||||
if(getEdgeCount(i) == 0) continue;
|
||||
|
||||
if((node != NULL) && (node->getType() == type) && (node->getKey() == key))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int PathGraph::findEntrance ( int key ) const
|
||||
{
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
PathNode const * node = getNode(i);
|
||||
|
||||
if(node == NULL) continue;
|
||||
|
||||
if(getEdgeCount(i) == 0) continue;
|
||||
|
||||
PathNodeType type = node->getType();
|
||||
|
||||
if((type == PNT_CellPortal) || (type == PNT_BuildingEntrance) || (type == PNT_CityEntrance))
|
||||
{
|
||||
if(node->getKey() == key)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int PathGraph::findNearestNode ( Vector const & position_p ) const
|
||||
{
|
||||
int minNode = -1;
|
||||
float minDist2 = REAL_MAX;
|
||||
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
PathNode const * node = getNode(i);
|
||||
|
||||
if(node == NULL) continue;
|
||||
|
||||
if(getEdgeCount(i) == 0) continue;
|
||||
|
||||
float dist2 = position_p.magnitudeBetweenSquared(node->getPosition_p());
|
||||
|
||||
if(dist2 < minDist2)
|
||||
{
|
||||
minNode = i;
|
||||
minDist2 = dist2;
|
||||
}
|
||||
}
|
||||
|
||||
return minNode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int PathGraph::findNearestNode ( PathNodeType searchType, Vector const & position_p ) const
|
||||
{
|
||||
int minNode = -1;
|
||||
float minDist2 = REAL_MAX;
|
||||
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
PathNode const * node = getNode(i);
|
||||
|
||||
if(node == NULL) continue;
|
||||
|
||||
if(getEdgeCount(i) == 0) continue;
|
||||
|
||||
PathNodeType type = node->getType();
|
||||
|
||||
if(type != searchType) continue;
|
||||
|
||||
float dist2 = position_p.magnitudeBetweenSquared(node->getPosition_p());
|
||||
|
||||
if(dist2 < minDist2)
|
||||
{
|
||||
minNode = i;
|
||||
minDist2 = dist2;
|
||||
}
|
||||
}
|
||||
|
||||
return minNode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathGraph::findNodesInRange ( Vector const & position_p, float range, PathNodeList & results ) const
|
||||
{
|
||||
float range2 = range * range;
|
||||
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
PathNode const * node = getNode(i);
|
||||
|
||||
if(node == NULL) continue;
|
||||
|
||||
if(getEdgeCount(i) == 0) continue;
|
||||
|
||||
float dist2 = position_p.magnitudeBetweenSquared(node->getPosition_p());
|
||||
|
||||
if(dist2 < range2)
|
||||
{
|
||||
results.push_back( const_cast<PathNode*>(node) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int PathGraph::getNodeKey ( int nodeIndex ) const
|
||||
{
|
||||
PathNode const * node = getNode(nodeIndex);
|
||||
|
||||
return node ? node->getKey() : -1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathGraph::searchLock ( void ) const
|
||||
{
|
||||
DEBUG_FATAL(m_searchLock,("PathGraph::searchLock - Tried to lock a path graph that was already locked\n"));
|
||||
|
||||
m_searchLock = true;
|
||||
}
|
||||
|
||||
void PathGraph::searchUnlock ( void ) const
|
||||
{
|
||||
DEBUG_WARNING(!m_searchLock,("PathGraph::searchUnlock - Graph was already unlocked\n"));
|
||||
|
||||
m_searchLock = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathGraph::setPartTags ( void )
|
||||
{
|
||||
static PathNodeStack unprocessed;
|
||||
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
PathNode * node = getNode(i);
|
||||
|
||||
node->setPartId(-1);
|
||||
|
||||
// ignore nodes without edges unless they're the only node in the cell
|
||||
|
||||
int edgeCount = getEdgeCount(node->getIndex());
|
||||
|
||||
if(edgeCount > 0)
|
||||
{
|
||||
unprocessed.push(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
PathNodeType type = node->getType();
|
||||
|
||||
if((nodeCount == 1) && (type == PNT_CellPortal))
|
||||
{
|
||||
unprocessed.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PathNodeStack processing;
|
||||
|
||||
int currentTag = 0;
|
||||
|
||||
while(!unprocessed.empty())
|
||||
{
|
||||
PathNode * currentNode = unprocessed.top();
|
||||
unprocessed.pop();
|
||||
|
||||
if(currentNode->getPartId() != -1) continue;
|
||||
|
||||
processing.push(currentNode);
|
||||
|
||||
while(!processing.empty())
|
||||
{
|
||||
PathNode * node = processing.top();
|
||||
processing.pop();
|
||||
|
||||
if(node->getPartId() != -1) continue;
|
||||
|
||||
node->setPartId(currentTag);
|
||||
|
||||
int edgeCount = getEdgeCount(node->getIndex());
|
||||
|
||||
for(int i = 0; i < edgeCount; i++)
|
||||
{
|
||||
int neighborIndex = getEdge(node->getIndex(),i)->getIndexB();
|
||||
|
||||
PathNode * neighborNode = getNode(neighborIndex);
|
||||
|
||||
processing.push(neighborNode);
|
||||
}
|
||||
}
|
||||
|
||||
currentTag++;
|
||||
}
|
||||
|
||||
m_partCount = currentTag;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
int PathGraph::getPartCount ( void ) const
|
||||
{
|
||||
return m_partCount;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,101 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathGraph.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PathGraph_H
|
||||
#define INCLUDED_PathGraph_H
|
||||
|
||||
#include "sharedCollision/BaseClass.h" // this really needs to be in a different library
|
||||
#include "sharedPathfinding/PathfindingEnums.h"
|
||||
|
||||
class PathGraph;
|
||||
class PathEdge;
|
||||
class PathNode;
|
||||
class Iff;
|
||||
class DebugShapeRenderer;
|
||||
class Vector;
|
||||
|
||||
typedef stdvector<int>::fwd IndexList;
|
||||
typedef stdvector<PathNode *>::fwd PathNodeList;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class PathGraph : public BaseClass
|
||||
{
|
||||
public:
|
||||
|
||||
PathGraph ( PathGraphType type = PGT_None );
|
||||
|
||||
virtual ~PathGraph();
|
||||
|
||||
// ----------
|
||||
|
||||
virtual PathGraphType getType ( void ) const;
|
||||
virtual void setType ( PathGraphType newType );
|
||||
|
||||
virtual int getNodeCount ( void ) const = 0;
|
||||
virtual PathNode * getNode ( int nodeIndex ) = 0;
|
||||
virtual PathNode const * getNode ( int nodeIndex ) const = 0;
|
||||
|
||||
virtual int getEdgeCount ( int nodeIndex ) const = 0;
|
||||
virtual PathEdge * getEdge ( int nodeIndex, int edgeIndex ) = 0;
|
||||
virtual PathEdge const * getEdge ( int nodeIndex, int edgeIndex ) const = 0;
|
||||
|
||||
virtual PathNode * getNeighbor ( int nodeIndex, int edgeIndex );
|
||||
virtual PathNode const * getNeighbor ( int nodeIndex, int edgeIndex ) const;
|
||||
|
||||
virtual void drawDebugShapes ( DebugShapeRenderer * renderer ) const;
|
||||
|
||||
// ----------
|
||||
|
||||
virtual int findNode ( PathNodeType type, int key ) const;
|
||||
virtual int findEntrance ( int entranceKey ) const;
|
||||
virtual int findNearestNode ( Vector const & position_p ) const;
|
||||
virtual int findNearestNode ( PathNodeType type, Vector const & position_p ) const;
|
||||
virtual void findNodesInRange( Vector const & position_p, float range, PathNodeList & results) const;
|
||||
|
||||
virtual int getNodeKey ( int nodeIndex ) const;
|
||||
|
||||
// If the A* search is using node marks to associate search nodes with path nodes,
|
||||
// then we can only have 1 search going at a time. Locking and unlocking the path
|
||||
// graph helps to catch if we try to do more than one search at a time.
|
||||
|
||||
virtual void searchLock ( void ) const;
|
||||
virtual void searchUnlock ( void ) const;
|
||||
|
||||
virtual void setPartTags ( void );
|
||||
virtual int getPartCount ( void ) const;
|
||||
|
||||
protected:
|
||||
|
||||
PathGraphType m_type;
|
||||
|
||||
int m_partCount;
|
||||
|
||||
mutable bool m_searchLock;
|
||||
};
|
||||
|
||||
// [1] - The first set of functions allows access to the full set of
|
||||
// edges in the graph, the second set allows access to the outgoing
|
||||
// edges for a particular node in the graph.
|
||||
|
||||
// ----------
|
||||
|
||||
inline PathGraphType PathGraph::getType ( void ) const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
inline void PathGraph::setType ( PathGraphType newType )
|
||||
{
|
||||
m_type = newType;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathGraph.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/PathGraphIterator.h"
|
||||
|
||||
#include "sharedPathfinding/PathGraph.h"
|
||||
#include "sharedPathfinding/PathEdge.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
PathGraphIterator::PathGraphIterator ()
|
||||
: m_graph(NULL),
|
||||
m_nodeIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
PathGraphIterator::PathGraphIterator ( PathGraph const * graph, int nodeIndex )
|
||||
: m_graph(graph),
|
||||
m_nodeIndex(nodeIndex)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
bool PathGraphIterator::isValid ( void ) const
|
||||
{
|
||||
return (m_graph != NULL) && (m_nodeIndex != -1) && (m_graph->getNode(m_nodeIndex) != NULL);
|
||||
}
|
||||
|
||||
PathNode const * PathGraphIterator::getNode ( void ) const
|
||||
{
|
||||
if( (m_graph != NULL) && (m_nodeIndex != -1) )
|
||||
{
|
||||
return m_graph->getNode( m_nodeIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int PathGraphIterator::getNeighborCount ( void ) const
|
||||
{
|
||||
if(!isValid()) return 0;
|
||||
|
||||
return m_graph->getEdgeCount( m_nodeIndex );
|
||||
}
|
||||
|
||||
PathNode const * PathGraphIterator::getNeighbor ( int whichNeighbor ) const
|
||||
{
|
||||
if(!isValid()) return NULL;
|
||||
|
||||
return m_graph->getNode( m_graph->getEdge( m_nodeIndex, whichNeighbor )->getIndexB() );
|
||||
}
|
||||
|
||||
void PathGraphIterator::stepTo ( int whichNeighbor )
|
||||
{
|
||||
if(!isValid()) return;
|
||||
|
||||
m_nodeIndex = m_graph->getEdge( m_nodeIndex, whichNeighbor )->getIndexB();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,50 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathGraphIterator.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PathGraphIterator_H
|
||||
#define INCLUDED_PathGraphIterator_H
|
||||
|
||||
class PathGraph;
|
||||
class PathNode;
|
||||
|
||||
// ======================================================================
|
||||
// This is an accessory class to make code that traverses path graphs
|
||||
// easier. It's not an iterator in the strict STL sense, but it is quite
|
||||
// helpful.
|
||||
|
||||
class PathGraphIterator
|
||||
{
|
||||
public:
|
||||
|
||||
PathGraphIterator ();
|
||||
|
||||
PathGraphIterator ( PathGraph const * graph, int nodeIndex );
|
||||
|
||||
// ----------
|
||||
|
||||
bool isValid ( void ) const;
|
||||
|
||||
PathNode const * getNode ( void ) const;
|
||||
|
||||
int getNeighborCount ( void ) const;
|
||||
PathNode const * getNeighbor ( int whichNeighbor ) const;
|
||||
|
||||
void stepTo ( int whichNeighbor );
|
||||
|
||||
// ----------
|
||||
|
||||
protected:
|
||||
|
||||
PathGraph const * m_graph;
|
||||
int m_nodeIndex;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathNode.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/PathNode.h"
|
||||
|
||||
#include "sharedFile/Iff.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
PathNode::PathNode()
|
||||
: m_graph(NULL),
|
||||
m_index(-1),
|
||||
m_id(-1),
|
||||
m_key(-1),
|
||||
m_type(PNT_Invalid),
|
||||
m_partId(-1),
|
||||
m_position( Vector::zero ),
|
||||
m_radius(0.0f),
|
||||
m_userId(-1)
|
||||
{
|
||||
clearMarks();
|
||||
}
|
||||
|
||||
PathNode::PathNode ( Vector const & position )
|
||||
: m_graph(NULL),
|
||||
m_index(-1),
|
||||
m_id(-1),
|
||||
m_key(-1),
|
||||
m_type(PNT_Invalid),
|
||||
m_partId(-1),
|
||||
m_position( position ),
|
||||
m_radius(0.0f),
|
||||
m_userId(-1)
|
||||
{
|
||||
clearMarks();
|
||||
}
|
||||
|
||||
PathNode::~PathNode()
|
||||
{
|
||||
}
|
||||
|
||||
void PathNode::copy ( PathNode const & P )
|
||||
{
|
||||
m_id = P.m_id;
|
||||
m_key = P.m_key;
|
||||
m_type = P.m_type;
|
||||
m_partId = P.m_partId;
|
||||
m_position = P.m_position;
|
||||
m_radius = P.m_radius;
|
||||
m_userId = P.m_userId;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathNode::read_0000 ( Iff & iff )
|
||||
{
|
||||
m_index = iff.read_int32();
|
||||
m_id = iff.read_int32();
|
||||
m_key = iff.read_int32();
|
||||
m_type = static_cast<PathNodeType>(iff.read_int32());
|
||||
m_position = iff.read_floatVector();
|
||||
m_radius = iff.read_float();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathNode::write ( Iff & iff ) const
|
||||
{
|
||||
iff.insertChunkData( m_index );
|
||||
iff.insertChunkData( m_id );
|
||||
iff.insertChunkData( m_key );
|
||||
iff.insertChunkData( m_type );
|
||||
iff.insertChunkData( m_position );
|
||||
iff.insertChunkData( m_radius );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool PathNode::hasSubgraph ( void ) const
|
||||
{
|
||||
if(m_type == PNT_BuildingCell) return true;
|
||||
if(m_type == PNT_BuildingCellPart) return true;
|
||||
if(m_type == PNT_CityBuilding) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool PathNode::isConcrete ( void ) const
|
||||
{
|
||||
if(m_type == PNT_BuildingEntrance) return false;
|
||||
if(m_type == PNT_BuildingCell) return false;
|
||||
if(m_type == PNT_BuildingPortal) return false;
|
||||
if(m_type == PNT_CityBuildingEntrance) return false;
|
||||
if(m_type == PNT_CityBuilding) return false;
|
||||
if(m_type == PNT_Invalid) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,238 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathNode.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PathNode_H
|
||||
#define INCLUDED_PathNode_H
|
||||
|
||||
#include "sharedMath/Vector.h"
|
||||
#include "sharedPathfinding/PathfindingEnums.h"
|
||||
|
||||
class Iff;
|
||||
class PathGraph;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class PathNode
|
||||
{
|
||||
public:
|
||||
|
||||
// ----------
|
||||
|
||||
PathNode ( void );
|
||||
|
||||
PathNode ( Vector const & position_p );
|
||||
|
||||
virtual ~PathNode();
|
||||
|
||||
virtual void copy ( PathNode const & P );
|
||||
|
||||
// ----------
|
||||
|
||||
PathGraph * getGraph ( void );
|
||||
PathGraph const * getGraph ( void ) const;
|
||||
void setGraph ( PathGraph * graph );
|
||||
|
||||
bool hasSubgraph ( void ) const;
|
||||
|
||||
int getIndex ( void ) const;
|
||||
void setIndex ( int newIndex );
|
||||
|
||||
int getId ( void ) const;
|
||||
void setId ( int newId );
|
||||
|
||||
int getKey ( void ) const;
|
||||
void setKey ( int newKey );
|
||||
|
||||
PathNodeType getType ( void ) const;
|
||||
void setType ( PathNodeType newType );
|
||||
|
||||
int getPartId ( void ) const;
|
||||
void setPartId ( int newPart );
|
||||
|
||||
// ----------
|
||||
|
||||
Vector const & getPosition_p ( void ) const;
|
||||
virtual void setPosition_p ( Vector const & newPosition );
|
||||
|
||||
float getRadius ( void ) const;
|
||||
void setRadius ( float newRadius );
|
||||
|
||||
// ----------
|
||||
|
||||
int getUserId ( void ) const;
|
||||
void setUserId ( int newId ) const;
|
||||
|
||||
int getMark ( int whichMark ) const;
|
||||
void setMark ( int whichMark, int newValue ) const;
|
||||
void clearMarks ( void ) const;
|
||||
|
||||
// ----------
|
||||
|
||||
void read_0000 ( Iff & iff );
|
||||
|
||||
void write ( Iff & iff ) const;
|
||||
|
||||
bool isConcrete ( void ) const;
|
||||
|
||||
protected:
|
||||
|
||||
PathGraph * m_graph;
|
||||
|
||||
int m_index;
|
||||
int m_id;
|
||||
int m_key;
|
||||
PathNodeType m_type;
|
||||
int m_partId;
|
||||
|
||||
Vector m_position;
|
||||
float m_radius;
|
||||
|
||||
// These are used to speed up some algorithms. They're not persisted.
|
||||
// Code that uses the marks MUST clear them after use.
|
||||
|
||||
mutable int m_userId;
|
||||
mutable int m_marks[4];
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline PathGraph * PathNode::getGraph ( void )
|
||||
{
|
||||
return m_graph;
|
||||
}
|
||||
|
||||
inline PathGraph const * PathNode::getGraph ( void ) const
|
||||
{
|
||||
return m_graph;
|
||||
}
|
||||
|
||||
inline void PathNode::setGraph ( PathGraph * graph )
|
||||
{
|
||||
m_graph = graph;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathNode::getIndex ( void ) const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
inline void PathNode::setIndex ( int newIndex )
|
||||
{
|
||||
m_index = newIndex;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathNode::getId ( void ) const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
inline void PathNode::setId ( int newId )
|
||||
{
|
||||
m_id = newId;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathNode::getKey ( void ) const
|
||||
{
|
||||
return m_key;
|
||||
}
|
||||
|
||||
inline void PathNode::setKey ( int newKey )
|
||||
{
|
||||
m_key = newKey;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline PathNodeType PathNode::getType ( void ) const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
inline void PathNode::setType ( PathNodeType newType )
|
||||
{
|
||||
m_type = newType;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathNode::getPartId ( void ) const
|
||||
{
|
||||
return m_partId;
|
||||
}
|
||||
|
||||
inline void PathNode::setPartId ( int newId )
|
||||
{
|
||||
m_partId = newId;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline Vector const & PathNode::getPosition_p ( void ) const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
inline void PathNode::setPosition_p ( Vector const & newPosition )
|
||||
{
|
||||
m_position = newPosition;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline float PathNode::getRadius ( void ) const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
inline void PathNode::setRadius ( float newRadius )
|
||||
{
|
||||
m_radius = newRadius;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PathNode::getUserId ( void ) const
|
||||
{
|
||||
return m_userId;
|
||||
}
|
||||
|
||||
inline void PathNode::setUserId ( int newId ) const
|
||||
{
|
||||
m_userId = newId;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
inline int PathNode::getMark ( int whichMark ) const
|
||||
{
|
||||
return m_marks[whichMark];
|
||||
}
|
||||
|
||||
inline void PathNode::setMark ( int whichMark, int newMark ) const
|
||||
{
|
||||
m_marks[whichMark] = newMark;
|
||||
}
|
||||
|
||||
inline void PathNode::clearMarks ( void ) const
|
||||
{
|
||||
m_marks[0] = -1;
|
||||
m_marks[1] = -1;
|
||||
m_marks[2] = -1;
|
||||
m_marks[3] = -1;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,652 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathSearch.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/PathSearch.h"
|
||||
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/MemoryBlockManager.h"
|
||||
#include "sharedFoundation/MemoryBlockManagerMacros.h"
|
||||
|
||||
#include "sharedDebug/PerformanceTimer.h"
|
||||
|
||||
#include "sharedPathfinding/PathGraph.h"
|
||||
#include "sharedPathfinding/PathNode.h"
|
||||
#include "sharedPathfinding/PathEdge.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
const float BIG_HEURISTIC = 1000000000.0f;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
size_t PathNodeHasher::operator() ( PathNode const * node ) const
|
||||
{
|
||||
return reinterpret_cast<size_t>(node);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
class PathSearchNode
|
||||
{
|
||||
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
|
||||
|
||||
public:
|
||||
|
||||
PathSearchNode( PathSearch * search, PathGraph const * graph, PathNode const * node );
|
||||
|
||||
int getNeighborCount ( void );
|
||||
|
||||
PathNode const * getPathNode ( void ) const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
int getPathNodeIndex ( void ) const
|
||||
{
|
||||
return m_node->getIndex();
|
||||
}
|
||||
|
||||
PathSearchNode * getNeighbor ( int whichNeighbor );
|
||||
|
||||
// ----------
|
||||
|
||||
PathSearchNode * getParent ( void ) const
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
void setParent ( PathSearchNode * newParent )
|
||||
{
|
||||
m_parent = newParent;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
float getCost ( void ) const
|
||||
{
|
||||
return m_cost;
|
||||
}
|
||||
|
||||
void setCost ( float newCost )
|
||||
{
|
||||
m_cost = newCost;
|
||||
m_total = m_cost + m_heuristic;
|
||||
}
|
||||
|
||||
float getTotal ( void ) const
|
||||
{
|
||||
return m_total;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
bool isQueued ( void )
|
||||
{
|
||||
return m_queued;
|
||||
}
|
||||
|
||||
void setQueued ( bool queued )
|
||||
{
|
||||
m_queued = queued;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void setPathIndex ( int index )
|
||||
{
|
||||
m_pathIndex = index;
|
||||
}
|
||||
|
||||
int getPathIndex ( void ) const
|
||||
{
|
||||
return m_pathIndex;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
PathSearchNode * getSearchNode ( PathNode const * node );
|
||||
PathSearchNode * createSearchNode ( PathNode const * node );
|
||||
|
||||
// ----------
|
||||
|
||||
protected:
|
||||
|
||||
PathSearch * m_search;
|
||||
PathSearchNode * m_parent;
|
||||
PathGraph const * m_graph;
|
||||
PathNode const * m_node;
|
||||
|
||||
bool m_queued;
|
||||
|
||||
float m_cost;
|
||||
float m_heuristic;
|
||||
float m_total;
|
||||
|
||||
int m_pathIndex;
|
||||
};
|
||||
|
||||
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(PathSearchNode, true, 0, 0, 0);
|
||||
|
||||
// ----------
|
||||
|
||||
PathSearchNode::PathSearchNode ( PathSearch * search, PathGraph const * graph, PathNode const * node )
|
||||
: m_search(search),
|
||||
m_parent(NULL),
|
||||
m_graph(graph),
|
||||
m_node(node),
|
||||
m_queued(false),
|
||||
m_cost(REAL_MAX),
|
||||
m_heuristic(0.0f),
|
||||
m_total(REAL_MAX),
|
||||
m_pathIndex(-1)
|
||||
{
|
||||
m_heuristic = m_search->calcHeuristic(m_node);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int PathSearchNode::getNeighborCount ( void )
|
||||
{
|
||||
return m_graph->getEdgeCount( m_node->getIndex() );
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
PathSearchNode * PathSearchNode::getNeighbor ( int whichNeighbor )
|
||||
{
|
||||
int neighborIndex = m_graph->getEdge( m_node->getIndex(), whichNeighbor )->getIndexB();
|
||||
|
||||
PathNode const * neighborNode = m_graph->getNode(neighborIndex);
|
||||
|
||||
if(neighborNode != NULL)
|
||||
{
|
||||
return getSearchNode(neighborNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PathSearchNode * PathSearchNode::createSearchNode( PathNode const * node )
|
||||
{
|
||||
// doing bad voodoo with the node marks
|
||||
|
||||
PathSearchNode * oldNode = NULL;
|
||||
|
||||
int mark = node->getMark(3);
|
||||
|
||||
if(mark != -1)
|
||||
{
|
||||
oldNode = (PathSearchNode*)((void*)mark);
|
||||
}
|
||||
|
||||
delete oldNode;
|
||||
|
||||
PathSearchNode * searchNode = new PathSearchNode(m_search,m_graph,node);
|
||||
|
||||
node->setMark( 3, (int)((void*)searchNode) );
|
||||
|
||||
m_search->m_visitedNodes->push_back(node);
|
||||
|
||||
return searchNode;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
PathSearchNode * PathSearchNode::getSearchNode( PathNode const * node )
|
||||
{
|
||||
// doing bad voodoo with the node marks
|
||||
|
||||
PathSearchNode * searchNode = NULL;
|
||||
|
||||
int mark = node->getMark(3);
|
||||
|
||||
if(mark != -1)
|
||||
{
|
||||
searchNode = (PathSearchNode*)((void*)mark);
|
||||
}
|
||||
|
||||
if(searchNode == NULL)
|
||||
{
|
||||
return createSearchNode(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
return searchNode;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
bool PathSearchGreater( PathSearchNode const * A, PathSearchNode const * B )
|
||||
{
|
||||
return A->getTotal() > B->getTotal();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class PathSearchQueue
|
||||
{
|
||||
public:
|
||||
|
||||
void push ( PathSearchNode * node )
|
||||
{
|
||||
m_nodes.push_back(node);
|
||||
|
||||
std::push_heap(m_nodes.begin(),m_nodes.end(),PathSearchGreater);
|
||||
|
||||
node->setQueued(true);
|
||||
}
|
||||
|
||||
PathSearchNode * pop ( void )
|
||||
{
|
||||
PathSearchNode * node = m_nodes.front();
|
||||
|
||||
std::pop_heap(m_nodes.begin(),m_nodes.end(),PathSearchGreater);
|
||||
m_nodes.pop_back();
|
||||
|
||||
node->setQueued(false);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void update ( PathSearchNode * node )
|
||||
{
|
||||
if(node->isQueued())
|
||||
{
|
||||
for(uint i = 0; i < m_nodes.size(); i++)
|
||||
{
|
||||
if(m_nodes[i] == node)
|
||||
{
|
||||
std::push_heap( m_nodes.begin(), m_nodes.begin() + i + 1, PathSearchGreater );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
push(node);
|
||||
}
|
||||
}
|
||||
|
||||
void clear ( void )
|
||||
{
|
||||
m_nodes.clear();
|
||||
}
|
||||
|
||||
bool empty ( void )
|
||||
{
|
||||
return m_nodes.empty();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<PathSearchNode *> m_nodes;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void PathSearch::install()
|
||||
{
|
||||
PathSearchNode::install();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PathSearch::PathSearch ( void )
|
||||
: m_graph(NULL),
|
||||
m_start(NULL),
|
||||
m_goal(NULL),
|
||||
m_multiGoal(false),
|
||||
m_goals(new NodeList()),
|
||||
m_queue(new PathSearchQueue()),
|
||||
m_path(new IndexList()),
|
||||
m_visitedNodes(new NodeList())
|
||||
{
|
||||
m_path->reserve(20);
|
||||
m_visitedNodes->reserve(20);
|
||||
}
|
||||
|
||||
PathSearch::~PathSearch()
|
||||
{
|
||||
delete m_goals;
|
||||
m_goals = NULL;
|
||||
|
||||
delete m_queue;
|
||||
m_queue = NULL;
|
||||
|
||||
delete m_path;
|
||||
m_path = NULL;
|
||||
|
||||
delete m_visitedNodes;
|
||||
m_visitedNodes = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PathSearchNode * PathSearch::search ( void )
|
||||
{
|
||||
PathSearchNode * startNode = new PathSearchNode(this,m_graph,m_start);
|
||||
|
||||
startNode->setCost(0.0f);
|
||||
startNode->setPathIndex(0);
|
||||
|
||||
m_queue->push(startNode);
|
||||
|
||||
while(!m_queue->empty())
|
||||
{
|
||||
PathSearchNode * node = m_queue->pop();
|
||||
|
||||
if(atGoal(node))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
int neighborCount = node->getNeighborCount();
|
||||
|
||||
for(int i = 0; i < neighborCount; i++)
|
||||
{
|
||||
PathSearchNode * neighbor = node->getNeighbor(i);
|
||||
|
||||
if(neighbor != NULL)
|
||||
{
|
||||
float newCost = node->getCost() + costBetween(node->getPathNode(),neighbor->getPathNode());
|
||||
|
||||
if( newCost < neighbor->getCost() )
|
||||
{
|
||||
neighbor->setParent(node);
|
||||
neighbor->setCost(newCost);
|
||||
neighbor->setPathIndex( node->getPathIndex() + 1);
|
||||
|
||||
m_queue->update(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
extern float pathSearchTime;
|
||||
|
||||
bool PathSearch::search ( PathGraph const * graph, int startIndex, int goalIndex )
|
||||
{
|
||||
PerformanceTimer timer;
|
||||
|
||||
timer.start();
|
||||
|
||||
m_graph = graph;
|
||||
m_start = graph->getNode(startIndex);
|
||||
m_goal = graph->getNode(goalIndex);
|
||||
m_multiGoal = false;
|
||||
|
||||
if(m_start == NULL) return false;
|
||||
if(m_goal == NULL) return false;
|
||||
|
||||
m_path->clear();
|
||||
|
||||
PathSearchNode * endNode = search();
|
||||
|
||||
bool buildOk = buildPath(endNode);
|
||||
|
||||
cleanup();
|
||||
|
||||
timer.stop();
|
||||
|
||||
pathSearchTime += timer.getElapsedTime();
|
||||
|
||||
return buildOk;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool PathSearch::search ( PathGraph const * graph, int startIndex, IndexList const & goalIndices )
|
||||
{
|
||||
PerformanceTimer timer;
|
||||
|
||||
timer.start();
|
||||
|
||||
m_graph = graph;
|
||||
m_start = graph->getNode(startIndex);
|
||||
|
||||
m_multiGoal = true;
|
||||
|
||||
int goalCount = goalIndices.size();
|
||||
|
||||
if(goalCount == 0) return false;
|
||||
if(m_start == NULL) return false;
|
||||
|
||||
m_goals->resize(goalCount);
|
||||
|
||||
for(int i = 0; i < goalCount; i++)
|
||||
{
|
||||
m_goals->at(i) = graph->getNode(goalIndices[i]);
|
||||
}
|
||||
|
||||
PathSearchNode * endNode = search();
|
||||
|
||||
bool buildOk = buildPath(endNode);
|
||||
|
||||
cleanup();
|
||||
|
||||
timer.stop();
|
||||
|
||||
pathSearchTime += timer.getElapsedTime();
|
||||
|
||||
return buildOk;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool PathSearch::buildPath ( PathSearchNode * endNode )
|
||||
{
|
||||
if( endNode == NULL )
|
||||
{
|
||||
m_path->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
int pathLength = endNode->getPathIndex() + 1;
|
||||
|
||||
m_path->resize(pathLength);
|
||||
|
||||
PathSearchNode * cursor = endNode;
|
||||
|
||||
while(cursor)
|
||||
{
|
||||
int pathIndex = cursor->getPathIndex();
|
||||
int nodeIndex = cursor->getPathNodeIndex();
|
||||
|
||||
m_path->at(pathIndex) = nodeIndex;
|
||||
|
||||
cursor = cursor->getParent();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PathSearch::cleanup ( void )
|
||||
{
|
||||
int visitedCount = m_visitedNodes->size();
|
||||
|
||||
for(int i = 0; i < visitedCount; i++)
|
||||
{
|
||||
PathNode const * visitedNode = m_visitedNodes->at(i);
|
||||
|
||||
int mark = visitedNode->getMark(3);
|
||||
|
||||
if(mark != -1)
|
||||
{
|
||||
PathSearchNode * searchNode = (PathSearchNode*)((void*)mark);
|
||||
|
||||
delete searchNode;
|
||||
}
|
||||
|
||||
visitedNode->clearMarks();
|
||||
}
|
||||
|
||||
m_queue->clear();
|
||||
m_goals->clear();
|
||||
m_visitedNodes->clear();
|
||||
|
||||
m_multiGoal = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
float PathSearch::costBetween ( PathNode const * A, PathNode const * B ) const
|
||||
{
|
||||
if(m_graph->getType() == PGT_Building)
|
||||
{
|
||||
if(A->getType() == PNT_BuildingCell)
|
||||
{
|
||||
return BIG_HEURISTIC;
|
||||
}
|
||||
|
||||
if(B->getType() == PNT_BuildingCell)
|
||||
{
|
||||
return BIG_HEURISTIC;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector posA = A->getPosition_p();
|
||||
Vector posB = B->getPosition_p();
|
||||
|
||||
posA.y = 0;
|
||||
posB.y = 0;
|
||||
|
||||
float dist = posA.magnitudeBetween(posB);
|
||||
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
float PathSearch::calcHeuristic ( PathNode const * A ) const
|
||||
{
|
||||
if(!m_graph) return BIG_HEURISTIC;
|
||||
|
||||
if(m_multiGoal)
|
||||
{
|
||||
int minGoal = -1;
|
||||
float minHeuristic = REAL_MAX;
|
||||
|
||||
int goalCount = m_goals->size();
|
||||
|
||||
for(int i = 0; i < goalCount; i++)
|
||||
{
|
||||
PathNode const * goal = m_goals->at(i);
|
||||
|
||||
float heuristic = calcHeuristic(A,goal);
|
||||
|
||||
if(heuristic < minHeuristic)
|
||||
{
|
||||
minHeuristic = heuristic;
|
||||
minGoal = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(minGoal != -1)
|
||||
{
|
||||
return minHeuristic;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BIG_HEURISTIC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return calcHeuristic(A,m_goal);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
float PathSearch::calcHeuristic ( PathNode const * A, PathNode const * goal ) const
|
||||
{
|
||||
if(m_graph->getType() == PGT_Building)
|
||||
{
|
||||
// HACK - Exporter versions 2.136 and earlier created building graph
|
||||
// edges connected to cell 0, which is incorrect since cell 0 represents
|
||||
// the outside of the building.
|
||||
|
||||
// Get around this by making any edge connected to the graph node
|
||||
// for cell 0 have a huge heuristic.
|
||||
|
||||
if(m_goal->getType() == PNT_BuildingCell)
|
||||
{
|
||||
if(m_goal->getKey() == 0)
|
||||
{
|
||||
return BIG_HEURISTIC;
|
||||
}
|
||||
}
|
||||
|
||||
if(A->getType() == PNT_BuildingCell)
|
||||
{
|
||||
if(A->getKey() == 0)
|
||||
{
|
||||
return BIG_HEURISTIC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return costBetween(A,goal) * 3.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
IndexList const & PathSearch::getPath ( void ) const
|
||||
{
|
||||
return *m_path;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool PathSearch::atGoal ( PathSearchNode * searchNode ) const
|
||||
{
|
||||
if(searchNode == NULL) return false;
|
||||
|
||||
if(m_multiGoal)
|
||||
{
|
||||
PathNode const * pathNode = searchNode->getPathNode();
|
||||
|
||||
if(pathNode == NULL) return false;
|
||||
|
||||
return std::find( m_goals->begin(), m_goals->end(), pathNode ) != m_goals->end();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_goal && (m_goal == searchNode->getPathNode());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -0,0 +1,83 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathSearch.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PathSearch_H
|
||||
#define INCLUDED_PathSearch_H
|
||||
|
||||
class PathGraph;
|
||||
class PathNode;
|
||||
class PathSearch;
|
||||
class PathSearchNode;
|
||||
class PathSearchQueue;
|
||||
|
||||
|
||||
struct PathNodeHasher
|
||||
{
|
||||
size_t operator() ( PathNode const * node ) const;
|
||||
};
|
||||
|
||||
typedef stdvector<int>::fwd IndexList;
|
||||
typedef stdvector<PathNode const *>::fwd NodeList;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class PathSearch
|
||||
{
|
||||
public:
|
||||
|
||||
PathSearch();
|
||||
~PathSearch();
|
||||
|
||||
static void install ( void );
|
||||
|
||||
// ----------
|
||||
|
||||
bool search ( PathGraph const * graph, int startIndex, int goalIndex );
|
||||
|
||||
bool search ( PathGraph const * graph, int startIndex, IndexList const & goalIndices );
|
||||
|
||||
IndexList const & getPath ( void ) const;
|
||||
|
||||
protected:
|
||||
|
||||
PathSearchNode * search ( void );
|
||||
|
||||
float costBetween ( PathNode const * A, PathNode const * B ) const;
|
||||
|
||||
float calcHeuristic ( PathNode const * A ) const;
|
||||
float calcHeuristic ( PathNode const * A, PathNode const * goal ) const;
|
||||
|
||||
void cleanup ( void );
|
||||
|
||||
bool buildPath ( PathSearchNode * endNode );
|
||||
|
||||
bool atGoal ( PathSearchNode * endNode ) const;
|
||||
|
||||
// ----------
|
||||
|
||||
friend class PathSearchNode;
|
||||
|
||||
PathGraph const * m_graph;
|
||||
PathNode const * m_start;
|
||||
|
||||
PathNode const * m_goal;
|
||||
|
||||
bool m_multiGoal;
|
||||
NodeList * m_goals;
|
||||
|
||||
PathSearchQueue * m_queue;
|
||||
|
||||
IndexList * m_path;
|
||||
|
||||
NodeList * m_visitedNodes;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif // INCLUDED_PathSearch_H
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Pathfinding.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/Pathfinding.h"
|
||||
|
||||
#include "sharedCollision/Floor.h"
|
||||
#include "sharedCollision/FloorMesh.h"
|
||||
#include "sharedCollision/FloorManager.h"
|
||||
|
||||
#include "sharedFile/Iff.h"
|
||||
|
||||
#include "sharedObject/CellProperty.h"
|
||||
|
||||
#include "sharedPathfinding/PathSearch.h"
|
||||
#include "sharedPathfinding/SimplePathGraph.h"
|
||||
|
||||
const Tag TAG_PGRF = TAG(P,G,R,F);
|
||||
const Tag TAG_PNOD = TAG(P,N,O,D);
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void Pathfinding::install ( void )
|
||||
{
|
||||
FloorManager::setPathGraphFactory( &Pathfinding::graphFactory );
|
||||
FloorManager::setPathGraphWriter( &Pathfinding::graphWriter );
|
||||
FloorManager::setPathGraphRenderer( &Pathfinding::graphRenderer );
|
||||
|
||||
PathSearch::install();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void Pathfinding::remove ( void )
|
||||
{
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
BaseClass * Pathfinding::graphFactory ( Iff & iff )
|
||||
{
|
||||
if(iff.getCurrentName() == TAG_PGRF)
|
||||
{
|
||||
SimplePathGraph * graph = new SimplePathGraph();
|
||||
|
||||
graph->read(iff);
|
||||
|
||||
graph->setPartTags();
|
||||
|
||||
return graph;
|
||||
}
|
||||
else if(iff.getCurrentName() == TAG_PNOD)
|
||||
{
|
||||
// This is an old IFF, the path information isn't in a PGRF form.
|
||||
|
||||
SimplePathGraph * graph = new SimplePathGraph();
|
||||
|
||||
graph->read_old(iff);
|
||||
|
||||
graph->setPartTags();
|
||||
|
||||
return graph;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARNING(true,("Pathfinding::graphFactory - Don't know how to construct a path graph from the IFF in %s\n",iff.getFileName()));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void Pathfinding::graphWriter ( BaseClass const * baseGraph, Iff & iff )
|
||||
{
|
||||
SimplePathGraph const * graph = safe_cast<SimplePathGraph const *>(baseGraph);
|
||||
|
||||
graph->write(iff);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void Pathfinding::graphRenderer ( BaseClass const * baseGraph, DebugShapeRenderer * renderer )
|
||||
{
|
||||
PathGraph const * graph = safe_cast<PathGraph const *>(baseGraph);
|
||||
|
||||
graph->drawDebugShapes(renderer);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,36 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Pathfinding.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_Pathfinding_H
|
||||
#define INCLUDED_Pathfinding_H
|
||||
|
||||
class CellProperty;
|
||||
class BaseClass;
|
||||
class Iff;
|
||||
class DebugShapeRenderer;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class Pathfinding
|
||||
{
|
||||
public:
|
||||
|
||||
static void install ( void );
|
||||
static void remove ( void );
|
||||
|
||||
static void setupCell ( CellProperty const * newCell );
|
||||
|
||||
static BaseClass * graphFactory ( Iff & iff );
|
||||
static void graphWriter ( BaseClass const * baseGraph, Iff & iff );
|
||||
static void graphRenderer ( BaseClass const * baseGraph, DebugShapeRenderer * renderer );
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathfindingEnums.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PathfindingEnums_H
|
||||
#define INCLUDED_PathfindingEnums_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
enum PathGraphType
|
||||
{
|
||||
PGT_Cell,
|
||||
PGT_Building,
|
||||
PGT_City,
|
||||
|
||||
PGT_None,
|
||||
};
|
||||
|
||||
// ----------
|
||||
|
||||
enum PathNodeType
|
||||
{
|
||||
// node types for cell graphs
|
||||
|
||||
PNT_CellPortal = 0,
|
||||
PNT_CellWaypoint = 1,
|
||||
PNT_CellPOI = 2,
|
||||
|
||||
// node types for building graphs
|
||||
|
||||
PNT_BuildingEntrance = 3,
|
||||
PNT_BuildingCell = 4,
|
||||
PNT_BuildingPortal = 5,
|
||||
|
||||
// node types for city graphs
|
||||
|
||||
PNT_CityBuildingEntrance = 6,
|
||||
PNT_CityWaypoint = 7,
|
||||
PNT_CityPOI = 8,
|
||||
PNT_CityBuilding = 9,
|
||||
PNT_CityEntrance = 10, // the city gates, in a sense
|
||||
|
||||
// new node type to represent one contiguous piece of a cell
|
||||
|
||||
PNT_BuildingCellPart = 11,
|
||||
|
||||
PNT_Invalid = 12,
|
||||
};
|
||||
|
||||
// ----------
|
||||
|
||||
enum PathBuildResult
|
||||
{
|
||||
PBR_OK,
|
||||
PBR_Unreachable,
|
||||
PBR_Incomplete,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedPathfinding.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/SetupSharedPathfinding.h"
|
||||
|
||||
#include "sharedDebug/InstallTimer.h"
|
||||
#include "sharedCollision/FloorMesh.h"
|
||||
#include "sharedObject/PortalPropertyTemplate.h"
|
||||
#include "sharedPathfinding/ConfigSharedPathfinding.h"
|
||||
#include "sharedPathfinding/PathEdge.h"
|
||||
#include "sharedPathfinding/Pathfinding.h"
|
||||
#include "sharedPathfinding/PathNode.h"
|
||||
#include "sharedPathfinding/SimplePathGraph.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
typedef BaseClass * (*ExpandBuildingGraphHook)( PortalPropertyTemplate * portalTemplate, BaseClass * baseBuildingGraph );
|
||||
|
||||
BaseClass * expandBuildingGraph ( PortalPropertyTemplate * portalTemplate, BaseClass * baseBuildingGraph );
|
||||
|
||||
void SetupSharedPathfinding::install ( void )
|
||||
{
|
||||
InstallTimer const installTimer("SetupSharedPathfinding::install");
|
||||
|
||||
ConfigSharedPathfinding::install();
|
||||
Pathfinding::install();
|
||||
|
||||
PortalPropertyTemplate::setExpandBuildingGraphHook(expandBuildingGraph);
|
||||
}
|
||||
|
||||
void SetupSharedPathfinding::remove ( void )
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int findNeighbor ( PathNode * node, PathNodeType neighborType, int neighborKey )
|
||||
{
|
||||
int nodeIndex = node->getIndex();
|
||||
|
||||
PathGraph * graph = node->getGraph();
|
||||
|
||||
int neighborCount = graph->getEdgeCount(nodeIndex);
|
||||
|
||||
for(int i = 0; i < neighborCount; i++)
|
||||
{
|
||||
PathNode * neighbor = graph->getNeighbor(nodeIndex,i);
|
||||
|
||||
if((neighbor->getType() == neighborType) && (neighbor->getKey() == neighborKey))
|
||||
{
|
||||
return neighbor->getIndex();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Expand the building graph by creating BuildingCellPart nodes for all
|
||||
// parts of the cell graph in each cell
|
||||
|
||||
BaseClass * expandBuildingGraph ( PortalPropertyTemplate * portalTemplate, BaseClass * baseBuildingGraph )
|
||||
{
|
||||
if(baseBuildingGraph == NULL) return NULL;
|
||||
|
||||
SimplePathGraph * buildingGraph = safe_cast<SimplePathGraph*>(baseBuildingGraph);
|
||||
|
||||
SimplePathGraph::NodeList * newBuildingNodes = new SimplePathGraph::NodeList( buildingGraph->getNodes() );
|
||||
SimplePathGraph::EdgeList * newBuildingEdges = new SimplePathGraph::EdgeList( buildingGraph->getEdges() );
|
||||
|
||||
// ----------
|
||||
|
||||
int buildingNodeCount = buildingGraph->getNodeCount();
|
||||
|
||||
for(int iBuildingNode = 0; iBuildingNode < buildingNodeCount; iBuildingNode++)
|
||||
{
|
||||
PathNode * buildingCellNode = buildingGraph->getNode(iBuildingNode);
|
||||
|
||||
if(buildingCellNode->getType() != PNT_BuildingCell) continue;
|
||||
|
||||
// ----------
|
||||
|
||||
int cellIndex = buildingCellNode->getKey();
|
||||
|
||||
PortalPropertyTemplateCell const * cell = &portalTemplate->getCell(cellIndex);
|
||||
|
||||
FloorMesh const * floorMesh = cell->getFloorMesh();
|
||||
|
||||
if(floorMesh == NULL) continue;
|
||||
|
||||
PathGraph const * cellGraph = safe_cast<PathGraph const *>(floorMesh->getPathGraph());
|
||||
|
||||
if(cellGraph == NULL) continue;
|
||||
|
||||
// ----------
|
||||
|
||||
int cellPartCount = cellGraph->getPartCount();
|
||||
|
||||
for(int i = 0; i < cellPartCount; i++)
|
||||
{
|
||||
int partNodeIndex = newBuildingNodes->size();
|
||||
|
||||
newBuildingNodes->resize(newBuildingNodes->size() + 1);
|
||||
|
||||
PathNode & partNode = newBuildingNodes->back();
|
||||
|
||||
partNode.setType(PNT_BuildingCellPart);
|
||||
partNode.setPosition_p(buildingCellNode->getPosition_p());
|
||||
partNode.setKey(buildingCellNode->getKey());
|
||||
partNode.setId(i);
|
||||
|
||||
// ----------
|
||||
// search through the nodes in the cell graph, add the indices of all
|
||||
// portals that have a portal node in this part of the graph to our
|
||||
// portal id set
|
||||
|
||||
typedef std::set<int> IntSet;
|
||||
|
||||
IntSet portalIds;
|
||||
|
||||
for(int j = 0; j < cellGraph->getNodeCount(); j++)
|
||||
{
|
||||
PathNode const * cellNode = cellGraph->getNode(j);
|
||||
|
||||
NOT_NULL(cellNode);
|
||||
|
||||
if((cellNode->getPartId() == i) && (cellNode->getType() == PNT_CellPortal))
|
||||
{
|
||||
portalIds.insert(cellNode->getKey());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
// for each portal ID in the set, find the neighboring BuildingPortal node
|
||||
// of the BuildingCell node that corresponds with that ID, and add path
|
||||
// edges for it
|
||||
|
||||
for(IntSet::iterator it = portalIds.begin(); it != portalIds.end(); ++it)
|
||||
{
|
||||
int portalId = *it;
|
||||
|
||||
int portalNodeIndex = findNeighbor(buildingCellNode,PNT_BuildingPortal,portalId);
|
||||
|
||||
if(portalNodeIndex == -1) portalNodeIndex = findNeighbor(buildingCellNode,PNT_BuildingEntrance,portalId);
|
||||
|
||||
if(portalNodeIndex != -1)
|
||||
{
|
||||
newBuildingEdges->push_back( PathEdge(partNodeIndex,portalNodeIndex) );
|
||||
newBuildingEdges->push_back( PathEdge(portalNodeIndex,partNodeIndex) );
|
||||
}
|
||||
}
|
||||
|
||||
// and add a link from the building cell node to the building cell part node
|
||||
|
||||
newBuildingEdges->push_back( PathEdge(iBuildingNode,partNodeIndex) );
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
SimplePathGraph * newBuildingGraph = new SimplePathGraph ( newBuildingNodes, newBuildingEdges );
|
||||
|
||||
newBuildingGraph->setType(PGT_Building);
|
||||
|
||||
return newBuildingGraph;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedPathfinding.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_SetupSharedPathfinding_H
|
||||
#define INCLUDED_SetupSharedPathfinding_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class SetupSharedPathfinding
|
||||
{
|
||||
public:
|
||||
|
||||
static void install ( void );
|
||||
static void remove ( void );
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,579 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PathGraph.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
#include "sharedPathfinding/SimplePathGraph.h"
|
||||
|
||||
#include "sharedCollision/ConfigSharedCollision.h"
|
||||
#include "sharedCollision/FloorMesh.h"
|
||||
#include "sharedCollision/FloorLocator.h"
|
||||
|
||||
#include "sharedFile/Iff.h"
|
||||
|
||||
#include "sharedMath/DebugShapeRenderer.h"
|
||||
#include "sharedMath/Sphere.h"
|
||||
|
||||
#include "sharedPathfinding/PathNode.h"
|
||||
#include "sharedPathfinding/PathEdge.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
const Tag TAG_PGRF = TAG(P,G,R,F);
|
||||
const Tag TAG_PNOD = TAG(P,N,O,D);
|
||||
const Tag TAG_PEDG = TAG(P,E,D,G);
|
||||
const Tag TAG_ECNT = TAG(E,C,N,T);
|
||||
const Tag TAG_ESTR = TAG(E,S,T,R);
|
||||
const Tag TAG_META = TAG(M,E,T,A);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
void readArray_Class ( Iff & iff, T * & array, Tag tag )
|
||||
{
|
||||
iff.enterChunk(tag);
|
||||
{
|
||||
int count = iff.read_int32();
|
||||
|
||||
if(array == NULL) array = new T();
|
||||
|
||||
array->resize(count);
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
array->at(i).read(iff);
|
||||
}
|
||||
}
|
||||
iff.exitChunk(tag);
|
||||
}
|
||||
|
||||
template<class T, class Reader>
|
||||
void readArray_Class ( Iff & iff, T * & array, Tag tag, Reader R )
|
||||
{
|
||||
iff.enterChunk(tag);
|
||||
{
|
||||
int count = iff.read_int32();
|
||||
|
||||
if(array == NULL) array = new T();
|
||||
|
||||
array->resize(count);
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
(array->at(i).*R)(iff);
|
||||
}
|
||||
}
|
||||
iff.exitChunk(tag);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void readArray_Struct ( Iff & iff, T * & array, Tag tag )
|
||||
{
|
||||
iff.enterChunk(tag);
|
||||
{
|
||||
int count = iff.read_int32();
|
||||
|
||||
if(array == NULL) array = new T();
|
||||
|
||||
array->resize(count);
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
// bleh. hacky.
|
||||
|
||||
uint8 * bytes = reinterpret_cast<uint8*>(&array->at(i));
|
||||
|
||||
iff.read_uint8( sizeof(typename T::value_type), bytes );
|
||||
}
|
||||
}
|
||||
iff.exitChunk(tag);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
void writeArray_Class ( Iff & iff, T * array, Tag tag )
|
||||
{
|
||||
iff.insertChunk(tag);
|
||||
{
|
||||
int count = array->size();
|
||||
|
||||
iff.insertChunkData(count);
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
array->at(i).write(iff);
|
||||
}
|
||||
}
|
||||
iff.exitChunk(tag);
|
||||
}
|
||||
|
||||
template<class T, class Writer>
|
||||
void writeArray_Class ( Iff & iff, T * array, Tag tag, Writer W )
|
||||
{
|
||||
iff.insertChunk(tag);
|
||||
{
|
||||
int count = array->size();
|
||||
|
||||
iff.insertChunkData(count);
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
(array->at(i).*W)(iff);
|
||||
}
|
||||
}
|
||||
iff.exitChunk(tag);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void writeArray_Struct ( Iff & iff, T * array, Tag tag )
|
||||
{
|
||||
iff.insertChunk(tag);
|
||||
{
|
||||
int count = array->size();
|
||||
|
||||
iff.insertChunkData(count);
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
iff.insertChunkData( array->at(i) );
|
||||
}
|
||||
}
|
||||
iff.exitChunk(tag);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
SimplePathGraph::SimplePathGraph ( PathGraphType type )
|
||||
: PathGraph( type ),
|
||||
m_nodes( new SimplePathGraph::NodeList() ),
|
||||
m_edges( new SimplePathGraph::EdgeList() ),
|
||||
m_edgeCounts( new IndexList() ),
|
||||
m_edgeStarts( new IndexList() )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
m_debugLines = NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
SimplePathGraph::SimplePathGraph( SimplePathGraph::NodeList * nodes, SimplePathGraph::EdgeList * edges, PathGraphType type )
|
||||
: PathGraph( type ),
|
||||
m_nodes( nodes ),
|
||||
m_edges( edges ),
|
||||
m_edgeCounts( new IndexList() ),
|
||||
m_edgeStarts( new IndexList() )
|
||||
{
|
||||
int nodeCount = nodes->size();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
nodes->at(i).setGraph(this);
|
||||
nodes->at(i).setIndex(i);
|
||||
}
|
||||
|
||||
buildIndexTables();
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
m_debugLines = NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
SimplePathGraph::~SimplePathGraph()
|
||||
{
|
||||
delete m_nodes;
|
||||
m_nodes = NULL;
|
||||
|
||||
delete m_edges;
|
||||
m_edges = NULL;
|
||||
|
||||
delete m_edgeCounts;
|
||||
m_edgeCounts = NULL;
|
||||
|
||||
delete m_edgeStarts;
|
||||
m_edgeStarts = NULL;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
delete m_debugLines;
|
||||
m_debugLines = NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void SimplePathGraph::clear ( void )
|
||||
{
|
||||
m_nodes->clear();
|
||||
m_edges->clear();
|
||||
m_edgeCounts->clear();
|
||||
m_edgeStarts->clear();
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(m_debugLines) m_debugLines->clear();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SimplePathGraph::buildIndexTables ( void )
|
||||
{
|
||||
std::sort( m_edges->begin(), m_edges->end() );
|
||||
|
||||
m_edgeCounts->clear();
|
||||
m_edgeStarts->clear();
|
||||
|
||||
m_edgeCounts->resize(m_nodes->size(),0);
|
||||
m_edgeStarts->resize(m_nodes->size(),-1);
|
||||
|
||||
int edgeCount = m_edges->size();
|
||||
|
||||
int i;
|
||||
|
||||
for(i = 0; i < edgeCount; i++)
|
||||
{
|
||||
int node = m_edges->at(i).getIndexA();
|
||||
|
||||
m_edgeCounts->at(node)++;
|
||||
|
||||
if(m_edgeStarts->at(node) == -1)
|
||||
{
|
||||
m_edgeStarts->at(node) = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int SimplePathGraph::getNodeCount ( void ) const
|
||||
{
|
||||
return m_nodes->size();
|
||||
}
|
||||
|
||||
PathNode * SimplePathGraph::getNode ( int nodeIndex )
|
||||
{
|
||||
if (static_cast<unsigned int>(nodeIndex) < m_nodes->size())
|
||||
return &m_nodes->at(nodeIndex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PathNode const * SimplePathGraph::getNode ( int nodeIndex ) const
|
||||
{
|
||||
if (static_cast<unsigned int>(nodeIndex) < m_nodes->size())
|
||||
return &m_nodes->at(nodeIndex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int SimplePathGraph::getEdgeCount ( int nodeIndex ) const
|
||||
{
|
||||
return m_edgeCounts->at(nodeIndex);
|
||||
}
|
||||
|
||||
PathEdge * SimplePathGraph::getEdge ( int nodeIndex, int edgeIndex )
|
||||
{
|
||||
return &m_edges->at( m_edgeStarts->at(nodeIndex) + edgeIndex );
|
||||
}
|
||||
|
||||
PathEdge const * SimplePathGraph::getEdge ( int nodeIndex, int edgeIndex ) const
|
||||
{
|
||||
return &m_edges->at( m_edgeStarts->at(nodeIndex) + edgeIndex );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SimplePathGraph::read ( Iff & iff )
|
||||
{
|
||||
clear();
|
||||
|
||||
// ----------
|
||||
|
||||
iff.enterForm(TAG_PGRF);
|
||||
|
||||
switch (iff.getCurrentName())
|
||||
{
|
||||
case TAG_0000:
|
||||
m_version = 0;
|
||||
read_0000(iff);
|
||||
break;
|
||||
|
||||
case TAG_0001:
|
||||
m_version = 1;
|
||||
read_0001(iff);
|
||||
break;
|
||||
|
||||
default:
|
||||
FATAL(true,("SimplePathGraph::read - Invalid version"));
|
||||
break;
|
||||
}
|
||||
|
||||
iff.exitForm(TAG_PGRF);
|
||||
|
||||
// ----------
|
||||
// Looks like the graph type isn't getting saved out. Patch it up at runtime
|
||||
|
||||
if(getNodeCount() > 0)
|
||||
{
|
||||
PathNode const * node = getNode(0);
|
||||
|
||||
PathNodeType type = node->getType();
|
||||
|
||||
if(type == PNT_CellPortal || type == PNT_CellWaypoint || type == PNT_CellPOI)
|
||||
{
|
||||
setType(PGT_Cell);
|
||||
}
|
||||
else if(type == PNT_BuildingEntrance || type == PNT_BuildingCell || type == PNT_BuildingPortal || type == PNT_BuildingCellPart)
|
||||
{
|
||||
setType(PGT_Building);
|
||||
}
|
||||
else if(type == PNT_CityBuildingEntrance || type == PNT_CityWaypoint || type == PNT_CityPOI || type == PNT_CityBuilding || type == PNT_CityEntrance)
|
||||
{
|
||||
setType(PGT_City);
|
||||
}
|
||||
else
|
||||
{
|
||||
setType(PGT_None);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
int nodeCount = m_nodes->size();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
m_nodes->at(i).setGraph(this);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(ConfigSharedCollision::getBuildDebugData())
|
||||
{
|
||||
buildDebugData();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Version 4 floor meshes stored path information in an array of floor
|
||||
// locators and an array of int pairs.
|
||||
|
||||
void SimplePathGraph::read_old ( Iff & iff )
|
||||
{
|
||||
clear();
|
||||
|
||||
// ----------
|
||||
|
||||
iff.enterChunk(TAG_PNOD);
|
||||
{
|
||||
FloorLocator loc;
|
||||
|
||||
while(iff.getChunkLengthLeft())
|
||||
{
|
||||
loc.read_0000(iff);
|
||||
|
||||
m_nodes->push_back( PathNode(loc.getPosition_p()) );
|
||||
}
|
||||
}
|
||||
iff.exitChunk(TAG_PNOD);
|
||||
|
||||
iff.enterChunk(TAG_PEDG);
|
||||
{
|
||||
while(iff.getChunkLengthLeft())
|
||||
{
|
||||
int a = iff.read_int32();
|
||||
int b = iff.read_int32();
|
||||
|
||||
m_edges->push_back( PathEdge(a,b) );
|
||||
m_edges->push_back( PathEdge(b,a) );
|
||||
}
|
||||
}
|
||||
iff.exitChunk(TAG_PEDG);
|
||||
|
||||
// ----------
|
||||
|
||||
buildIndexTables();
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(ConfigSharedCollision::getBuildDebugData())
|
||||
{
|
||||
buildDebugData();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SimplePathGraph::read_0000 ( Iff & iff )
|
||||
{
|
||||
iff.enterForm(TAG_0000);
|
||||
|
||||
// ----------
|
||||
|
||||
readArray_Class( iff, m_nodes, TAG_PNOD, &PathNode::read_0000 );
|
||||
|
||||
readArray_Class( iff, m_edges, TAG_PEDG, &PathEdge::read_0000 );
|
||||
|
||||
readArray_Struct( iff, m_edgeCounts, TAG_ECNT );
|
||||
|
||||
readArray_Struct( iff, m_edgeStarts, TAG_ESTR );
|
||||
|
||||
// ----------
|
||||
|
||||
iff.exitForm(TAG_0000);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void SimplePathGraph::read_0001 ( Iff & iff )
|
||||
{
|
||||
iff.enterForm(TAG_0001);
|
||||
|
||||
// ----------
|
||||
|
||||
iff.enterChunk(TAG_META);
|
||||
{
|
||||
setType( static_cast<PathGraphType>(iff.read_int32()) );
|
||||
}
|
||||
iff.exitChunk(TAG_META);
|
||||
|
||||
readArray_Class( iff, m_nodes, TAG_PNOD, &PathNode::read_0000 );
|
||||
|
||||
readArray_Class( iff, m_edges, TAG_PEDG, &PathEdge::read_0000 );
|
||||
|
||||
readArray_Struct( iff, m_edgeCounts, TAG_ECNT );
|
||||
|
||||
readArray_Struct( iff, m_edgeStarts, TAG_ESTR );
|
||||
|
||||
// ----------
|
||||
|
||||
iff.exitForm(TAG_0001);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
void SimplePathGraph::write ( Iff & iff ) const
|
||||
{
|
||||
iff.insertForm(TAG_PGRF);
|
||||
|
||||
iff.insertForm(TAG_0001);
|
||||
|
||||
// ----------
|
||||
|
||||
iff.insertChunk(TAG_META);
|
||||
{
|
||||
iff.insertChunkData( static_cast<int>(getType()) );
|
||||
}
|
||||
iff.exitChunk(TAG_META);
|
||||
|
||||
writeArray_Class( iff, m_nodes, TAG_PNOD );
|
||||
|
||||
writeArray_Class( iff, m_edges, TAG_PEDG );
|
||||
|
||||
writeArray_Struct( iff, m_edgeCounts, TAG_ECNT );
|
||||
|
||||
writeArray_Struct( iff, m_edgeStarts, TAG_ESTR );
|
||||
|
||||
// ----------
|
||||
|
||||
iff.exitForm(TAG_0001);
|
||||
|
||||
iff.exitForm(TAG_PGRF);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SimplePathGraph::drawDebugShapes ( DebugShapeRenderer * renderer ) const
|
||||
{
|
||||
UNREF(renderer);
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(renderer == NULL) return;
|
||||
|
||||
if( m_debugLines ) renderer->drawLineList( *m_debugLines, VectorArgb::solidYellow );
|
||||
|
||||
int nodeCount = getNodeCount();
|
||||
|
||||
for(int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
PathNode const * node = getNode(i);
|
||||
|
||||
// if(node->isPortalAdjacent())
|
||||
// {
|
||||
// renderer->setColor( VectorArgb::solidMagenta );
|
||||
// }
|
||||
// else
|
||||
{
|
||||
renderer->setColor( VectorArgb::solidCyan );
|
||||
}
|
||||
|
||||
Vector center = node->getPosition_p() + Vector(0.0f,0.5f,0.0f);
|
||||
|
||||
renderer->drawSphere( Sphere(center,0.2f) );
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
SimplePathGraph::NodeList const & SimplePathGraph::getNodes ( void ) const
|
||||
{
|
||||
return *m_nodes;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
SimplePathGraph::EdgeList const & SimplePathGraph::getEdges ( void ) const
|
||||
{
|
||||
return *m_edges;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
void SimplePathGraph::buildDebugData ( void )
|
||||
{
|
||||
m_debugLines = new VectorList();
|
||||
|
||||
int edgeCount = m_edges->size();
|
||||
|
||||
m_debugLines->reserve(edgeCount*2);
|
||||
|
||||
for(int i = 0; i < edgeCount; i++)
|
||||
{
|
||||
PathEdge const & edge = m_edges->at(i);
|
||||
|
||||
int A = edge.getIndexA();
|
||||
int B = edge.getIndexB();
|
||||
|
||||
Vector a = getNode(A)->getPosition_p();
|
||||
Vector b = getNode(B)->getPosition_p();
|
||||
|
||||
m_debugLines->push_back( a + Vector(0.0f,0.7f,0.0f) );
|
||||
m_debugLines->push_back( b + Vector(0.0f,0.3f,0.0f) );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SimplePathGraph.h
|
||||
// Copyright 2001 Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_SimplePathGraph_H
|
||||
#define INCLUDED_SimplePathGraph_H
|
||||
|
||||
#include "sharedPathfinding/PathGraph.h"
|
||||
|
||||
#include "sharedMath/Vector.h"
|
||||
|
||||
class FloorLocator;
|
||||
|
||||
typedef std::pair<int,int> IndexPair;
|
||||
typedef stdvector<int>::fwd IntList;
|
||||
typedef stdvector<Vector>::fwd VectorList;
|
||||
typedef stdvector<IndexPair>::fwd IndexPairList;
|
||||
typedef stdvector<FloorLocator>::fwd FloorLocatorList;
|
||||
|
||||
// ======================================================================
|
||||
// Very simple concrete path graph class, uses base PathEdge and PathNode
|
||||
// classes and stores them in a vector.
|
||||
|
||||
class SimplePathGraph : public PathGraph
|
||||
{
|
||||
public:
|
||||
|
||||
typedef stdvector<PathEdge>::fwd EdgeList;
|
||||
typedef stdvector<PathNode>::fwd NodeList;
|
||||
|
||||
SimplePathGraph ( PathGraphType type = PGT_None );
|
||||
|
||||
SimplePathGraph ( NodeList * nodes, EdgeList * edges, PathGraphType type = PGT_None );
|
||||
|
||||
virtual ~SimplePathGraph();
|
||||
|
||||
// ----------
|
||||
|
||||
void clear ( void );
|
||||
|
||||
// ----------
|
||||
// PathGraph interface
|
||||
|
||||
virtual int getNodeCount ( void ) const;
|
||||
virtual PathNode * getNode ( int nodeIndex );
|
||||
virtual PathNode const * getNode ( int nodeIndex ) const;
|
||||
|
||||
virtual int getEdgeCount ( int nodeIndex ) const;
|
||||
virtual PathEdge * getEdge ( int nodeIndex, int edgeIndex );
|
||||
virtual PathEdge const * getEdge ( int nodeIndex, int edgeIndex ) const;
|
||||
|
||||
virtual void read ( Iff & iff );
|
||||
virtual void write ( Iff & iff ) const;
|
||||
|
||||
virtual void drawDebugShapes ( DebugShapeRenderer * renderer ) const;
|
||||
|
||||
// ----------
|
||||
// SimplePathGraph interface
|
||||
|
||||
virtual NodeList const & getNodes ( void ) const;
|
||||
virtual EdgeList const & getEdges ( void ) const;
|
||||
|
||||
// ----------
|
||||
|
||||
int getVersion ( void ) const;
|
||||
|
||||
void read_old ( Iff & iff );
|
||||
|
||||
protected:
|
||||
|
||||
void buildIndexTables ( void );
|
||||
|
||||
void read_0000 ( Iff & iff );
|
||||
void read_0001 ( Iff & iff );
|
||||
|
||||
// ----------
|
||||
|
||||
int m_version;
|
||||
|
||||
NodeList * m_nodes;
|
||||
EdgeList * m_edges;
|
||||
IndexList * m_edgeCounts;
|
||||
IndexList * m_edgeStarts;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
void buildDebugData ( void );
|
||||
|
||||
VectorList * m_debugLines;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
// ----------
|
||||
|
||||
inline int SimplePathGraph::getVersion ( void ) const
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstSharedPathfinding.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedPathfinding/FirstSharedPathfinding.h"
|
||||
@@ -130,6 +130,7 @@ include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedObject/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSynchronization/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
|
||||
)
|
||||
|
||||
@@ -111,9 +111,19 @@ endif()
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shared
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMathArchive/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedXml/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
|
||||
)
|
||||
|
||||
add_library(sharedUtility STATIC
|
||||
|
||||
@@ -205,7 +205,7 @@ void CachedFileManager::preloadSomeAssets ()
|
||||
if (possibleExtension)
|
||||
{
|
||||
ConstCharCrcString const extension (possibleExtension + 1);
|
||||
ExtensionMap::iterator iter = ms_extensionMap.find (&extension);
|
||||
ExtensionMap::iterator iter = ms_extensionMap.find ((const CrcString*)&extension);
|
||||
if (iter == ms_extensionMap.end ())
|
||||
{
|
||||
CachedFileInfo * const info = new CachedFileInfo (extension.getString ());
|
||||
|
||||
@@ -281,7 +281,7 @@ void InteriorLayoutReaderWriter::addObject(char const * const cellName, char con
|
||||
{
|
||||
Node * node = 0;
|
||||
TemporaryCrcString const cellNameCrcString(cellName, true);
|
||||
NodeMap::iterator iter = m_nodeMap->find(&cellNameCrcString);
|
||||
NodeMap::iterator iter = m_nodeMap->find((const CrcString*)&cellNameCrcString);
|
||||
if (iter != m_nodeMap->end())
|
||||
node = iter->second;
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user