mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
595 lines
18 KiB
C++
595 lines
18 KiB
C++
//
|
|
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
//
|
|
|
|
#include "Shared/Include/SharedAssert.h"
|
|
#include "Include/Editor.h"
|
|
#include "Include/Editor_Common.h"
|
|
#include "DebugUtils/Include/RecastDebugDraw.h"
|
|
#include "DebugUtils/Include/DetourDebugDraw.h"
|
|
#include "Include/InputGeom.h"
|
|
#include <DetourTileCache/Include/DetourTileCache.h>
|
|
|
|
static void EditorCommon_DrawInputGeometry(duDebugDraw* const dd, const InputGeom* const geom,
|
|
const float maxSlope, const float textureScale)
|
|
{
|
|
duDebugDrawTriMeshSlope(dd, geom->getMesh()->getVerts(), geom->getMesh()->getVertCount(),
|
|
geom->getMesh()->getTris(), geom->getMesh()->getNormals(), geom->getMesh()->getTriCount(),
|
|
maxSlope, textureScale, nullptr);
|
|
}
|
|
|
|
static void EditorCommon_DrawBoundingBox(duDebugDraw* const dd, const InputGeom* const geom)
|
|
{
|
|
const float* const origBmin = geom->getMeshBoundsMin();
|
|
const float* const origBmax = geom->getMeshBoundsMax();
|
|
|
|
// Draw Mesh bounds
|
|
duDebugDrawBoxWire(dd, origBmin[0], origBmin[1], origBmin[2], origBmax[0], origBmax[1], origBmax[2], duRGBA(255, 255, 255, 170), 1.0f, nullptr);
|
|
|
|
const float* const origNavBmin = geom->getOriginalNavMeshBoundsMin();
|
|
const float* const origNavBmax = geom->getOriginalNavMeshBoundsMax();
|
|
|
|
const float* const navBmin = geom->getNavMeshBoundsMin();
|
|
const float* const navBmax = geom->getNavMeshBoundsMax();
|
|
|
|
// Draw Original NavMesh bounds (e.g. when loading from a .gset with a predetermined NavMesh bound that differs from the mesh bound)
|
|
if ((!rdVequal(origBmin, origNavBmin) || !rdVequal(origBmax, origNavBmax)) && (!rdVequal(navBmin, origNavBmin) || !rdVequal(navBmax, origNavBmax)))
|
|
duDebugDrawBoxWire(dd, origNavBmin[0], origNavBmin[1], origNavBmin[2], origNavBmax[0], origNavBmax[1], origNavBmax[2], duRGBA(0, 80, 255, 215), 1.0f, nullptr);
|
|
|
|
// Draw NavMesh bounds
|
|
if (!rdVequal(origBmin, navBmin) || !rdVequal(origBmax, navBmax))
|
|
duDebugDrawBoxWire(dd, navBmin[0], navBmin[1], navBmin[2], navBmax[0], navBmax[1], navBmax[2], duRGBA(0, 255, 0, 215), 1.0f, nullptr);
|
|
}
|
|
|
|
static void EditorCommon_DrawTilingGrid(duDebugDraw* const dd, const InputGeom* const geom, const int tileSize, const float cellSize)
|
|
{
|
|
const float* const bmin = geom->getNavMeshBoundsMin();
|
|
const float* const bmax = geom->getNavMeshBoundsMax();
|
|
|
|
int gw = 0, gh = 0;
|
|
rcCalcGridSize(bmin, bmax, cellSize, &gw, &gh);
|
|
|
|
const int tw = (gw + tileSize - 1) / tileSize;
|
|
const int th = (gh + tileSize - 1) / tileSize;
|
|
const float s = tileSize * cellSize;
|
|
|
|
duDebugDrawGridXY(dd, bmax[0], bmin[1], bmin[2], tw, th, s, duRGBA(0, 0, 0, 64), 1.0f, nullptr);
|
|
}
|
|
|
|
int EditorCommon_SetAndRenderTileProperties(const InputGeom* const geom, const int tileSize,
|
|
const float cellSize, int& maxTiles, int& maxPolysPerTile)
|
|
{
|
|
int gridSize = 1;
|
|
|
|
if (geom)
|
|
{
|
|
int gw = 0, gh = 0;
|
|
const float* bmin = geom->getNavMeshBoundsMin();
|
|
const float* bmax = geom->getNavMeshBoundsMax();
|
|
rcCalcGridSize(bmin, bmax, cellSize, &gw, &gh);
|
|
const int ts = tileSize;
|
|
const int tw = (gw + ts-1) / ts;
|
|
const int th = (gh + ts-1) / ts;
|
|
|
|
ImGui::Text("Tiles: %d x %d", tw, th);
|
|
ImGui::Text("Tile Sizes: %g x %g (%g)", tw* cellSize, th*cellSize, tileSize*cellSize);
|
|
|
|
// Max tiles and max polys affect how the tile IDs are calculated.
|
|
// There are 28 bits available for identifying a tile and a polygon.
|
|
int tileBits = rdMin((int)rdIlog2(rdNextPow2(tw*th)), 16);
|
|
int polyBits = 28 - tileBits;
|
|
|
|
maxTiles = 1 << tileBits;
|
|
maxPolysPerTile = 1 << polyBits;
|
|
|
|
gridSize = tw*th;
|
|
|
|
ImGui::Text("Max Tiles: %d", maxTiles);
|
|
ImGui::Text("Max Polys: %d", maxPolysPerTile);
|
|
}
|
|
else
|
|
{
|
|
maxTiles = 0;
|
|
maxPolysPerTile = 0;
|
|
gridSize = 1;
|
|
}
|
|
|
|
return gridSize;
|
|
}
|
|
|
|
Editor_StaticTileMeshCommon::Editor_StaticTileMeshCommon()
|
|
: m_triareas(nullptr)
|
|
, m_solid(nullptr)
|
|
, m_chf(nullptr)
|
|
, m_cset(nullptr)
|
|
, m_pmesh(nullptr)
|
|
, m_dmesh(nullptr)
|
|
, m_tileMeshDrawFlags(TM_DRAWFLAGS_INPUT_MESH|TM_DRAWFLAGS_NAVMESH)
|
|
, m_tileCol(duRGBA(0, 0, 0, 64))
|
|
, m_totalBuildTimeMs(0.0f)
|
|
, m_drawActiveTile(false)
|
|
, m_keepInterResults(false)
|
|
{
|
|
m_lastBuiltTileBmin[0] = 0.0f;
|
|
m_lastBuiltTileBmin[1] = 0.0f;
|
|
m_lastBuiltTileBmin[2] = 0.0f;
|
|
|
|
m_lastBuiltTileBmax[0] = 0.0f;
|
|
m_lastBuiltTileBmax[1] = 0.0f;
|
|
m_lastBuiltTileBmax[2] = 0.0f;
|
|
|
|
memset(&m_cfg, 0, sizeof(rcConfig));
|
|
}
|
|
|
|
void Editor_StaticTileMeshCommon::cleanup()
|
|
{
|
|
delete[] m_triareas;
|
|
m_triareas = 0;
|
|
rcFreeHeightField(m_solid);
|
|
m_solid = 0;
|
|
rcFreeCompactHeightfield(m_chf);
|
|
m_chf = 0;
|
|
rcFreeContourSet(m_cset);
|
|
m_cset = 0;
|
|
rcFreePolyMesh(m_pmesh);
|
|
m_pmesh = 0;
|
|
rcFreePolyMeshDetail(m_dmesh);
|
|
m_dmesh = 0;
|
|
}
|
|
|
|
void Editor_StaticTileMeshCommon::renderRecastDebugMenu()
|
|
{
|
|
ImGui::Text("Recast Render Options");
|
|
|
|
bool isEnabled = m_tileMeshDrawFlags & TM_DRAWFLAGS_INPUT_MESH;
|
|
|
|
// This should always be available, since if we load a large mesh we want to
|
|
// be able to toggle this off to save on performance. The renderer has to be
|
|
// moved to its own thread to solve this issue.
|
|
if (ImGui::Checkbox("Input Mesh", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_INPUT_MESH);
|
|
|
|
// Check which modes are valid.
|
|
//const bool hasNavMesh =m_navMesh != 0;
|
|
const bool hasChf = m_chf != 0;
|
|
const bool hasCset = m_cset != 0;
|
|
const bool hasSolid = m_solid != 0;
|
|
const bool hasDMesh = m_dmesh != 0;
|
|
|
|
const bool intermediateDataUnavailable = !hasChf || !hasCset || !hasSolid || !hasDMesh;
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_NAVMESH;
|
|
//ImGui::BeginDisabled(!hasNavMesh);
|
|
|
|
if (ImGui::Checkbox("NavMesh", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_NAVMESH);
|
|
|
|
//ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_VOXELS;
|
|
ImGui::BeginDisabled(!hasSolid);
|
|
|
|
if (ImGui::Checkbox("Voxels", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_VOXELS);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_VOXELS_WALKABLE;
|
|
ImGui::BeginDisabled(!hasSolid);
|
|
|
|
if (ImGui::Checkbox("Walkable Voxels", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_VOXELS_WALKABLE);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_COMPACT;
|
|
ImGui::BeginDisabled(!hasChf);
|
|
|
|
if (ImGui::Checkbox("Compact", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_COMPACT);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_COMPACT_DISTANCE;
|
|
ImGui::BeginDisabled(!hasChf);
|
|
|
|
if (ImGui::Checkbox("Compact Distance", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_COMPACT_DISTANCE);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_COMPACT_REGIONS;
|
|
ImGui::BeginDisabled(!hasChf);
|
|
|
|
if (ImGui::Checkbox("Compact Regions", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_COMPACT_REGIONS);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_REGION_CONNECTIONS;
|
|
ImGui::BeginDisabled(!hasCset);
|
|
|
|
if (ImGui::Checkbox("Region Connections", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_REGION_CONNECTIONS);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_RAW_CONTOURS;
|
|
ImGui::BeginDisabled(!hasCset);
|
|
|
|
if (ImGui::Checkbox("Raw Contours", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_RAW_CONTOURS);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_CONTOURS;
|
|
ImGui::BeginDisabled(!hasCset);
|
|
|
|
if (ImGui::Checkbox("Contours", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_CONTOURS);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_POLYMESH;
|
|
ImGui::BeginDisabled(!hasDMesh);
|
|
|
|
if (ImGui::Checkbox("Poly Mesh", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_POLYMESH);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_POLYMESH_DETAIL;
|
|
ImGui::BeginDisabled(!hasDMesh);
|
|
|
|
if (ImGui::Checkbox("Poly Mesh Detail", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_POLYMESH_DETAIL);
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
//if (intermediateDataUnavailable) // todo(amos): tool tip
|
|
//{
|
|
// ImGui::Separator();
|
|
|
|
// ImGui::Text("Tick 'Keep Intermediate Results'");
|
|
// ImGui::Text("rebuild some tiles to see");
|
|
// ImGui::Text("more debug mode options.");
|
|
//}
|
|
}
|
|
|
|
void Editor_StaticTileMeshCommon::renderTileMeshData()
|
|
{
|
|
if (!m_geom || !m_geom->getMesh())
|
|
return;
|
|
|
|
const float texScale = 1.0f / (m_cellSize * 10.0f);
|
|
|
|
// Draw input mesh
|
|
if (getTileMeshDrawFlags() & TM_DRAWFLAGS_INPUT_MESH)
|
|
EditorCommon_DrawInputGeometry(&m_dd, m_geom, m_agentMaxSlope, texScale);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
// Draw bounds
|
|
EditorCommon_DrawBoundingBox(&m_dd, m_geom);
|
|
|
|
// Tiling grid.
|
|
EditorCommon_DrawTilingGrid(&m_dd, m_geom, m_tileSize, m_cellSize);
|
|
|
|
const float* recastDrawOffset = getRecastDrawOffset();
|
|
const float* detourDrawOffset = getDetourDrawOffset();
|
|
|
|
const unsigned int recastDrawFlags = getTileMeshDrawFlags();
|
|
const unsigned int detourDrawFlags = getNavMeshDrawFlags();
|
|
|
|
if (m_drawActiveTile)
|
|
{
|
|
// Draw active tile
|
|
// NOTE: only perform offset in x-y
|
|
duDebugDrawBoxWire(&m_dd, m_lastBuiltTileBmin[0]+detourDrawOffset[0], m_lastBuiltTileBmin[1]+detourDrawOffset[1], m_lastBuiltTileBmin[2],
|
|
m_lastBuiltTileBmax[0]+detourDrawOffset[0], m_lastBuiltTileBmax[1]+detourDrawOffset[1], m_lastBuiltTileBmax[2], m_tileCol, 1.0f, nullptr);
|
|
}
|
|
|
|
if (m_navMesh && m_navQuery)
|
|
{
|
|
if (m_tileMeshDrawFlags & TM_DRAWFLAGS_NAVMESH)
|
|
{
|
|
duDebugDrawNavMeshWithClosedList(&m_dd, *m_navMesh, *m_navQuery, detourDrawOffset, m_navMeshDrawFlags, m_traverseLinkDrawTypes);
|
|
duDebugDrawNavMeshPolysWithFlags(&m_dd, *m_navMesh, EDITOR_POLYFLAGS_DISABLED, detourDrawOffset, detourDrawFlags, duRGBA(0, 0, 0, 128));
|
|
}
|
|
}
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
if (m_chf)
|
|
{
|
|
if (recastDrawFlags & TM_DRAWFLAGS_COMPACT)
|
|
duDebugDrawCompactHeightfieldSolid(&m_dd, *m_chf, recastDrawOffset);
|
|
|
|
if (recastDrawFlags & TM_DRAWFLAGS_COMPACT_DISTANCE)
|
|
duDebugDrawCompactHeightfieldDistance(&m_dd, *m_chf, recastDrawOffset);
|
|
if (recastDrawFlags & TM_DRAWFLAGS_COMPACT_REGIONS)
|
|
duDebugDrawCompactHeightfieldRegions(&m_dd, *m_chf, recastDrawOffset);
|
|
}
|
|
|
|
if (m_solid)
|
|
{
|
|
if (recastDrawFlags & TM_DRAWFLAGS_VOXELS)
|
|
{
|
|
glEnable(GL_FOG);
|
|
duDebugDrawHeightfieldSolid(&m_dd, *m_solid, recastDrawOffset);
|
|
glDisable(GL_FOG);
|
|
}
|
|
if (recastDrawFlags & TM_DRAWFLAGS_VOXELS_WALKABLE)
|
|
{
|
|
glEnable(GL_FOG);
|
|
duDebugDrawHeightfieldWalkable(&m_dd, *m_solid, recastDrawOffset);
|
|
glDisable(GL_FOG);
|
|
}
|
|
}
|
|
|
|
if (m_cset)
|
|
{
|
|
if (recastDrawFlags & TM_DRAWFLAGS_RAW_CONTOURS)
|
|
{
|
|
glDepthMask(GL_FALSE);
|
|
duDebugDrawRawContours(&m_dd, *m_cset, recastDrawOffset);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
if (recastDrawFlags & TM_DRAWFLAGS_CONTOURS)
|
|
{
|
|
glDepthMask(GL_FALSE);
|
|
duDebugDrawContours(&m_dd, *m_cset, recastDrawOffset);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
}
|
|
|
|
if ((m_chf &&m_cset) &&
|
|
(recastDrawFlags & TM_DRAWFLAGS_REGION_CONNECTIONS))
|
|
{
|
|
duDebugDrawCompactHeightfieldRegions(&m_dd, *m_chf, recastDrawOffset);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
duDebugDrawRegionConnections(&m_dd, *m_cset, recastDrawOffset);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
|
|
if (m_pmesh && (recastDrawFlags & TM_DRAWFLAGS_POLYMESH))
|
|
{
|
|
glDepthMask(GL_FALSE);
|
|
duDebugDrawPolyMesh(&m_dd, *m_pmesh, recastDrawOffset);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
|
|
if (m_dmesh && (recastDrawFlags & TM_DRAWFLAGS_POLYMESH_DETAIL))
|
|
{
|
|
glDepthMask(GL_FALSE);
|
|
duDebugDrawPolyMeshDetail(&m_dd, *m_dmesh, recastDrawOffset);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
|
|
// TODO: also add flags for this
|
|
m_geom->drawConvexVolumes(&m_dd, recastDrawOffset);
|
|
|
|
// NOTE: commented out because this already gets rendered when the off-mesh
|
|
// connection tool is activated. And if we generated an off-mesh link, this
|
|
// would overlap with that as well.
|
|
//m_geom->drawOffMeshConnections(&m_dd, recastDrawOffset);
|
|
|
|
if (m_tool)
|
|
m_tool->handleRender();
|
|
|
|
renderToolStates();
|
|
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
|
|
void Editor_StaticTileMeshCommon::renderIntermediateTileMeshOptions()
|
|
{
|
|
ImGui::Indent();
|
|
ImGui::Indent();
|
|
|
|
if (ImGui::Button("Load", ImVec2(123, 0)))
|
|
{
|
|
Editor::loadNavMesh(m_modelName.c_str());
|
|
}
|
|
|
|
if (ImGui::Button("Save", ImVec2(123, 0)))
|
|
{
|
|
Editor::saveAll(m_modelName.c_str(), m_navMesh);
|
|
}
|
|
|
|
ImGui::Unindent();
|
|
ImGui::Unindent();
|
|
|
|
ImGui::Text("Build Time: %.1fms", m_totalBuildTimeMs);
|
|
|
|
if (m_navMesh)
|
|
{
|
|
const dtNavMeshParams& params = *m_navMesh->getParams();
|
|
//const float* origin = m_navMesh->m_orig;
|
|
|
|
//ImGui::Text("Mesh Origin: \n\tX: %g \n\tY: %g \n\tZ: %g", origin[0], origin[1], origin[2]);
|
|
ImGui::Text("Tile Dimensions: %g x %g", params.tileWidth, params.tileHeight);
|
|
ImGui::Text("Poly Group Count: %d", params.polyGroupCount);
|
|
ImGui::Text("Traversal Table Size: %d", params.traversalTableSize);
|
|
ImGui::Text("Traversal Table Count: %d", params.traversalTableCount);
|
|
ImGui::Text("Max Tiles: %d", params.maxTiles);
|
|
ImGui::Text("Max Polys: %d", params.maxPolys);
|
|
|
|
ImGui::Separator();
|
|
}
|
|
else
|
|
ImGui::Separator();
|
|
}
|
|
|
|
void drawTiles(duDebugDraw* dd, dtTileCache* tc, const float* offset)
|
|
{
|
|
unsigned int fcol[6];
|
|
float bmin[3], bmax[3];
|
|
|
|
for (int i = 0; i < tc->getTileCount(); ++i)
|
|
{
|
|
const dtCompressedTile* tile = tc->getTile(i);
|
|
if (!tile->header) continue;
|
|
|
|
tc->calcTightTileBounds(tile->header, bmin, bmax);
|
|
|
|
const unsigned int col = duIntToCol(i, 64);
|
|
duCalcBoxColors(fcol, col, col);
|
|
duDebugDrawBox(dd, bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2], fcol, offset);
|
|
}
|
|
|
|
for (int i = 0; i < tc->getTileCount(); ++i)
|
|
{
|
|
const dtCompressedTile* tile = tc->getTile(i);
|
|
if (!tile->header) continue;
|
|
|
|
tc->calcTightTileBounds(tile->header, bmin, bmax);
|
|
|
|
const unsigned int col = duIntToCol(i, 255);
|
|
const float pad = tc->getParams()->cs * 0.1f;
|
|
duDebugDrawBoxWire(dd, bmin[0] - pad, bmin[1] - pad, bmin[2] - pad,
|
|
bmax[0] + pad, bmax[1] + pad, bmax[2] + pad, col, 2.0f, offset);
|
|
}
|
|
}
|
|
|
|
void drawObstacles(duDebugDraw* dd, const dtTileCache* tc, const float* offset)
|
|
{
|
|
// Draw obstacles
|
|
for (int i = 0; i < tc->getObstacleCount(); ++i)
|
|
{
|
|
const dtTileCacheObstacle* ob = tc->getObstacle(i);
|
|
if (ob->state == DT_OBSTACLE_EMPTY) continue;
|
|
float bmin[3], bmax[3];
|
|
tc->getObstacleBounds(ob, bmin, bmax);
|
|
|
|
unsigned int col = 0;
|
|
if (ob->state == DT_OBSTACLE_PROCESSING)
|
|
col = duRGBA(255, 255, 0, 128);
|
|
else if (ob->state == DT_OBSTACLE_PROCESSED)
|
|
col = duRGBA(255, 192, 0, 192);
|
|
else if (ob->state == DT_OBSTACLE_REMOVING)
|
|
col = duRGBA(220, 0, 0, 128);
|
|
|
|
duDebugDrawCylinder(dd, bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2], col, offset);
|
|
duDebugDrawCylinderWire(dd, bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2], duDarkenCol(col), 2.0f, offset);
|
|
}
|
|
}
|
|
|
|
Editor_DynamicTileMeshCommon::Editor_DynamicTileMeshCommon()
|
|
: m_tileCache(nullptr)
|
|
, m_talloc(nullptr)
|
|
, m_tcomp(nullptr)
|
|
, m_tmproc(nullptr)
|
|
, m_cacheBuildTimeMs(0.0f)
|
|
, m_cacheCompressedSize(0)
|
|
, m_cacheRawSize(0)
|
|
, m_cacheLayerCount(0)
|
|
, m_cacheBuildMemUsage(0)
|
|
, m_tileMeshDrawFlags(TM_DRAWFLAGS_INPUT_MESH|TM_DRAWFLAGS_NAVMESH)
|
|
, m_keepInterResults(false)
|
|
{
|
|
}
|
|
|
|
void Editor_DynamicTileMeshCommon::renderRecastRenderOptions()
|
|
{
|
|
ImGui::Text("Recast Render Options");
|
|
|
|
bool isEnabled = m_tileMeshDrawFlags & TM_DRAWFLAGS_INPUT_MESH;
|
|
|
|
// This should always be available, since if we load a large mesh we want to
|
|
// be able to toggle this off to save on performance. The renderer has to be
|
|
// moved to its own thread to solve this issue.
|
|
if (ImGui::Checkbox("Input Mesh", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_INPUT_MESH);
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_NAVMESH;
|
|
//ImGui::BeginDisabled(!hasNavMesh);
|
|
|
|
if (ImGui::Checkbox("NavMesh", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_NAVMESH);
|
|
|
|
//ImGui::EndDisabled();
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_TILE_CACHE_BOUNDS;
|
|
|
|
ImGui::BeginDisabled(!m_tileCache);
|
|
|
|
if (ImGui::Checkbox("Cache Bounds", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_TILE_CACHE_BOUNDS);
|
|
|
|
isEnabled = getTileMeshDrawFlags() & TM_DRAWFLAGS_TILE_CACHE_OBSTACLES;
|
|
|
|
if (ImGui::Checkbox("Temp Obstacles", &isEnabled))
|
|
toggleTileMeshDrawFlag(TM_DRAWFLAGS_TILE_CACHE_OBSTACLES);
|
|
|
|
ImGui::EndDisabled();
|
|
}
|
|
|
|
void Editor_DynamicTileMeshCommon::renderTileMeshData()
|
|
{
|
|
if (!m_geom || !m_geom->getMesh())
|
|
return;
|
|
|
|
const float texScale = 1.0f / (m_cellSize * 10.0f);
|
|
const unsigned int recastDrawFlags = getTileMeshDrawFlags();
|
|
const unsigned int detourDrawFlags = getNavMeshDrawFlags();
|
|
|
|
const float* recastDrawOffset = getRecastDrawOffset();
|
|
const float* detourDrawOffset = getDetourDrawOffset();
|
|
|
|
// Draw input mesh
|
|
if (recastDrawFlags & TM_DRAWFLAGS_INPUT_MESH)
|
|
EditorCommon_DrawInputGeometry(&m_dd, m_geom, m_agentMaxSlope, texScale);
|
|
|
|
// Draw bounds
|
|
EditorCommon_DrawBoundingBox(&m_dd, m_geom);
|
|
|
|
// Tiling grid.
|
|
EditorCommon_DrawTilingGrid(&m_dd, m_geom, m_tileSize, m_cellSize);
|
|
|
|
if (m_tileCache && recastDrawFlags & TM_DRAWFLAGS_TILE_CACHE_BOUNDS)
|
|
drawTiles(&m_dd, m_tileCache, detourDrawOffset);
|
|
|
|
if (m_tileCache && recastDrawFlags & TM_DRAWFLAGS_TILE_CACHE_OBSTACLES)
|
|
drawObstacles(&m_dd, m_tileCache, detourDrawOffset);
|
|
|
|
if (m_navMesh && m_navQuery)
|
|
{
|
|
if (recastDrawFlags & TM_DRAWFLAGS_NAVMESH)
|
|
{
|
|
duDebugDrawNavMeshWithClosedList(&m_dd, *m_navMesh, *m_navQuery, detourDrawOffset, detourDrawFlags);
|
|
duDebugDrawNavMeshPolysWithFlags(&m_dd, *m_navMesh, EDITOR_POLYFLAGS_DISABLED, detourDrawOffset, detourDrawFlags, duRGBA(0, 0, 0, 128));
|
|
}
|
|
}
|
|
|
|
// TODO: also add flags for this
|
|
m_geom->drawConvexVolumes(&m_dd, recastDrawOffset);
|
|
|
|
// NOTE: commented out because this already gets rendered when the off-mesh
|
|
// connection tool is activated. And if we generated an off-mesh link, this
|
|
// would overlap with that as well.
|
|
//m_geom->drawOffMeshConnections(&m_dd, recastDrawOffset);
|
|
|
|
if (m_tool)
|
|
m_tool->handleRender();
|
|
|
|
renderToolStates();
|
|
|
|
glDepthMask(GL_TRUE);
|
|
}
|