865 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			865 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// This software is provided 'as-is', without any express or implied
							 | 
						||
| 
								 | 
							
								// warranty.  In no event will the authors be held liable for any damages
							 | 
						||
| 
								 | 
							
								// arising from the use of this software.
							 | 
						||
| 
								 | 
							
								// Permission is granted to anyone to use this software for any purpose,
							 | 
						||
| 
								 | 
							
								// including commercial applications, and to alter it and redistribute it
							 | 
						||
| 
								 | 
							
								// freely, subject to the following restrictions:
							 | 
						||
| 
								 | 
							
								// 1. The origin of this software must not be misrepresented; you must not
							 | 
						||
| 
								 | 
							
								//    claim that you wrote the original software. If you use this software
							 | 
						||
| 
								 | 
							
								//    in a product, an acknowledgment in the product documentation would be
							 | 
						||
| 
								 | 
							
								//    appreciated but is not required.
							 | 
						||
| 
								 | 
							
								// 2. Altered source versions must be plainly marked as such, and must not be
							 | 
						||
| 
								 | 
							
								//    misrepresented as being the original software.
							 | 
						||
| 
								 | 
							
								// 3. This notice may not be removed or altered from any source distribution.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "DebugDraw.h"
							 | 
						||
| 
								 | 
							
								#include "DetourDebugDraw.h"
							 | 
						||
| 
								 | 
							
								#include "DetourNavMesh.h"
							 | 
						||
| 
								 | 
							
								#include "DetourCommon.h"
							 | 
						||
| 
								 | 
							
								#include "DetourNode.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static float distancePtLine2d(const float* pt, const float* p, const float* q)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									float pqx = q[0] - p[0];
							 | 
						||
| 
								 | 
							
									float pqz = q[2] - p[2];
							 | 
						||
| 
								 | 
							
									float dx = pt[0] - p[0];
							 | 
						||
| 
								 | 
							
									float dz = pt[2] - p[2];
							 | 
						||
| 
								 | 
							
									float d = pqx*pqx + pqz*pqz;
							 | 
						||
| 
								 | 
							
									float t = pqx*dx + pqz*dz;
							 | 
						||
| 
								 | 
							
									if (d != 0) t /= d;
							 | 
						||
| 
								 | 
							
									dx = p[0] + t*pqx - pt[0];
							 | 
						||
| 
								 | 
							
									dz = p[2] + t*pqz - pt[2];
							 | 
						||
| 
								 | 
							
									return dx*dx + dz*dz;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile,
							 | 
						||
| 
								 | 
							
															   const unsigned int col, const float linew,
							 | 
						||
