So you are getting the "location not free" error? Then its an easy fix. When you create the tiles, you also assign a tile positon (dtNavMeshCreationParams.x/.y). The position is created by the double-for-loop inside buildAllTiles and used in the buildTileMesh method.
Code:
for (int y = 0; y < th; ++y)
{
for (int x = 0; x < tw; ++x)
{
m_tileBmin[0] = bmin[0] + x*tcs;
m_tileBmin[1] = bmin[1];
m_tileBmin[2] = bmin[2] + y*tcs;
m_tileBmax[0] = bmin[0] + (x+1)*tcs;
m_tileBmax[1] = bmax[1];
m_tileBmax[2] = bmin[2] + (y+1)*tcs;
int dataSize = 0;
unsigned char* data = buildTileMesh(x, y, m_tileBmin, m_tileBmax, dataSize);
Thats why you get that error :P Just calculate the TilePositon and use that instead. detour is using the following code to calculate the TilePosition by a given coordinate:
Code:
// DetourNavMesh.cpp, line 1115
void dtNavMesh::calcTileLoc(const float* pos, int* tx, int* ty) const
{
*tx = (int)floorf((pos[0]-m_orig[0]) / m_tileWidth);
*ty = (int)floorf((pos[2]-m_orig[2]) / m_tileHeight);
}
where pos is the position to look for a tile and m_orig is the nav_mesh origin. You can set the origin when create the nav_mesh. I'm using these values:
Code:
dtNavMeshParams params;
params.maxPolys = MaxPoly;
params.maxTiles = MaxTiles;
params.tileWidth = (GRID_SIZE / 4);
params.tileHeight = (GRID_SIZE / 4);
params.orig[0] = -(32 * GRID_SIZE);
params.orig[1] = 0;
params.orig[2] = -(32 * GRID_SIZE);
GRID_SIZE = 1600.0f / 3.0f
and this is my buildAllTiles Function
Code:
bool buildAllTiles(float* bounds)
{
if (!m_geom) return false;
if (!m_navMesh) return false;
const float* bmin = bounds;
const float* bmax = &bounds[3];
int gw = 0, gh = 0;
rcCalcGridSize(bmin, bmax, CellSize, &gw, &gh);
const int ts = (int)TileSize;
const int tw = (int)((gw + ts-1) / ts);
const int th = (int)((gh + ts-1) / ts);
const float tcs = TileSize / GridDiv;
float m_tileBmin[3];
float m_tileBmax[3];
for (int y = 0; y < th; ++y)
{
for (int x = 0; x < tw; ++x)
{
m_tileBmin[0] = bmin[0] + x*tcs;
m_tileBmin[1] = bmin[1];
m_tileBmin[2] = bmin[2] + y*tcs;
m_tileBmax[0] = bmin[0] + (x+1)*tcs;
m_tileBmax[1] = bmax[1];
m_tileBmax[2] = bmin[2] + (y+1)*tcs;
int tx = (int)floorf((m_tileBmin[0]-(-32 * GRID_SIZE)) / (TileSize / GridDiv));
int ty = (int)floorf((m_tileBmin[2]-(-32 * GRID_SIZE)) / (TileSize / GridDiv));
Console::WriteLine("Building Tile {0} / {1} for ADT_{2}_{3}", tx, ty, ty / 4, tx / 4);
int dataSize = 0;
unsigned char* data = buildTileMesh(tx, ty, m_tileBmin, m_tileBmax, dataSize);
if (data)
{
// Remove any previous data (navmesh owns and deletes the data).
m_navMesh->removeTile(m_navMesh->getTileRefAt(tx,ty,0),0,0);
// Let the navmesh own the data.
dtStatus status = m_navMesh->addTile(data,dataSize,DT_TILE_FREE_DATA,0,0);
if (dtStatusFailed(status))
{
Console::WriteLine("Error on m_navMesh->addTile()");
dtFree(data);
return false;
}
}
}
}
return true;
}