RecastDebugDraw.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  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. #define _USE_MATH_DEFINES
  19. #include <math.h>
  20. #include "DebugDraw.h"
  21. #include "RecastDebugDraw.h"
  22. #include "recast/Recast/Recast.h"
  23. void duDebugDrawTriMesh(duDebugDraw* dd, const float* verts, int /*nverts*/,
  24. const int* tris, const float* normals, int ntris,
  25. const unsigned char* flags, const float texScale)
  26. {
  27. if (!dd) return;
  28. if (!verts) return;
  29. if (!tris) return;
  30. if (!normals) return;
  31. float uva[2];
  32. float uvb[2];
  33. float uvc[2];
  34. const unsigned int unwalkable = duRGBA(192,128,0,255);
  35. dd->texture(true);
  36. dd->begin(DU_DRAW_TRIS);
  37. for (int i = 0; i < ntris*3; i += 3)
  38. {
  39. const float* norm = &normals[i];
  40. unsigned int color;
  41. unsigned char a = (unsigned char)(220*(2+norm[0]+norm[1])/4);
  42. if (flags && !flags[i/3])
  43. color = duLerpCol(duRGBA(a,a,a,255), unwalkable, 64);
  44. else
  45. color = duRGBA(a,a,a,255);
  46. const float* va = &verts[tris[i+0]*3];
  47. const float* vb = &verts[tris[i+1]*3];
  48. const float* vc = &verts[tris[i+2]*3];
  49. int ax = 0, ay = 0;
  50. if (rcAbs(norm[1]) > rcAbs(norm[ax]))
  51. ax = 1;
  52. if (rcAbs(norm[2]) > rcAbs(norm[ax]))
  53. ax = 2;
  54. ax = (1<<ax)&3; // +1 mod 3
  55. ay = (1<<ax)&3; // +1 mod 3
  56. uva[0] = va[ax]*texScale;
  57. uva[1] = va[ay]*texScale;
  58. uvb[0] = vb[ax]*texScale;
  59. uvb[1] = vb[ay]*texScale;
  60. uvc[0] = vc[ax]*texScale;
  61. uvc[1] = vc[ay]*texScale;
  62. dd->vertex(va, color, uva);
  63. dd->vertex(vb, color, uvb);
  64. dd->vertex(vc, color, uvc);
  65. }
  66. dd->end();
  67. dd->texture(false);
  68. }
  69. void duDebugDrawTriMeshSlope(duDebugDraw* dd, const float* verts, int /*nverts*/,
  70. const int* tris, const float* normals, int ntris,
  71. const float walkableSlopeAngle, const float texScale)
  72. {
  73. if (!dd) return;
  74. if (!verts) return;
  75. if (!tris) return;
  76. if (!normals) return;
  77. const float walkableThr = cosf(walkableSlopeAngle/180.0f*DU_PI);
  78. float uva[2];
  79. float uvb[2];
  80. float uvc[2];
  81. dd->texture(true);
  82. const unsigned int unwalkable = duRGBA(192,128,0,255);
  83. dd->begin(DU_DRAW_TRIS);
  84. for (int i = 0; i < ntris*3; i += 3)
  85. {
  86. const float* norm = &normals[i];
  87. unsigned int color;
  88. unsigned char a = (unsigned char)(220*(2+norm[0]+norm[1])/4);
  89. if (norm[1] < walkableThr)
  90. color = duLerpCol(duRGBA(a,a,a,255), unwalkable, 64);
  91. else
  92. color = duRGBA(a,a,a,255);
  93. const float* va = &verts[tris[i+0]*3];
  94. const float* vb = &verts[tris[i+1]*3];
  95. const float* vc = &verts[tris[i+2]*3];
  96. int ax = 0, ay = 0;
  97. if (rcAbs(norm[1]) > rcAbs(norm[ax]))
  98. ax = 1;
  99. if (rcAbs(norm[2]) > rcAbs(norm[ax]))
  100. ax = 2;
  101. ax = (1<<ax)&3; // +1 mod 3
  102. ay = (1<<ax)&3; // +1 mod 3
  103. uva[0] = va[ax]*texScale;
  104. uva[1] = va[ay]*texScale;
  105. uvb[0] = vb[ax]*texScale;
  106. uvb[1] = vb[ay]*texScale;
  107. uvc[0] = vc[ax]*texScale;
  108. uvc[1] = vc[ay]*texScale;
  109. dd->vertex(va, color, uva);
  110. dd->vertex(vb, color, uvb);
  111. dd->vertex(vc, color, uvc);
  112. }
  113. dd->end();
  114. dd->texture(false);
  115. }
  116. void duDebugDrawHeightfieldSolid(duDebugDraw* dd, const rcHeightfield& hf)
  117. {
  118. if (!dd) return;
  119. const float* orig = hf.bmin;
  120. const float cs = hf.cs;
  121. const float ch = hf.ch;
  122. const int w = hf.width;
  123. const int h = hf.height;
  124. unsigned int fcol[6];
  125. duCalcBoxColors(fcol, duRGBA(255,255,255,255), duRGBA(255,255,255,255));
  126. dd->begin(DU_DRAW_QUADS);
  127. for (int y = 0; y < h; ++y)
  128. {
  129. for (int x = 0; x < w; ++x)
  130. {
  131. float fx = orig[0] + x*cs;
  132. float fz = orig[2] + y*cs;
  133. const rcSpan* s = hf.spans[x + y*w];
  134. while (s)
  135. {
  136. duAppendBox(dd, fx, orig[1]+s->smin*ch, fz, fx+cs, orig[1] + s->smax*ch, fz+cs, fcol);
  137. s = s->next;
  138. }
  139. }
  140. }
  141. dd->end();
  142. }
  143. void duDebugDrawHeightfieldWalkable(duDebugDraw* dd, const rcHeightfield& hf)
  144. {
  145. if (!dd) return;
  146. const float* orig = hf.bmin;
  147. const float cs = hf.cs;
  148. const float ch = hf.ch;
  149. const int w = hf.width;
  150. const int h = hf.height;
  151. unsigned int fcol[6];
  152. duCalcBoxColors(fcol, duRGBA(255,255,255,255), duRGBA(217,217,217,255));
  153. dd->begin(DU_DRAW_QUADS);
  154. for (int y = 0; y < h; ++y)
  155. {
  156. for (int x = 0; x < w; ++x)
  157. {
  158. float fx = orig[0] + x*cs;
  159. float fz = orig[2] + y*cs;
  160. const rcSpan* s = hf.spans[x + y*w];
  161. while (s)
  162. {
  163. if (s->area == RC_WALKABLE_AREA)
  164. fcol[0] = duRGBA(64,128,160,255);
  165. else if (s->area == RC_NULL_AREA)
  166. fcol[0] = duRGBA(64,64,64,255);
  167. else
  168. fcol[0] = duMultCol(duIntToCol(s->area, 255), 200);
  169. duAppendBox(dd, fx, orig[1]+s->smin*ch, fz, fx+cs, orig[1] + s->smax*ch, fz+cs, fcol);
  170. s = s->next;
  171. }
  172. }
  173. }
  174. dd->end();
  175. }
  176. void duDebugDrawCompactHeightfieldSolid(duDebugDraw* dd, const rcCompactHeightfield& chf)
  177. {
  178. if (!dd) return;
  179. const float cs = chf.cs;
  180. const float ch = chf.ch;
  181. dd->begin(DU_DRAW_QUADS);
  182. for (int y = 0; y < chf.height; ++y)
  183. {
  184. for (int x = 0; x < chf.width; ++x)
  185. {
  186. const float fx = chf.bmin[0] + x*cs;
  187. const float fz = chf.bmin[2] + y*cs;
  188. const rcCompactCell& c = chf.cells[x+y*chf.width];
  189. for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
  190. {
  191. const rcCompactSpan& s = chf.spans[i];
  192. unsigned int color;
  193. if (chf.areas[i] == RC_WALKABLE_AREA)
  194. color = duRGBA(0,192,255,64);
  195. else if (chf.areas[i] == RC_NULL_AREA)
  196. color = duRGBA(0,0,0,64);
  197. else
  198. color = duIntToCol(chf.areas[i], 255);
  199. const float fy = chf.bmin[1] + (s.y+1)*ch;
  200. dd->vertex(fx, fy, fz, color);
  201. dd->vertex(fx, fy, fz+cs, color);
  202. dd->vertex(fx+cs, fy, fz+cs, color);
  203. dd->vertex(fx+cs, fy, fz, color);
  204. }
  205. }
  206. }
  207. dd->end();
  208. }
  209. void duDebugDrawCompactHeightfieldRegions(duDebugDraw* dd, const rcCompactHeightfield& chf)
  210. {
  211. if (!dd) return;
  212. const float cs = chf.cs;
  213. const float ch = chf.ch;
  214. dd->begin(DU_DRAW_QUADS);
  215. for (int y = 0; y < chf.height; ++y)
  216. {
  217. for (int x = 0; x < chf.width; ++x)
  218. {
  219. const float fx = chf.bmin[0] + x*cs;
  220. const float fz = chf.bmin[2] + y*cs;
  221. const rcCompactCell& c = chf.cells[x+y*chf.width];
  222. for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
  223. {
  224. const rcCompactSpan& s = chf.spans[i];
  225. const float fy = chf.bmin[1] + (s.y)*ch;
  226. unsigned int color;
  227. if (s.reg)
  228. color = duIntToCol(s.reg, 192);
  229. else
  230. color = duRGBA(0,0,0,64);
  231. dd->vertex(fx, fy, fz, color);
  232. dd->vertex(fx, fy, fz+cs, color);
  233. dd->vertex(fx+cs, fy, fz+cs, color);
  234. dd->vertex(fx+cs, fy, fz, color);
  235. }
  236. }
  237. }
  238. dd->end();
  239. }
  240. void duDebugDrawCompactHeightfieldDistance(duDebugDraw* dd, const rcCompactHeightfield& chf)
  241. {
  242. if (!dd) return;
  243. if (!chf.dist) return;
  244. const float cs = chf.cs;
  245. const float ch = chf.ch;
  246. float maxd = chf.maxDistance;
  247. if (maxd < 1.0f) maxd = 1;
  248. const float dscale = 255.0f / maxd;
  249. dd->begin(DU_DRAW_QUADS);
  250. for (int y = 0; y < chf.height; ++y)
  251. {
  252. for (int x = 0; x < chf.width; ++x)
  253. {
  254. const float fx = chf.bmin[0] + x*cs;
  255. const float fz = chf.bmin[2] + y*cs;
  256. const rcCompactCell& c = chf.cells[x+y*chf.width];
  257. for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
  258. {
  259. const rcCompactSpan& s = chf.spans[i];
  260. const float fy = chf.bmin[1] + (s.y+1)*ch;
  261. const unsigned char cd = (unsigned char)(chf.dist[i] * dscale);
  262. const unsigned int color = duRGBA(cd,cd,cd,255);
  263. dd->vertex(fx, fy, fz, color);
  264. dd->vertex(fx, fy, fz+cs, color);
  265. dd->vertex(fx+cs, fy, fz+cs, color);
  266. dd->vertex(fx+cs, fy, fz, color);
  267. }
  268. }
  269. }
  270. dd->end();
  271. }
  272. static void drawLayerPortals(duDebugDraw* dd, const rcHeightfieldLayer* layer)
  273. {
  274. const float cs = layer->cs;
  275. const float ch = layer->ch;
  276. const int w = layer->width;
  277. const int h = layer->height;
  278. unsigned int pcol = duRGBA(255,255,255,255);
  279. const int segs[4*4] = {0,0,0,1, 0,1,1,1, 1,1,1,0, 1,0,0,0};
  280. // Layer portals
  281. dd->begin(DU_DRAW_LINES, 2.0f);
  282. for (int y = 0; y < h; ++y)
  283. {
  284. for (int x = 0; x < w; ++x)
  285. {
  286. const int idx = x+y*w;
  287. const int lh = (int)layer->heights[idx];
  288. if (lh == 255) continue;
  289. for (int dir = 0; dir < 4; ++dir)
  290. {
  291. if (layer->cons[idx] & (1<<(dir+4)))
  292. {
  293. const int* seg = &segs[dir*4];
  294. const float ax = layer->bmin[0] + (x+seg[0])*cs;
  295. const float ay = layer->bmin[1] + (lh+2)*ch;
  296. const float az = layer->bmin[2] + (y+seg[1])*cs;
  297. const float bx = layer->bmin[0] + (x+seg[2])*cs;
  298. const float by = layer->bmin[1] + (lh+2)*ch;
  299. const float bz = layer->bmin[2] + (y+seg[3])*cs;
  300. dd->vertex(ax, ay, az, pcol);
  301. dd->vertex(bx, by, bz, pcol);
  302. }
  303. }
  304. }
  305. }
  306. dd->end();
  307. }
  308. void duDebugDrawHeightfieldLayer(duDebugDraw* dd, const struct rcHeightfieldLayer& layer, const int idx)
  309. {
  310. const float cs = layer.cs;
  311. const float ch = layer.ch;
  312. const int w = layer.width;
  313. const int h = layer.height;
  314. unsigned int color = duIntToCol(idx+1, 255);
  315. // Layer bounds
  316. float bmin[3], bmax[3];
  317. bmin[0] = layer.bmin[0] + layer.minx*cs;
  318. bmin[1] = layer.bmin[1];
  319. bmin[2] = layer.bmin[2] + layer.miny*cs;
  320. bmax[0] = layer.bmin[0] + (layer.maxx+1)*cs;
  321. bmax[1] = layer.bmax[1];
  322. bmax[2] = layer.bmin[2] + (layer.maxy+1)*cs;
  323. duDebugDrawBoxWire(dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], duTransCol(color,128), 2.0f);
  324. // Layer height
  325. dd->begin(DU_DRAW_QUADS);
  326. for (int y = 0; y < h; ++y)
  327. {
  328. for (int x = 0; x < w; ++x)
  329. {
  330. const int lidx = x+y*w;
  331. const int lh = (int)layer.heights[lidx];
  332. if (h == 0xff) continue;
  333. const unsigned char area = layer.areas[lidx];
  334. unsigned int col;
  335. if (area == RC_WALKABLE_AREA)
  336. col = duLerpCol(color, duRGBA(0,192,255,64), 32);
  337. else if (area == RC_NULL_AREA)
  338. col = duLerpCol(color, duRGBA(0,0,0,64), 32);
  339. else
  340. col = duLerpCol(color, duIntToCol(area, 255), 32);
  341. const float fx = layer.bmin[0] + x*cs;
  342. const float fy = layer.bmin[1] + (lh+1)*ch;
  343. const float fz = layer.bmin[2] + y*cs;
  344. dd->vertex(fx, fy, fz, col);
  345. dd->vertex(fx, fy, fz+cs, col);
  346. dd->vertex(fx+cs, fy, fz+cs, col);
  347. dd->vertex(fx+cs, fy, fz, col);
  348. }
  349. }
  350. dd->end();
  351. // Portals
  352. drawLayerPortals(dd, &layer);
  353. }
  354. void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset)
  355. {
  356. if (!dd) return;
  357. for (int i = 0; i < lset.nlayers; ++i)
  358. duDebugDrawHeightfieldLayer(dd, lset.layers[i], i);
  359. }
  360. /*
  361. void duDebugDrawLayerContours(duDebugDraw* dd, const struct rcLayerContourSet& lcset)
  362. {
  363. if (!dd) return;
  364. const float* orig = lcset.bmin;
  365. const float cs = lcset.cs;
  366. const float ch = lcset.ch;
  367. const unsigned char a = 255;// (unsigned char)(alpha*255.0f);
  368. const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
  369. dd->begin(DU_DRAW_LINES, 2.0f);
  370. for (int i = 0; i < lcset.nconts; ++i)
  371. {
  372. const rcLayerContour& c = lcset.conts[i];
  373. unsigned int color = 0;
  374. color = duIntToCol(i, a);
  375. for (int j = 0; j < c.nverts; ++j)
  376. {
  377. const int k = (j+1) % c.nverts;
  378. const unsigned char* va = &c.verts[j*4];
  379. const unsigned char* vb = &c.verts[k*4];
  380. const float ax = orig[0] + va[0]*cs;
  381. const float ay = orig[1] + (va[1]+1+(i&1))*ch;
  382. const float az = orig[2] + va[2]*cs;
  383. const float bx = orig[0] + vb[0]*cs;
  384. const float by = orig[1] + (vb[1]+1+(i&1))*ch;
  385. const float bz = orig[2] + vb[2]*cs;
  386. unsigned int col = color;
  387. if ((va[3] & 0xf) != 0xf)
  388. {
  389. col = duRGBA(255,255,255,128);
  390. int d = va[3] & 0xf;
  391. const float cx = (ax+bx)*0.5f;
  392. const float cy = (ay+by)*0.5f;
  393. const float cz = (az+bz)*0.5f;
  394. const float dx = cx + offs[d*2+0]*2*cs;
  395. const float dy = cy;
  396. const float dz = cz + offs[d*2+1]*2*cs;
  397. dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
  398. dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
  399. }
  400. duAppendArrow(dd, ax,ay,az, bx,by,bz, 0.0f, cs*0.5f, col);
  401. }
  402. }
  403. dd->end();
  404. dd->begin(DU_DRAW_POINTS, 4.0f);
  405. for (int i = 0; i < lcset.nconts; ++i)
  406. {
  407. const rcLayerContour& c = lcset.conts[i];
  408. unsigned int color = 0;
  409. for (int j = 0; j < c.nverts; ++j)
  410. {
  411. const unsigned char* va = &c.verts[j*4];
  412. color = duDarkenCol(duIntToCol(i, a));
  413. if (va[3] & 0x80)
  414. color = duRGBA(255,0,0,255);
  415. float fx = orig[0] + va[0]*cs;
  416. float fy = orig[1] + (va[1]+1+(i&1))*ch;
  417. float fz = orig[2] + va[2]*cs;
  418. dd->vertex(fx,fy,fz, color);
  419. }
  420. }
  421. dd->end();
  422. }
  423. void duDebugDrawLayerPolyMesh(duDebugDraw* dd, const struct rcLayerPolyMesh& lmesh)
  424. {
  425. if (!dd) return;
  426. const int nvp = lmesh.nvp;
  427. const float cs = lmesh.cs;
  428. const float ch = lmesh.ch;
  429. const float* orig = lmesh.bmin;
  430. const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
  431. dd->begin(DU_DRAW_TRIS);
  432. for (int i = 0; i < lmesh.npolys; ++i)
  433. {
  434. const unsigned short* p = &lmesh.polys[i*nvp*2];
  435. unsigned int color;
  436. if (lmesh.areas[i] == RC_WALKABLE_AREA)
  437. color = duRGBA(0,192,255,64);
  438. else if (lmesh.areas[i] == RC_NULL_AREA)
  439. color = duRGBA(0,0,0,64);
  440. else
  441. color = duIntToCol(lmesh.areas[i], 255);
  442. unsigned short vi[3];
  443. for (int j = 2; j < nvp; ++j)
  444. {
  445. if (p[j] == RC_MESH_NULL_IDX) break;
  446. vi[0] = p[0];
  447. vi[1] = p[j-1];
  448. vi[2] = p[j];
  449. for (int k = 0; k < 3; ++k)
  450. {
  451. const unsigned short* v = &lmesh.verts[vi[k]*3];
  452. const float x = orig[0] + v[0]*cs;
  453. const float y = orig[1] + (v[1]+1)*ch;
  454. const float z = orig[2] + v[2]*cs;
  455. dd->vertex(x,y,z, color);
  456. }
  457. }
  458. }
  459. dd->end();
  460. // Draw neighbours edges
  461. const unsigned int coln = duRGBA(0,48,64,32);
  462. dd->begin(DU_DRAW_LINES, 1.5f);
  463. for (int i = 0; i < lmesh.npolys; ++i)
  464. {
  465. const unsigned short* p = &lmesh.polys[i*nvp*2];
  466. for (int j = 0; j < nvp; ++j)
  467. {
  468. if (p[j] == RC_MESH_NULL_IDX) break;
  469. if (p[nvp+j] & 0x8000) continue;
  470. const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1;
  471. int vi[2] = {p[j], p[nj]};
  472. for (int k = 0; k < 2; ++k)
  473. {
  474. const unsigned short* v = &lmesh.verts[vi[k]*3];
  475. const float x = orig[0] + v[0]*cs;
  476. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  477. const float z = orig[2] + v[2]*cs;
  478. dd->vertex(x, y, z, coln);
  479. }
  480. }
  481. }
  482. dd->end();
  483. // Draw boundary edges
  484. const unsigned int colb = duRGBA(0,48,64,220);
  485. dd->begin(DU_DRAW_LINES, 2.5f);
  486. for (int i = 0; i < lmesh.npolys; ++i)
  487. {
  488. const unsigned short* p = &lmesh.polys[i*nvp*2];
  489. for (int j = 0; j < nvp; ++j)
  490. {
  491. if (p[j] == RC_MESH_NULL_IDX) break;
  492. if ((p[nvp+j] & 0x8000) == 0) continue;
  493. const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1;
  494. int vi[2] = {p[j], p[nj]};
  495. unsigned int col = colb;
  496. if ((p[nvp+j] & 0xf) != 0xf)
  497. {
  498. const unsigned short* va = &lmesh.verts[vi[0]*3];
  499. const unsigned short* vb = &lmesh.verts[vi[1]*3];
  500. const float ax = orig[0] + va[0]*cs;
  501. const float ay = orig[1] + (va[1]+1+(i&1))*ch;
  502. const float az = orig[2] + va[2]*cs;
  503. const float bx = orig[0] + vb[0]*cs;
  504. const float by = orig[1] + (vb[1]+1+(i&1))*ch;
  505. const float bz = orig[2] + vb[2]*cs;
  506. const float cx = (ax+bx)*0.5f;
  507. const float cy = (ay+by)*0.5f;
  508. const float cz = (az+bz)*0.5f;
  509. int d = p[nvp+j] & 0xf;
  510. const float dx = cx + offs[d*2+0]*2*cs;
  511. const float dy = cy;
  512. const float dz = cz + offs[d*2+1]*2*cs;
  513. dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
  514. dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
  515. col = duRGBA(255,255,255,128);
  516. }
  517. for (int k = 0; k < 2; ++k)
  518. {
  519. const unsigned short* v = &lmesh.verts[vi[k]*3];
  520. const float x = orig[0] + v[0]*cs;
  521. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  522. const float z = orig[2] + v[2]*cs;
  523. dd->vertex(x, y, z, col);
  524. }
  525. }
  526. }
  527. dd->end();
  528. dd->begin(DU_DRAW_POINTS, 3.0f);
  529. const unsigned int colv = duRGBA(0,0,0,220);
  530. for (int i = 0; i < lmesh.nverts; ++i)
  531. {
  532. const unsigned short* v = &lmesh.verts[i*3];
  533. const float x = orig[0] + v[0]*cs;
  534. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  535. const float z = orig[2] + v[2]*cs;
  536. dd->vertex(x,y,z, colv);
  537. }
  538. dd->end();
  539. }
  540. */
  541. static void getContourCenter(const rcContour* cont, const float* orig, float cs, float ch, float* center)
  542. {
  543. center[0] = 0;
  544. center[1] = 0;
  545. center[2] = 0;
  546. if (!cont->nverts)
  547. return;
  548. for (int i = 0; i < cont->nverts; ++i)
  549. {
  550. const int* v = &cont->verts[i*4];
  551. center[0] += (float)v[0];
  552. center[1] += (float)v[1];
  553. center[2] += (float)v[2];
  554. }
  555. const float s = 1.0f / cont->nverts;
  556. center[0] *= s * cs;
  557. center[1] *= s * ch;
  558. center[2] *= s * cs;
  559. center[0] += orig[0];
  560. center[1] += orig[1] + 4*ch;
  561. center[2] += orig[2];
  562. }
  563. static const rcContour* findContourFromSet(const rcContourSet& cset, unsigned short reg)
  564. {
  565. for (int i = 0; i < cset.nconts; ++i)
  566. {
  567. if (cset.conts[i].reg == reg)
  568. return &cset.conts[i];
  569. }
  570. return 0;
  571. }
  572. void duDebugDrawRegionConnections(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
  573. {
  574. if (!dd) return;
  575. const float* orig = cset.bmin;
  576. const float cs = cset.cs;
  577. const float ch = cset.ch;
  578. // Draw centers
  579. float pos[3], pos2[3];
  580. unsigned int color = duRGBA(0,0,0,196);
  581. dd->begin(DU_DRAW_LINES, 2.0f);
  582. for (int i = 0; i < cset.nconts; ++i)
  583. {
  584. const rcContour* cont = &cset.conts[i];
  585. getContourCenter(cont, orig, cs, ch, pos);
  586. for (int j = 0; j < cont->nverts; ++j)
  587. {
  588. const int* v = &cont->verts[j*4];
  589. if (v[3] == 0 || (unsigned short)v[3] < cont->reg) continue;
  590. const rcContour* cont2 = findContourFromSet(cset, (unsigned short)v[3]);
  591. if (cont2)
  592. {
  593. getContourCenter(cont2, orig, cs, ch, pos2);
  594. duAppendArc(dd, pos[0],pos[1],pos[2], pos2[0],pos2[1],pos2[2], 0.25f, 0.6f, 0.6f, color);
  595. }
  596. }
  597. }
  598. dd->end();
  599. unsigned char a = (unsigned char)(alpha * 255.0f);
  600. dd->begin(DU_DRAW_POINTS, 7.0f);
  601. for (int i = 0; i < cset.nconts; ++i)
  602. {
  603. const rcContour* cont = &cset.conts[i];
  604. unsigned int col = duDarkenCol(duIntToCol(cont->reg,a));
  605. getContourCenter(cont, orig, cs, ch, pos);
  606. dd->vertex(pos, col);
  607. }
  608. dd->end();
  609. }
  610. void duDebugDrawRawContours(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
  611. {
  612. if (!dd) return;
  613. const float* orig = cset.bmin;
  614. const float cs = cset.cs;
  615. const float ch = cset.ch;
  616. const unsigned char a = (unsigned char)(alpha*255.0f);
  617. dd->begin(DU_DRAW_LINES, 2.0f);
  618. for (int i = 0; i < cset.nconts; ++i)
  619. {
  620. const rcContour& c = cset.conts[i];
  621. unsigned int color = duIntToCol(c.reg, a);
  622. for (int j = 0; j < c.nrverts; ++j)
  623. {
  624. const int* v = &c.rverts[j*4];
  625. float fx = orig[0] + v[0]*cs;
  626. float fy = orig[1] + (v[1]+1+(i&1))*ch;
  627. float fz = orig[2] + v[2]*cs;
  628. dd->vertex(fx,fy,fz,color);
  629. if (j > 0)
  630. dd->vertex(fx,fy,fz,color);
  631. }
  632. // Loop last segment.
  633. const int* v = &c.rverts[0];
  634. float fx = orig[0] + v[0]*cs;
  635. float fy = orig[1] + (v[1]+1+(i&1))*ch;
  636. float fz = orig[2] + v[2]*cs;
  637. dd->vertex(fx,fy,fz,color);
  638. }
  639. dd->end();
  640. dd->begin(DU_DRAW_POINTS, 2.0f);
  641. for (int i = 0; i < cset.nconts; ++i)
  642. {
  643. const rcContour& c = cset.conts[i];
  644. unsigned int color = duDarkenCol(duIntToCol(c.reg, a));
  645. for (int j = 0; j < c.nrverts; ++j)
  646. {
  647. const int* v = &c.rverts[j*4];
  648. float off = 0;
  649. unsigned int colv = color;
  650. if (v[3] & RC_BORDER_VERTEX)
  651. {
  652. colv = duRGBA(255,255,255,a);
  653. off = ch*2;
  654. }
  655. float fx = orig[0] + v[0]*cs;
  656. float fy = orig[1] + (v[1]+1+(i&1))*ch + off;
  657. float fz = orig[2] + v[2]*cs;
  658. dd->vertex(fx,fy,fz, colv);
  659. }
  660. }
  661. dd->end();
  662. }
  663. void duDebugDrawContours(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
  664. {
  665. if (!dd) return;
  666. const float* orig = cset.bmin;
  667. const float cs = cset.cs;
  668. const float ch = cset.ch;
  669. const unsigned char a = (unsigned char)(alpha*255.0f);
  670. dd->begin(DU_DRAW_LINES, 2.5f);
  671. for (int i = 0; i < cset.nconts; ++i)
  672. {
  673. const rcContour& c = cset.conts[i];
  674. if (!c.nverts)
  675. continue;
  676. const unsigned int color = duIntToCol(c.reg, a);
  677. const unsigned int bcolor = duLerpCol(color,duRGBA(255,255,255,a),128);
  678. for (int j = 0, k = c.nverts-1; j < c.nverts; k=j++)
  679. {
  680. const int* va = &c.verts[k*4];
  681. const int* vb = &c.verts[j*4];
  682. unsigned int col = (va[3] & RC_AREA_BORDER) ? bcolor : color;
  683. float fx,fy,fz;
  684. fx = orig[0] + va[0]*cs;
  685. fy = orig[1] + (va[1]+1+(i&1))*ch;
  686. fz = orig[2] + va[2]*cs;
  687. dd->vertex(fx,fy,fz, col);
  688. fx = orig[0] + vb[0]*cs;
  689. fy = orig[1] + (vb[1]+1+(i&1))*ch;
  690. fz = orig[2] + vb[2]*cs;
  691. dd->vertex(fx,fy,fz, col);
  692. }
  693. }
  694. dd->end();
  695. dd->begin(DU_DRAW_POINTS, 3.0f);
  696. for (int i = 0; i < cset.nconts; ++i)
  697. {
  698. const rcContour& c = cset.conts[i];
  699. unsigned int color = duDarkenCol(duIntToCol(c.reg, a));
  700. for (int j = 0; j < c.nverts; ++j)
  701. {
  702. const int* v = &c.verts[j*4];
  703. float off = 0;
  704. unsigned int colv = color;
  705. if (v[3] & RC_BORDER_VERTEX)
  706. {
  707. colv = duRGBA(255,255,255,a);
  708. off = ch*2;
  709. }
  710. float fx = orig[0] + v[0]*cs;
  711. float fy = orig[1] + (v[1]+1+(i&1))*ch + off;
  712. float fz = orig[2] + v[2]*cs;
  713. dd->vertex(fx,fy,fz, colv);
  714. }
  715. }
  716. dd->end();
  717. }
  718. void duDebugDrawPolyMesh(duDebugDraw* dd, const struct rcPolyMesh& mesh)
  719. {
  720. if (!dd) return;
  721. const int nvp = mesh.nvp;
  722. const float cs = mesh.cs;
  723. const float ch = mesh.ch;
  724. const float* orig = mesh.bmin;
  725. dd->begin(DU_DRAW_TRIS);
  726. for (int i = 0; i < mesh.npolys; ++i)
  727. {
  728. const unsigned short* p = &mesh.polys[i*nvp*2];
  729. unsigned int color;
  730. if (mesh.areas[i] == RC_WALKABLE_AREA)
  731. color = duRGBA(0,192,255,64);
  732. else if (mesh.areas[i] == RC_NULL_AREA)
  733. color = duRGBA(0,0,0,64);
  734. else
  735. color = duIntToCol(mesh.areas[i], 255);
  736. unsigned short vi[3];
  737. for (int j = 2; j < nvp; ++j)
  738. {
  739. if (p[j] == RC_MESH_NULL_IDX) break;
  740. vi[0] = p[0];
  741. vi[1] = p[j-1];
  742. vi[2] = p[j];
  743. for (int k = 0; k < 3; ++k)
  744. {
  745. const unsigned short* v = &mesh.verts[vi[k]*3];
  746. const float x = orig[0] + v[0]*cs;
  747. const float y = orig[1] + (v[1]+1)*ch;
  748. const float z = orig[2] + v[2]*cs;
  749. dd->vertex(x,y,z, color);
  750. }
  751. }
  752. }
  753. dd->end();
  754. // Draw neighbours edges
  755. const unsigned int coln = duRGBA(0,48,64,32);
  756. dd->begin(DU_DRAW_LINES, 1.5f);
  757. for (int i = 0; i < mesh.npolys; ++i)
  758. {
  759. const unsigned short* p = &mesh.polys[i*nvp*2];
  760. for (int j = 0; j < nvp; ++j)
  761. {
  762. if (p[j] == RC_MESH_NULL_IDX) break;
  763. if (p[nvp+j] & 0x8000) continue;
  764. const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1;
  765. const int vi[2] = {p[j], p[nj]};
  766. for (int k = 0; k < 2; ++k)
  767. {
  768. const unsigned short* v = &mesh.verts[vi[k]*3];
  769. const float x = orig[0] + v[0]*cs;
  770. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  771. const float z = orig[2] + v[2]*cs;
  772. dd->vertex(x, y, z, coln);
  773. }
  774. }
  775. }
  776. dd->end();
  777. // Draw boundary edges
  778. const unsigned int colb = duRGBA(0,48,64,220);
  779. dd->begin(DU_DRAW_LINES, 2.5f);
  780. for (int i = 0; i < mesh.npolys; ++i)
  781. {
  782. const unsigned short* p = &mesh.polys[i*nvp*2];
  783. for (int j = 0; j < nvp; ++j)
  784. {
  785. if (p[j] == RC_MESH_NULL_IDX) break;
  786. if ((p[nvp+j] & 0x8000) == 0) continue;
  787. const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1;
  788. const int vi[2] = {p[j], p[nj]};
  789. unsigned int col = colb;
  790. if ((p[nvp+j] & 0xf) != 0xf)
  791. col = duRGBA(255,255,255,128);
  792. for (int k = 0; k < 2; ++k)
  793. {
  794. const unsigned short* v = &mesh.verts[vi[k]*3];
  795. const float x = orig[0] + v[0]*cs;
  796. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  797. const float z = orig[2] + v[2]*cs;
  798. dd->vertex(x, y, z, col);
  799. }
  800. }
  801. }
  802. dd->end();
  803. dd->begin(DU_DRAW_POINTS, 3.0f);
  804. const unsigned int colv = duRGBA(0,0,0,220);
  805. for (int i = 0; i < mesh.nverts; ++i)
  806. {
  807. const unsigned short* v = &mesh.verts[i*3];
  808. const float x = orig[0] + v[0]*cs;
  809. const float y = orig[1] + (v[1]+1)*ch + 0.1f;
  810. const float z = orig[2] + v[2]*cs;
  811. dd->vertex(x,y,z, colv);
  812. }
  813. dd->end();
  814. }
  815. void duDebugDrawPolyMeshDetail(duDebugDraw* dd, const struct rcPolyMeshDetail& dmesh)
  816. {
  817. if (!dd) return;
  818. dd->begin(DU_DRAW_TRIS);
  819. for (int i = 0; i < dmesh.nmeshes; ++i)
  820. {
  821. const unsigned int* m = &dmesh.meshes[i*4];
  822. const unsigned int bverts = m[0];
  823. const unsigned int btris = m[2];
  824. const int ntris = (int)m[3];
  825. const float* verts = &dmesh.verts[bverts*3];
  826. const unsigned char* tris = &dmesh.tris[btris*4];
  827. unsigned int color = duIntToCol(i, 192);
  828. for (int j = 0; j < ntris; ++j)
  829. {
  830. dd->vertex(&verts[tris[j*4+0]*3], color);
  831. dd->vertex(&verts[tris[j*4+1]*3], color);
  832. dd->vertex(&verts[tris[j*4+2]*3], color);
  833. }
  834. }
  835. dd->end();
  836. // Internal edges.
  837. dd->begin(DU_DRAW_LINES, 1.0f);
  838. const unsigned int coli = duRGBA(0,0,0,64);
  839. for (int i = 0; i < dmesh.nmeshes; ++i)
  840. {
  841. const unsigned int* m = &dmesh.meshes[i*4];
  842. const unsigned int bverts = m[0];
  843. const unsigned int btris = m[2];
  844. const int ntris = (int)m[3];
  845. const float* verts = &dmesh.verts[bverts*3];
  846. const unsigned char* tris = &dmesh.tris[btris*4];
  847. for (int j = 0; j < ntris; ++j)
  848. {
  849. const unsigned char* t = &tris[j*4];
  850. for (int k = 0, kp = 2; k < 3; kp=k++)
  851. {
  852. unsigned char ef = (t[3] >> (kp*2)) & 0x3;
  853. if (ef == 0)
  854. {
  855. // Internal edge
  856. if (t[kp] < t[k])
  857. {
  858. dd->vertex(&verts[t[kp]*3], coli);
  859. dd->vertex(&verts[t[k]*3], coli);
  860. }
  861. }
  862. }
  863. }
  864. }
  865. dd->end();
  866. // External edges.
  867. dd->begin(DU_DRAW_LINES, 2.0f);
  868. const unsigned int cole = duRGBA(0,0,0,64);
  869. for (int i = 0; i < dmesh.nmeshes; ++i)
  870. {
  871. const unsigned int* m = &dmesh.meshes[i*4];
  872. const unsigned int bverts = m[0];
  873. const unsigned int btris = m[2];
  874. const int ntris = (int)m[3];
  875. const float* verts = &dmesh.verts[bverts*3];
  876. const unsigned char* tris = &dmesh.tris[btris*4];
  877. for (int j = 0; j < ntris; ++j)
  878. {
  879. const unsigned char* t = &tris[j*4];
  880. for (int k = 0, kp = 2; k < 3; kp=k++)
  881. {
  882. unsigned char ef = (t[3] >> (kp*2)) & 0x3;
  883. if (ef != 0)
  884. {
  885. // Ext edge
  886. dd->vertex(&verts[t[kp]*3], cole);
  887. dd->vertex(&verts[t[k]*3], cole);
  888. }
  889. }
  890. }
  891. }
  892. dd->end();
  893. dd->begin(DU_DRAW_POINTS, 3.0f);
  894. const unsigned int colv = duRGBA(0,0,0,64);
  895. for (int i = 0; i < dmesh.nmeshes; ++i)
  896. {
  897. const unsigned int* m = &dmesh.meshes[i*4];
  898. const unsigned int bverts = m[0];
  899. const int nverts = (int)m[1];
  900. const float* verts = &dmesh.verts[bverts*3];
  901. for (int j = 0; j < nverts; ++j)
  902. dd->vertex(&verts[j*3], colv);
  903. }
  904. dd->end();
  905. }