613 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			613 lines
		
	
	
		
			16 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.
 | ||
|  | //
 | ||
|  | 
 | ||
|  | #define _USE_MATH_DEFINES
 | ||
|  | #include <string.h>
 | ||
|  | #include "DebugDraw.h"
 | ||
|  | #include "DetourMath.h"
 | ||
|  | #include "DetourNavMesh.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | duDebugDraw::~duDebugDraw() | ||
|  | { | ||
|  | 	// Empty
 | ||
|  | } | ||
|  | 
 | ||
|  | unsigned int duDebugDraw::areaToCol(unsigned int area) | ||
|  | { | ||
|  | 	if (area == 0) | ||
|  | 	{ | ||
|  | 		// Treat zero area type as default.
 | ||
|  | 		return duRGBA(0, 192, 255, 255); | ||
|  | 	} | ||
|  | 	else | ||
|  | 	{ | ||
|  | 		return duIntToCol(area, 255); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | inline int bit(int a, int b) | ||
|  | { | ||
|  | 	return (a & (1 << b)) >> b; | ||
|  | } | ||
|  | 
 | ||
|  | unsigned int duIntToCol(int i, int a) | ||
|  | { | ||
|  | 	int	r = bit(i, 1) + bit(i, 3) * 2 + 1; | ||
|  | 	int	g = bit(i, 2) + bit(i, 4) * 2 + 1; | ||
|  | 	int	b = bit(i, 0) + bit(i, 5) * 2 + 1; | ||
|  | 	return duRGBA(r*63,g*63,b*63,a); | ||
|  | } | ||
|  | 
 | ||
|  | void duIntToCol(int i, float* col) | ||
|  | { | ||
|  | 	int	r = bit(i, 0) + bit(i, 3) * 2 + 1; | ||
|  | 	int	g = bit(i, 1) + bit(i, 4) * 2 + 1; | ||
|  | 	int	b = bit(i, 2) + bit(i, 5) * 2 + 1; | ||
|  | 	col[0] = 1 - r*63.0f/255.0f; | ||
|  | 	col[1] = 1 - g*63.0f/255.0f; | ||
|  | 	col[2] = 1 - b*63.0f/255.0f; | ||
|  | } | ||
|  | 
 | ||
|  | void duCalcBoxColors(unsigned int* colors, unsigned int colTop, unsigned int colSide) | ||
|  | { | ||
|  | 	if (!colors) return; | ||
|  | 	 | ||
|  | 	colors[0] = duMultCol(colTop, 250); | ||
|  | 	colors[1] = duMultCol(colSide, 140); | ||
|  | 	colors[2] = duMultCol(colSide, 165); | ||
|  | 	colors[3] = duMultCol(colSide, 217); | ||
|  | 	colors[4] = duMultCol(colSide, 165); | ||
|  | 	colors[5] = duMultCol(colSide, 217); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 							 float maxx, float maxy, float maxz, unsigned int col, const float lineWidth) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_LINES, lineWidth); | ||
|  | 	duAppendCylinderWire(dd, minx,miny,minz, maxx,maxy,maxz, col); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 						float maxx, float maxy, float maxz, unsigned int col, const float lineWidth) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_LINES, lineWidth); | ||
|  | 	duAppendBoxWire(dd, minx,miny,minz, maxx,maxy,maxz, col); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0, | ||
|  | 					const float x1, const float y1, const float z1, const float h, | ||
|  | 					const float as0, const float as1, unsigned int col, const float lineWidth) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_LINES, lineWidth); | ||
|  | 	duAppendArc(dd, x0,y0,z0, x1,y1,z1, h, as0, as1, col); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0, | ||
|  | 					  const float x1, const float y1, const float z1, | ||
|  | 					  const float as0, const float as1, unsigned int col, const float lineWidth) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_LINES, lineWidth); | ||
|  | 	duAppendArrow(dd, x0,y0,z0, x1,y1,z1, as0, as1, col); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawCircle(struct duDebugDraw* dd, const float x, const float y, const float z, | ||
|  | 					   const float r, unsigned int col, const float lineWidth) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_LINES, lineWidth); | ||
|  | 	duAppendCircle(dd, x,y,z, r, col); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawCross(struct duDebugDraw* dd, const float x, const float y, const float z, | ||
|  | 					  const float size, unsigned int col, const float lineWidth) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_LINES, lineWidth); | ||
|  | 	duAppendCross(dd, x,y,z, size, col); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawBox(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 					float maxx, float maxy, float maxz, const unsigned int* fcol) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_QUADS); | ||
|  | 	duAppendBox(dd, minx,miny,minz, maxx,maxy,maxz, fcol); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawCylinder(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 						 float maxx, float maxy, float maxz, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	dd->begin(DU_DRAW_TRIS); | ||
|  | 	duAppendCylinder(dd, minx,miny,minz, maxx,maxy,maxz, col); | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 
 | ||
|  | void duDebugDrawGridXZ(struct duDebugDraw* dd, const float ox, const float oy, const float oz, | ||
|  | 					   const int w, const int h, const float size, | ||
|  | 					   const unsigned int col, const float lineWidth) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 
 | ||
|  | 	dd->begin(DU_DRAW_LINES, lineWidth); | ||
|  | 	for (int i = 0; i <= h; ++i) | ||
|  | 	{ | ||
|  | 		dd->vertex(ox,oy,oz+i*size, col); | ||
|  | 		dd->vertex(ox+w*size,oy,oz+i*size, col); | ||
|  | 	} | ||
|  | 	for (int i = 0; i <= w; ++i) | ||
|  | 	{ | ||
|  | 		dd->vertex(ox+i*size,oy,oz, col); | ||
|  | 		dd->vertex(ox+i*size,oy,oz+h*size, col); | ||
|  | 	} | ||
|  | 	dd->end(); | ||
|  | } | ||
|  | 		  | ||
|  | 
 | ||
