Guest User

Untitled

a guest
Jul 16th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 50.41 KB | None | 0 0
  1. diff --git a/contrib/mmap/src/MapBuilder.cpp b/contrib/mmap/src/MapBuilder.cpp
  2. index 43330f5..453b936 100644
  3. --- a/contrib/mmap/src/MapBuilder.cpp
  4. +++ b/contrib/mmap/src/MapBuilder.cpp
  5. @@ -650,10 +650,9 @@ namespace MMAP
  6.  
  7. // old code for non-statically assigned bitmask sizes:
  8. ///*** calculate number of bits needed to store tiles & polys ***/
  9. - //uint32 tileCount = tiles->size() * rcSqr(TILES_PER_MMTILE);
  10. - //tileBits = dtIlog2(dtNextPow2(tileCount);
  11. + //int tileBits = dtIlog2(dtNextPow2(tiles->size()));
  12. //if (tileBits < 1) tileBits = 1; // need at least one bit!
  13. - //polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits;
  14. + //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits;
  15.  
  16. int tileBits = STATIC_TILE_BITS;
  17. int polyBits = STATIC_POLY_BITS;
  18. @@ -689,8 +688,8 @@ namespace MMAP
  19. // navmesh creation params
  20. dtNavMeshParams navMeshParams;
  21. memset(&navMeshParams, 0, sizeof(dtNavMeshParams));
  22. - navMeshParams.tileWidth = GRID_SIZE / TILES_PER_MMTILE;
  23. - navMeshParams.tileHeight = GRID_SIZE / TILES_PER_MMTILE;
  24. + navMeshParams.tileWidth = GRID_SIZE;
  25. + navMeshParams.tileHeight = GRID_SIZE;
  26. rcVcopy(navMeshParams.orig, bmin);
  27. navMeshParams.maxTiles = maxTiles;
  28. navMeshParams.maxPolys = maxPolysPerTile;
  29. @@ -728,27 +727,7 @@ namespace MMAP
  30. // console output
  31. char tileString[10];
  32. sprintf(tileString, "[%02i,%02i]: ", tileX, tileY);
  33. -
  34. - // open the file for writing
  35. - char fileName[255];
  36. - sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX);
  37. - FILE* file = fopen(fileName, "wb");
  38. - if (!file)
  39. - {
  40. - char message[1024];
  41. - sprintf(message, "Failed to open %s for writing!\n", fileName);
  42. - perror(message);
  43. - return;
  44. - }
  45. -
  46. - mmapTileHeader header(m_terrainBuilder);
  47. - fwrite(&header, sizeof(header), 1, file);
  48. -
  49. - float cellSize = 0.5f; // larger number => less voxels => faster build time
  50. - // too large, and tight spaces won't be pathable.
  51. - float agentHeight = 1.5f;
  52. - float agentRadius = 0.5f;
  53. - float agentMaxClimb = 1.65f;
  54. + printf("%s Building movemap tiles... \r", tileString);
  55.  
  56. IntermediateValues iv;
  57. initIntermediateValues(iv);
  58. @@ -764,316 +743,352 @@ namespace MMAP
  59. int lTriCount = meshData.liquidTris.size() / 3;
  60. uint8* lTriFlags = meshData.liquidType.getCArray();
  61.  
  62. - // init detour tile bounds
  63. - float tileMin[3], tileMax[3];
  64. - rcVcopy(tileMin, bmin);
  65. - rcVcopy(tileMax, bmax);
  66. + // these are WORLD UNIT based metrics
  67. + // this are basic unit dimentions
  68. + // value have to divide GRID_SIZE(533.33333f) ( aka: 0.5333, 0.3333, 0.1333, etc )
  69. + const static float BASE_UNIT_DIM = 0.53333333f;
  70. +
  71. + // All are in UNIT metrics!
  72. + const static int VERTEX_PER_MAP = int(GRID_SIZE/BASE_UNIT_DIM + 0.5f);
  73. + const static int VERTEX_PER_TILE = 40; // must divide VERTEX_PER_MAP
  74. + const static int TILES_PER_MAP = VERTEX_PER_MAP/VERTEX_PER_TILE;
  75.  
  76. - /* init mmtile config */
  77. rcConfig config;
  78. memset(&config, 0, sizeof(rcConfig));
  79. - config.maxVertsPerPoly = 6;
  80.  
  81. - // these are WORLD UNIT based metrics
  82. - config.cs = cellSize;
  83. - config.ch = .3f;
  84. - config.walkableSlopeAngle = m_maxWalkableAngle;
  85. + rcVcopy(config.bmin, bmin);
  86. + rcVcopy(config.bmax, bmax);
  87.  
  88. - // these are VOXEL-based metrics
  89. - config.tileSize = (int)ceilf(TILE_SIZE / config.cs);
  90. - config.walkableRadius = (int)ceilf(agentRadius / config.cs);
  91. + config.maxVertsPerPoly = DT_VERTS_PER_POLYGON;
  92. + config.cs = BASE_UNIT_DIM;
  93. + config.ch = BASE_UNIT_DIM;
  94. + config.walkableSlopeAngle = m_maxWalkableAngle;
  95. + config.tileSize = VERTEX_PER_TILE;
  96. + config.walkableRadius = 1;
  97. config.borderSize = config.walkableRadius + 3;
  98. - config.maxEdgeLen = 1500;
  99. - config.walkableHeight = (int)ceilf(agentHeight / config.ch);
  100. - config.walkableClimb = (int)ceilf(agentHeight / config.ch);
  101. - config.minRegionArea = (int)rcSqr(50);
  102. - config.mergeRegionArea = (int)rcSqr(20);
  103. - config.maxSimplificationError = 1.3f;
  104. - config.detailSampleDist = config.cs * 16.f;
  105. - config.detailSampleMaxError = config.ch * 1.f;
  106. -
  107. - vector<dtTileRef> finishedTiles;
  108. -
  109. - for (uint32 x = 0; x < TILES_PER_MMTILE; ++x)
  110. + config.maxEdgeLen = VERTEX_PER_TILE + 1; //anything bigger than tileSize
  111. + config.walkableHeight = 3;
  112. + config.walkableClimb = 2; // keep less than walkableHeight
  113. + config.minRegionArea = rcSqr(50);
  114. + config.mergeRegionArea = rcSqr(30);
  115. + config.maxSimplificationError = 2.5f; // eliminates most jagged edges (tinny polygons)
  116. + config.detailSampleDist = config.cs * 8;
  117. + config.detailSampleMaxError = config.ch * 2;
  118. +
  119. + // this sets the dimensions of the heightfield - should maybe happen before border padding
  120. + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
  121. +
  122. + // allocate subregions : tiles
  123. + TileSet* tileSet = new TileSet;
  124. + rcVcopy(tileSet->bmin, config.bmin);
  125. + rcVcopy(tileSet->bmax, config.bmax);
  126. + tileSet->cs = config.cs;
  127. + tileSet->ch = config.ch;
  128. + tileSet->width = TILES_PER_MAP;
  129. + tileSet->height = TILES_PER_MAP;
  130. + tileSet->tiles = new Tile[tileSet->height * tileSet->width];
  131. +
  132. + // Initialize per tile config.
  133. + rcConfig tileCfg;
  134. + memcpy(&tileCfg, &config, sizeof(rcConfig));
  135. + tileCfg.width = config.tileSize + config.borderSize*2;
  136. + tileCfg.height = config.tileSize + config.borderSize*2;
  137. +
  138. + // build all tiles
  139. + for (int y = 0; y < tileSet->height; ++y)
  140. {
  141. - tileMin[0] = bmin[0] + TILE_SIZE * x;
  142. - tileMax[0] = tileMin[0] + TILE_SIZE;
  143. -
  144. - for (uint32 y = 0; y < TILES_PER_MMTILE; ++y)
  145. + for (int x = 0; x < tileSet->width; ++x)
  146. {
  147. - tileMin[2] = bmin[2] + TILE_SIZE * y;
  148. - tileMax[2] = tileMin[2] + TILE_SIZE;
  149. -
  150. - clearIntermediateValues(iv);
  151. -
  152. - /* tile-specific config settings */
  153. - rcVcopy(config.bmin, tileMin);
  154. - rcVcopy(config.bmax, tileMax);
  155. -
  156. - // pad bounds with a border
  157. - float pad = config.borderSize*config.cs;
  158. - config.bmin[0] -= pad;
  159. - config.bmin[2] -= pad;
  160. - config.bmax[0] += pad;
  161. - config.bmax[2] += pad;
  162. -
  163. - // this sets the dimensions of the heightfield - should maybe happen before border padding
  164. - rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
  165. -
  166. - /* start build */
  167. + Tile& tile = tileSet->tiles[x + y*tileSet->width];
  168. + tile.x = x;
  169. + tile.y = y;
  170. +
  171. + // Calculate the per tile bounding box.
  172. + tileCfg.bmin[0] = config.bmin[0] + (x*config.tileSize - config.borderSize)*config.cs;
  173. + tileCfg.bmin[2] = config.bmin[2] + (y*config.tileSize - config.borderSize)*config.cs;
  174. + tileCfg.bmax[0] = config.bmin[0] + ((x+1)*config.tileSize + config.borderSize)*config.cs;
  175. + tileCfg.bmax[2] = config.bmin[2] + ((y+1)*config.tileSize + config.borderSize)*config.cs;
  176. +
  177. + float tbmin[2], tbmax[2];
  178. + tbmin[0] = tileCfg.bmin[0];
  179. + tbmin[1] = tileCfg.bmin[2];
  180. + tbmax[0] = tileCfg.bmax[0];
  181. + tbmax[1] = tileCfg.bmax[2];
  182.  
  183. // build heightfield
  184. - printf("%sBuilding Recast Heightfield... \r", tileString);
  185. - iv.heightfield = rcAllocHeightfield();
  186. - if (!iv.heightfield || !rcCreateHeightfield(m_rcContext, *iv.heightfield, config.width, config.height, config.bmin, config.bmax, config.cs, config.ch))
  187. + tile.solid = rcAllocHeightfield();
  188. + if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch))
  189. {
  190. printf("%sFailed building heightfield! \n", tileString);
  191. continue;
  192. }
  193.  
  194. - printf("%sRasterizing triangles... \r", tileString);
  195. -
  196. - // flag walkable terrain triangles
  197. - iv.triFlags = (unsigned char*)dtAlloc(sizeof(unsigned char)*tTriCount, DT_ALLOC_PERM);
  198. - memset(iv.triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char));
  199. - rcClearUnwalkableTriangles(m_rcContext, config.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, iv.triFlags);
  200. - rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, iv.triFlags, tTriCount, *iv.heightfield, config.walkableClimb);
  201. - dtFree(iv.triFlags);
  202. - iv.triFlags = NULL;
  203. + // mark all walkable tiles, both liquids and solids
  204. + unsigned char* triFlags = new unsigned char[tTriCount];
  205. + memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char));
  206. + rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
  207. + rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
  208. + delete [] triFlags;
  209.  
  210. - // filter out unwalkable spans (order of calls matters, see rcFilterLowHangingWalkableObstacles)
  211. - rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *iv.heightfield);
  212. - rcFilterLedgeSpans(m_rcContext, config.walkableHeight, config.walkableClimb, *iv.heightfield);
  213. - rcFilterWalkableLowHeightSpans(m_rcContext, config.walkableHeight, *iv.heightfield);
  214. + rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *tile.solid);
  215. + rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
  216. + rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid);
  217.  
  218. - // do after filtering because same rules don't apply to swimming
  219. - rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *iv.heightfield, config.walkableClimb);
  220. + rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb);
  221.  
  222. // compact heightfield spans
  223. - printf("%sCompacting heightfield... \r", tileString);
  224. - iv.compactHeightfield = rcAllocCompactHeightfield();
  225. - if (!iv.compactHeightfield || !rcBuildCompactHeightfield(m_rcContext, config.walkableHeight, config.walkableClimb, *iv.heightfield, *iv.compactHeightfield))
  226. + tile.chf = rcAllocCompactHeightfield();
  227. + if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf))
  228. {
  229. printf("%sFailed compacting heightfield! \n", tileString);
  230. continue;
  231. }
  232.  
  233. - if (!m_debugOutput)
  234. - {
  235. - rcFreeHeightField(iv.heightfield);
  236. - iv.heightfield = NULL;
  237. - }
  238. -
  239. // build polymesh intermediates
  240. - printf("%sEroding walkable area width... \r", tileString);
  241. - if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *iv.compactHeightfield))
  242. + if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf))
  243. {
  244. printf("%sFailed eroding area! \n", tileString);
  245. continue;
  246. }
  247.  
  248. - printf("%sSmoothing area boundaries... \r", tileString);
  249. - if (!rcMedianFilterWalkableArea(m_rcContext, *iv.compactHeightfield))
  250. - {
  251. - printf("%sFailed median filter! \n", tileString);
  252. - continue;
  253. - }
  254. -
  255. - printf("%sBuilding distance field... \r", tileString);
  256. - if (!rcBuildDistanceField(m_rcContext, *iv.compactHeightfield))
  257. + if (!rcBuildDistanceField(m_rcContext, *tile.chf))
  258. {
  259. printf("%sFailed building distance field! \n", tileString);
  260. continue;
  261. }
  262.  
  263. - // bottleneck is here
  264. - printf("%sBuilding regions... \r", tileString);
  265. - if (!rcBuildRegions(m_rcContext, *iv.compactHeightfield, config.borderSize, config.minRegionArea, config.mergeRegionArea))
  266. + if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea))
  267. {
  268. printf("%sFailed building regions! \n", tileString);
  269. continue;
  270. }
  271.  
  272. - printf("%sBuilding contours... \r", tileString);
  273. - iv.contours = rcAllocContourSet();
  274. - if (!iv.contours || !rcBuildContours(m_rcContext, *iv.compactHeightfield, config.maxSimplificationError, config.maxEdgeLen, *iv.contours))
  275. + tile.cset = rcAllocContourSet();
  276. + if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset))
  277. {
  278. printf("%sFailed building contours! \n", tileString);
  279. continue;
  280. }
  281.  
  282. // build polymesh
  283. - printf("%sBuilding polymesh... \r", tileString);
  284. - iv.polyMesh = rcAllocPolyMesh();
  285. - if (!iv.polyMesh || !rcBuildPolyMesh(m_rcContext, *iv.contours, config.maxVertsPerPoly, *iv.polyMesh))
  286. + tile.pmesh = rcAllocPolyMesh();
  287. + if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh))
  288. {
  289. printf("%sFailed building polymesh! \n", tileString);
  290. continue;
  291. }
  292.  
  293. - printf("%sBuilding polymesh detail... \r", tileString);
  294. - iv.polyMeshDetail = rcAllocPolyMeshDetail();
  295. - if (!iv.polyMeshDetail || !rcBuildPolyMeshDetail(m_rcContext, *iv.polyMesh, *iv.compactHeightfield, config.detailSampleDist, config.detailSampleMaxError, *iv.polyMeshDetail))
  296. + tile.dmesh = rcAllocPolyMeshDetail();
  297. + if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg .detailSampleMaxError, *tile.dmesh))
  298. {
  299. printf("%sFailed building polymesh detail! \n", tileString);
  300. continue;
  301. }
  302.  
  303. - if (!m_debugOutput)
  304. - {
  305. - rcFreeCompactHeightfield(iv.compactHeightfield);
  306. - iv.compactHeightfield = NULL;
  307. - rcFreeContourSet(iv.contours);
  308. - iv.contours = NULL;
  309. - }
  310. + // free those up
  311. + // we may want to keep them in the future for debug
  312. + // but right now, we don't have the code to merge them
  313. + rcFreeHeightField(tile.solid);
  314. + tile.solid = NULL;
  315. + rcFreeCompactHeightfield(tile.chf);
  316. + tile.chf = NULL;
  317. + rcFreeContourSet(tile.cset);
  318. + tile.cset = NULL;
  319. + }
  320. + }
  321.  
  322. - // this might be handled within Recast at some point
  323. - // very important, without this tiles do not get connected to neighbors!!
  324. - printf("%sCleaning vertex padding... \r", tileString);
  325. - for (int i = 0; i < iv.polyMesh->nverts; ++i)
  326. - {
  327. - unsigned short* v = &iv.polyMesh->verts[i*3];
  328. - v[0] -= (unsigned short)config.borderSize;
  329. - v[2] -= (unsigned short)config.borderSize;
  330. - }
  331. + // merge per tile poly and detail meshes
  332. + rcPolyMesh** pmmerge = new rcPolyMesh*[tileSet->width*tileSet->height];
  333. + if (!pmmerge)
  334. + {
  335. + printf("%s alloc pmmerge FIALED! \r", tileString);
  336. + return;
  337. + }
  338.  
  339. - // polymesh vertex indices are stored with ushorts in detour, can't have more than 65535
  340. - if (iv.polyMesh->nverts >= 0xffff)
  341. - {
  342. - printf("%sToo many vertices! \n", tileString);
  343. - continue;
  344. - }
  345. + rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[tileSet->width*tileSet->height];
  346. + if (!dmmerge)
  347. + {
  348. + printf("%s alloc dmmerge FIALED! \r", tileString);
  349. + return;
  350. + }
  351.  
  352. - printf("%sSetting polys as walkable... \r", tileString);
  353. - // handle area type here
  354. - // TODO: special flag for DYNAMIC polygons, ie surfaces that can be turned on and off
  355. - for (int i = 0; i < iv.polyMesh->npolys; ++i)
  356. - if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
  357. - iv.polyMesh->flags[i] = iv.polyMesh->areas[i];
  358. -
  359. - dtNavMeshCreateParams params;
  360. - memset(&params, 0, sizeof(params));
  361. - params.verts = iv.polyMesh->verts;
  362. - params.vertCount = iv.polyMesh->nverts;
  363. - params.polys = iv.polyMesh->polys;
  364. - params.polyAreas = iv.polyMesh->areas;
  365. - params.polyFlags = iv.polyMesh->flags;
  366. - params.polyCount = iv.polyMesh->npolys;
  367. - params.nvp = iv.polyMesh->nvp;
  368. - params.detailMeshes = iv.polyMeshDetail->meshes;
  369. - params.detailVerts = iv.polyMeshDetail->verts;
  370. - params.detailVertsCount = iv.polyMeshDetail->nverts;
  371. - params.detailTris = iv.polyMeshDetail->tris;
  372. - params.detailTriCount = iv.polyMeshDetail->ntris;
  373. - params.walkableHeight = agentHeight;
  374. - params.walkableRadius = agentRadius;
  375. - params.walkableClimb = agentMaxClimb;
  376. - float pos[3] = {(tileMin[0] + tileMax[0]) / 2, 0.f, (tileMin[2] + tileMax[2]) / 2}; // center of current dtTile
  377. - navMesh->calcTileLoc(pos, &params.tileX, &params.tileY);
  378. - rcVcopy(params.bmin, tileMin);
  379. - rcVcopy(params.bmax, tileMax);
  380. - params.cs = config.cs;
  381. - params.ch = config.ch;
  382. - params.tileSize = config.tileSize;
  383. -
  384. - // will hold final navmesh
  385. - unsigned char* navData = NULL;
  386. - int navDataSize = 0;
  387. -
  388. - // these values are checked within dtCreateNavMeshData - handle them here
  389. - // so we have a clear error message
  390. - if (params.nvp > DT_VERTS_PER_POLYGON)
  391. - {
  392. - printf("%sInvalid verts-per-polygon value! \n", tileString);
  393. - continue;
  394. - }
  395. - if (params.vertCount >= 0xffff)
  396. + int nmerge = 0;
  397. + for (int y = 0; y < tileSet->height; ++y)
  398. + {
  399. + for (int x = 0; x < tileSet->width; ++x)
  400. + {
  401. + Tile& tile = tileSet->tiles[x + y*tileSet->width];
  402. + if (tile.pmesh)
  403. {
  404. - printf("%sToo many vertices! \n", tileString);
  405. - continue;
  406. + pmmerge[nmerge] = tile.pmesh;
  407. + dmmerge[nmerge] = tile.dmesh;
  408. + nmerge++;
  409. }
  410. - if (!params.vertCount || !params.verts)
  411. - {
  412. - // occurs mostly when adjacent tiles have models
  413. - // loaded but those models don't span into this tile
  414. + }
  415. + }
  416.  
  417. - // message is an annoyance
  418. - //printf("%sNo vertices to build tile! \n", tileString);
  419. - continue;
  420. - }
  421. - if (!params.polyCount || !params.polys)
  422. - {
  423. - printf("%sNo polygons to build tile! \n", tileString);
  424. - continue;
  425. - }
  426. - if (!params.detailMeshes || !params.detailVerts || !params.detailTris)
  427. - {
  428. - printf("%sNo detail mesh to build tile! \n", tileString);
  429. - continue;
  430. - }
  431. + iv.polyMesh = rcAllocPolyMesh();
  432. + if (!iv.polyMesh)
  433. + {
  434. + printf("%s alloc iv.polyMesh FIALED! \r", tileString);
  435. + return;
  436. + }
  437. + rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh);
  438.  
  439. - printf("%sBuilding navmesh tile... \r", tileString);
  440. - if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
  441. - {
  442. - printf("%s Failed building navmesh tile! \n", tileString);
  443. - continue;
  444. - }
  445. + iv.polyMeshDetail = rcAllocPolyMeshDetail();
  446. + if (!iv.polyMeshDetail)
  447. + {
  448. + printf("%s alloc m_dmesh FIALED! \r", tileString);
  449. + return;
  450. + }
  451. + rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail);
  452.  
  453. - dtTileRef tileRef = 0;
  454. - printf("%sAdding tile to navmesh... \r", tileString);
  455. - // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile
  456. - // is removed via removeTile()
  457. - dtStatus dtResult = navMesh->addTile(navData, navDataSize, 0, 0, &tileRef);
  458. - if (!tileRef || dtResult != DT_SUCCESS)
  459. - {
  460. - printf("%sFailed adding tile to navmesh! \n", tileString);
  461. - continue;
  462. - }
  463. + // free things up
  464. + delete [] pmmerge;
  465. + delete [] dmmerge;
  466.  
  467. - // store tile ref so that tile can be written to disk later
  468. - finishedTiles.push_back(tileRef);
  469. - ++header.tileCount;
  470. -
  471. - // TODO: writing this to file does no good, debug data is just overwritten by next tile
  472. - //if (m_debugOutput)
  473. - //{
  474. - // for (int i = 0; i < iv.polyMesh->nverts; ++i)
  475. - // {
  476. - // unsigned short* v = &iv.polyMesh->verts[i*3];
  477. - // v[0] += (unsigned short)config.borderSize;
  478. - // v[2] += (unsigned short)config.borderSize;
  479. - // }
  480. - // writeIV(mapID, tileX, tileY, iv);
  481. - //}
  482. - }
  483. + delete tileSet;
  484. +
  485. + // remove padding for extraction
  486. + for (int i = 0; i < iv.polyMesh->nverts; ++i)
  487. + {
  488. + unsigned short* v = &iv.polyMesh->verts[i*3];
  489. + v[0] -= (unsigned short)config.borderSize;
  490. + v[2] -= (unsigned short)config.borderSize;
  491. }
  492.  
  493. - printf("%sWriting to file... \r", tileString);
  494. - for (vector<dtTileRef>::iterator it = finishedTiles.begin(); it != finishedTiles.end(); ++it)
  495. + // set polygons as walkable
  496. + // TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
  497. + for (int i = 0; i < iv.polyMesh->npolys; ++i)
  498. + if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
  499. + iv.polyMesh->flags[i] = iv.polyMesh->areas[i];
  500. +
  501. + // setup mesh parameters
  502. + dtNavMeshCreateParams params;
  503. + memset(&params, 0, sizeof(params));
  504. + params.verts = iv.polyMesh->verts;
  505. + params.vertCount = iv.polyMesh->nverts;
  506. + params.polys = iv.polyMesh->polys;
  507. + params.polyAreas = iv.polyMesh->areas;
  508. + params.polyFlags = iv.polyMesh->flags;
  509. + params.polyCount = iv.polyMesh->npolys;
  510. + params.nvp = iv.polyMesh->nvp;
  511. + params.detailMeshes = iv.polyMeshDetail->meshes;
  512. + params.detailVerts = iv.polyMeshDetail->verts;
  513. + params.detailVertsCount = iv.polyMeshDetail->nverts;
  514. + params.detailTris = iv.polyMeshDetail->tris;
  515. + params.detailTriCount = iv.polyMeshDetail->ntris;
  516. + params.walkableHeight = BASE_UNIT_DIM*config.walkableHeight; // agent height
  517. + params.walkableRadius = BASE_UNIT_DIM*config.walkableRadius; // agent radius
  518. + params.walkableClimb = BASE_UNIT_DIM*config.walkableClimb; // keep less that walkableHeight (aka agent height)!
  519. + params.tileX = (((bmin[0] + bmax[0]) / 2) - navMesh->getParams()->orig[0]) / GRID_SIZE;
  520. + params.tileY = (((bmin[2] + bmax[2]) / 2) - navMesh->getParams()->orig[2]) / GRID_SIZE;
  521. + rcVcopy(params.bmin, bmin);
  522. + rcVcopy(params.bmax, bmax);
  523. + params.cs = config.cs;
  524. + params.ch = config.ch;
  525. + params.tileSize = VERTEX_PER_MAP;
  526. +
  527. + // will hold final navmesh
  528. + unsigned char* navData = NULL;
  529. + int navDataSize = 0;
  530. +
  531. + do
  532. {
  533. - int dataSize;
  534. - unsigned char* data;
  535. + // these values are checked within dtCreateNavMeshData - handle them here
  536. + // so we have a clear error message
  537. + if (params.nvp > DT_VERTS_PER_POLYGON)
  538. + {
  539. + printf("%s Invalid verts-per-polygon value! \n", tileString);
  540. + continue;
  541. + }
  542. + if (params.vertCount >= 0xffff)
  543. + {
  544. + printf("%s Too many vertices! \n", tileString);
  545. + continue;
  546. + }
  547. + if (!params.vertCount || !params.verts)
  548. + {
  549. + // occurs mostly when adjacent tiles have models
  550. + // loaded but those models don't span into this tile
  551.  
  552. - // remove the tile from the mesh, and retrieve the tile's data so that
  553. - // we can write it to disk
  554. - navMesh->removeTile(*it, &data, &dataSize);
  555. + // message is an annoyance
  556. + //printf("%sNo vertices to build tile! \n", tileString);
  557. + continue;
  558. + }
  559. + if (!params.polyCount || !params.polys)
  560. + {
  561. + printf("%s No polygons to build tile! \n", tileString);
  562. + continue;
  563. + }
  564. + if (!params.detailMeshes || !params.detailVerts || !params.detailTris)
  565. + {
  566. + printf("%s No detail mesh to build tile! \n", tileString);
  567. + continue;
  568. + }
  569.  
  570. - fwrite(&dataSize, sizeof(dataSize), 1, file);
  571. - fwrite(data, sizeof(unsigned char), dataSize, file);
  572. + printf("%s Building navmesh tile... \r", tileString);
  573. + if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
  574. + {
  575. + printf("%s Failed building navmesh tile! \n", tileString);
  576. + continue;
  577. + }
  578.  
  579. - // free memory used by tile
  580. - dtFree(data);
  581. - }
  582. + dtTileRef tileRef = 0;
  583. + printf("%s Adding tile to navmesh... \r", tileString);
  584. + // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile
  585. + // is removed via removeTile()
  586. + dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef);
  587. + if (!tileRef || dtResult != DT_SUCCESS)
  588. + {
  589. + printf("%s Failed adding tile to navmesh! \n", tileString);
  590. + continue;
  591. + }
  592. +
  593. + // file output
  594. + char fileName[255];
  595. + sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX);
  596. + FILE* file = fopen(fileName, "wb");
  597. + if (!file)
  598. + {
  599. + char message[1024];
  600. + sprintf(message, "Failed to open %s for writing!\n", fileName);
  601. + perror(message);
  602. + navMesh->removeTile(tileRef, NULL, NULL);
  603. + continue;
  604. + }
  605. +
  606. + printf("%s Writing to file... \r", tileString);
  607. +
  608. + // write header
  609. + mmapTileHeader header(m_terrainBuilder);
  610. + header.size = uint32(navDataSize);
  611. + fwrite(&header, sizeof(mmapTileHeader), 1, file);
  612. +
  613. + // write data
  614. + fwrite(navData, sizeof(unsigned char), navDataSize, file);
  615. + fclose(file);
  616. +
  617. + // now that tile is written to disk, we can unload it
  618. + navMesh->removeTile(tileRef, NULL, NULL);
  619. + } while (0);
  620.  
  621. - // re-write header, so that tilecount is up to date
  622. - fseek(file, 0, SEEK_SET);
  623. - fwrite(&header, sizeof(header), 1, file);
  624. - fclose(file);
  625.  
  626. if (m_debugOutput)
  627. + {
  628. + // restore padding so that the debug visualization is correct
  629. + for (int i = 0; i < iv.polyMesh->nverts; ++i)
  630. + {
  631. + unsigned short* v = &iv.polyMesh->verts[i*3];
  632. + v[0] += (unsigned short)config.borderSize;
  633. + v[2] += (unsigned short)config.borderSize;
  634. + }
  635. +
  636. generateObjFile(mapID, tileX, tileY, meshData);
  637. + writeIV(mapID, tileX, tileY, iv);
  638. + }
  639.  
  640. - m_rcContext->resetLog();
  641. + clearIntermediateValues(iv);
  642. }
  643.  
  644. void MapBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax)
  645. @@ -1098,7 +1113,6 @@ namespace MMAP
  646. {
  647. iv.compactHeightfield = NULL;
  648. iv.heightfield = NULL;
  649. - iv.triFlags = NULL;
  650. iv.contours = NULL;
  651. iv.polyMesh = NULL;
  652. iv.polyMeshDetail = NULL;
  653. @@ -1111,7 +1125,6 @@ namespace MMAP
  654. rcFreeContourSet(iv.contours); iv.contours = NULL;
  655. rcFreePolyMesh(iv.polyMesh); iv.polyMesh = NULL;
  656. rcFreePolyMeshDetail(iv.polyMeshDetail); iv.polyMeshDetail = NULL;
  657. - dtFree(iv.triFlags); iv.triFlags = NULL;
  658. }
  659.  
  660. void MapBuilder::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData meshData)
  661. @@ -1119,7 +1132,7 @@ namespace MMAP
  662. generateRealObj(mapID, tileX, tileY, meshData);
  663.  
  664. char tileString[25];
  665. - sprintf(tileString, "[%02u,%02u]: ", tileX, tileY);
  666. + sprintf(tileString, "[%02u,%02u]: ", tileY, tileX);
  667. printf("%sWriting debug output... \r", tileString);
  668.  
  669. char objFileName[255];
  670. @@ -1219,24 +1232,26 @@ namespace MMAP
  671. string name("meshes/%03u%02i%02i.");
  672.  
  673. #define DEBUG_WRITE(fileExtension,data) \
  674. - sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \
  675. - file = fopen(fileName, "wb"); \
  676. - if (!file) \
  677. - { \
  678. - char message[1024]; \
  679. - sprintf(message, "%sFailed to open %s for writing!\n", tileString, fileName); \
  680. - perror(message); \
  681. - } \
  682. - else \
  683. - debugWrite(file, data); \
  684. - if(file) fclose(file); \
  685. - printf("%sWriting debug output... \r", tileString)
  686. -
  687. - DEBUG_WRITE("hf", iv.heightfield);
  688. - DEBUG_WRITE("chf", iv.compactHeightfield);
  689. - DEBUG_WRITE("cs", iv.contours);
  690. - DEBUG_WRITE("pmesh", iv.polyMesh);
  691. - DEBUG_WRITE("dmesh", iv.polyMeshDetail);
  692. + do { \
  693. + sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \
  694. + file = fopen(fileName, "wb"); \
  695. + if (!file) \
  696. + { \
  697. + char message[1024]; \
  698. + sprintf(message, "%sFailed to open %s for writing!\n", tileString, fileName); \
  699. + perror(message); \
  700. + } \
  701. + else \
  702. + debugWrite(file, data); \
  703. + if(file) fclose(file); \
  704. + printf("%sWriting debug output... \r", tileString); \
  705. + } while (false)
  706. +
  707. + if (iv.heightfield) DEBUG_WRITE("hf", iv.heightfield);
  708. + if (iv.compactHeightfield) DEBUG_WRITE("chf", iv.compactHeightfield);
  709. + if (iv.contours) DEBUG_WRITE("cs", iv.contours);
  710. + if (iv.polyMesh) DEBUG_WRITE("pmesh", iv.polyMesh);
  711. + if (iv.polyMeshDetail) DEBUG_WRITE("dmesh", iv.polyMeshDetail);
  712.  
  713. #undef DEBUG_WRITE
  714. }
  715. diff --git a/contrib/mmap/src/MapBuilder.h b/contrib/mmap/src/MapBuilder.h
  716. index ce8dea4..e8b0d90 100644
  717. --- a/contrib/mmap/src/MapBuilder.h
  718. +++ b/contrib/mmap/src/MapBuilder.h
  719. @@ -35,11 +35,8 @@ using namespace std;
  720. using namespace VMAP;
  721. // G3D namespace typedefs conflicts with ACE typedefs
  722.  
  723. -#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
  724. -#define MMAP_VERSION 1
  725. -
  726. -#define TILES_PER_MMTILE 16
  727. -#define TILE_SIZE (GRID_SIZE / TILES_PER_MMTILE)
  728. +#define MMAP_MAGIC 0x4d4d4150
  729. +#define MMAP_VERSION 2
  730.  
  731. namespace MMAP
  732. {
  733. @@ -48,7 +45,6 @@ namespace MMAP
  734. struct IntermediateValues
  735. {
  736. rcHeightfield* heightfield;
  737. - unsigned char* triFlags;
  738. rcCompactHeightfield* compactHeightfield;
  739. rcContourSet* contours;
  740. rcPolyMesh* polyMesh;
  741. @@ -60,7 +56,7 @@ namespace MMAP
  742. uint32 mmapMagic;
  743. uint32 dtVersion;
  744. uint32 mmapVersion;
  745. - uint32 tileCount;
  746. + uint32 size;
  747. bool usesHiRes : 1;
  748. bool usesLiquids : 1;
  749.  
  750. @@ -68,21 +64,51 @@ namespace MMAP
  751. mmapMagic(MMAP_MAGIC),
  752. dtVersion(DT_NAVMESH_VERSION),
  753. mmapVersion(MMAP_VERSION),
  754. - tileCount(0)
  755. + size(0)
  756. {}
  757.  
  758. mmapTileHeader(TerrainBuilder* terrainBuilder) :
  759. mmapMagic(MMAP_MAGIC),
  760. dtVersion(DT_NAVMESH_VERSION),
  761. mmapVersion(MMAP_VERSION),
  762. - tileCount(0)
  763. + size(0)
  764. {
  765. usesHiRes = terrainBuilder->usesHiRes();
  766. usesLiquids = terrainBuilder->usesLiquids();
  767. }
  768.  
  769. private:
  770. - mmapTileHeader(const mmapTileHeader &header);
  771. + mmapTileHeader(const mmapTileHeader& header);
  772. + };
  773. +
  774. + struct Tile
  775. + {
  776. + inline Tile() : chf(0), solid(0), cset(0), pmesh(0), dmesh(0), buildTime(0) {}
  777. + inline ~Tile()
  778. + {
  779. + rcFreeCompactHeightfield(chf);
  780. + rcFreeContourSet(cset);
  781. + rcFreeHeightField(solid);
  782. + rcFreePolyMesh(pmesh);
  783. + rcFreePolyMeshDetail(dmesh);
  784. + }
  785. + int x, y;
  786. + rcCompactHeightfield* chf;
  787. + rcHeightfield* solid;
  788. + rcContourSet* cset;
  789. + rcPolyMesh* pmesh;
  790. + rcPolyMeshDetail* dmesh;
  791. + int buildTime;
  792. + };
  793. +
  794. + struct TileSet
  795. + {
  796. + inline TileSet() : width(0), height(0), tiles(0) {}
  797. + inline ~TileSet() { delete [] tiles; }
  798. + int width, height;
  799. + float bmin[3], bmax[3];
  800. + float cs, ch;
  801. + Tile* tiles;
  802. };
  803.  
  804. class MapBuilder
  805. @@ -114,6 +140,7 @@ namespace MMAP
  806.  
  807. // load and unload models
  808. bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData);
  809. + void unloadVMap(uint32 mapID, uint32 tileX, uint32 tileY);
  810.  
  811. // vert and triangle methods
  812. void transform(vector<Vector3> original, vector<Vector3> &transformed,
  813. @@ -169,6 +196,7 @@ namespace MMAP
  814.  
  815. float m_maxWalkableAngle;
  816.  
  817. + // build performance - not really used for now
  818. rcContext* m_rcContext;
  819. };
  820. }
  821. diff --git a/dep/recastnavigation/RecastDemo/Include/Debug.h b/dep/recastnavigation/RecastDemo/Include/Debug.h
  822. index ae533d1..8e6e0c5 100644
  823. --- a/dep/recastnavigation/RecastDemo/Include/Debug.h
  824. +++ b/dep/recastnavigation/RecastDemo/Include/Debug.h
  825. @@ -59,13 +59,13 @@ struct mmapTileHeader
  826. unsigned int mmapMagic;
  827. unsigned int dtVersion;
  828. unsigned int mmapVersion;
  829. - unsigned int tileCount;
  830. + unsigned int size;
  831. bool usesHiRes : 1;
  832. bool usesLiquid : 1;
  833.  
  834. mmapTileHeader() :
  835. mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
  836. - mmapVersion(MMAP_VERSION), tileCount(0)
  837. + mmapVersion(MMAP_VERSION), size(0)
  838. {}
  839. };
  840.  
  841. diff --git a/dep/recastnavigation/RecastDemo/Source/Debug.cpp b/dep/recastnavigation/RecastDemo/Source/Debug.cpp
  842. index ebbc3ac..e9c4a97 100644
  843. --- a/dep/recastnavigation/RecastDemo/Source/Debug.cpp
  844. +++ b/dep/recastnavigation/RecastDemo/Source/Debug.cpp
  845. @@ -51,22 +51,16 @@ void duReadNavMesh(char* tile, dtNavMesh* &navMesh)
  846. mmapTileHeader header;
  847. fread(&header, sizeof(header), 1, file);
  848.  
  849. - unsigned int length;
  850. + unsigned char* data = (unsigned char*)dtAlloc(header.size, DT_ALLOC_PERM);
  851. + fread(data, header.size, 1, file);
  852.  
  853. - for (unsigned int i2 = 0; i2 < header.tileCount; ++i2)
  854. - {
  855. - fread(&length, sizeof(length), 1, file);
  856. -
  857. - unsigned char* data = (unsigned char*)dtAlloc(length, DT_ALLOC_PERM);
  858. - fread(data, length, 1, file);
  859. + dtStatus status = navMesh->addTile(data, header.size, DT_TILE_FREE_DATA, 0 , NULL);
  860.  
  861. - dtStatus status = navMesh->addTile(data, length, DT_TILE_FREE_DATA, 0 , NULL);
  862. + if (status != DT_SUCCESS)
  863. + dtFree(data);
  864. + else
  865. + count++;
  866.  
  867. - if (status != DT_SUCCESS)
  868. - dtFree(data);
  869. - else
  870. - count++;
  871. - }
  872. fclose(file);
  873. }
  874. }
  875. diff --git a/src/game/GridMap.h b/src/game/GridMap.h
  876. index c13a9f0..48ee48a 100644
  877. --- a/src/game/GridMap.h
  878. +++ b/src/game/GridMap.h
  879. @@ -286,7 +286,7 @@ private:
  880. void LoadNavMesh(int gx, int gy);
  881. void UnloadNavMesh(int gx, int gy);
  882. dtNavMesh* m_navMesh;
  883. - UNORDERED_MAP<uint32, std::list<dtTileRef>*> m_mmapLoadedTiles; // maps [map grid coords] to [dtTile]
  884. + UNORDERED_MAP<uint32, dtTileRef> m_mmapLoadedTiles; // maps [map grid coords] to [dtTile]
  885.  
  886. static std::set<uint32> s_mmapDisabledIds; // stores list of mapids which do not use pathfinding
  887. // end movemap-related
  888. diff --git a/src/game/MoveMap.cpp b/src/game/MoveMap.cpp
  889. index 2bcd577..a136af4 100644
  890. --- a/src/game/MoveMap.cpp
  891. +++ b/src/game/MoveMap.cpp
  892. @@ -22,38 +22,35 @@
  893. #include "Utilities/UnorderedMapSet.h"
  894. #include "World.h"
  895.  
  896. -/****** TerrainInfo navmesh load/unload ******/
  897. -
  898. uint32 packTileID(int x, int y) { return uint32(x << 16 | y); }
  899.  
  900. void TerrainInfo::LoadNavMesh(int gx, int gy)
  901. {
  902. - // load the navmesh first
  903. if (!m_navMesh)
  904. {
  905. uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i.mmap")+1;
  906. - char *fileName = new char[pathLen];
  907. - snprintf(fileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i.mmap").c_str(), m_mapId);
  908. + char *temp = new char[pathLen];
  909. + snprintf(temp, pathLen, (sWorld.GetDataPath()+"mmaps/%03i.mmap").c_str(), m_mapId);
  910. + std::string fileName = temp;
  911. + delete [] temp;
  912.  
  913. - FILE* file = fopen(fileName, "rb");
  914. + FILE* file = fopen(fileName.c_str(), "rb");
  915. if (!file)
  916. {
  917. - sLog.outDebug("MMAP: Error: Could not open mmap file '%s'", fileName);
  918. - delete [] fileName;
  919. + sLog.outDebug("MMAP: Error: Could not open mmap file '%s'", fileName.c_str());
  920. return;
  921. }
  922.  
  923. dtNavMeshParams params;
  924. fread(&params, sizeof(dtNavMeshParams), 1, file);
  925. fclose(file);
  926. - delete [] fileName;
  927.  
  928. m_navMesh = dtAllocNavMesh();
  929. if (!m_navMesh->init(&params))
  930. {
  931. dtFreeNavMesh(m_navMesh);
  932. m_navMesh = NULL;
  933. - sLog.outError("MMAP: Failed to initialize mmap %03u from file %s", m_mapId, fileName);
  934. + sLog.outError("MMAP: Failed to initialize mmap %03u from file %s", m_mapId, fileName.c_str());
  935. return;
  936. }
  937. }
  938. @@ -66,56 +63,73 @@ void TerrainInfo::LoadNavMesh(int gx, int gy)
  939. return;
  940. }
  941.  
  942. - // now load the tile
  943. - MmapTileReader reader(m_mapId, gx, gy);
  944. - if (!reader.check())
  945. + // mmaps/0000000.mmtile
  946. + uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1;
  947. + char *fileName = new char[pathLen];
  948. + snprintf(fileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), m_mapId, gx, gy);
  949. +
  950. + FILE *file = fopen(fileName, "rb");
  951. + if (!file)
  952. {
  953. - sLog.outError("MMAP: Bad header in mmap %03u%02i%02i.mmtile", m_mapId, gx, gy);
  954. + sLog.outDebug("MMAP: Could not open mmtile file '%s'", fileName);
  955. + delete [] fileName;
  956. return;
  957. }
  958. + delete [] fileName;
  959.  
  960. - tileRefList* newTiles = new tileRefList();
  961. - unsigned char* data = NULL;
  962. - uint32 length = 0;
  963. + // read header
  964. + mmapTileHeader fileHeader;
  965. + fread(&fileHeader, sizeof(mmapTileHeader), 1, file);
  966.  
  967. - while (reader.read(data, length))
  968. + if (fileHeader.mmapMagic != MMAP_MAGIC)
  969. {
  970. - dtMeshHeader* header = (dtMeshHeader*)data;
  971. - dtTileRef tileRef = 0;
  972. -
  973. - // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
  974. - dtStatus dtResult = m_navMesh->addTile(data, length, DT_TILE_FREE_DATA, 0, &tileRef);
  975. - if(dtResult == DT_SUCCESS)
  976. - newTiles->push_back(tileRef);
  977. - else
  978. - dtFree(data);
  979. + sLog.outError("MMAP: Bad header in mmap %03u%02i%02i.mmtile", m_mapId, gx, gy);
  980. + return;
  981. }
  982.  
  983. - // have we loaded everything we expected?
  984. - if(reader.getTileCount() == newTiles->size())
  985. - {
  986. - sLog.outDetail("MMAP: Loaded mmtile %03i[%02i,%02i]", m_mapId, gx, gy);
  987. - m_mmapLoadedTiles.insert(std::pair<uint32, tileRefList*>(packedGridPos, newTiles));
  988. - }
  989. - else
  990. - {
  991. - // one or more of the tiles failed
  992. - // we cannot allow having partially loaded maps
  993. - sLog.outError("MMAP: Could not load %03u%02i%02i.mmtile into navmesh", m_mapId, gx, gy);
  994. + unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM);
  995. + MANGOS_ASSERT(data);
  996.  
  997. - // unload everything we can
  998. - for (tileRefList::iterator itr = newTiles->begin(); itr != newTiles->end(); )
  999. + fread(data, fileHeader.size, 1, file);
  1000. + fclose(file);
  1001. +
  1002. + dtMeshHeader* header = (dtMeshHeader*)data;
  1003. + dtTileRef tileRef = 0;
  1004. +
  1005. + // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
  1006. + dtStatus dtResult = m_navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef);
  1007. + switch(dtResult)
  1008. + {
  1009. + case DT_SUCCESS:
  1010. {
  1011. - if(DT_SUCCESS == m_navMesh->removeTile(*itr, NULL, NULL))
  1012. - itr = newTiles->erase(itr);
  1013. - else
  1014. - ++itr;
  1015. + m_mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
  1016. + sLog.outDetail("MMAP: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", m_mapId, gx, gy, m_mapId, header->x, header->y);
  1017. }
  1018. -
  1019. - // if we got here with newTiles not empty its really bad - but again, we cannot recover
  1020. - MANGOS_ASSERT(newTiles->empty());
  1021. - delete newTiles;
  1022. + break;
  1023. + case DT_FAILURE_DATA_MAGIC:
  1024. + {
  1025. + sLog.outError("MMAP: %03u%02i%02i.mmtile has an invalid header", m_mapId, gx, gy);
  1026. + dtFree(data);
  1027. + }
  1028. + break;
  1029. + case DT_FAILURE_DATA_VERSION:
  1030. + {
  1031. + 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);
  1032. + dtFree(data);
  1033. + }
  1034. + break;
  1035. + case DT_FAILURE_OUT_OF_MEMORY:
  1036. + case DT_FAILURE:
  1037. + default:
  1038. + {
  1039. + sLog.outError("MMAP: Could not load %03u%02i%02i.mmtile into navmesh", m_mapId, gx, gy);
  1040. + dtFree(data);
  1041. + }
  1042. + break;
  1043. }
  1044. +
  1045. + if (fileHeader.mmapVersion != MMAP_VERSION)
  1046. + sLog.outDebug("MMAP: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", m_mapId, gx, gy, fileHeader.mmapVersion, MMAP_VERSION);
  1047. }
  1048.  
  1049. void TerrainInfo::UnloadNavMesh(int gx, int gy)
  1050. @@ -132,29 +146,20 @@ void TerrainInfo::UnloadNavMesh(int gx, int gy)
  1051. return;
  1052. }
  1053.  
  1054. - tileRefList* tiles = m_mmapLoadedTiles[packedGridPos];
  1055. - for (tileRefList::iterator itr = tiles->begin(); itr != tiles->end(); )
  1056. + dtTileRef tileRef = m_mmapLoadedTiles[packedGridPos];
  1057. +
  1058. + // unload, and mark as non loaded
  1059. + if(DT_SUCCESS != m_navMesh->removeTile(tileRef, NULL, NULL))
  1060. {
  1061. - // unload, and mark as non loaded
  1062. - if(DT_SUCCESS == m_navMesh->removeTile(*itr, NULL, NULL))
  1063. - itr = tiles->erase(itr);
  1064. - else
  1065. - ++itr;
  1066. + // because the Terrain unloads the grid, this is technically a memory leak
  1067. + // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
  1068. + sLog.outError("MMAP: Could not unload %03u%02i%02i.mmtile from navmesh", m_mapId, gx, gy);
  1069. }
  1070. -
  1071. - if (tiles->empty())
  1072. - sLog.outDetail("MMAP: Unloaded mmtile %03i[%02i,%02i] from %03i", m_mapId, gx, gy, m_mapId);
  1073. else
  1074. {
  1075. - // because the Terrain unloads the grid, this is technically a memory leak
  1076. - // if the grid is later loaded, dtNavMesh::addTile will return errors for the dtTileRefs we were unable to unload
  1077. - // if we got here, something is really worng - we cannot recover anyway
  1078. - sLog.outError("MMAP: Could not unload %u tile(s) from navmesh (%03u%02i%02i.mmtile)", tiles->size(), m_mapId, gx, gy);
  1079. - MANGOS_ASSERT(false);
  1080. + m_mmapLoadedTiles.erase(packedGridPos);
  1081. + sLog.outDetail("MMAP: Unloaded mmtile %03i[%02i,%02i] from %03i", m_mapId, gx, gy, m_mapId);
  1082. }
  1083. -
  1084. - delete tiles;
  1085. - m_mmapLoadedTiles.erase(packedGridPos);
  1086. }
  1087.  
  1088. dtNavMesh const* TerrainInfo::GetNavMesh() const
  1089. @@ -162,8 +167,6 @@ dtNavMesh const* TerrainInfo::GetNavMesh() const
  1090. return m_navMesh;
  1091. }
  1092.  
  1093. -/****** pathfinding enabled/disabled ******/
  1094. -
  1095. std::set<uint32> TerrainInfo::s_mmapDisabledIds = std::set<uint32>();
  1096.  
  1097. void TerrainInfo::preventPathfindingOnMaps(std::string ignoreMapIds)
  1098. @@ -187,87 +190,3 @@ bool TerrainInfo::IsPathfindingEnabled() const
  1099. {
  1100. return sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED) && s_mmapDisabledIds.find(m_mapId) == s_mmapDisabledIds.end();
  1101. }
  1102. -
  1103. -/****** MmapTileReader ******/
  1104. -MmapTileReader::MmapTileReader(uint32 mapId, int32 x, int32 y)
  1105. - : m_mmapTileFile(NULL), m_currentTile(0), m_mmapFileName(NULL)
  1106. -{
  1107. - // mmaps/0000000.mmtile
  1108. - uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1;
  1109. - m_mmapFileName = new char[pathLen];
  1110. - snprintf(m_mmapFileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
  1111. -
  1112. - m_mmapTileFile = fopen(m_mmapFileName, "rb");
  1113. - if (!m_mmapTileFile)
  1114. - return;
  1115. -
  1116. - uint32 bytesRead = fread(&m_header, 1, sizeof(mmapTileHeader), m_mmapTileFile);
  1117. - if (bytesRead != sizeof(mmapTileHeader))
  1118. - memset(&m_header, 0, sizeof(mmapTileHeader));
  1119. -}
  1120. -
  1121. -MmapTileReader::~MmapTileReader()
  1122. -{
  1123. - delete [] m_mmapFileName;
  1124. -
  1125. - if (m_mmapTileFile)
  1126. - fclose(m_mmapTileFile);
  1127. -}
  1128. -
  1129. -bool MmapTileReader::check()
  1130. -{
  1131. - if (!m_mmapTileFile)
  1132. - {
  1133. - sLog.outDebug("Could not open mmtile file '%s'", m_mmapFileName);
  1134. - return false;
  1135. - }
  1136. -
  1137. - if (m_header.mmapMagic != MMAP_MAGIC)
  1138. - {
  1139. - sLog.outError("mmtile file '%s' has wrong format", m_mmapFileName);
  1140. - return false;
  1141. - }
  1142. -
  1143. - if (m_header.dtVersion != DT_NAVMESH_VERSION)
  1144. - {
  1145. - sLog.outError("mmtile file '%s' was built with Detour v%i, expected v%", m_mmapFileName, m_header.dtVersion, DT_NAVMESH_VERSION);
  1146. - return false;
  1147. - }
  1148. -
  1149. - if (m_header.tileCount == 0)
  1150. - {
  1151. - sLog.outDebug("mmtile file '%s' contains 0 tiles", m_mmapFileName);
  1152. - return false;
  1153. - }
  1154. -
  1155. - return true;
  1156. -}
  1157. -
  1158. -bool MmapTileReader::read(unsigned char* &data, uint32 &dataLength)
  1159. -{
  1160. - if (!m_mmapTileFile)
  1161. - return false;
  1162. -
  1163. - uint32 bytesRead = fread(&dataLength, 1, sizeof(uint32), m_mmapTileFile);
  1164. - if (sizeof(uint32) != bytesRead)
  1165. - return false;
  1166. -
  1167. - // check if we have read all the tiles
  1168. - if (m_header.tileCount <= m_currentTile)
  1169. - return false;
  1170. -
  1171. - // allocate and read tile data
  1172. - data = (unsigned char*)dtAlloc(dataLength, DT_ALLOC_PERM);
  1173. - MANGOS_ASSERT(data);
  1174. -
  1175. - bytesRead = fread(data, 1, dataLength, m_mmapTileFile);
  1176. - if (bytesRead != dataLength)
  1177. - {
  1178. - dtFree(data);
  1179. - return false;
  1180. - }
  1181. -
  1182. - m_currentTile++;
  1183. -
  1184. - return true;
  1185. -}
  1186. diff --git a/src/game/MoveMap.h b/src/game/MoveMap.h
  1187. index 2cb4e47..fa0d41a 100644
  1188. --- a/src/game/MoveMap.h
  1189. +++ b/src/game/MoveMap.h
  1190. @@ -20,10 +20,8 @@
  1191. #define _MOVE_MAP_H
  1192.  
  1193. #include "Platform/Define.h"
  1194. -#include <list>
  1195.  
  1196. #include "../../dep/recastnavigation/Detour/Include/DetourAlloc.h"
  1197. -#include "../../dep/recastnavigation/Detour/Include/DetourNavMesh.h"
  1198.  
  1199. /* memory management */
  1200.  
  1201. @@ -37,40 +35,19 @@ inline void dtCustomFree(void* ptr)
  1202. delete [] (unsigned char*)ptr;
  1203. }
  1204.  
  1205. -/* mmap tile structure */
  1206. +/* mmap file info */
  1207.  
  1208. #define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
  1209. -#define MMAP_VERSION 1
  1210. +#define MMAP_VERSION 2
  1211.  
  1212. struct mmapTileHeader
  1213. {
  1214. uint32 mmapMagic;
  1215. uint32 dtVersion;
  1216. uint32 mmapVersion;
  1217. - uint32 tileCount;
  1218. + uint32 size;
  1219. bool usesHiRes : 1;
  1220. bool usesLiquids : 1;
  1221. };
  1222.  
  1223. -typedef std::list<dtTileRef> tileRefList;
  1224. -
  1225. -class MmapTileReader
  1226. -{
  1227. -public:
  1228. - MmapTileReader(uint32 mapId, int32 x, int32 y);
  1229. - ~MmapTileReader();
  1230. -
  1231. - // validates the mmtile file
  1232. - bool check();
  1233. -
  1234. - // reads and returns the next dtMeshTile data
  1235. - bool read(unsigned char* &data, uint32 &dataLength);
  1236. - uint32 getTileCount() { return m_header.tileCount; }
  1237. -private:
  1238. - char* m_mmapFileName;
  1239. - FILE* m_mmapTileFile;
  1240. - mmapTileHeader m_header;
  1241. - uint32 m_currentTile;
  1242. -};
  1243. -
  1244. #endif // _MOVE_MAP_H
Add Comment
Please, Sign In to add comment