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:
Aurelien Rainone 2018-01-05 12:38:53 +01:00 committed by Jakob Botsch Nielsen
parent bda59b7c62
commit 4988ecbaf0
7 changed files with 154 additions and 114 deletions

View File

@ -132,6 +132,9 @@ protected:
SampleDebugDraw m_dd;
dtNavMesh* loadAll(const char* path);
void saveAll(const char* path, const dtNavMesh* mesh);
public:
Sample();
virtual ~Sample();

View File

@ -62,7 +62,7 @@ protected:
DrawMode m_drawMode;
void cleanup();
public:
Sample_SoloMesh();
virtual ~Sample_SoloMesh();

View File

@ -92,6 +92,7 @@ static char* parseRow(char* buf, char* bufEnd, char* row, int len)
case '\t':
case ' ':
if (start) break;
// else falls through
default:
start = false;
row[n++] = c;

View File

@ -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);
}

View File

@ -79,20 +79,38 @@ void Sample_SoloMesh::cleanup()
dtFreeNavMesh(m_navMesh);
m_navMesh = 0;
}
void Sample_SoloMesh::handleSettings()
{
Sample::handleCommonSettings();
if (imguiCheck("Keep Itermediate Results", m_keepInterResults))
m_keepInterResults = !m_keepInterResults;
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];
snprintf(msg, 64, "Build Time: %.1fms", m_totalBuildTimeMs);
imguiLabel(msg);
imguiSeparator();
}

View File

@ -242,114 +242,6 @@ struct NavMeshTileHeader
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()
{
Sample::handleCommonSettings();
@ -401,13 +293,13 @@ void Sample_TileMesh::handleSettings()
if (imguiButton("Save"))
{
saveAll("all_tiles_navmesh.bin", m_navMesh);
Sample::saveAll("all_tiles_navmesh.bin", m_navMesh);
}
if (imguiButton("Load"))
{
dtFreeNavMesh(m_navMesh);
m_navMesh = loadAll("all_tiles_navmesh.bin");
m_navMesh = Sample::loadAll("all_tiles_navmesh.bin");
m_navQuery->init(m_navMesh, 2048);
}

View File

@ -76,6 +76,7 @@ static char* parseRow(char* buf, char* bufEnd, char* row, int len)
case '\t':
case ' ':
if (start) break;
// else falls through
default:
start = false;
row[n++] = c;