Removed layer portals, added cons, which stores connectivity and portals. Layer heights is stored as bytes.
This commit is contained in:
parent
9f2390e196
commit
b6a93f063a
@ -385,7 +385,44 @@ static void drawLayerPortals(duDebugDraw* dd, const rcHeightfieldLayer* layer, c
|
|||||||
{
|
{
|
||||||
const float cs = layer->cs;
|
const float cs = layer->cs;
|
||||||
const float ch = layer->ch;
|
const float ch = layer->ch;
|
||||||
const float h = (layer->ymax-layer->ymin+1)*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 h = (int)layer->heights[idx];
|
||||||
|
if (h == 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] + (h+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] + (h+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();
|
||||||
|
|
||||||
|
|
||||||
|
/* const float h = rcMax(layer->bmax[1]-layer->bmin[1], ch);
|
||||||
|
|
||||||
unsigned int pcol = duLerpCol(color,duRGBA(255,255,255,255),64);
|
unsigned int pcol = duLerpCol(color,duRGBA(255,255,255,255),64);
|
||||||
dd->begin(DU_DRAW_LINES, 2.0f);
|
dd->begin(DU_DRAW_LINES, 2.0f);
|
||||||
@ -396,34 +433,32 @@ static void drawLayerPortals(duDebugDraw* dd, const rcHeightfieldLayer* layer, c
|
|||||||
{
|
{
|
||||||
const int xx = portal->dir == 0 ? (int)portal->pos : (int)portal->pos+1;
|
const int xx = portal->dir == 0 ? (int)portal->pos : (int)portal->pos+1;
|
||||||
const float fx = layer->bmin[0] + xx*cs;
|
const float fx = layer->bmin[0] + xx*cs;
|
||||||
const float fya = layer->bmin[1] + (layer->ymin)*ch;
|
const float fy = layer->bmin[1];
|
||||||
const float fyb = layer->bmin[1] + (layer->ymin)*ch;
|
|
||||||
const float fza = layer->bmin[2] + portal->smin*cs;
|
const float fza = layer->bmin[2] + portal->smin*cs;
|
||||||
const float fzb = layer->bmin[2] + portal->smax*cs;
|
const float fzb = layer->bmin[2] + portal->smax*cs;
|
||||||
dd->vertex(fx, fya+h, fza, pcol);
|
dd->vertex(fx, fy+h, fza, pcol);
|
||||||
dd->vertex(fx, fyb+h, fzb, pcol);
|
dd->vertex(fx, fy+h, fzb, pcol);
|
||||||
dd->vertex(fx, fya, fza, pcol);
|
dd->vertex(fx, fy, fza, pcol);
|
||||||
dd->vertex(fx, fya+h, fza, pcol);
|
dd->vertex(fx, fy+h, fza, pcol);
|
||||||
dd->vertex(fx, fyb, fzb, pcol);
|
dd->vertex(fx, fy, fzb, pcol);
|
||||||
dd->vertex(fx, fyb+h, fzb, pcol);
|
dd->vertex(fx, fy+h, fzb, pcol);
|
||||||
}
|
}
|
||||||
else if (portal->dir == 3 || portal->dir == 1)
|
else if (portal->dir == 3 || portal->dir == 1)
|
||||||
{
|
{
|
||||||
const int yy = portal->dir == 3 ? (int)portal->pos : (int)portal->pos+1;
|
const int yy = portal->dir == 3 ? (int)portal->pos : (int)portal->pos+1;
|
||||||
const float fxa = layer->bmin[0] + portal->smin*cs;
|
const float fxa = layer->bmin[0] + portal->smin*cs;
|
||||||
const float fxb = layer->bmin[0] + portal->smax*cs;
|
const float fxb = layer->bmin[0] + portal->smax*cs;
|
||||||
const float fya = layer->bmin[1] + (layer->ymin)*ch;
|
const float fy = layer->bmin[1];
|
||||||
const float fyb = layer->bmin[1] + (layer->ymin)*ch;
|
|
||||||
const float fz = layer->bmin[2] + yy*cs;
|
const float fz = layer->bmin[2] + yy*cs;
|
||||||
dd->vertex(fxa, fya+h, fz, pcol);
|
dd->vertex(fxa, fy+h, fz, pcol);
|
||||||
dd->vertex(fxb, fyb+h, fz, pcol);
|
dd->vertex(fxb, fy+h, fz, pcol);
|
||||||
dd->vertex(fxa, fya, fz, pcol);
|
dd->vertex(fxa, fy, fz, pcol);
|
||||||
dd->vertex(fxa, fya+h, fz, pcol);
|
dd->vertex(fxa, fy+h, fz, pcol);
|
||||||
dd->vertex(fxb, fyb, fz, pcol);
|
dd->vertex(fxb, fy, fz, pcol);
|
||||||
dd->vertex(fxb, fyb+h, fz, pcol);
|
dd->vertex(fxb, fy+h, fz, pcol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dd->end();
|
dd->end();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset)
|
void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset)
|
||||||
@ -445,8 +480,6 @@ void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLay
|
|||||||
float bmin[3], bmax[3];
|
float bmin[3], bmax[3];
|
||||||
rcVcopy(bmin, layer->bmin);
|
rcVcopy(bmin, layer->bmin);
|
||||||
rcVcopy(bmax, layer->bmax);
|
rcVcopy(bmax, layer->bmax);
|
||||||
bmin[1] = layer->bmin[1] + (layer->ymin-1)*ch;
|
|
||||||
bmax[1] = layer->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);
|
duDebugDrawBoxWire(dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], duTransCol(color,128), 2.0f);
|
||||||
|
|
||||||
// Layer height
|
// Layer height
|
||||||
@ -505,8 +538,6 @@ void duDebugDrawHeightfieldLayersRegions(duDebugDraw* dd, const struct rcHeightf
|
|||||||
float bmin[3], bmax[3];
|
float bmin[3], bmax[3];
|
||||||
rcVcopy(bmin, layer->bmin);
|
rcVcopy(bmin, layer->bmin);
|
||||||
rcVcopy(bmax, layer->bmax);
|
rcVcopy(bmax, layer->bmax);
|
||||||
bmin[1] = layer->bmin[1] + (layer->ymin-1)*ch;
|
|
||||||
bmax[1] = layer->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);
|
duDebugDrawBoxWire(dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], duTransCol(color,128), 2.0f);
|
||||||
|
|
||||||
// Layer height
|
// Layer height
|
||||||
|
@ -222,14 +222,6 @@ struct rcLeanHeightfield
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct rcHeightfieldLayerPortal
|
|
||||||
{
|
|
||||||
unsigned char pos; // Position of the portal.
|
|
||||||
unsigned char dir; // Direction of the portal (same as used by rcGetCon()).
|
|
||||||
unsigned char smin, smax; // Span min/max of the portal.
|
|
||||||
unsigned short hmin, hmax; // Span min/max of the portal.
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rcHeightfieldLayer
|
struct rcHeightfieldLayer
|
||||||
{
|
{
|
||||||
float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
||||||
@ -237,11 +229,11 @@ struct rcHeightfieldLayer
|
|||||||
int width, height; // Width and height of the layer.
|
int width, height; // Width and height of the layer.
|
||||||
int nportals; // Number of portals.
|
int nportals; // Number of portals.
|
||||||
unsigned char regCount;
|
unsigned char regCount;
|
||||||
unsigned short ymin, ymax; // Height min/max range.
|
unsigned char maxHeight; // Height min/max range.
|
||||||
unsigned short* heights; // Heighfield.
|
unsigned char* heights; // Heighfield.
|
||||||
unsigned char* areas; // Area types.
|
unsigned char* areas; // Area types.
|
||||||
unsigned char* regs; // Regions.
|
unsigned char* regs; // Regions.
|
||||||
rcHeightfieldLayerPortal* portals; // Portals.
|
unsigned char* cons; // Connections.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rcHeightfieldLayerSet
|
struct rcHeightfieldLayerSet
|
||||||
|
@ -106,7 +106,7 @@ void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
|
|||||||
rcFree(lset->layers[i].heights);
|
rcFree(lset->layers[i].heights);
|
||||||
rcFree(lset->layers[i].areas);
|
rcFree(lset->layers[i].areas);
|
||||||
rcFree(lset->layers[i].regs);
|
rcFree(lset->layers[i].regs);
|
||||||
rcFree(lset->layers[i].portals);
|
rcFree(lset->layers[i].cons);
|
||||||
}
|
}
|
||||||
rcFree(lset->layers);
|
rcFree(lset->layers);
|
||||||
rcFree(lset);
|
rcFree(lset);
|
||||||
|
@ -89,24 +89,6 @@ struct rcLayerSweepSpan
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
rcHeightfieldLayerPortal* allocPortal(rcHeightfieldLayerPortal** portals, int& nportals, int& cportals)
|
|
||||||
{
|
|
||||||
if (nportals+1 >= cportals)
|
|
||||||
{
|
|
||||||
cportals *= 2;
|
|
||||||
rcHeightfieldLayerPortal* np = (rcHeightfieldLayerPortal*)rcAlloc(sizeof(rcHeightfieldLayerPortal)*cportals,RC_ALLOC_PERM);
|
|
||||||
if (!np)
|
|
||||||
return 0;
|
|
||||||
if (nportals > 0)
|
|
||||||
memcpy(np,*portals,sizeof(rcHeightfieldLayerPortal)*nportals);
|
|
||||||
rcFree(*portals);
|
|
||||||
*portals = np;
|
|
||||||
}
|
|
||||||
nportals++;
|
|
||||||
return &(*portals)[nportals-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||||
const int borderSize, const int walkableHeight,
|
const int borderSize, const int walkableHeight,
|
||||||
rcHeightfieldLayerSet& lset)
|
rcHeightfieldLayerSet& lset)
|
||||||
@ -345,19 +327,24 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|||||||
for (int j = 0; j < nneis; ++j)
|
for (int j = 0; j < nneis; ++j)
|
||||||
{
|
{
|
||||||
const unsigned char nei = reg.neis[j];
|
const unsigned char nei = reg.neis[j];
|
||||||
|
rcLayerRegion& regn = regs[nei];
|
||||||
// Skip already visited.
|
// Skip already visited.
|
||||||
if (regs[nei].layerId != 0xff)
|
if (regn.layerId != 0xff)
|
||||||
continue;
|
continue;
|
||||||
// Skip if the neighbour is overlapping root region.
|
// Skip if the neighbour is overlapping root region.
|
||||||
if (contains(root.layers, root.nlayers, nei))
|
if (contains(root.layers, root.nlayers, nei))
|
||||||
continue;
|
continue;
|
||||||
|
// Skip if the height range would become too large.
|
||||||
|
const int ymin = rcMin(root.ymin, regn.ymin);
|
||||||
|
const int ymax = rcMin(root.ymax, regn.ymax);
|
||||||
|
if ((ymax - ymin) >= 255)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (nstack < MAX_STACK)
|
if (nstack < MAX_STACK)
|
||||||
{
|
{
|
||||||
// Deepen
|
// Deepen
|
||||||
stack[nstack++] = (unsigned char)nei;
|
stack[nstack++] = (unsigned char)nei;
|
||||||
|
|
||||||
rcLayerRegion& regn = regs[nei];
|
|
||||||
// Mark layer id
|
// Mark layer id
|
||||||
regn.layerId = layerId;
|
regn.layerId = layerId;
|
||||||
// Merge current layers to root.
|
// Merge current layers to root.
|
||||||
@ -395,6 +382,11 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|||||||
// Skip if teh regions are not close to each other.
|
// Skip if teh regions are not close to each other.
|
||||||
if (!overlapRange(ri.ymin,ri.ymax+mergeHeight, rj.ymin,rj.ymax+mergeHeight))
|
if (!overlapRange(ri.ymin,ri.ymax+mergeHeight, rj.ymin,rj.ymax+mergeHeight))
|
||||||
continue;
|
continue;
|
||||||
|
// Skip if the height range would become too large.
|
||||||
|
const int ymin = rcMin(ri.ymin, rj.ymin);
|
||||||
|
const int ymax = rcMin(ri.ymax, rj.ymax);
|
||||||
|
if ((ymax - ymin) >= 255)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Make sure that there is no overlap when mergin 'ri' and 'rj'.
|
// Make sure that there is no overlap when mergin 'ri' and 'rj'.
|
||||||
bool overlap = false;
|
bool overlap = false;
|
||||||
@ -495,13 +487,6 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|||||||
}
|
}
|
||||||
memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers);
|
memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers);
|
||||||
|
|
||||||
rcScopedDelete<unsigned char> cons = (unsigned char*)rcAlloc(sizeof(unsigned char)*lw*lh, RC_ALLOC_TEMP);
|
|
||||||
if (!cons)
|
|
||||||
{
|
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'con' (%d).", lw*lh);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Store layers.
|
// Store layers.
|
||||||
for (int i = 0; i < lset.nlayers; ++i)
|
for (int i = 0; i < lset.nlayers; ++i)
|
||||||
@ -515,17 +500,14 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|||||||
layer->height = lh;
|
layer->height = lh;
|
||||||
layer->cs = chf.cs;
|
layer->cs = chf.cs;
|
||||||
layer->ch = chf.ch;
|
layer->ch = chf.ch;
|
||||||
// TODO: Should this be local bbox instead?
|
|
||||||
rcVcopy(layer->bmin, bmin);
|
|
||||||
rcVcopy(layer->bmax, bmax);
|
|
||||||
|
|
||||||
layer->heights = (unsigned short*)rcAlloc(sizeof(unsigned short)*lw*lh, RC_ALLOC_PERM);
|
layer->heights = (unsigned char*)rcAlloc(sizeof(unsigned char)*lw*lh, RC_ALLOC_PERM);
|
||||||
if (!layer->heights)
|
if (!layer->heights)
|
||||||
{
|
{
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'heights' (%d).", w*h);
|
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'heights' (%d).", w*h);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memset(layer->heights, 0xff, sizeof(unsigned short)*lw*lh);
|
memset(layer->heights, 0xff, sizeof(unsigned char)*lw*lh);
|
||||||
|
|
||||||
layer->areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*lw*lh, RC_ALLOC_PERM);
|
layer->areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*lw*lh, RC_ALLOC_PERM);
|
||||||
if (!layer->areas)
|
if (!layer->areas)
|
||||||
@ -535,18 +517,31 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|||||||
}
|
}
|
||||||
memset(layer->areas, RC_NULL_AREA, sizeof(unsigned char)*lw*lh);
|
memset(layer->areas, RC_NULL_AREA, sizeof(unsigned char)*lw*lh);
|
||||||
|
|
||||||
memset(cons, 0, sizeof(unsigned char)*lw*lh);
|
layer->cons = (unsigned char*)rcAlloc(sizeof(unsigned char)*lw*lh, RC_ALLOC_PERM);
|
||||||
|
if (!layer->cons)
|
||||||
|
{
|
||||||
|
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'cons' (%d).", w*h);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset(layer->cons, 0, sizeof(unsigned char)*lw*lh);
|
||||||
|
|
||||||
// Find layer height bounds.
|
// Find layer height bounds.
|
||||||
|
int ymin = 0, ymax = 0;
|
||||||
for (int j = 0; j < nregs; ++j)
|
for (int j = 0; j < nregs; ++j)
|
||||||
{
|
{
|
||||||
if (regs[j].start && regs[j].layerId == curId)
|
if (regs[j].start && regs[j].layerId == curId)
|
||||||
{
|
{
|
||||||
layer->ymin = regs[j].ymin;
|
ymin = (int)regs[j].ymin;
|
||||||
layer->ymax = regs[j].ymax;
|
ymax = (int)regs[j].ymax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adjust the bbox to fit the heighfield.
|
||||||
|
rcVcopy(layer->bmin, bmin);
|
||||||
|
rcVcopy(layer->bmax, bmax);
|
||||||
|
layer->bmin[1] = bmin[1] + ymin*chf.ch;
|
||||||
|
layer->bmax[1] = bmin[1] + ymax*chf.ch;
|
||||||
|
|
||||||
// Copy height and area from compact heighfield.
|
// Copy height and area from compact heighfield.
|
||||||
for (int y = 0; y < lh; ++y)
|
for (int y = 0; y < lh; ++y)
|
||||||
{
|
{
|
||||||
@ -567,10 +562,11 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|||||||
continue;
|
continue;
|
||||||
// Store height and area type.
|
// Store height and area type.
|
||||||
const int idx = x+y*lw;
|
const int idx = x+y*lw;
|
||||||
layer->heights[idx] = s.y;
|
layer->heights[idx] = (unsigned char)(s.y - ymin);
|
||||||
layer->areas[idx] = chf.areas[i];
|
layer->areas[idx] = chf.areas[i];
|
||||||
|
|
||||||
// Check connection.
|
// Check connection.
|
||||||
|
unsigned char portal = 0;
|
||||||
unsigned char con = 0;
|
unsigned char con = 0;
|
||||||
for (int dir = 0; dir < 4; ++dir)
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
{
|
{
|
||||||
@ -580,109 +576,21 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|||||||
const int ay = cy + rcGetDirOffsetY(dir);
|
const int ay = cy + rcGetDirOffsetY(dir);
|
||||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||||
unsigned char alid = srcReg[ai] != 0xff ? regs[srcReg[ai]].layerId : 0xff;
|
unsigned char alid = srcReg[ai] != 0xff ? regs[srcReg[ai]].layerId : 0xff;
|
||||||
|
// Portal mask
|
||||||
if (chf.areas[ai] != RC_NULL_AREA && lid != alid)
|
if (chf.areas[ai] != RC_NULL_AREA && lid != alid)
|
||||||
|
portal |= (unsigned char)(1<<dir);
|
||||||
|
// Valid connection mask
|
||||||
|
if (chf.areas[ai] != RC_NULL_AREA && lid == alid)
|
||||||
|
{
|
||||||
|
const int nx = ax - borderSize;
|
||||||
|
const int ny = ay - borderSize;
|
||||||
|
if (nx >= 0 && ny >= 0 && nx < lw && ny < lh)
|
||||||
con |= (unsigned char)(1<<dir);
|
con |= (unsigned char)(1<<dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cons[idx] = con;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create portals
|
layer->cons[idx] = (portal << 4) | con;
|
||||||
int cportals = 6;
|
|
||||||
layer->portals = (rcHeightfieldLayerPortal*)rcAlloc(sizeof(rcHeightfieldLayerPortal)*cportals,RC_ALLOC_PERM);
|
|
||||||
if (!layer->portals)
|
|
||||||
{
|
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'portals' (%d).", cportals);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
layer->nportals = 0;
|
|
||||||
|
|
||||||
// Directions same as rcGetCon()
|
|
||||||
const unsigned char XM = 1<<0; // x-
|
|
||||||
const unsigned char YP = 1<<1; // y+
|
|
||||||
const unsigned char XP = 1<<2; // x+
|
|
||||||
const unsigned char YM = 1<<3; // y-
|
|
||||||
|
|
||||||
// Portals along x-axis
|
|
||||||
for (int y = 0; y < lh; ++y)
|
|
||||||
{
|
|
||||||
const unsigned char dir[2] = {3,1};
|
|
||||||
const unsigned char mask[2] = {YM,YP};
|
|
||||||
int start[2] = { -1, -1};
|
|
||||||
|
|
||||||
for (int x = 0; x < lw+1; ++x)
|
|
||||||
{
|
|
||||||
const int idx = x+y*lw;
|
|
||||||
for (int j = 0; j < 2; ++j)
|
|
||||||
{
|
|
||||||
unsigned char set = x<lw ? (cons[idx] & mask[j]) : 0;
|
|
||||||
if (set)
|
|
||||||
{
|
|
||||||
if (start[j] == -1)
|
|
||||||
start[j] = x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (start[j] != -1)
|
|
||||||
{
|
|
||||||
// Add portal.
|
|
||||||
rcHeightfieldLayerPortal* portal = allocPortal(&layer->portals, layer->nportals, cportals);
|
|
||||||
if (!portal)
|
|
||||||
{
|
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'portals' (%d).", cportals);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
portal->pos = (unsigned char)y/*+off[j]*/;
|
|
||||||
portal->smin = (unsigned char)start[j];
|
|
||||||
portal->smax = (unsigned char)x;
|
|
||||||
portal->dir = dir[j];
|
|
||||||
|
|
||||||
start[j] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Portals along y-axis
|
|
||||||
for (int x = 0; x < lw; ++x)
|
|
||||||
{
|
|
||||||
const unsigned char dir[2] = {0,2};
|
|
||||||
const unsigned char mask[2] = {XM,XP};
|
|
||||||
int start[2] = { -1, -1};
|
|
||||||
|
|
||||||
for (int y = 0; y < lh+1; ++y)
|
|
||||||
{
|
|
||||||
const int idx = x+y*lw;
|
|
||||||
for (int j = 0; j < 2; ++j)
|
|
||||||
{
|
|
||||||
unsigned char set = y<lh ? (cons[idx] & mask[j]) : 0;
|
|
||||||
if (set)
|
|
||||||
{
|
|
||||||
if (start[j] == -1)
|
|
||||||
start[j] = y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (start[j] != -1)
|
|
||||||
{
|
|
||||||
// Add portal.
|
|
||||||
rcHeightfieldLayerPortal* portal = allocPortal(&layer->portals,layer->nportals,cportals);
|
|
||||||
if (!portal)
|
|
||||||
{
|
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'portals' (%d).", cportals);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
portal->pos = (unsigned char)x/*+off[j]*/;
|
|
||||||
portal->smin = (unsigned char)start[j];
|
|
||||||
portal->smax = (unsigned char)y;
|
|
||||||
portal->dir = dir[j];
|
|
||||||
|
|
||||||
start[j] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1005,37 +913,30 @@ static bool appendVertex(rcTempContour& cont, const int x, const int y, const in
|
|||||||
|
|
||||||
|
|
||||||
static unsigned char getNeighbourReg(rcHeightfieldLayer& layer,
|
static unsigned char getNeighbourReg(rcHeightfieldLayer& layer,
|
||||||
const unsigned char* cons,
|
const int ax, const int ay, const int dir)
|
||||||
const int ax, const int ay, const int dir,
|
|
||||||
const int walkableClimb)
|
|
||||||
{
|
{
|
||||||
const int ia = ax+ay*layer.width;
|
const int ia = ax+ay*layer.width;
|
||||||
|
|
||||||
|
const unsigned char con = layer.cons[ia] & 0xf;
|
||||||
|
const unsigned char portal = layer.cons[ia] >> 4;
|
||||||
|
const unsigned char mask = (unsigned char)(1<<dir);
|
||||||
|
|
||||||
|
if ((con & mask) == 0)
|
||||||
|
{
|
||||||
|
// No connection, return portal or hard edge.
|
||||||
|
if (portal & mask)
|
||||||
|
return 0xfe - dir;
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
const int bx = ax + rcGetDirOffsetX(dir);
|
const int bx = ax + rcGetDirOffsetX(dir);
|
||||||
const int by = ay + rcGetDirOffsetY(dir);
|
const int by = ay + rcGetDirOffsetY(dir);
|
||||||
if (bx < 0 || by < 0 || bx >= layer.width || by >= layer.height)
|
|
||||||
{
|
|
||||||
if (cons[ia] & (1<<dir))
|
|
||||||
return 0xfe - dir;
|
|
||||||
return 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int ib = bx+by*layer.width;
|
const int ib = bx+by*layer.width;
|
||||||
|
|
||||||
if (rcAbs((int)layer.heights[ia] - (int)layer.heights[ib]) > walkableClimb)
|
|
||||||
{
|
|
||||||
if (cons[ia] & (1<<dir))
|
|
||||||
return 0xfe - dir;
|
|
||||||
return 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return layer.regs[ib];
|
return layer.regs[ib];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool walkContour(rcHeightfieldLayer& layer,
|
static bool walkContour(rcHeightfieldLayer& layer, int x, int y, rcTempContour& cont)
|
||||||
const unsigned char* cons,
|
|
||||||
int x, int y, const int walkableClimb,
|
|
||||||
rcTempContour& cont)
|
|
||||||
{
|
{
|
||||||
const int w = layer.width;
|
const int w = layer.width;
|
||||||
const int h = layer.height;
|
const int h = layer.height;
|
||||||
@ -1049,7 +950,7 @@ static bool walkContour(rcHeightfieldLayer& layer,
|
|||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
const int dir = (i+3)&3;
|
const int dir = (i+3)&3;
|
||||||
unsigned char rn = getNeighbourReg(layer, cons, x, y, dir, walkableClimb);
|
unsigned char rn = getNeighbourReg(layer, x, y, dir);
|
||||||
if (rn != layer.regs[x+y*w])
|
if (rn != layer.regs[x+y*w])
|
||||||
{
|
{
|
||||||
startDir = dir;
|
startDir = dir;
|
||||||
@ -1065,7 +966,7 @@ static bool walkContour(rcHeightfieldLayer& layer,
|
|||||||
int iter = 0;
|
int iter = 0;
|
||||||
while (iter < maxIter)
|
while (iter < maxIter)
|
||||||
{
|
{
|
||||||
unsigned char rn = getNeighbourReg(layer, cons, x, y, dir, walkableClimb);
|
unsigned char rn = getNeighbourReg(layer, x, y, dir);
|
||||||
|
|
||||||
int nx = x;
|
int nx = x;
|
||||||
int ny = y;
|
int ny = y;
|
||||||
@ -1269,19 +1170,18 @@ static void simplifyContour(rcTempContour& cont, const float maxError)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getCornerHeight(rcHeightfieldLayer& layer, const unsigned char* cons,
|
static int getCornerHeight(rcHeightfieldLayer& layer,
|
||||||
const int x, const int y, const int z, const int walkableClimb,
|
const int x, const int y, const int z,
|
||||||
|
const int walkableClimb,
|
||||||
bool& shouldRemove)
|
bool& shouldRemove)
|
||||||
{
|
{
|
||||||
const int w = layer.width;
|
const int w = layer.width;
|
||||||
const int h = layer.height;
|
const int h = layer.height;
|
||||||
|
|
||||||
// unsigned char ic[4];
|
|
||||||
// unsigned char ia[4];
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
unsigned char ic = 0xff;
|
unsigned char portal = 0xf;
|
||||||
int ih = 0;
|
int height = 0;
|
||||||
|
|
||||||
for (int dz = -1; dz <= 0; ++dz)
|
for (int dz = -1; dz <= 0; ++dz)
|
||||||
{
|
{
|
||||||
@ -1292,25 +1192,29 @@ static int getCornerHeight(rcHeightfieldLayer& layer, const unsigned char* cons,
|
|||||||
if (px >= 0 && pz >= 0 && px < w && pz < h)
|
if (px >= 0 && pz >= 0 && px < w && pz < h)
|
||||||
{
|
{
|
||||||
const int idx = px + pz*w;
|
const int idx = px + pz*w;
|
||||||
const int hh = (int)layer.heights[idx];
|
const int h = (int)layer.heights[idx];
|
||||||
if (rcAbs(hh-y) <= walkableClimb)
|
if (rcAbs(h-y) <= walkableClimb)
|
||||||
{
|
{
|
||||||
ih = rcMax(ih, hh);
|
height = rcMax(height, h);
|
||||||
ic &= cons[idx];
|
portal &= (layer.cons[idx] >> 4);
|
||||||
//ia[n] = layer.areas[idx];
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int portalCount = 0;
|
||||||
|
for (int dir = 0; dir < 4; ++dir)
|
||||||
|
if (portal & (1<<dir))
|
||||||
|
portalCount++;
|
||||||
|
|
||||||
shouldRemove = false;
|
shouldRemove = false;
|
||||||
if (n > 1 && (ic == 1 || ic == 2 || ic == 4 || ic == 8))
|
if (n > 1 && portalCount == 1)
|
||||||
{
|
{
|
||||||
shouldRemove = true;
|
shouldRemove = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ih;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1340,14 +1244,6 @@ bool rcBuildLayerContours(rcContext* ctx,
|
|||||||
}
|
}
|
||||||
memset(lcset.conts, 0, sizeof(rcLayerContour)*lcset.nconts);
|
memset(lcset.conts, 0, sizeof(rcLayerContour)*lcset.nconts);
|
||||||
|
|
||||||
rcScopedDelete<unsigned char> cons = (unsigned char*)rcAlloc(sizeof(unsigned char)*w*h, RC_ALLOC_TEMP);
|
|
||||||
if (!cons)
|
|
||||||
{
|
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildLayerContours: Out of memory 'cons' (%d).", w*h);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memset(cons,0,sizeof(unsigned char)*w*h);
|
|
||||||
|
|
||||||
// Allocate temp buffer for contour tracing.
|
// Allocate temp buffer for contour tracing.
|
||||||
const int maxTempVerts = (w*h*2)*2; // Twice around the layer.
|
const int maxTempVerts = (w*h*2)*2; // Twice around the layer.
|
||||||
rcTempContour temp;
|
rcTempContour temp;
|
||||||
@ -1357,37 +1253,19 @@ bool rcBuildLayerContours(rcContext* ctx,
|
|||||||
temp.cpoly = maxTempVerts;
|
temp.cpoly = maxTempVerts;
|
||||||
|
|
||||||
temp.verts = (unsigned char*)rcAlloc(sizeof(unsigned char)*temp.cverts, RC_ALLOC_TEMP);
|
temp.verts = (unsigned char*)rcAlloc(sizeof(unsigned char)*temp.cverts, RC_ALLOC_TEMP);
|
||||||
if (!cons)
|
if (!temp.verts)
|
||||||
{
|
{
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildLayerContours: Out of memory 'temp.verts' (%d).", temp.cverts);
|
ctx->log(RC_LOG_ERROR, "rcBuildLayerContours: Out of memory 'temp.verts' (%d).", temp.cverts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp.poly = (unsigned short*)rcAlloc(sizeof(unsigned short)*temp.cpoly, RC_ALLOC_TEMP);
|
temp.poly = (unsigned short*)rcAlloc(sizeof(unsigned short)*temp.cpoly, RC_ALLOC_TEMP);
|
||||||
if (!cons)
|
if (!temp.poly)
|
||||||
{
|
{
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildLayerContours: Out of memory 'temp.poly' (%d).", temp.cpoly);
|
ctx->log(RC_LOG_ERROR, "rcBuildLayerContours: Out of memory 'temp.poly' (%d).", temp.cpoly);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paint portals
|
|
||||||
for (int i = 0; i < layer.nportals; ++i)
|
|
||||||
{
|
|
||||||
const rcHeightfieldLayerPortal* portal = &layer.portals[i];
|
|
||||||
if (portal->dir == 0 || portal->dir == 2)
|
|
||||||
{
|
|
||||||
const unsigned char mask = (const unsigned char)(1 << portal->dir);
|
|
||||||
for (int j = (int)portal->smin; j < (int)portal->smax; ++j)
|
|
||||||
cons[(int)portal->pos + j*w] |= mask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const unsigned char mask = (const unsigned char)(1 << portal->dir);
|
|
||||||
for (int j = (int)portal->smin; j < (int)portal->smax; ++j)
|
|
||||||
cons[j + (int)portal->pos*w] |= mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find contours.
|
// Find contours.
|
||||||
for (int y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
@ -1406,7 +1284,7 @@ bool rcBuildLayerContours(rcContext* ctx,
|
|||||||
cont.reg = ri;
|
cont.reg = ri;
|
||||||
cont.area = layer.areas[idx];
|
cont.area = layer.areas[idx];
|
||||||
|
|
||||||
if (!walkContour(layer, cons, x, y, walkableClimb, temp))
|
if (!walkContour(layer, x, y, temp))
|
||||||
{
|
{
|
||||||
ctx->log(RC_LOG_ERROR, "rcBuildLayerContours: Failed to walk contour (nverts=%d cverts=%d).", temp.nverts, temp.cverts);
|
ctx->log(RC_LOG_ERROR, "rcBuildLayerContours: Failed to walk contour (nverts=%d cverts=%d).", temp.nverts, temp.cverts);
|
||||||
return false;
|
return false;
|
||||||
@ -1429,7 +1307,7 @@ bool rcBuildLayerContours(rcContext* ctx,
|
|||||||
{
|
{
|
||||||
bool shouldRemove;
|
bool shouldRemove;
|
||||||
unsigned char* v = &temp.verts[i*4];
|
unsigned char* v = &temp.verts[i*4];
|
||||||
v[1] = getCornerHeight(layer, cons, (int)v[0], (int)v[1], (int)v[2], walkableClimb, shouldRemove);
|
v[1] = getCornerHeight(layer, (int)v[0], (int)v[1], (int)v[2], walkableClimb, shouldRemove);
|
||||||
v[3] = shouldRemove ? 1 : 0;
|
v[3] = shouldRemove ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@ -40,6 +40,7 @@ protected:
|
|||||||
rcPolyMeshDetail* m_dmesh;
|
rcPolyMeshDetail* m_dmesh;
|
||||||
rcConfig m_cfg;
|
rcConfig m_cfg;
|
||||||
|
|
||||||
|
|
||||||
static const int MAX_LAYERS = 128;
|
static const int MAX_LAYERS = 128;
|
||||||
rcHeightfieldLayerSet* m_lset;
|
rcHeightfieldLayerSet* m_lset;
|
||||||
rcLayerContourSet* m_lcsets[MAX_LAYERS];
|
rcLayerContourSet* m_lcsets[MAX_LAYERS];
|
||||||
@ -47,6 +48,7 @@ protected:
|
|||||||
rcLayerPolyMesh* m_lmeshes[MAX_LAYERS];
|
rcLayerPolyMesh* m_lmeshes[MAX_LAYERS];
|
||||||
int m_nlmeshes;
|
int m_nlmeshes;
|
||||||
|
|
||||||
|
|
||||||
enum DrawMode
|
enum DrawMode
|
||||||
{
|
{
|
||||||
DRAWMODE_NAVMESH,
|
DRAWMODE_NAVMESH,
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "ConvexVolumeTool.h"
|
#include "ConvexVolumeTool.h"
|
||||||
#include "CrowdTool.h"
|
#include "CrowdTool.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# define snprintf _snprintf
|
# define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
@ -740,7 +741,7 @@ void Sample_TileMesh::handleRenderOverlay(double* proj, double* model, int* view
|
|||||||
unsigned int color = duIntToCol(i+1, 255);
|
unsigned int color = duIntToCol(i+1, 255);
|
||||||
float pos[3];
|
float pos[3];
|
||||||
rcVcopy(pos, layer->bmin);
|
rcVcopy(pos, layer->bmin);
|
||||||
pos[1] = layer->bmin[1] + ((layer->ymin+layer->ymax)/2)*layer->ch;
|
pos[1] = (layer->bmin[1] + layer->bmax[1])*0.5f;
|
||||||
if (gluProject((GLdouble)pos[0], (GLdouble)pos[1], (GLdouble)pos[2], model, proj, view, &x, &y, &z))
|
if (gluProject((GLdouble)pos[0], (GLdouble)pos[1], (GLdouble)pos[2], model, proj, view, &x, &y, &z))
|
||||||
{
|
{
|
||||||
char text[32];
|
char text[32];
|
||||||
@ -946,6 +947,7 @@ void Sample_TileMesh::buildAllTiles()
|
|||||||
m_ctx->stopTimer(RC_TIMER_TEMP);
|
m_ctx->stopTimer(RC_TIMER_TEMP);
|
||||||
|
|
||||||
m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TEMP)/1000.0f;
|
m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TEMP)/1000.0f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sample_TileMesh::removeAllTiles()
|
void Sample_TileMesh::removeAllTiles()
|
||||||
@ -963,6 +965,7 @@ void Sample_TileMesh::removeAllTiles()
|
|||||||
m_navMesh->removeTile(m_navMesh->getTileRefAt(x,y),0,0);
|
m_navMesh->removeTile(m_navMesh->getTileRefAt(x,y),0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const float* bmin, const float* bmax, int& dataSize)
|
unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const float* bmin, const float* bmax, int& dataSize)
|
||||||
{
|
{
|
||||||
if (!m_geom || !m_geom->getMesh() || !m_geom->getChunkyMesh())
|
if (!m_geom || !m_geom->getMesh() || !m_geom->getChunkyMesh())
|
||||||
@ -1166,13 +1169,18 @@ unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const
|
|||||||
if (!rcBuildLayerContours(m_ctx, m_lset->layers[i],
|
if (!rcBuildLayerContours(m_ctx, m_lset->layers[i],
|
||||||
m_cfg.walkableClimb, m_cfg.maxSimplificationError,
|
m_cfg.walkableClimb, m_cfg.maxSimplificationError,
|
||||||
*m_lcsets[m_nlcsets]))
|
*m_lcsets[m_nlcsets]))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m_lmeshes[m_nlmeshes] = rcAllocLayerPolyMesh();
|
m_lmeshes[m_nlmeshes] = rcAllocLayerPolyMesh();
|
||||||
if (!rcBuildLayerPolyMesh(m_ctx, *m_lcsets[m_nlcsets],
|
if (!rcBuildLayerPolyMesh(m_ctx, *m_lcsets[m_nlcsets],
|
||||||
m_cfg.maxVertsPerPoly,
|
m_cfg.maxVertsPerPoly,
|
||||||
*m_lmeshes[m_nlmeshes]))
|
*m_lmeshes[m_nlmeshes]))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
m_nlcsets++;
|
m_nlcsets++;
|
||||||
m_nlmeshes++;
|
m_nlmeshes++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user