diff options
author | Thanasis Antoniou | 2019-03-09 23:15:18 +0200 |
---|---|---|
committer | Thanasis Antoniou | 2019-03-09 23:17:09 +0200 |
commit | c60c0c967651422a4d2027c3b7c156bfcfc548d3 (patch) | |
tree | 07b387a47554cb4eb070fd8e134c2105266dbfff | |
parent | 05dcd7ff2316caffe54d97ec3677512678dd8733 (diff) | |
download | scummvm-rg350-c60c0c967651422a4d2027c3b7c156bfcfc548d3.tar.gz scummvm-rg350-c60c0c967651422a4d2027c3b7c156bfcfc548d3.tar.bz2 scummvm-rg350-c60c0c967651422a4d2027c3b7c156bfcfc548d3.zip |
BLADERUNNER: Alternate fix method for rare path finding assert faults
Disabled by default. This one allows polygons merged on a single point.
-rw-r--r-- | engines/bladerunner/obstacles.cpp | 54 | ||||
-rw-r--r-- | engines/bladerunner/obstacles.h | 4 |
2 files changed, 38 insertions, 20 deletions
diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp index 66f3f73382..1886de324d 100644 --- a/engines/bladerunner/obstacles.cpp +++ b/engines/bladerunner/obstacles.cpp @@ -33,6 +33,7 @@ #include "common/debug.h" #define DISABLE_PATHFINDING 0 +#define USE_PATHFINDING_EXPERIMENTAL_FIX_2 0 // Alternate Fix: Allows polygons merged on one point #define WITHIN_TOLERANCE(a, b) (((a) - 0.009) < (b) && ((a) + 0.009) > (b)) @@ -107,7 +108,7 @@ bool Obstacles::lineLineIntersection(LineSegment a, LineSegment b, Vector2 *inte return false; } -bool Obstacles::linePolygonIntersection(LineSegment lineA, VertexType lineAType, Polygon *polyB, Vector2 *intersectionPoint, int *intersectionIndex) { +bool Obstacles::linePolygonIntersection(LineSegment lineA, VertexType lineAType, Polygon *polyB, Vector2 *intersectionPoint, int *intersectionIndex, int pathLengthSinceLastIntersection) { bool hasIntersection = false; float nearestIntersectionDistance = 0.0f; @@ -126,15 +127,15 @@ bool Obstacles::linePolygonIntersection(LineSegment lineA, VertexType lineAType, || (lineAType == BOTTOM_LEFT && lineBType == BOTTOM_RIGHT) || (lineAType == TOP_LEFT && lineBType == BOTTOM_LEFT) ) { - if (!(WITHIN_TOLERANCE(lineB.end.x, intersectionPoint->x) && WITHIN_TOLERANCE(lineB.end.y, intersectionPoint->y))) { - if (newIntersectionPoint != *intersectionPoint) { - float newIntersectionDistance = getLength(lineA.start.x, lineA.start.y, newIntersectionPoint.x, newIntersectionPoint.y); - if (!hasIntersection || newIntersectionDistance < nearestIntersectionDistance) { - hasIntersection = true; - nearestIntersectionDistance = newIntersectionDistance; - *intersectionPoint = newIntersectionPoint; - *intersectionIndex = i; - } + if ( (pathLengthSinceLastIntersection > 2) + || ( (!(WITHIN_TOLERANCE(lineB.end.x, intersectionPoint->x) && WITHIN_TOLERANCE(lineB.end.y, intersectionPoint->y))) + && (newIntersectionPoint != *intersectionPoint) )) { + float newIntersectionDistance = getLength(lineA.start.x, lineA.start.y, newIntersectionPoint.x, newIntersectionPoint.y); + if (!hasIntersection || newIntersectionDistance < nearestIntersectionDistance) { + hasIntersection = true; + nearestIntersectionDistance = newIntersectionDistance; + *intersectionPoint = newIntersectionPoint; + *intersectionIndex = i; } } } @@ -191,6 +192,7 @@ bool Obstacles::mergePolygons(Polygon &polyA, Polygon &polyB) { bool flagAddVertexToVertexList = true; bool flagDidFindIntersection = false; int vertIndex = 0; + int pathLengthSinceLastIntersection = 0; // Part of pathfinding fix 2. It's only updated when enabling that fix, otherwise it is always zero (0). Polygon *startingPolygon = polyPrimary; int flagDone = false; @@ -204,12 +206,16 @@ bool Obstacles::mergePolygons(Polygon &polyA, Polygon &polyB) { polyPrimaryType = polyPrimary->vertexType[vertIndex]; if (flagAddVertexToVertexList) { - // In some cases polygons will have only one intersection (touching corners) and because of that second SWAP never occure, +#if USE_PATHFINDING_EXPERIMENTAL_FIX_2 + assert(polyMerged.verticeCount < kPolygonVertexCount); +#else + // In some cases polygons will have only one intersection (touching corners) and because of that second SWAP never occurs, // algorithm will stop only when the merged polygon is full. if (polyMerged.verticeCount >= kPolygonVertexCount) { flagDidMergePolygons = false; break; } +#endif polyMerged.vertices[polyMerged.verticeCount] = polyLine.start; polyMerged.vertexType[polyMerged.verticeCount] = polyPrimaryType; polyMerged.verticeCount++; @@ -218,7 +224,7 @@ bool Obstacles::mergePolygons(Polygon &polyA, Polygon &polyB) { flagAddVertexToVertexList = true; int polySecondaryIntersectionIndex = -1; - if (linePolygonIntersection(polyLine, polyPrimaryType, polySecondary, &intersectionPoint, &polySecondaryIntersectionIndex)) { + if (linePolygonIntersection(polyLine, polyPrimaryType, polySecondary, &intersectionPoint, &polySecondaryIntersectionIndex, pathLengthSinceLastIntersection)) { if (WITHIN_TOLERANCE(intersectionPoint.x, polyLine.start.x) && WITHIN_TOLERANCE(intersectionPoint.y, polyLine.start.y)) { flagAddVertexToVertexList = false; polyMerged.verticeCount--; // TODO(madmoose): How would this work? @@ -231,8 +237,14 @@ bool Obstacles::mergePolygons(Polygon &polyA, Polygon &polyB) { SWAP(polyPrimary, polySecondary); flagDidMergePolygons = true; +#if USE_PATHFINDING_EXPERIMENTAL_FIX_2 + pathLengthSinceLastIntersection = 0; +#endif } else { vertIndex = (vertIndex + 1) % polyPrimary->verticeCount; +#if USE_PATHFINDING_EXPERIMENTAL_FIX_2 + pathLengthSinceLastIntersection++; +#endif flagDidFindIntersection = false; } if (polyPrimary->vertices[vertIndex] == startingPolygon->vertices[0]) { @@ -543,11 +555,13 @@ bool Obstacles::findPolygonVerticeByXZ(int *polygonIndex, int *verticeIndex, int return false; } -bool Obstacles::findPolygonVerticeByXZWithinTolerance(float x, float z, int *polygonIndex, int *verticeIndex) const { +bool Obstacles::findPolygonVerticeByXZWithinTolerance(float x, float z, int *polygonIndex, int *verticeIndex, int startSearchFromPolygonIdx) const { *polygonIndex = -1; *verticeIndex = -1; - for (int i = 0; i != kPolygonCount; ++i) { +// for (int i = 0; i != kPolygonCount; ++i) { + for (int countUp = 0, i = startSearchFromPolygonIdx; countUp != kPolygonCount; ++countUp, ++i) { + i = i % kPolygonCount; // we want to circle around to go through all polygons if (!_polygons[i].isPresent || _polygons[i].verticeCount == 0) { continue; } @@ -687,7 +701,7 @@ bool Obstacles::findFarthestAvailablePathVertex(Vector2 *path, int pathSize, Vec int vertexTypeStartPrev = -1; int polygonIndexStart = -1; int vertexIndexStart = -1; - bool startOnPolygon = findPolygonVerticeByXZWithinTolerance(start.x, start.z, &polygonIndexStart, &vertexIndexStart); + bool startOnPolygon = findPolygonVerticeByXZWithinTolerance(start.x, start.z, &polygonIndexStart, &vertexIndexStart, 0); if (startOnPolygon) { int vertexIndexStartPrev = (vertexIndexStart - 1 + _polygons[polygonIndexStart].verticeCount) % _polygons[polygonIndexStart].verticeCount; @@ -700,7 +714,7 @@ bool Obstacles::findFarthestAvailablePathVertex(Vector2 *path, int pathSize, Vec bool foundVertexNeighbor = false; int polygonIndexPath = -1; int vertexIndexPath = -1; - bool pathVertexOnPolygon = findPolygonVerticeByXZWithinTolerance(path[pathVertexIdx].x, path[pathVertexIdx].y, &polygonIndexPath, &vertexIndexPath) == 1; + bool pathVertexOnPolygon = findPolygonVerticeByXZWithinTolerance(path[pathVertexIdx].x, path[pathVertexIdx].y, &polygonIndexPath, &vertexIndexPath, 0) == 1; //start and current path vertices are on same polygon and are next to each other if (pathVertexOnPolygon && polygonIndexStart == polygonIndexPath) { @@ -748,8 +762,12 @@ bool Obstacles::findFarthestAvailablePathVertex(Vector2 *path, int pathSize, Vec int polygonIndexIntersection = -1; int vertexIndexIntersection = -1; - if (findPolygonVerticeByXZWithinTolerance(intersection.x, intersection.y, &polygonIndexIntersection, &vertexIndexIntersection)) { - // hntersection has to be vertex only on current polygon + if (findPolygonVerticeByXZWithinTolerance(intersection.x, intersection.y, &polygonIndexIntersection, &vertexIndexIntersection, currentPolygonIdx)) { + // Intersection has to be vertex only on current polygon + // Part of pathfinding fix 2 (dealing with merge on only one edge point) + // but also speeds up process: + // we start (a cyclical) searching in Polygons array + // beginning from the current polygon index assert(polygonIndexIntersection == currentPolygonIdx); if (verticesCanIntersect(vertexTypeStartPrev, vertexTypeStart, start.x, start.z, path[pathVertexIdx].x, path[pathVertexIdx].y)) { diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h index af17184393..9cec3d4f15 100644 --- a/engines/bladerunner/obstacles.h +++ b/engines/bladerunner/obstacles.h @@ -71,7 +71,7 @@ class Obstacles { bool _backup; static bool lineLineIntersection(LineSegment a, LineSegment b, Vector2 *intersectionPoint); - static bool linePolygonIntersection(LineSegment lineA, VertexType lineAType, Polygon *polyB, Vector2 *intersectionPoint, int *intersectionIndex); + static bool linePolygonIntersection(LineSegment lineA, VertexType lineAType, Polygon *polyB, Vector2 *intersectionPoint, int *intersectionIndex, int pathLengthSinceLastIntersection); bool mergePolygons(Polygon &polyA, Polygon &PolyB); @@ -93,7 +93,7 @@ public: float pathTotalDistance(const Vector2 *path, int pathSize, Vector2 from, Vector2 to) const; bool findPolygonVerticeByXZ(int *polygonIndex, int *verticeIndex, int *verticeCount, float x, float z) const; - bool findPolygonVerticeByXZWithinTolerance(float x, float z, int *polygonIndex, int *verticeIndex) const; + bool findPolygonVerticeByXZWithinTolerance(float x, float z, int *polygonIndex, int *verticeIndex, int startSearchFromPolygonIdx) const; void clearPath(); int buildNegativePath(int polyIndex, int vertStartIndex, Vector2 startPos, int vertEndIndex, Vector2 endPos, Vector2 *path, int pathCapacity, bool *pathBlocked); |