Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

Diff Revisions 152 vs 315 for /trunk/Source Code/Libs/src/ReCast/DebugUtils/Source/DetourDebugDraw.cpp

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