add pathfinding library

This commit is contained in:
MihailRis 2025-08-02 17:18:40 +03:00
parent 958fc1d689
commit caab689731
6 changed files with 126 additions and 2 deletions

View File

@ -27,6 +27,7 @@
#include "voxels/Block.hpp"
#include "voxels/Chunk.hpp"
#include "voxels/Chunks.hpp"
#include "voxels/Pathfinding.hpp"
#include "window/Window.hpp"
#include "world/Level.hpp"
#include "world/LevelEvents.hpp"
@ -386,6 +387,36 @@ void WorldRenderer::renderFrame(
skybox->draw(ctx, camera, assets, worldInfo.daytime, clouds);
// In-world lines
for (const auto& [_, agent] : level.pathfinding->getAgents()) {
const auto& route = agent.route;
if (!route.found)
continue;
for (int i = 1; i < route.nodes.size(); i++) {
const auto& a = route.nodes.at(i - 1);
const auto& b = route.nodes.at(i);
if (i == 1) {
lines->pushLine(
glm::vec3(a.pos) + glm::vec3(0.5f),
glm::vec3(a.pos) + glm::vec3(0.5f, 1.0f, 0.5f),
glm::vec4(1, 1, 1, 1)
);
}
lines->pushLine(
glm::vec3(a.pos) + glm::vec3(0.5f),
glm::vec3(b.pos) + glm::vec3(0.5f),
glm::vec4(1, 0, 1, 1)
);
lines->pushLine(
glm::vec3(b.pos) + glm::vec3(0.5f),
glm::vec3(b.pos) + glm::vec3(0.5f, 1.0f, 0.5f),
glm::vec4(1, 1, 1, 1)
);
}
}
linesShader.use();
linesShader.uniformMatrix("u_projview", camera.getProjView());
lines->draw(*lineBatch);

View File

@ -38,6 +38,7 @@ extern const luaL_Reg mat4lib[];
extern const luaL_Reg networklib[];
extern const luaL_Reg packlib[];
extern const luaL_Reg particleslib[]; // gfx.particles
extern const luaL_Reg pathfindinglib[];
extern const luaL_Reg playerlib[];
extern const luaL_Reg posteffectslib[]; // gfx.posteffects
extern const luaL_Reg quatlib[];

View File

@ -0,0 +1,55 @@
#include "api_lua.hpp"
#include "voxels/Pathfinding.hpp"
#include "world/Level.hpp"
using namespace scripting;
static voxels::Agent* get_agent(lua::State* L) {
return level->pathfinding->getAgent(lua::tointeger(L, 1));
}
static int l_create_agent(lua::State* L) {
return lua::pushinteger(L, level->pathfinding->createAgent());
}
static int l_set_enabled(lua::State* L) {
if (auto agent = get_agent(L)) {
agent->enabled = lua::toboolean(L, 2);
}
return 0;
}
static int l_is_enabled(lua::State* L) {
if (auto agent = get_agent(L)) {
return lua::pushboolean(L, agent->enabled);
}
return lua::pushboolean(L, false);
}
static int l_make_route(lua::State* L) {
if (auto agent = get_agent(L)) {
auto start = lua::tovec3(L, 2);
auto target = lua::tovec3(L, 3);
auto route = level->pathfinding->perform(*agent, start, target);
agent->route = route;
if (!route.found) {
return 0;
}
lua::createtable(L, route.nodes.size(), 0);
for (int i = 0; i < route.nodes.size(); i++) {
lua::pushvec3(L, route.nodes[i].pos);
lua::rawseti(L, i + 1);
}
return 1;
}
return 0;
}
const luaL_Reg pathfindinglib[] = {
{"create_agent", lua::wrap<l_create_agent>},
{"set_enabled", lua::wrap<l_set_enabled>},
{"is_enabled", lua::wrap<l_is_enabled>},
{"make_route", lua::wrap<l_make_route>},
{NULL, NULL}
};

View File

@ -72,6 +72,7 @@ static void create_libs(State* L, StateType stateType) {
openlib(L, "input", inputlib);
openlib(L, "inventory", inventorylib);
openlib(L, "network", networklib);
openlib(L, "pathfinding", pathfindinglib);
openlib(L, "player", playerlib);
openlib(L, "time", timelib);
openlib(L, "world", worldlib);

View File

@ -75,6 +75,12 @@ static void restore_route(
}
}
int Pathfinding::createAgent() {
int id = nextAgent++;
agents[id] = Agent();
return id;
}
Route Pathfinding::perform(
const Agent& agent, const glm::ivec3& start, const glm::ivec3& end
) {
@ -89,12 +95,16 @@ Route Pathfinding::perform(
std::unordered_map<glm::ivec3, Node> parents;
const auto& chunks = *level.chunks;
int height = std::max(agent.height, 1);
while (!queue.empty()) {
if (blocked.size() == agent.maxVisitedBlocks) {
break;
}
auto node = queue.top();
queue.pop();
if (node.pos.x == end.x && glm::abs((node.pos.y - end.y) / agent.height) == 0 && node.pos.z == end.z) {
if (node.pos.x == end.x && glm::abs((node.pos.y - end.y) / height) == 0 && node.pos.z == end.z) {
restore_route(route, node, parents);
route.nodes.push_back({start});
route.found = true;
@ -144,6 +154,18 @@ Route Pathfinding::perform(
return route;
}
Agent* Pathfinding::getAgent(int id) {
const auto& found = agents.find(id);
if (found != agents.end()) {
return &found->second;
}
return nullptr;
}
const std::unordered_map<int, Agent>& Pathfinding::getAgents() const {
return agents;
}
static int check_point(
const ContentUnitIndices<Block>& defs,
const GlobalChunks& chunks,

View File

@ -4,6 +4,7 @@
#include <memory>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <unordered_map>
class Level;
class GlobalChunks;
@ -19,7 +20,12 @@ namespace voxels {
};
struct Agent {
int height;
bool enabled = false;
int height = 1;
int maxVisitedBlocks = 1e5;
glm::ivec3 start;
glm::ivec3 target;
Route route;
};
struct Map {
@ -46,12 +52,20 @@ namespace voxels {
public:
Pathfinding(const Level& level);
int createAgent();
Route perform(
const Agent& agent, const glm::ivec3& start, const glm::ivec3& end
);
Agent* getAgent(int id);
const std::unordered_map<int, Agent>& getAgents() const;
private:
const Level& level;
const GlobalChunks& chunks;
std::unordered_map<int, Agent> agents;
int nextAgent = 1;
int getSurfaceAt(const glm::ivec3& pos, int maxDelta);
};