Removed layer portals, added cons, which stores connectivity and portals. Layer heights is stored as bytes.

This commit is contained in:
Mikko Mononen 2011-03-11 15:12:15 +00:00
parent 9f2390e196
commit b6a93f063a
7 changed files with 156 additions and 245 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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)
con |= (unsigned char)(1<<dir); portal |= (unsigned char)(1<<dir);
} // Valid connection mask
} if (chf.areas[ai] != RC_NULL_AREA && lid == alid)
cons[idx] = con;
}
}
}
// Create portals
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); const int nx = ax - borderSize;
return false; const int ny = ay - borderSize;
if (nx >= 0 && ny >= 0 && nx < lw && ny < lh)
con |= (unsigned char)(1<<dir);
} }
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 layer->cons[idx] = (portal << 4) | con;
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,
bool& shouldRemove) const int walkableClimb,
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;
} }

View File

@ -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,

View File

@ -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++;