|  | void duAppendCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 						  float maxx, float maxy, float maxz, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 
 | ||
|  | 	static const int NUM_SEG = 16; | ||
|  | 	static float dir[NUM_SEG*2]; | ||
|  | 	static bool init = false; | ||
|  | 	if (!init) | ||
|  | 	{ | ||
|  | 		init = true; | ||
|  | 		for (int i = 0; i < NUM_SEG; ++i) | ||
|  | 		{ | ||
|  | 			const float a = (float)i/(float)NUM_SEG*DU_PI*2; | ||
|  | 			dir[i*2] = dtMathCosf(a); | ||
|  | 			dir[i*2+1] = dtMathSinf(a); | ||
|  | 		} | ||
|  | 	} | ||
|  | 	 | ||
|  | 	const float cx = (maxx + minx)/2; | ||
|  | 	const float cz = (maxz + minz)/2; | ||
|  | 	const float rx = (maxx - minx)/2; | ||
|  | 	const float rz = (maxz - minz)/2; | ||
|  | 	 | ||
|  | 	for (int i = 0, j = NUM_SEG-1; i < NUM_SEG; j = i++) | ||
|  | 	{ | ||
|  | 		dd->vertex(cx+dir[j*2+0]*rx, miny, cz+dir[j*2+1]*rz, col); | ||
|  | 		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col); | ||
|  | 		dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col); | ||
|  | 		dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, col); | ||
|  | 	} | ||
|  | 	for (int i = 0; i < NUM_SEG; i += NUM_SEG/4) | ||
|  | 	{ | ||
|  | 		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col); | ||
|  | 		dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, col); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 					 float maxx, float maxy, float maxz, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	// Top
 | ||
|  | 	dd->vertex(minx, miny, minz, col); | ||
|  | 	dd->vertex(maxx, miny, minz, col); | ||
|  | 	dd->vertex(maxx, miny, minz, col); | ||
|  | 	dd->vertex(maxx, miny, maxz, col); | ||
|  | 	dd->vertex(maxx, miny, maxz, col); | ||
|  | 	dd->vertex(minx, miny, maxz, col); | ||
|  | 	dd->vertex(minx, miny, maxz, col); | ||
|  | 	dd->vertex(minx, miny, minz, col); | ||
|  | 	 | ||
|  | 	// bottom
 | ||
|  | 	dd->vertex(minx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, maxy, maxz, col); | ||
|  | 	dd->vertex(maxx, maxy, maxz, col); | ||
|  | 	dd->vertex(minx, maxy, maxz, col); | ||
|  | 	dd->vertex(minx, maxy, maxz, col); | ||
|  | 	dd->vertex(minx, maxy, minz, col); | ||
|  | 	 | ||
|  | 	// Sides
 | ||
