Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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(¶ms, 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, ¶ms.tileX, ¶ms.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(¶ms, &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(¶ms, 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(¶ms, &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(¶ms, sizeof(dtNavMeshParams), 1, file);
- fclose(file);
- - delete [] fileName;
- m_navMesh = dtAllocNavMesh();
- if (!m_navMesh->init(¶ms))
- {
- 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
Add Comment
Please, Sign In to add comment