13#include "DetourCommon.h"
14#include "DetourNavMeshQuery.h"
50 G3D::Vector3 dest(destX, destY, destZ);
53 G3D::Vector3 start(x, y, z);
78 if (!polyPath || !polyPathSize)
82 float minDist2d = FLT_MAX;
83 float minDist3d = 0.0f;
85 for (
uint32 i = 0; i < polyPathSize; ++i)
88 if (dtStatusFailed(
_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)))
91 float d = dtVdist2DSqr(point, closestPoint);
95 nearestPoly = polyPath[i];
96 minDist3d = dtVdistSqr(point, closestPoint);
104 *distance = dtSqrt(minDist3d);
122 float closestPoint[
VERTEX_SIZE] = { 0.0f, 0.0f, 0.0f };
125 *distance = dtVdist(closestPoint, point);
136 *distance = dtVdist(closestPoint, point);
147 float distToStartPoly, distToEndPoly;
148 float startPoint[
VERTEX_SIZE] = { startPos.y, startPos.z, startPos.x };
149 float endPoint[
VERTEX_SIZE] = { endPos.y, endPos.z, endPos.x };
159 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n");
184 bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f);
187 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly);
189 bool buildShotrcut =
false;
194 G3D::Vector3
const& p = (distToStartPoly > 7.0f) ? startPos : endPos;
195 if (
_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z))
197 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: underWater case\n");
199 buildShotrcut =
true;
203 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: flying case\n");
205 buildShotrcut =
true;
219 if (dtStatusSucceed(
_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)))
221 dtVcopy(endPoint, closestPoint);
232 if (startPoly == endPoly)
234 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: (startPoly == endPoly)\n");
248 bool startPolyFound =
false;
249 bool endPolyFound =
false;
250 uint32 pathStartIndex = 0;
255 for (; pathStartIndex <
_polyLength; ++pathStartIndex)
262 startPolyFound =
true;
267 for (pathEndIndex =
_polyLength - 1; pathEndIndex > pathStartIndex; --pathEndIndex)
275 if (startPolyFound && endPolyFound)
277 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: (startPolyFound && endPolyFound)\n");
286 else if (startPolyFound && !endPolyFound)
288 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n");
305 dtPolyRef suffixStartPoly =
_pathPolyRefs[prefixPolyLength - 1];
309 if (dtStatusFailed(
_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)))
315 if (dtStatusFailed(
_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)))
325 uint32 suffixPolyLength = 0;
333 (
int*)&suffixPolyLength,
336 if (!suffixPolyLength || dtStatusFailed(dtResult))
344 SF_LOG_DEBUG(
"maps",
"++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",
_polyLength, prefixPolyLength, suffixPolyLength);
347 _polyLength = prefixPolyLength + suffixPolyLength - 1;
351 SF_LOG_DEBUG(
"maps",
"++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n");
394 dtStatus dtResult = DT_FAILURE;
420 if (pointCount < 2 || dtStatusFailed(dtResult))
425 SF_LOG_DEBUG(
"maps",
"++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount);
432 SF_LOG_DEBUG(
"maps",
"++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount,
_pointPathLimit);
439 for (
uint32 i = 0; i < pointCount; ++i)
473 float ground = map->
GetHeight(phase, x, y, z + 5.0f,
true);
474 float floor = map->
GetHeight(phase, x, y, z,
true);
477 z = fabs(ground - z) <= fabs(floor - z) ? ground : floor;
515 G3D::Vector3
const& prev = densified.back();
517 float const dx = next.x - prev.x;
518 float const dy = next.y - prev.y;
519 float const dist2d = sqrt(dx * dx + dy * dy);
524 for (
uint32 s = 1; s < steps; ++s)
526 float const t = float(s) / float(steps);
527 float x = prev.x + dx * t;
528 float y = prev.y + dy * t;
529 float z = prev.z + (next.z - prev.z) * t;
550 SF_LOG_DEBUG(
"maps",
"++ BuildShortcut :: making shortcut\n");
587 _filter.setIncludeFlags(includeFlags);
588 _filter.setExcludeFlags(excludeFlags);
604 _filter.setIncludeFlags(includedFlags);
631 int tx = -1, ty = -1;
634 _navMesh->calcTileLoc(point, &tx, &ty);
639 if (tx < 0 || ty < 0)
642 return (
_navMesh->getTileAt(tx, ty, 0) != NULL);
647 int32 furthestPath = -1;
648 int32 furthestVisited = -1;
651 for (
int32 i = npath - 1; i >= 0; --i)
654 for (
int32 j = nvisited - 1; j >= 0; --j)
656 if (path[i] == visited[j])
668 if (furthestPath == -1 || furthestVisited == -1)
674 uint32 req = nvisited - furthestVisited;
675 uint32 orig =
uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath;
676 uint32 size = npath > orig ? npath - orig : 0;
677 if (req + size > maxPath)
678 size = maxPath - req;
681 memmove(path + req, path + orig, size *
sizeof(dtPolyRef));
684 for (
uint32 i = 0; i < req; ++i)
685 path[i] = visited[(nvisited - 1) - i];
691 float minTargetDist, dtPolyRef
const* path,
uint32 pathSize,
692 float* steerPos,
unsigned char& steerPosFlag, dtPolyRef& steerPosRef)
695 static const uint32 MAX_STEER_POINTS = 3;
697 unsigned char steerPathFlags[MAX_STEER_POINTS];
698 dtPolyRef steerPathPolys[MAX_STEER_POINTS];
700 dtStatus dtResult =
_navMeshQuery->findStraightPath(startPos, endPos, path, pathSize,
701 steerPath, steerPathFlags, steerPathPolys, (
int*)&nsteerPath, MAX_STEER_POINTS);
702 if (!nsteerPath || dtStatusFailed(dtResult))
707 while (ns < nsteerPath)
710 if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
716 if (ns >= nsteerPath)
720 steerPos[1] = startPos[1];
721 steerPosFlag = steerPathFlags[ns];
722 steerPosRef = steerPathPolys[ns];
728 dtPolyRef
const* polyPath,
uint32 polyPathSize,
729 float* smoothPath,
int* smoothPathSize,
uint32 maxSmoothPathSize)
735 memcpy(polys, polyPath,
sizeof(dtPolyRef) * polyPathSize);
736 uint32 npolys = polyPathSize;
739 if (dtStatusFailed(
_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)))
742 if (dtStatusFailed(
_navMeshQuery->closestPointOnPolyBoundary(polys[npolys - 1], endPos, targetPos)))
745 dtVcopy(&smoothPath[nsmoothPath *
VERTEX_SIZE], iterPos);
750 while (npolys && nsmoothPath < maxSmoothPathSize)
754 unsigned char steerPosFlag;
760 bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END);
761 bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION);
765 dtVsub(delta, steerPos, iterPos);
766 float len = dtSqrt(dtVdot(delta, delta));
774 dtVmad(moveTgt, iterPos, delta, len);
778 const static uint32 MAX_VISIT_POLY = 16;
779 dtPolyRef visited[MAX_VISIT_POLY];
782 _navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &
_filter, result, visited, (
int*)&nvisited, MAX_VISIT_POLY);
787 dtVcopy(iterPos, result);
793 dtVcopy(iterPos, targetPos);
794 if (nsmoothPath < maxSmoothPathSize)
796 dtVcopy(&smoothPath[nsmoothPath *
VERTEX_SIZE], iterPos);
805 dtPolyRef polyRef = polys[0];
807 while (npos < npolys && polyRef != steerPosRef)
810 polyRef = polys[npos];
814 for (
uint32 i = npos; i < npolys; ++i)
815 polys[i - npos] = polys[i];
821 if (dtStatusSucceed(
_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)))
823 if (nsmoothPath < maxSmoothPathSize)
825 dtVcopy(&smoothPath[nsmoothPath *
VERTEX_SIZE], startPos);
829 dtVcopy(iterPos, endPos);
830 _navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]);
836 if (nsmoothPath < maxSmoothPathSize)
838 dtVcopy(&smoothPath[nsmoothPath *
VERTEX_SIZE], iterPos);
843 *smoothPathSize = nsmoothPath;
851 const float dx = v2[0] - v1[0];
852 const float dy = v2[1] - v1[1];
853 const float dz = v2[2] - v1[2];
854 return (dx * dx + dz * dz) < r * r && fabsf(dy) < h;
859 G3D::Vector3 d = p1 - p2;
860 return (d.x * d.x + d.y * d.y) < r * r && fabsf(d.z) < h;
865 return (p1 - p2).squaredLength();
#define SF_LOG_DEBUG(filterType__,...)
#define SF_LOG_ERROR(filterType__,...)
#define MAP_LIQUID_TYPE_MAGMA
#define MAP_LIQUID_TYPE_WATER
#define MAP_LIQUID_TYPE_OCEAN
#define MAP_LIQUID_TYPE_SLIME
#define SMOOTH_PATH_STEP_SIZE
#define MAX_POINT_PATH_LENGTH
@ PATHFIND_NOT_USING_PATH
@ UNIT_STATE_IGNORE_PATHFINDING
bool CanFly() const OVERRIDE
CreatureTemplate const * GetCreatureTemplate() const
static MMapManager * createOrGetMMapManager()
static bool IsPathfindingEnabled(uint32 mapId)
dtNavMeshQuery const * GetNavMeshQuery(uint32 mapId, uint32 instanceId, TerrainSet swaps)
dtNavMesh const * GetNavMesh(uint32 mapId, TerrainSet swaps)
float GetHeight(float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const
PathGenerator(Unit const *owner)
bool HaveTile(G3D::Vector3 const &p) const
void SetActualEndPosition(G3D::Vector3 const &point)
G3D::Vector3 const & GetStartPosition() const
float Dist3DSqr(G3D::Vector3 const &p1, G3D::Vector3 const &p2) const
dtStatus FindSmoothPath(float const *startPos, float const *endPos, dtPolyRef const *polyPath, uint32 polyPathSize, float *smoothPath, int *smoothPathSize, uint32 smoothPathMaxSize)
Unit const *const _sourceUnit
dtNavMeshQuery const * _navMeshQuery
G3D::Vector3 const & GetEndPosition() const
dtPolyRef GetPolyByLocation(float const *Point, float *Distance) const
void BuildPolyPath(G3D::Vector3 const &startPos, G3D::Vector3 const &endPos)
bool InRangeYZX(float const *v1, float const *v2, float r, float h) const
void SetStartPosition(G3D::Vector3 const &point)
uint32 FixupCorridor(dtPolyRef *path, uint32 npath, uint32 maxPath, dtPolyRef const *visited, uint32 nvisited)
dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]
Movement::PointsArray _pathPoints
bool InRange(G3D::Vector3 const &p1, G3D::Vector3 const &p2, float r, float h) const
NavTerrain GetNavTerrain(float x, float y, float z)
void BuildPointPath(float const *startPoint, float const *endPoint)
dtNavMesh const * _navMesh
dtPolyRef GetPathPolyByPosition(dtPolyRef const *polyPath, uint32 polyPathSize, float const *Point, float *Distance=NULL) const
bool CalculatePath(float destX, float destY, float destZ, bool forceDest=false)
bool GetSteerTarget(float const *startPos, float const *endPos, float minTargetDist, dtPolyRef const *path, uint32 pathSize, float *steerPos, unsigned char &steerPosFlag, dtPolyRef &steerPosRef)
void SetEndPosition(G3D::Vector3 const &point)
G3D::Vector3 const & GetActualEndPosition() const
static float ResolveTerrainZ(Unit const *unit, float x, float y, float z)
G3D::Vector3 _endPosition
uint32 GetPhaseMask() const
void UpdateAllowedPositionZ(float x, float y, float &z) const
Map const * GetBaseMap() const
std::vector< Vector3 > PointsArray
bool IsValidMapCoord(float c)