|  | 	dd->vertex(minx, miny, minz, col); | ||
|  | 	dd->vertex(minx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, miny, minz, col); | ||
|  | 	dd->vertex(maxx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, miny, maxz, col); | ||
|  | 	dd->vertex(maxx, maxy, maxz, col); | ||
|  | 	dd->vertex(minx, miny, maxz, col); | ||
|  | 	dd->vertex(minx, maxy, maxz, col); | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendBoxPoints(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 					   float maxx, float maxy, float maxz, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	// Top
 | ||
|  | 	dd->vertex(minx, miny, minz, col); | ||
|  | 	dd->vertex(maxx, miny, minz, col); | ||
|  | 	dd->vertex(maxx, miny, minz, col); | ||
|  | 	dd->vertex(maxx, miny, maxz, col); | ||
|  | 	dd->vertex(maxx, miny, maxz, col); | ||
|  | 	dd->vertex(minx, miny, maxz, col); | ||
|  | 	dd->vertex(minx, miny, maxz, col); | ||
|  | 	dd->vertex(minx, miny, minz, col); | ||
|  | 	 | ||
|  | 	// bottom
 | ||
|  | 	dd->vertex(minx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, maxy, minz, col); | ||
|  | 	dd->vertex(maxx, maxy, maxz, col); | ||
|  | 	dd->vertex(maxx, maxy, maxz, col); | ||
|  | 	dd->vertex(minx, maxy, maxz, col); | ||
|  | 	dd->vertex(minx, maxy, maxz, col); | ||
|  | 	dd->vertex(minx, maxy, minz, col); | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendBox(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 				 float maxx, float maxy, float maxz, const unsigned int* fcol) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	const float verts[8*3] = | ||
|  | 	{ | ||
|  | 		minx, miny, minz, | ||
|  | 		maxx, miny, minz, | ||
|  | 		maxx, miny, maxz, | ||
|  | 		minx, miny, maxz, | ||
|  | 		minx, maxy, minz, | ||
|  | 		maxx, maxy, minz, | ||
|  | 		maxx, maxy, maxz, | ||
|  | 		minx, maxy, maxz, | ||
|  | 	}; | ||
|  | 	static const unsigned char inds[6*4] = | ||
|  | 	{ | ||
|  | 		7, 6, 5, 4, | ||
|  | 		0, 1, 2, 3, | ||
|  | 		1, 5, 6, 2, | ||
|  | 		3, 7, 4, 0, | ||
|  | 		2, 6, 7, 3, | ||
|  | 		0, 4, 5, 1, | ||
|  | 	}; | ||
|  | 	 | ||
|  | 	const unsigned char* in = inds; | ||
|  | 	for (int i = 0; i < 6; ++i) | ||
|  | 	{ | ||
|  | 		dd->vertex(&verts[*in*3], fcol[i]); in++; | ||
|  | 		dd->vertex(&verts[*in*3], fcol[i]); in++; | ||
|  | 		dd->vertex(&verts[*in*3], fcol[i]); in++; | ||
|  | 		dd->vertex(&verts[*in*3], fcol[i]); in++; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendCylinder(struct duDebugDraw* dd, float minx, float miny, float minz, | ||
|  | 					  float maxx, float maxy, float maxz, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	 | ||
|  | 	static const int NUM_SEG = 16; | ||
|  | 	static float dir[NUM_SEG*2]; | ||
|  | 	static bool init = false; | ||
|  | 	if (!init) | ||
|  | 	{ | ||
|  | 		init = true; | ||
|  | 		for (int i = 0; i < NUM_SEG; ++i) | ||
|  | 		{ | ||
|  | 			const float a = (float)i/(float)NUM_SEG*DU_PI*2; | ||
|  | 			dir[i*2] = cosf(a); | ||
|  | 			dir[i*2+1] = sinf(a); | ||
|  | 		} | ||
|  | 	} | ||
|  | 	 | ||
|  | 	unsigned int col2 = duMultCol(col, 160); | ||
|  | 	 | ||
|  | 	const float cx = (maxx + minx)/2; | ||
|  | 	const float cz = (maxz + minz)/2; | ||
|  | 	const float rx = (maxx - minx)/2; | ||
|  | 	const float rz = (maxz - minz)/2; | ||
|  | 
 | ||
|  | 	for (int i = 2; i < NUM_SEG; ++i) | ||
|  | 	{ | ||
|  | 		const int a = 0, b = i-1, c = i; | ||
|  | 		dd->vertex(cx+dir[a*2+0]*rx, miny, cz+dir[a*2+1]*rz, col2); | ||
|  | 		dd->vertex(cx+dir[b*2+0]*rx, miny, cz+dir[b*2+1]*rz, col2); | ||
|  | 		dd->vertex(cx+dir[c*2+0]*rx, miny, cz+dir[c*2+1]*rz, col2); | ||
|  | 	} | ||
|  | 	for (int i = 2; i < NUM_SEG; ++i) | ||
|  | 	{ | ||
|  | 		const int a = 0, b = i, c = i-1; | ||
|  | 		dd->vertex(cx+dir[a*2+0]*rx, maxy, cz+dir[a*2+1]*rz, col); | ||
|  | 		dd->vertex(cx+dir[b*2+0]*rx, maxy, cz+dir[b*2+1]*rz, col); | ||
|  | 		dd->vertex(cx+dir[c*2+0]*rx, maxy, cz+dir[c*2+1]*rz, col); | ||
|  | 	} | ||
|  | 	for (int i = 0, j = NUM_SEG-1; i < NUM_SEG; j = i++) | ||
|  | 	{ | ||
|  | 		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col2); | ||
|  | 		dd->vertex(cx+dir[j*2+0]*rx, miny, cz+dir[j*2+1]*rz, col2); | ||
|  | 		dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col); | ||
|  | 
 | ||
|  | 		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col2); | ||
|  | 		dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col); | ||
|  | 		dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, col); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | inline void evalArc(const float x0, const float y0, const float z0, | ||
|  | 					const float dx, const float dy, const float dz, | ||
|  | 					const float h, const float u, float* res) | ||
|  | { | ||
|  | 	res[0] = x0 + dx * u; | ||
|  | 	res[1] = y0 + dy * u + h * (1-(u*2-1)*(u*2-1)); | ||
|  | 	res[2] = z0 + dz * u; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | inline void vcross(float* dest, const float* v1, const float* v2) | ||
|  | { | ||
|  | 	dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; | ||
|  | 	dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; | ||
|  | 	dest[2] = v1[0]*v2[1] - v1[1]*v2[0];  | ||
|  | } | ||
|  | 
 | ||
|  | inline void vnormalize(float* v) | ||
|  | { | ||
|  | 	float d = 1.0f / sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); | ||
|  | 	v[0] *= d; | ||
|  | 	v[1] *= d; | ||
|  | 	v[2] *= d; | ||
|  | } | ||
|  | 
 | ||
