Fix for Issue 54: Bug when a non-shared vertex is marked for remove

This commit is contained in:
Mikko Mononen 2010-03-18 08:42:45 +00:00
parent 70c17e8212
commit 8291ceace2
6 changed files with 155 additions and 52 deletions

View File

@ -297,7 +297,7 @@ public:
// startRef - (in) ref to the polygon where the start lies.
// startPos[3] - (in) start position of the query.
// endPos[3] - (in) end position of the query.
// t - (out) hit parameter along the segment, 0 if no hit.
// t - (out) hit parameter along the segment, FLT_MAX if no hit.
// hitNormal[3] - (out) normal of the nearest hit.
// filter - (in) path polygon filter.
// path - (out) visited path polygons.

View File

@ -1826,8 +1826,16 @@ int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float*
if (tmax > t)
t = tmax;
// Store visited polygons.
if (n < pathSize)
path[n++] = curRef;
// Ray end is completely inside the polygon.
if (segMax == -1)
{
t = FLT_MAX;
return n;
}
// Follow neighbours.
dtPolyRef nextRef = 0;

View File

@ -483,53 +483,70 @@ static void pushBack(int v, int* arr, int& an)
an++;
}
static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int maxTris)
static int removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int maxTris)
{
const int nvp = mesh.nvp;
// Count number of polygons to remove.
int nrem = 0;
int numRemovedVerts = 0;
int numRemainingEdges = 0;
for (int i = 0; i < mesh.npolys; ++i)
{
unsigned short* p = &mesh.polys[i*nvp*2];
for (int j = 0; j < nvp; ++j)
if (p[j] == rem) { nrem++; break; }
{
if (p[j] == RC_MESH_NULL_IDX) break;
numRemainingEdges++;
if (p[j] == rem)
{
numRemovedVerts++;
numRemainingEdges -= 2;
}
}
}
// There would be too few edges remaining to create a polygon.
// This can happen for example when a tip of a triangle is marked
// as deletion, but there are no other polys that share the vertex.
// In this case, the vertex should not be removed.
if (numRemainingEdges <= 2)
return -1;
int nedges = 0;
rcScopedDelete<int> edges = new int[nrem*nvp*4];
rcScopedDelete<int> edges = new int[numRemovedVerts*nvp*4];
if (!edges)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'edges' (%d).", nrem*nvp*4);
return false;
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'edges' (%d).", numRemovedVerts*nvp*4);
return 0;
}
int nhole = 0;
rcScopedDelete<int> hole = new int[nrem*nvp];
rcScopedDelete<int> hole = new int[numRemovedVerts*nvp];
if (!hole)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hole' (%d).", nrem*nvp);
return false;
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hole' (%d).", numRemovedVerts*nvp);
return 0;
}
int nhreg = 0;
rcScopedDelete<int> hreg = new int[nrem*nvp];
rcScopedDelete<int> hreg = new int[numRemovedVerts*nvp];
if (!hreg)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hreg' (%d).", nrem*nvp);
return false;
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hreg' (%d).", numRemovedVerts*nvp);
return 0;
}
int nharea = 0;
rcScopedDelete<int> harea = new int[nrem*nvp];
rcScopedDelete<int> harea = new int[numRemovedVerts*nvp];
if (!harea)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'harea' (%d).", nrem*nvp);
return false;
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'harea' (%d).", numRemovedVerts*nvp);
return 0;
}
for (int i = 0; i < mesh.npolys; ++i)
@ -588,7 +605,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m
}
if (nedges == 0)
return true;
return 1;
// Start with one vertex, keep appending connected
// segments to the start and end of the hole.
@ -645,7 +662,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tris' (%d).", nhole*3);
return false;
return 0;
}
rcScopedDelete<int> tverts = new int[nhole*4];
@ -653,7 +670,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tverts' (%d).", nhole*4);
return false;
return 0;
}
rcScopedDelete<int> thole = new int[nhole];
@ -661,7 +678,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'thole' (%d).", nhole);
return false;
return 0;
}
// Generate temp vertex array for triangulation.
@ -690,21 +707,21 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Out of memory 'polys' (%d).", (ntris+1)*nvp);
return false;
return 0;
}
rcScopedDelete<unsigned short> pregs = new unsigned short[ntris];
if (!pregs)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pregs' (%d).", ntris);
return false;
return 0;
}
rcScopedDelete<unsigned char> pareas = new unsigned char[ntris];
if (!pregs)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pareas' (%d).", ntris);
return false;
return 0;
}
unsigned short* tmpPoly = &polys[ntris*nvp];
@ -726,7 +743,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m
}
}
if (!npolys)
return true;
return 1;
// Merge polygons.
if (nvp > 3)
@ -790,11 +807,11 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Too many polygons %d (max:%d).", mesh.npolys, maxTris);
return false;
return 0;
}
}
return true;
return 1;
}
@ -1046,16 +1063,27 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh)
{
if (vflags[i])
{
if (!removeVertex(mesh, i, maxTris))
int res = removeVertex(mesh, i, maxTris);
if (!res)
{
// Failed to remove vertex
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Failed to remove edge vertex %d.", i);
return false;
}
// Note: mesh.nverts is already decremented inside removeVertex()!
for (int j = i; j < mesh.nverts; ++j)
vflags[j] = vflags[j+1];
--i;
else if (res == -1)
{
// Vertex should not be removed.
continue;
}
else
{
// Remove vertex
// Note: mesh.nverts is already decremented inside removeVertex()!
for (int j = i; j < mesh.nverts; ++j)
vflags[j] = vflags[j+1];
--i;
}
}
}

View File

@ -16,8 +16,8 @@
8D1107260486CEB800E47090 /* Recast */,
);
breakpoints = (
6B8037A6113D1788005ED67B /* RecastMesh.cpp:504 */,
6B8037B4113D193D005ED67B /* RecastMesh.cpp:532 */,
6B8037A6113D1788005ED67B /* RecastMesh.cpp:521 */,
6B8037B4113D193D005ED67B /* RecastMesh.cpp:549 */,
6B904B781144F2B000A12E63 /* Sample_Debug.cpp:87 */,
6B904B941144F35E00A12E63 /* Sample_Debug.cpp:120 */,
);
@ -310,6 +310,12 @@
6B904C6B1152164400A12E63 /* PBXTextBookmark */ = 6B904C6B1152164400A12E63 /* PBXTextBookmark */;
6B904C6C1152164400A12E63 /* PBXTextBookmark */ = 6B904C6C1152164400A12E63 /* PBXTextBookmark */;
6B904C6D1152164400A12E63 /* PBXTextBookmark */ = 6B904C6D1152164400A12E63 /* PBXTextBookmark */;
6B904C6F115218D800A12E63 /* PBXTextBookmark */ = 6B904C6F115218D800A12E63 /* PBXTextBookmark */;
6B904C70115218D800A12E63 /* PBXTextBookmark */ = 6B904C70115218D800A12E63 /* PBXTextBookmark */;
6B904C71115218D800A12E63 /* PBXTextBookmark */ = 6B904C71115218D800A12E63 /* PBXTextBookmark */;
6B904C72115218D800A12E63 /* PBXTextBookmark */ = 6B904C72115218D800A12E63 /* PBXTextBookmark */;
6B904C7411521CEA00A12E63 /* PBXTextBookmark */ = 6B904C7411521CEA00A12E63 /* PBXTextBookmark */;
6B904C7611521D4400A12E63 /* PBXTextBookmark */ = 6B904C7611521D4400A12E63 /* PBXTextBookmark */;
6B92D9121140F58200E82EC3 = 6B92D9121140F58200E82EC3 /* PBXTextBookmark */;
6B92D91C1140F5F800E82EC3 = 6B92D91C1140F5F800E82EC3 /* PBXTextBookmark */;
6B92D9411140F84100E82EC3 = 6B92D9411140F84100E82EC3 /* PBXTextBookmark */;
@ -522,9 +528,9 @@
};
6B137C870F7FCC1100459200 /* RecastMesh.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {815, 19904}}";
sepNavSelRange = "{14617, 0}";
sepNavVisRange = "{10934, 788}";
sepNavIntBoundsRect = "{{0, 0}, {815, 20224}}";
sepNavSelRange = "{13330, 0}";
sepNavVisRange = "{12592, 895}";
};
};
6B137C880F7FCC1100459200 /* RecastRasterization.cpp */ = {
@ -1072,7 +1078,7 @@
vrLen = 868;
vrLoc = 21829;
};
6B8037A6113D1788005ED67B /* RecastMesh.cpp:504 */ = {
6B8037A6113D1788005ED67B /* RecastMesh.cpp:521 */ = {
isa = PBXFileBreakpoint;
actions = (
);
@ -1084,12 +1090,12 @@
functionName = "checkNullPolys(rcPolyMesh& mesh)";
hitCount = 0;
ignoreCount = 0;
lineNumber = 504;
lineNumber = 521;
location = Recast;
modificationTime = 290591670.511081;
state = 1;
};
6B8037B4113D193D005ED67B /* RecastMesh.cpp:532 */ = {
6B8037B4113D193D005ED67B /* RecastMesh.cpp:549 */ = {
isa = PBXFileBreakpoint;
actions = (
);
@ -1101,7 +1107,7 @@
functionName = "removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int maxTris)";
hitCount = 0;
ignoreCount = 0;
lineNumber = 532;
lineNumber = 549;
location = Recast;
modificationTime = 290591670.511272;
state = 1;
@ -2642,6 +2648,66 @@
vrLen = 1021;
vrLoc = 16495;
};
6B904C6F115218D800A12E63 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */;
name = "NavMeshTesterTool.cpp: 633";
rLen = 0;
rLoc = 17051;
rType = 0;
vrLen = 1021;
vrLoc = 16495;
};
6B904C70115218D800A12E63 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6B137C870F7FCC1100459200 /* RecastMesh.cpp */;
name = "RecastMesh.cpp: 568";
rLen = 0;
rLoc = 15139;
rType = 0;
vrLen = 723;
vrLoc = 10999;
};
6B904C71115218D800A12E63 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */;
name = "NavMeshTesterTool.cpp: 633";
rLen = 0;
rLoc = 17051;
rType = 0;
vrLen = 1021;
vrLoc = 16495;
};
6B904C72115218D800A12E63 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6B137C870F7FCC1100459200 /* RecastMesh.cpp */;
name = "RecastMesh.cpp: 498";
rLen = 0;
rLoc = 13375;
rType = 0;
vrLen = 758;
vrLoc = 12451;
};
6B904C7411521CEA00A12E63 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6B137C870F7FCC1100459200 /* RecastMesh.cpp */;
name = "RecastMesh.cpp: 1072";
rLen = 0;
rLoc = 27474;
rType = 0;
vrLen = 707;
vrLoc = 26829;
};
6B904C7611521D4400A12E63 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6B137C870F7FCC1100459200 /* RecastMesh.cpp */;
name = "RecastMesh.cpp: 512";
rLen = 0;
rLoc = 13330;
rType = 0;
vrLen = 895;
vrLoc = 12592;
};
6B92D9121140F58200E82EC3 /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6B137C830F7FCC1100459200 /* RecastContour.cpp */;
@ -2881,7 +2947,7 @@
6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {831, 15024}}";
sepNavSelRange = "{16816, 0}";
sepNavSelRange = "{17051, 0}";
sepNavVisRange = "{16495, 1021}";
};
};
@ -3041,7 +3107,7 @@
fRef = 6B137C870F7FCC1100459200 /* RecastMesh.cpp */;
name = "RecastMesh.cpp: 568";
rLen = 0;
rLoc = 14617;
rLoc = 15139;
rType = 0;
vrLen = 788;
vrLoc = 10934;
@ -3051,7 +3117,7 @@
fRef = 6B137C870F7FCC1100459200 /* RecastMesh.cpp */;
name = "RecastMesh.cpp: 568";
rLen = 0;
rLoc = 14617;
rLoc = 15139;
rType = 0;
vrLen = 788;
vrLoc = 10934;

View File

@ -281,14 +281,14 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
<integer>52</integer>
<integer>46</integer>
<integer>33</integer>
<integer>21</integer>
<integer>1</integer>
<integer>0</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 429}, {358, 643}}</string>
<string>{{0, 347}, {358, 643}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@ -323,7 +323,7 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A30F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>NavMeshTesterTool.cpp</string>
<string>RecastMesh.cpp</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
@ -331,11 +331,11 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A40F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>NavMeshTesterTool.cpp</string>
<string>RecastMesh.cpp</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>6B904C6D1152164400A12E63</string>
<string>6B904C7611521D4400A12E63</string>
<key>history</key>
<array>
<string>6B8DE70D10B01BBF00DF20FB</string>
@ -372,7 +372,6 @@
<string>6B8036D0113BAF79005ED67B</string>
<string>6B8036F7113BB746005ED67B</string>
<string>6B803729113D1079005ED67B</string>
<string>6BC8BE261140ED5F00555B22</string>
<string>6B92D96A1140FBDA00E82EC3</string>
<string>6B92D97A1140FE6000E82EC3</string>
<string>6B92D97D1140FE6000E82EC3</string>
@ -401,7 +400,8 @@
<string>6B904C591152139200A12E63</string>
<string>6B904C631152164400A12E63</string>
<string>6B904C641152164400A12E63</string>
<string>6B904C651152164400A12E63</string>
<string>6B904C6F115218D800A12E63</string>
<string>6B904C70115218D800A12E63</string>
</array>
<key>prevStack</key>
<array>
@ -487,6 +487,7 @@
<string>6B904C6A1152164400A12E63</string>
<string>6B904C6B1152164400A12E63</string>
<string>6B904C6C1152164400A12E63</string>
<string>6B904C71115218D800A12E63</string>
</array>
</dict>
<key>SplitCount</key>