Reuse vectors in the short-range pathfinder, making SplitAAEdges much faster and reducing memory fragmentation substantially. Refs #3588

This was SVN commit r18349.
This commit is contained in:
wraitii 2016-06-09 17:38:59 +00:00
parent 91e4ac58e3
commit 01603708de
2 changed files with 74 additions and 20 deletions

View file

@ -72,6 +72,49 @@ struct AsyncShortPathRequest
entity_id_t notify;
};
// A vertex around the corners of an obstruction
// (paths will be sequences of these vertexes)
struct Vertex
{
enum
{
UNEXPLORED,
OPEN,
CLOSED,
};
CFixedVector2D p;
fixed g, h;
u16 pred;
u8 status;
u8 quadInward : 4; // the quadrant which is inside the shape (or NONE)
u8 quadOutward : 4; // the quadrants of the next point on the path which this vertex must be in, given 'pred'
};
// Obstruction edges (paths will not cross any of these).
// Defines the two points of the edge.
struct Edge
{
CFixedVector2D p0, p1;
};
// Axis-aligned obstruction squares (paths will not cross any of these).
// Defines the opposing corners of an axis-aligned square
// (from which four individual edges can be trivially computed), requiring p0 <= p1
struct Square
{
CFixedVector2D p0, p1;
};
// Axis-aligned obstruction edges.
// p0 defines one end; c1 is either the X or Y coordinate of the other end,
// depending on the context in which this is used.
struct EdgeAA
{
CFixedVector2D p0;
fixed c1;
};
/**
* Implementation of ICmpPathfinder
*/
@ -122,6 +165,21 @@ public:
u16 m_MaxSameTurnMoves; // max number of moves that can be created and processed in the same turn
// memory optimizations: those vectors are created once, reused for all calculations;
std::vector<Edge> edgesUnaligned;
std::vector<EdgeAA> edgesLeft;
std::vector<EdgeAA> edgesRight;
std::vector<EdgeAA> edgesBottom;
std::vector<EdgeAA> edgesTop;
// List of obstruction vertexes (plus start/end points); we'll try to find paths through
// the graph defined by these vertexes
std::vector<Vertex> vertexes;
// List of collision edges - paths must never cross these.
// (Edges are one-sided so intersections are fine in one direction, but not the other direction.)
std::vector<Edge> edges;
std::vector<Square> edgeSquares; // axis-aligned squares; equivalent to 4 edges
bool m_DebugOverlay;
std::vector<SOverlayLine> m_DebugOverlayShortPathLines;
AtlasOverlay* m_AtlasOverlay;

View file

@ -362,12 +362,12 @@ static void AddTerrainEdges(std::vector<Edge>& edges, std::vector<Vertex>& verte
}
// XXX rewrite this stuff
std::vector<u16> segmentsR;
std::vector<u16> segmentsL;
for (int j = j0; j < j1; ++j)
{
std::vector<u16> segmentsR;
std::vector<u16> segmentsL;
segmentsR.clear();
segmentsL.clear();
for (int i = i0; i <= i1; ++i)
{
bool a = IS_PASSABLE(grid.get(i, j+1), passClass);
@ -420,12 +420,12 @@ static void AddTerrainEdges(std::vector<Edge>& edges, std::vector<Vertex>& verte
}
}
}
std::vector<u16> segmentsU;
std::vector<u16> segmentsD;
for (int i = i0; i < i1; ++i)
{
std::vector<u16> segmentsU;
std::vector<u16> segmentsD;
segmentsU.clear();
segmentsD.clear();
for (int j = j0; j <= j1; ++j)
{
bool a = IS_PASSABLE(grid.get(i+1, j), passClass);
@ -487,10 +487,6 @@ static void SplitAAEdges(const CFixedVector2D& a,
std::vector<EdgeAA>& edgesLeft, std::vector<EdgeAA>& edgesRight,
std::vector<EdgeAA>& edgesBottom, std::vector<EdgeAA>& edgesTop)
{
edgesLeft.reserve(squares.size());
edgesRight.reserve(squares.size());
edgesBottom.reserve(squares.size());
edgesTop.reserve(squares.size());
for (const Square& square : squares)
{
@ -594,8 +590,8 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter,
// List of collision edges - paths must never cross these.
// (Edges are one-sided so intersections are fine in one direction, but not the other direction.)
std::vector<Edge> edges;
std::vector<Square> edgeSquares; // axis-aligned squares; equivalent to 4 edges
edges.clear();
edgeSquares.clear(); // axis-aligned squares; equivalent to 4 edges
// Create impassable edges at the max-range boundary, so we can't escape the region
// where we're meant to be searching
@ -609,7 +605,7 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter,
// List of obstruction vertexes (plus start/end points); we'll try to find paths through
// the graph defined by these vertexes
std::vector<Vertex> vertexes;
vertexes.clear();
// Add the start point to the graph
CFixedVector2D posStart(x0, z0);
@ -833,11 +829,11 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter,
if (edgeSquares.size() > 8)
std::partial_sort(edgeSquares.begin(), edgeSquares.begin() + 8, edgeSquares.end(), SquareSort(vertexes[curr.id].p));
std::vector<Edge> edgesUnaligned;
std::vector<EdgeAA> edgesLeft;
std::vector<EdgeAA> edgesRight;
std::vector<EdgeAA> edgesBottom;
std::vector<EdgeAA> edgesTop;
edgesUnaligned.clear();
edgesLeft.clear();
edgesRight.clear();
edgesBottom.clear();
edgesTop.clear();
SplitAAEdges(vertexes[curr.id].p, edges, edgeSquares, edgesUnaligned, edgesLeft, edgesRight, edgesBottom, edgesTop);
// Check the lines to every other vertex