| 
								 | 
							
															   bool inner)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									static const float thr = 0.01f*0.01f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_LINES, linew);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < tile->header->polyCount; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtPoly* p = &tile->polys[i];
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) continue;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										const dtPolyDetail* pd = &tile->detailMeshes[i];
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for (int j = 0, nj = (int)p->vertCount; j < nj; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											unsigned int c = col;
							 | 
						||
| 
								 | 
							
											if (inner)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (p->neis[j] == 0) continue;
							 | 
						||
| 
								 | 
							
												if (p->neis[j] & DT_EXT_LINK)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													bool con = false;
							 | 
						||
| 
								 | 
							
													for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														if (tile->links[k].edge == j)
							 | 
						||
| 
								 | 
							
														{
							 | 
						||
| 
								 | 
							
															con = true;
							 | 
						||
| 
								 | 
							
															break;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													if (con)
							 | 
						||
| 
								 | 
							
														c = duRGBA(255,255,255,48);
							 | 
						||
| 
								 | 
							
													else
							 | 
						||
| 
								 | 
							
														c = duRGBA(0,0,0,48);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													c = duRGBA(0,48,64,32);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (p->neis[j] != 0) continue;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											const float* v0 = &tile->verts[p->verts[j]*3];
							 | 
						||
| 
								 | 
							
											const float* v1 = &tile->verts[p->verts[(j+1) % nj]*3];
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											// Draw detail mesh edges which align with the actual poly edge.
							 | 
						||
| 
								 | 
							
											// This is really slow.
							 | 
						||
| 
								 | 
							
											for (int k = 0; k < pd->triCount; ++k)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												const unsigned char* t = &tile->detailTris[(pd->triBase+k)*4];
							 | 
						||
| 
								 | 
							
												const float* tv[3];
							 | 
						||
| 
								 | 
							
												for (int m = 0; m < 3; ++m)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if (t[m] < p->vertCount)
							 | 
						||
| 
								 | 
							
														tv[m] = &tile->verts[p->verts[t[m]]*3];
							 | 
						||
| 
								 | 
							
													else
							 | 
						||
| 
								 | 
							
														tv[m] = &tile->detailVerts[(pd->vertBase+(t[m]-p->vertCount))*3];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												for (int m = 0, n = 2; m < 3; n=m++)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ((dtGetDetailTriEdgeFlags(t[3], n) & DT_DETAIL_EDGE_BOUNDARY) == 0)
							 | 
						||
| 
								 | 
							
														continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if (distancePtLine2d(tv[n],v0,v1) < thr &&
							 | 
						||
| 
								 | 
							
														distancePtLine2d(tv[m],v0,v1) < thr)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														dd->vertex(tv[n], c);
							 | 
						||
| 
								 | 
							
														dd->vertex(tv[m], c);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query,
							 | 
						||
| 
								 | 
							
														 const dtMeshTile* tile, unsigned char flags)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									dtPolyRef base = mesh.getPolyRefBase(tile);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int tileNum = mesh.decodePolyIdTile(base);
							 | 
						||
| 
								 | 
							
									const unsigned int tileColor = duIntToCol(tileNum, 128);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->depthMask(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_TRIS);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < tile->header->polyCount; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtPoly* p = &tile->polys[i];
							 | 
						||
| 
								 | 
							
										if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)	// Skip off-mesh links.
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
										const dtPolyDetail* pd = &tile->detailMeshes[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										unsigned int col;
							 | 
						||
| 
								 | 
							
										if (query && query->isInClosedList(base | (dtPolyRef)i))
							 | 
						||
| 
								 | 
							
											col = duRGBA(255,196,0,64);
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if (flags & DU_DRAWNAVMESH_COLOR_TILES)
							 | 
						||
| 
								 | 
							
												col = tileColor;
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												col = duTransCol(dd->areaToCol(p->getArea()), 64);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for (int j = 0; j < pd->triCount; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
							 | 
						||
| 
								 | 
							
											for (int k = 0; k < 3; ++k)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (t[k] < p->vertCount)
							 | 
						||
| 
								 | 
							
													dd->vertex(&tile->verts[p->verts[t[k]]*3], col);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													dd->vertex(&tile->detailVerts[(pd->vertBase+t[k]-p->vertCount)*3], col);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Draw inter poly boundaries
							 | 
						||
| 
								 | 
							
									drawPolyBoundaries(dd, tile, duRGBA(0,48,64,32), 1.5f, true);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Draw outer poly boundaries
							 | 
						||
| 
								 | 
							
									drawPolyBoundaries(dd, tile, duRGBA(0,48,64,220), 2.5f, false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (flags & DU_DRAWNAVMESH_OFFMESHCONS)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										dd->begin(DU_DRAW_LINES, 2.0f);
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < tile->header->polyCount; ++i)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const dtPoly* p = &tile->polys[i];
							 | 
						||
| 
								 | 
							
											if (p->getType() != DT_POLYTYPE_OFFMESH_CONNECTION)	// Skip regular polys.
							 | 
						||
| 
								 | 
							
												continue;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											unsigned int col, col2;
							 | 
						||
| 
								 | 
							
											if (query && query->isInClosedList(base | (dtPolyRef)i))
							 | 
						||
| 
								 | 
							
												col = duRGBA(255,196,0,220);
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												col = duDarkenCol(duTransCol(dd->areaToCol(p->getArea()), 220));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const dtOffMeshConnection* con = &tile->offMeshCons[i - tile->header->offMeshBase];
							 | 
						||
| 
								 | 
							
											const float* va = &tile->verts[p->verts[0]*3];
							 | 
						||
| 
								 | 
							
											const float* vb = &tile->verts[p->verts[1]*3];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Check to see if start and end end-points have links.
							 | 
						||
| 
								 | 
							
											bool startSet = false;
							 | 
						||
| 
								 | 
							
											bool endSet = false;
							 | 
						||
| 
								 | 
							
											for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (tile->links[k].edge == 0)
							 | 
						||
| 
								 | 
							
													startSet = true;
							 | 
						||
| 
								 | 
							
												if (tile->links[k].edge == 1)
							 | 
						||
| 
								 | 
							
													endSet = true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											// End points and their on-mesh locations.
							 | 
						||
| 
								 | 
							
											dd->vertex(va[0],va[1],va[2], col);
							 | 
						||
| 
								 | 
							
											dd->vertex(con->pos[0],con->pos[1],con->pos[2], col);
							 | 
						||
| 
								 | 
							
											col2 = startSet ? col : duRGBA(220,32,16,196);
							 | 
						||
| 
								 | 
							
											duAppendCircle(dd, con->pos[0],con->pos[1]+0.1f,con->pos[2], con->rad, col2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											dd->vertex(vb[0],vb[1],vb[2], col);
							 | 
						||
| 
								 | 
							
											dd->vertex(con->pos[3],con->pos[4],con->pos[5], col);
							 | 
						||
| 
								 | 
							
											col2 = endSet ? col : duRGBA(220,32,16,196);
							 | 
						||
| 
								 | 
							
											duAppendCircle(dd, con->pos[3],con->pos[4]+0.1f,con->pos[5], con->rad, col2);
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											// End point vertices.
							 | 
						||
| 
								 | 
							
											dd->vertex(con->pos[0],con->pos[1],con->pos[2], duRGBA(0,48,64,196));
							 | 
						||
| 
								 | 
							
											dd->vertex(con->pos[0],con->pos[1]+0.2f,con->pos[2], duRGBA(0,48,64,196));
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											dd->vertex(con->pos[3],con->pos[4],con->pos[5], duRGBA(0,48,64,196));
							 | 
						||
| 
								 | 
							
											dd->vertex(con->pos[3],con->pos[4]+0.2f,con->pos[5], duRGBA(0,48,64,196));
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											// Connection arc.
							 | 
						||
| 
								 | 
							
											duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
							 | 
						||
| 
								 | 
							
														(con->flags & 1) ? 0.6f : 0, 0.6f, col);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										dd->end();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const unsigned int vcol = duRGBA(0,0,0,196);
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_POINTS, 3.0f);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < tile->header->vertCount; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const float* v = &tile->verts[i*3];
							 | 
						||
| 
								 | 
							
										dd->vertex(v[0], v[1], v[2], vcol);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									dd->depthMask(true);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh& mesh, unsigned char flags)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < mesh.getMaxTiles(); ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtMeshTile* tile = mesh.getTile(i);
							 | 
						||
