mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-15 20:08:54 +03:00
Added Recast&Detour implementation
- Implemented debug renderer of navigation meshes - Can now generate navigation meshes from .map files
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <src/Scene/Components/QuakeMap.h>
|
||||
#include "src/Scene/Systems/QuakeMapBuilder.h"
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/AI/NavManager.h>
|
||||
|
||||
|
||||
class QuakeMapPanel : ComponentPanel {
|
||||
@@ -74,6 +75,32 @@ public:
|
||||
|
||||
//ComponentTableReset(component.Class, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
ImGui::Text("Build Navigation Mesh");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (ImGui::Button("Build Navigation"))
|
||||
{
|
||||
for (auto& mesh : component.m_Brushes)
|
||||
{
|
||||
if (mesh.HasComponent<ModelComponent>())\
|
||||
{
|
||||
TransformComponent& transformComponent = mesh.GetComponent<TransformComponent>();
|
||||
for (auto& mesh : mesh.GetComponent<ModelComponent>().ModelResource->GetMeshes())
|
||||
{
|
||||
Nuake::NavManager::Get().PushMesh(mesh, transformComponent.GetGlobalTransform());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nuake::NavManager::Get().BuildNavMesh();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#include "src/Core/Input.h"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "glad/glad.h"
|
||||
|
||||
void EditorLayer::OnAttach()
|
||||
{
|
||||
@@ -50,6 +52,28 @@ void EditorLayer::OnUpdate()
|
||||
glDepthFunc(GL_LESS);
|
||||
}
|
||||
|
||||
if (m_EditorInterface->ShouldDrawNavMesh())
|
||||
{
|
||||
auto cam = Engine::GetCurrentScene()->m_EditorCamera;
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixf(glm::value_ptr(cam->GetPerspective()));
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(glm::value_ptr(cam->GetTransform()));
|
||||
|
||||
|
||||
glDepthFunc(GL_LESS);
|
||||
RenderCommand::Disable(RendererEnum::DEPTH_TEST);
|
||||
Nuake::NavManager::Get().DrawNavMesh();
|
||||
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
|
||||
|
||||
Nuake::NavManager::Get().DrawNavMesh();
|
||||
glDepthFunc(GL_GREATER);
|
||||
Nuake::NavManager::Get().DrawNavMesh();
|
||||
glDepthFunc(GL_LESS);
|
||||
}
|
||||
|
||||
if (m_EditorInterface->ShouldDrawCollision())
|
||||
{
|
||||
m_GizmoDrawer->DrawGizmos(currentScene, false);
|
||||
@@ -58,6 +82,8 @@ void EditorLayer::OnUpdate()
|
||||
m_GizmoDrawer->DrawGizmos(currentScene, true);
|
||||
glDepthFunc(GL_LESS);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
sceneFramebuffer->Unbind();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <src/Application/Layer.h>
|
||||
#include "Commands/CommandBuffer.h"
|
||||
#include "src/AI/NavMeshDebugDrawer.h"
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
@@ -25,4 +26,6 @@ private:
|
||||
CommandBuffer mCommandBuffer;
|
||||
Nuake::EditorInterface* m_EditorInterface;
|
||||
GizmoDrawer* m_GizmoDrawer;
|
||||
|
||||
Nuake::NavMeshDebugDrawer m_NavMeshDrawer;
|
||||
};
|
||||
@@ -2242,6 +2242,11 @@ namespace Nuake {
|
||||
PhysicsManager::Get().SetDrawDebug(m_DebugCollisions);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Draw navigation meshes", NULL, m_DrawNavMesh))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Settings", NULL)) {}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Nuake
|
||||
bool m_DrawAxis = true;
|
||||
bool m_ShowImGuiDemo = false;
|
||||
bool m_DebugCollisions = true;
|
||||
bool m_DrawNavMesh = true;
|
||||
bool m_ShowOverlay = true;
|
||||
bool m_IsHoveringViewport = false;
|
||||
bool m_IsViewportFocused = false;
|
||||
@@ -76,6 +77,7 @@ namespace Nuake
|
||||
|
||||
bool ShouldDrawAxis() const { return m_DrawAxis; }
|
||||
bool ShouldDrawCollision() const { return m_DebugCollisions; }
|
||||
bool ShouldDrawNavMesh() const { return m_DrawNavMesh; }
|
||||
bool LoadProject(const std::string& projectPath);
|
||||
|
||||
private:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include "src/Scripting/ScriptingEngine.h"
|
||||
#include "src/Audio/AudioManager.h"
|
||||
#include "src/AI/NavManager.h"
|
||||
#include "src/Threading/JobSystem.h"
|
||||
#include "src/Rendering/Renderer.h"
|
||||
#include "src/Rendering/Renderer2D.h"
|
||||
@@ -33,6 +34,7 @@ namespace Nuake
|
||||
{
|
||||
AudioManager::Get().Initialize();
|
||||
PhysicsManager::Get().Init();
|
||||
NavManager::Get().Initialize();
|
||||
|
||||
// Creates the window
|
||||
s_CurrentWindow = Window::Get();
|
||||
|
||||
274
Nuake/src/AI/NavManager.cpp
Normal file
274
Nuake/src/AI/NavManager.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
#include "NavManager.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include "src/Rendering/Vertex.h"
|
||||
#include "Recast.h"
|
||||
#include <DetourNavMeshBuilder.h>
|
||||
#include <DetourNavMesh.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
#include <DetourDebugDraw.h>
|
||||
#include <DebugDraw.h>
|
||||
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
void NavManager::Initialize()
|
||||
{
|
||||
m_RecastContext = CreateRef<rcContext>();
|
||||
}
|
||||
|
||||
void NavManager::Cleanup()
|
||||
{
|
||||
dtFree(m_DetourNavMesh);
|
||||
}
|
||||
|
||||
void NavManager::PushMesh(const Ref<Mesh>& mesh, const Matrix4& transform)
|
||||
{
|
||||
m_Meshes.push_back({ mesh, transform });
|
||||
}
|
||||
|
||||
void NavManager::BuildNavMesh()
|
||||
{
|
||||
// Merge all meshes togheter
|
||||
std::vector<Vector3> vertices;
|
||||
std::vector<int> indices;
|
||||
|
||||
// Since we are merging all the meshes togheter, we need to offset
|
||||
// the indices so they point to the correct vertices in the array.
|
||||
// Example: Model1 + Model2 + Model3 will get merged together in one array
|
||||
// and we need to make sure the indices of Model2 point to the correct location in the merged array
|
||||
uint32_t currentVertexOffset = 0;
|
||||
for (auto& mesh : m_Meshes)
|
||||
{
|
||||
for (auto& vert : mesh.mesh->GetVertices())
|
||||
{
|
||||
Vector4 transformVertex = mesh.transform * Vector4(vert.position.x, vert.position.y, vert.position.z, 1.0f);
|
||||
vertices.push_back({ transformVertex.x, transformVertex.y, transformVertex.z });
|
||||
}
|
||||
|
||||
for (auto& index : mesh.mesh->GetIndices())
|
||||
{
|
||||
indices.push_back(currentVertexOffset + index);
|
||||
}
|
||||
|
||||
currentVertexOffset = std::size(vertices);
|
||||
}
|
||||
|
||||
float bmin[3] = { -100.0f, -100.0f, -100.0f };
|
||||
float bmax[3] = { 100.0f, 100.0f, 100.0f };
|
||||
rcConfig recastConfig;
|
||||
recastConfig.cs = 0.2f;
|
||||
recastConfig.ch = 0.2f;
|
||||
recastConfig.tileSize = 10.0f;
|
||||
recastConfig.walkableSlopeAngle = 45.0f;
|
||||
recastConfig.maxEdgeLen = 12.0f;
|
||||
recastConfig.detailSampleDist = 1.2f;
|
||||
recastConfig.detailSampleMaxError = 0.1f;
|
||||
recastConfig.maxVertsPerPoly = 6.0f;
|
||||
recastConfig.walkableHeight = 1.0f;
|
||||
recastConfig.walkableClimb = 1.0f;
|
||||
recastConfig.walkableRadius = 1.0f;
|
||||
recastConfig.maxSimplificationError = 1.3f;
|
||||
recastConfig.minRegionArea = 8.0f;
|
||||
recastConfig.mergeRegionArea = 20.0f;
|
||||
recastConfig.detailSampleDist = 6.0f;
|
||||
recastConfig.detailSampleMaxError = 1.0f;
|
||||
|
||||
rcVcopy(recastConfig.bmin, bmin);
|
||||
rcVcopy(recastConfig.bmax, bmax);
|
||||
|
||||
// Calculate grid size given world size
|
||||
rcCalcGridSize(recastConfig.bmin, recastConfig.bmax, recastConfig.cs, &recastConfig.width, &recastConfig.height);
|
||||
|
||||
Logger::Log("Building navigation:", "NavManager", VERBOSE);
|
||||
Logger::Log(" - " + std::to_string(recastConfig.width) + " x " + std::to_string(recastConfig.height), "NavManager", VERBOSE);
|
||||
|
||||
auto voxelHeightField = rcAllocHeightfield();
|
||||
if (!voxelHeightField)
|
||||
{
|
||||
Logger::Log("buildNavigation: Out of memory 'solid'.", "NavManager", CRITICAL);
|
||||
}
|
||||
if (!rcCreateHeightfield(m_RecastContext.get(), *voxelHeightField, recastConfig.width, recastConfig.height, recastConfig.bmin, recastConfig.bmax, recastConfig.cs, recastConfig.ch))
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not create solid heightfield.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
unsigned char* m_triareas = new unsigned char[indices.size()];
|
||||
memset(m_triareas, 0, indices.size() * sizeof(unsigned char));
|
||||
|
||||
float* verts = reinterpret_cast<float*>(vertices.data());
|
||||
int* tris = reinterpret_cast<int*>(indices.data());
|
||||
rcMarkWalkableTriangles(m_RecastContext.get(), 45.0f, verts, std::size(vertices), tris, std::size(indices) / 3, m_triareas);
|
||||
if (!rcRasterizeTriangles(m_RecastContext.get(), verts, std::size(vertices), tris, m_triareas, std::size(indices) / 3, *voxelHeightField, recastConfig.walkableClimb))
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not rasterize triangles.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
// Filter walkable surfaces.
|
||||
const bool filterLowHangingObstacles = true;
|
||||
const bool filterLedgeSpans = true;
|
||||
const bool filterWalkableLowHeightSpans = true;
|
||||
if (filterLowHangingObstacles)
|
||||
{
|
||||
rcFilterLowHangingWalkableObstacles(m_RecastContext.get(), recastConfig.walkableClimb, *voxelHeightField);
|
||||
}
|
||||
|
||||
if (filterLedgeSpans)
|
||||
{
|
||||
rcFilterLedgeSpans(m_RecastContext.get(), recastConfig.walkableHeight, recastConfig.walkableClimb, *voxelHeightField);
|
||||
}
|
||||
|
||||
if (filterWalkableLowHeightSpans)
|
||||
{
|
||||
rcFilterWalkableLowHeightSpans(m_RecastContext.get(), recastConfig.walkableHeight, *voxelHeightField);
|
||||
}
|
||||
|
||||
auto compactHeightField = rcAllocCompactHeightfield();
|
||||
bool result = rcBuildCompactHeightfield(m_RecastContext.get(), recastConfig.walkableHeight, recastConfig.walkableClimb, *voxelHeightField, *compactHeightField);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not build compact data.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
// We dont need to keep in memory the height field
|
||||
rcFreeHeightField(voxelHeightField);
|
||||
|
||||
result = rcErodeWalkableArea(m_RecastContext.get(), recastConfig.walkableRadius, *compactHeightField);
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not erode.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
// Water shed for now...
|
||||
result = rcBuildDistanceField(m_RecastContext.get(), *compactHeightField);
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not build distance field.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
result = rcBuildRegions(m_RecastContext.get(), *compactHeightField, 0, recastConfig.minRegionArea, recastConfig.mergeRegionArea);
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not build watershed regions.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
// Trace and simplify region countours.
|
||||
auto contourSet = rcAllocContourSet();
|
||||
result = rcBuildContours(m_RecastContext.get(), *compactHeightField, recastConfig.maxSimplificationError, recastConfig.maxEdgeLen, *contourSet);
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not create contours.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
// Build polygons mesh from contours
|
||||
auto polygonMesh = rcAllocPolyMesh();
|
||||
result = rcBuildPolyMesh(m_RecastContext.get(), *contourSet, recastConfig.maxVertsPerPoly, *polygonMesh);
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not triangulate contours.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
// Create detail polygon mesh
|
||||
auto detailMesh = rcAllocPolyMeshDetail();
|
||||
result = rcBuildPolyMeshDetail(m_RecastContext.get(), *polygonMesh, *compactHeightField, recastConfig.detailSampleDist, recastConfig.detailSampleMaxError, *detailMesh);
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("buildNavigation: Could not build detail mesh.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
// Free memory
|
||||
rcFreeCompactHeightfield(compactHeightField);
|
||||
rcFreeContourSet(contourSet);
|
||||
|
||||
// Apply flags and areas type checking here, example, swim, grass, door, etc.
|
||||
// Should be user defined almost...
|
||||
|
||||
// DETOUR
|
||||
unsigned char* navData = 0;
|
||||
int navDataSize = 0;
|
||||
|
||||
// Create detour data from poly mesh...
|
||||
dtNavMeshCreateParams params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.verts = polygonMesh->verts;
|
||||
params.vertCount = polygonMesh->nverts;
|
||||
params.polys = polygonMesh->polys;
|
||||
params.polyAreas = polygonMesh->areas;
|
||||
params.polyFlags = polygonMesh->flags;
|
||||
params.polyCount = polygonMesh->npolys;
|
||||
params.nvp = polygonMesh->nvp;
|
||||
params.detailVerts = detailMesh->verts;
|
||||
params.detailVertsCount = detailMesh->nverts;
|
||||
params.detailTris = detailMesh->tris;
|
||||
params.detailTriCount = detailMesh->ntris;
|
||||
|
||||
// Off connection, might be useful for user defined jump points?
|
||||
// Maybe useful for ziplines, scripted jumppad, idk
|
||||
// See sample OffMeshConnectionTool.cpp in RecastDemo project.
|
||||
|
||||
//params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
|
||||
//params.offMeshConRad = m_geom->getOffMeshConnectionRads();
|
||||
//params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
|
||||
//params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
|
||||
//params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
|
||||
//params.offMeshConUserID = m_geom->getOffMeshConnectionId();
|
||||
//params.offMeshConCount = m_geom->getOffMeshConnectionCount();
|
||||
|
||||
const float agentHeight = 0.1f;
|
||||
const float agentRadius = 0.1f;
|
||||
const float agentMaxClimb = 0.1f;
|
||||
params.walkableHeight = agentHeight;
|
||||
params.walkableRadius = agentRadius;
|
||||
params.walkableClimb = agentMaxClimb;
|
||||
|
||||
rcVcopy(params.bmin, polygonMesh->bmin);
|
||||
rcVcopy(params.bmax, polygonMesh->bmax);
|
||||
|
||||
// Cell size and cell height
|
||||
params.cs = recastConfig.cs;
|
||||
params.ch = recastConfig.ch;
|
||||
params.buildBvTree = true; // Not sure the difference it makes in performance. based on sample.
|
||||
|
||||
result = dtCreateNavMeshData(¶ms, &navData, &navDataSize);
|
||||
if (!result)
|
||||
{
|
||||
Logger::Log("Could not build Detour navmesh.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
m_DetourNavMesh = dtAllocNavMesh();
|
||||
if (!m_DetourNavMesh)
|
||||
{
|
||||
Logger::Log("Could not create Detour navmesh.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
dtStatus status;
|
||||
status = m_DetourNavMesh->init(navData, navDataSize, DT_TILE_FREE_DATA);
|
||||
if (dtStatusFailed(status))
|
||||
{
|
||||
dtFree(navData);
|
||||
Logger::Log("Could not init Detour navmesh", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
m_DetourNavQuery = dtAllocNavMeshQuery();
|
||||
if (!m_DetourNavQuery)
|
||||
{
|
||||
Logger::Log("Could not create Detour navquery.", "NavManager", CRITICAL);
|
||||
}
|
||||
|
||||
status = m_DetourNavQuery->init(m_DetourNavMesh, 2048);
|
||||
if (!status)
|
||||
{
|
||||
Logger::Log("Could not init Detour navmesh query", "NavManager", CRITICAL);
|
||||
}
|
||||
}
|
||||
|
||||
void NavManager::DrawNavMesh()
|
||||
{
|
||||
if (m_DetourNavMesh)
|
||||
{
|
||||
duDebugDrawNavMeshBVTree(&m_DebugDrawer, *m_DetourNavMesh);
|
||||
duDebugDrawNavMeshNodes(&m_DebugDrawer, *m_DetourNavQuery);
|
||||
duDebugDrawNavMesh(&m_DebugDrawer, *m_DetourNavMesh, DU_DRAWNAVMESH_OFFMESHCONS);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
Nuake/src/AI/NavManager.h
Normal file
49
Nuake/src/AI/NavManager.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Rendering/Mesh/Mesh.h"
|
||||
#include "NavMeshDebugDrawer.h"
|
||||
|
||||
class rcContext;
|
||||
class dtNavMesh;
|
||||
class dtNavMeshQuery;
|
||||
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
struct MeshTransformKeyPair
|
||||
{
|
||||
Ref<Mesh> mesh;
|
||||
Matrix4 transform;
|
||||
};
|
||||
|
||||
class NavManager
|
||||
{
|
||||
public:
|
||||
static NavManager& Get()
|
||||
{
|
||||
static NavManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void Initialize();
|
||||
void PushMesh(const Ref<Mesh>& mesh, const Matrix4& transform);
|
||||
|
||||
void BuildNavMesh();
|
||||
|
||||
void DrawNavMesh();
|
||||
|
||||
void Cleanup();
|
||||
|
||||
private:
|
||||
NavManager() = default;
|
||||
~NavManager() = default;
|
||||
|
||||
std::vector<MeshTransformKeyPair> m_Meshes;
|
||||
|
||||
NavMeshDebugDrawer m_DebugDrawer;
|
||||
|
||||
Ref<rcContext> m_RecastContext;
|
||||
dtNavMesh* m_DetourNavMesh;
|
||||
dtNavMeshQuery* m_DetourNavQuery;
|
||||
};
|
||||
}
|
||||
126
Nuake/src/AI/NavMeshDebugDrawer.cpp
Normal file
126
Nuake/src/AI/NavMeshDebugDrawer.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "NavMeshDebugDrawer.h"
|
||||
#include <glad/glad.h>
|
||||
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
GLCheckerTexture::GLCheckerTexture()
|
||||
{
|
||||
if (m_texId != 0)
|
||||
glDeleteTextures(1, &m_texId);
|
||||
}
|
||||
|
||||
void GLCheckerTexture::bind()
|
||||
{
|
||||
if (m_texId == 0)
|
||||
{
|
||||
// Create checker pattern.
|
||||
const unsigned int col0 = duRGBA(215, 215, 215, 255);
|
||||
const unsigned int col1 = duRGBA(255, 255, 255, 255);
|
||||
static const int TSIZE = 64;
|
||||
unsigned int data[TSIZE * TSIZE];
|
||||
|
||||
glGenTextures(1, &m_texId);
|
||||
glBindTexture(GL_TEXTURE_2D, m_texId);
|
||||
|
||||
int level = 0;
|
||||
int size = TSIZE;
|
||||
while (size > 0)
|
||||
{
|
||||
for (int y = 0; y < size; ++y)
|
||||
for (int x = 0; x < size; ++x)
|
||||
data[x + y * size] = (x == 0 || y == 0) ? col0 : col1;
|
||||
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
size /= 2;
|
||||
level++;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_texId);
|
||||
}
|
||||
}
|
||||
|
||||
GLCheckerTexture::~GLCheckerTexture()
|
||||
{
|
||||
if (m_texId != 0)
|
||||
{
|
||||
glDeleteTextures(1, &m_texId);
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::depthMask(bool state)
|
||||
{
|
||||
glDepthMask(state ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::texture(bool state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
m_Texture.bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::begin(duDebugDrawPrimitives prim, float size)
|
||||
{
|
||||
switch (prim)
|
||||
{
|
||||
case DU_DRAW_POINTS:
|
||||
glPointSize(size);
|
||||
glBegin(GL_POINTS);
|
||||
break;
|
||||
case DU_DRAW_LINES:
|
||||
glLineWidth(size);
|
||||
glBegin(GL_LINES);
|
||||
break;
|
||||
case DU_DRAW_TRIS:
|
||||
glBegin(GL_TRIANGLES);
|
||||
break;
|
||||
case DU_DRAW_QUADS:
|
||||
glBegin(GL_QUADS);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::vertex(const float* pos, unsigned int color)
|
||||
{
|
||||
glColor4ubv((GLubyte*)&color);
|
||||
glVertex3fv(pos);
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::vertex(const float x, const float y, const float z, unsigned int color)
|
||||
{
|
||||
glColor4ubv((GLubyte*)&color);
|
||||
glVertex3f(x, y, z);
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::vertex(const float* pos, unsigned int color, const float* uv)
|
||||
{
|
||||
glColor4ubv((GLubyte*)&color);
|
||||
glTexCoord2fv(uv);
|
||||
glVertex3fv(pos);
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v)
|
||||
{
|
||||
glColor4ubv((GLubyte*)&color);
|
||||
glTexCoord2f(u, v);
|
||||
glVertex3f(x, y, z);
|
||||
}
|
||||
|
||||
void NavMeshDebugDrawer::end()
|
||||
{
|
||||
glEnd();
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
}
|
||||
}
|
||||
39
Nuake/src/AI/NavMeshDebugDrawer.h
Normal file
39
Nuake/src/AI/NavMeshDebugDrawer.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <DebugDraw.h>
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
|
||||
class GLCheckerTexture
|
||||
{
|
||||
private:
|
||||
unsigned int m_texId;
|
||||
|
||||
public:
|
||||
GLCheckerTexture();
|
||||
~GLCheckerTexture();
|
||||
|
||||
void bind();
|
||||
};
|
||||
|
||||
|
||||
class NavMeshDebugDrawer : public duDebugDraw
|
||||
{
|
||||
private:
|
||||
GLCheckerTexture m_Texture;
|
||||
|
||||
public:
|
||||
virtual void depthMask(bool state);
|
||||
virtual void texture(bool state);
|
||||
|
||||
virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f);
|
||||
|
||||
virtual void vertex(const float* pos, unsigned int color);
|
||||
virtual void vertex(const float x, const float y, const float z, unsigned int color);
|
||||
virtual void vertex(const float* pos, unsigned int color, const float* uv);
|
||||
virtual void vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v);
|
||||
|
||||
virtual void end();
|
||||
};
|
||||
}
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
typedef unsigned int GLenum;
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
#include "src/Rendering/Mesh/Mesh.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
#include "src/Scene/Systems/QuakeMapBuilder.h"
|
||||
#include "src/Scene/Entities/Entity.h"
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
class QuakeMapComponent
|
||||
{
|
||||
public:
|
||||
std::vector<Ref<Mesh>> m_Meshes;
|
||||
std::vector<Entity> m_Brushes;
|
||||
std::string Path;
|
||||
float ScaleFactor = 1.0f;
|
||||
bool HasCollisions = false;
|
||||
@@ -22,6 +26,11 @@ namespace Nuake {
|
||||
SERIALIZE_VAL(HasCollisions);
|
||||
SERIALIZE_VAL(Path);
|
||||
SERIALIZE_VAL(AutoRebuild);
|
||||
for (uint32_t i = 0; i < std::size(m_Brushes); i++)
|
||||
{
|
||||
j["Brushes"][i] = m_Brushes[i].GetID();
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < m_Meshes.size(); i++)
|
||||
{
|
||||
j["Meshes"][i] = m_Meshes[i]->Serialize();
|
||||
@@ -37,6 +46,14 @@ namespace Nuake {
|
||||
this->AutoRebuild = j["AutoRebuild"];
|
||||
}
|
||||
|
||||
if (j.contains("Brushes"))
|
||||
{
|
||||
for (auto& b : j["Brushes"])
|
||||
{
|
||||
//m_Brushes.push_back(Engine::GetCurrentScene()->GetEntityByID(b));
|
||||
}
|
||||
}
|
||||
|
||||
this->Path = j["Path"];
|
||||
this->HasCollisions = j["HasCollisions"];
|
||||
return true;
|
||||
|
||||
@@ -513,6 +513,8 @@ namespace Nuake {
|
||||
auto& transformComponent = brushEntity.GetComponent<TransformComponent>();
|
||||
auto& bsp = brushEntity.AddComponent<BSPBrushComponent>();
|
||||
|
||||
quakeMapC.m_Brushes.push_back(brushEntity);
|
||||
|
||||
bsp.IsSolid = true;
|
||||
bsp.IsTransparent = false;
|
||||
bsp.IsFunc = false;
|
||||
|
||||
25
premake5.lua
25
premake5.lua
@@ -35,7 +35,7 @@ include "Nuake/dependencies/jolt_p5.lua"
|
||||
include "Nuake/dependencies/soloud_p5.lua"
|
||||
include "Nuake/dependencies/optick_p5.lua"
|
||||
include "Nuake/dependencies/coral_p5.lua"
|
||||
|
||||
include "Nuake/dependencies/recastnavigation_p5.lua"
|
||||
include "NuakeNet/premake5.lua"
|
||||
|
||||
project "Nuake"
|
||||
@@ -90,7 +90,12 @@ project "Nuake"
|
||||
"%{prj.name}/src/Vendors/incbin",
|
||||
"%{prj.name}/dependencies/build",
|
||||
"%{prj.name}/dependencies/soloud/include",
|
||||
"%{prj.name}/dependencies/Coral/Coral.Native/Include"
|
||||
"%{prj.name}/dependencies/Coral/Coral.Native/Include",
|
||||
"%{prj.name}/dependencies/recastnavigation/DebugUtils/Include",
|
||||
"%{prj.name}/dependencies/recastnavigation/Detour/Include",
|
||||
"%{prj.name}/dependencies/recastnavigation/DetourCrowd/Include",
|
||||
"%{prj.name}/dependencies/recastnavigation/DetourTileCache/Include",
|
||||
"%{prj.name}/dependencies/recastnavigation/Recast/Include"
|
||||
}
|
||||
|
||||
links
|
||||
@@ -286,7 +291,7 @@ project "Editor"
|
||||
"%{prj.name}/src/**.h"
|
||||
}
|
||||
|
||||
includedirs
|
||||
includedirs
|
||||
{
|
||||
"%{prj.name}/../Nuake",
|
||||
"%{prj.name}/../Nuake/src/Vendors",
|
||||
@@ -295,10 +300,15 @@ project "Editor"
|
||||
"%{prj.name}/../Nuake/dependencies/assimp/include",
|
||||
"%{prj.name}/../Nuake/dependencies/build",
|
||||
"%{prj.name}/../Nuake/src/Vendors/msdfgen",
|
||||
"%{prj.name}/../Nuake/dependencies/JoltPhysics",
|
||||
"%{prj.name}/../Nuake/dependencies/JoltPhysics",
|
||||
"%{prj.name}/../Nuake/dependencies/build",
|
||||
"%{prj.name}/../Nuake/dependencies/soloud/include",
|
||||
"/usr/include/gtk-3.0/",
|
||||
"%{prj.name}/../Nuake/dependencies/recastnavigation/DebugUtils/Include",
|
||||
"%{prj.name}/../Nuake/dependencies/recastnavigation/Detour/Include",
|
||||
"%{prj.name}/../Nuake/dependencies/recastnavigation/DetourCrowd/Include",
|
||||
"%{prj.name}/../Nuake/dependencies/recastnavigation/DetourTileCache/Include",
|
||||
"%{prj.name}/../Nuake/dependencies/recastnavigation/Recast/Include"
|
||||
}
|
||||
|
||||
libdirs
|
||||
@@ -325,7 +335,12 @@ project "Editor"
|
||||
"Freetype",
|
||||
"JoltPhysics",
|
||||
"soloud",
|
||||
"Coral.Native"
|
||||
"Coral.Native",
|
||||
"DebugUtils",
|
||||
"Detour",
|
||||
"DetourCrowd",
|
||||
"DetourTileCache",
|
||||
"Recast"
|
||||
}
|
||||
|
||||
filter "system:Windows"
|
||||
|
||||
Reference in New Issue
Block a user