DetourDebugDraw.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  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 "DebugDraw.h"
  19. #include "DetourDebugDraw.h"
  20. #include "DetourNavMesh.h"
  21. #include "DetourCommon.h"
  22. #include "DetourNode.h"
  23. static float distancePtLine2d(const float* pt, const float* p, const float* q)
  24. {
  25. float pqx = q[0] - p[0];
  26. float pqz = q[2] - p[2];
  27. float dx = pt[0] - p[0];
  28. float dz = pt[2] - p[2];
  29. float d = pqx*pqx + pqz*pqz;
  30. float t = pqx*dx + pqz*dz;
  31. if (d != 0) t /= d;
  32. dx = p[0] + t*pqx - pt[0];
  33. dz = p[2] + t*pqz - pt[2];
  34. return dx*dx + dz*dz;
  35. }
  36. static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile,
  37. const unsigned int col, const float linew,
  38. bool inner)
  39. {
  40. static const float thr = 0.01f*0.01f;
  41. dd->begin(DU_DRAW_LINES, linew);
  42. for (int i = 0; i < tile->header->polyCount; ++i)
  43. {
  44. const dtPoly* p = &tile->polys[i];
  45. if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) continue;
  46. const dtPolyDetail* pd = &tile->detailMeshes[i];
  47. for (int j = 0, nj = (int)p->vertCount; j < nj; ++j)
  48. {
  49. unsigned int c = col;
  50. if (inner)
  51. {
  52. if (p->neis[j] == 0) continue;
  53. if (p->neis[j] & DT_EXT_LINK)
  54. {
  55. bool con = false;
  56. for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
  57. {
  58. if (tile->links[k].edge == j)
  59. {
  60. con = true;
  61. break;
  62. }
  63. }
  64. if (con)
  65. c = duRGBA(255,255,255,48);
  66. else
  67. c = duRGBA(0,0,0,48);
  68. }
  69. else
  70. c = duRGBA(0,48,64,32);
  71. }
  72. else
  73. {
  74. if (p->neis[j] != 0) continue;
  75. }
  76. const float* v0 = &tile->verts[p->verts[j]*3];
  77. const float* v1 = &tile->verts[p->verts[(j+1) % nj]*3];
  78. // Draw detail mesh edges which align with the actual poly edge.
  79. // This is really slow.
  80. for (int k = 0; k < pd->triCount; ++k)
  81. {
  82. const unsigned char* t = &tile->detailTris[(pd->triBase+k)*4];
  83. const float* tv[3];
  84. for (int m = 0; m < 3; ++m)
  85. {
  86. if (t[m] < p->vertCount)
  87. tv[m] = &tile->verts[p->verts[t[m]]*3];
  88. else
  89. tv[m] = &tile->detailVerts[(pd->vertBase+(t[m]-p->vertCount))*3];
  90. }
  91. for (int m = 0, n = 2; m < 3; n=m++)
  92. {
  93. if ((dtGetDetailTriEdgeFlags(t[3], n) & DT_DETAIL_EDGE_BOUNDARY) == 0)
  94. continue;
  95. if (distancePtLine2d(tv[n],v0,v1) < thr &&
  96. distancePtLine2d(tv[m],v0,v1) < thr)
  97. {
  98. dd->vertex(tv[n], c);
  99. dd->vertex(tv[m], c);
  100. }
  101. }
  102. }
  103. }
  104. }
  105. dd->end();
  106. }
  107. static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query,
  108. const dtMeshTile* tile, unsigned char flags)
  109. {
  110. dtPolyRef base = mesh.getPolyRefBase(tile);
  111. int tileNum = mesh.decodePolyIdTile(base);
  112. const unsigned int tileColor = duIntToCol(tileNum, 128);
  113. dd->depthMask(false);
  114. dd->begin(DU_DRAW_TRIS);
  115. for (int i = 0; i < tile->header->polyCount; ++i)
  116. {
  117. const dtPoly* p = &tile->polys[i];
  118. if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) // Skip off-mesh links.
  119. continue;
  120. const dtPolyDetail* pd = &tile->detailMeshes[i];
  121. unsigned int col;
  122. if (query && query->isInClosedList(base | (dtPolyRef)i))
  123. col = duRGBA(255,196,0,64);
  124. else
  125. {
  126. if (flags & DU_DRAWNAVMESH_COLOR_TILES)
  127. col = tileColor;
  128. else
  129. col = duTransCol(dd->areaToCol(p->getArea()), 64);
  130. }
  131. for (int j = 0; j < pd->triCount; ++j)
  132. {
  133. const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
  134. for (int k = 0; k < 3; ++k)
  135. {
  136. if (t[k] < p->vertCount)
  137. dd->vertex(&tile->verts[p->verts[t[k]]*3], col);
  138. else
  139. dd->vertex(&tile->detailVerts[(pd->vertBase+t[k]-p->vertCount)*3], col);
  140. }
  141. }
  142. }
  143. dd->end();
  144. // Draw inter poly boundaries
  145. drawPolyBoundaries(dd, tile, duRGBA(0,48,64,32), 1.5f, true);
  146. // Draw outer poly boundaries
  147. drawPolyBoundaries(dd, tile, duRGBA(0,48,64,220), 2.5f, false);
  148. if (flags & DU_DRAWNAVMESH_OFFMESHCONS)
  149. {
  150. dd->begin(DU_DRAW_LINES, 2.0f);
  151. for (int i = 0; i < tile->header->polyCount; ++i)
  152. {
  153. const dtPoly* p = &tile->polys[i];
  154. if (p->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) // Skip regular polys.
  155. continue;
  156. unsigned int col, col2;
  157. if (query && query->isInClosedList(base | (dtPolyRef)i))
  158. col = duRGBA(255,196,0,220);
  159. else
  160. col = duDarkenCol(duTransCol(dd->areaToCol(p->getArea()), 220));
  161. const dtOffMeshConnection* con = &tile->offMeshCons[i - tile->header->offMeshBase];
  162. const float* va = &tile->verts[p->verts[0]*3];
  163. const float* vb = &tile->verts[p->verts[1]*3];
  164. // Check to see if start and end end-points have links.
  165. bool startSet = false;
  166. bool endSet = false;
  167. for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
  168. {
  169. if (tile->links[k].edge == 0)
  170. startSet = true;
  171. if (tile->links[k].edge == 1)
  172. endSet = true;
  173. }
  174. // End points and their on-mesh locations.
  175. dd->vertex(va[0],va[1],va[2], col);
  176. dd->vertex(con->pos[0],con->pos[1],con->pos[2], col);
  177. col2 = startSet ? col : duRGBA(220,32,16,196);
  178. duAppendCircle(dd, con->pos[0],con->pos[1]+0.1f,con->pos[2], con->rad, col2);
  179. dd->vertex(vb[0],vb[1],vb[2], col);
  180. dd->vertex(con->pos[3],con->pos[4],con->pos[5], col);
  181. col2 = endSet ? col : duRGBA(220,32,16,196);
  182. duAppendCircle(dd, con->pos[3],con->pos[4]+0.1f,con->pos[5], con->rad, col2);
  183. // End point vertices.
  184. dd->vertex(con->pos[0],con->pos[1],con->pos[2], duRGBA(0,48,64,196));
  185. dd->vertex(con->pos[0],con->pos[1]+0.2f,con->pos[2], duRGBA(0,48,64,196));
  186. dd->vertex(con->pos[3],con->pos[4],con->pos[5], duRGBA(0,48,64,196));
  187. dd->vertex(con->pos[3],con->pos[4]+0.2f,con->pos[5], duRGBA(0,48,64,196));
  188. // Connection arc.
  189. duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
  190. (con->flags & 1) ? 0.6f : 0, 0.6f, col);
  191. }
  192. dd->end();
  193. }
  194. const unsigned int vcol = duRGBA(0,0,0,196);
  195. dd->begin(DU_DRAW_POINTS, 3.0f);
  196. for (int i = 0; i < tile->header->vertCount; ++i)
  197. {
  198. const float* v = &tile->verts[i*3];
  199. dd->vertex(v[0], v[1], v[2], vcol);
  200. }
  201. dd->end();
  202. dd->depthMask(true);
  203. }
  204. void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh& mesh, unsigned char flags)
  205. {
  206. if (!dd) return;
  207. for (int i = 0; i < mesh.getMaxTiles(); ++i)
  208. {
  209. const dtMeshTile* tile = mesh.getTile(i);
  210. if (!tile->header) continue;
  211. drawMeshTile(dd, mesh, 0, tile, flags);
  212. }
  213. }
  214. void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, unsigned char flags)
  215. {
  216. if (!dd) return;
  217. const dtNavMeshQuery* q = (flags & DU_DRAWNAVMESH_CLOSEDLIST) ? &query : 0;
  218. for (int i = 0; i < mesh.getMaxTiles(); ++i)
  219. {
  220. const dtMeshTile* tile = mesh.getTile(i);
  221. if (!tile->header) continue;
  222. drawMeshTile(dd, mesh, q, tile, flags);
  223. }
  224. }
  225. void duDebugDrawNavMeshNodes(struct duDebugDraw* dd, const dtNavMeshQuery& query)
  226. {
  227. if (!dd) return;
  228. const dtNodePool* pool = query.getNodePool();
  229. if (pool)
  230. {
  231. const float off = 0.5f;
  232. dd->begin(DU_DRAW_POINTS, 4.0f);
  233. for (int i = 0; i < pool->getHashSize(); ++i)
  234. {
  235. for (dtNodeIndex j = pool->getFirst(i); j != DT_NULL_IDX; j = pool->getNext(j))
  236. {
  237. const dtNode* node = pool->getNodeAtIdx(j+1);
  238. if (!node) continue;
  239. dd->vertex(node->pos[0],node->pos[1]+off,node->pos[2], duRGBA(255,192,0,255));
  240. }
  241. }
  242. dd->end();
  243. dd->begin(DU_DRAW_LINES, 2.0f);
  244. for (int i = 0; i < pool->getHashSize(); ++i)
  245. {
  246. for (dtNodeIndex j = pool->getFirst(i); j != DT_NULL_IDX; j = pool->getNext(j))
  247. {
  248. const dtNode* node = pool->getNodeAtIdx(j+1);
  249. if (!node) continue;
  250. if (!node->pidx) continue;
  251. const dtNode* parent = pool->getNodeAtIdx(node->pidx);
  252. if (!parent) continue;
  253. dd->vertex(node->pos[0],node->pos[1]+off,node->pos[2], duRGBA(255,192,0,128));
  254. dd->vertex(parent->pos[0],parent->pos[1]+off,parent->pos[2], duRGBA(255,192,0,128));
  255. }
  256. }
  257. dd->end();
  258. }
  259. }
  260. static void drawMeshTileBVTree(duDebugDraw* dd, const dtMeshTile* tile)
  261. {
  262. // Draw BV nodes.
  263. const float cs = 1.0f / tile->header->bvQuantFactor;
  264. dd->begin(DU_DRAW_LINES, 1.0f);
  265. for (int i = 0; i < tile->header->bvNodeCount; ++i)
  266. {
  267. const dtBVNode* n = &tile->bvTree[i];
  268. if (n->i < 0) // Leaf indices are positive.
  269. continue;
  270. duAppendBoxWire(dd, tile->header->bmin[0] + n->bmin[0]*cs,
  271. tile->header->bmin[1] + n->bmin[1]*cs,
  272. tile->header->bmin[2] + n->bmin[2]*cs,
  273. tile->header->bmin[0] + n->bmax[0]*cs,
  274. tile->header->bmin[1] + n->bmax[1]*cs,
  275. tile->header->bmin[2] + n->bmax[2]*cs,
  276. duRGBA(255,255,255,128));
  277. }
  278. dd->end();
  279. }
  280. void duDebugDrawNavMeshBVTree(duDebugDraw* dd, const dtNavMesh& mesh)
  281. {
  282. if (!dd) return;
  283. for (int i = 0; i < mesh.getMaxTiles(); ++i)
  284. {
  285. const dtMeshTile* tile = mesh.getTile(i);
  286. if (!tile->header) continue;
  287. drawMeshTileBVTree(dd, tile);
  288. }
  289. }
  290. static void drawMeshTilePortal(duDebugDraw* dd, const dtMeshTile* tile)
  291. {
  292. // Draw portals
  293. const float padx = 0.04f;
  294. const float pady = tile->header->walkableClimb;
  295. dd->begin(DU_DRAW_LINES, 2.0f);
  296. for (int side = 0; side < 8; ++side)
  297. {
  298. unsigned short m = DT_EXT_LINK | (unsigned short)side;
  299. for (int i = 0; i < tile->header->polyCount; ++i)
  300. {
  301. dtPoly* poly = &tile->polys[i];
  302. // Create new links.
  303. const int nv = poly->vertCount;
  304. for (int j = 0; j < nv; ++j)
  305. {
  306. // Skip edges which do not point to the right side.
  307. if (poly->neis[j] != m)
  308. continue;
  309. // Create new links
  310. const float* va = &tile->verts[poly->verts[j]*3];
  311. const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3];
  312. if (side == 0 || side == 4)
  313. {
  314. unsigned int col = side == 0 ? duRGBA(128,0,0,128) : duRGBA(128,0,128,128);
  315. const float x = va[0] + ((side == 0) ? -padx : padx);
  316. dd->vertex(x,va[1]-pady,va[2], col);
  317. dd->vertex(x,va[1]+pady,va[2], col);
  318. dd->vertex(x,va[1]+pady,va[2], col);
  319. dd->vertex(x,vb[1]+pady,vb[2], col);
  320. dd->vertex(x,vb[1]+pady,vb[2], col);
  321. dd->vertex(x,vb[1]-pady,vb[2], col);
  322. dd->vertex(x,vb[1]-pady,vb[2], col);
  323. dd->vertex(x,va[1]-pady,va[2], col);
  324. }
  325. else if (side == 2 || side == 6)
  326. {
  327. unsigned int col = side == 2 ? duRGBA(0,128,0,128) : duRGBA(0,128,128,128);
  328. const float z = va[2] + ((side == 2) ? -padx : padx);
  329. dd->vertex(va[0],va[1]-pady,z, col);
  330. dd->vertex(va[0],va[1]+pady,z, col);
  331. dd->vertex(va[0],va[1]+pady,z, col);
  332. dd->vertex(vb[0],vb[1]+pady,z, col);
  333. dd->vertex(vb[0],vb[1]+pady,z, col);
  334. dd->vertex(vb[0],vb[1]-pady,z, col);
  335. dd->vertex(vb[0],vb[1]-pady,z, col);
  336. dd->vertex(va[0],va[1]-pady,z, col);
  337. }
  338. }
  339. }
  340. }
  341. dd->end();
  342. }
  343. void duDebugDrawNavMeshPortals(duDebugDraw* dd, const dtNavMesh& mesh)
  344. {
  345. if (!dd) return;
  346. for (int i = 0; i < mesh.getMaxTiles(); ++i)
  347. {
  348. const dtMeshTile* tile = mesh.getTile(i);
  349. if (!tile->header) continue;
  350. drawMeshTilePortal(dd, tile);
  351. }
  352. }
  353. void duDebugDrawNavMeshPolysWithFlags(struct duDebugDraw* dd, const dtNavMesh& mesh,
  354. const unsigned short polyFlags, const unsigned int col)
  355. {
  356. if (!dd) return;
  357. for (int i = 0; i < mesh.getMaxTiles(); ++i)
  358. {
  359. const dtMeshTile* tile = mesh.getTile(i);
  360. if (!tile->header) continue;
  361. dtPolyRef base = mesh.getPolyRefBase(tile);
  362. for (int j = 0; j < tile->header->polyCount; ++j)
  363. {
  364. const dtPoly* p = &tile->polys[j];
  365. if ((p->flags & polyFlags) == 0) continue;
  366. duDebugDrawNavMeshPoly(dd, mesh, base|(dtPolyRef)j, col);
  367. }
  368. }
  369. }
  370. void duDebugDrawNavMeshPoly(duDebugDraw* dd, const dtNavMesh& mesh, dtPolyRef ref, const unsigned int col)
  371. {
  372. if (!dd) return;
  373. const dtMeshTile* tile = 0;
  374. const dtPoly* poly = 0;
  375. if (dtStatusFailed(mesh.getTileAndPolyByRef(ref, &tile, &poly)))
  376. return;
  377. dd->depthMask(false);
  378. const unsigned int c = duTransCol(col, 64);
  379. const unsigned int ip = (unsigned int)(poly - tile->polys);
  380. if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
  381. {
  382. dtOffMeshConnection* con = &tile->offMeshCons[ip - tile->header->offMeshBase];
  383. dd->begin(DU_DRAW_LINES, 2.0f);
  384. // Connection arc.
  385. duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
  386. (con->flags & 1) ? 0.6f : 0.0f, 0.6f, c);
  387. dd->end();
  388. }
  389. else
  390. {
  391. const dtPolyDetail* pd = &tile->detailMeshes[ip];
  392. dd->begin(DU_DRAW_TRIS);
  393. for (int i = 0; i < pd->triCount; ++i)
  394. {
  395. const unsigned char* t = &tile->detailTris[(pd->triBase+i)*4];
  396. for (int j = 0; j < 3; ++j)
  397. {
  398. if (t[j] < poly->vertCount)
  399. dd->vertex(&tile->verts[poly->verts[t[j]]*3], c);
  400. else
  401. dd->vertex(&tile->detailVerts[(pd->vertBase+t[j]-poly->vertCount)*3], c);
  402. }
  403. }
  404. dd->end();
  405. }
  406. dd->depthMask(true);
  407. }
  408. static void debugDrawTileCachePortals(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
  409. {
  410. const int w = (int)layer.header->width;
  411. const int h = (int)layer.header->height;
  412. const float* bmin = layer.header->bmin;
  413. // Portals
  414. unsigned int pcol = duRGBA(255,255,255,255);
  415. const int segs[4*4] = {0,0,0,1, 0,1,1,1, 1,1,1,0, 1,0,0,0};
  416. // Layer portals
  417. dd->begin(DU_DRAW_LINES, 2.0f);
  418. for (int y = 0; y < h; ++y)
  419. {
  420. for (int x = 0; x < w; ++x)
  421. {
  422. const int idx = x+y*w;
  423. const int lh = (int)layer.heights[idx];
  424. if (lh == 0xff) continue;
  425. for (int dir = 0; dir < 4; ++dir)
  426. {
  427. if (layer.cons[idx] & (1<<(dir+4)))
  428. {
  429. const int* seg = &segs[dir*4];
  430. const float ax = bmin[0] + (x+seg[0])*cs;
  431. const float ay = bmin[1] + (lh+2)*ch;
  432. const float az = bmin[2] + (y+seg[1])*cs;
  433. const float bx = bmin[0] + (x+seg[2])*cs;
  434. const float by = bmin[1] + (lh+2)*ch;
  435. const float bz = bmin[2] + (y+seg[3])*cs;
  436. dd->vertex(ax, ay, az, pcol);
  437. dd->vertex(bx, by, bz, pcol);
  438. }
  439. }
  440. }
  441. }
  442. dd->end();
  443. }
  444. void duDebugDrawTileCacheLayerAreas(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
  445. {
  446. const int w = (int)layer.header->width;
  447. const int h = (int)layer.header->height;
  448. const float* bmin = layer.header->bmin;
  449. const float* bmax = layer.header->bmax;
  450. const int idx = layer.header->tlayer;
  451. unsigned int color = duIntToCol(idx+1, 255);
  452. // Layer bounds
  453. float lbmin[3], lbmax[3];
  454. lbmin[0] = bmin[0] + layer.header->minx*cs;
  455. lbmin[1] = bmin[1];
  456. lbmin[2] = bmin[2] + layer.header->miny*cs;
  457. lbmax[0] = bmin[0] + (layer.header->maxx+1)*cs;
  458. lbmax[1] = bmax[1];
  459. lbmax[2] = bmin[2] + (layer.header->maxy+1)*cs;
  460. duDebugDrawBoxWire(dd, lbmin[0],lbmin[1],lbmin[2], lbmax[0],lbmax[1],lbmax[2], duTransCol(color,128), 2.0f);
  461. // Layer height
  462. dd->begin(DU_DRAW_QUADS);
  463. for (int y = 0; y < h; ++y)
  464. {
  465. for (int x = 0; x < w; ++x)
  466. {
  467. const int lidx = x+y*w;
  468. const int lh = (int)layer.heights[lidx];
  469. if (lh == 0xff) continue;
  470. const unsigned char area = layer.areas[lidx];
  471. unsigned int col;
  472. if (area == 63)
  473. col = duLerpCol(color, duRGBA(0,192,255,64), 32);
  474. else if (area == 0)
  475. col = duLerpCol(color, duRGBA(0,0,0,64), 32);
  476. else
  477. col = duLerpCol(color, dd->areaToCol(area), 32);
  478. const float fx = bmin[0] + x*cs;
  479. const float fy = bmin[1] + (lh+1)*ch;
  480. const float fz = bmin[2] + y*cs;
  481. dd->vertex(fx, fy, fz, col);
  482. dd->vertex(fx, fy, fz+cs, col);
  483. dd->vertex(fx+cs, fy, fz+cs, col);
  484. dd->vertex(fx+cs, fy, fz, col);
  485. }
  486. }
  487. dd->end();
  488. debugDrawTileCachePortals(dd, layer, cs, ch);
  489. }
  490. void duDebugDrawTileCacheLayerRegions(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
  491. {
  492. const int w = (int)layer.header->width;
  493. const int h = (int)layer.header->height;
  494. const float* bmin = layer.header->bmin;
  495. const float* bmax = layer.header->bmax;
  496. const int idx = layer.header->tlayer;
  497. unsigned int color = duIntToCol(idx+1, 255);
  498. // Layer bounds
  499. float lbmin[3], lbmax[3];
  500. lbmin[0] = bmin[0] + layer.header->minx*cs;
  501. lbmin[1] = bmin[1];
  502. lbmin[2] = bmin[2] + layer.header->miny*cs;
  503. lbmax[0] = bmin[0] + (layer.header->maxx+1)*cs;
  504. lbmax[1] = bmax[1];
  505. lbmax[2] = bmin[2] + (layer.header->maxy+1)*cs;
  506. duDebugDrawBoxWire(dd, lbmin[0],lbmin[1],lbmin[2], lbmax[0],lbmax[1],lbmax[2], duTransCol(color,128), 2.0f);
  507. // Layer height
  508. dd->begin(DU_DRAW_QUADS);
  509. for (int y = 0; y < h; ++y)
  510. {
  511. for (int x = 0; x < w; ++x)
  512. {
  513. const int lidx = x+y*w;
  514. const int lh = (int)layer.heights[lidx];
  515. if (lh == 0xff) continue;
  516. const unsigned char reg = layer.regs[lidx];
  517. unsigned int col = duLerpCol(color, duIntToCol(reg, 255), 192);
  518. const float fx = bmin[0] + x*cs;
  519. const float fy = bmin[1] + (lh+1)*ch;
  520. const float fz = bmin[2] + y*cs;
  521. dd->vertex(fx, fy, fz, col);
  522. dd->vertex(fx, fy, fz+cs, col);
  523. dd->vertex(fx+cs, fy, fz+cs, col);
  524. dd->vertex(fx+cs, fy, fz, col);
  525. }
  526. }
  527. dd->end();
  528. debugDrawTileCachePortals(dd, layer, cs, ch);
  529. }
  530. /*struct dtTileCacheContour
  531. {
  532. int nverts;
  533. unsigned char* verts;
  534. unsigned char reg;
  535. unsigned char area;
  536. };
  537. struct dtTileCacheContourSet
  538. {
  539. int nconts;
  540. dtTileCacheContour* conts;
  541. };*/
  542. void duDebugDrawTileCacheContours(duDebugDraw* dd, const struct dtTileCacheContourSet& lcset,
  543. const float* orig, const float cs, const float ch)
  544. {
  545. if (!dd) return;
  546. const unsigned char a = 255;// (unsigned char)(alpha*255.0f);
  547. const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
  548. dd->begin(DU_DRAW_LINES, 2.0f);
  549. for (int i = 0; i < lcset.nconts; ++i)
  550. {
  551. const dtTileCacheContour& c = lcset.conts[i];
  552. unsigned int color = 0;
  553. color = duIntToCol(i, a);
  554. for (int j = 0; j < c.nverts; ++j)
  555. {
  556. const int k = (j+1) % c.nverts;
  557. const unsigned char* va = &c.verts[j*4];
  558. const unsigned char* vb = &c.verts[k*4];
  559. const float ax = orig[0] + va[0]*cs;
  560. const float ay = orig[1] + (va[1]+1+(i&1))*ch;
  561. const float az = orig[2] + va[2]*cs;
  562. const float bx = orig[0] + vb[0]*cs;
  563. const float by = orig[1] + (vb[1]+1+(i&1))*ch;
  564. const float bz = orig[2] + vb[2]*cs;
  565. unsigned int col = color;
  566. if ((va[3] & 0xf) != 0xf)
  567. {
  568. // Portal segment
  569. col = duRGBA(255,255,255,128);
  570. int d = va[3] & 0xf;
  571. const float cx = (ax+bx)*0.5f;
  572. const float cy = (ay+by)*0.5f;
  573. const float cz = (az+bz)*0.5f;
  574. const float dx = cx + offs[d*2+0]*2*cs;
  575. const float dy = cy;
  576. const float dz = cz + offs[d*2+1]*2*cs;
  577. dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
  578. dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
  579. }
  580. duAppendArrow(dd, ax,ay,az, bx,by,bz, 0.0f, cs*0.5f, col);
  581. }
  582. }
  583. dd->end();
  584. dd->begin(DU_DRAW_POINTS, 4.0f);
  585. for (int i = 0; i < lcset.nconts; ++i)
  586. {
  587. const dtTileCacheContour& c = lcset.conts[i];
  588. unsigned int color = 0;
  589. for (int j = 0; j < c.nverts; ++j)
  590. {
  591. const unsigned char* va = &c.verts[j*4];
  592. color = duDarkenCol(duIntToCol(i, a));
  593. if (va[3] & 0x80)
  594. {
  595. // Border vertex
  596. color = duRGBA(255,0,0,255);
  597. }
  598. float fx = orig[0] + va[0]*cs;
  599. float fy = orig[1] + (va[1]+1+(i&1))*ch;
  600. float fz = orig[2] + va[2]*cs;
  601. dd->vertex(fx,fy,fz, color);
  602. }
  603. }
  604. dd->end();
  605. }
  606. void duDebugDrawTileCachePolyMesh(duDebugDraw* dd, const struct dtTileCachePolyMesh& lmesh,
  607. const float* orig, const float cs, const float ch)
  608. {
  609. if (!dd) return;
  610. const int nvp = lmesh.nvp;
  611. const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
  612. dd->begin(DU_DRAW_TRIS);
  613. for (int i = 0; i < lmesh.npolys; ++i)
  614. {
  615. const unsigned short* p = &lmesh.polys[i*nvp*2];
  616. const unsigned char area = lmesh.areas[i];
  617. unsigned int color;
  618. if (area == DT_TILECACHE_WALKABLE_AREA)
  619. color = duRGBA(0,192,255,64);
  620. else if (area == DT_TILECACHE_NULL_AREA)
  621. color = duRGBA(0,0,0,64);
  622. else
  623. color = dd->areaToCol(area);
  624. unsigned short vi[3];
  625. for (int j = 2; j < nvp; ++j)
  626. {
  627. if (p[j] == DT_TILECACHE_NULL_IDX) break;
  628. vi[0] = p[0];
  629. vi[1] = p[j-1];
  630. vi[2] = p[j];
  631. for (int k = 0; k < 3; ++k)
  632. {
  633. const unsigned short* v = &lmesh.verts[vi[k]*3];
  634. const float x = orig[0] + v[0]*cs;
  635. const float y = orig[1] + (v[1]+1)*ch;
  636. const float z = orig[2] + v[2]*cs;
  637. dd->vertex(x,y,z, color);
  638. }
  639. }
  640. }
  641. dd->end();
  642. // Draw neighbours edges
  643. const unsigned int coln = duRGBA(0,48,64,32);
  644. dd->begin(DU_DRAW_LINES, 1.5f);
  645. for (int i = 0; i < lmesh.npolys; ++i)
  646. {
  647. const unsigned short* p = &lmesh.polys[i*nvp*2];
  648. for (int j = 0; j < nvp; ++j)
  649. {
  650. if (p[j] == DT_TILECACHE_NULL_IDX) break;
  651. if (p[nvp+j] & 0x8000) continue;
  652. const int nj = (j+1 >= nvp || p[j+1] == DT_TILECACHE_NULL_IDX) ? 0 : j+1;
  653. int vi[2] = {p[j], p[nj]};
  654. for (int k = 0; k < 2; ++k)
  655. {
  656. const unsigned short* v = &lmesh.verts[vi[k]*3];
  657. const float x = orig[0] + v[0]*cs;
  658. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  659. const float z = orig[2] + v[2]*cs;
  660. dd->vertex(x, y, z, coln);
  661. }
  662. }
  663. }
  664. dd->end();
  665. // Draw boundary edges
  666. const unsigned int colb = duRGBA(0,48,64,220);
  667. dd->begin(DU_DRAW_LINES, 2.5f);
  668. for (int i = 0; i < lmesh.npolys; ++i)
  669. {
  670. const unsigned short* p = &lmesh.polys[i*nvp*2];
  671. for (int j = 0; j < nvp; ++j)
  672. {
  673. if (p[j] == DT_TILECACHE_NULL_IDX) break;
  674. if ((p[nvp+j] & 0x8000) == 0) continue;
  675. const int nj = (j+1 >= nvp || p[j+1] == DT_TILECACHE_NULL_IDX) ? 0 : j+1;
  676. int vi[2] = {p[j], p[nj]};
  677. unsigned int col = colb;
  678. if ((p[nvp+j] & 0xf) != 0xf)
  679. {
  680. const unsigned short* va = &lmesh.verts[vi[0]*3];
  681. const unsigned short* vb = &lmesh.verts[vi[1]*3];
  682. const float ax = orig[0] + va[0]*cs;
  683. const float ay = orig[1] + (va[1]+1+(i&1))*ch;
  684. const float az = orig[2] + va[2]*cs;
  685. const float bx = orig[0] + vb[0]*cs;
  686. const float by = orig[1] + (vb[1]+1+(i&1))*ch;
  687. const float bz = orig[2] + vb[2]*cs;
  688. const float cx = (ax+bx)*0.5f;
  689. const float cy = (ay+by)*0.5f;
  690. const float cz = (az+bz)*0.5f;
  691. int d = p[nvp+j] & 0xf;
  692. const float dx = cx + offs[d*2+0]*2*cs;
  693. const float dy = cy;
  694. const float dz = cz + offs[d*2+1]*2*cs;
  695. dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
  696. dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
  697. col = duRGBA(255,255,255,128);
  698. }
  699. for (int k = 0; k < 2; ++k)
  700. {
  701. const unsigned short* v = &lmesh.verts[vi[k]*3];
  702. const float x = orig[0] + v[0]*cs;
  703. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  704. const float z = orig[2] + v[2]*cs;
  705. dd->vertex(x, y, z, col);
  706. }
  707. }
  708. }
  709. dd->end();
  710. dd->begin(DU_DRAW_POINTS, 3.0f);
  711. const unsigned int colv = duRGBA(0,0,0,220);
  712. for (int i = 0; i < lmesh.nverts; ++i)
  713. {
  714. const unsigned short* v = &lmesh.verts[i*3];
  715. const float x = orig[0] + v[0]*cs;
  716. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  717. const float z = orig[2] + v[2]*cs;
  718. dd->vertex(x,y,z, colv);
  719. }
  720. dd->end();
  721. }