| 
								 | 
							
										if (!tile->header) continue;
							 | 
						||
| 
								 | 
							
										drawMeshTile(dd, mesh, 0, tile, flags);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, unsigned char flags)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const dtNavMeshQuery* q = (flags & DU_DRAWNAVMESH_CLOSEDLIST) ? &query : 0;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < mesh.getMaxTiles(); ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtMeshTile* tile = mesh.getTile(i);
							 | 
						||
| 
								 | 
							
										if (!tile->header) continue;
							 | 
						||
| 
								 | 
							
										drawMeshTile(dd, mesh, q, tile, flags);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawNavMeshNodes(struct duDebugDraw* dd, const dtNavMeshQuery& query)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const dtNodePool* pool = query.getNodePool();
							 | 
						||
| 
								 | 
							
									if (pool)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const float off = 0.5f;
							 | 
						||
| 
								 | 
							
										dd->begin(DU_DRAW_POINTS, 4.0f);
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < pool->getHashSize(); ++i)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for (dtNodeIndex j = pool->getFirst(i); j != DT_NULL_IDX; j = pool->getNext(j))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												const dtNode* node = pool->getNodeAtIdx(j+1);
							 | 
						||
| 
								 | 
							
												if (!node) continue;
							 | 
						||
| 
								 | 
							
												dd->vertex(node->pos[0],node->pos[1]+off,node->pos[2], duRGBA(255,192,0,255));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										dd->end();
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										dd->begin(DU_DRAW_LINES, 2.0f);
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < pool->getHashSize(); ++i)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for (dtNodeIndex j = pool->getFirst(i); j != DT_NULL_IDX; j = pool->getNext(j))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												const dtNode* node = pool->getNodeAtIdx(j+1);
							 | 
						||
| 
								 | 
							
												if (!node) continue;
							 | 
						||
| 
								 | 
							
												if (!node->pidx) continue;
							 | 
						||
| 
								 | 
							
												const dtNode* parent = pool->getNodeAtIdx(node->pidx);
							 | 
						||
| 
								 | 
							
												if (!parent) continue;
							 | 
						||
| 
								 | 
							
												dd->vertex(node->pos[0],node->pos[1]+off,node->pos[2], duRGBA(255,192,0,128));
							 | 
						||
| 
								 | 
							
												dd->vertex(parent->pos[0],parent->pos[1]+off,parent->pos[2], duRGBA(255,192,0,128));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										dd->end();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void drawMeshTileBVTree(duDebugDraw* dd, const dtMeshTile* tile)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									// Draw BV nodes.
							 | 
						||
| 
								 | 
							
									const float cs = 1.0f / tile->header->bvQuantFactor;
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_LINES, 1.0f);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < tile->header->bvNodeCount; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtBVNode* n = &tile->bvTree[i];
							 | 
						||
| 
								 | 
							
										if (n->i < 0) // Leaf indices are positive.
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										duAppendBoxWire(dd, tile->header->bmin[0] + n->bmin[0]*cs,
							 | 
						||
| 
								 | 
							
														tile->header->bmin[1] + n->bmin[1]*cs,
							 | 
						||
| 
								 | 
							
														tile->header->bmin[2] + n->bmin[2]*cs,
							 | 
						||
| 
								 | 
							
														tile->header->bmin[0] + n->bmax[0]*cs,
							 | 
						||
| 
								 | 
							
														tile->header->bmin[1] + n->bmax[1]*cs,
							 | 
						||
| 
								 | 
							
														tile->header->bmin[2] + n->bmax[2]*cs,
							 | 
						||
| 
								 | 
							
														duRGBA(255,255,255,128));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawNavMeshBVTree(duDebugDraw* dd, const dtNavMesh& mesh)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < mesh.getMaxTiles(); ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtMeshTile* tile = mesh.getTile(i);
							 | 
						||
