Trying to fix prunetool svn weirdness.

This commit is contained in:
Mikko Mononen 2012-10-21 15:51:58 +00:00
parent 30aed0538e
commit 4c6b604ca3
2 changed files with 10 additions and 387 deletions

View File

@ -1,349 +0,0 @@
//
// 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 <string.h>
#include <float.h>
#include "SDL.h"
#include "SDL_opengl.h"
#include "imgui.h"
#include "NavMeshPruneTool.h"
#include "InputGeom.h"
#include "Sample.h"
#include "DetourNavMesh.h"
#include "DetourCommon.h"
#include "DetourAssert.h"
#include "DetourDebugDraw.h"
#ifdef WIN32
# define snprintf _snprintf
#endif
// Copy/paste from Recast int array
class PolyRefArray
{
dtPolyRef* m_data;
int m_size, m_cap;
inline PolyRefArray(const PolyRefArray&);
inline PolyRefArray& operator=(const PolyRefArray&);
public:
inline PolyRefArray() : m_data(0), m_size(0), m_cap(0) {}
inline PolyRefArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); }
inline ~PolyRefArray() { dtFree(m_data); }
void resize(int n)
{
if (n > m_cap)
{
if (!m_cap) m_cap = n;
while (m_cap < n) m_cap *= 2;
dtPolyRef* newData = (dtPolyRef*)dtAlloc(m_cap*sizeof(dtPolyRef), DT_ALLOC_TEMP);
if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(dtPolyRef));
dtFree(m_data);
m_data = newData;
}
m_size = n;
}
inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; }
inline dtPolyRef pop() { if (m_size > 0) m_size--; return m_data[m_size]; }
inline const dtPolyRef& operator[](int i) const { return m_data[i]; }
inline dtPolyRef& operator[](int i) { return m_data[i]; }
inline int size() const { return m_size; }
};
class NavmeshFlags
{
struct TileFlags
{
inline void purge() { dtFree(flags); }
unsigned char* flags;
int nflags;
dtPolyRef base;
};
const dtNavMesh* m_nav;
TileFlags* m_tiles;
int m_ntiles;
public:
NavmeshFlags() :
m_nav(0), m_tiles(0), m_ntiles(0)
{
}
~NavmeshFlags()
{
for (int i = 0; i < m_ntiles; ++i)
m_tiles[i].purge();
dtFree(m_tiles);
}
bool init(const dtNavMesh* nav)
{
m_ntiles = nav->getMaxTiles();
if (!m_ntiles)
return true;
m_tiles = (TileFlags*)dtAlloc(sizeof(TileFlags)*m_ntiles, DT_ALLOC_TEMP);
if (!m_tiles)
{
return false;
}
memset(m_tiles, 0, sizeof(TileFlags)*m_ntiles);
// Alloc flags for each tile.
for (int i = 0; i < nav->getMaxTiles(); ++i)
{
const dtMeshTile* tile = nav->getTile(i);
if (!tile->header) continue;
TileFlags* tf = &m_tiles[i];
tf->nflags = tile->header->polyCount;
tf->base = nav->getPolyRefBase(tile);
if (tf->nflags)
{
tf->flags = (unsigned char*)dtAlloc(tf->nflags, DT_ALLOC_TEMP);
if (!tf->flags)
return false;
memset(tf->flags, 0, tf->nflags);
}
}
m_nav = nav;
return false;
}
inline void clearAllFlags()
{
for (int i = 0; i < m_ntiles; ++i)
{
TileFlags* tf = &m_tiles[i];
if (tf->nflags)
memset(tf->flags, 0, tf->nflags);
}
}
inline unsigned char getFlags(dtPolyRef ref)
{
dtAssert(m_nav);
dtAssert(m_ntiles);
// Assume the ref is valid, no bounds checks.
unsigned int salt, it, ip;
m_nav->decodePolyId(ref, salt, it, ip);
return m_tiles[it].flags[ip];
}
inline void setFlags(dtPolyRef ref, unsigned char flags)
{
dtAssert(m_nav);
dtAssert(m_ntiles);
// Assume the ref is valid, no bounds checks.
unsigned int salt, it, ip;
m_nav->decodePolyId(ref, salt, it, ip);
m_tiles[it].flags[ip] = flags;
}
};
static void floodNavmesh(dtNavMesh* nav, NavmeshFlags* flags, dtPolyRef start, unsigned char flag)
{
// If already visited, skip.
if (flags->getFlags(start))
return;
PolyRefArray openList;
openList.push(start);
while (openList.size())
{
const dtPolyRef ref = openList.pop();
// Get current poly and tile.
// The API input has been cheked already, skip checking internal data.
const dtMeshTile* tile = 0;
const dtPoly* poly = 0;
nav->getTileAndPolyByRefUnsafe(ref, &tile, &poly);
// Visit linked polygons.
for (unsigned int i = poly->firstLink; i != DT_NULL_LINK; i = tile->links[i].next)
{
const dtPolyRef neiRef = tile->links[i].ref;
// Skip invalid and already visited.
if (!neiRef || flags->getFlags(neiRef))
continue;
// Mark as visited
flags->setFlags(neiRef, flag);
// Visit neighbours
openList.push(neiRef);
}
}
}
static void disableUnvisitedPolys(dtNavMesh* nav, NavmeshFlags* flags)
{
for (int i = 0; i < nav->getMaxTiles(); ++i)
{
const dtMeshTile* tile = ((const dtNavMesh*)nav)->getTile(i);
if (!tile->header) continue;
const dtPolyRef base = nav->getPolyRefBase(tile);
for (int j = 0; j < tile->header->polyCount; ++j)
{
const dtPolyRef ref = base | (unsigned int)j;
if (!flags->getFlags(ref))
{
unsigned short f = 0;
nav->getPolyFlags(ref, &f);
nav->setPolyFlags(ref, f | SAMPLE_POLYFLAGS_DISABLED);
}
}
}
}
NavMeshPruneTool::NavMeshPruneTool() :
m_flags(0),
m_hitPosSet(false)
{
}
NavMeshPruneTool::~NavMeshPruneTool()
{
delete m_flags;
}
void NavMeshPruneTool::init(Sample* sample)
{
m_sample = sample;
}
void NavMeshPruneTool::reset()
{
m_hitPosSet = false;
delete m_flags;
m_flags = 0;
}
void NavMeshPruneTool::handleMenu()
{
dtNavMesh* nav = m_sample->getNavMesh();
if (!nav) return;
if (!m_flags) return;
if (imguiButton("Clear Selection"))
{
m_flags->clearAllFlags();
}
if (imguiButton("Prune Unselected"))
{
disableUnvisitedPolys(nav, m_flags);
delete m_flags;
m_flags = 0;
}
}
void NavMeshPruneTool::handleClick(const float* /*s*/, const float* p, bool shift)
{
if (!m_sample) return;
InputGeom* geom = m_sample->getInputGeom();
if (!geom) return;
dtNavMesh* nav = m_sample->getNavMesh();
if (!nav) return;
dtNavMeshQuery* query = m_sample->getNavMeshQuery();
if (!query) return;
dtVcopy(m_hitPos, p);
m_hitPosSet = true;
if (!m_flags)
{
m_flags = new NavmeshFlags;
m_flags->init(nav);
}
const float ext[3] = {2,4,2};
dtQueryFilter filter;
dtPolyRef ref = 0;
query->findNearestPoly(p, ext, &filter, &ref, 0);
floodNavmesh(nav, m_flags, ref, 1);
}
void NavMeshPruneTool::handleToggle()
{
}
void NavMeshPruneTool::handleStep()
{
}
void NavMeshPruneTool::handleUpdate(const float /*dt*/)
{
}
void NavMeshPruneTool::handleRender()
{
DebugDrawGL dd;
if (m_hitPosSet)
{
const float s = m_sample->getAgentRadius();
const unsigned int col = duRGBA(255,255,255,255);
dd.begin(DU_DRAW_LINES);
dd.vertex(m_hitPos[0]-s,m_hitPos[1],m_hitPos[2], col);
dd.vertex(m_hitPos[0]+s,m_hitPos[1],m_hitPos[2], col);
dd.vertex(m_hitPos[0],m_hitPos[1]-s,m_hitPos[2], col);
dd.vertex(m_hitPos[0],m_hitPos[1]+s,m_hitPos[2], col);
dd.vertex(m_hitPos[0],m_hitPos[1],m_hitPos[2]-s, col);
dd.vertex(m_hitPos[0],m_hitPos[1],m_hitPos[2]+s, col);
dd.end();
}
const dtNavMesh* nav = m_sample->getNavMesh();
if (m_flags && nav)
{
for (int i = 0; i < nav->getMaxTiles(); ++i)
{
const dtMeshTile* tile = nav->getTile(i);
if (!tile->header) continue;
const dtPolyRef base = nav->getPolyRefBase(tile);
for (int j = 0; j < tile->header->polyCount; ++j)
{
const dtPolyRef ref = base | (unsigned int)j;
if (m_flags->getFlags(ref))
{
duDebugDrawNavMeshPoly(&dd, *nav, ref, duRGBA(255,255,255,128));
}
}
}
}
}
void NavMeshPruneTool::handleRenderOverlay(double* proj, double* model, int* view)
{
// Tool help
const int h = view[3];
imguiDrawText(280, h-40, IMGUI_ALIGN_LEFT, "LMB: Click fill area.", imguiRGBA(255,255,255,192));
}

