123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612 |
- //
- // 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();
- }
|