| 
								 | 
							
										if (!tile->header) continue;
							 | 
						||
| 
								 | 
							
										drawMeshTileBVTree(dd, tile);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void drawMeshTilePortal(duDebugDraw* dd, const dtMeshTile* tile)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									// Draw portals
							 | 
						||
| 
								 | 
							
									const float padx = 0.04f;
							 | 
						||
| 
								 | 
							
									const float pady = tile->header->walkableClimb;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_LINES, 2.0f);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (int side = 0; side < 8; ++side)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										unsigned short m = DT_EXT_LINK | (unsigned short)side;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < tile->header->polyCount; ++i)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											dtPoly* poly = &tile->polys[i];
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											// Create new links.
							 | 
						||
| 
								 | 
							
											const int nv = poly->vertCount;
							 | 
						||
| 
								 | 
							
											for (int j = 0; j < nv; ++j)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												// Skip edges which do not point to the right side.
							 | 
						||
| 
								 | 
							
												if (poly->neis[j] != m)
							 | 
						||
| 
								 | 
							
													continue;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												// Create new links
							 | 
						||
| 
								 | 
							
												const float* va = &tile->verts[poly->verts[j]*3];
							 | 
						||
| 
								 | 
							
												const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3];
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												if (side == 0 || side == 4)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													unsigned int col = side == 0 ? duRGBA(128,0,0,128) : duRGBA(128,0,128,128);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													const float x = va[0] + ((side == 0) ? -padx : padx);
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													dd->vertex(x,va[1]-pady,va[2], col);
							 | 
						||
| 
								 | 
							
													dd->vertex(x,va[1]+pady,va[2], col);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													dd->vertex(x,va[1]+pady,va[2], col);
							 | 
						||
| 
								 | 
							
													dd->vertex(x,vb[1]+pady,vb[2], col);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													dd->vertex(x,vb[1]+pady,vb[2], col);
							 | 
						||
| 
								 | 
							
													dd->vertex(x,vb[1]-pady,vb[2], col);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													dd->vertex(x,vb[1]-pady,vb[2], col);
							 | 
						||
| 
								 | 
							
													dd->vertex(x,va[1]-pady,va[2], col);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if (side == 2 || side == 6)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													unsigned int col = side == 2 ? duRGBA(0,128,0,128) : duRGBA(0,128,128,128);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													const float z = va[2] + ((side == 2) ? -padx : padx);
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													dd->vertex(va[0],va[1]-pady,z, col);
							 | 
						||
| 
								 | 
							
													dd->vertex(va[0],va[1]+pady,z, col);
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													dd->vertex(va[0],va[1]+pady,z, col);
							 | 
						||
| 
								 | 
							
													dd->vertex(vb[0],vb[1]+pady,z, col);
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													dd->vertex(vb[0],vb[1]+pady,z, col);
							 | 
						||
| 
								 | 
							
													dd->vertex(vb[0],vb[1]-pady,z, col);
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													dd->vertex(vb[0],vb[1]-pady,z, col);
							 | 
						||
| 
								 | 
							
													dd->vertex(va[0],va[1]-pady,z, col);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawNavMeshPortals(duDebugDraw* dd, const dtNavMesh& mesh)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < mesh.getMaxTiles(); ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtMeshTile* tile = mesh.getTile(i);
							 | 
						||
| 
								 | 
							
										if (!tile->header) continue;
							 | 
						||
| 
								 | 
							
										drawMeshTilePortal(dd, tile);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawNavMeshPolysWithFlags(struct duDebugDraw* dd, const dtNavMesh& mesh,
							 | 
						||
| 
								 | 
							
																	  const unsigned short polyFlags, const unsigned int col)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < mesh.getMaxTiles(); ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtMeshTile* tile = mesh.getTile(i);
							 | 
						||
| 
								 | 
							
										if (!tile->header) continue;
							 | 
						||
