pathfinding

This commit is contained in:
det-fys 2023-12-29 20:03:34 +01:00
parent a4b77f420a
commit a168f51fbd
19 changed files with 496 additions and 49 deletions

View File

@ -1,6 +1,7 @@
g_require("scripts/thread.lua")
g_require("scripts/input.lua")
g_require("scripts/player.lua")
g_require("scripts/npc.lua")
print("autoexec")
@ -24,4 +25,8 @@ onkeypress["KEY_T"] = function ()
end
playercamera = not playercamera
end
end
for i = 1, 10 do
spawnnpc(1 + i, 1, 0, player)
end

View File

@ -64,6 +64,18 @@ function i_setcontrolcallback(callback) end
---@return number
function ent_spawn(x, y, z, pitch, yaw, roll, sx, sy, sz) end
---@param ent1 number
---@param ent2 number
---@return number
function ent_distance(ent1, ent2) end
---@param ent number
---@param x number
---@param y number
---@param z number
---@return number
function ent_distanceto(ent, x, y, z) end
--- Model
---@param ent number
@ -120,11 +132,10 @@ function cct_getforwardxz(ent) end
---@param ent number
---@param x number
---@param y number
---@param z number
---@param speed number
---@return nil
function cct_turnto(ent, x, y, z, speed) end
function cct_turnto(ent, x, z, speed) end
---@param ent number
---@param angle number
@ -137,4 +148,18 @@ function cct_turntoangle(ent, angle, speed) end
---@param y number
---@param z number
---@return nil
function cct_move(ent, x, y, z) end
function cct_move(ent, x, y, z) end
---@param ent number
---@param x number
---@param y number
---@param z number
---@return boolean
function cct_findpath(ent, x, y, z) end
---@param ent number
---@return boolean found
---@return number x
---@return number y
---@return number z
function cct_getnextpathnode(ent) end

71
main/scripts/npc.lua Normal file
View File

@ -0,0 +1,71 @@
g_require("scripts/thread.lua")
function spawnnpc(x, y, z, follow)
local npc = ent_spawn(x, y, z, 0, 0, 0, 1, 1, 1)
mdl_set(npc, "models/test_skeletal.mdl.json")
mdl_anim(npc, "init", 0, 0)
mdl_anim(npc, "stand", 0, 0)
cct_add(npc, 0.25, 1.2)
local tick = 1 / g_gettps()
local function disttonode(ent, node_x, node_z)
local _, ent_y, _ = cct_getpos(ent)
return ent_distanceto(ent, node_x, ent_y, node_z)
end
thread(function ()
while true do
wait(1)
if ent_distance(npc, follow) > 10 then
local follow_x, follow_y, follow_z = cct_getpos(follow)
local path_found = cct_findpath(npc, follow_x, follow_y, follow_z)
print("path found: ", path_found)
if path_found then
mdl_anim(npc, "walk2", 6, 0.2)
local walk = true
while walk do
local next_node, node_x, node_y, node_z = cct_getnextpathnode(npc)
print("nextnode: ", next_node, node_x, node_y, node_z)
if not next_node then
break
end
while disttonode(npc, node_x, node_z) > 1 do
if ent_distance(npc, follow) < 5 then
walk = false
break
end
cct_turnto(npc, node_x, node_z, 3)
local move_x = 0
local move_y = -3.0
local move_z = 0
move_x, move_z = cct_getforwardxz(npc)
cct_move(npc, move_x * tick * 3, move_y * tick * 3, move_z * tick * 3)
local new_x, new_y, new_z = cct_getpos(npc)
local dist = ent_distanceto(npc, new_x, new_y, new_z)
-- blocked
if dist < tick * 0.2 then
walk = false
break
end
wait(0)
end
end
mdl_stopanim(npc, "walk2", 0.1)
end
end
end
end)
end

View File

