123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- //
- // 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.
- //
- #define _USE_MATH_DEFINES
- #include <math.h>
- #include <stdio.h>
- #include "Sample.h"
- #include "InputGeom.h"
- #include "Recast.h"
- #include "RecastDebugDraw.h"
- #include "DetourDebugDraw.h"
- #include "DetourNavMesh.h"
- #include "DetourNavMeshQuery.h"
- #include "DetourCrowd.h"
- #include "imgui.h"
- #include "SDL.h"
- #include "SDL_opengl.h"
- #ifdef WIN32
- # define snprintf _snprintf
- #endif
- unsigned int SampleDebugDraw::areaToCol(unsigned int area)
- {
- switch(area)
- {
- // Ground (0) : light blue
- case SAMPLE_POLYAREA_GROUND: return duRGBA(0, 192, 255, 255);
- // Water : blue
- case SAMPLE_POLYAREA_WATER: return duRGBA(0, 0, 255, 255);
- // Road : brown
- case SAMPLE_POLYAREA_ROAD: return duRGBA(50, 20, 12, 255);
- // Door : cyan
- case SAMPLE_POLYAREA_DOOR: return duRGBA(0, 255, 255, 255);
- // Grass : green
- case SAMPLE_POLYAREA_GRASS: return duRGBA(0, 255, 0, 255);
- // Jump : yellow
- case SAMPLE_POLYAREA_JUMP: return duRGBA(255, 255, 0, 255);
- // Unexpected : red
- default: return duRGBA(255, 0, 0, 255);
- }
- }
- Sample::Sample() :
- m_geom(0),
- m_navMesh(0),
- m_navQuery(0),
- m_crowd(0),
- m_navMeshDrawFlags(DU_DRAWNAVMESH_OFFMESHCONS|DU_DRAWNAVMESH_CLOSEDLIST),
- m_filterLowHangingObstacles(true),
- m_filterLedgeSpans(true),
- m_filterWalkableLowHeightSpans(true),
- m_tool(0),
- m_ctx(0)
- {
- resetCommonSettings();
- m_navQuery = dtAllocNavMeshQuery();
- m_crowd = dtAllocCrowd();
- for (int i = 0; i < MAX_TOOLS; i++)
- m_toolStates[i] = 0;
- }
- Sample::~Sample()
- {
- dtFreeNavMeshQuery(m_navQuery);
- dtFreeNavMesh(m_navMesh);
- dtFreeCrowd(m_crowd);
- delete m_tool;
- for (int i = 0; i < MAX_TOOLS; i++)
- delete m_toolStates[i];
- }
- void Sample::setTool(SampleTool* tool)
- {
- delete m_tool;
- m_tool = tool;
- if (tool)
- m_tool->init(this);
- }
- void Sample::handleSettings()
- {
- }
- void Sample::handleTools()
- {
- }
- void Sample::handleDebugMode()
- {
- }
- void Sample::handleRender()
- {
- if (!m_geom)
- return;
-
- // Draw mesh
- duDebugDrawTriMesh(&m_dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
- m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0, 1.0f);
- // Draw bounds
- const float* bmin = m_geom->getMeshBoundsMin();
- const float* bmax = m_geom->getMeshBoundsMax();
- duDebugDrawBoxWire(&m_dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], duRGBA(255,255,255,128), 1.0f);
- }
- void Sample::handleRenderOverlay(double* /*proj*/, double* /*model*/, int* /*view*/)
- {
- }
- void Sample::handleMeshChanged(InputGeom* geom)
- {
- m_geom = geom;
- const BuildSettings* buildSettings = geom->getBuildSettings();
- if (buildSettings)
- {
- m_cellSize = buildSettings->cellSize;
- m_cellHeight = buildSettings->cellHeight;
- m_agentHeight = buildSettings->agentHeight;
- m_agentRadius = buildSettings->agentRadius;
- m_agentMaxClimb = buildSettings->agentMaxClimb;
- m_agentMaxSlope = buildSettings->agentMaxSlope;
- m_regionMinSize = buildSettings->regionMinSize;
- m_regionMergeSize = buildSettings->regionMergeSize;
- m_edgeMaxLen = buildSettings->edgeMaxLen;
- m_edgeMaxError = buildSettings->edgeMaxError;
- m_vertsPerPoly = buildSettings->vertsPerPoly;
- m_detailSampleDist = buildSettings->detailSampleDist;
- m_detailSampleMaxError = buildSettings->detailSampleMaxError;
- m_partitionType = buildSettings->partitionType;
- }
- }
- void Sample::collectSettings(BuildSettings& settings)
- {
- settings.cellSize = m_cellSize;
- settings.cellHeight = m_cellHeight;
- settings.agentHeight = m_agentHeight;
- settings.agentRadius = m_agentRadius;
- settings.agentMaxClimb = m_agentMaxClimb;
- settings.agentMaxSlope = m_agentMaxSlope;
- settings.regionMinSize = m_regionMinSize;
- settings.regionMergeSize = m_regionMergeSize;
- settings.edgeMaxLen = m_edgeMaxLen;
- settings.edgeMaxError = m_edgeMaxError;
- settings.vertsPerPoly = m_vertsPerPoly;
- settings.detailSampleDist = m_detailSampleDist;
- settings.detailSampleMaxError = m_detailSampleMaxError;
- settings.partitionType = m_partitionType;
- }
- void Sample::resetCommonSettings()
- {
- m_cellSize = 0.3f;
- m_cellHeight = 0.2f;
- m_agentHeight = 2.0f;
- m_agentRadius = 0.6f;
- m_agentMaxClimb = 0.9f;
- m_agentMaxSlope = 45.0f;
- m_regionMinSize = 8;
- m_regionMergeSize = 20;
- m_edgeMaxLen = 12.0f;
- m_edgeMaxError = 1.3f;
- m_vertsPerPoly = 6.0f;
- m_detailSampleDist = 6.0f;
- m_detailSampleMaxError = 1.0f;
- m_partitionType = SAMPLE_PARTITION_WATERSHED;
- }
- void Sample::handleCommonSettings()
- {
- imguiLabel("Rasterization");
- imguiSlider("Cell Size", &m_cellSize, 0.1f, 1.0f, 0.01f);
- imguiSlider("Cell Height", &m_cellHeight, 0.1f, 1.0f, 0.01f);
-
- if (m_geom)
- {
- const float* bmin = m_geom->getNavMeshBoundsMin();
- const float* bmax = m_geom->getNavMeshBoundsMax();
- int gw = 0, gh = 0;
- rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
- char text[64];
- snprintf(text, 64, "Voxels %d x %d", gw, gh);
- imguiValue(text);
- }
-
- imguiSeparator();
- imguiLabel("Agent");
- imguiSlider("Height", &m_agentHeight, 0.1f, 5.0f, 0.1f);
- imguiSlider("Radius", &m_agentRadius, 0.0f, 5.0f, 0.1f);
- imguiSlider("Max Climb", &m_agentMaxClimb, 0.1f, 5.0f, 0.1f);
- imguiSlider("Max Slope", &m_agentMaxSlope, 0.0f, 90.0f, 1.0f);
-
- imguiSeparator();
- imguiLabel("Region");
- imguiSlider("Min Region Size", &m_regionMinSize, 0.0f, 150.0f, 1.0f);
- imguiSlider("Merged Region Size", &m_regionMergeSize, 0.0f, 150.0f, 1.0f);
- imguiSeparator();
- imguiLabel("Partitioning");
- if (imguiCheck("Watershed", m_partitionType == SAMPLE_PARTITION_WATERSHED))
- m_partitionType = SAMPLE_PARTITION_WATERSHED;
- if (imguiCheck("Monotone", m_partitionType == SAMPLE_PARTITION_MONOTONE))
- m_partitionType = SAMPLE_PARTITION_MONOTONE;
- if (imguiCheck("Layers", m_partitionType == SAMPLE_PARTITION_LAYERS))
- m_partitionType = SAMPLE_PARTITION_LAYERS;
-
- imguiSeparator();
- imguiLabel("Filtering");
- if (imguiCheck("Low Hanging Obstacles", m_filterLowHangingObstacles))
- m_filterLowHangingObstacles = !m_filterLowHangingObstacles;
- if (imguiCheck("Ledge Spans", m_filterLedgeSpans))
- m_filterLedgeSpans= !m_filterLedgeSpans;
- if (imguiCheck("Walkable Low Height Spans", m_filterWalkableLowHeightSpans))
- m_filterWalkableLowHeightSpans = !m_filterWalkableLowHeightSpans;
- imguiSeparator();
- imguiLabel("Polygonization");
- imguiSlider("Max Edge Length", &m_edgeMaxLen, 0.0f, 50.0f, 1.0f);
- imguiSlider("Max Edge Error", &m_edgeMaxError, 0.1f, 3.0f, 0.1f);
- imguiSlider("Verts Per Poly", &m_vertsPerPoly, 3.0f, 12.0f, 1.0f);
- imguiSeparator();
- imguiLabel("Detail Mesh");
- imguiSlider("Sample Distance", &m_detailSampleDist, 0.0f, 16.0f, 1.0f);
- imguiSlider("Max Sample Error", &m_detailSampleMaxError, 0.0f, 16.0f, 1.0f);
-
- imguiSeparator();
- }
- void Sample::handleClick(const float* s, const float* p, bool shift)
- {
- if (m_tool)
- m_tool->handleClick(s, p, shift);
- }
- void Sample::handleToggle()
- {
- if (m_tool)
- m_tool->handleToggle();
- }
- void Sample::handleStep()
- {
- if (m_tool)
- m_tool->handleStep();
- }
- bool Sample::handleBuild()
- {
- return true;
- }
- void Sample::handleUpdate(const float dt)
- {
- if (m_tool)
- m_tool->handleUpdate(dt);
- updateToolStates(dt);
- }
- void Sample::updateToolStates(const float dt)
- {
- for (int i = 0; i < MAX_TOOLS; i++)
- {
- if (m_toolStates[i])
- m_toolStates[i]->handleUpdate(dt);
- }
- }
- void Sample::initToolStates(Sample* sample)
- {
- for (int i = 0; i < MAX_TOOLS; i++)
- {
- if (m_toolStates[i])
- m_toolStates[i]->init(sample);
- }
- }
- void Sample::resetToolStates()
- {
- for (int i = 0; i < MAX_TOOLS; i++)
- {
- if (m_toolStates[i])
- m_toolStates[i]->reset();
- }
- }
- void Sample::renderToolStates()
- {
- for (int i = 0; i < MAX_TOOLS; i++)
- {
- if (m_toolStates[i])
- m_toolStates[i]->handleRender();
- }
- }
- void Sample::renderOverlayToolStates(double* proj, double* model, int* view)
- {
- for (int i = 0; i < MAX_TOOLS; i++)
- {
- if (m_toolStates[i])
- m_toolStates[i]->handleRenderOverlay(proj, model, view);
- }
- }
- static const int NAVMESHSET_MAGIC = 'M'<<24 | 'S'<<16 | 'E'<<8 | 'T'; //'MSET';
- static const int NAVMESHSET_VERSION = 1;
- struct NavMeshSetHeader
- {
- int magic;
- int version;
- int numTiles;
- dtNavMeshParams params;
- };
- struct NavMeshTileHeader
- {
- dtTileRef tileRef;
- int dataSize;
- };
- dtNavMesh* Sample::loadAll(const char* path)
- {
- FILE* fp = fopen(path, "rb");
- if (!fp) return 0;
- // Read header.
- NavMeshSetHeader header;
- size_t readLen = fread(&header, sizeof(NavMeshSetHeader), 1, fp);
- if (readLen != 1)
- {
- fclose(fp);
- return 0;
- }
- if (header.magic != NAVMESHSET_MAGIC)
- {
- fclose(fp);
- return 0;
- }
- if (header.version != NAVMESHSET_VERSION)
- {
- fclose(fp);
- return 0;
- }
- dtNavMesh* mesh = dtAllocNavMesh();
- if (!mesh)
- {
- fclose(fp);
- return 0;
- }
- dtStatus status = mesh->init(&header.params);
- if (dtStatusFailed(status))
- {
- fclose(fp);
- return 0;
- }
- // Read tiles.
- for (int i = 0; i < header.numTiles; ++i)
- {
- NavMeshTileHeader tileHeader;
- readLen = fread(&tileHeader, sizeof(tileHeader), 1, fp);
- if (readLen != 1)
- {
- fclose(fp);
- return 0;
- }
- if (!tileHeader.tileRef || !tileHeader.dataSize)
- break;
- unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM);
- if (!data) break;
- memset(data, 0, tileHeader.dataSize);
- readLen = fread(data, tileHeader.dataSize, 1, fp);
- if (readLen != 1)
- {
- dtFree(data);
- fclose(fp);
- return 0;
- }
- mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0);
- }
- fclose(fp);
- return mesh;
- }
- void Sample::saveAll(const char* path, const dtNavMesh* mesh)
- {
- if (!mesh) return;
- FILE* fp = fopen(path, "wb");
- if (!fp)
- return;
- // Store header.
- NavMeshSetHeader header;
- header.magic = NAVMESHSET_MAGIC;
- header.version = NAVMESHSET_VERSION;
- header.numTiles = 0;
- for (int i = 0; i < mesh->getMaxTiles(); ++i)
- {
- const dtMeshTile* tile = mesh->getTile(i);
- if (!tile || !tile->header || !tile->dataSize) continue;
- header.numTiles++;
- }
- memcpy(&header.params, mesh->getParams(), sizeof(dtNavMeshParams));
- fwrite(&header, sizeof(NavMeshSetHeader), 1, fp);
- // Store tiles.
- for (int i = 0; i < mesh->getMaxTiles(); ++i)
- {
- const dtMeshTile* tile = mesh->getTile(i);
- if (!tile || !tile->header || !tile->dataSize) continue;
- NavMeshTileHeader tileHeader;
- tileHeader.tileRef = mesh->getTileRef(tile);
- tileHeader.dataSize = tile->dataSize;
- fwrite(&tileHeader, sizeof(tileHeader), 1, fp);
- fwrite(tile->data, tile->dataSize, 1, fp);
- }
- fclose(fp);
- }
|