void PathGenerator::ReducePathLenghtByDist(float dist) { if (GetPathType() == PATHFIND_BLANK) { TC_LOG_ERROR("maps", "PathGenerator::ReducePathLenghtByDist called before path was built"); return; } if (_pathPoints.size() < 2) // path building failure return; uint32 i = _pathPoints.size(); G3D::Vector3 nextVec = _pathPoints[--i]; while (i > 0) { G3D::Vector3 currVec = _pathPoints[--i]; G3D::Vector3 diffVec = (nextVec - currVec); float len = diffVec.length(); if (len > dist) { float step = dist / len; // same as nextVec _pathPoints[i + 1] -= diffVec * step; _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i + 1].x, _pathPoints[i + 1].y, _pathPoints[i + 1].z); _pathPoints.resize(i + 2); break; } else if (i == 0) // at second point { _pathPoints[1] = _pathPoints[0]; _pathPoints.resize(2); break; } dist -= len; nextVec = currVec; // we're going backwards } }
void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; if (_straightLine) { dtResult = DT_SUCCESS; pointCount = 1; memcpy(&pathPoints[VERTEX_SIZE * 0], startPoint, sizeof(float)* 3); // first point // path has to be split into polygons with dist SMOOTH_PATH_STEP_SIZE between them G3D::Vector3 startVec = G3D::Vector3(startPoint[0], startPoint[1], startPoint[2]); G3D::Vector3 endVec = G3D::Vector3(endPoint[0], endPoint[1], endPoint[2]); G3D::Vector3 diffVec = (endVec - startVec); G3D::Vector3 prevVec = startVec; float len = diffVec.length(); diffVec *= SMOOTH_PATH_STEP_SIZE / len; while (len > SMOOTH_PATH_STEP_SIZE) { len -= SMOOTH_PATH_STEP_SIZE; prevVec += diffVec; pathPoints[VERTEX_SIZE * pointCount + 0] = prevVec.x; pathPoints[VERTEX_SIZE * pointCount + 1] = prevVec.y; pathPoints[VERTEX_SIZE * pointCount + 2] = prevVec.z; ++pointCount; } memcpy(&pathPoints[VERTEX_SIZE * pointCount], endPoint, sizeof(float)* 3); // last point ++pointCount; } else if (_useStraightPath) { dtResult = _navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position _pathPolyRefs, // current path _polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, _pointPathLimit); // maximum number of points/polygons to use } else { dtResult = FindSmoothPath( startPoint, // start position endPoint, // end position _pathPolyRefs, // current path _polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, _pointPathLimit); // maximum number of points } if (pointCount < 2 || dtStatusFailed(dtResult)) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here /// @todo check the exact cases TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); _type = PATHFIND_NOPATH; return; } else if (pointCount == _pointPathLimit) { TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, _pointPathLimit); BuildShortcut(); _type = PATHFIND_SHORT; return; } _pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) _pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); NormalizePath(); // first point is always our current location - we need the next one SetActualEndPosition(_pathPoints[pointCount-1]); // force the given destination, if needed if (_forceDestination && (!(_type & PATHFIND_NORMAL) || !InRange(GetEndPosition(), GetActualEndPosition(), 1.0f, 1.0f))) { // we may want to keep partial subpath if (Dist3DSqr(GetActualEndPosition(), GetEndPosition()) < 0.3f * Dist3DSqr(GetStartPosition(), GetEndPosition())) { SetActualEndPosition(GetEndPosition()); _pathPoints[_pathPoints.size()-1] = GetEndPosition(); } else { SetActualEndPosition(GetEndPosition()); BuildShortcut(); } _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", _type, pointCount, _polyLength); }