Added sharedPathfinding library

This commit is contained in:
Anonymous
2014-01-14 12:04:45 -07:00
parent 41eaddd9ba
commit dfa993e0d4
50 changed files with 3874 additions and 2 deletions
+1
View File
@@ -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
)
@@ -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)
@@ -0,0 +1 @@
#include "../../src/shared/ConfigSharedPathfinding.h"
@@ -0,0 +1 @@
#include "../../src/shared/DynamicPathGraph.h"
@@ -0,0 +1 @@
#include "../../src/shared/DynamicPathNode.h"
@@ -0,0 +1 @@
#include "../../src/shared/FirstSharedPathfinding.h"
@@ -0,0 +1 @@
#include "../../src/shared/PathEdge.h"
@@ -0,0 +1 @@
#include "../../src/shared/PathGraph.h"
@@ -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"
@@ -0,0 +1 @@
#include "../../src/shared/PathfindingEnums.h"
@@ -0,0 +1 @@
#include "../../src/shared/SetupSharedPathfinding.h"
@@ -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