RecastDemo: add Load & Save buttons for SoloMesh Sample, and fix warnings (#258)
* Implement saveAll loadAll for Sample_SoloMesh - Solo mesh sample is loaded and saved as a tiled mesh containing an unique tile, so as to remain compatible with tiled mesh - navmesh is saved to/loaded from `solo_navmesh.bin` binary file - add and connect the corresponding 'Save/Load' GUI elements * Fix `implit-fallthrough` gcc warnings On linux with gcc 7.2.0+ and all warnings treated as errors, implicit fallthroughs in case statements are considered as errors. If the comment just below the next `case` or `default` matches various strings, one of which is `falls through` the fallthrough is then considered explicit.
This commit is contained in:
parent
bda59b7c62
commit
4988ecbaf0
@ -132,6 +132,9 @@ protected:
|
|||||||
|
|
||||||
SampleDebugDraw m_dd;
|
SampleDebugDraw m_dd;
|
||||||
|
|
||||||
|
dtNavMesh* loadAll(const char* path);
|
||||||
|
void saveAll(const char* path, const dtNavMesh* mesh);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sample();
|
Sample();
|
||||||
virtual ~Sample();
|
virtual ~Sample();
|
||||||
|
@ -62,7 +62,7 @@ protected:
|
|||||||
DrawMode m_drawMode;
|
DrawMode m_drawMode;
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sample_SoloMesh();
|
Sample_SoloMesh();
|
||||||
virtual ~Sample_SoloMesh();
|
virtual ~Sample_SoloMesh();
|
||||||
|
@ -92,6 +92,7 @@ static char* parseRow(char* buf, char* bufEnd, char* row, int len)
|
|||||||
case '\t':
|
case '\t':
|
||||||
case ' ':
|
case ' ':
|
||||||
if (start) break;
|
if (start) break;
|
||||||
|
// else falls through
|
||||||
default:
|
default:
|
||||||
start = false;
|
start = false;
|
||||||
row[n++] = c;
|
row[n++] = c;
|
||||||
|
@ -322,3 +322,128 @@ void Sample::renderOverlayToolStates(double* proj, double* model, int* 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);
|
||||||
|
}
|
||||||
|
@ -79,20 +79,38 @@ void Sample_SoloMesh::cleanup()
|
|||||||
dtFreeNavMesh(m_navMesh);
|
dtFreeNavMesh(m_navMesh);
|
||||||
m_navMesh = 0;
|
m_navMesh = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sample_SoloMesh::handleSettings()
|
void Sample_SoloMesh::handleSettings()
|
||||||
{
|
{
|
||||||
Sample::handleCommonSettings();
|
Sample::handleCommonSettings();
|
||||||
|
|
||||||
if (imguiCheck("Keep Itermediate Results", m_keepInterResults))
|
if (imguiCheck("Keep Itermediate Results", m_keepInterResults))
|
||||||
m_keepInterResults = !m_keepInterResults;
|
m_keepInterResults = !m_keepInterResults;
|
||||||
|
|
||||||
imguiSeparator();
|
imguiSeparator();
|
||||||
|
|
||||||
|
imguiIndent();
|
||||||
|
imguiIndent();
|
||||||
|
|
||||||
|
if (imguiButton("Save"))
|
||||||
|
{
|
||||||
|
Sample::saveAll("solo_navmesh.bin", m_navMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imguiButton("Load"))
|
||||||
|
{
|
||||||
|
dtFreeNavMesh(m_navMesh);
|
||||||
|
m_navMesh = Sample::loadAll("solo_navmesh.bin");
|
||||||
|
m_navQuery->init(m_navMesh, 2048);
|
||||||
|
}
|
||||||
|
|
||||||
|
imguiUnindent();
|
||||||
|
imguiUnindent();
|
||||||
|
|
||||||
char msg[64];
|
char msg[64];
|
||||||
snprintf(msg, 64, "Build Time: %.1fms", m_totalBuildTimeMs);
|
snprintf(msg, 64, "Build Time: %.1fms", m_totalBuildTimeMs);
|
||||||
imguiLabel(msg);
|
imguiLabel(msg);
|
||||||
|
|
||||||
imguiSeparator();
|
imguiSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,114 +242,6 @@ struct NavMeshTileHeader
|
|||||||
int dataSize;
|
int dataSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Sample_TileMesh::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);
|
|
||||||
}
|
|
||||||
|
|
||||||
dtNavMesh* Sample_TileMesh::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)
|
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sample_TileMesh::handleSettings()
|
void Sample_TileMesh::handleSettings()
|
||||||
{
|
{
|
||||||
Sample::handleCommonSettings();
|
Sample::handleCommonSettings();
|
||||||
@ -401,13 +293,13 @@ void Sample_TileMesh::handleSettings()
|
|||||||
|
|
||||||
if (imguiButton("Save"))
|
if (imguiButton("Save"))
|
||||||
{
|
{
|
||||||
saveAll("all_tiles_navmesh.bin", m_navMesh);
|
Sample::saveAll("all_tiles_navmesh.bin", m_navMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imguiButton("Load"))
|
if (imguiButton("Load"))
|
||||||
{
|
{
|
||||||
dtFreeNavMesh(m_navMesh);
|
dtFreeNavMesh(m_navMesh);
|
||||||
m_navMesh = loadAll("all_tiles_navmesh.bin");
|
m_navMesh = Sample::loadAll("all_tiles_navmesh.bin");
|
||||||
m_navQuery->init(m_navMesh, 2048);
|
m_navQuery->init(m_navMesh, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ static char* parseRow(char* buf, char* bufEnd, char* row, int len)
|
|||||||
case '\t':
|
case '\t':
|
||||||
case ' ':
|
case ' ':
|
||||||
if (start) break;
|
if (start) break;
|
||||||
|
// else falls through
|
||||||
default:
|
default:
|
||||||
start = false;
|
start = false;
|
||||||
row[n++] = c;
|
row[n++] = c;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user