| 
								 | 
							
										dtPolyRef base = mesh.getPolyRefBase(tile);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (int j = 0; j < tile->header->polyCount; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const dtPoly* p = &tile->polys[j];
							 | 
						||
| 
								 | 
							
											if ((p->flags & polyFlags) == 0) continue;
							 | 
						||
| 
								 | 
							
											duDebugDrawNavMeshPoly(dd, mesh, base|(dtPolyRef)j, col);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawNavMeshPoly(duDebugDraw* dd, const dtNavMesh& mesh, dtPolyRef ref, const unsigned int col)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const dtMeshTile* tile = 0;
							 | 
						||
| 
								 | 
							
									const dtPoly* poly = 0;
							 | 
						||
| 
								 | 
							
									if (dtStatusFailed(mesh.getTileAndPolyByRef(ref, &tile, &poly)))
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->depthMask(false);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const unsigned int c = duTransCol(col, 64);
							 | 
						||
| 
								 | 
							
									const unsigned int ip = (unsigned int)(poly - tile->polys);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										dtOffMeshConnection* con = &tile->offMeshCons[ip - tile->header->offMeshBase];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										dd->begin(DU_DRAW_LINES, 2.0f);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Connection arc.
							 | 
						||
| 
								 | 
							
										duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
							 | 
						||
| 
								 | 
							
													(con->flags & 1) ? 0.6f : 0.0f, 0.6f, c);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										dd->end();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtPolyDetail* pd = &tile->detailMeshes[ip];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										dd->begin(DU_DRAW_TRIS);
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < pd->triCount; ++i)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const unsigned char* t = &tile->detailTris[(pd->triBase+i)*4];
							 | 
						||
| 
								 | 
							
											for (int j = 0; j < 3; ++j)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (t[j] < poly->vertCount)
							 | 
						||