|  | inline void vsub(float* dest, const float* v1, const float* v2) | ||
|  | { | ||
|  | 	dest[0] = v1[0]-v2[0]; | ||
|  | 	dest[1] = v1[1]-v2[1]; | ||
|  | 	dest[2] = v1[2]-v2[2]; | ||
|  | } | ||
|  | 
 | ||
|  | inline float vdistSqr(const float* v1, const float* v2) | ||
|  | { | ||
|  | 	const float x = v1[0]-v2[0]; | ||
|  | 	const float y = v1[1]-v2[1]; | ||
|  | 	const float z = v1[2]-v2[2]; | ||
|  | 	return x*x + y*y + z*z; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void appendArrowHead(struct duDebugDraw* dd, const float* p, const float* q, | ||
|  | 					 const float s, unsigned int col) | ||
|  | { | ||
|  | 	const float eps = 0.001f; | ||
|  | 	if (!dd) return; | ||
|  | 	if (vdistSqr(p,q) < eps*eps) return; | ||
|  | 	float ax[3], ay[3] = {0,1,0}, az[3]; | ||
|  | 	vsub(az, q, p); | ||
|  | 	vnormalize(az); | ||
|  | 	vcross(ax, ay, az); | ||
|  | 	vcross(ay, az, ax); | ||
|  | 	vnormalize(ay); | ||
|  | 
 | ||
|  | 	dd->vertex(p, col); | ||
|  | //	dd->vertex(p[0]+az[0]*s+ay[0]*s/2, p[1]+az[1]*s+ay[1]*s/2, p[2]+az[2]*s+ay[2]*s/2, col);
 | ||
|  | 	dd->vertex(p[0]+az[0]*s+ax[0]*s/3, p[1]+az[1]*s+ax[1]*s/3, p[2]+az[2]*s+ax[2]*s/3, col); | ||
|  | 
 | ||
|  | 	dd->vertex(p, col); | ||
|  | //	dd->vertex(p[0]+az[0]*s-ay[0]*s/2, p[1]+az[1]*s-ay[1]*s/2, p[2]+az[2]*s-ay[2]*s/2, col);
 | ||
|  | 	dd->vertex(p[0]+az[0]*s-ax[0]*s/3, p[1]+az[1]*s-ax[1]*s/3, p[2]+az[2]*s-ax[2]*s/3, col); | ||
|  | 	 | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0, | ||
|  | 				 const float x1, const float y1, const float z1, const float h, | ||
|  | 				 const float as0, const float as1, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	static const int NUM_ARC_PTS = 8; | ||
|  | 	static const float PAD = 0.05f; | ||
|  | 	static const float ARC_PTS_SCALE = (1.0f-PAD*2) / (float)NUM_ARC_PTS; | ||
|  | 	const float dx = x1 - x0; | ||
|  | 	const float dy = y1 - y0; | ||
|  | 	const float dz = z1 - z0; | ||
|  | 	const float len = sqrtf(dx*dx + dy*dy + dz*dz); | ||
|  | 	float prev[3]; | ||
|  | 	evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD, prev); | ||
|  | 	for (int i = 1; i <= NUM_ARC_PTS; ++i) | ||
|  | 	{ | ||
|  | 		const float u = PAD + i * ARC_PTS_SCALE; | ||
|  | 		float pt[3]; | ||
|  | 		evalArc(x0,y0,z0, dx,dy,dz, len*h, u, pt); | ||
|  | 		dd->vertex(prev[0],prev[1],prev[2], col); | ||
|  | 		dd->vertex(pt[0],pt[1],pt[2], col); | ||
|  | 		prev[0] = pt[0]; prev[1] = pt[1]; prev[2] = pt[2]; | ||
|  | 	} | ||
|  | 	 | ||
|  | 	// End arrows
 | ||
|  | 	if (as0 > 0.001f) | ||
|  | 	{ | ||
|  | 		float p[3], q[3]; | ||
|  | 		evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD, p); | ||
|  | 		evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD+0.05f, q); | ||
|  | 		appendArrowHead(dd, p, q, as0, col); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (as1 > 0.001f) | ||
|  | 	{ | ||
|  | 		float p[3], q[3]; | ||
|  | 		evalArc(x0,y0,z0, dx,dy,dz, len*h, 1-PAD, p); | ||
|  | 		evalArc(x0,y0,z0, dx,dy,dz, len*h, 1-(PAD+0.05f), q); | ||
|  | 		appendArrowHead(dd, p, q, as1, col); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0, | ||
|  | 				   const float x1, const float y1, const float z1, | ||
|  | 				   const float as0, const float as1, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 
 | ||
|  | 	dd->vertex(x0,y0,z0, col); | ||
|  | 	dd->vertex(x1,y1,z1, col); | ||
|  | 	 | ||
|  | 	// End arrows
 | ||
|  | 	const float p[3] = {x0,y0,z0}, q[3] = {x1,y1,z1}; | ||
|  | 	if (as0 > 0.001f) | ||
|  | 		appendArrowHead(dd, p, q, as0, col); | ||
|  | 	if (as1 > 0.001f) | ||
|  | 		appendArrowHead(dd, q, p, as1, col); | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendCircle(struct duDebugDraw* dd, const float x, const float y, const float z, | ||
|  | 					const float r, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	static const int NUM_SEG = 40; | ||
|  | 	static float dir[40*2]; | ||
|  | 	static bool init = false; | ||
|  | 	if (!init) | ||
|  | 	{ | ||
|  | 		init = true; | ||
|  | 		for (int i = 0; i < NUM_SEG; ++i) | ||
|  | 		{ | ||
|  | 			const float a = (float)i/(float)NUM_SEG*DU_PI*2; | ||
|  | 			dir[i*2] = cosf(a); | ||
|  | 			dir[i*2+1] = sinf(a); | ||
|  | 		} | ||
|  | 	} | ||
|  | 	 | ||
|  | 	for (int i = 0, j = NUM_SEG-1; i < NUM_SEG; j = i++) | ||
|  | 	{ | ||
|  | 		dd->vertex(x+dir[j*2+0]*r, y, z+dir[j*2+1]*r, col); | ||
|  | 		dd->vertex(x+dir[i*2+0]*r, y, z+dir[i*2+1]*r, col); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void duAppendCross(struct duDebugDraw* dd, const float x, const float y, const float z, | ||
|  | 				   const float s, unsigned int col) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	dd->vertex(x-s,y,z, col); | ||
|  | 	dd->vertex(x+s,y,z, col); | ||
|  | 	dd->vertex(x,y-s,z, col); | ||
|  | 	dd->vertex(x,y+s,z, col); | ||
|  | 	dd->vertex(x,y,z-s, col); | ||
|  | 	dd->vertex(x,y,z+s, col); | ||
|  | } | ||
|  | 
 | ||
|  | duDisplayList::duDisplayList(int cap) : | ||
|  | 	m_pos(0), | ||
|  | 	m_color(0), | ||
|  | 	m_size(0), | ||
|  | 	m_cap(0), | ||
|  | 	m_depthMask(true), | ||
|  | 	m_prim(DU_DRAW_LINES), | ||
|  | 	m_primSize(1.0f) | ||
|  | { | ||
|  | 	if (cap < 8) | ||
|  | 		cap = 8; | ||
|  | 	resize(cap); | ||
|  | } | ||
|  | 
 | ||
|  | duDisplayList::~duDisplayList() | ||
|  | { | ||
|  | 	delete [] m_pos; | ||
|  | 	delete [] m_color; | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::resize(int cap) | ||
|  | { | ||
|  | 	float* newPos = new float[cap*3]; | ||
|  | 	if (m_size) | ||
|  | 		memcpy(newPos, m_pos, sizeof(float)*3*m_size); | ||
|  | 	delete [] m_pos; | ||
|  | 	m_pos = newPos; | ||
|  | 
 | ||
|  | 	unsigned int* newColor = new unsigned int[cap]; | ||
|  | 	if (m_size) | ||
|  | 		memcpy(newColor, m_color, sizeof(unsigned int)*m_size); | ||
|  | 	delete [] m_color; | ||
|  | 	m_color = newColor; | ||
|  | 	 | ||
|  | 	m_cap = cap; | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::clear() | ||
|  | { | ||
|  | 	m_size = 0; | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::depthMask(bool state) | ||
|  | { | ||
|  | 	m_depthMask = state; | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::begin(duDebugDrawPrimitives prim, float size) | ||
|  | { | ||
|  | 	clear(); | ||
|  | 	m_prim = prim; | ||
|  | 	m_primSize = size; | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::vertex(const float x, const float y, const float z, unsigned int color) | ||
|  | { | ||
|  | 	if (m_size+1 >= m_cap) | ||
|  | 		resize(m_cap*2); | ||
|  | 	float* p = &m_pos[m_size*3]; | ||
|  | 	p[0] = x; | ||
|  | 	p[1] = y; | ||
|  | 	p[2] = z; | ||
|  | 	m_color[m_size] = color; | ||
|  | 	m_size++; | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::vertex(const float* pos, unsigned int color) | ||
|  | { | ||
|  | 	vertex(pos[0],pos[1],pos[2],color); | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::end() | ||
|  | { | ||
|  | } | ||
|  | 
 | ||
|  | void duDisplayList::draw(struct duDebugDraw* dd) | ||
|  | { | ||
|  | 	if (!dd) return; | ||
|  | 	if (!m_size) return; | ||
|  | 	dd->depthMask(m_depthMask); | ||
|  | 	dd->begin(m_prim, m_primSize); | ||
|  | 	for (int i = 0; i < m_size; ++i) | ||
|  | 		dd->vertex(&m_pos[i*3], m_color[i]); | ||
|  | 	dd->end(); | ||
|  | } |