This commit is contained in:
axelrodR 2014-02-27 01:32:45 +02:00
commit 0f42ab2122

View File

@ -741,6 +741,145 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
return true;
}
static void getHeightDataSeedsFromVertices(const rcCompactHeightfield& chf,
const unsigned short* poly, const int npoly,
const unsigned short* verts, const int bs,
rcHeightPatch& hp, rcIntArray& stack)
{
// Floodfill the heightfield to get 2D height data,
// starting at vertex locations as seeds.
// Note: Reads to the compact heightfield are offset by border size (bs)
// since border size offset is already removed from the polymesh vertices.
memset(hp.data, 0, sizeof(unsigned short)*hp.width*hp.height);
stack.resize(0);
static const int offset[9*2] =
{
0,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1, -1,0,
};
// Use poly vertices as seed points for the flood fill.
for (int j = 0; j < npoly; ++j)
{
int cx = 0, cz = 0, ci =-1;
int dmin = RC_UNSET_HEIGHT;
for (int k = 0; k < 9; ++k)
{
const int ax = (int)verts[poly[j]*3+0] + offset[k*2+0];
const int ay = (int)verts[poly[j]*3+1];
const int az = (int)verts[poly[j]*3+2] + offset[k*2+1];
if (ax < hp.xmin || ax >= hp.xmin+hp.width ||
az < hp.ymin || az >= hp.ymin+hp.height)
continue;
const rcCompactCell& c = chf.cells[(ax+bs)+(az+bs)*chf.width];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
const rcCompactSpan& s = chf.spans[i];
int d = rcAbs(ay - (int)s.y);
if (d < dmin)
{
cx = ax;
cz = az;
ci = i;
dmin = d;
}
}
}
if (ci != -1)
{
stack.push(cx);
stack.push(cz);
stack.push(ci);
}
}
// Find center of the polygon using flood fill.
int pcx = 0, pcz = 0;
for (int j = 0; j < npoly; ++j)
{
pcx += (int)verts[poly[j]*3+0];
pcz += (int)verts[poly[j]*3+2];
}
pcx /= npoly;
pcz /= npoly;
for (int i = 0; i < stack.size(); i += 3)
{
int cx = stack[i+0];
int cy = stack[i+1];
int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width;
hp.data[idx] = 1;
}
while (stack.size() > 0)
{
int ci = stack.pop();
int cy = stack.pop();
int cx = stack.pop();
// Check if close to center of the polygon.
if (rcAbs(cx-pcx) <= 1 && rcAbs(cy-pcz) <= 1)
{
stack.resize(0);
stack.push(cx);
stack.push(cy);
stack.push(ci);
break;
}
const rcCompactSpan& cs = chf.spans[ci];
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue;
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
if (ax < hp.xmin || ax >= (hp.xmin+hp.width) ||
ay < hp.ymin || ay >= (hp.ymin+hp.height))
continue;
if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != 0)
continue;
const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir);
int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width;
hp.data[idx] = 1;
stack.push(ax);
stack.push(ay);
stack.push(ai);
}
}
memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height);
// Mark start locations.
for (int i = 0; i < stack.size(); i += 3)
{
int cx = stack[i+0];
int cy = stack[i+1];
int ci = stack[i+2];
int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width;
const rcCompactSpan& cs = chf.spans[ci];
hp.data[idx] = cs.y;
// getHeightData seeds are given in coordinates with borders
stack[i+0] += bs;
stack[i+1] += bs;
}
}
static void getHeightData(const rcCompactHeightfield& chf,
const unsigned short* poly, const int npoly,
const unsigned short* verts, const int bs,
@ -752,6 +891,8 @@ static void getHeightData(const rcCompactHeightfield& chf,
stack.resize(0);
memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height);
bool empty = true;
// Copy the height from the same region, and mark region borders
// as seed points to fill the rest.
@ -769,6 +910,7 @@ static void getHeightData(const rcCompactHeightfield& chf,
{
// Store height
hp.data[hx + hy*hp.width] = s.y;
empty = false;
// If any of the neighbours is not in same region,
// add the current location as flood fill start
@ -800,6 +942,10 @@ static void getHeightData(const rcCompactHeightfield& chf,
}
}
// if the polygon does not contian any points from the current region (rare, but happens)
// then use the cells closest to the polygon vertices as seeds to fill the height field
if (empty)
getHeightDataSeedsFromVertices(chf, poly, npoly, verts, bs, hp, stack);
static const int RETRACT_SIZE = 256;
int head = 0;