12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064 |
- //
- // 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 <math.h>
- #include "DebugDraw.h"
- #include "RecastDebugDraw.h"
- #include "Recast.h"
- void duDebugDrawTriMesh(duDebugDraw* dd, const float* verts, int /*nverts*/,
- const int* tris, const float* normals, int ntris,
- const unsigned char* flags, const float texScale)
- {
- if (!dd) return;
- if (!verts) return;
- if (!tris) return;
- if (!normals) return;
- float uva[2];
- float uvb[2];
- float uvc[2];
- const unsigned int unwalkable = duRGBA(192,128,0,255);
- dd->texture(true);
- dd->begin(DU_DRAW_TRIS);
- for (int i = 0; i < ntris*3; i += 3)
- {
- const float* norm = &normals[i];
- unsigned int color;
- unsigned char a = (unsigned char)(220*(2+norm[0]+norm[1])/4);
- if (flags && !flags[i/3])
- color = duLerpCol(duRGBA(a,a,a,255), unwalkable, 64);
- else
- color = duRGBA(a,a,a,255);
- const float* va = &verts[tris[i+0]*3];
- const float* vb = &verts[tris[i+1]*3];
- const float* vc = &verts[tris[i+2]*3];
-
- int ax = 0, ay = 0;
- if (rcAbs(norm[1]) > rcAbs(norm[ax]))
- ax = 1;
- if (rcAbs(norm[2]) > rcAbs(norm[ax]))
- ax = 2;
- ax = (1<<ax)&3; // +1 mod 3
- ay = (1<<ax)&3; // +1 mod 3
- uva[0] = va[ax]*texScale;
- uva[1] = va[ay]*texScale;
- uvb[0] = vb[ax]*texScale;
- uvb[1] = vb[ay]*texScale;
- uvc[0] = vc[ax]*texScale;
- uvc[1] = vc[ay]*texScale;
-
- dd->vertex(va, color, uva);
- dd->vertex(vb, color, uvb);
- dd->vertex(vc, color, uvc);
- }
- dd->end();
- dd->texture(false);
- }
- void duDebugDrawTriMeshSlope(duDebugDraw* dd, const float* verts, int /*nverts*/,
- const int* tris, const float* normals, int ntris,
- const float walkableSlopeAngle, const float texScale)
- {
- if (!dd) return;
- if (!verts) return;
- if (!tris) return;
- if (!normals) return;
-
- const float walkableThr = cosf(walkableSlopeAngle/180.0f*DU_PI);
-
- float uva[2];
- float uvb[2];
- float uvc[2];
-
- dd->texture(true);
- const unsigned int unwalkable = duRGBA(192,128,0,255);
-
- dd->begin(DU_DRAW_TRIS);
- for (int i = 0; i < ntris*3; i += 3)
- {
- const float* norm = &normals[i];
- unsigned int color;
- unsigned char a = (unsigned char)(220*(2+norm[0]+norm[1])/4);
- if (norm[1] < walkableThr)
- color = duLerpCol(duRGBA(a,a,a,255), unwalkable, 64);
- else
- color = duRGBA(a,a,a,255);
-
- const float* va = &verts[tris[i+0]*3];
- const float* vb = &verts[tris[i+1]*3];
- const float* vc = &verts[tris[i+2]*3];
-
- int ax = 0, ay = 0;
- if (rcAbs(norm[1]) > rcAbs(norm[ax]))
- ax = 1;
- if (rcAbs(norm[2]) > rcAbs(norm[ax]))
- ax = 2;
- ax = (1<<ax)&3; // +1 mod 3
- ay = (1<<ax)&3; // +1 mod 3
-
- uva[0] = va[ax]*texScale;
- uva[1] = va[ay]*texScale;
- uvb[0] = vb[ax]*texScale;
- uvb[1] = vb[ay]*texScale;
- uvc[0] = vc[ax]*texScale;
- uvc[1] = vc[ay]*texScale;
-
- dd->vertex(va, color, uva);
- dd->vertex(vb, color, uvb);
- dd->vertex(vc, color, uvc);
- }
- dd->end();
- dd->texture(false);
- }
- void duDebugDrawHeightfieldSolid(duDebugDraw* dd, const rcHeightfield& hf)
- {
- if (!dd) return;
- const float* orig = hf.bmin;
- const float cs = hf.cs;
- const float ch = hf.ch;
-
- const int w = hf.width;
- const int h = hf.height;
-
- unsigned int fcol[6];
- duCalcBoxColors(fcol, duRGBA(255,255,255,255), duRGBA(255,255,255,255));
-
- dd->begin(DU_DRAW_QUADS);
-
- for (int y = 0; y < h; ++y)
- {
- for (int x = 0; x < w; ++x)
- {
- float fx = orig[0] + x*cs;
- float fz = orig[2] + y*cs;
- const rcSpan* s = hf.spans[x + y*w];
- while (s)
- {
- duAppendBox(dd, fx, orig[1]+s->smin*ch, fz, fx+cs, orig[1] + s->smax*ch, fz+cs, fcol);
- s = s->next;
- }
- }
- }
- dd->end();
- }
- void duDebugDrawHeightfieldWalkable(duDebugDraw* dd, const rcHeightfield& hf)
- {
- if (!dd) return;
- const float* orig = hf.bmin;
- const float cs = hf.cs;
- const float ch = hf.ch;
-
- const int w = hf.width;
- const int h = hf.height;
-
- unsigned int fcol[6];
- duCalcBoxColors(fcol, duRGBA(255,255,255,255), duRGBA(217,217,217,255));
- dd->begin(DU_DRAW_QUADS);
-
- for (int y = 0; y < h; ++y)
- {
- for (int x = 0; x < w; ++x)
- {
- float fx = orig[0] + x*cs;
- float fz = orig[2] + y*cs;
- const rcSpan* s = hf.spans[x + y*w];
- while (s)
- {
- if (s->area == RC_WALKABLE_AREA)
- fcol[0] = duRGBA(64,128,160,255);
- else if (s->area == RC_NULL_AREA)
- fcol[0] = duRGBA(64,64,64,255);
- else
- fcol[0] = duMultCol(dd->areaToCol(s->area), 200);
-
- duAppendBox(dd, fx, orig[1]+s->smin*ch, fz, fx+cs, orig[1] + s->smax*ch, fz+cs, fcol);
- s = s->next;
- }
- }
- }
-
- dd->end();
- }
- void duDebugDrawCompactHeightfieldSolid(duDebugDraw* dd, const rcCompactHeightfield& chf)
- {
- if (!dd) return;
- const float cs = chf.cs;
- const float ch = chf.ch;
- dd->begin(DU_DRAW_QUADS);
-
- for (int y = 0; y < chf.height; ++y)
- {
- for (int x = 0; x < chf.width; ++x)
- {
- const float fx = chf.bmin[0] + x*cs;
- const float fz = chf.bmin[2] + y*cs;
- const rcCompactCell& c = chf.cells[x+y*chf.width];
- for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
- {
- const rcCompactSpan& s = chf.spans[i];
- const unsigned char area = chf.areas[i];
- unsigned int color;
- if (area == RC_WALKABLE_AREA)
- color = duRGBA(0,192,255,64);
- else if (area == RC_NULL_AREA)
- color = duRGBA(0,0,0,64);
- else
- color = dd->areaToCol(area);
-
- const float fy = chf.bmin[1] + (s.y+1)*ch;
- dd->vertex(fx, fy, fz, color);
- dd->vertex(fx, fy, fz+cs, color);
- dd->vertex(fx+cs, fy, fz+cs, color);
- dd->vertex(fx+cs, fy, fz, color);
- }
- }
- }
- dd->end();
- }
- void duDebugDrawCompactHeightfieldRegions(duDebugDraw* dd, const rcCompactHeightfield& chf)
- {
- if (!dd) return;
- const float cs = chf.cs;
- const float ch = chf.ch;
- dd->begin(DU_DRAW_QUADS);
- for (int y = 0; y < chf.height; ++y)
- {
- for (int x = 0; x < chf.width; ++x)
- {
- const float fx = chf.bmin[0] + x*cs;
- const float fz = chf.bmin[2] + y*cs;
- const rcCompactCell& c = chf.cells[x+y*chf.width];
-
- for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
- {
- const rcCompactSpan& s = chf.spans[i];
- const float fy = chf.bmin[1] + (s.y)*ch;
- unsigned int color;
- if (s.reg)
- color = duIntToCol(s.reg, 192);
- else
- color = duRGBA(0,0,0,64);
- dd->vertex(fx, fy, fz, color);
- dd->vertex(fx, fy, fz+cs, color);
- dd->vertex(fx+cs, fy, fz+cs, color);
- dd->vertex(fx+cs, fy, fz, color);
- }
- }
- }
-
- dd->end();
- }
- void duDebugDrawCompactHeightfieldDistance(duDebugDraw* dd, const rcCompactHeightfield& chf)
- {
- if (!dd) return;
- if (!chf.dist) return;
-
- const float cs = chf.cs;
- const float ch = chf.ch;
-
- float maxd = chf.maxDistance;
- if (maxd < 1.0f) maxd = 1;
- const float dscale = 255.0f / maxd;
-
- dd->begin(DU_DRAW_QUADS);
-
- for (int y = 0; y < chf.height; ++y)
- {
- for (int x = 0; x < chf.width; ++x)
- {
- const float fx = chf.bmin[0] + x*cs;
- const float fz = chf.bmin[2] + y*cs;
- const rcCompactCell& c = chf.cells[x+y*chf.width];
-
- for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
- {
- const rcCompactSpan& s = chf.spans[i];
- const float fy = chf.bmin[1] + (s.y+1)*ch;
- const unsigned char cd = (unsigned char)(chf.dist[i] * dscale);
- const unsigned int color = duRGBA(cd,cd,cd,255);
- dd->vertex(fx, fy, fz, color);
- dd->vertex(fx, fy, fz+cs, color);
- dd->vertex(fx+cs, fy, fz+cs, color);
- dd->vertex(fx+cs, fy, fz, color);
- }
- }
- }
- dd->end();
- }
- static void drawLayerPortals(duDebugDraw* dd, const rcHeightfieldLayer* layer)
- {
- const float cs = layer->cs;
- const float ch = layer->ch;
- const int w = layer->width;
- const int h = layer->height;
-
- 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 == 255) continue;
-
- for (int dir = 0; dir < 4; ++dir)
- {
- if (layer->cons[idx] & (1<<(dir+4)))
- {
- const int* seg = &segs[dir*4];
- const float ax = layer->bmin[0] + (x+seg[0])*cs;
- const float ay = layer->bmin[1] + (lh+2)*ch;
- const float az = layer->bmin[2] + (y+seg[1])*cs;
- const float bx = layer->bmin[0] + (x+seg[2])*cs;
- const float by = layer->bmin[1] + (lh+2)*ch;
- const float bz = layer->bmin[2] + (y+seg[3])*cs;
- dd->vertex(ax, ay, az, pcol);
- dd->vertex(bx, by, bz, pcol);
- }
- }
- }
- }
- dd->end();
- }
- void duDebugDrawHeightfieldLayer(duDebugDraw* dd, const struct rcHeightfieldLayer& layer, const int idx)
- {
- const float cs = layer.cs;
- const float ch = layer.ch;
- const int w = layer.width;
- const int h = layer.height;
-
- unsigned int color = duIntToCol(idx+1, 255);
-
- // Layer bounds
- float bmin[3], bmax[3];
- bmin[0] = layer.bmin[0] + layer.minx*cs;
- bmin[1] = layer.bmin[1];
- bmin[2] = layer.bmin[2] + layer.miny*cs;
- bmax[0] = layer.bmin[0] + (layer.maxx+1)*cs;
- bmax[1] = layer.bmax[1];
- bmax[2] = layer.bmin[2] + (layer.maxy+1)*cs;
- duDebugDrawBoxWire(dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[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 (h == 0xff) continue;
- const unsigned char area = layer.areas[lidx];
-
- unsigned int col;
- if (area == RC_WALKABLE_AREA)
- col = duLerpCol(color, duRGBA(0,192,255,64), 32);
- else if (area == RC_NULL_AREA)
- col = duLerpCol(color, duRGBA(0,0,0,64), 32);
- else
- col = duLerpCol(color, dd->areaToCol(area), 32);
-
- const float fx = layer.bmin[0] + x*cs;
- const float fy = layer.bmin[1] + (lh+1)*ch;
- const float fz = layer.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();
-
- // Portals
- drawLayerPortals(dd, &layer);
- }
- void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset)
- {
- if (!dd) return;
- for (int i = 0; i < lset.nlayers; ++i)
- duDebugDrawHeightfieldLayer(dd, lset.layers[i], i);
- }
- /*
- void duDebugDrawLayerContours(duDebugDraw* dd, const struct rcLayerContourSet& lcset)
- {
- if (!dd) return;
-
- const float* orig = lcset.bmin;
- const float cs = lcset.cs;
- const float ch = lcset.ch;
-
- 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 rcLayerContour& 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)
- {
- 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 rcLayerContour& 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)
- 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 duDebugDrawLayerPolyMesh(duDebugDraw* dd, const struct rcLayerPolyMesh& lmesh)
- {
- if (!dd) return;
-
- const int nvp = lmesh.nvp;
- const float cs = lmesh.cs;
- const float ch = lmesh.ch;
- const float* orig = lmesh.bmin;
-
- 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];
-
- unsigned int color;
- if (lmesh.areas[i] == RC_WALKABLE_AREA)
- color = duRGBA(0,192,255,64);
- else if (lmesh.areas[i] == RC_NULL_AREA)
- color = duRGBA(0,0,0,64);
- else
- color = duIntToCol(lmesh.areas[i], 255);
-
- unsigned short vi[3];
- for (int j = 2; j < nvp; ++j)
- {
- if (p[j] == RC_MESH_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] == RC_MESH_NULL_IDX) break;
- if (p[nvp+j] & 0x8000) continue;
- const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_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] == RC_MESH_NULL_IDX) break;
- if ((p[nvp+j] & 0x8000) == 0) continue;
- const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_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();
- }
- */
- static void getContourCenter(const rcContour* cont, const float* orig, float cs, float ch, float* center)
- {
- center[0] = 0;
- center[1] = 0;
- center[2] = 0;
- if (!cont->nverts)
- return;
- for (int i = 0; i < cont->nverts; ++i)
- {
- const int* v = &cont->verts[i*4];
- center[0] += (float)v[0];
- center[1] += (float)v[1];
- center[2] += (float)v[2];
- }
- const float s = 1.0f / cont->nverts;
- center[0] *= s * cs;
- center[1] *= s * ch;
- center[2] *= s * cs;
- center[0] += orig[0];
- center[1] += orig[1] + 4*ch;
- center[2] += orig[2];
- }
- static const rcContour* findContourFromSet(const rcContourSet& cset, unsigned short reg)
- {
- for (int i = 0; i < cset.nconts; ++i)
- {
- if (cset.conts[i].reg == reg)
- return &cset.conts[i];
- }
- return 0;
- }
- void duDebugDrawRegionConnections(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
- {
- if (!dd) return;
-
- const float* orig = cset.bmin;
- const float cs = cset.cs;
- const float ch = cset.ch;
-
- // Draw centers
- float pos[3], pos2[3];
- unsigned int color = duRGBA(0,0,0,196);
- dd->begin(DU_DRAW_LINES, 2.0f);
- for (int i = 0; i < cset.nconts; ++i)
- {
- const rcContour* cont = &cset.conts[i];
- getContourCenter(cont, orig, cs, ch, pos);
- for (int j = 0; j < cont->nverts; ++j)
- {
- const int* v = &cont->verts[j*4];
- if (v[3] == 0 || (unsigned short)v[3] < cont->reg) continue;
- const rcContour* cont2 = findContourFromSet(cset, (unsigned short)v[3]);
- if (cont2)
- {
- getContourCenter(cont2, orig, cs, ch, pos2);
- duAppendArc(dd, pos[0],pos[1],pos[2], pos2[0],pos2[1],pos2[2], 0.25f, 0.6f, 0.6f, color);
- }
- }
- }
-
- dd->end();
- unsigned char a = (unsigned char)(alpha * 255.0f);
- dd->begin(DU_DRAW_POINTS, 7.0f);
- for (int i = 0; i < cset.nconts; ++i)
- {
- const rcContour* cont = &cset.conts[i];
- unsigned int col = duDarkenCol(duIntToCol(cont->reg,a));
- getContourCenter(cont, orig, cs, ch, pos);
- dd->vertex(pos, col);
- }
- dd->end();
- }
- void duDebugDrawRawContours(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
- {
- if (!dd) return;
- const float* orig = cset.bmin;
- const float cs = cset.cs;
- const float ch = cset.ch;
-
- const unsigned char a = (unsigned char)(alpha*255.0f);
-
- dd->begin(DU_DRAW_LINES, 2.0f);
-
- for (int i = 0; i < cset.nconts; ++i)
- {
- const rcContour& c = cset.conts[i];
- unsigned int color = duIntToCol(c.reg, a);
- for (int j = 0; j < c.nrverts; ++j)
- {
- const int* v = &c.rverts[j*4];
- float fx = orig[0] + v[0]*cs;
- float fy = orig[1] + (v[1]+1+(i&1))*ch;
- float fz = orig[2] + v[2]*cs;
- dd->vertex(fx,fy,fz,color);
- if (j > 0)
- dd->vertex(fx,fy,fz,color);
- }
- // Loop last segment.
- const int* v = &c.rverts[0];
- float fx = orig[0] + v[0]*cs;
- float fy = orig[1] + (v[1]+1+(i&1))*ch;
- float fz = orig[2] + v[2]*cs;
- dd->vertex(fx,fy,fz,color);
- }
- dd->end();
- dd->begin(DU_DRAW_POINTS, 2.0f);
- for (int i = 0; i < cset.nconts; ++i)
- {
- const rcContour& c = cset.conts[i];
- unsigned int color = duDarkenCol(duIntToCol(c.reg, a));
-
- for (int j = 0; j < c.nrverts; ++j)
- {
- const int* v = &c.rverts[j*4];
- float off = 0;
- unsigned int colv = color;
- if (v[3] & RC_BORDER_VERTEX)
- {
- colv = duRGBA(255,255,255,a);
- off = ch*2;
- }
-
- float fx = orig[0] + v[0]*cs;
- float fy = orig[1] + (v[1]+1+(i&1))*ch + off;
- float fz = orig[2] + v[2]*cs;
- dd->vertex(fx,fy,fz, colv);
- }
- }
- dd->end();
- }
- void duDebugDrawContours(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
- {
- if (!dd) return;
- const float* orig = cset.bmin;
- const float cs = cset.cs;
- const float ch = cset.ch;
-
- const unsigned char a = (unsigned char)(alpha*255.0f);
-
- dd->begin(DU_DRAW_LINES, 2.5f);
-
- for (int i = 0; i < cset.nconts; ++i)
- {
- const rcContour& c = cset.conts[i];
- if (!c.nverts)
- continue;
- const unsigned int color = duIntToCol(c.reg, a);
- const unsigned int bcolor = duLerpCol(color,duRGBA(255,255,255,a),128);
- for (int j = 0, k = c.nverts-1; j < c.nverts; k=j++)
- {
- const int* va = &c.verts[k*4];
- const int* vb = &c.verts[j*4];
- unsigned int col = (va[3] & RC_AREA_BORDER) ? bcolor : color;
- float fx,fy,fz;
- fx = orig[0] + va[0]*cs;
- fy = orig[1] + (va[1]+1+(i&1))*ch;
- fz = orig[2] + va[2]*cs;
- dd->vertex(fx,fy,fz, col);
- fx = orig[0] + vb[0]*cs;
- fy = orig[1] + (vb[1]+1+(i&1))*ch;
- fz = orig[2] + vb[2]*cs;
- dd->vertex(fx,fy,fz, col);
- }
- }
- dd->end();
- dd->begin(DU_DRAW_POINTS, 3.0f);
-
- for (int i = 0; i < cset.nconts; ++i)
- {
- const rcContour& c = cset.conts[i];
- unsigned int color = duDarkenCol(duIntToCol(c.reg, a));
- for (int j = 0; j < c.nverts; ++j)
- {
- const int* v = &c.verts[j*4];
- float off = 0;
- unsigned int colv = color;
- if (v[3] & RC_BORDER_VERTEX)
- {
- colv = duRGBA(255,255,255,a);
- off = ch*2;
- }
- float fx = orig[0] + v[0]*cs;
- float fy = orig[1] + (v[1]+1+(i&1))*ch + off;
- float fz = orig[2] + v[2]*cs;
- dd->vertex(fx,fy,fz, colv);
- }
- }
- dd->end();
- }
- void duDebugDrawPolyMesh(duDebugDraw* dd, const struct rcPolyMesh& mesh)
- {
- if (!dd) return;
- const int nvp = mesh.nvp;
- const float cs = mesh.cs;
- const float ch = mesh.ch;
- const float* orig = mesh.bmin;
-
- dd->begin(DU_DRAW_TRIS);
-
- for (int i = 0; i < mesh.npolys; ++i)
- {
- const unsigned short* p = &mesh.polys[i*nvp*2];
- const unsigned char area = mesh.areas[i];
-
- unsigned int color;
- if (area == RC_WALKABLE_AREA)
- color = duRGBA(0,192,255,64);
- else if (area == RC_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] == RC_MESH_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 = &mesh.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 < mesh.npolys; ++i)
- {
- const unsigned short* p = &mesh.polys[i*nvp*2];
- for (int j = 0; j < nvp; ++j)
- {
- if (p[j] == RC_MESH_NULL_IDX) break;
- if (p[nvp+j] & 0x8000) continue;
- const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1;
- const int vi[2] = {p[j], p[nj]};
-
- for (int k = 0; k < 2; ++k)
- {
- const unsigned short* v = &mesh.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 < mesh.npolys; ++i)
- {
- const unsigned short* p = &mesh.polys[i*nvp*2];
- for (int j = 0; j < nvp; ++j)
- {
- if (p[j] == RC_MESH_NULL_IDX) break;
- if ((p[nvp+j] & 0x8000) == 0) continue;
- const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1;
- const int vi[2] = {p[j], p[nj]};
-
- unsigned int col = colb;
- if ((p[nvp+j] & 0xf) != 0xf)
- col = duRGBA(255,255,255,128);
- for (int k = 0; k < 2; ++k)
- {
- const unsigned short* v = &mesh.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 < mesh.nverts; ++i)
- {
- const unsigned short* v = &mesh.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();
- }
- void duDebugDrawPolyMeshDetail(duDebugDraw* dd, const struct rcPolyMeshDetail& dmesh)
- {
- if (!dd) return;
- dd->begin(DU_DRAW_TRIS);
-
- for (int i = 0; i < dmesh.nmeshes; ++i)
- {
- const unsigned int* m = &dmesh.meshes[i*4];
- const unsigned int bverts = m[0];
- const unsigned int btris = m[2];
- const int ntris = (int)m[3];
- const float* verts = &dmesh.verts[bverts*3];
- const unsigned char* tris = &dmesh.tris[btris*4];
- unsigned int color = duIntToCol(i, 192);
- for (int j = 0; j < ntris; ++j)
- {
- dd->vertex(&verts[tris[j*4+0]*3], color);
- dd->vertex(&verts[tris[j*4+1]*3], color);
- dd->vertex(&verts[tris[j*4+2]*3], color);
- }
- }
- dd->end();
- // Internal edges.
- dd->begin(DU_DRAW_LINES, 1.0f);
- const unsigned int coli = duRGBA(0,0,0,64);
- for (int i = 0; i < dmesh.nmeshes; ++i)
- {
- const unsigned int* m = &dmesh.meshes[i*4];
- const unsigned int bverts = m[0];
- const unsigned int btris = m[2];
- const int ntris = (int)m[3];
- const float* verts = &dmesh.verts[bverts*3];
- const unsigned char* tris = &dmesh.tris[btris*4];
-
- for (int j = 0; j < ntris; ++j)
- {
- const unsigned char* t = &tris[j*4];
- for (int k = 0, kp = 2; k < 3; kp=k++)
- {
- unsigned char ef = (t[3] >> (kp*2)) & 0x3;
- if (ef == 0)
- {
- // Internal edge
- if (t[kp] < t[k])
- {
- dd->vertex(&verts[t[kp]*3], coli);
- dd->vertex(&verts[t[k]*3], coli);
- }
- }
- }
- }
- }
- dd->end();
-
- // External edges.
- dd->begin(DU_DRAW_LINES, 2.0f);
- const unsigned int cole = duRGBA(0,0,0,64);
- for (int i = 0; i < dmesh.nmeshes; ++i)
- {
- const unsigned int* m = &dmesh.meshes[i*4];
- const unsigned int bverts = m[0];
- const unsigned int btris = m[2];
- const int ntris = (int)m[3];
- const float* verts = &dmesh.verts[bverts*3];
- const unsigned char* tris = &dmesh.tris[btris*4];
-
- for (int j = 0; j < ntris; ++j)
- {
- const unsigned char* t = &tris[j*4];
- for (int k = 0, kp = 2; k < 3; kp=k++)
- {
- unsigned char ef = (t[3] >> (kp*2)) & 0x3;
- if (ef != 0)
- {
- // Ext edge
- dd->vertex(&verts[t[kp]*3], cole);
- dd->vertex(&verts[t[k]*3], cole);
- }
- }
- }
- }
- dd->end();
-
- dd->begin(DU_DRAW_POINTS, 3.0f);
- const unsigned int colv = duRGBA(0,0,0,64);
- for (int i = 0; i < dmesh.nmeshes; ++i)
- {
- const unsigned int* m = &dmesh.meshes[i*4];
- const unsigned int bverts = m[0];
- const int nverts = (int)m[1];
- const float* verts = &dmesh.verts[bverts*3];
- for (int j = 0; j < nverts; ++j)
- dd->vertex(&verts[j*3], colv);
- }
- dd->end();
- }
|