DetourNavMeshBuilder.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. //
  2. // Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
  3. //
  4. // This software is provided 'as-is', without any express or implied
  5. // warranty. In no event will the authors be held liable for any damages
  6. // arising from the use of this software.
  7. // Permission is granted to anyone to use this software for any purpose,
  8. // including commercial applications, and to alter it and redistribute it
  9. // freely, subject to the following restrictions:
  10. // 1. The origin of this software must not be misrepresented; you must not
  11. // claim that you wrote the original software. If you use this software
  12. // in a product, an acknowledgment in the product documentation would be
  13. // appreciated but is not required.
  14. // 2. Altered source versions must be plainly marked as such, and must not be
  15. // misrepresented as being the original software.
  16. // 3. This notice may not be removed or altered from any source distribution.
  17. //
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <float.h>
  22. #include "DetourNavMesh.h"
  23. #include "DetourCommon.h"
  24. #include "DetourMath.h"
  25. #include "DetourNavMeshBuilder.h"
  26. #include "DetourAlloc.h"
  27. #include "DetourAssert.h"
  28. static unsigned short MESH_NULL_IDX = 0xffff;
  29. struct BVItem
  30. {
  31. unsigned short bmin[3];
  32. unsigned short bmax[3];
  33. int i;
  34. };
  35. static int compareItemX(const void* va, const void* vb)
  36. {
  37. const BVItem* a = (const BVItem*)va;
  38. const BVItem* b = (const BVItem*)vb;
  39. if (a->bmin[0] < b->bmin[0])
  40. return -1;
  41. if (a->bmin[0] > b->bmin[0])
  42. return 1;
  43. return 0;
  44. }
  45. static int compareItemY(const void* va, const void* vb)
  46. {
  47. const BVItem* a = (const BVItem*)va;
  48. const BVItem* b = (const BVItem*)vb;
  49. if (a->bmin[1] < b->bmin[1])
  50. return -1;
  51. if (a->bmin[1] > b->bmin[1])
  52. return 1;
  53. return 0;
  54. }
  55. static int compareItemZ(const void* va, const void* vb)
  56. {
  57. const BVItem* a = (const BVItem*)va;
  58. const BVItem* b = (const BVItem*)vb;
  59. if (a->bmin[2] < b->bmin[2])
  60. return -1;
  61. if (a->bmin[2] > b->bmin[2])
  62. return 1;
  63. return 0;
  64. }
  65. static void calcExtends(BVItem* items, const int /*nitems*/, const int imin, const int imax,
  66. unsigned short* bmin, unsigned short* bmax)
  67. {
  68. bmin[0] = items[imin].bmin[0];
  69. bmin[1] = items[imin].bmin[1];
  70. bmin[2] = items[imin].bmin[2];
  71. bmax[0] = items[imin].bmax[0];
  72. bmax[1] = items[imin].bmax[1];
  73. bmax[2] = items[imin].bmax[2];
  74. for (int i = imin+1; i < imax; ++i)
  75. {
  76. const BVItem& it = items[i];
  77. if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
  78. if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
  79. if (it.bmin[2] < bmin[2]) bmin[2] = it.bmin[2];
  80. if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
  81. if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
  82. if (it.bmax[2] > bmax[2]) bmax[2] = it.bmax[2];
  83. }
  84. }
  85. inline int longestAxis(unsigned short x, unsigned short y, unsigned short z)
  86. {
  87. int axis = 0;
  88. unsigned short maxVal = x;
  89. if (y > maxVal)
  90. {
  91. axis = 1;
  92. maxVal = y;
  93. }
  94. if (z > maxVal)
  95. {
  96. axis = 2;
  97. maxVal = z;
  98. }
  99. return axis;
  100. }
  101. static void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNode, dtBVNode* nodes)
  102. {
  103. int inum = imax - imin;
  104. int icur = curNode;
  105. dtBVNode& node = nodes[curNode++];
  106. if (inum == 1)
  107. {
  108. // Leaf
  109. node.bmin[0] = items[imin].bmin[0];
  110. node.bmin[1] = items[imin].bmin[1];
  111. node.bmin[2] = items[imin].bmin[2];
  112. node.bmax[0] = items[imin].bmax[0];
  113. node.bmax[1] = items[imin].bmax[1];
  114. node.bmax[2] = items[imin].bmax[2];
  115. node.i = items[imin].i;
  116. }
  117. else
  118. {
  119. // Split
  120. calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
  121. int axis = longestAxis(node.bmax[0] - node.bmin[0],
  122. node.bmax[1] - node.bmin[1],
  123. node.bmax[2] - node.bmin[2]);
  124. if (axis == 0)
  125. {
  126. // Sort along x-axis
  127. qsort(items+imin, inum, sizeof(BVItem), compareItemX);
  128. }
  129. else if (axis == 1)
  130. {
  131. // Sort along y-axis
  132. qsort(items+imin, inum, sizeof(BVItem), compareItemY);
  133. }
  134. else
  135. {
  136. // Sort along z-axis
  137. qsort(items+imin, inum, sizeof(BVItem), compareItemZ);
  138. }
  139. int isplit = imin+inum/2;
  140. // Left
  141. subdivide(items, nitems, imin, isplit, curNode, nodes);
  142. // Right
  143. subdivide(items, nitems, isplit, imax, curNode, nodes);
  144. int iescape = curNode - icur;
  145. // Negative index means escape.
  146. node.i = -iescape;
  147. }
  148. }
  149. static int createBVTree(const unsigned short* verts, const int /*nverts*/,
  150. const unsigned short* polys, const int npolys, const int nvp,
  151. const float cs, const float ch,
  152. const int /*nnodes*/, dtBVNode* nodes)
  153. {
  154. // Build tree
  155. BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP);
  156. for (int i = 0; i < npolys; i++)
  157. {
  158. BVItem& it = items[i];
  159. it.i = i;
  160. // Calc polygon bounds.
  161. const unsigned short* p = &polys[i*nvp*2];
  162. it.bmin[0] = it.bmax[0] = verts[p[0]*3+0];
  163. it.bmin[1] = it.bmax[1] = verts[p[0]*3+1];
  164. it.bmin[2] = it.bmax[2] = verts[p[0]*3+2];
  165. for (int j = 1; j < nvp; ++j)
  166. {
  167. if (p[j] == MESH_NULL_IDX) break;
  168. unsigned short x = verts[p[j]*3+0];
  169. unsigned short y = verts[p[j]*3+1];
  170. unsigned short z = verts[p[j]*3+2];
  171. if (x < it.bmin[0]) it.bmin[0] = x;
  172. if (y < it.bmin[1]) it.bmin[1] = y;
  173. if (z < it.bmin[2]) it.bmin[2] = z;
  174. if (x > it.bmax[0]) it.bmax[0] = x;
  175. if (y > it.bmax[1]) it.bmax[1] = y;
  176. if (z > it.bmax[2]) it.bmax[2] = z;
  177. }
  178. // Remap y
  179. it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1]*ch/cs);
  180. it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1]*ch/cs);
  181. }
  182. int curNode = 0;
  183. subdivide(items, npolys, 0, npolys, curNode, nodes);
  184. dtFree(items);
  185. return curNode;
  186. }
  187. static unsigned char classifyOffMeshPoint(const float* pt, const float* bmin, const float* bmax)
  188. {
  189. static const unsigned char XP = 1<<0;
  190. static const unsigned char ZP = 1<<1;
  191. static const unsigned char XM = 1<<2;
  192. static const unsigned char ZM = 1<<3;
  193. unsigned char outcode = 0;
  194. outcode |= (pt[0] >= bmax[0]) ? XP : 0;
  195. outcode |= (pt[2] >= bmax[2]) ? ZP : 0;
  196. outcode |= (pt[0] < bmin[0]) ? XM : 0;
  197. outcode |= (pt[2] < bmin[2]) ? ZM : 0;
  198. switch (outcode)
  199. {
  200. case XP: return 0;
  201. case XP|ZP: return 1;
  202. case ZP: return 2;
  203. case XM|ZP: return 3;
  204. case XM: return 4;
  205. case XM|ZM: return 5;
  206. case ZM: return 6;
  207. case XP|ZM: return 7;
  208. };
  209. return 0xff;
  210. }
  211. // TODO: Better error handling.
  212. /// @par
  213. ///
  214. /// The output data array is allocated using the detour allocator (dtAlloc()). The method
  215. /// used to free the memory will be determined by how the tile is added to the navigation
  216. /// mesh.
  217. ///
  218. /// @see dtNavMesh, dtNavMesh::addTile()
  219. bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize)
  220. {
  221. if (params->nvp > DT_VERTS_PER_POLYGON)
  222. return false;
  223. if (params->vertCount >= 0xffff)
  224. return false;
  225. if (!params->vertCount || !params->verts)
  226. return false;
  227. if (!params->polyCount || !params->polys)
  228. return false;
  229. const int nvp = params->nvp;
  230. // Classify off-mesh connection points. We store only the connections
  231. // whose start point is inside the tile.
  232. unsigned char* offMeshConClass = 0;
  233. int storedOffMeshConCount = 0;
  234. int offMeshConLinkCount = 0;
  235. if (params->offMeshConCount > 0)
  236. {
  237. offMeshConClass = (unsigned char*)dtAlloc(sizeof(unsigned char)*params->offMeshConCount*2, DT_ALLOC_TEMP);
  238. if (!offMeshConClass)
  239. return false;
  240. // Find tight heigh bounds, used for culling out off-mesh start locations.
  241. float hmin = FLT_MAX;
  242. float hmax = -FLT_MAX;
  243. if (params->detailVerts && params->detailVertsCount)
  244. {
  245. for (int i = 0; i < params->detailVertsCount; ++i)
  246. {
  247. const float h = params->detailVerts[i*3+1];
  248. hmin = dtMin(hmin,h);
  249. hmax = dtMax(hmax,h);
  250. }
  251. }
  252. else
  253. {
  254. for (int i = 0; i < params->vertCount; ++i)
  255. {
  256. const unsigned short* iv = &params->verts[i*3];
  257. const float h = params->bmin[1] + iv[1] * params->ch;
  258. hmin = dtMin(hmin,h);
  259. hmax = dtMax(hmax,h);
  260. }
  261. }
  262. hmin -= params->walkableClimb;
  263. hmax += params->walkableClimb;
  264. float bmin[3], bmax[3];
  265. dtVcopy(bmin, params->bmin);
  266. dtVcopy(bmax, params->bmax);
  267. bmin[1] = hmin;
  268. bmax[1] = hmax;
  269. for (int i = 0; i < params->offMeshConCount; ++i)
  270. {
  271. const float* p0 = &params->offMeshConVerts[(i*2+0)*3];
  272. const float* p1 = &params->offMeshConVerts[(i*2+1)*3];
  273. offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax);
  274. offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax);
  275. // Zero out off-mesh start positions which are not even potentially touching the mesh.
  276. if (offMeshConClass[i*2+0] == 0xff)
  277. {
  278. if (p0[1] < bmin[1] || p0[1] > bmax[1])
  279. offMeshConClass[i*2+0] = 0;
  280. }
  281. // Cound how many links should be allocated for off-mesh connections.
  282. if (offMeshConClass[i*2+0] == 0xff)
  283. offMeshConLinkCount++;
  284. if (offMeshConClass[i*2+1] == 0xff)
  285. offMeshConLinkCount++;
  286. if (offMeshConClass[i*2+0] == 0xff)
  287. storedOffMeshConCount++;
  288. }
  289. }
  290. // Off-mesh connectionss are stored as polygons, adjust values.
  291. const int totPolyCount = params->polyCount + storedOffMeshConCount;
  292. const int totVertCount = params->vertCount + storedOffMeshConCount*2;
  293. // Find portal edges which are at tile borders.
  294. int edgeCount = 0;
  295. int portalCount = 0;
  296. for (int i = 0; i < params->polyCount; ++i)
  297. {
  298. const unsigned short* p = &params->polys[i*2*nvp];
  299. for (int j = 0; j < nvp; ++j)
  300. {
  301. if (p[j] == MESH_NULL_IDX) break;
  302. edgeCount++;
  303. if (p[nvp+j] & 0x8000)
  304. {
  305. unsigned short dir = p[nvp+j] & 0xf;
  306. if (dir != 0xf)
  307. portalCount++;
  308. }
  309. }
  310. }
  311. const int maxLinkCount = edgeCount + portalCount*2 + offMeshConLinkCount*2;
  312. // Find unique detail vertices.
  313. int uniqueDetailVertCount = 0;
  314. int detailTriCount = 0;
  315. if (params->detailMeshes)
  316. {
  317. // Has detail mesh, count unique detail vertex count and use input detail tri count.
  318. detailTriCount = params->detailTriCount;
  319. for (int i = 0; i < params->polyCount; ++i)
  320. {
  321. const unsigned short* p = &params->polys[i*nvp*2];
  322. int ndv = params->detailMeshes[i*4+1];
  323. int nv = 0;
  324. for (int j = 0; j < nvp; ++j)
  325. {
  326. if (p[j] == MESH_NULL_IDX) break;
  327. nv++;
  328. }
  329. ndv -= nv;
  330. uniqueDetailVertCount += ndv;
  331. }
  332. }
  333. else
  334. {
  335. // No input detail mesh, build detail mesh from nav polys.
  336. uniqueDetailVertCount = 0; // No extra detail verts.
  337. detailTriCount = 0;
  338. for (int i = 0; i < params->polyCount; ++i)
  339. {
  340. const unsigned short* p = &params->polys[i*nvp*2];
  341. int nv = 0;
  342. for (int j = 0; j < nvp; ++j)
  343. {
  344. if (p[j] == MESH_NULL_IDX) break;
  345. nv++;
  346. }
  347. detailTriCount += nv-2;
  348. }
  349. }
  350. // Calculate data size
  351. const int headerSize = dtAlign4(sizeof(dtMeshHeader));
  352. const int vertsSize = dtAlign4(sizeof(float)*3*totVertCount);
  353. const int polysSize = dtAlign4(sizeof(dtPoly)*totPolyCount);
  354. const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount);
  355. const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount);
  356. const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount);
  357. const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount);
  358. const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0;
  359. const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount);
  360. const int dataSize = headerSize + vertsSize + polysSize + linksSize +
  361. detailMeshesSize + detailVertsSize + detailTrisSize +
  362. bvTreeSize + offMeshConsSize;
  363. unsigned char* data = (unsigned char*)dtAlloc(sizeof(unsigned char)*dataSize, DT_ALLOC_PERM);
  364. if (!data)
  365. {
  366. dtFree(offMeshConClass);
  367. return false;
  368. }
  369. memset(data, 0, dataSize);
  370. unsigned char* d = data;
  371. dtMeshHeader* header = (dtMeshHeader*)d; d += headerSize;
  372. float* navVerts = (float*)d; d += vertsSize;
  373. dtPoly* navPolys = (dtPoly*)d; d += polysSize;
  374. d += linksSize;
  375. dtPolyDetail* navDMeshes = (dtPolyDetail*)d; d += detailMeshesSize;
  376. float* navDVerts = (float*)d; d += detailVertsSize;
  377. unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize;
  378. dtBVNode* navBvtree = (dtBVNode*)d; d += bvTreeSize;
  379. dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshConsSize;
  380. // Store header
  381. header->magic = DT_NAVMESH_MAGIC;
  382. header->version = DT_NAVMESH_VERSION;
  383. header->x = params->tileX;
  384. header->y = params->tileY;
  385. header->layer = params->tileLayer;
  386. header->userId = params->userId;
  387. header->polyCount = totPolyCount;
  388. header->vertCount = totVertCount;
  389. header->maxLinkCount = maxLinkCount;
  390. dtVcopy(header->bmin, params->bmin);
  391. dtVcopy(header->bmax, params->bmax);
  392. header->detailMeshCount = params->polyCount;
  393. header->detailVertCount = uniqueDetailVertCount;
  394. header->detailTriCount = detailTriCount;
  395. header->bvQuantFactor = 1.0f / params->cs;
  396. header->offMeshBase = params->polyCount;
  397. header->walkableHeight = params->walkableHeight;
  398. header->walkableRadius = params->walkableRadius;
  399. header->walkableClimb = params->walkableClimb;
  400. header->offMeshConCount = storedOffMeshConCount;
  401. header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0;
  402. const int offMeshVertsBase = params->vertCount;
  403. const int offMeshPolyBase = params->polyCount;
  404. // Store vertices
  405. // Mesh vertices
  406. for (int i = 0; i < params->vertCount; ++i)
  407. {
  408. const unsigned short* iv = &params->verts[i*3];
  409. float* v = &navVerts[i*3];
  410. v[0] = params->bmin[0] + iv[0] * params->cs;
  411. v[1] = params->bmin[1] + iv[1] * params->ch;
  412. v[2] = params->bmin[2] + iv[2] * params->cs;
  413. }
  414. // Off-mesh link vertices.
  415. int n = 0;
  416. for (int i = 0; i < params->offMeshConCount; ++i)
  417. {
  418. // Only store connections which start from this tile.
  419. if (offMeshConClass[i*2+0] == 0xff)
  420. {
  421. const float* linkv = &params->offMeshConVerts[i*2*3];
  422. float* v = &navVerts[(offMeshVertsBase + n*2)*3];
  423. dtVcopy(&v[0], &linkv[0]);
  424. dtVcopy(&v[3], &linkv[3]);
  425. n++;
  426. }
  427. }
  428. // Store polygons
  429. // Mesh polys
  430. const unsigned short* src = params->polys;
  431. for (int i = 0; i < params->polyCount; ++i)
  432. {
  433. dtPoly* p = &navPolys[i];
  434. p->vertCount = 0;
  435. p->flags = params->polyFlags[i];
  436. p->setArea(params->polyAreas[i]);
  437. p->setType(DT_POLYTYPE_GROUND);
  438. for (int j = 0; j < nvp; ++j)
  439. {
  440. if (src[j] == MESH_NULL_IDX) break;
  441. p->verts[j] = src[j];
  442. if (src[nvp+j] & 0x8000)
  443. {
  444. // Border or portal edge.
  445. unsigned short dir = src[nvp+j] & 0xf;
  446. if (dir == 0xf) // Border
  447. p->neis[j] = 0;
  448. else if (dir == 0) // Portal x-
  449. p->neis[j] = DT_EXT_LINK | 4;
  450. else if (dir == 1) // Portal z+
  451. p->neis[j] = DT_EXT_LINK | 2;
  452. else if (dir == 2) // Portal x+
  453. p->neis[j] = DT_EXT_LINK | 0;
  454. else if (dir == 3) // Portal z-
  455. p->neis[j] = DT_EXT_LINK | 6;
  456. }
  457. else
  458. {
  459. // Normal connection
  460. p->neis[j] = src[nvp+j]+1;
  461. }
  462. p->vertCount++;
  463. }
  464. src += nvp*2;
  465. }
  466. // Off-mesh connection vertices.
  467. n = 0;
  468. for (int i = 0; i < params->offMeshConCount; ++i)
  469. {
  470. // Only store connections which start from this tile.
  471. if (offMeshConClass[i*2+0] == 0xff)
  472. {
  473. dtPoly* p = &navPolys[offMeshPolyBase+n];
  474. p->vertCount = 2;
  475. p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0);
  476. p->verts[1] = (unsigned short)(offMeshVertsBase + n*2+1);
  477. p->flags = params->offMeshConFlags[i];
  478. p->setArea(params->offMeshConAreas[i]);
  479. p->setType(DT_POLYTYPE_OFFMESH_CONNECTION);
  480. n++;
  481. }
  482. }
  483. // Store detail meshes and vertices.
  484. // The nav polygon vertices are stored as the first vertices on each mesh.
  485. // We compress the mesh data by skipping them and using the navmesh coordinates.
  486. if (params->detailMeshes)
  487. {
  488. unsigned short vbase = 0;
  489. for (int i = 0; i < params->polyCount; ++i)
  490. {
  491. dtPolyDetail& dtl = navDMeshes[i];
  492. const int vb = (int)params->detailMeshes[i*4+0];
  493. const int ndv = (int)params->detailMeshes[i*4+1];
  494. const int nv = navPolys[i].vertCount;
  495. dtl.vertBase = (unsigned int)vbase;
  496. dtl.vertCount = (unsigned char)(ndv-nv);
  497. dtl.triBase = (unsigned int)params->detailMeshes[i*4+2];
  498. dtl.triCount = (unsigned char)params->detailMeshes[i*4+3];
  499. // Copy vertices except the first 'nv' verts which are equal to nav poly verts.
  500. if (ndv-nv)
  501. {
  502. memcpy(&navDVerts[vbase*3], &params->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
  503. vbase += (unsigned short)(ndv-nv);
  504. }
  505. }
  506. // Store triangles.
  507. memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount);
  508. }
  509. else
  510. {
  511. // Create dummy detail mesh by triangulating polys.
  512. int tbase = 0;
  513. for (int i = 0; i < params->polyCount; ++i)
  514. {
  515. dtPolyDetail& dtl = navDMeshes[i];
  516. const int nv = navPolys[i].vertCount;
  517. dtl.vertBase = 0;
  518. dtl.vertCount = 0;
  519. dtl.triBase = (unsigned int)tbase;
  520. dtl.triCount = (unsigned char)(nv-2);
  521. // Triangulate polygon (local indices).
  522. for (int j = 2; j < nv; ++j)
  523. {
  524. unsigned char* t = &navDTris[tbase*4];
  525. t[0] = 0;
  526. t[1] = (unsigned char)(j-1);
  527. t[2] = (unsigned char)j;
  528. // Bit for each edge that belongs to poly boundary.
  529. t[3] = (1<<2);
  530. if (j == 2) t[3] |= (1<<0);
  531. if (j == nv-1) t[3] |= (1<<4);
  532. tbase++;
  533. }
  534. }
  535. }
  536. // Store and create BVtree.
  537. // TODO: take detail mesh into account! use byte per bbox extent?
  538. if (params->buildBvTree)
  539. {
  540. createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
  541. nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
  542. }
  543. // Store Off-Mesh connections.
  544. n = 0;
  545. for (int i = 0; i < params->offMeshConCount; ++i)
  546. {
  547. // Only store connections which start from this tile.
  548. if (offMeshConClass[i*2+0] == 0xff)
  549. {
  550. dtOffMeshConnection* con = &offMeshCons[n];
  551. con->poly = (unsigned short)(offMeshPolyBase + n);
  552. // Copy connection end-points.
  553. const float* endPts = &params->offMeshConVerts[i*2*3];
  554. dtVcopy(&con->pos[0], &endPts[0]);
  555. dtVcopy(&con->pos[3], &endPts[3]);
  556. con->rad = params->offMeshConRad[i];
  557. con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0;
  558. con->side = offMeshConClass[i*2+1];
  559. if (params->offMeshConUserID)
  560. con->userId = params->offMeshConUserID[i];
  561. n++;
  562. }
  563. }
  564. dtFree(offMeshConClass);
  565. *outData = data;
  566. *outDataSize = dataSize;
  567. return true;
  568. }
  569. bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
  570. {
  571. dtMeshHeader* header = (dtMeshHeader*)data;
  572. int swappedMagic = DT_NAVMESH_MAGIC;
  573. int swappedVersion = DT_NAVMESH_VERSION;
  574. dtSwapEndian(&swappedMagic);
  575. dtSwapEndian(&swappedVersion);
  576. if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) &&
  577. (header->magic != swappedMagic || header->version != swappedVersion))
  578. {
  579. return false;
  580. }
  581. dtSwapEndian(&header->magic);
  582. dtSwapEndian(&header->version);
  583. dtSwapEndian(&header->x);
  584. dtSwapEndian(&header->y);
  585. dtSwapEndian(&header->layer);
  586. dtSwapEndian(&header->userId);
  587. dtSwapEndian(&header->polyCount);
  588. dtSwapEndian(&header->vertCount);
  589. dtSwapEndian(&header->maxLinkCount);
  590. dtSwapEndian(&header->detailMeshCount);
  591. dtSwapEndian(&header->detailVertCount);
  592. dtSwapEndian(&header->detailTriCount);
  593. dtSwapEndian(&header->bvNodeCount);
  594. dtSwapEndian(&header->offMeshConCount);
  595. dtSwapEndian(&header->offMeshBase);
  596. dtSwapEndian(&header->walkableHeight);
  597. dtSwapEndian(&header->walkableRadius);
  598. dtSwapEndian(&header->walkableClimb);
  599. dtSwapEndian(&header->bmin[0]);
  600. dtSwapEndian(&header->bmin[1]);
  601. dtSwapEndian(&header->bmin[2]);
  602. dtSwapEndian(&header->bmax[0]);
  603. dtSwapEndian(&header->bmax[1]);
  604. dtSwapEndian(&header->bmax[2]);
  605. dtSwapEndian(&header->bvQuantFactor);
  606. // Freelist index and pointers are updated when tile is added, no need to swap.
  607. return true;
  608. }
  609. /// @par
  610. ///
  611. /// @warning This function assumes that the header is in the correct endianess already.
  612. /// Call #dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess
  613. /// to start with. Call #dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from
  614. /// native to foreign endianess.
  615. bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
  616. {
  617. // Make sure the data is in right format.
  618. dtMeshHeader* header = (dtMeshHeader*)data;
  619. if (header->magic != DT_NAVMESH_MAGIC)
  620. return false;
  621. if (header->version != DT_NAVMESH_VERSION)
  622. return false;
  623. // Patch header pointers.
  624. const int headerSize = dtAlign4(sizeof(dtMeshHeader));
  625. const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount);
  626. const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount);
  627. const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount));
  628. const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount);
  629. const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount);
  630. const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount);
  631. const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount);
  632. const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount);
  633. unsigned char* d = data + headerSize;
  634. float* verts = (float*)d; d += vertsSize;
  635. dtPoly* polys = (dtPoly*)d; d += polysSize;
  636. /*dtLink* links = (dtLink*)d;*/ d += linksSize;
  637. dtPolyDetail* detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize;
  638. float* detailVerts = (float*)d; d += detailVertsSize;
  639. /*unsigned char* detailTris = (unsigned char*)d;*/ d += detailTrisSize;
  640. dtBVNode* bvTree = (dtBVNode*)d; d += bvtreeSize;
  641. dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize;
  642. // Vertices
  643. for (int i = 0; i < header->vertCount*3; ++i)
  644. {
  645. dtSwapEndian(&verts[i]);
  646. }
  647. // Polys
  648. for (int i = 0; i < header->polyCount; ++i)
  649. {
  650. dtPoly* p = &polys[i];
  651. // poly->firstLink is update when tile is added, no need to swap.
  652. for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j)
  653. {
  654. dtSwapEndian(&p->verts[j]);
  655. dtSwapEndian(&p->neis[j]);
  656. }
  657. dtSwapEndian(&p->flags);
  658. }
  659. // Links are rebuild when tile is added, no need to swap.
  660. // Detail meshes
  661. for (int i = 0; i < header->detailMeshCount; ++i)
  662. {
  663. dtPolyDetail* pd = &detailMeshes[i];
  664. dtSwapEndian(&pd->vertBase);
  665. dtSwapEndian(&pd->triBase);
  666. }
  667. // Detail verts
  668. for (int i = 0; i < header->detailVertCount*3; ++i)
  669. {
  670. dtSwapEndian(&detailVerts[i]);
  671. }
  672. // BV-tree
  673. for (int i = 0; i < header->bvNodeCount; ++i)
  674. {
  675. dtBVNode* node = &bvTree[i];
  676. for (int j = 0; j < 3; ++j)
  677. {
  678. dtSwapEndian(&node->bmin[j]);
  679. dtSwapEndian(&node->bmax[j]);
  680. }
  681. dtSwapEndian(&node->i);
  682. }
  683. // Off-mesh Connections.
  684. for (int i = 0; i < header->offMeshConCount; ++i)
  685. {
  686. dtOffMeshConnection* con = &offMeshCons[i];
  687. for (int j = 0; j < 6; ++j)
  688. dtSwapEndian(&con->pos[j]);
  689. dtSwapEndian(&con->rad);
  690. dtSwapEndian(&con->poly);
  691. }
  692. return true;
  693. }