From 29db8cde1bf323e6f828db3b70a754a3025e9076 Mon Sep 17 00:00:00 2001 From: Mikko Mononen Date: Sun, 19 Jan 2014 17:49:40 +0200 Subject: [PATCH] Fix for detail mesh corner cases - fix case where thing long poly center may not be on the region --- Recast/Source/RecastMeshDetail.cpp | 115 +++++++++++++---------------- 1 file changed, 53 insertions(+), 62 deletions(-) diff --git a/Recast/Source/RecastMeshDetail.cpp b/Recast/Source/RecastMeshDetail.cpp index 3b94663..69ed147 100644 --- a/Recast/Source/RecastMeshDetail.cpp +++ b/Recast/Source/RecastMeshDetail.cpp @@ -751,64 +751,55 @@ static void getHeightData(const rcCompactHeightfield& chf, // since border size offset is already removed from the polymesh vertices. stack.resize(0); - - static const int offset[9*2] = - { - 0,0, -1,0, 0,1, 1,0, 0,-1, -1,-1, -1,1, 1,1, 1,-1 - }; - - // find the center of the polygon - 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; - - // find a span with the right region around this point - // No need to check for connectivity because the region ensures it - for (int dir = 0; dir < 9; ++dir) - { - int ax = pcx + offset[dir*2+0]; - int az = pcz + offset[dir*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]; - if (s.reg == region) - { - stack.push(ax); - stack.push(az); - stack.push(i); - break; - } - } - if (stack.size() > 0) - break; - } - - // Floodfill the heightfield to get 2D height data, - // starting at center location found above as seed. - memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height); - // Mark start locations. - for (int i = 0; i < stack.size(); i += 3) + // Copy the height from the same region, and mark region borders + // as seed points to fill the rest. + for (int hy = 0; hy < hp.height; hy++) { - 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; - } + int y = hp.ymin + hy + bs; + for (int hx = 0; hx < hp.width; hx++) + { + int x = hp.xmin + hx + bs; + const rcCompactCell& c = chf.cells[x+y*chf.width]; + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + const rcCompactSpan& s = chf.spans[i]; + if (s.reg == region) + { + // Store height + hp.data[hx + hy*hp.width] = s.y; + + // If any of the neighbours is not in same region, + // add the current location as flood fill start + bool border = false; + for (int dir = 0; dir < 4; ++dir) + { + if (rcGetCon(s, dir) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(dir); + const int ay = y + rcGetDirOffsetY(dir); + const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir); + const rcCompactSpan& as = chf.spans[ai]; + if (as.reg != region) + { + border = true; + break; + } + } + } + if (border) + { + stack.push(x); + stack.push(y); + stack.push(i); + } + break; + } + } + } + } + static const int RETRACT_SIZE = 256; int head = 0; @@ -834,19 +825,19 @@ static void getHeightData(const rcCompactHeightfield& chf, const int ax = cx + rcGetDirOffsetX(dir); const int ay = cy + rcGetDirOffsetY(dir); + const int hx = ax - hp.xmin - bs; + const int hy = ay - hp.ymin - bs; - if (ax < hp.xmin || ax >= (hp.xmin+hp.width) || - ay < hp.ymin || ay >= (hp.ymin+hp.height)) + if (hx < 0 || hx >= hp.width || hy < 0 || hy >= hp.height) continue; - if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != RC_UNSET_HEIGHT) + if (hp.data[hx + hy*hp.width] != RC_UNSET_HEIGHT) continue; - const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir); - + const int ai = (int)chf.cells[ax + ay*chf.width].index + rcGetCon(cs, dir); const rcCompactSpan& as = chf.spans[ai]; - int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width; - hp.data[idx] = as.y; + + hp.data[hx + hy*hp.width] = as.y; stack.push(ax); stack.push(ay);