View File

@ -50,7 +50,6 @@ static int loadBin(const char* path, unsigned char** data)
*/
Sample_Debug::Sample_Debug() :
m_chf(0),
m_cset(0),
m_pmesh(0)
{
@ -138,7 +137,7 @@ Sample_Debug::Sample_Debug() :
if (m_cset)
{
FileIO io;
if (io.openForRead("PathSet_TMP_NA_PathingTestAReg1_1_2_CS.rc"))
if (io.openForRead("dump.cset"))
{
duReadContourSet(*m_cset, &io);
@ -146,33 +145,23 @@ Sample_Debug::Sample_Debug() :
m_cset->bmin[0], m_cset->bmin[1], m_cset->bmin[2],
m_cset->bmax[0], m_cset->bmax[1], m_cset->bmax[2]);
printf("cs=%f ch=%f\n", m_cset->cs, m_cset->ch);
m_cset->bmax[1] *= 0.1f;
}
else
{
printf("could not open test.cset\n");
printf("could not open dump.cset\n");
}
}
else
{
printf("Could not alloc cset\n");
}
/* if (m_cset)
{
m_pmesh = rcAllocPolyMesh();
if (m_pmesh)
{
rcBuildPolyMesh(m_ctx, *m_cset, 6, *m_pmesh);
}
}*/
}
}
Sample_Debug::~Sample_Debug()
{
rcFreeCompactHeightfield(m_chf);
rcFreeContourSet(m_cset);
rcFreePolyMesh(m_pmesh);
}
@ -193,12 +182,6 @@ void Sample_Debug::handleRender()
{
DebugDrawGL dd;
if (m_chf)
{
duDebugDrawCompactHeightfieldRegions(&dd, *m_chf);
// duDebugDrawCompactHeightfieldSolid(&dd, *m_chf);
}
if (m_navMesh)
duDebugDrawNavMesh(&dd, *m_navMesh, DU_DRAWNAVMESH_OFFMESHCONS);
@ -215,6 +198,9 @@ void Sample_Debug::handleRender()
{
duDebugDrawRawContours(&dd, *m_cset, 0.25f);
duDebugDrawContours(&dd, *m_cset);
const float* bmin = m_cset->bmin;
const float* bmax = m_cset->bmax;
duDebugDrawBoxWire(&dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], duRGBA(255,255,255,128), 1.0f);
}
if (m_pmesh)
@ -333,8 +319,6 @@ const float* Sample_Debug::getBoundsMin()
{
if (m_cset)
return m_cset->bmin;
if (m_chf)
return m_chf->bmin;
if (m_navMesh)
return m_bmin;
return 0;
@ -344,8 +328,6 @@ const float* Sample_Debug::getBoundsMax()
{
if (m_cset)
return m_cset->bmax;
if (m_chf)
return m_chf->bmax;
if (m_navMesh)
return m_bmax;
return 0;
@ -366,22 +348,12 @@ void Sample_Debug::handleToggle()
bool Sample_Debug::handleBuild()
{
if (m_chf)
if (m_cset)
{
rcFreeContourSet(m_cset);
m_cset = 0;
// Create contours.
m_cset = rcAllocContourSet();
if (!m_cset)
m_pmesh = rcAllocPolyMesh();
if (m_pmesh)
{
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'cset'.");
return false;
}
if (!rcBuildContours(m_ctx, *m_chf, /*m_cfg.maxSimplificationError*/1.3f, /*m_cfg.maxEdgeLen*/12, *m_cset))
{
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create contours.");
return false;
rcBuildPolyMesh(m_ctx, *m_cset, 6, *m_pmesh);
}
}