| 
								 | 
							
													dd->vertex(&tile->verts[poly->verts[t[j]]*3], c);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													dd->vertex(&tile->detailVerts[(pd->vertBase+t[j]-poly->vertCount)*3], c);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										dd->end();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->depthMask(true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void debugDrawTileCachePortals(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									const int w = (int)layer.header->width;
							 | 
						||
| 
								 | 
							
									const int h = (int)layer.header->height;
							 | 
						||
| 
								 | 
							
									const float* bmin = layer.header->bmin;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Portals
							 | 
						||
| 
								 | 
							
									unsigned int pcol = duRGBA(255,255,255,255);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const int segs[4*4] = {0,0,0,1, 0,1,1,1, 1,1,1,0, 1,0,0,0};
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Layer portals
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_LINES, 2.0f);
							 | 
						||
| 
								 | 
							
									for (int y = 0; y < h; ++y)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (int x = 0; x < w; ++x)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const int idx = x+y*w;
							 | 
						||
| 
								 | 
							
											const int lh = (int)layer.heights[idx];
							 | 
						||
| 
								 | 
							
											if (lh == 0xff) continue;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											for (int dir = 0; dir < 4; ++dir)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (layer.cons[idx] & (1<<(dir+4)))
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													const int* seg = &segs[dir*4];
							 | 
						||
| 
								 | 
							
													const float ax = bmin[0] + (x+seg[0])*cs;
							 | 
						||
| 
								 | 
							
													const float ay = bmin[1] + (lh+2)*ch;
							 | 
						||
| 
								 | 
							
													const float az = bmin[2] + (y+seg[1])*cs;
							 | 
						||
| 
								 | 
							
													const float bx = bmin[0] + (x+seg[2])*cs;
							 | 
						||
| 
								 | 
							
													const float by = bmin[1] + (lh+2)*ch;
							 | 
						||
| 
								 | 
							
													const float bz = bmin[2] + (y+seg[3])*cs;
							 | 
						||
| 
								 | 
							
													dd->vertex(ax, ay, az, pcol);
							 | 
						||
| 
								 | 
							
													dd->vertex(bx, by, bz, pcol);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawTileCacheLayerAreas(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									const int w = (int)layer.header->width;
							 | 
						||
| 
								 | 
							
									const int h = (int)layer.header->height;
							 | 
						||
| 
								 | 
							
									const float* bmin = layer.header->bmin;
							 | 
						||
| 
								 | 
							
									const float* bmax = layer.header->bmax;
							 | 
						||
| 
								 | 
							
									const int idx = layer.header->tlayer;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									unsigned int color = duIntToCol(idx+1, 255);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Layer bounds
							 | 
						||
| 
								 | 
							
									float lbmin[3], lbmax[3];
							 | 
						||
| 
								 | 
							
									lbmin[0] = bmin[0] + layer.header->minx*cs;
							 | 
						||
| 
								 | 
							
									lbmin[1] = bmin[1];
							 | 
						||
| 
								 | 
							
									lbmin[2] = bmin[2] + layer.header->miny*cs;
							 | 
						||
| 
								 | 
							
									lbmax[0] = bmin[0] + (layer.header->maxx+1)*cs;
							 | 
						||
| 
								 | 
							
									lbmax[1] = bmax[1];
							 | 
						||
| 
								 | 
							
									lbmax[2] = bmin[2] + (layer.header->maxy+1)*cs;
							 | 
						||
| 
								 | 
							
									duDebugDrawBoxWire(dd, lbmin[0],lbmin[1],lbmin[2], lbmax[0],lbmax[1],lbmax[2], duTransCol(color,128), 2.0f);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Layer height
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_QUADS);
							 | 
						||
| 
								 | 
							
									for (int y = 0; y < h; ++y)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (int x = 0; x < w; ++x)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const int lidx = x+y*w;
							 | 
						||
| 
								 | 
							
											const int lh = (int)layer.heights[lidx];
							 | 
						||
| 
								 | 
							
											if (lh == 0xff) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const unsigned char area = layer.areas[lidx];
							 | 
						||
| 
								 | 
							
											unsigned int col;
							 | 
						||
| 
								 | 
							
											if (area == 63)
							 | 
						||
| 
								 | 
							
												col = duLerpCol(color, duRGBA(0,192,255,64), 32);
							 | 
						||
| 
								 | 
							
											else if (area == 0)
							 | 
						||
| 
								 | 
							
												col = duLerpCol(color, duRGBA(0,0,0,64), 32);
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												col = duLerpCol(color, dd->areaToCol(area), 32);
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											const float fx = bmin[0] + x*cs;
							 | 
						||
| 
								 | 
							
											const float fy = bmin[1] + (lh+1)*ch;
							 | 
						||
| 
								 | 
							
											const float fz = bmin[2] + y*cs;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											dd->vertex(fx, fy, fz, col);
							 | 
						||
| 
								 | 
							
											dd->vertex(fx, fy, fz+cs, col);
							 | 
						||
| 
								 | 
							
											dd->vertex(fx+cs, fy, fz+cs, col);
							 | 
						||
| 
								 | 
							
											dd->vertex(fx+cs, fy, fz, col);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									debugDrawTileCachePortals(dd, layer, cs, ch);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawTileCacheLayerRegions(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									const int w = (int)layer.header->width;
							 | 
						||
| 
								 | 
							
									const int h = (int)layer.header->height;
							 | 
						||
| 
								 | 
							
									const float* bmin = layer.header->bmin;
							 | 
						||
| 
								 | 
							
									const float* bmax = layer.header->bmax;
							 | 
						||
| 
								 | 
							
									const int idx = layer.header->tlayer;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									unsigned int color = duIntToCol(idx+1, 255);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Layer bounds
							 | 
						||
| 
								 | 
							
									float lbmin[3], lbmax[3];
							 | 
						||
| 
								 | 
							
									lbmin[0] = bmin[0] + layer.header->minx*cs;
							 | 
						||
| 
								 | 
							
									lbmin[1] = bmin[1];
							 | 
						||
| 
								 | 
							
									lbmin[2] = bmin[2] + layer.header->miny*cs;
							 | 
						||
| 
								 | 
							
									lbmax[0] = bmin[0] + (layer.header->maxx+1)*cs;
							 | 
						||
| 
								 | 
							
									lbmax[1] = bmax[1];
							 | 
						||
| 
								 | 
							
									lbmax[2] = bmin[2] + (layer.header->maxy+1)*cs;
							 | 
						||
| 
								 | 
							
									duDebugDrawBoxWire(dd, lbmin[0],lbmin[1],lbmin[2], lbmax[0],lbmax[1],lbmax[2], duTransCol(color,128), 2.0f);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Layer height
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_QUADS);
							 | 
						||
| 
								 | 
							
									for (int y = 0; y < h; ++y)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (int x = 0; x < w; ++x)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const int lidx = x+y*w;
							 | 
						||
| 
								 | 
							
											const int lh = (int)layer.heights[lidx];
							 | 
						||
| 
								 | 
							
											if (lh == 0xff) continue;
							 | 
						||
| 
								 | 
							
											const unsigned char reg = layer.regs[lidx];
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											unsigned int col = duLerpCol(color, duIntToCol(reg, 255), 192);
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											const float fx = bmin[0] + x*cs;
							 | 
						||
| 
								 | 
							
											const float fy = bmin[1] + (lh+1)*ch;
							 | 
						||
| 
								 | 
							
											const float fz = bmin[2] + y*cs;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											dd->vertex(fx, fy, fz, col);
							 | 
						||
| 
								 | 
							
											dd->vertex(fx, fy, fz+cs, col);
							 | 
						||
| 
								 | 
							
											dd->vertex(fx+cs, fy, fz+cs, col);
							 | 
						||
| 
								 | 
							
											dd->vertex(fx+cs, fy, fz, col);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									debugDrawTileCachePortals(dd, layer, cs, ch);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*struct dtTileCacheContour
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int nverts;
							 | 
						||
| 
								 | 
							
									unsigned char* verts;
							 | 
						||
| 
								 | 
							
									unsigned char reg;
							 | 
						||
| 
								 | 
							
									unsigned char area;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct dtTileCacheContourSet
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int nconts;
							 | 
						||
| 
								 | 
							
									dtTileCacheContour* conts;
							 | 
						||
| 
								 | 
							
								};*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawTileCacheContours(duDebugDraw* dd, const struct dtTileCacheContourSet& lcset,
							 | 
						||
| 
								 | 
							
																  const float* orig, const float cs, const float ch)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const unsigned char a = 255;// (unsigned char)(alpha*255.0f);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_LINES, 2.0f);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < lcset.nconts; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtTileCacheContour& c = lcset.conts[i];
							 | 
						||
