#pragma once #include "render/Renderer.h" #include #include #include namespace ZL { class PathFinder { public: struct ObstacleMesh { const VertexDataStruct* mesh = nullptr; Eigen::Vector3f offset = Eigen::Vector3f::Zero(); }; struct Cell { int x = 0; int z = 0; }; struct NavigationArea { std::string name; bool available = true; std::vector polygon; }; void build(const std::vector& obstacleMeshes, const std::string& configPath, const std::string& zipPath = ""); std::vector findPath(const Eigen::Vector3f& start, const Eigen::Vector3f& end) const; bool setAreaAvailable(const std::string& areaName, bool available); bool isReady() const { return ready; } bool isWalkable(const Eigen::Vector3f& point) const; const std::vector& getAreas() const { return areas; } float getFloorY() const { return floorY; } private: float cellSize = 0.4f; float agentRadius = 0.45f; float floorY = 0.0f; float objectPadding = 0.25f; float minX = 0.0f; float minZ = 0.0f; int gridWidth = 0; int gridDepth = 0; bool ready = false; std::string loadedConfigPath; std::string loadedZipPath; std::vector obstacles; std::vector walkable; std::vector areas; void loadConfig(const std::string& configPath, const std::string& zipPath); void resetGridBounds(); void rebuildWalkableGrid(); void markAvailableAreasWalkable(); void markObstacleMeshesBlocked(); bool worldToCell(const Eigen::Vector3f& point, Cell& out) const; Eigen::Vector3f cellCenter(const Cell& cell) const; bool isInsideGrid(const Cell& cell) const; bool isCellWalkable(const Cell& cell) const; int indexOf(const Cell& cell) const; bool findNearestWalkableCell(const Eigen::Vector3f& point, Cell& out) const; bool hasLineOfSight(const Cell& from, const Cell& to) const; std::vector smoothCells(const std::vector& cells) const; static bool pointInPolygon(float x, float z, const std::vector& polygon); }; } // namespace ZL