DetourTileCache.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. // Modified by Lasse Oorni and cosmy1 for Urho3D
  2. #include "DetourTileCache.h"
  3. #include "DetourTileCacheBuilder.h"
  4. #include "DetourNavMeshBuilder.h"
  5. #include "DetourNavMesh.h"
  6. #include "DetourCommon.h"
  7. #include "DetourMath.h"
  8. #include "DetourAlloc.h"
  9. #include "DetourAssert.h"
  10. #include <string.h>
  11. #include <new>
  12. dtTileCache* dtAllocTileCache()
  13. {
  14. void* mem = dtAlloc(sizeof(dtTileCache), DT_ALLOC_PERM);
  15. if (!mem) return 0;
  16. return new(mem) dtTileCache;
  17. }
  18. void dtFreeTileCache(dtTileCache* tc)
  19. {
  20. if (!tc) return;
  21. tc->~dtTileCache();
  22. dtFree(tc);
  23. }
  24. static bool contains(const dtCompressedTileRef* a, const int n, const dtCompressedTileRef v)
  25. {
  26. for (int i = 0; i < n; ++i)
  27. if (a[i] == v)
  28. return true;
  29. return false;
  30. }
  31. inline int computeTileHash(int x, int y, const int mask)
  32. {
  33. const unsigned int h1 = 0x8da6b343; // Large multiplicative constants;
  34. const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes
  35. unsigned int n = h1 * x + h2 * y;
  36. return (int)(n & mask);
  37. }
  38. struct BuildContext
  39. {
  40. inline BuildContext(struct dtTileCacheAlloc* a) : layer(0), lcset(0), lmesh(0), alloc(a) {}
  41. inline ~BuildContext() { purge(); }
  42. void purge()
  43. {
  44. dtFreeTileCacheLayer(alloc, layer);
  45. layer = 0;
  46. dtFreeTileCacheContourSet(alloc, lcset);
  47. lcset = 0;
  48. dtFreeTileCachePolyMesh(alloc, lmesh);
  49. lmesh = 0;
  50. }
  51. struct dtTileCacheLayer* layer;
  52. struct dtTileCacheContourSet* lcset;
  53. struct dtTileCachePolyMesh* lmesh;
  54. struct dtTileCacheAlloc* alloc;
  55. };
  56. dtTileCache::dtTileCache() :
  57. m_tileLutSize(0),
  58. m_tileLutMask(0),
  59. m_posLookup(0),
  60. m_nextFreeTile(0),
  61. m_tiles(0),
  62. m_saltBits(0),
  63. m_tileBits(0),
  64. m_talloc(0),
  65. m_tcomp(0),
  66. m_tmproc(0),
  67. m_obstacles(0),
  68. m_nextFreeObstacle(0),
  69. m_nreqs(0),
  70. m_nupdate(0)
  71. {
  72. memset(&m_params, 0, sizeof(m_params));
  73. // Urho3D: initialize all class members
  74. memset(&m_reqs, 0, sizeof(m_reqs));
  75. memset(&m_update, 0, sizeof(m_update));
  76. }
  77. dtTileCache::~dtTileCache()
  78. {
  79. // Urho3D: added null check for tile allocation
  80. if (m_tiles)
  81. {
  82. for (int i = 0; i < m_params.maxTiles; ++i)
  83. {
  84. if (m_tiles[i].flags & DT_COMPRESSEDTILE_FREE_DATA)
  85. {
  86. dtFree(m_tiles[i].data);
  87. m_tiles[i].data = 0;
  88. }
  89. }
  90. }
  91. dtFree(m_obstacles);
  92. m_obstacles = 0;
  93. dtFree(m_posLookup);
  94. m_posLookup = 0;
  95. dtFree(m_tiles);
  96. m_tiles = 0;
  97. m_nreqs = 0;
  98. m_nupdate = 0;
  99. }
  100. const dtCompressedTile* dtTileCache::getTileByRef(dtCompressedTileRef ref) const
  101. {
  102. if (!ref)
  103. return 0;
  104. unsigned int tileIndex = decodeTileIdTile(ref);
  105. unsigned int tileSalt = decodeTileIdSalt(ref);
  106. if ((int)tileIndex >= m_params.maxTiles)
  107. return 0;
  108. const dtCompressedTile* tile = &m_tiles[tileIndex];
  109. if (tile->salt != tileSalt)
  110. return 0;
  111. return tile;
  112. }
  113. dtStatus dtTileCache::init(const dtTileCacheParams* params,
  114. dtTileCacheAlloc* talloc,
  115. dtTileCacheCompressor* tcomp,
  116. dtTileCacheMeshProcess* tmproc)
  117. {
  118. m_talloc = talloc;
  119. m_tcomp = tcomp;
  120. m_tmproc = tmproc;
  121. m_nreqs = 0;
  122. memcpy(&m_params, params, sizeof(m_params));
  123. // Alloc space for obstacles.
  124. m_obstacles = (dtTileCacheObstacle*)dtAlloc(sizeof(dtTileCacheObstacle)*m_params.maxObstacles, DT_ALLOC_PERM);
  125. if (!m_obstacles)
  126. return DT_FAILURE | DT_OUT_OF_MEMORY;
  127. memset(m_obstacles, 0, sizeof(dtTileCacheObstacle)*m_params.maxObstacles);
  128. m_nextFreeObstacle = 0;
  129. for (int i = m_params.maxObstacles-1; i >= 0; --i)
  130. {
  131. m_obstacles[i].salt = 1;
  132. m_obstacles[i].next = m_nextFreeObstacle;
  133. m_nextFreeObstacle = &m_obstacles[i];
  134. }
  135. // Init tiles
  136. m_tileLutSize = dtNextPow2(m_params.maxTiles/4);
  137. if (!m_tileLutSize) m_tileLutSize = 1;
  138. m_tileLutMask = m_tileLutSize-1;
  139. m_tiles = (dtCompressedTile*)dtAlloc(sizeof(dtCompressedTile)*m_params.maxTiles, DT_ALLOC_PERM);
  140. if (!m_tiles)
  141. return DT_FAILURE | DT_OUT_OF_MEMORY;
  142. m_posLookup = (dtCompressedTile**)dtAlloc(sizeof(dtCompressedTile*)*m_tileLutSize, DT_ALLOC_PERM);
  143. if (!m_posLookup)
  144. return DT_FAILURE | DT_OUT_OF_MEMORY;
  145. memset(m_tiles, 0, sizeof(dtCompressedTile)*m_params.maxTiles);
  146. memset(m_posLookup, 0, sizeof(dtCompressedTile*)*m_tileLutSize);
  147. m_nextFreeTile = 0;
  148. for (int i = m_params.maxTiles-1; i >= 0; --i)
  149. {
  150. m_tiles[i].salt = 1;
  151. m_tiles[i].next = m_nextFreeTile;
  152. m_nextFreeTile = &m_tiles[i];
  153. }
  154. // Init ID generator values.
  155. m_tileBits = dtIlog2(dtNextPow2((unsigned int)m_params.maxTiles));
  156. // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
  157. m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits);
  158. if (m_saltBits < 10)
  159. return DT_FAILURE | DT_INVALID_PARAM;
  160. return DT_SUCCESS;
  161. }
  162. int dtTileCache::getTilesAt(const int tx, const int ty, dtCompressedTileRef* tiles, const int maxTiles) const
  163. {
  164. int n = 0;
  165. // Find tile based on hash.
  166. int h = computeTileHash(tx,ty,m_tileLutMask);
  167. dtCompressedTile* tile = m_posLookup[h];
  168. while (tile)
  169. {
  170. if (tile->header &&
  171. tile->header->tx == tx &&
  172. tile->header->ty == ty)
  173. {
  174. if (n < maxTiles)
  175. tiles[n++] = getTileRef(tile);
  176. }
  177. tile = tile->next;
  178. }
  179. return n;
  180. }
  181. dtCompressedTile* dtTileCache::getTileAt(const int tx, const int ty, const int tlayer)
  182. {
  183. // Find tile based on hash.
  184. int h = computeTileHash(tx,ty,m_tileLutMask);
  185. dtCompressedTile* tile = m_posLookup[h];
  186. while (tile)
  187. {
  188. if (tile->header &&
  189. tile->header->tx == tx &&
  190. tile->header->ty == ty &&
  191. tile->header->tlayer == tlayer)
  192. {
  193. return tile;
  194. }
  195. tile = tile->next;
  196. }
  197. return 0;
  198. }
  199. dtCompressedTileRef dtTileCache::getTileRef(const dtCompressedTile* tile) const
  200. {
  201. if (!tile) return 0;
  202. const unsigned int it = (unsigned int)(tile - m_tiles);
  203. return (dtCompressedTileRef)encodeTileId(tile->salt, it);
  204. }
  205. dtObstacleRef dtTileCache::getObstacleRef(const dtTileCacheObstacle* ob) const
  206. {
  207. if (!ob) return 0;
  208. const unsigned int idx = (unsigned int)(ob - m_obstacles);
  209. return encodeObstacleId(ob->salt, idx);
  210. }
  211. const dtTileCacheObstacle* dtTileCache::getObstacleByRef(dtObstacleRef ref)
  212. {
  213. if (!ref)
  214. return 0;
  215. unsigned int idx = decodeObstacleIdObstacle(ref);
  216. if ((int)idx >= m_params.maxObstacles)
  217. return 0;
  218. const dtTileCacheObstacle* ob = &m_obstacles[idx];
  219. unsigned int salt = decodeObstacleIdSalt(ref);
  220. if (ob->salt != salt)
  221. return 0;
  222. return ob;
  223. }
  224. dtStatus dtTileCache::addTile(unsigned char* data, const int dataSize, unsigned char flags, dtCompressedTileRef* result)
  225. {
  226. // Make sure the data is in right format.
  227. dtTileCacheLayerHeader* header = (dtTileCacheLayerHeader*)data;
  228. if (header->magic != DT_TILECACHE_MAGIC)
  229. return DT_FAILURE | DT_WRONG_MAGIC;
  230. if (header->version != DT_TILECACHE_VERSION)
  231. return DT_FAILURE | DT_WRONG_VERSION;
  232. // Make sure the location is free.
  233. if (getTileAt(header->tx, header->ty, header->tlayer))
  234. return DT_FAILURE;
  235. // Allocate a tile.
  236. dtCompressedTile* tile = 0;
  237. if (m_nextFreeTile)
  238. {
  239. tile = m_nextFreeTile;
  240. m_nextFreeTile = tile->next;
  241. tile->next = 0;
  242. }
  243. // Make sure we could allocate a tile.
  244. if (!tile)
  245. return DT_FAILURE | DT_OUT_OF_MEMORY;
  246. // Insert tile into the position lut.
  247. int h = computeTileHash(header->tx, header->ty, m_tileLutMask);
  248. tile->next = m_posLookup[h];
  249. m_posLookup[h] = tile;
  250. // Init tile.
  251. const int headerSize = dtAlign4(sizeof(dtTileCacheLayerHeader));
  252. tile->header = (dtTileCacheLayerHeader*)data;
  253. tile->data = data;
  254. tile->dataSize = dataSize;
  255. tile->compressed = tile->data + headerSize;
  256. tile->compressedSize = tile->dataSize - headerSize;
  257. tile->flags = flags;
  258. if (result)
  259. *result = getTileRef(tile);
  260. return DT_SUCCESS;
  261. }
  262. dtStatus dtTileCache::removeTile(dtCompressedTileRef ref, unsigned char** data, int* dataSize)
  263. {
  264. if (!ref)
  265. return DT_FAILURE | DT_INVALID_PARAM;
  266. unsigned int tileIndex = decodeTileIdTile(ref);
  267. unsigned int tileSalt = decodeTileIdSalt(ref);
  268. if ((int)tileIndex >= m_params.maxTiles)
  269. return DT_FAILURE | DT_INVALID_PARAM;
  270. dtCompressedTile* tile = &m_tiles[tileIndex];
  271. if (tile->salt != tileSalt)
  272. return DT_FAILURE | DT_INVALID_PARAM;
  273. // Remove tile from hash lookup.
  274. const int h = computeTileHash(tile->header->tx,tile->header->ty,m_tileLutMask);
  275. dtCompressedTile* prev = 0;
  276. dtCompressedTile* cur = m_posLookup[h];
  277. while (cur)
  278. {
  279. if (cur == tile)
  280. {
  281. if (prev)
  282. prev->next = cur->next;
  283. else
  284. m_posLookup[h] = cur->next;
  285. break;
  286. }
  287. prev = cur;
  288. cur = cur->next;
  289. }
  290. // Reset tile.
  291. if (tile->flags & DT_COMPRESSEDTILE_FREE_DATA)
  292. {
  293. // Owns data
  294. dtFree(tile->data);
  295. tile->data = 0;
  296. tile->dataSize = 0;
  297. if (data) *data = 0;
  298. if (dataSize) *dataSize = 0;
  299. }
  300. else
  301. {
  302. if (data) *data = tile->data;
  303. if (dataSize) *dataSize = tile->dataSize;
  304. }
  305. tile->header = 0;
  306. tile->data = 0;
  307. tile->dataSize = 0;
  308. tile->compressed = 0;
  309. tile->compressedSize = 0;
  310. tile->flags = 0;
  311. // Update salt, salt should never be zero.
  312. tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
  313. if (tile->salt == 0)
  314. tile->salt++;
  315. // Add to free list.
  316. tile->next = m_nextFreeTile;
  317. m_nextFreeTile = tile;
  318. return DT_SUCCESS;
  319. }
  320. dtObstacleRef dtTileCache::addObstacle(const float* pos, const float radius, const float height, dtObstacleRef* result)
  321. {
  322. if (m_nreqs >= MAX_REQUESTS)
  323. return DT_FAILURE | DT_BUFFER_TOO_SMALL;
  324. dtTileCacheObstacle* ob = 0;
  325. if (m_nextFreeObstacle)
  326. {
  327. ob = m_nextFreeObstacle;
  328. m_nextFreeObstacle = ob->next;
  329. ob->next = 0;
  330. }
  331. if (!ob)
  332. return DT_FAILURE | DT_OUT_OF_MEMORY;
  333. unsigned short salt = ob->salt;
  334. memset(ob, 0, sizeof(dtTileCacheObstacle));
  335. ob->salt = salt;
  336. ob->state = DT_OBSTACLE_PROCESSING;
  337. dtVcopy(ob->pos, pos);
  338. ob->radius = radius;
  339. ob->height = height;
  340. ObstacleRequest* req = &m_reqs[m_nreqs++];
  341. memset(req, 0, sizeof(ObstacleRequest));
  342. req->action = REQUEST_ADD;
  343. req->ref = getObstacleRef(ob);
  344. if (result)
  345. *result = req->ref;
  346. return DT_SUCCESS;
  347. }
  348. dtObstacleRef dtTileCache::removeObstacle(const dtObstacleRef ref)
  349. {
  350. if (!ref)
  351. return DT_SUCCESS;
  352. if (m_nreqs >= MAX_REQUESTS)
  353. return DT_FAILURE | DT_BUFFER_TOO_SMALL;
  354. ObstacleRequest* req = &m_reqs[m_nreqs++];
  355. memset(req, 0, sizeof(ObstacleRequest));
  356. req->action = REQUEST_REMOVE;
  357. req->ref = ref;
  358. return DT_SUCCESS;
  359. }
  360. dtStatus dtTileCache::queryTiles(const float* bmin, const float* bmax,
  361. dtCompressedTileRef* results, int* resultCount, const int maxResults) const
  362. {
  363. const int MAX_TILES = 32;
  364. dtCompressedTileRef tiles[MAX_TILES];
  365. int n = 0;
  366. const float tw = m_params.width * m_params.cs;
  367. const float th = m_params.height * m_params.cs;
  368. const int tx0 = (int)dtMathFloorf((bmin[0]-m_params.orig[0]) / tw);
  369. const int tx1 = (int)dtMathFloorf((bmax[0]-m_params.orig[0]) / tw);
  370. const int ty0 = (int)dtMathFloorf((bmin[2]-m_params.orig[2]) / th);
  371. const int ty1 = (int)dtMathFloorf((bmax[2]-m_params.orig[2]) / th);
  372. for (int ty = ty0; ty <= ty1; ++ty)
  373. {
  374. for (int tx = tx0; tx <= tx1; ++tx)
  375. {
  376. const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
  377. for (int i = 0; i < ntiles; ++i)
  378. {
  379. const dtCompressedTile* tile = &m_tiles[decodeTileIdTile(tiles[i])];
  380. float tbmin[3], tbmax[3];
  381. calcTightTileBounds(tile->header, tbmin, tbmax);
  382. if (dtOverlapBounds(bmin,bmax, tbmin,tbmax))
  383. {
  384. if (n < maxResults)
  385. results[n++] = tiles[i];
  386. }
  387. }
  388. }
  389. }
  390. *resultCount = n;
  391. return DT_SUCCESS;
  392. }
  393. dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
  394. {
  395. if (m_nupdate == 0)
  396. {
  397. // Process requests.
  398. for (int i = 0; i < m_nreqs; ++i)
  399. {
  400. ObstacleRequest* req = &m_reqs[i];
  401. unsigned int idx = decodeObstacleIdObstacle(req->ref);
  402. if ((int)idx >= m_params.maxObstacles)
  403. continue;
  404. dtTileCacheObstacle* ob = &m_obstacles[idx];
  405. unsigned int salt = decodeObstacleIdSalt(req->ref);
  406. if (ob->salt != salt)
  407. continue;
  408. if (req->action == REQUEST_ADD)
  409. {
  410. // Find touched tiles.
  411. float bmin[3], bmax[3];
  412. getObstacleBounds(ob, bmin, bmax);
  413. int ntouched = 0;
  414. queryTiles(bmin, bmax, ob->touched, &ntouched, DT_MAX_TOUCHED_TILES);
  415. ob->ntouched = (unsigned char)ntouched;
  416. // Add tiles to update list.
  417. ob->npending = 0;
  418. for (int j = 0; j < ob->ntouched; ++j)
  419. {
  420. if (m_nupdate < MAX_UPDATE)
  421. {
  422. if (!contains(m_update, m_nupdate, ob->touched[j]))
  423. m_update[m_nupdate++] = ob->touched[j];
  424. ob->pending[ob->npending++] = ob->touched[j];
  425. }
  426. }
  427. }
  428. else if (req->action == REQUEST_REMOVE)
  429. {
  430. // Prepare to remove obstacle.
  431. ob->state = DT_OBSTACLE_REMOVING;
  432. // Add tiles to update list.
  433. ob->npending = 0;
  434. for (int j = 0; j < ob->ntouched; ++j)
  435. {
  436. if (m_nupdate < MAX_UPDATE)
  437. {
  438. if (!contains(m_update, m_nupdate, ob->touched[j]))
  439. m_update[m_nupdate++] = ob->touched[j];
  440. ob->pending[ob->npending++] = ob->touched[j];
  441. }
  442. }
  443. }
  444. }
  445. m_nreqs = 0;
  446. }
  447. // Process updates
  448. if (m_nupdate)
  449. {
  450. // Build mesh
  451. const dtCompressedTileRef ref = m_update[0];
  452. dtStatus status = buildNavMeshTile(ref, navmesh);
  453. m_nupdate--;
  454. if (m_nupdate > 0)
  455. memmove(m_update, m_update+1, m_nupdate*sizeof(dtCompressedTileRef));
  456. // Update obstacle states.
  457. for (int i = 0; i < m_params.maxObstacles; ++i)
  458. {
  459. dtTileCacheObstacle* ob = &m_obstacles[i];
  460. if (ob->state == DT_OBSTACLE_PROCESSING || ob->state == DT_OBSTACLE_REMOVING)
  461. {
  462. // Remove handled tile from pending list.
  463. for (int j = 0; j < (int)ob->npending; j++)
  464. {
  465. if (ob->pending[j] == ref)
  466. {
  467. ob->pending[j] = ob->pending[(int)ob->npending-1];
  468. ob->npending--;
  469. break;
  470. }
  471. }
  472. // If all pending tiles processed, change state.
  473. if (ob->npending == 0)
  474. {
  475. if (ob->state == DT_OBSTACLE_PROCESSING)
  476. {
  477. ob->state = DT_OBSTACLE_PROCESSED;
  478. }
  479. else if (ob->state == DT_OBSTACLE_REMOVING)
  480. {
  481. ob->state = DT_OBSTACLE_EMPTY;
  482. // Update salt, salt should never be zero.
  483. ob->salt = (ob->salt+1) & ((1<<16)-1);
  484. if (ob->salt == 0)
  485. ob->salt++;
  486. // Return obstacle to free list.
  487. ob->next = m_nextFreeObstacle;
  488. m_nextFreeObstacle = ob;
  489. }
  490. }
  491. }
  492. }
  493. if (dtStatusFailed(status))
  494. return status;
  495. }
  496. return DT_SUCCESS;
  497. }
  498. dtStatus dtTileCache::buildNavMeshTilesAt(const int tx, const int ty, dtNavMesh* navmesh)
  499. {
  500. const int MAX_TILES = 32;
  501. dtCompressedTileRef tiles[MAX_TILES];
  502. const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
  503. for (int i = 0; i < ntiles; ++i)
  504. {
  505. dtStatus status = buildNavMeshTile(tiles[i], navmesh);
  506. if (dtStatusFailed(status))
  507. return status;
  508. }
  509. return DT_SUCCESS;
  510. }
  511. dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh* navmesh)
  512. {
  513. dtAssert(m_talloc);
  514. dtAssert(m_tcomp);
  515. unsigned int idx = decodeTileIdTile(ref);
  516. if (idx > (unsigned int)m_params.maxTiles)
  517. return DT_FAILURE | DT_INVALID_PARAM;
  518. const dtCompressedTile* tile = &m_tiles[idx];
  519. unsigned int salt = decodeTileIdSalt(ref);
  520. if (tile->salt != salt)
  521. return DT_FAILURE | DT_INVALID_PARAM;
  522. m_talloc->reset();
  523. BuildContext bc(m_talloc);
  524. const int walkableClimbVx = (int)(m_params.walkableClimb / m_params.ch);
  525. dtStatus status;
  526. // Decompress tile layer data.
  527. status = dtDecompressTileCacheLayer(m_talloc, m_tcomp, tile->data, tile->dataSize, &bc.layer);
  528. if (dtStatusFailed(status))
  529. return status;
  530. // Rasterize obstacles.
  531. for (int i = 0; i < m_params.maxObstacles; ++i)
  532. {
  533. const dtTileCacheObstacle* ob = &m_obstacles[i];
  534. if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
  535. continue;
  536. if (contains(ob->touched, ob->ntouched, ref))
  537. {
  538. dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
  539. ob->pos, ob->radius, ob->height, 0);
  540. }
  541. }
  542. // Build navmesh
  543. status = dtBuildTileCacheRegions(m_talloc, *bc.layer, walkableClimbVx);
  544. if (dtStatusFailed(status))
  545. return status;
  546. bc.lcset = dtAllocTileCacheContourSet(m_talloc);
  547. if (!bc.lcset)
  548. return status;
  549. status = dtBuildTileCacheContours(m_talloc, *bc.layer, walkableClimbVx,
  550. m_params.maxSimplificationError, *bc.lcset);
  551. if (dtStatusFailed(status))
  552. return status;
  553. bc.lmesh = dtAllocTileCachePolyMesh(m_talloc);
  554. if (!bc.lmesh)
  555. return status;
  556. status = dtBuildTileCachePolyMesh(m_talloc, *bc.lcset, *bc.lmesh);
  557. if (dtStatusFailed(status))
  558. return status;
  559. // Early out if the mesh tile is empty.
  560. if (!bc.lmesh->npolys)
  561. return DT_SUCCESS;
  562. dtNavMeshCreateParams params;
  563. memset(&params, 0, sizeof(params));
  564. params.verts = bc.lmesh->verts;
  565. params.vertCount = bc.lmesh->nverts;
  566. params.polys = bc.lmesh->polys;
  567. params.polyAreas = bc.lmesh->areas;
  568. params.polyFlags = bc.lmesh->flags;
  569. params.polyCount = bc.lmesh->npolys;
  570. params.nvp = DT_VERTS_PER_POLYGON;
  571. params.walkableHeight = m_params.walkableHeight;
  572. params.walkableRadius = m_params.walkableRadius;
  573. params.walkableClimb = m_params.walkableClimb;
  574. params.tileX = tile->header->tx;
  575. params.tileY = tile->header->ty;
  576. params.tileLayer = tile->header->tlayer;
  577. params.cs = m_params.cs;
  578. params.ch = m_params.ch;
  579. params.buildBvTree = false;
  580. dtVcopy(params.bmin, tile->header->bmin);
  581. dtVcopy(params.bmax, tile->header->bmax);
  582. if (m_tmproc)
  583. {
  584. m_tmproc->process(&params, bc.lmesh->areas, bc.lmesh->flags);
  585. }
  586. unsigned char* navData = 0;
  587. int navDataSize = 0;
  588. if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
  589. return DT_FAILURE;
  590. // Remove existing tile.
  591. navmesh->removeTile(navmesh->getTileRefAt(tile->header->tx,tile->header->ty,tile->header->tlayer),0,0);
  592. // Add new tile, or leave the location empty.
  593. if (navData)
  594. {
  595. // Let the navmesh own the data.
  596. status = navmesh->addTile(navData,navDataSize,DT_TILE_FREE_DATA,0,0);
  597. if (dtStatusFailed(status))
  598. {
  599. dtFree(navData);
  600. return status;
  601. }
  602. }
  603. return DT_SUCCESS;
  604. }
  605. void dtTileCache::calcTightTileBounds(const dtTileCacheLayerHeader* header, float* bmin, float* bmax) const
  606. {
  607. const float cs = m_params.cs;
  608. bmin[0] = header->bmin[0] + header->minx*cs;
  609. bmin[1] = header->bmin[1];
  610. bmin[2] = header->bmin[2] + header->miny*cs;
  611. bmax[0] = header->bmin[0] + (header->maxx+1)*cs;
  612. bmax[1] = header->bmax[1];
  613. bmax[2] = header->bmin[2] + (header->maxy+1)*cs;
  614. }
  615. void dtTileCache::getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const
  616. {
  617. bmin[0] = ob->pos[0] - ob->radius;
  618. bmin[1] = ob->pos[1];
  619. bmin[2] = ob->pos[2] - ob->radius;
  620. bmax[0] = ob->pos[0] + ob->radius;
  621. bmax[1] = ob->pos[1] + ob->height;
  622. bmax[2] = ob->pos[2] + ob->radius;
  623. }