| 
								 | 
							
										unsigned int color = 0;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										color = duIntToCol(i, a);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for (int j = 0; j < c.nverts; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const int k = (j+1) % c.nverts;
							 | 
						||
| 
								 | 
							
											const unsigned char* va = &c.verts[j*4];
							 | 
						||
| 
								 | 
							
											const unsigned char* vb = &c.verts[k*4];
							 | 
						||
| 
								 | 
							
											const float ax = orig[0] + va[0]*cs;
							 | 
						||
| 
								 | 
							
											const float ay = orig[1] + (va[1]+1+(i&1))*ch;
							 | 
						||
| 
								 | 
							
											const float az = orig[2] + va[2]*cs;
							 | 
						||
| 
								 | 
							
											const float bx = orig[0] + vb[0]*cs;
							 | 
						||
| 
								 | 
							
											const float by = orig[1] + (vb[1]+1+(i&1))*ch;
							 | 
						||
| 
								 | 
							
											const float bz = orig[2] + vb[2]*cs;
							 | 
						||
| 
								 | 
							
											unsigned int col = color;
							 | 
						||
| 
								 | 
							
											if ((va[3] & 0xf) != 0xf)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												// Portal segment
							 | 
						||
| 
								 | 
							
												col = duRGBA(255,255,255,128);
							 | 
						||
| 
								 | 
							
												int d = va[3] & 0xf;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												const float cx = (ax+bx)*0.5f;
							 | 
						||
| 
								 | 
							
												const float cy = (ay+by)*0.5f;
							 | 
						||
| 
								 | 
							
												const float cz = (az+bz)*0.5f;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												const float dx = cx + offs[d*2+0]*2*cs;
							 | 
						||
| 
								 | 
							
												const float dy = cy;
							 | 
						||
| 
								 | 
							
												const float dz = cz + offs[d*2+1]*2*cs;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
							 | 
						||
| 
								 | 
							
												dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											duAppendArrow(dd, ax,ay,az, bx,by,bz, 0.0f, cs*0.5f, col);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_POINTS, 4.0f);	
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < lcset.nconts; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const dtTileCacheContour& c = lcset.conts[i];
							 | 
						||
| 
								 | 
							
										unsigned int color = 0;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for (int j = 0; j < c.nverts; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const unsigned char* va = &c.verts[j*4];
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											color = duDarkenCol(duIntToCol(i, a));
							 | 
						||
| 
								 | 
							
											if (va[3] & 0x80)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												// Border vertex
							 | 
						||
| 
								 | 
							
												color = duRGBA(255,0,0,255);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											float fx = orig[0] + va[0]*cs;
							 | 
						||
| 
								 | 
							
											float fy = orig[1] + (va[1]+1+(i&1))*ch;
							 | 
						||
| 
								 | 
							
											float fz = orig[2] + va[2]*cs;
							 | 
						||
| 
								 | 
							
											dd->vertex(fx,fy,fz, color);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void duDebugDrawTileCachePolyMesh(duDebugDraw* dd, const struct dtTileCachePolyMesh& lmesh,
							 | 
						||
| 
								 | 
							
																  const float* orig, const float cs, const float ch)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!dd) return;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const int nvp = lmesh.nvp;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_TRIS);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < lmesh.npolys; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const unsigned short* p = &lmesh.polys[i*nvp*2];
							 | 
						||
| 
								 | 
							
										const unsigned char area = lmesh.areas[i];
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										unsigned int color;
							 | 
						||
| 
								 | 
							
										if (area == DT_TILECACHE_WALKABLE_AREA)
							 | 
						||
| 
								 | 
							
											color = duRGBA(0,192,255,64);
							 | 
						||
| 
								 | 
							
										else if (area == DT_TILECACHE_NULL_AREA)
							 | 
						||
| 
								 | 
							
											color = duRGBA(0,0,0,64);
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											color = dd->areaToCol(area);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										unsigned short vi[3];
							 | 
						||
| 
								 | 
							
										for (int j = 2; j < nvp; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if (p[j] == DT_TILECACHE_NULL_IDX) break;
							 | 
						||
| 
								 | 
							
											vi[0] = p[0];
							 | 
						||
| 
								 | 
							
											vi[1] = p[j-1];
							 | 
						||
| 
								 | 
							
											vi[2] = p[j];
							 | 
						||
| 
								 | 
							
											for (int k = 0; k < 3; ++k)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												const unsigned short* v = &lmesh.verts[vi[k]*3];
							 | 
						||
| 
								 | 
							
												const float x = orig[0] + v[0]*cs;
							 | 
						||
| 
								 | 
							
												const float y = orig[1] + (v[1]+1)*ch;
							 | 
						||
| 
								 | 
							
												const float z = orig[2] + v[2]*cs;
							 | 
						||
| 
								 | 
							
												dd->vertex(x,y,z, color);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Draw neighbours edges
							 | 
						||
| 
								 | 
							
									const unsigned int coln = duRGBA(0,48,64,32);
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_LINES, 1.5f);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < lmesh.npolys; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const unsigned short* p = &lmesh.polys[i*nvp*2];
							 | 
						||
