Created
November 23, 2010 20:01
-
-
Save vermie/712419 to your computer and use it in GitHub Desktop.
generator for multiple dtTiles per mmtile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/contrib/mmap/src/MapBuilder.cpp b/contrib/mmap/src/MapBuilder.cpp | |
index dde03c7..546085c 100644 | |
--- a/contrib/mmap/src/MapBuilder.cpp | |
+++ b/contrib/mmap/src/MapBuilder.cpp | |
@@ -39,12 +39,15 @@ namespace MMAP | |
m_skipJunkMaps (skipJunkMaps), | |
m_skipBattlegrounds (skipBattlegrounds), | |
m_maxWalkableAngle (maxWalkableAngle), | |
- m_newTilesOnly (newTilesOnly) | |
+ m_newTilesOnly (newTilesOnly), | |
+ m_rcContext (NULL) | |
{ | |
m_vmapManager = new VMapManager2(); | |
m_terrainBuilder = new TerrainBuilder(skipLiquid, hiResHeightmaps); | |
+ m_rcContext = new rcContext; | |
+ | |
discoverTiles(); | |
} | |
@@ -59,6 +62,7 @@ namespace MMAP | |
delete m_terrainBuilder; | |
delete m_vmapManager; | |
+ delete m_rcContext; | |
} | |
void MapBuilder::discoverTiles() | |
@@ -641,8 +645,10 @@ namespace MMAP | |
{ | |
set<uint32>* tiles = getTileList(mapID); | |
+ uint32 tileCount = tiles->size() * rcSqr(TILES_PER_MMTILE); | |
+ | |
/*** calculate number of bits needed to store tiles & polys ***/ | |
- int tileBits = rcMin((int)dtIlog2(dtNextPow2(tiles->size())), 12); | |
+ int tileBits = rcMin((int)dtIlog2(dtNextPow2(tileCount)), 12); | |
if (tileBits < 1) tileBits = 1; // need at least one bit! | |
int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits; | |
int maxTiles = 1 << tileBits; | |
@@ -676,8 +682,8 @@ namespace MMAP | |
// navmesh creation params | |
dtNavMeshParams navMeshParams; | |
memset(&navMeshParams, 0, sizeof(dtNavMeshParams)); | |
- navMeshParams.tileWidth = GRID_SIZE; | |
- navMeshParams.tileHeight = GRID_SIZE; | |
+ navMeshParams.tileWidth = GRID_SIZE / TILES_PER_MMTILE; | |
+ navMeshParams.tileHeight = GRID_SIZE / TILES_PER_MMTILE; | |
rcVcopy(navMeshParams.orig, bmin); | |
navMeshParams.maxTiles = maxTiles; | |
navMeshParams.maxPolys = maxPolysPerTile; | |
@@ -709,7 +715,7 @@ namespace MMAP | |
} | |
void MapBuilder::buildMoveMapTile(uint32 mapID, uint32 tileX, uint32 tileY, | |
- MeshData meshData, float* bmin, float* bmax, | |
+ MeshData meshData, float bmin[3], float bmax[3], | |
dtNavMesh* navMesh) | |
{ | |
// console output | |
@@ -728,6 +734,7 @@ namespace MMAP | |
return; | |
} | |
+ // write header - implicit ctor initializes values for us | |
mmapTileHeader header; | |
fwrite(&header, sizeof(header), 1, file); | |
@@ -750,262 +757,317 @@ namespace MMAP | |
int* lTris = meshData.liquidTris.getCArray(); | |
int lTriCount = meshData.liquidTris.size() / 3; | |
uint8* lTriFlags = meshData.liquidType.getCArray(); | |
- do | |
+ | |
+ // init detour tile bounds | |
+ float tileMin[3], tileMax[3]; | |
+ float tileSize = GRID_SIZE / TILES_PER_MMTILE; | |
+ rcVcopy(tileMin, bmin); | |
+ rcVcopy(tileMax, bmax); | |
+ | |
+ /* 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; | |
+ | |
+ // these are VOXEL-based metrics | |
+ config.tileSize = (int)ceilf(tileSize / config.cs); | |
+ config.walkableRadius = (int)ceilf(agentRadius / config.cs); | |
+ 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) | |
{ | |
- /*** init 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 | |
- rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); | |
- config.tileSize = (int)ceilf(GRID_SIZE / config.cs); | |
- config.walkableRadius = (int)ceilf(agentRadius / config.cs); | |
- 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; | |
- | |
- // pad bounds with a border | |
- config.bmin[0] -= config.borderSize*config.cs; | |
- config.bmin[2] -= config.borderSize*config.cs; | |
- config.bmax[0] += config.borderSize*config.cs; | |
- config.bmax[2] += config.borderSize*config.cs; | |
- | |
- // this sets the dimensions of the heightfield - should maybe happen before border padding | |
- rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); | |
- | |
- // build performance | |
- rcContext context; | |
- | |
- /*********** start build ***********/ | |
- | |
- // build heightfield | |
- printf("%sBuilding Recast Heightfield... \r", tileString); | |
- iv.heightfield = rcAllocHeightfield(); | |
- if (!iv.heightfield || !rcCreateHeightfield(&context, *iv.heightfield, config.width, config.height, config.bmin, config.bmax, config.cs, config.ch)) | |
+ tileMin[0] = bmin[0] + tileSize * x; | |
+ tileMax[0] = tileMin[0] + tileSize; | |
+ | |
+ //if (abs(tileMax[0] - bmax[0]) < tileSize * .5) | |
+ // tileMax[0] = bmax[0]; | |
+ | |
+ for (uint32 y = 0; y < TILES_PER_MMTILE; ++y) | |
{ | |
- printf("%sFailed building heightfield! \n", tileString); | |
- continue; | |
- } | |
+ tileMin[2] = bmin[2] + tileSize * y; | |
+ tileMax[2] = tileMin[2] + tileSize; | |
- printf("%sRasterizing triangles... \r", tileString); | |
+ //if (abs(tileMax[2] - bmax[2]) < tileSize * .5) | |
+ // tileMax[2] = bmax[2]; | |
- // 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(&context, config.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, iv.triFlags); | |
- rcRasterizeTriangles(&context, tVerts, tVertCount, tTris, iv.triFlags, tTriCount, *iv.heightfield, config.walkableClimb); | |
- dtFree(iv.triFlags); | |
- iv.triFlags = NULL; | |
+ clearIntermediateValues(iv); | |
- // filter out unwalkable spans (order of calls matters, see rcFilterLowHangingWalkableObstacles) | |
- rcFilterLowHangingWalkableObstacles(&context, config.walkableClimb, *iv.heightfield); | |
- rcFilterLedgeSpans(&context, config.walkableHeight, config.walkableClimb, *iv.heightfield); | |
- rcFilterWalkableLowHeightSpans(&context, config.walkableHeight, *iv.heightfield); | |
+ /* tile-specific config settings */ | |
+ rcVcopy(config.bmin, tileMin); | |
+ rcVcopy(config.bmax, tileMax); | |
- // do after filtering because same rules don't apply to swimming | |
- rcRasterizeTriangles(&context, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *iv.heightfield, config.walkableClimb); | |
+ // 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; | |
- // compact heightfield spans | |
- printf("%sCompacting heightfield... \r", tileString); | |
- iv.compactHeightfield = rcAllocCompactHeightfield(); | |
- if (!iv.compactHeightfield || !rcBuildCompactHeightfield(&context, config.walkableHeight, config.walkableClimb, *iv.heightfield, *iv.compactHeightfield)) | |
- { | |
- printf("%sFailed compacting heightfield! \n", tileString); | |
- continue; | |
- } | |
+ // this sets the dimensions of the heightfield - should maybe happen before border padding | |
+ rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); | |
+ //printf("tile width = %d \ntile height = %d\n", config.width, config.height); | |
- if (!m_debugOutput) | |
- { | |
- rcFreeHeightField(iv.heightfield); | |
- iv.heightfield = NULL; | |
- } | |
+ /* start build */ | |
- // build polymesh intermediates | |
- printf("%sEroding walkable area width... \r", tileString); | |
- if (!rcErodeWalkableArea(&context, config.walkableRadius, *iv.compactHeightfield)) | |
- { | |
- printf("%sFailed eroding area! \n", tileString); | |
- continue; | |
- } | |
+ // 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)) | |
+ { | |
+ printf("%sFailed building heightfield! \n", tileString); | |
+ continue; | |
+ } | |
- printf("%sSmoothing area boundaries... \r", tileString); | |
- if (!rcMedianFilterWalkableArea(&context, *iv.compactHeightfield)) | |
- { | |
- printf("%sFailed median filter! \n", tileString); | |
- continue; | |
- } | |
+ printf("%sRasterizing triangles... \r", tileString); | |
- printf("%sBuilding distance field... \r", tileString); | |
- if (!rcBuildDistanceField(&context, *iv.compactHeightfield)) | |
- { | |
- printf("%sFailed building distance field! \n", tileString); | |
- continue; | |
- } | |
+ // 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; | |
- // bottleneck is here | |
- printf("%sBuilding regions... \r", tileString); | |
- if (!rcBuildRegions(&context, *iv.compactHeightfield, config.borderSize, config.minRegionArea, config.mergeRegionArea)) | |
- { | |
- printf("%sFailed building regions! \n", tileString); | |
- continue; | |
- } | |
+ // 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); | |
- printf("%sBuilding contours... \r", tileString); | |
- iv.contours = rcAllocContourSet(); | |
- if (!iv.contours || !rcBuildContours(&context, *iv.compactHeightfield, config.maxSimplificationError, config.maxEdgeLen, *iv.contours)) | |
- { | |
- printf("%sFailed building contours! \n", tileString); | |
- continue; | |
- } | |
+ // do after filtering because same rules don't apply to swimming | |
+ rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *iv.heightfield, config.walkableClimb); | |
- // build polymesh | |
- printf("%sBuilding polymesh... \r", tileString); | |
- iv.polyMesh = rcAllocPolyMesh(); | |
- if (!iv.polyMesh || !rcBuildPolyMesh(&context, *iv.contours, config.maxVertsPerPoly, *iv.polyMesh)) | |
- { | |
- printf("%sFailed building polymesh! \n", tileString); | |
- continue; | |
- } | |
+ // 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)) | |
+ { | |
+ printf("%sFailed compacting heightfield! \n", tileString); | |
+ continue; | |
+ } | |
- printf("%sBuilding polymesh detail... \r", tileString); | |
- iv.polyMeshDetail = rcAllocPolyMeshDetail(); | |
- if (!iv.polyMeshDetail || !rcBuildPolyMeshDetail(&context, *iv.polyMesh, *iv.compactHeightfield, config.detailSampleDist, config.detailSampleMaxError, *iv.polyMeshDetail)) | |
- { | |
- printf("%sFailed building polymesh detail! \n", tileString); | |
- continue; | |
- } | |
+ if (!m_debugOutput) | |
+ { | |
+ rcFreeHeightField(iv.heightfield); | |
+ iv.heightfield = NULL; | |
+ } | |
- if (!m_debugOutput) | |
- { | |
- rcFreeCompactHeightfield(iv.compactHeightfield); | |
- iv.compactHeightfield = NULL; | |
- rcFreeContourSet(iv.contours); | |
- iv.contours = NULL; | |
- } | |
+ // build polymesh intermediates | |
+ printf("%sEroding walkable area width... \r", tileString); | |
+ if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *iv.compactHeightfield)) | |
+ { | |
+ printf("%sFailed eroding area! \n", tileString); | |
+ continue; | |
+ } | |
- // this might be handled within Recast at some point | |
- 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; | |
- } | |
+ printf("%sSmoothing area boundaries... \r", tileString); | |
+ if (!rcMedianFilterWalkableArea(m_rcContext, *iv.compactHeightfield)) | |
+ { | |
+ printf("%sFailed median filter! \n", tileString); | |
+ continue; | |
+ } | |
- // 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; | |
- } | |
+ printf("%sBuilding distance field... \r", tileString); | |
+ if (!rcBuildDistanceField(m_rcContext, *iv.compactHeightfield)) | |
+ { | |
+ printf("%sFailed building distance field! \n", tileString); | |
+ continue; | |
+ } | |
- printf("%sSetting polys as walkable... \r", tileString); | |
- 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; | |
- 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 = 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("%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 | |
+ // bottleneck is here | |
+ printf("%sBuilding regions... \r", tileString); | |
+ if (!rcBuildRegions(m_rcContext, *iv.compactHeightfield, config.borderSize, config.minRegionArea, config.mergeRegionArea)) | |
+ { | |
+ printf("%sFailed building regions! \n", tileString); | |
+ continue; | |
+ } | |
- // 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; | |
- } | |
+ printf("%sBuilding contours... \r", tileString); | |
+ iv.contours = rcAllocContourSet(); | |
+ if (!iv.contours || !rcBuildContours(m_rcContext, *iv.compactHeightfield, config.maxSimplificationError, config.maxEdgeLen, *iv.contours)) | |
+ { | |
+ printf("%sFailed building contours! \n", tileString); | |
+ continue; | |
+ } | |
- printf("%s Building navmesh tile... \r", tileString); | |
- if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) | |
- { | |
- printf("%s Failed building navmesh tile! \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)) | |
+ { | |
+ printf("%sFailed building polymesh! \n", tileString); | |
+ continue; | |
+ } | |
- 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; | |
+ 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)) | |
+ { | |
+ printf("%sFailed building polymesh detail! \n", tileString); | |
+ continue; | |
+ } | |
+ | |
+ if (!m_debugOutput) | |
+ { | |
+ rcFreeCompactHeightfield(iv.compactHeightfield); | |
+ iv.compactHeightfield = NULL; | |
+ rcFreeContourSet(iv.contours); | |
+ iv.contours = NULL; | |
+ } | |
+ | |
+ // this might be handled within Recast at some point | |
+ // very important, without this tiles do not get attached 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; | |
+ } | |
+ | |
+ // 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; | |
+ } | |
+ | |
+ 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}; | |
+ 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; | |
+ | |
+ //printf("x = %d, y = %d \n", params.tileX, params.tileY); | |
+ | |
+ // 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) | |
+ { | |
+ printf("%sToo 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 | |
+ | |
+ // 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; | |
+ } | |
+ | |
+ printf("%sBuilding navmesh tile... \r", tileString); | |
+ if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) | |
+ { | |
+ printf("%s Failed building navmesh tile! \n", tileString); | |
+ continue; | |
+ } | |
+ | |
+ 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; | |
+ } | |
+ | |
+ // 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); | |
+ //} | |
} | |
+ } | |
- printf("%s Writing to file... \r", tileString); | |
- fwrite(&navDataSize, sizeof(navDataSize), 1, file); | |
- fwrite(navData, sizeof(unsigned char), navDataSize, file); | |
+ printf("%sWriting to file... \r", tileString); | |
+ for (vector<dtTileRef>::iterator it = finishedTiles.begin(); it != finishedTiles.end(); ++it) | |
+ { | |
+ int dataSize; | |
+ unsigned char* data; | |
- ++header.tileCount; | |
+ // 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); | |
- // now that tile is written to disk, we can unload it | |
- navMesh->removeTile(tileRef, 0, 0); | |
- } while (0); | |
+ fwrite(&dataSize, sizeof(dataSize), 1, file); | |
+ fwrite(data, sizeof(unsigned char), dataSize, file); | |
+ | |
+ // free memory used by tile | |
+ dtFree(data); | |
+ } | |
// re-write header, so that tilecount is up to date | |
fseek(file, 0, SEEK_SET); | |
@@ -1013,12 +1075,9 @@ namespace MMAP | |
fclose(file); | |
if (m_debugOutput) | |
- { | |
generateObjFile(mapID, tileX, tileY, meshData); | |
- writeIV(mapID, tileX, tileY, iv); | |
- } | |
- clearIntermediateValues(iv); | |
+ m_rcContext->resetLog(); | |
} | |
void MapBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) | |
@@ -1083,7 +1142,7 @@ namespace MMAP | |
fwrite(&b, sizeof(char), 1, objFile); | |
fclose(objFile); | |
- sprintf(objFileName, "meshes/%03u%02u%02u.mesh", mapID, tileX, tileY); | |
+ sprintf(objFileName, "meshes/%03u%02u%02u.mesh", mapID, tileY, tileX); | |
objFile = fopen(objFileName, "wb"); | |
if (!objFile) | |
{ | |
@@ -1164,7 +1223,7 @@ namespace MMAP | |
string name("meshes/%03u%02i%02i."); | |
#define DEBUG_WRITE(fileExtension,data) \ | |
- sprintf(fileName, (name + fileExtension).c_str(), mapID, tileX, tileY); \ | |
+ sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \ | |
file = fopen(fileName, "wb"); \ | |
if (!file) \ | |
{ \ | |
diff --git a/contrib/mmap/src/MapBuilder.h b/contrib/mmap/src/MapBuilder.h | |
index c77975d..1fc9077 100644 | |
--- a/contrib/mmap/src/MapBuilder.h | |
+++ b/contrib/mmap/src/MapBuilder.h | |
@@ -38,6 +38,8 @@ using namespace VMAP; | |
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP' | |
#define MMAP_VERSION 1 | |
+#define TILES_PER_MMTILE 64 | |
+ | |
namespace MMAP | |
{ | |
typedef map<uint32,set<uint32>*> TileList; | |
@@ -112,8 +114,8 @@ namespace MMAP | |
uint32 tileX, | |
uint32 tileY, | |
MeshData meshData, | |
- float* bmin, | |
- float* bmax, | |
+ float bmin[3], | |
+ float bmax[3], | |
dtNavMesh* navMesh); | |
void getTileBounds(uint32 tileX, uint32 tileY, | |
@@ -151,6 +153,8 @@ namespace MMAP | |
bool m_newTilesOnly; | |
float m_maxWalkableAngle; | |
+ | |
+ rcContext* m_rcContext; | |
}; | |
} | |
diff --git a/contrib/mmap/win/VC100/MoveMapGen_VC100.vcxproj b/contrib/mmap/win/VC100/MoveMapGen_VC100.vcxproj | |
diff --git a/contrib/mmap/win/VC100/MoveMapGen_VC100.vcxproj.filters b/contrib/mmap/win/VC100/MoveMapGen_VC100.vcxproj.filters | |
diff --git a/dep/recastnavigation/RecastDemo/Include/Debug.h b/dep/recastnavigation/RecastDemo/Include/Debug.h | |
index 14c3ad3..8845a91 100644 | |
--- a/dep/recastnavigation/RecastDemo/Include/Debug.h | |
+++ b/dep/recastnavigation/RecastDemo/Include/Debug.h | |
@@ -51,4 +51,20 @@ public: | |
inline const char* getFileName() const { return m_filename; } | |
}; | |
+#define MMAP_MAGIC 0x4d4d4150 // 'MMAP' | |
+#define MMAP_VERSION 1 | |
+ | |
+struct mmapTileHeader | |
+{ | |
+ unsigned int mmapMagic; | |
+ unsigned int dtVersion; | |
+ unsigned int mmapVersion; | |
+ unsigned int tileCount; | |
+ | |
+ mmapTileHeader() : | |
+ mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), | |
+ mmapVersion(MMAP_VERSION), tileCount(0) | |
+ {} | |
+}; | |
+ | |
#endif | |
diff --git a/dep/recastnavigation/RecastDemo/Source/Debug.cpp b/dep/recastnavigation/RecastDemo/Source/Debug.cpp | |
index 9eb8dd7..ebbc3ac 100644 | |
--- a/dep/recastnavigation/RecastDemo/Source/Debug.cpp | |
+++ b/dep/recastnavigation/RecastDemo/Source/Debug.cpp | |
@@ -24,24 +24,54 @@ void duReadNavMesh(char* tile, dtNavMesh* &navMesh) | |
fread(¶ms, sizeof(dtNavMeshParams), 1, file); | |
fclose(file); | |
- dtFreeNavMesh(navMesh); | |
- navMesh = dtAllocNavMesh(); | |
- navMesh->init(¶ms); | |
- | |
- file = fopen(("mmaps/" + tileName.substr(0, 3) + tileName.substr(5, 2) + tileName.substr(3, 2) + ".mmtile").c_str(), "rb"); | |
- if(file) | |
+ if (!navMesh) | |
{ | |
- fseek(file, 0, SEEK_END); | |
- int length = ftell(file); | |
- fseek(file, 0, SEEK_SET); | |
+ dtFreeNavMesh(navMesh); | |
+ navMesh = dtAllocNavMesh(); | |
+ navMesh->init(¶ms); | |
+ } | |
- unsigned char* data = new unsigned char[length]; | |
- fread(data, length, 1, file); | |
- fclose(file); | |
+ int map = atoi(tileName.substr(0, 3).c_str()); | |
+ int x = atoi(tileName.substr(5, 2).c_str()); | |
+ int y = atoi(tileName.substr(3, 2).c_str()); | |
+ bool loaded = false; | |
- navMesh->addTile(data, length, DT_TILE_FREE_DATA, 0 , NULL); | |
- } | |
- else | |
+ char fname[50]; | |
+ | |
+ int count = 0; | |
+ for (int i = x-1; i <= x+1; ++i) | |
+ for (int j = y-1; j <= y+1; ++j) | |
+ //int i = x; | |
+ //int j = y; | |
+ { | |
+ sprintf(fname, "mmaps/%03i%02i%02i.mmtile", map, j, i); | |
+ file = fopen(fname, "rb"); | |
+ if(file) | |
+ { | |
+ mmapTileHeader header; | |
+ fread(&header, sizeof(header), 1, file); | |
+ | |
+ unsigned int length; | |
+ | |
+ 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, length, DT_TILE_FREE_DATA, 0 , NULL); | |
+ | |
+ if (status != DT_SUCCESS) | |
+ dtFree(data); | |
+ else | |
+ count++; | |
+ } | |
+ fclose(file); | |
+ } | |
+ } | |
+ | |
+ if (!count) | |
{ | |
dtFreeNavMesh(navMesh); | |
navMesh = NULL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment