Skip to content

Instantly share code, notes, and snippets.

@vermie
Created December 2, 2010 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vermie/726329 to your computer and use it in GitHub Desktop.
Save vermie/726329 to your computer and use it in GitHub Desktop.
solomesh tile approach
diff --git a/contrib/mmap/src/MapBuilder.cpp b/contrib/mmap/src/MapBuilder.cpp
index 43330f5..453b936 100644
--- a/contrib/mmap/src/MapBuilder.cpp
+++ b/contrib/mmap/src/MapBuilder.cpp
@@ -650,10 +650,9 @@ namespace MMAP
// old code for non-statically assigned bitmask sizes:
///*** calculate number of bits needed to store tiles & polys ***/
- //uint32 tileCount = tiles->size() * rcSqr(TILES_PER_MMTILE);
- //tileBits = dtIlog2(dtNextPow2(tileCount);
+ //int tileBits = dtIlog2(dtNextPow2(tiles->size()));
//if (tileBits < 1) tileBits = 1; // need at least one bit!
- //polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits;
+ //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits;
int tileBits = STATIC_TILE_BITS;
int polyBits = STATIC_POLY_BITS;
@@ -689,8 +688,8 @@ namespace MMAP
// navmesh creation params
dtNavMeshParams navMeshParams;
memset(&navMeshParams, 0, sizeof(dtNavMeshParams));
- navMeshParams.tileWidth = GRID_SIZE / TILES_PER_MMTILE;
- navMeshParams.tileHeight = GRID_SIZE / TILES_PER_MMTILE;
+ navMeshParams.tileWidth = GRID_SIZE;
+ navMeshParams.tileHeight = GRID_SIZE;
rcVcopy(navMeshParams.orig, bmin);
navMeshParams.maxTiles = maxTiles;
navMeshParams.maxPolys = maxPolysPerTile;
@@ -728,27 +727,7 @@ namespace MMAP
// console output
char tileString[10];
sprintf(tileString, "[%02i,%02i]: ", tileX, tileY);
-
- // open the file for writing
- char fileName[255];
- sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX);
- FILE* file = fopen(fileName, "wb");
- if (!file)
- {
- char message[1024];
- sprintf(message, "Failed to open %s for writing!\n", fileName);
- perror(message);
- return;
- }
-
- mmapTileHeader header(m_terrainBuilder);
- fwrite(&header, sizeof(header), 1, file);
-
- float cellSize = 0.5f; // larger number => less voxels => faster build time
- // too large, and tight spaces won't be pathable.
- float agentHeight = 1.5f;
- float agentRadius = 0.5f;
- float agentMaxClimb = 1.65f;
+ printf("%s Building movemap tiles... \r", tileString);
IntermediateValues iv;
initIntermediateValues(iv);
@@ -764,316 +743,352 @@ namespace MMAP
int lTriCount = meshData.liquidTris.size() / 3;
uint8* lTriFlags = meshData.liquidType.getCArray();
- // init detour tile bounds
- float tileMin[3], tileMax[3];
- rcVcopy(tileMin, bmin);
- rcVcopy(tileMax, bmax);
+ // these are WORLD UNIT based metrics
+ // this are basic unit dimentions
+ // value have to divide GRID_SIZE(533.33333f) ( aka: 0.5333, 0.3333, 0.1333, etc )
+ const static float BASE_UNIT_DIM = 0.53333333f;
+
+ // All are in UNIT metrics!
+ const static int VERTEX_PER_MAP = int(GRID_SIZE/BASE_UNIT_DIM + 0.5f);
+ const static int VERTEX_PER_TILE = 40; // must divide VERTEX_PER_MAP
+ const static int TILES_PER_MAP = VERTEX_PER_MAP/VERTEX_PER_TILE;
- /* init mmtile config */
rcConfig config;
memset(&config, 0, sizeof(rcConfig));
- config.maxVertsPerPoly = 6;
- // these are WORLD UNIT based metrics
- config.cs = cellSize;
- config.ch = .3f;
- config.walkableSlopeAngle = m_maxWalkableAngle;
+ rcVcopy(config.bmin, bmin);
+ rcVcopy(config.bmax, bmax);
- // these are VOXEL-based metrics
- config.tileSize = (int)ceilf(TILE_SIZE / config.cs);
- config.walkableRadius = (int)ceilf(agentRadius / config.cs);
+ config.maxVertsPerPoly = DT_VERTS_PER_POLYGON;
+ config.cs = BASE_UNIT_DIM;
+ config.ch = BASE_UNIT_DIM;
+ config.walkableSlopeAngle = m_maxWalkableAngle;
+ config.tileSize = VERTEX_PER_TILE;
+ config.walkableRadius = 1;
config.borderSize = config.walkableRadius + 3;
- config.maxEdgeLen = 1500;
- config.walkableHeight = (int)ceilf(agentHeight / config.ch);
- config.walkableClimb = (int)ceilf(agentHeight / config.ch);
- config.minRegionArea = (int)rcSqr(50);
- config.mergeRegionArea = (int)rcSqr(20);
- config.maxSimplificationError = 1.3f;
- config.detailSampleDist = config.cs * 16.f;
- config.detailSampleMaxError = config.ch * 1.f;
-
- vector<dtTileRef> finishedTiles;
-
- for (uint32 x = 0; x < TILES_PER_MMTILE; ++x)
+ config.maxEdgeLen = VERTEX_PER_TILE + 1; //anything bigger than tileSize
+ config.walkableHeight = 3;
+ config.walkableClimb = 2; // keep less than walkableHeight
+ config.minRegionArea = rcSqr(50);
+ config.mergeRegionArea = rcSqr(30);
+ config.maxSimplificationError = 2.5f; // eliminates most jagged edges (tinny polygons)
+ config.detailSampleDist = config.cs * 8;
+ config.detailSampleMaxError = config.ch * 2;
+
+ // this sets the dimensions of the heightfield - should maybe happen before border padding
+ rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
+
+ // allocate subregions : tiles
+ TileSet* tileSet = new TileSet;
+ rcVcopy(tileSet->bmin, config.bmin);
+ rcVcopy(tileSet->bmax, config.bmax);
+ tileSet->cs = config.cs;
+ tileSet->ch = config.ch;
+ tileSet->width = TILES_PER_MAP;
+ tileSet->height = TILES_PER_MAP;
+ tileSet->tiles = new Tile[tileSet->height * tileSet->width];
+
+ // Initialize per tile config.
+ rcConfig tileCfg;
+ memcpy(&tileCfg, &config, sizeof(rcConfig));
+ tileCfg.width = config.tileSize + config.borderSize*2;
+ tileCfg.height = config.tileSize + config.borderSize*2;
+
+ // build all tiles
+ for (int y = 0; y < tileSet->height; ++y)
{
- tileMin[0] = bmin[0] + TILE_SIZE * x;
- tileMax[0] = tileMin[0] + TILE_SIZE;
-
- for (uint32 y = 0; y < TILES_PER_MMTILE; ++y)
+ for (int x = 0; x < tileSet->width; ++x)
{
- tileMin[2] = bmin[2] + TILE_SIZE * y;
- tileMax[2] = tileMin[2] + TILE_SIZE;
-
- clearIntermediateValues(iv);
-
- /* tile-specific config settings */
- rcVcopy(config.bmin, tileMin);
- rcVcopy(config.bmax, tileMax);
-
- // pad bounds with a border
- float pad = config.borderSize*config.cs;
- config.bmin[0] -= pad;
- config.bmin[2] -= pad;
- config.bmax[0] += pad;
- config.bmax[2] += pad;
-
- // this sets the dimensions of the heightfield - should maybe happen before border padding
- rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
-
- /* start build */
+ Tile& tile = tileSet->tiles[x + y*tileSet->width];
+ tile.x = x;
+ tile.y = y;
+
+ // Calculate the per tile bounding box.
+ tileCfg.bmin[0] = config.bmin[0] + (x*config.tileSize - config.borderSize)*config.cs;
+ tileCfg.bmin[2] = config.bmin[2] + (y*config.tileSize - config.borderSize)*config.cs;
+ tileCfg.bmax[0] = config.bmin[0] + ((x+1)*config.tileSize + config.borderSize)*config.cs;
+ tileCfg.bmax[2] = config.bmin[2] + ((y+1)*config.tileSize + config.borderSize)*config.cs;
+
+ float tbmin[2], tbmax[2];
+ tbmin[0] = tileCfg.bmin[0];
+ tbmin[1] = tileCfg.bmin[2];
+ tbmax[0] = tileCfg.bmax[0];
+ tbmax[1] = tileCfg.bmax[2];
// build heightfield
- printf("%sBuilding Recast Heightfield... \r", tileString);
- iv.heightfield = rcAllocHeightfield();
- if (!iv.heightfield || !rcCreateHeightfield(m_rcContext, *iv.heightfield, config.width, config.height, config.bmin, config.bmax, config.cs, config.ch))
+ tile.solid = rcAllocHeightfield();
+ if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch))
{
printf("%sFailed building heightfield! \n", tileString);
continue;
}
- printf("%sRasterizing triangles... \r", tileString);
-
- // flag walkable terrain triangles
- iv.triFlags = (unsigned char*)dtAlloc(sizeof(unsigned char)*tTriCount, DT_ALLOC_PERM);
- memset(iv.triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char));
- rcClearUnwalkableTriangles(m_rcContext, config.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, iv.triFlags);
- rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, iv.triFlags, tTriCount, *iv.heightfield, config.walkableClimb);
- dtFree(iv.triFlags);
- iv.triFlags = NULL;
+ // mark all walkable tiles, both liquids and solids
+ unsigned char* triFlags = new unsigned char[tTriCount];
+ memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char));
+ rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
+ rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
+ delete [] triFlags;
- // filter out unwalkable spans (order of calls matters, see rcFilterLowHangingWalkableObstacles)
- rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *iv.heightfield);
- rcFilterLedgeSpans(m_rcContext, config.walkableHeight, config.walkableClimb, *iv.heightfield);
- rcFilterWalkableLowHeightSpans(m_rcContext, config.walkableHeight, *iv.heightfield);
+ rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *tile.solid);
+ rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
+ rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid);
- // do after filtering because same rules don't apply to swimming
- rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *iv.heightfield, config.walkableClimb);
+ rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb);
// compact heightfield spans
- printf("%sCompacting heightfield... \r", tileString);
- iv.compactHeightfield = rcAllocCompactHeightfield();
- if (!iv.compactHeightfield || !rcBuildCompactHeightfield(m_rcContext, config.walkableHeight, config.walkableClimb, *iv.heightfield, *iv.compactHeightfield))
+ tile.chf = rcAllocCompactHeightfield();
+ if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf))
{
printf("%sFailed compacting heightfield! \n", tileString);
continue;
}
- if (!m_debugOutput)
- {
- rcFreeHeightField(iv.heightfield);
- iv.heightfield = NULL;
- }
-
// build polymesh intermediates
- printf("%sEroding walkable area width... \r", tileString);
- if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *iv.compactHeightfield))
+ if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf))
{
printf("%sFailed eroding area! \n", tileString);
continue;
}
- printf("%sSmoothing area boundaries... \r", tileString);
- if (!rcMedianFilterWalkableArea(m_rcContext, *iv.compactHeightfield))
- {
- printf("%sFailed median filter! \n", tileString);
- continue;
- }
-
- printf("%sBuilding distance field... \r", tileString);
- if (!rcBuildDistanceField(m_rcContext, *iv.compactHeightfield))
+ if (!rcBuildDistanceField(m_rcContext, *tile.chf))
{
printf("%sFailed building distance field! \n", tileString);
continue;
}
- // bottleneck is here
- printf("%sBuilding regions... \r", tileString);
- if (!rcBuildRegions(m_rcContext, *iv.compactHeightfield, config.borderSize, config.minRegionArea, config.mergeRegionArea))
+ if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea))
{
printf("%sFailed building regions! \n", tileString);
continue;
}
- printf("%sBuilding contours... \r", tileString);
- iv.contours = rcAllocContourSet();
- if (!iv.contours || !rcBuildContours(m_rcContext, *iv.compactHeightfield, config.maxSimplificationError, config.maxEdgeLen, *iv.contours))
+ tile.cset = rcAllocContourSet();
+ if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset))
{
printf("%sFailed building contours! \n", tileString);
continue;
}
// build polymesh
- printf("%sBuilding polymesh... \r", tileString);
- iv.polyMesh = rcAllocPolyMesh();
- if (!iv.polyMesh || !rcBuildPolyMesh(m_rcContext, *iv.contours, config.maxVertsPerPoly, *iv.polyMesh))
+ tile.pmesh = rcAllocPolyMesh();
+ if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh))
{
printf("%sFailed building polymesh! \n", tileString);
continue;
}
- printf("%sBuilding polymesh detail... \r", tileString);
- iv.polyMeshDetail = rcAllocPolyMeshDetail();
- if (!iv.polyMeshDetail || !rcBuildPolyMeshDetail(m_rcContext, *iv.polyMesh, *iv.compactHeightfield, config.detailSampleDist, config.detailSampleMaxError, *iv.polyMeshDetail))
+ tile.dmesh = rcAllocPolyMeshDetail();
+ if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg .detailSampleMaxError, *tile.dmesh))
{
printf("%sFailed building polymesh detail! \n", tileString);
continue;
}
- if (!m_debugOutput)
- {
- rcFreeCompactHeightfield(iv.compactHeightfield);
- iv.compactHeightfield = NULL;
- rcFreeContourSet(iv.contours);
- iv.contours = NULL;
- }
+ // free those up
+ // we may want to keep them in the future for debug
+ // but right now, we don't have the code to merge them
+ rcFreeHeightField(tile.solid);
+ tile.solid = NULL;
+ rcFreeCompactHeightfield(tile.chf);
+ tile.chf = NULL;
+ rcFreeContourSet(tile.cset);
+ tile.cset = NULL;
+ }
+ }
- // this might be handled within Recast at some point
- // very important, without this tiles do not get connected to neighbors!!
- printf("%sCleaning vertex padding... \r", tileString);
- for (int i = 0; i < iv.polyMesh->nverts; ++i)
- {
- unsigned short* v = &iv.polyMesh->verts[i*3];
- v[0] -= (unsigned short)config.borderSize;
- v[2] -= (unsigned short)config.borderSize;
- }
+ // merge per tile poly and detail meshes
+ rcPolyMesh** pmmerge = new rcPolyMesh*[tileSet->width*tileSet->height];
+ if (!pmmerge)
+ {
+ printf("%s alloc pmmerge FIALED! \r", tileString);
+ return;
+ }
- // polymesh vertex indices are stored with ushorts in detour, can't have more than 65535
- if (iv.polyMesh->nverts >= 0xffff)
- {
- printf("%sToo many vertices! \n", tileString);
- continue;
- }
+ rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[tileSet->width*tileSet->height];
+ if (!dmmerge)
+ {
+ printf("%s alloc dmmerge FIALED! \r", tileString);
+ return;
+ }
- printf("%sSetting polys as walkable... \r", tileString);
- // handle area type here
- // TODO: special flag for DYNAMIC polygons, ie surfaces that can be turned on and off
- for (int i = 0; i < iv.polyMesh->npolys; ++i)
- if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
- iv.polyMesh->flags[i] = iv.polyMesh->areas[i];
-
- dtNavMeshCreateParams params;
- memset(&params, 0, sizeof(params));
- params.verts = iv.polyMesh->verts;
- params.vertCount = iv.polyMesh->nverts;
- params.polys = iv.polyMesh->polys;
- params.polyAreas = iv.polyMesh->areas;
- params.polyFlags = iv.polyMesh->flags;
- params.polyCount = iv.polyMesh->npolys;
- params.nvp = iv.polyMesh->nvp;
- params.detailMeshes = iv.polyMeshDetail->meshes;
- params.detailVerts = iv.polyMeshDetail->verts;
- params.detailVertsCount = iv.polyMeshDetail->nverts;
- params.detailTris = iv.polyMeshDetail->tris;
- params.detailTriCount = iv.polyMeshDetail->ntris;
- params.walkableHeight = agentHeight;
- params.walkableRadius = agentRadius;
- params.walkableClimb = agentMaxClimb;
- float pos[3] = {(tileMin[0] + tileMax[0]) / 2, 0.f, (tileMin[2] + tileMax[2]) / 2}; // center of current dtTile
- navMesh->calcTileLoc(pos, &params.tileX, &params.tileY);
- rcVcopy(params.bmin, tileMin);
- rcVcopy(params.bmax, tileMax);
- params.cs = config.cs;
- params.ch = config.ch;
- params.tileSize = config.tileSize;
-
- // will hold final navmesh
- unsigned char* navData = NULL;
- int navDataSize = 0;
-
- // these values are checked within dtCreateNavMeshData - handle them here
- // so we have a clear error message
- if (params.nvp > DT_VERTS_PER_POLYGON)
- {
- printf("%sInvalid verts-per-polygon value! \n", tileString);
- continue;
- }
- if (params.vertCount >= 0xffff)
+ int nmerge = 0;
+ for (int y = 0; y < tileSet->height; ++y)
+ {
+ for (int x = 0; x < tileSet->width; ++x)
+ {
+ Tile& tile = tileSet->tiles[x + y*tileSet->width];
+ if (tile.pmesh)
{
- printf("%sToo many vertices! \n", tileString);
- continue;
+ pmmerge[nmerge] = tile.pmesh;
+ dmmerge[nmerge] = tile.dmesh;
+ nmerge++;
}
- if (!params.vertCount || !params.verts)
- {
- // occurs mostly when adjacent tiles have models
- // loaded but those models don't span into this tile
+ }
+ }
- // message is an annoyance
- //printf("%sNo vertices to build tile! \n", tileString);
- continue;
- }
- if (!params.polyCount || !params.polys)
- {
- printf("%sNo polygons to build tile! \n", tileString);
- continue;
- }
- if (!params.detailMeshes || !params.detailVerts || !params.detailTris)
- {
- printf("%sNo detail mesh to build tile! \n", tileString);
- continue;
- }
+ iv.polyMesh = rcAllocPolyMesh();
+ if (!iv.polyMesh)
+ {
+ printf("%s alloc iv.polyMesh FIALED! \r", tileString);
+ return;
+ }
+ rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh);
- printf("%sBuilding navmesh tile... \r", tileString);
- if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
- {
- printf("%s Failed building navmesh tile! \n", tileString);
- continue;
- }
+ iv.polyMeshDetail = rcAllocPolyMeshDetail();
+ if (!iv.polyMeshDetail)
+ {
+ printf("%s alloc m_dmesh FIALED! \r", tileString);
+ return;
+ }
+ rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail);
- dtTileRef tileRef = 0;
- printf("%sAdding tile to navmesh... \r", tileString);
- // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile
- // is removed via removeTile()
- dtStatus dtResult = navMesh->addTile(navData, navDataSize, 0, 0, &tileRef);
- if (!tileRef || dtResult != DT_SUCCESS)
- {
- printf("%sFailed adding tile to navmesh! \n", tileString);
- continue;
- }
+ // free things up
+ delete [] pmmerge;
+ delete [] dmmerge;
- // store tile ref so that tile can be written to disk later
- finishedTiles.push_back(tileRef);
- ++header.tileCount;
-
- // TODO: writing this to file does no good, debug data is just overwritten by next tile
- //if (m_debugOutput)
- //{
- // for (int i = 0; i < iv.polyMesh->nverts; ++i)
- // {
- // unsigned short* v = &iv.polyMesh->verts[i*3];
- // v[0] += (unsigned short)config.borderSize;
- // v[2] += (unsigned short)config.borderSize;
- // }
- // writeIV(mapID, tileX, tileY, iv);
- //}
- }
+ delete tileSet;
+
+ // remove padding for extraction
+ for (int i = 0; i < iv.polyMesh->nverts; ++i)
+ {
+ unsigned short* v = &iv.polyMesh->verts[i*3];
+ v[0] -= (unsigned short)config.borderSize;
+ v[2] -= (unsigned short)config.borderSize;
}
- printf("%sWriting to file... \r", tileString);
- for (vector<dtTileRef>::iterator it = finishedTiles.begin(); it != finishedTiles.end(); ++it)
+ // set polygons as walkable
+ // TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
+ for (int i = 0; i < iv.polyMesh->npolys; ++i)
+ if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
+ iv.polyMesh->flags[i] = iv.polyMesh->areas[i];
+
+ // setup mesh parameters
+ dtNavMeshCreateParams params;
+ memset(&params, 0, sizeof(params));
+ params.verts = iv.polyMesh->verts;
+ params.vertCount = iv.polyMesh->nverts;
+ params.polys = iv.polyMesh->polys;
+ params.polyAreas = iv.polyMesh->areas;
+ params.polyFlags = iv.polyMesh->flags;
+ params.polyCount = iv.polyMesh->npolys;
+ params.nvp = iv.polyMesh->nvp;
+ params.detailMeshes = iv.polyMeshDetail->meshes;
+ params.detailVerts = iv.polyMeshDetail->verts;
+ params.detailVertsCount = iv.polyMeshDetail->nverts;
+ params.detailTris = iv.polyMeshDetail->tris;
+ params.detailTriCount = iv.polyMeshDetail->ntris;
+ params.walkableHeight = BASE_UNIT_DIM*config.walkableHeight; // agent height
+ params.walkableRadius = BASE_UNIT_DIM*config.walkableRadius; // agent radius
+ params.walkableClimb = BASE_UNIT_DIM*config.walkableClimb; // keep less that walkableHeight (aka agent height)!
+ params.tileX = (((bmin[0] + bmax[0]) / 2) - navMesh->getParams()->orig[0]) / GRID_SIZE;
+ params.tileY = (((bmin[2] + bmax[2]) / 2) - navMesh->getParams()->orig[2]) / GRID_SIZE;
+ rcVcopy(params.bmin, bmin);
+ rcVcopy(params.bmax, bmax);
+ params.cs = config.cs;
+ params.ch = config.ch;
+ params.tileSize = VERTEX_PER_MAP;
+
+ // will hold final navmesh
+ unsigned char* navData = NULL;
+ int navDataSize = 0;
+
+ do
{
- int dataSize;
- unsigned char* data;
+ // these values are checked within dtCreateNavMeshData - handle them here
+ // so we have a clear error message
+ if (params.nvp > DT_VERTS_PER_POLYGON)
+ {
+ printf("%s Invalid verts-per-polygon value! \n", tileString);
+ continue;
+ }
+ if (params.vertCount >= 0xffff)
+ {
+ printf("%s Too many vertices! \n", tileString);
+ continue;
+ }
+ if (!params.vertCount || !params.verts)
+ {
+ // occurs mostly when adjacent tiles have models
+ // loaded but those models don't span into this tile
- // remove the tile from the mesh, and retrieve the tile's data so that
- // we can write it to disk
- navMesh->removeTile(*it, &data, &dataSize);
+ // message is an annoyance
+ //printf("%sNo vertices to build tile! \n", tileString);
+ continue;
+ }
+ if (!params.polyCount || !params.polys)
+ {
+ printf("%s No polygons to build tile! \n", tileString);
+ continue;
+ }
+ if (!params.detailMeshes || !params.detailVerts || !params.detailTris)
+ {
+ printf("%s No detail mesh to build tile! \n", tileString);
+ continue;
+ }
- fwrite(&dataSize, sizeof(dataSize), 1, file);
- fwrite(data, sizeof(unsigned char), dataSize, file);
+ printf("%s Building navmesh tile... \r", tileString);
+ if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
+ {
+ printf("%s Failed building navmesh tile! \n", tileString);
+ continue;
+ }
- // free memory used by tile
- dtFree(data);
- }
+ dtTileRef tileRef = 0;
+ printf("%s Adding tile to navmesh... \r", tileString);
+ // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile
+ // is removed via removeTile()
+ dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef);
+ if (!tileRef || dtResult != DT_SUCCESS)
+ {
+ printf("%s Failed adding tile to navmesh! \n", tileString);
+ continue;
+ }
+
+ // file output
+ char fileName[255];
+ sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX);
+ FILE* file = fopen(fileName, "wb");
+ if (!file)
+ {
+ char message[1024];
+ sprintf(message, "Failed to open %s for writing!\n", fileName);
+ perror(message);
+ navMesh->removeTile(tileRef, NULL, NULL);
+ continue;
+ }
+
+ printf("%s Writing to file... \r", tileString);
+
+ // write header
+ mmapTileHeader header(m_terrainBuilder);
+ header.size = uint32(navDataSize);
+ fwrite(&header, sizeof(mmapTileHeader), 1, file);
+
+ // write data
+ fwrite(navData, sizeof(unsigned char), navDataSize, file);
+ fclose(file);
+
+ // now that tile is written to disk, we can unload it
+ navMesh->removeTile(tileRef, NULL, NULL);
+ } while (0);
- // re-write header, so that tilecount is up to date
- fseek(file, 0, SEEK_SET);
- fwrite(&header, sizeof(header), 1, file);
- fclose(file);
if (m_debugOutput)
+ {
+ // restore padding so that the debug visualization is correct
+ for (int i = 0; i < iv.polyMesh->nverts; ++i)
+ {
+ unsigned short* v = &iv.polyMesh->verts[i*3];
+ v[0] += (unsigned short)config.borderSize;
+ v[2] += (unsigned short)config.borderSize;
+ }
+
generateObjFile(mapID, tileX, tileY, meshData);
+ writeIV(mapID, tileX, tileY, iv);
+ }
- m_rcContext->resetLog();
+ clearIntermediateValues(iv);
}
void MapBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax)
@@ -1098,7 +1113,6 @@ namespace MMAP
{
iv.compactHeightfield = NULL;
iv.heightfield = NULL;
- iv.triFlags = NULL;
iv.contours = NULL;
iv.polyMesh = NULL;
iv.polyMeshDetail = NULL;
@@ -1111,7 +1125,6 @@ namespace MMAP
rcFreeContourSet(iv.contours); iv.contours = NULL;
rcFreePolyMesh(iv.polyMesh); iv.polyMesh = NULL;
rcFreePolyMeshDetail(iv.polyMeshDetail); iv.polyMeshDetail = NULL;
- dtFree(iv.triFlags); iv.triFlags = NULL;
}
void MapBuilder::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData meshData)
@@ -1119,7 +1132,7 @@ namespace MMAP
generateRealObj(mapID, tileX, tileY, meshData);
char tileString[25];
- sprintf(tileString, "[%02u,%02u]: ", tileX, tileY);
+ sprintf(tileString, "[%02u,%02u]: ", tileY, tileX);
printf("%sWriting debug output... \r", tileString);
char objFileName[255];
@@ -1219,24 +1232,26 @@ namespace MMAP
string name("meshes/%03u%02i%02i.");
#define DEBUG_WRITE(fileExtension,data) \
- sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \
- file = fopen(fileName, "wb"); \
- if (!file) \
- { \
- char message[1024]; \
- sprintf(message, "%sFailed to open %s for writing!\n", tileString, fileName); \
- perror(message); \
- } \
- else \
- debugWrite(file, data); \
- if(file) fclose(file); \
- printf("%sWriting debug output... \r", tileString)
-
- DEBUG_WRITE("hf", iv.heightfield);
- DEBUG_WRITE("chf", iv.compactHeightfield);
- DEBUG_WRITE("cs", iv.contours);
- DEBUG_WRITE("pmesh", iv.polyMesh);
- DEBUG_WRITE("dmesh", iv.polyMeshDetail);
+ do { \
+ sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \
+ file = fopen(fileName, "wb"); \
+ if (!file) \
+ { \
+ char message[1024]; \
+ sprintf(message, "%sFailed to open %s for writing!\n", tileString, fileName); \
+ perror(message); \
+ } \
+ else \
+ debugWrite(file, data); \
+ if(file) fclose(file); \
+ printf("%sWriting debug output... \r", tileString); \
+ } while (false)
+
+ if (iv.heightfield) DEBUG_WRITE("hf", iv.heightfield);
+ if (iv.compactHeightfield) DEBUG_WRITE("chf", iv.compactHeightfield);
+ if (iv.contours) DEBUG_WRITE("cs", iv.contours);
+ if (iv.polyMesh) DEBUG_WRITE("pmesh", iv.polyMesh);
+ if (iv.polyMeshDetail) DEBUG_WRITE("dmesh", iv.polyMeshDetail);
#undef DEBUG_WRITE
}
diff --git a/contrib/mmap/src/MapBuilder.h b/contrib/mmap/src/MapBuilder.h
index ce8dea4..e8b0d90 100644
--- a/contrib/mmap/src/MapBuilder.h
+++ b/contrib/mmap/src/MapBuilder.h
@@ -35,11 +35,8 @@ using namespace std;
using namespace VMAP;
// G3D namespace typedefs conflicts with ACE typedefs
-#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 1
-
-#define TILES_PER_MMTILE 16
-#define TILE_SIZE (GRID_SIZE / TILES_PER_MMTILE)
+#define MMAP_MAGIC 0x4d4d4150
+#define MMAP_VERSION 2
namespace MMAP
{
@@ -48,7 +45,6 @@ namespace MMAP
struct IntermediateValues
{
rcHeightfield* heightfield;
- unsigned char* triFlags;
rcCompactHeightfield* compactHeightfield;
rcContourSet* contours;
rcPolyMesh* polyMesh;
@@ -60,7 +56,7 @@ namespace MMAP
uint32 mmapMagic;
uint32 dtVersion;
uint32 mmapVersion;
- uint32 tileCount;
+ uint32 size;
bool usesHiRes : 1;
bool usesLiquids : 1;
@@ -68,21 +64,51 @@ namespace MMAP
mmapMagic(MMAP_MAGIC),
dtVersion(DT_NAVMESH_VERSION),
mmapVersion(MMAP_VERSION),
- tileCount(0)
+ size(0)
{}
mmapTileHeader(TerrainBuilder* terrainBuilder) :
mmapMagic(MMAP_MAGIC),
dtVersion(DT_NAVMESH_VERSION),
mmapVersion(MMAP_VERSION),
- tileCount(0)
+ size(0)
{
usesHiRes = terrainBuilder->usesHiRes();
usesLiquids = terrainBuilder->usesLiquids();
}
private:
- mmapTileHeader(const mmapTileHeader &header);
+ mmapTileHeader(const mmapTileHeader& header);
+ };
+
+ struct Tile
+ {
+ inline Tile() : chf(0), solid(0), cset(0), pmesh(0), dmesh(0), buildTime(0) {}
+ inline ~Tile()
+ {
+ rcFreeCompactHeightfield(chf);
+ rcFreeContourSet(cset);
+ rcFreeHeightField(solid);
+ rcFreePolyMesh(pmesh);
+ rcFreePolyMeshDetail(dmesh);
+ }
+ int x, y;
+ rcCompactHeightfield* chf;
+ rcHeightfield* solid;
+ rcContourSet* cset;
+ rcPolyMesh* pmesh;
+ rcPolyMeshDetail* dmesh;
+ int buildTime;
+ };
+
+ struct TileSet
+ {
+ inline TileSet() : width(0), height(0), tiles(0) {}
+ inline ~TileSet() { delete [] tiles; }
+ int width, height;
+ float bmin[3], bmax[3];
+ float cs, ch;
+ Tile* tiles;
};
class MapBuilder
@@ -114,6 +140,7 @@ namespace MMAP
// load and unload models
bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData);
+ void unloadVMap(uint32 mapID, uint32 tileX, uint32 tileY);
// vert and triangle methods
void transform(vector<Vector3> original, vector<Vector3> &transformed,
@@ -169,6 +196,7 @@ namespace MMAP
float m_maxWalkableAngle;
+ // build performance - not really used for now
rcContext* m_rcContext;
};
}
diff --git a/dep/recastnavigation/RecastDemo/Include/Debug.h b/dep/recastnavigation/RecastDemo/Include/Debug.h
index ae533d1..8e6e0c5 100644
--- a/dep/recastnavigation/RecastDemo/Include/Debug.h
+++ b/dep/recastnavigation/RecastDemo/Include/Debug.h
@@ -59,13 +59,13 @@ struct mmapTileHeader
unsigned int mmapMagic;
unsigned int dtVersion;
unsigned int mmapVersion;
- unsigned int tileCount;
+ unsigned int size;
bool usesHiRes : 1;
bool usesLiquid : 1;
mmapTileHeader() :
mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
- mmapVersion(MMAP_VERSION), tileCount(0)
+ mmapVersion(MMAP_VERSION), size(0)
{}
};
diff --git a/dep/recastnavigation/RecastDemo/Source/Debug.cpp b/dep/recastnavigation/RecastDemo/Source/Debug.cpp
index ebbc3ac..e9c4a97 100644
--- a/dep/recastnavigation/RecastDemo/Source/Debug.cpp
+++ b/dep/recastnavigation/RecastDemo/Source/Debug.cpp
@@ -51,22 +51,16 @@ void duReadNavMesh(char* tile, dtNavMesh* &navMesh)
mmapTileHeader header;
fread(&header, sizeof(header), 1, file);
- unsigned int length;
+ unsigned char* data = (unsigned char*)dtAlloc(header.size, DT_ALLOC_PERM);
+ fread(data, header.size, 1, file);
- for (unsigned int i2 = 0; i2 < header.tileCount; ++i2)
- {
- fread(&length, sizeof(length), 1, file);
-
- unsigned char* data = (unsigned char*)dtAlloc(length, DT_ALLOC_PERM);
- fread(data, length, 1, file);
+ dtStatus status = navMesh->addTile(data, header.size, DT_TILE_FREE_DATA, 0 , NULL);
- dtStatus status = navMesh->addTile(data, length, DT_TILE_FREE_DATA, 0 , NULL);
+ if (status != DT_SUCCESS)
+ dtFree(data);
+ else
+ count++;
- if (status != DT_SUCCESS)
- dtFree(data);
- else
- count++;
- }
fclose(file);
}
}
diff --git a/src/game/GridMap.h b/src/game/GridMap.h
index c13a9f0..48ee48a 100644
--- a/src/game/GridMap.h
+++ b/src/game/GridMap.h
@@ -286,7 +286,7 @@ private:
void LoadNavMesh(int gx, int gy);
void UnloadNavMesh(int gx, int gy);
dtNavMesh* m_navMesh;
- UNORDERED_MAP<uint32, std::list<dtTileRef>*> m_mmapLoadedTiles; // maps [map grid coords] to [dtTile]
+ UNORDERED_MAP<uint32, dtTileRef> m_mmapLoadedTiles; // maps [map grid coords] to [dtTile]
static std::set<uint32> s_mmapDisabledIds; // stores list of mapids which do not use pathfinding
// end movemap-related
diff --git a/src/game/MoveMap.cpp b/src/game/MoveMap.cpp
index 2bcd577..a136af4 100644
--- a/src/game/MoveMap.cpp
+++ b/src/game/MoveMap.cpp
@@ -22,38 +22,35 @@
#include "Utilities/UnorderedMapSet.h"
#include "World.h"
-/****** TerrainInfo navmesh load/unload ******/
-
uint32 packTileID(int x, int y) { return uint32(x << 16 | y); }
void TerrainInfo::LoadNavMesh(int gx, int gy)
{
- // load the navmesh first
if (!m_navMesh)
{
uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i.mmap")+1;
- char *fileName = new char[pathLen];
- snprintf(fileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i.mmap").c_str(), m_mapId);
+ char *temp = new char[pathLen];
+ snprintf(temp, pathLen, (sWorld.GetDataPath()+"mmaps/%03i.mmap").c_str(), m_mapId);
+ std::string fileName = temp;
+ delete [] temp;
- FILE* file = fopen(fileName, "rb");
+ FILE* file = fopen(fileName.c_str(), "rb");
if (!file)
{
- sLog.outDebug("MMAP: Error: Could not open mmap file '%s'", fileName);
- delete [] fileName;
+ sLog.outDebug("MMAP: Error: Could not open mmap file '%s'", fileName.c_str());
return;
}
dtNavMeshParams params;
fread(&params, sizeof(dtNavMeshParams), 1, file);
fclose(file);
- delete [] fileName;
m_navMesh = dtAllocNavMesh();
if (!m_navMesh->init(&params))
{
dtFreeNavMesh(m_navMesh);
m_navMesh = NULL;
- sLog.outError("MMAP: Failed to initialize mmap %03u from file %s", m_mapId, fileName);
+ sLog.outError("MMAP: Failed to initialize mmap %03u from file %s", m_mapId, fileName.c_str());
return;
}
}
@@ -66,56 +63,73 @@ void TerrainInfo::LoadNavMesh(int gx, int gy)
return;
}
- // now load the tile
- MmapTileReader reader(m_mapId, gx, gy);
- if (!reader.check())
+ // mmaps/0000000.mmtile
+ uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1;
+ char *fileName = new char[pathLen];
+ snprintf(fileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), m_mapId, gx, gy);
+
+ FILE *file = fopen(fileName, "rb");
+ if (!file)
{
- sLog.outError("MMAP: Bad header in mmap %03u%02i%02i.mmtile", m_mapId, gx, gy);
+ sLog.outDebug("MMAP: Could not open mmtile file '%s'", fileName);
+ delete [] fileName;
return;
}
+ delete [] fileName;
- tileRefList* newTiles = new tileRefList();
- unsigned char* data = NULL;
- uint32 length = 0;
+ // read header
+ mmapTileHeader fileHeader;
+ fread(&fileHeader, sizeof(mmapTileHeader), 1, file);
- while (reader.read(data, length))
+ if (fileHeader.mmapMagic != MMAP_MAGIC)
{
- dtMeshHeader* header = (dtMeshHeader*)data;
- dtTileRef tileRef = 0;
-
- // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
- dtStatus dtResult = m_navMesh->addTile(data, length, DT_TILE_FREE_DATA, 0, &tileRef);
- if(dtResult == DT_SUCCESS)
- newTiles->push_back(tileRef);
- else
- dtFree(data);
+ sLog.outError("MMAP: Bad header in mmap %03u%02i%02i.mmtile", m_mapId, gx, gy);
+ return;
}
- // have we loaded everything we expected?
- if(reader.getTileCount() == newTiles->size())
- {
- sLog.outDetail("MMAP: Loaded mmtile %03i[%02i,%02i]", m_mapId, gx, gy);
- m_mmapLoadedTiles.insert(std::pair<uint32, tileRefList*>(packedGridPos, newTiles));
- }
- else
- {
- // one or more of the tiles failed
- // we cannot allow having partially loaded maps
- sLog.outError("MMAP: Could not load %03u%02i%02i.mmtile into navmesh", m_mapId, gx, gy);
+ unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM);
+ MANGOS_ASSERT(data);
- // unload everything we can
- for (tileRefList::iterator itr = newTiles->begin(); itr != newTiles->end(); )
+ fread(data, fileHeader.size, 1, file);
+ fclose(file);
+
+ dtMeshHeader* header = (dtMeshHeader*)data;
+ dtTileRef tileRef = 0;
+
+ // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
+ dtStatus dtResult = m_navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef);
+ switch(dtResult)
+ {
+ case DT_SUCCESS:
{
- if(DT_SUCCESS == m_navMesh->removeTile(*itr, NULL, NULL))
- itr = newTiles->erase(itr);
- else
- ++itr;
+ m_mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
+ sLog.outDetail("MMAP: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", m_mapId, gx, gy, m_mapId, header->x, header->y);
}
-
- // if we got here with newTiles not empty its really bad - but again, we cannot recover
- MANGOS_ASSERT(newTiles->empty());
- delete newTiles;
+ break;
+ case DT_FAILURE_DATA_MAGIC:
+ {
+ sLog.outError("MMAP: %03u%02i%02i.mmtile has an invalid header", m_mapId, gx, gy);
+ dtFree(data);
+ }
+ break;
+ case DT_FAILURE_DATA_VERSION:
+ {
+ sLog.outError("MMAP: %03u%02i%02i.mmtile was built with Detour v%i, expected v%i",m_mapId, gx, gy, header->version, DT_NAVMESH_VERSION);
+ dtFree(data);
+ }
+ break;
+ case DT_FAILURE_OUT_OF_MEMORY:
+ case DT_FAILURE:
+ default:
+ {
+ sLog.outError("MMAP: Could not load %03u%02i%02i.mmtile into navmesh", m_mapId, gx, gy);
+ dtFree(data);
+ }
+ break;
}
+
+ if (fileHeader.mmapVersion != MMAP_VERSION)
+ sLog.outDebug("MMAP: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", m_mapId, gx, gy, fileHeader.mmapVersion, MMAP_VERSION);
}
void TerrainInfo::UnloadNavMesh(int gx, int gy)
@@ -132,29 +146,20 @@ void TerrainInfo::UnloadNavMesh(int gx, int gy)
return;
}
- tileRefList* tiles = m_mmapLoadedTiles[packedGridPos];
- for (tileRefList::iterator itr = tiles->begin(); itr != tiles->end(); )
+ dtTileRef tileRef = m_mmapLoadedTiles[packedGridPos];
+
+ // unload, and mark as non loaded
+ if(DT_SUCCESS != m_navMesh->removeTile(tileRef, NULL, NULL))
{
- // unload, and mark as non loaded
- if(DT_SUCCESS == m_navMesh->removeTile(*itr, NULL, NULL))
- itr = tiles->erase(itr);
- else
- ++itr;
+ // because the Terrain unloads the grid, this is technically a memory leak
+ // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
+ sLog.outError("MMAP: Could not unload %03u%02i%02i.mmtile from navmesh", m_mapId, gx, gy);
}
-
- if (tiles->empty())
- sLog.outDetail("MMAP: Unloaded mmtile %03i[%02i,%02i] from %03i", m_mapId, gx, gy, m_mapId);
else
{
- // because the Terrain unloads the grid, this is technically a memory leak
- // if the grid is later loaded, dtNavMesh::addTile will return errors for the dtTileRefs we were unable to unload
- // if we got here, something is really worng - we cannot recover anyway
- sLog.outError("MMAP: Could not unload %u tile(s) from navmesh (%03u%02i%02i.mmtile)", tiles->size(), m_mapId, gx, gy);
- MANGOS_ASSERT(false);
+ m_mmapLoadedTiles.erase(packedGridPos);
+ sLog.outDetail("MMAP: Unloaded mmtile %03i[%02i,%02i] from %03i", m_mapId, gx, gy, m_mapId);
}
-
- delete tiles;
- m_mmapLoadedTiles.erase(packedGridPos);
}
dtNavMesh const* TerrainInfo::GetNavMesh() const
@@ -162,8 +167,6 @@ dtNavMesh const* TerrainInfo::GetNavMesh() const
return m_navMesh;
}
-/****** pathfinding enabled/disabled ******/
-
std::set<uint32> TerrainInfo::s_mmapDisabledIds = std::set<uint32>();
void TerrainInfo::preventPathfindingOnMaps(std::string ignoreMapIds)
@@ -187,87 +190,3 @@ bool TerrainInfo::IsPathfindingEnabled() const
{
return sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED) && s_mmapDisabledIds.find(m_mapId) == s_mmapDisabledIds.end();
}
-
-/****** MmapTileReader ******/
-MmapTileReader::MmapTileReader(uint32 mapId, int32 x, int32 y)
- : m_mmapTileFile(NULL), m_currentTile(0), m_mmapFileName(NULL)
-{
- // mmaps/0000000.mmtile
- uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1;
- m_mmapFileName = new char[pathLen];
- snprintf(m_mmapFileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
-
- m_mmapTileFile = fopen(m_mmapFileName, "rb");
- if (!m_mmapTileFile)
- return;
-
- uint32 bytesRead = fread(&m_header, 1, sizeof(mmapTileHeader), m_mmapTileFile);
- if (bytesRead != sizeof(mmapTileHeader))
- memset(&m_header, 0, sizeof(mmapTileHeader));
-}
-
-MmapTileReader::~MmapTileReader()
-{
- delete [] m_mmapFileName;
-
- if (m_mmapTileFile)
- fclose(m_mmapTileFile);
-}
-
-bool MmapTileReader::check()
-{
- if (!m_mmapTileFile)
- {
- sLog.outDebug("Could not open mmtile file '%s'", m_mmapFileName);
- return false;
- }
-
- if (m_header.mmapMagic != MMAP_MAGIC)
- {
- sLog.outError("mmtile file '%s' has wrong format", m_mmapFileName);
- return false;
- }
-
- if (m_header.dtVersion != DT_NAVMESH_VERSION)
- {
- sLog.outError("mmtile file '%s' was built with Detour v%i, expected v%", m_mmapFileName, m_header.dtVersion, DT_NAVMESH_VERSION);
- return false;
- }
-
- if (m_header.tileCount == 0)
- {
- sLog.outDebug("mmtile file '%s' contains 0 tiles", m_mmapFileName);
- return false;
- }
-
- return true;
-}
-
-bool MmapTileReader::read(unsigned char* &data, uint32 &dataLength)
-{
- if (!m_mmapTileFile)
- return false;
-
- uint32 bytesRead = fread(&dataLength, 1, sizeof(uint32), m_mmapTileFile);
- if (sizeof(uint32) != bytesRead)
- return false;
-
- // check if we have read all the tiles
- if (m_header.tileCount <= m_currentTile)
- return false;
-
- // allocate and read tile data
- data = (unsigned char*)dtAlloc(dataLength, DT_ALLOC_PERM);
- MANGOS_ASSERT(data);
-
- bytesRead = fread(data, 1, dataLength, m_mmapTileFile);
- if (bytesRead != dataLength)
- {
- dtFree(data);
- return false;
- }
-
- m_currentTile++;
-
- return true;
-}
diff --git a/src/game/MoveMap.h b/src/game/MoveMap.h
index 2cb4e47..fa0d41a 100644
--- a/src/game/MoveMap.h
+++ b/src/game/MoveMap.h
@@ -20,10 +20,8 @@
#define _MOVE_MAP_H
#include "Platform/Define.h"
-#include <list>
#include "../../dep/recastnavigation/Detour/Include/DetourAlloc.h"
-#include "../../dep/recastnavigation/Detour/Include/DetourNavMesh.h"
/* memory management */
@@ -37,40 +35,19 @@ inline void dtCustomFree(void* ptr)
delete [] (unsigned char*)ptr;
}
-/* mmap tile structure */
+/* mmap file info */
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 1
+#define MMAP_VERSION 2
struct mmapTileHeader
{
uint32 mmapMagic;
uint32 dtVersion;
uint32 mmapVersion;
- uint32 tileCount;
+ uint32 size;
bool usesHiRes : 1;
bool usesLiquids : 1;
};
-typedef std::list<dtTileRef> tileRefList;
-
-class MmapTileReader
-{
-public:
- MmapTileReader(uint32 mapId, int32 x, int32 y);
- ~MmapTileReader();
-
- // validates the mmtile file
- bool check();
-
- // reads and returns the next dtMeshTile data
- bool read(unsigned char* &data, uint32 &dataLength);
- uint32 getTileCount() { return m_header.tileCount; }
-private:
- char* m_mmapFileName;
- FILE* m_mmapTileFile;
- mmapTileHeader m_header;
- uint32 m_currentTile;
-};
-
#endif // _MOVE_MAP_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment