Fixed mem leaks with layers. Added layer region generation test.
This commit is contained in:
parent
f140c3962d
commit
ce6f2a52fc
@ -32,6 +32,7 @@ void duDebugDrawCompactHeightfieldDistance(struct duDebugDraw* dd, const struct
|
||||
void duDebugDrawLeanHeightfieldSolid(duDebugDraw* dd, const struct rcLeanHeightfield& lhf);
|
||||
|
||||
void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset);
|
||||
void duDebugDrawHeightfieldLayersRegions(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset);
|
||||
|
||||
void duDebugDrawRegionConnections(struct duDebugDraw* dd, const struct rcContourSet& cset, const float alpha = 1.0f);
|
||||
void duDebugDrawRawContours(struct duDebugDraw* dd, const struct rcContourSet& cset, const float alpha = 1.0f);
|
||||
|
@ -329,13 +329,14 @@ void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLay
|
||||
|
||||
const float cs = lset.cs;
|
||||
const float ch = lset.ch;
|
||||
const int w = lset.width;
|
||||
const int h = lset.height;
|
||||
|
||||
for (int i = 0; i < lset.nlayers; ++i)
|
||||
{
|
||||
const rcHeightfieldLayer* layer = &lset.layers[i];
|
||||
|
||||
|
||||
const int w = layer->width;
|
||||
const int h = layer->height;
|
||||
|
||||
unsigned int color = duIntToCol(i+1, 255);
|
||||
|
||||
// Layer bounds
|
||||
@ -415,6 +416,93 @@ void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLay
|
||||
|
||||
}
|
||||
|
||||
void duDebugDrawHeightfieldLayersRegions(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset)
|
||||
{
|
||||
if (!dd) return;
|
||||
|
||||
const float cs = lset.cs;
|
||||
const float ch = lset.ch;
|
||||
|
||||
for (int i = 0; i < lset.nlayers; ++i)
|
||||
{
|
||||
const rcHeightfieldLayer* layer = &lset.layers[i];
|
||||
|
||||
const int w = layer->width;
|
||||
const int h = layer->height;
|
||||
|
||||
unsigned int color = duIntToCol(i+1, 255);
|
||||
|
||||
// Layer bounds
|
||||
float bmin[3], bmax[3];
|
||||
rcVcopy(bmin, lset.bmin);
|
||||
rcVcopy(bmax, lset.bmax);
|
||||
bmin[1] = lset.bmin[1] + (layer->ymin-1)*ch;
|
||||
bmax[1] = lset.bmin[1] + (layer->ymax+1)*ch;
|
||||
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 idx = x+y*w;
|
||||
const int h = (int)layer->heights[idx];
|
||||
if (h == 0xffff) continue;
|
||||
const unsigned char area = layer->regs ? layer->regs[idx]+1 : 1;
|
||||
|
||||
unsigned int col = duLerpCol(color, duIntToCol(area, 255), 128);
|
||||
|
||||
const float fx = lset.bmin[0] + x*cs;
|
||||
const float fy = lset.bmin[1] + (h+1)*ch;
|
||||
const float fz = lset.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
|
||||
unsigned int pcol = duLerpCol(color,duRGBA(255,255,255,255),128);
|
||||
dd->begin(DU_DRAW_LINES, 2.0f);
|
||||
for (int j = 0; j < layer->nportals; ++j)
|
||||
{
|
||||
const rcHeightfieldLayerPortal* portal = &layer->portals[j];
|
||||
if (portal->dir == 0 || portal->dir == 2)
|
||||
{
|
||||
const int ha = (int)layer->heights[portal->pos + portal->smin*w];
|
||||
const int hb = (int)layer->heights[portal->pos + (portal->smax-1)*w];
|
||||
const int xx = (portal->dir == 0) ? portal->pos : portal->pos+1;
|
||||
const float fx = lset.bmin[0] + xx*cs;
|
||||
const float fya = lset.bmin[1] + (ha+4)*ch;
|
||||
const float fyb = lset.bmin[1] + (hb+4)*ch;
|
||||
const float fza = lset.bmin[2] + portal->smin*cs;
|
||||
const float fzb = lset.bmin[2] + portal->smax*cs;
|
||||
dd->vertex(fx, fya, fza, pcol);
|
||||
dd->vertex(fx, fyb, fzb, pcol);
|
||||
}
|
||||
else if (portal->dir == 3 || portal->dir == 1)
|
||||
{
|
||||
const int ha = (int)layer->heights[portal->smin + portal->pos*w];
|
||||
const int hb = (int)layer->heights[(portal->smax-1) + portal->pos*w];
|
||||
const int yy = (portal->dir == 3) ? portal->pos : portal->pos+1;
|
||||
const float fxa = lset.bmin[0] + portal->smin*cs;
|
||||
const float fxb = lset.bmin[0] + portal->smax*cs;
|
||||
const float fya = lset.bmin[1] + (ha+3)*ch;
|
||||
const float fyb = lset.bmin[1] + (hb+3)*ch;
|
||||
const float fz = lset.bmin[2] + yy*cs;
|
||||
dd->vertex(fxa, fya, fz, pcol);
|
||||
dd->vertex(fxb, fyb, fz, pcol);
|
||||
}
|
||||
}
|
||||
dd->end();*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void getContourCenter(const rcContour* cont, const float* orig, float cs, float ch, float* center)
|
||||
{
|
||||
center[0] = 0;
|
||||
|
@ -221,6 +221,38 @@ struct rcLeanHeightfield
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct rcHeightfieldLayerPortal
|
||||
{
|
||||
unsigned short pos; // Position of the portal.
|
||||
unsigned short smin, smax; // Span min/max of the portal.
|
||||
unsigned char dir; // Direction of the portal (same as used by rcGetCon()).
|
||||
};
|
||||
|
||||
struct rcHeightfieldLayer
|
||||
{
|
||||
int width, height; // Width and height of the layer.
|
||||
int nportals; // Number of portals.
|
||||
unsigned short ymin, ymax; // Height min/max range.
|
||||
unsigned short* heights; // Heighfield.
|
||||
unsigned char* areas; // Area types.
|
||||
unsigned char* regs; // Regions.
|
||||
rcHeightfieldLayerPortal* portals; // Portals.
|
||||
};
|
||||
|
||||
struct rcHeightfieldLayerSet
|
||||
{
|
||||
rcHeightfieldLayer* layers; // Pointer to layers.
|
||||
int nlayers; // Number of layers.
|
||||
float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
||||
float cs, ch; // Cell size and height.
|
||||
};
|
||||
|
||||
rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet();
|
||||
void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset);
|
||||
|
||||
|
||||
|
||||
struct rcContour
|
||||
{
|
||||
int* verts; // Vertex coordinates, each vertex contains 4 components.
|
||||
@ -680,6 +712,7 @@ bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf);
|
||||
// Here area means the count of spans in an area.
|
||||
// Params:
|
||||
// chf - (in/out) compact heightfield representing the open space.
|
||||
// borderSize - (in) Non-navigable Border around the heightfield.
|
||||
// minRegionArea - (in) the smallest allowed region area.
|
||||
// maxMergeRegionArea - (in) the largest allowed region area which can be merged.
|
||||
// Returns false if operation ran out of memory.
|
||||
@ -696,12 +729,28 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
// Here area means the count of spans in an area.
|
||||
// Params:
|
||||
// chf - (in/out) compact heightfield representing the open space.
|
||||
// borderSize - (in) Non-navigable Border around the heightfield.
|
||||
// minRegionArea - (in) the smallest allowed regions size.
|
||||
// maxMergeRegionArea - (in) the largest allowed regions size which can be merged.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const int borderSize, const int minRegionArea, const int mergeRegionArea);
|
||||
|
||||
// Builds 2D layer representation of a heighfield.
|
||||
// Params:
|
||||
// chf - (in) compact heightfield representing the open space.
|
||||
// borderSize - (in) Non-navigable Border around the heightfield.
|
||||
// walkableHeight - (in) minimum height where the agent can still walk.
|
||||
// lset - (out) set of 2D heighfield layers.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const int borderSize, const int walkableHeight,
|
||||
rcHeightfieldLayerSet& lset);
|
||||
|
||||
// TODO: move this somewhere else, once the layer meshing is done.
|
||||
bool rcBuildLayerRegions(rcContext* ctx, rcHeightfieldLayer& layer, const int walkableClimb);
|
||||
|
||||
|
||||
// Builds simplified contours from the regions outlines.
|
||||
// Params:
|
||||
// chf - (in) compact heightfield which has regions set.
|
||||
@ -740,40 +789,4 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int
|
||||
|
||||
|
||||
|
||||
// TODO: Put in right place!
|
||||
struct rcHeightfieldLayerPortal
|
||||
{
|
||||
unsigned short pos, smin, smax;
|
||||
unsigned char dir;
|
||||
};
|
||||
|
||||
struct rcHeightfieldLayer
|
||||
{
|
||||
unsigned short ymin, ymax;
|
||||
unsigned short* heights;
|
||||
unsigned char* areas;
|
||||
rcHeightfieldLayerPortal* portals;
|
||||
int nportals;
|
||||
};
|
||||
|
||||
struct rcHeightfieldLayerSet
|
||||
{
|
||||
rcHeightfieldLayer* layers;
|
||||
int nlayers;
|
||||
int width, height;
|
||||
int borderSize;
|
||||
float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
||||
float cs, ch; // Cell size and height.
|
||||
};
|
||||
|
||||
rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet();
|
||||
void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset);
|
||||
|
||||
|
||||
bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const int borderSize, const int walkableHeight,
|
||||
rcHeightfieldLayerSet& lset);
|
||||
|
||||
|
||||
|
||||
#endif // RECAST_H
|
||||
|
@ -105,6 +105,8 @@ void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
|
||||
{
|
||||
rcFree(lset->layers[i].heights);
|
||||
rcFree(lset->layers[i].areas);
|
||||
rcFree(lset->layers[i].regs);
|
||||
rcFree(lset->layers[i].portals);
|
||||
}
|
||||
rcFree(lset->layers);
|
||||
rcFree(lset);
|
||||
|
@ -57,6 +57,14 @@ static void addUnique(unsigned char* a, unsigned char& an, unsigned char v)
|
||||
an++;
|
||||
}
|
||||
|
||||
static void addUniqueLast(unsigned char* a, unsigned char& an, unsigned char v)
|
||||
{
|
||||
const int n = (int)an;
|
||||
if (n > 0 && a[n-1] == v) return;
|
||||
a[an] = v;
|
||||
an++;
|
||||
}
|
||||
|
||||
static bool contains(const unsigned char* a, const unsigned char an, const unsigned char v)
|
||||
{
|
||||
const int n = (int)an;
|
||||
@ -469,9 +477,6 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const int lh = h - borderSize*2;
|
||||
|
||||
lset.nlayers = (int)layerId;
|
||||
lset.width = lw;
|
||||
lset.height = lh;
|
||||
lset.borderSize = borderSize;
|
||||
rcVcopy(lset.bmin, chf.bmin);
|
||||
rcVcopy(lset.bmax, chf.bmax);
|
||||
lset.bmin[0] += borderSize*chf.cs;
|
||||
@ -504,6 +509,10 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
|
||||
// Allocate memory for the current layer.
|
||||
rcHeightfieldLayer* layer = &lset.layers[i];
|
||||
|
||||
layer->width = lw;
|
||||
layer->height = lh;
|
||||
|
||||
layer->heights = (unsigned short*)rcAlloc(sizeof(unsigned short)*lw*lh, RC_ALLOC_PERM);
|
||||
if (!layer->heights)
|
||||
{
|
||||
@ -543,13 +552,18 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (srcReg[i] == 0xff) continue;
|
||||
// Skip unassigned regions.
|
||||
if (srcReg[i] == 0xff)
|
||||
continue;
|
||||
// Skip of does nto belong to current layer.
|
||||
unsigned char lid = regs[srcReg[i]].layerId;
|
||||
if (lid != curId)
|
||||
continue;
|
||||
// Store height and area type.
|
||||
const int idx = x+y*lw;
|
||||
layer->heights[idx] = s.y;
|
||||
layer->areas[idx] = chf.areas[i];
|
||||
|
||||
// Check connection.
|
||||
unsigned char con = 0;
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
@ -673,3 +687,233 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool isConnected(rcHeightfieldLayer& layer, const int ia, const int ib, const int walkableClimb)
|
||||
{
|
||||
if (layer.areas[ib] == RC_NULL_AREA) return false;
|
||||
if (rcAbs((int)layer.heights[ia] - (int)layer.heights[ib]) > walkableClimb) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct rcMonotoneRegion
|
||||
{
|
||||
unsigned char neis[RC_MAX_NEIS];
|
||||
unsigned char nneis;
|
||||
unsigned char regId;
|
||||
};
|
||||
|
||||
static bool canMerge(rcMonotoneRegion* reg, unsigned char newRegId, const rcMonotoneRegion* regs, const int nregs)
|
||||
{
|
||||
int count = 0;
|
||||
const int nnei = (int)reg->nneis;
|
||||
for (int i = 0; i < nnei; ++i)
|
||||
{
|
||||
if (regs[reg->neis[i]].regId == newRegId)
|
||||
count++;
|
||||
}
|
||||
return count == 1;
|
||||
}
|
||||
|
||||
// TODO: move this somewhere else, once the layer meshing is done.
|
||||
bool rcBuildLayerRegions(rcContext* ctx, rcHeightfieldLayer& layer, const int walkableClimb)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
// ctx->startTimer(RC_TIMER_BUILD_LAYERS);
|
||||
|
||||
const int w = layer.width;
|
||||
const int h = layer.height;
|
||||
|
||||
rcAssert(layer.regs == 0);
|
||||
|
||||
layer.regs = (unsigned char*)rcAlloc(sizeof(unsigned char)*w*h, RC_ALLOC_TEMP);
|
||||
if (!layer.regs)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'regs' (%d).", w*h);
|
||||
return false;
|
||||
}
|
||||
memset(layer.regs,0xff,sizeof(unsigned char)*w*h);
|
||||
|
||||
const int nsweeps = w;
|
||||
rcScopedDelete<rcLayerSweepSpan> sweeps = (rcLayerSweepSpan*)rcAlloc(sizeof(rcLayerSweepSpan)*nsweeps, RC_ALLOC_TEMP);
|
||||
if (!sweeps)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'sweeps' (%d).", nsweeps);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Partition walkable area into monotone regions.
|
||||
int prevCount[256];
|
||||
unsigned char regId = 0;
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
memset(prevCount,0,sizeof(int)*regId);
|
||||
unsigned char sweepId = 0;
|
||||
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const int idx = x + y*w;
|
||||
if (layer.areas[idx] == RC_NULL_AREA) continue;
|
||||
|
||||
unsigned char sid = 0xff;
|
||||
|
||||
// -x
|
||||
const int xidx = (x-1)+y*w;
|
||||
if (x > 0 && isConnected(layer, idx, xidx, walkableClimb))
|
||||
{
|
||||
if (layer.regs[xidx] != 0xff)
|
||||
sid = layer.regs[xidx];
|
||||
}
|
||||
|
||||
if (sid == 0xff)
|
||||
{
|
||||
sid = sweepId++;
|
||||
sweeps[sid].nei = 0xff;
|
||||
sweeps[sid].ns = 0;
|
||||
}
|
||||
|
||||
// -y
|
||||
const int yidx = x+(y-1)*w;
|
||||
if (y > 0 && isConnected(layer, idx, yidx, walkableClimb))
|
||||
{
|
||||
const unsigned char nr = layer.regs[yidx];
|
||||
if (nr != 0xff)
|
||||
{
|
||||
// Set neighbour when first valid neighbour is encoutered.
|
||||
if (sweeps[sid].ns == 0)
|
||||
sweeps[sid].nei = nr;
|
||||
|
||||
if (sweeps[sid].nei == nr)
|
||||
{
|
||||
// Update existing neighbour
|
||||
sweeps[sid].ns++;
|
||||
prevCount[nr]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is hit if there is nore than one neighbour.
|
||||
// Invalidate the neighbour.
|
||||
sweeps[sid].nei = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layer.regs[idx] = sid;
|
||||
}
|
||||
|
||||
// Create unique ID.
|
||||
for (int i = 0; i < sweepId; ++i)
|
||||
{
|
||||
// If the neighbour is set and there is only one continuous connection to it,
|
||||
// the sweep will be merged with the previous one, else new region is created.
|
||||
if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == (int)sweeps[i].ns)
|
||||
{
|
||||
sweeps[i].id = sweeps[i].nei;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regId == 255)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Region ID overflow.");
|
||||
return false;
|
||||
}
|
||||
sweeps[i].id = regId++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remap local sweep ids to region ids.
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const int idx = x+y*w;
|
||||
layer.regs[idx] = sweeps[layer.regs[idx]].id;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate and init layer regions.
|
||||
const int nregs = (int)regId;
|
||||
rcScopedDelete<rcMonotoneRegion> regs = (rcMonotoneRegion*)rcAlloc(sizeof(rcMonotoneRegion)*nregs, RC_ALLOC_TEMP);
|
||||
if (!regs)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'regs' (%d).", nregs);
|
||||
return false;
|
||||
}
|
||||
memset(regs, 0, sizeof(rcMonotoneRegion)*nregs);
|
||||
for (int i = 0; i < nregs; ++i)
|
||||
regs[i].regId = 0xff;
|
||||
|
||||
// Find region neighbours.
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const int idx = x+y*w;
|
||||
const unsigned char ri = layer.regs[idx];
|
||||
if (ri == 0xff)
|
||||
continue;
|
||||
|
||||
// Update neighbours
|
||||
const int ymi = x+(y-1)*w;
|
||||
if (y > 0 && isConnected(layer, idx, ymi, walkableClimb))
|
||||
{
|
||||
const unsigned char rai = layer.regs[ymi];
|
||||
if (rai != 0xff && rai != ri)
|
||||
{
|
||||
addUniqueLast(regs[ri].neis, regs[ri].nneis, rai);
|
||||
addUniqueLast(regs[rai].neis, regs[rai].nneis, ri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge regions.
|
||||
static const int MAX_STACK = 32;
|
||||
unsigned char stack[MAX_STACK];
|
||||
int nstack = 0;
|
||||
|
||||
unsigned char newRegId = 0;
|
||||
|
||||
for (int i = 0; i < nregs; ++i)
|
||||
{
|
||||
if (regs[i].regId != 0xff)
|
||||
continue;
|
||||
|
||||
nstack = 0;
|
||||
stack[nstack++] = (unsigned char)i;
|
||||
|
||||
regs[i].regId = newRegId;
|
||||
|
||||
while (nstack)
|
||||
{
|
||||
rcMonotoneRegion& reg = regs[stack[0]];
|
||||
nstack--;
|
||||
for (int j = 0; j < nstack; ++j)
|
||||
stack[j] = stack[j+1];
|
||||
|
||||
for (int j = 0; j < (int)reg.nneis; ++j)
|
||||
{
|
||||
const unsigned char nei = reg.neis[j];
|
||||
rcMonotoneRegion& regn = regs[nei];
|
||||
if (regn.regId != 0xff)
|
||||
continue;
|
||||
if (canMerge(®n, newRegId, regs, nregs))
|
||||
{
|
||||
regn.regId = newRegId;
|
||||
if (nstack < MAX_STACK)
|
||||
stack[nstack++] = nei;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newRegId++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < w*h; ++i)
|
||||
{
|
||||
if (layer.regs[i] != 0xff)
|
||||
layer.regs[i] = regs[layer.regs[i]].regId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Binary file not shown.
@ -665,7 +665,7 @@ void Sample_TileMesh::handleRender()
|
||||
if (m_lset && m_drawMode == DRAWMODE_HEIGHFIELD_LAYERS)
|
||||
{
|
||||
glDepthMask(GL_FALSE);
|
||||
duDebugDrawHeightfieldLayers(&dd, *m_lset);
|
||||
duDebugDrawHeightfieldLayersRegions(&dd, *m_lset);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
@ -1113,6 +1113,11 @@ unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const
|
||||
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build heighfield layers.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_lset->nlayers; ++i)
|
||||
{
|
||||
rcBuildLayerRegions(m_ctx, m_lset->layers[i], m_cfg.walkableClimb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user