@ -31,7 +31,7 @@ function setupplayer(ent)
local move_y = -3.0
local move_z = 0
local movespeed = 3.0
local movespeed = 10.0
if fb ~= 0 or rl ~= 0 then
local foward_x, forward_z = g_getcameraforwardxz()

View File

@ -3,7 +3,7 @@
using namespace TSR;
void TSR::Camera::UpdateVectors() {
void Camera::UpdateVectors() {
auto yaw_rad = glm::radians(yaw);
auto pitch_rad = glm::radians(pitch);
front_vector = glm::normalize(glm::vec3(cos(yaw_rad) * glm::cos(pitch_rad), glm::sin(pitch_rad), glm::sin(yaw_rad) * glm::cos(pitch_rad)));
@ -12,7 +12,7 @@ void TSR::Camera::UpdateVectors() {
up_vector = glm::normalize(glm::cross(right_vector, front_vector));
}
TSR::Camera::Camera(glm::vec3 i_position, float i_movement_speed, float i_mouse_sensitivity, float i_third_person_distance, float i_yaw, float i_pitch) :
Camera::Camera(glm::vec3 i_position, float i_movement_speed, float i_mouse_sensitivity, float i_third_person_distance, float i_yaw, float i_pitch) :
position(i_position),
movement_speed(i_movement_speed),
mouse_sensitivity(i_mouse_sensitivity),
@ -24,7 +24,7 @@ TSR::Camera::Camera(glm::vec3 i_position, float i_movement_speed, float i_mouse_
UpdateVectors();
}
glm::mat4 TSR::Camera::GetViewMatrix(bool firstperson) {
glm::mat4 Camera::GetViewMatrix(bool firstperson) {
float space = 0.3f;
auto dist = firstperson ? 0.0f : third_person_distance;
@ -48,7 +48,7 @@ glm::mat4 TSR::Camera::GetViewMatrix(bool firstperson) {
return glm::lookAt(position - front_vector * dist, position + front_vector, up_vector);
}
void TSR::Camera::ProcessMovement(Movement direction, float time) {
void Camera::ProcessMovement(Movement direction, float time) {
float diff = movement_speed * time;
switch (direction) {
case Movement::FORWARD:
@ -72,7 +72,7 @@ void TSR::Camera::ProcessMovement(Movement direction, float time) {
}
}
void TSR::Camera::ProcessMouse(float x_offset, float y_offset) {
void Camera::ProcessMouse(float x_offset, float y_offset) {
yaw += x_offset * mouse_sensitivity;
//pitch = std::min(89.0f, std::max(-89.0f, pitch + y_offset * mouse_sensitivity));
pitch = std::min(89.9f, std::max(-89.9f, pitch + y_offset * mouse_sensitivity));

View File

@ -30,4 +30,20 @@ void EntitySystem::RegisterLuaFunctions() {
LuaAPI::RegisterFunction("ent_despawn", [](entt::entity ent) {
EntitySystem::Despawn(ent);
});
LuaAPI::RegisterFunction("ent_distance", [](entt::entity ent, entt::entity other) {
auto& reg = Game::Registry();
auto& trans1 = reg.get<TransformComponent>(ent);
auto& trans2 = reg.get<TransformComponent>(other);
return glm::distance(trans1.trans.pos, trans2.trans.pos);
});
LuaAPI::RegisterFunction("ent_distanceto", [](entt::entity ent, float x, float y, float z) {
auto& reg = Game::Registry();
auto& trans1 = reg.get<TransformComponent>(ent);
glm::vec3 pos(x, y, z);
return glm::distance(trans1.trans.pos, pos);
});
}

View File

@ -58,9 +58,10 @@ static bool CCTTurnToAngle(CCTComponent& comp, float target, float speed) {
}
}
static bool CCTTurnTo(CCTComponent& comp, const glm::vec3& pos, float step) {
auto diff = pos - CCTGetPos(comp);
auto target = std::atan2(pos.x, pos.z);
static bool CCTTurnTo(CCTComponent& comp, const glm::vec2& pos, float step) {
auto self_pos = CCTGetPos(comp);
auto diff = pos - glm::vec2(self_pos.x, self_pos.z);
auto target = std::atan2(diff.x, diff.y);
return CCTTurnToAngle(comp, target, step);
}
@ -135,7 +136,7 @@ glm::vec3 CCTSystem::GetForward(entt::entity ent) {
return glm::vec3(std::sin(comp.angle), 0.0f, std::cos(comp.angle));
}
bool CCTSystem::TurnTo(entt::entity ent, const glm::vec3& pos, float speed) {
bool CCTSystem::TurnTo(entt::entity ent, const glm::vec2& pos, float speed) {
auto& reg = Game::Registry();
auto& comp = reg.get<CCTComponent>(ent);
@ -149,6 +150,30 @@ bool CCTSystem::TurnToAngle(entt::entity ent, float target, float speed) {
return CCTTurnToAngle(comp, target, speed);
}
bool CCTSystem::FindPath(entt::entity ent, const glm::vec3& end) {
auto& reg = Game::Registry();
auto& comp = reg.get<CCTComponent>(ent);
auto start = CCTGetPos(comp);
start.y += 0.5f;
return Game::Map().GetNodeGraph().FindPath(start, end, comp.path);
}
bool CCTSystem::GetNextPathNode(entt::entity ent, glm::vec3& node) {
auto& reg = Game::Registry();
auto& comp = reg.get<CCTComponent>(ent);
if (comp.path.empty())
return false;
node = comp.path.back();
comp.path.pop_back();
return true;
}
void CCTSystem::Update() {
auto& reg = Game::Registry();
@ -161,7 +186,26 @@ void CCTSystem::Update() {
}
void TSR::CCTSystem::RegisterLuaFunctions() {
void CCTSystem::DebugDraw(Renderer& renderer) {
auto& reg = Game::Registry();
auto v = reg.view<CCTComponent, TransformComponent>();
for (auto [ent, cct, trans] : v.each()) {
if (cct.path.empty())
return;
glm::vec3 start_pos = CCTGetPos(cct);
for (int i = cct.path.size() - 1; i > 0; --i) {
auto& node = cct.path[i];
renderer.AddDebugLine(start_pos, node, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f));
start_pos = node;
}
}
}
void CCTSystem::RegisterLuaFunctions() {
LuaAPI::RegisterFunction("cct_add", [](entt::entity ent, float radius, float height) {
CCTSystem::AddCCT(ent, radius, height);
});
@ -190,12 +234,24 @@ void TSR::CCTSystem::RegisterLuaFunctions() {
return std::make_tuple(forward.x, forward.z);
});
LuaAPI::RegisterFunction("cct_turnto", [](entt::entity ent, float x, float y, float z, float speed) {
auto pos = glm::vec3(x, y, z);
return CCTSystem::TurnTo(ent, pos, speed);
LuaAPI::RegisterFunction("cct_turnto", [](entt::entity ent, float x, float z, float speed) {
return CCTSystem::TurnTo(ent, glm::vec2(x, z), speed);
});
LuaAPI::RegisterFunction("cct_turntoangle", [](entt::entity ent, float angle, float speed) {
return CCTSystem::TurnToAngle(ent, angle, speed);
});
LuaAPI::RegisterFunction("cct_findpath", [](entt::entity ent, float x, float y, float z) {
auto pos = glm::vec3(x, y, z);
return CCTSystem::FindPath(ent, pos);
});
LuaAPI::RegisterFunction("cct_getnextpathnode", [](entt::entity ent) {
glm::vec3 node;
if (CCTSystem::GetNextPathNode(ent, node))
return std::make_tuple(true, node.x, node.y, node.z);
else
return std::make_tuple(false, 0.0f, 0.0f, 0.0f);
});
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "entity.hpp"
#include "paths.hpp"
namespace TSR {
@ -14,6 +15,8 @@ namespace TSR {
PxController* cct;
float angle;
std::vector<glm::vec3> path;
CCTComponent(float radius, float height, const glm::vec3& pos);
CCTComponent(const CCTComponent& other) = delete;
~CCTComponent();
@ -24,17 +27,22 @@ namespace TSR {
public:
static void AddCCT(entt::entity ent, float radius, float height);
static void RemoveCCT(entt::entity ent);
static int Move(entt::entity ent, const glm::vec3& disp, float dt);
static void SetPos(entt::entity ent, const glm::vec3& pos);
static glm::vec3 GetPos(entt::entity ent);
static glm::vec3 GetForward(entt::entity ent);
static bool TurnTo(entt::entity ent, const glm::vec3& pos, float step);
static bool TurnTo(entt::entity ent, const glm::vec2& pos, float step);
static bool TurnToAngle(entt::entity ent, float target, float step);
static bool FindPath(entt::entity ent, const glm::vec3& end);
static bool GetNextPathNode(entt::entity ent, glm::vec3& node);
static void Update();
static void DebugDraw(Renderer& renderer);
static void RegisterLuaFunctions();
};

View File

@ -25,6 +25,7 @@ float Game::s_frame_t = 0.0f;
int Game::s_tps = 50;
bool Game::s_debug_draw = false;
int Game::s_debug_mode = DEBUG_ALL;
static Camera cam;
@ -164,6 +165,19 @@ void Game::Run() {
s_physics_scene->EnableDebug(s_debug_draw);
break;
}
if (key != GLFW_KEY_F1 && Window::KeyDown(GLFW_KEY_F1)) {
switch (key) {
case GLFW_KEY_P:
s_debug_mode ^= DEBUG_PHYSICS;
break;
case GLFW_KEY_C:
s_debug_mode ^= DEBUG_CCT;
break;
}
}
}
if (action == GLFW_PRESS || action == GLFW_RELEASE)
@ -250,9 +264,15 @@ void Game::ClFrame(Renderer& renderer, float frame_t) {
ModelSystem::Render(renderer);
s_map->Draw(renderer);
if (s_debug_draw)
if (DebugEnabled(DEBUG_PHYSICS))
s_physics_scene->DrawDebug(renderer);
if (DebugEnabled(DEBUG_CCT))
CCTSystem::DebugDraw(renderer);
if (DebugEnabled(DEBUG_NODES))
s_map->GetNodeGraph().DebugDraw(renderer);
if (s_skybox_model)
s_skybox_model->Draw(renderer, nullptr);

View File

@ -19,6 +19,14 @@ namespace TSR {
LuaReference callback;
};
enum DebugMode : int {
DEBUG_NONE,
DEBUG_PHYSICS = 1 << 0,
DEBUG_CCT = 1 << 1,
DEBUG_NODES = 1 << 2,
DEBUG_ALL = DEBUG_PHYSICS | DEBUG_CCT | DEBUG_NODES
};
class Game {
static entt::registry s_registry;
@ -32,22 +40,24 @@ namespace TSR {
static int s_tps;
static bool s_debug_draw;
static int s_debug_mode;
static void StartGame(const std::string& map_name);
static void EndGame();
public:
static void Run();
static void SvFrame();
static void ClFrame(Renderer& renderer, float frame_t);
static entt::registry& Registry() { return s_registry; }
static PhysicsScene& Physics() { return *s_physics_scene; }
static const WorldMap& Map() { return *s_map; }
static uint64_t FrameNum() { return s_sv_frame; }
static float FrameT() { return s_frame_t; }
static int TPS() { return s_tps; }
static bool DebugEnabled(DebugMode mode) { return s_debug_draw && (s_debug_mode & mode); }
static void RegisterLuaFunctions();

138
src/tsr/paths.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "paths.hpp"
#include <queue>
using namespace TSR;
int NodeGraph::FindClosestNode(const glm::vec3& position) const {
float min_dist = std::numeric_limits<float>::max();
int min_node = -1;
for (int i = 0; i < m_nodes.size(); ++i) {
auto& node = m_nodes[i];
auto dist = glm::distance(node.position, position);
if (dist < min_dist) {
min_dist = dist;
min_node = i;
}
}
return min_node;
}
// This is a helper function to calculate the heuristic cost between two vectors
static float Heuristic(const glm::vec3& a, const glm::vec3& b) {
//return std::sqrt(std::pow(a.x - b.x, 2) + std::pow(a.y - b.y, 2) + std::pow(a.z - b.z, 2));
return glm::distance(a, b);
}
//using Heuristic = glm::distance;
NodeGraph::NodeGraph() {
}
void NodeGraph::AddNode(const glm::vec3& position) {
m_nodes.push_back(PathNode(position));
}
void NodeGraph::Build(std::function<bool(const glm::vec3&, const glm::vec3&)> test_reach_cb) {
for (int i = 0; i < m_nodes.size(); ++i) {
for (int j = 0; j < m_nodes.size(); ++j) {
if (i == j)
continue;
auto& node = m_nodes[i];
auto& other_node = m_nodes[j];
if (glm::distance(node.position, other_node.position) > 10.0f)
continue;
if (test_reach_cb(node.position, other_node.position))
node.reachable_nodes[node.num_reachable_nodes++] = j;
if (node.num_reachable_nodes == TSR_MAX_REACHABLE_PATHNODES)
break;
}
}
}
bool NodeGraph::FindPath(const glm::vec3& start, const glm::vec3& end, std::vector<glm::vec3>& path) const {
auto start_id = FindClosestNode(start);
auto end_id = FindClosestNode(end);
// Create a map to store the costs of visiting each node
std::unordered_map<int, float> cost_so_far;
// Create a map to store the best known path to each node
std::unordered_map<int, int> came_from;
// Create a priority queue to store the nodes to be explored,
// with the cost as the priority
std::priority_queue<std::pair<float, int>, std::vector<std::pair<float, int>>, std::greater<std::pair<float, int>>> frontier;
// Add the start node to the queue with a cost of 0
frontier.emplace(0, start_id);
cost_so_far[start_id] = 0;
// Loop until the queue is empty
while (!frontier.empty()) {
// Get the node with the lowest cost
int current_id = frontier.top().second;
frontier.pop();
// If we have reached the end, construct the path and return it
if (current_id == end_id) {
//std::vector<int> path;
path.clear();
while (current_id != start_id) {
path.emplace_back(m_nodes[current_id].position);
current_id = came_from[current_id];
}
//path.emplace_back(m_nodes[start_id].position);
//std::reverse(path.begin(), path.end());
return true;
}
// Explore all of the reachable nodes from the current node
for (int i = 0; i < m_nodes[current_id].num_reachable_nodes; ++i) {
int next_id = m_nodes[current_id].reachable_nodes[i];
// Calculate the cost to reach this node
float new_cost = cost_so_far[current_id] + 1; // Add 1 as a simple distance heuristic
// If this node has not been visited or if the new cost is lower than the previous cost,
// update the cost and add it to the queue
if (!cost_so_far.contains(next_id) || new_cost < cost_so_far[next_id]) {
cost_so_far[next_id] = new_cost;
float priority = new_cost + Heuristic(m_nodes[end_id].position, m_nodes[next_id].position); // Add the heuristic cost to the priority queue
frontier.emplace(priority, next_id);
came_from[next_id] = current_id;
}
}
}
// If we couldn't find a path, return an empty vector
return {};
return false;
}
void NodeGraph::DebugDraw(Renderer& renderer) const {
for (int i = 0; i < m_nodes.size(); ++i) {
auto& node = m_nodes[i];
renderer.AddDebugPoint(node.position, glm::vec3(1.0f, 0.0f, 1.0f));
for (int j = 0; j < node.num_reachable_nodes; ++j) {
auto& other_node = m_nodes[node.reachable_nodes[j]];
renderer.AddDebugLine(node.position, other_node.position, glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, 1.0f));
}
}
}

33
src/tsr/paths.hpp Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include "tsr.hpp"
#include "renderer.hpp"
namespace TSR {
struct PathNode {
glm::vec3 position;
int num_reachable_nodes;
int reachable_nodes[TSR_MAX_REACHABLE_PATHNODES];
PathNode(const glm::vec3& position) : position(position), num_reachable_nodes(0) {}
};
class NodeGraph {
std::vector<PathNode> m_nodes;
int FindClosestNode(const glm::vec3& position) const;
public:
NodeGraph();
void AddNode(const glm::vec3& position);
void Build(std::function<bool(const glm::vec3&, const glm::vec3&)> test_reach_cb);
//void FindPath(const glm::vec3& start, const glm::vec3& end, std::vector<glm::vec3>& path) const;
bool FindPath(const glm::vec3& start, const glm::vec3& end, std::vector<glm::vec3>& path) const;
const glm::vec3& GetNodePosition(int id) const { return m_nodes[id].position; }
void DebugDraw(Renderer& renderer) const;
};
}

View File

@ -586,6 +586,15 @@ void Renderer::Render(int width, int height) {
m_debug_vao.Draw(m_debug_lines, true);
}
if (!m_debug_points.empty()) {
//glStencilFunc(GL_ALWAYS, 0, 0xFF);
m_shader_debug.Use();
glUniformMatrix4fv(m_shader_debug.U(SU_VP), 1, GL_FALSE, glm::value_ptr(mat_vp));
glPointSize(10);
m_debug_vao.Draw(m_debug_points, false);
}
// SKYBOX
if (!m_draw_lists[RT_SKYBOX].empty()) {
m_shader_skybox.Use();
@ -647,4 +656,5 @@ void Renderer::Render(int width, int height) {
m_draw_lists[i].clear();
m_debug_lines.clear();
m_debug_points.clear();
}

View File

@ -288,6 +288,7 @@ namespace TSR {
std::vector<DrawRef> m_draw_lists[RT_COUNT];
std::vector<DebugVertex> m_debug_lines;
std::vector<DebugVertex> m_debug_points;
Shader m_shader_basic;
Shader m_shader_basic_instanced;
@ -328,6 +329,10 @@ namespace TSR {
m_debug_lines.push_back({ p2, color2 });
}
void AddDebugPoint(const glm::vec3& p, const glm::vec3& color = glm::vec3(1.0f)) {
m_debug_points.push_back({ p, color });
}
void SetViewMatrix(const glm::mat4& view_matrix) {
m_view_matrix = view_matrix;
}

View File

@ -24,6 +24,9 @@
#define TSR_NUM_COLORS 4
#define TSR_MAX_REACHABLE_PATHNODES 32
#define U8(_S) (const char*)u8##_S
namespace TSR {

View File

@ -48,9 +48,9 @@ int WorldMap::LoadNext() {
PhysicalObject phyobj;
ctx.model_matrix = glm::rotate(glm::translate(glm::mat4(1.0f), pos), glm::radians(rot), glm::vec3(0.0f, 1.0f, 0.0f));
phyobj.m_transform = PxTransform(PxMat44(glm::value_ptr(ctx.model_matrix)));
phyobj.transform = PxTransform(PxMat44(glm::value_ptr(ctx.model_matrix)));
ctx.model_matrix = glm::scale(ctx.model_matrix, glm::vec3(scale));
phyobj.m_scale = scale;
phyobj.scale = scale;
for (int i = 0; i < 4; ++i) {
auto& cns = color_strs[i];
@ -58,8 +58,8 @@ int WorldMap::LoadNext() {
ctx.colors[i] = JsonGetVec<4>(j_object.at(cns));
}
model_instances.m_contexts.push_back(ctx);
model_instances.m_physical_objects.push_back(phyobj);
model_instances.contexts.push_back(ctx);
model_instances.physical_object.push_back(phyobj);
}
m_loading_iter = m_loading_obj_data.cbegin();
@ -73,7 +73,7 @@ int WorldMap::LoadNext() {
case LoadingPhase::MODELS:
{
if (m_loading_iter == m_loading_obj_data.cend()) {
m_loading_phase = LoadingPhase::FINISHED;
m_loading_phase = LoadingPhase::PATHNODES;
m_loading_obj_data.clear();
return 100;
}
@ -83,21 +83,21 @@ int WorldMap::LoadNext() {
auto s = AssetMap::Get<Model>(models.first);
if (models.second.m_contexts.size() > 4) {
if (models.second.contexts.size() > 4) {
MapObject obj;
obj.m_model = s;
obj.m_ctx.ssbo = std::make_unique<InstancedSSBO>(models.second.m_contexts);
obj.model = s;
obj.ctx.ssbo = std::make_unique<InstancedSSBO>(models.second.contexts);
m_objects_instanced.push_back(std::move(obj));
}
else {
for (const auto& instance : models.second.m_contexts) {
for (const auto& instance : models.second.contexts) {
MapObject obj;
obj.m_model = s;
obj.m_ctx.model_matrix = instance.model_matrix;
obj.model = s;
obj.ctx.model_matrix = instance.model_matrix;
for (int i = 0; i < 4; i++)
obj.m_ctx.colors[i] = instance.colors[i];
obj.ctx.colors[i] = instance.colors[i];
m_objects.push_back(std::move(obj));
}
@ -108,9 +108,9 @@ int WorldMap::LoadNext() {
auto material = AssetMap::Get<PhysicsMaterial>("physics/default.material.json");
auto& shape = s->TriMesh();
for (const auto& phyobj : models.second.m_physical_objects) {
PxRigidStatic* actor = Physics::GetPhysics()->createRigidStatic(phyobj.m_transform);
PxShape* px_shape = PxRigidActorExt::createExclusiveShape(*actor, PxTriangleMeshGeometry(shape.Get(), PxMeshScale(phyobj.m_scale)), *material->Get());
for (const auto& phyobj : models.second.physical_object) {
PxRigidStatic* actor = Physics::GetPhysics()->createRigidStatic(phyobj.transform);
PxShape* px_shape = PxRigidActorExt::createExclusiveShape(*actor, PxTriangleMeshGeometry(shape.Get(), PxMeshScale(phyobj.scale)), *material->Get());
m_physics_scene->GetScene()->addActor(*actor);
@ -121,15 +121,15 @@ int WorldMap::LoadNext() {
else if (s->Shape() == SHAPE_BOX) {
auto material = AssetMap::Get<PhysicsMaterial>("physics/default.material.json");
for (const auto& phyobj : models.second.m_physical_objects) {
auto transform = phyobj.m_transform;
for (const auto& phyobj : models.second.physical_object) {
auto transform = phyobj.transform;
auto size = s->ShapeSize();
auto offset = s->ShapeOffset();
transform.p = transform.p + PxVec3(offset.x * phyobj.m_scale, offset.y * phyobj.m_scale, offset.z * phyobj.m_scale);
transform.p = transform.p + PxVec3(offset.x * phyobj.scale, offset.y * phyobj.scale, offset.z * phyobj.scale);
PxRigidStatic* actor = Physics::GetPhysics()->createRigidStatic(transform);
PxShape* px_shape = PxRigidActorExt::createExclusiveShape(*actor, PxBoxGeometry(size.x * phyobj.m_scale, size.y * phyobj.m_scale, size.z * phyobj.m_scale), *material->Get());
PxShape* px_shape = PxRigidActorExt::createExclusiveShape(*actor, PxBoxGeometry(size.x * phyobj.scale, size.y * phyobj.scale, size.z * phyobj.scale), *material->Get());
m_physics_scene->GetScene()->addActor(*actor);
}
@ -142,6 +142,38 @@ int WorldMap::LoadNext() {
break;
}
case LoadingPhase::PATHNODES:
{
auto j_map = nlohmann::json::parse(Filesystem::Read(m_map_path));
if (j_map.contains("pathnodes")) {
auto j_pathnodes = j_map.at("pathnodes");
for (const auto& j_pathnode : j_pathnodes) {
auto pos = JsonGetVec<3>(j_pathnode);
m_node_graph.AddNode(pos);
}
m_node_graph.Build([this](const glm::vec3& a, const glm::vec3& b) {
auto dir = glm::normalize(b - a);
auto dist = glm::distance(a, b);
PxRaycastBuffer hit;
bool status = m_physics_scene->GetScene()->raycast(PxVec3(a.x, a.y, a.z), PxVec3(dir.x, dir.y, dir.z), dist, hit);
if (status)
return false;
return true;
});
}
m_loading_phase = LoadingPhase::FINISHED;
return 100;
break;
}
case LoadingPhase::FINISHED:
return 100;
break;

View File

@ -5,6 +5,7 @@
#include "window.hpp"
#include "tsr.hpp"
#include "physics.hpp"
#include "paths.hpp"
namespace TSR {
@ -18,17 +19,18 @@ namespace TSR {
FIRST,
PARSE,
MODELS,
PATHNODES,
FINISHED,
} m_loading_phase;
struct PhysicalObject {
PxTransform m_transform;
float m_scale;
PxTransform transform;
float scale;
};
struct ModelInstances {
std::vector<BasicDrawCtx> m_contexts;
std::vector<PhysicalObject> m_physical_objects;
std::vector<BasicDrawCtx> contexts;
std::vector<PhysicalObject> physical_object;
};
using LoadingObjData = std::map<std::string, ModelInstances>;
@ -39,13 +41,15 @@ namespace TSR {
// final
struct MapObject {
DrawCtx m_ctx;
AssetPtr<Model> m_model;
DrawCtx ctx;
AssetPtr<Model> model;
};
std::vector<MapObject> m_objects;
std::vector<MapObject> m_objects_instanced;
NodeGraph m_node_graph;
public:
WorldMap(const std::string& map_path, PhysicsScene* physics_scene);
@ -56,11 +60,14 @@ namespace TSR {
void Draw(Renderer& r) const {
for (const auto& obj : m_objects)
obj.m_model->Draw(r, &obj.m_ctx);
obj.model->Draw(r, &obj.ctx);
for (const auto& obj : m_objects_instanced)
obj.m_model->DrawInstanced(r, &obj.m_ctx);
obj.model->DrawInstanced(r, &obj.ctx);
}
const NodeGraph& GetNodeGraph() const { return m_node_graph; }
};

View File

@ -129,6 +129,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\tsr\paths.cpp" />
<ClCompile Include="src\tsr\entity.cpp" />
<ClCompile Include="src\tsr\input.cpp" />
<ClCompile Include="src\tsr\luaapi.cpp" />
@ -147,6 +148,7 @@
<ClCompile Include="src\tsr\worldmap.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\tsr\paths.hpp" />
<ClInclude Include="src\tsr\input.hpp" />
<ClInclude Include="src\tsr\luaapi.hpp" />
<ClInclude Include="src\tsr\entity_cct.hpp" />

View File

@ -63,6 +63,9 @@
<ClCompile Include="src\tsr\entity.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\tsr\paths.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\tsr\window.hpp">
@ -116,5 +119,8 @@
<ClInclude Include="src\tsr\input.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\tsr\paths.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>