| 
								 | 
							
										for (int j = 0; j < nvp; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if (p[j] == DT_TILECACHE_NULL_IDX) break;
							 | 
						||
| 
								 | 
							
											if (p[nvp+j] & 0x8000) continue;
							 | 
						||
| 
								 | 
							
											const int nj = (j+1 >= nvp || p[j+1] == DT_TILECACHE_NULL_IDX) ? 0 : j+1; 
							 | 
						||
| 
								 | 
							
											int vi[2] = {p[j], p[nj]};
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											for (int k = 0; k < 2; ++k)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												const unsigned short* v = &lmesh.verts[vi[k]*3];
							 | 
						||
| 
								 | 
							
												const float x = orig[0] + v[0]*cs;
							 | 
						||
| 
								 | 
							
												const float y = orig[1] + (v[1]+1)*ch + 0.1f;
							 | 
						||
| 
								 | 
							
												const float z = orig[2] + v[2]*cs;
							 | 
						||
| 
								 | 
							
												dd->vertex(x, y, z, coln);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Draw boundary edges
							 | 
						||
| 
								 | 
							
									const unsigned int colb = duRGBA(0,48,64,220);
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_LINES, 2.5f);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < lmesh.npolys; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const unsigned short* p = &lmesh.polys[i*nvp*2];
							 | 
						||
| 
								 | 
							
										for (int j = 0; j < nvp; ++j)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if (p[j] == DT_TILECACHE_NULL_IDX) break;
							 | 
						||
| 
								 | 
							
											if ((p[nvp+j] & 0x8000) == 0) continue;
							 | 
						||
| 
								 | 
							
											const int nj = (j+1 >= nvp || p[j+1] == DT_TILECACHE_NULL_IDX) ? 0 : j+1; 
							 | 
						||
| 
								 | 
							
											int vi[2] = {p[j], p[nj]};
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											unsigned int col = colb;
							 | 
						||
| 
								 | 
							
											if ((p[nvp+j] & 0xf) != 0xf)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												const unsigned short* va = &lmesh.verts[vi[0]*3];
							 | 
						||
| 
								 | 
							
												const unsigned short* vb = &lmesh.verts[vi[1]*3];
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												const float ax = orig[0] + va[0]*cs;
							 | 
						||
| 
								 | 
							
												const float ay = orig[1] + (va[1]+1+(i&1))*ch;
							 | 
						||
| 
								 | 
							
												const float az = orig[2] + va[2]*cs;
							 | 
						||
| 
								 | 
							
												const float bx = orig[0] + vb[0]*cs;
							 | 
						||
| 
								 | 
							
												const float by = orig[1] + (vb[1]+1+(i&1))*ch;
							 | 
						||
| 
								 | 
							
												const float bz = orig[2] + vb[2]*cs;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												const float cx = (ax+bx)*0.5f;
							 | 
						||
| 
								 | 
							
												const float cy = (ay+by)*0.5f;
							 | 
						||
| 
								 | 
							
												const float cz = (az+bz)*0.5f;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												int d = p[nvp+j] & 0xf;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												const float dx = cx + offs[d*2+0]*2*cs;
							 | 
						||
| 
								 | 
							
												const float dy = cy;
							 | 
						||
| 
								 | 
							
												const float dz = cz + offs[d*2+1]*2*cs;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
							 | 
						||
| 
								 | 
							
												dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												col = duRGBA(255,255,255,128);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											for (int k = 0; k < 2; ++k)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												const unsigned short* v = &lmesh.verts[vi[k]*3];
							 | 
						||
| 
								 | 
							
												const float x = orig[0] + v[0]*cs;
							 | 
						||
| 
								 | 
							
												const float y = orig[1] + (v[1]+1)*ch + 0.1f;
							 | 
						||
| 
								 | 
							
												const float z = orig[2] + v[2]*cs;
							 | 
						||
| 
								 | 
							
												dd->vertex(x, y, z, col);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									dd->begin(DU_DRAW_POINTS, 3.0f);
							 | 
						||
| 
								 | 
							
									const unsigned int colv = duRGBA(0,0,0,220);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < lmesh.nverts; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const unsigned short* v = &lmesh.verts[i*3];
							 | 
						||
| 
								 | 
							
										const float x = orig[0] + v[0]*cs;
							 | 
						||
| 
								 | 
							
										const float y = orig[1] + (v[1]+1)*ch + 0.1f;
							 | 
						||
| 
								 | 
							
										const float z = orig[2] + v[2]*cs;
							 | 
						||
| 
								 | 
							
										dd->vertex(x,y,z, colv);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									dd->end();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |