diff --git a/Detour/Include/DetourStatNavMesh.h b/Detour/Include/DetourStatNavMesh.h
index 500fca5..281c165 100755
--- a/Detour/Include/DetourStatNavMesh.h
+++ b/Detour/Include/DetourStatNavMesh.h
@@ -64,11 +64,11 @@ public:
dtStatNavMesh();
~dtStatNavMesh();
- // Initializes the path finder with path data.
+ // Initializes the navmesh with data.
// Params:
- // data - (in) Pointer to path data.
- // dataSize - (in) size of the path data.
- // ownsData - (in) Flag indicating if the pathfinder should delete the data.
+ // data - (in) Pointer to navmesh data.
+ // dataSize - (in) size of the navmesh data.
+ // ownsData - (in) Flag indicating if the navmesh should own and delete the data.
bool init(unsigned char* data, int dataSize, bool ownsData);
// Finds the nearest navigation polygon around the center location.
diff --git a/RecastDemo/Bin/Recast.app/Contents/MacOS/Recast b/RecastDemo/Bin/Recast.app/Contents/MacOS/Recast
index 01c0a38..7d19718 100755
Binary files a/RecastDemo/Bin/Recast.app/Contents/MacOS/Recast and b/RecastDemo/Bin/Recast.app/Contents/MacOS/Recast differ
diff --git a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser
index 052167d..f91b9cb 100644
--- a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser
+++ b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.pbxuser
@@ -16,7 +16,7 @@
8D1107260486CEB800E47090 /* Recast */,
);
breakpoints = (
- 6B0249B11003783F00CF7107 /* Sample_TileMesh.cpp:833 */,
+ 6B0249B11003783F00CF7107 /* Sample_TileMesh.cpp:784 */,
6B0249ED10037C0A00CF7107 /* DetourTileNavMesh.cpp:1 */,
6B0249EF10037C0C00CF7107 /* DetourTileNavMesh.cpp:1 */,
6B024AC01004AB3900CF7107 /* DetourTileNavMesh.cpp:1 */,
@@ -610,6 +610,87 @@
6B555F4E100B4C5800247EA3 /* PBXTextBookmark */ = 6B555F4E100B4C5800247EA3 /* PBXTextBookmark */;
6B555F4F100B4C5800247EA3 /* PBXTextBookmark */ = 6B555F4F100B4C5800247EA3 /* PBXTextBookmark */;
6B555F52100B4CE300247EA3 /* PBXTextBookmark */ = 6B555F52100B4CE300247EA3 /* PBXTextBookmark */;
+ 6B555F5C100B53F500247EA3 /* PBXTextBookmark */ = 6B555F5C100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F5D100B53F500247EA3 /* PBXTextBookmark */ = 6B555F5D100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F5E100B53F500247EA3 /* PBXTextBookmark */ = 6B555F5E100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F5F100B53F500247EA3 /* PBXTextBookmark */ = 6B555F5F100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F60100B53F500247EA3 /* PBXTextBookmark */ = 6B555F60100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F61100B53F500247EA3 /* PBXTextBookmark */ = 6B555F61100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F62100B53F500247EA3 /* PBXTextBookmark */ = 6B555F62100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F63100B53F500247EA3 /* PBXTextBookmark */ = 6B555F63100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F64100B53F500247EA3 /* PBXTextBookmark */ = 6B555F64100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F65100B53F500247EA3 /* PBXTextBookmark */ = 6B555F65100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F66100B53F500247EA3 /* PBXTextBookmark */ = 6B555F66100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F67100B53F500247EA3 /* PBXTextBookmark */ = 6B555F67100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F68100B53F500247EA3 /* PBXTextBookmark */ = 6B555F68100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F69100B53F500247EA3 /* PBXTextBookmark */ = 6B555F69100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F6A100B53F500247EA3 /* PBXTextBookmark */ = 6B555F6A100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F6B100B53F500247EA3 /* PBXTextBookmark */ = 6B555F6B100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F6C100B53F500247EA3 /* PBXTextBookmark */ = 6B555F6C100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F6D100B53F500247EA3 /* PBXTextBookmark */ = 6B555F6D100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F6E100B53F500247EA3 /* PBXTextBookmark */ = 6B555F6E100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F6F100B53F500247EA3 /* PBXTextBookmark */ = 6B555F6F100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F70100B53F500247EA3 /* PBXTextBookmark */ = 6B555F70100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F71100B53F500247EA3 /* PBXTextBookmark */ = 6B555F71100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F72100B53F500247EA3 /* PBXTextBookmark */ = 6B555F72100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F73100B53F500247EA3 /* PBXTextBookmark */ = 6B555F73100B53F500247EA3 /* PBXTextBookmark */;
+ 6B555F74100B541500247EA3 /* PBXTextBookmark */ = 6B555F74100B541500247EA3 /* PBXTextBookmark */;
+ 6B555F75100B541900247EA3 /* PBXTextBookmark */ = 6B555F75100B541900247EA3 /* PBXTextBookmark */;
+ 6B555F76100B541900247EA3 /* PBXTextBookmark */ = 6B555F76100B541900247EA3 /* PBXTextBookmark */;
+ 6B555F77100B54CE00247EA3 /* PBXTextBookmark */ = 6B555F77100B54CE00247EA3 /* PBXTextBookmark */;
+ 6B555F78100B54CE00247EA3 /* PBXTextBookmark */ = 6B555F78100B54CE00247EA3 /* PBXTextBookmark */;
+ 6B555F79100B54CE00247EA3 /* PBXTextBookmark */ = 6B555F79100B54CE00247EA3 /* PBXTextBookmark */;
+ 6B555F7A100B54CE00247EA3 /* PBXTextBookmark */ = 6B555F7A100B54CE00247EA3 /* PBXTextBookmark */;
+ 6B555F7B100B54CE00247EA3 /* PBXTextBookmark */ = 6B555F7B100B54CE00247EA3 /* PBXTextBookmark */;
+ 6B555F7C100B54CE00247EA3 /* PBXTextBookmark */ = 6B555F7C100B54CE00247EA3 /* PBXTextBookmark */;
+ 6B555F82100B557700247EA3 /* PBXTextBookmark */ = 6B555F82100B557700247EA3 /* PBXTextBookmark */;
+ 6B555F83100B557700247EA3 /* PBXTextBookmark */ = 6B555F83100B557700247EA3 /* PBXTextBookmark */;
+ 6B555F84100B557700247EA3 /* PBXTextBookmark */ = 6B555F84100B557700247EA3 /* PBXTextBookmark */;
+ 6B555F85100B557700247EA3 /* PBXTextBookmark */ = 6B555F85100B557700247EA3 /* PBXTextBookmark */;
+ 6B555F88100B577A00247EA3 /* PBXTextBookmark */ = 6B555F88100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F89100B577A00247EA3 /* PBXTextBookmark */ = 6B555F89100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F8A100B577A00247EA3 /* PBXTextBookmark */ = 6B555F8A100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F8B100B577A00247EA3 /* PBXTextBookmark */ = 6B555F8B100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F8C100B577A00247EA3 /* PBXTextBookmark */ = 6B555F8C100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F8D100B577A00247EA3 /* PBXTextBookmark */ = 6B555F8D100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F8E100B577A00247EA3 /* PBXTextBookmark */ = 6B555F8E100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F8F100B577A00247EA3 /* PBXTextBookmark */ = 6B555F8F100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F90100B577A00247EA3 /* PBXTextBookmark */ = 6B555F90100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F91100B577A00247EA3 /* PBXTextBookmark */ = 6B555F91100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F92100B577A00247EA3 /* PBXTextBookmark */ = 6B555F92100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F93100B577A00247EA3 /* PBXTextBookmark */ = 6B555F93100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F94100B577A00247EA3 /* PBXTextBookmark */ = 6B555F94100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F95100B577A00247EA3 /* PBXTextBookmark */ = 6B555F95100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F96100B577A00247EA3 /* PBXTextBookmark */ = 6B555F96100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F97100B577A00247EA3 /* PBXTextBookmark */ = 6B555F97100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F98100B577A00247EA3 /* PBXTextBookmark */ = 6B555F98100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F99100B577A00247EA3 /* PBXTextBookmark */ = 6B555F99100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F9A100B577A00247EA3 /* PBXTextBookmark */ = 6B555F9A100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F9B100B577A00247EA3 /* PBXTextBookmark */ = 6B555F9B100B577A00247EA3 /* PBXTextBookmark */;
+ 6B555F9E100B57B500247EA3 /* PBXTextBookmark */ = 6B555F9E100B57B500247EA3 /* PBXTextBookmark */;
+ 6B555F9F100B57B500247EA3 /* PBXTextBookmark */ = 6B555F9F100B57B500247EA3 /* PBXTextBookmark */;
+ 6B555FA0100B57B500247EA3 /* PBXTextBookmark */ = 6B555FA0100B57B500247EA3 /* PBXTextBookmark */;
+ 6B555FA1100B57B500247EA3 /* PBXTextBookmark */ = 6B555FA1100B57B500247EA3 /* PBXTextBookmark */;
+ 6B555FA2100B57CA00247EA3 /* PBXTextBookmark */ = 6B555FA2100B57CA00247EA3 /* PBXTextBookmark */;
+ 6B555FA3100B57CC00247EA3 /* PBXTextBookmark */ = 6B555FA3100B57CC00247EA3 /* PBXTextBookmark */;
+ 6B555FA4100B57CC00247EA3 /* PBXTextBookmark */ = 6B555FA4100B57CC00247EA3 /* PBXTextBookmark */;
+ 6B555FA8100B589200247EA3 /* PBXTextBookmark */ = 6B555FA8100B589200247EA3 /* PBXTextBookmark */;
+ 6B555FA9100B589200247EA3 /* PBXTextBookmark */ = 6B555FA9100B589200247EA3 /* PBXTextBookmark */;
+ 6B555FAA100B589200247EA3 /* PBXTextBookmark */ = 6B555FAA100B589200247EA3 /* PBXTextBookmark */;
+ 6B555FAB100B589200247EA3 /* PBXTextBookmark */ = 6B555FAB100B589200247EA3 /* PBXTextBookmark */;
+ 6B555FAC100B589200247EA3 /* PBXTextBookmark */ = 6B555FAC100B589200247EA3 /* PBXTextBookmark */;
+ 6B555FB0100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB0100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FB1100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB1100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FB2100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB2100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FB3100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB3100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FB4100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB4100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FB5100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB5100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FB6100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB6100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FB7100B595C00247EA3 /* PBXTextBookmark */ = 6B555FB7100B595C00247EA3 /* PBXTextBookmark */;
+ 6B555FBA100B598E00247EA3 /* PBXTextBookmark */ = 6B555FBA100B598E00247EA3 /* PBXTextBookmark */;
+ 6B555FBD100B59B600247EA3 /* PBXTextBookmark */ = 6B555FBD100B59B600247EA3 /* PBXTextBookmark */;
+ 6B555FBF100B5A0000247EA3 /* PBXTextBookmark */ = 6B555FBF100B5A0000247EA3 /* PBXTextBookmark */;
+ 6B555FC0100B5A3300247EA3 /* PBXTextBookmark */ = 6B555FC0100B5A3300247EA3 /* PBXTextBookmark */;
6B7707B90FBD66CF00D21BAE = 6B7707B90FBD66CF00D21BAE /* PBXTextBookmark */;
6B7707F00FBD90F100D21BAE = 6B7707F00FBD90F100D21BAE /* PBXTextBookmark */;
6B7707F70FBD90F100D21BAE = 6B7707F70FBD90F100D21BAE /* PBXTextBookmark */;
@@ -689,7 +770,7 @@
vrLen = 558;
vrLoc = 362;
};
- 6B0249B11003783F00CF7107 /* Sample_TileMesh.cpp:833 */ = {
+ 6B0249B11003783F00CF7107 /* Sample_TileMesh.cpp:784 */ = {
isa = PBXFileBreakpoint;
actions = (
);
@@ -701,7 +782,7 @@
functionName = "BuilderTiledMesh::toolRecalc()";
hitCount = 0;
ignoreCount = 0;
- lineNumber = 833;
+ lineNumber = 784;
location = Recast;
modificationTime = 268741438.169822;
state = 1;
@@ -782,7 +863,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTiledNavMesh.h: 137";
rLen = 0;
- rLoc = 5005;
+ rLoc = 9483;
rType = 0;
vrLen = 1459;
vrLoc = 3572;
@@ -1081,7 +1162,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTiledNavMesh.cpp: 1073";
rLen = 0;
- rLoc = 27719;
+ rLoc = 12201;
rType = 0;
vrLen = 526;
vrLoc = 26309;
@@ -1161,7 +1242,7 @@
fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
name = "DetourStatNavMesh.h: 176";
rLen = 0;
- rLoc = 7183;
+ rLoc = 7185;
rType = 0;
vrLen = 1247;
vrLoc = 59;
@@ -1171,7 +1252,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTileNavMesh.h: 19";
rLen = 0;
- rLoc = 938;
+ rLoc = 937;
rType = 0;
vrLen = 1075;
vrLoc = 784;
@@ -1546,16 +1627,16 @@
};
6B25B6150FFA62BE004F1BC4 /* Sample_StatMesh.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 5568}}";
- sepNavSelRange = "{162, 0}";
- sepNavVisRange = "{0, 498}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 5200}}";
+ sepNavSelRange = "{7561, 0}";
+ sepNavVisRange = "{7958, 728}";
};
};
6B25B6160FFA62BE004F1BC4 /* Sample_StatMeshSimple.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 8588}}";
- sepNavSelRange = "{143, 0}";
- sepNavVisRange = "{0, 513}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 8304}}";
+ sepNavSelRange = "{4247, 49}";
+ sepNavVisRange = "{3933, 719}";
};
};
6B25B6180FFA62BE004F1BC4 /* main.cpp */ = {
@@ -1585,16 +1666,16 @@
};
6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {1223, 14524}}";
- sepNavSelRange = "{1062, 0}";
- sepNavVisRange = "{784, 548}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 14464}}";
+ sepNavSelRange = "{14722, 0}";
+ sepNavVisRange = "{14230, 802}";
};
};
6B2AEC550FFB89E7005BE9CC /* Sample_StatMeshTiled.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {950, 15932}}";
- sepNavSelRange = "{143, 0}";
- sepNavVisRange = "{0, 527}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 15520}}";
+ sepNavSelRange = "{5369, 89}";
+ sepNavVisRange = "{4879, 630}";
};
};
6B2AEC570FFB89F4005BE9CC /* Sample_StatMeshTiled.h */ = {
@@ -1606,16 +1687,16 @@
};
6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 3296}}";
- sepNavSelRange = "{2613, 0}";
- sepNavVisRange = "{6136, 1040}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 4960}}";
+ sepNavSelRange = "{4189, 0}";
+ sepNavVisRange = "{3741, 1240}";
};
};
6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 20864}}";
- sepNavSelRange = "{24104, 0}";
- sepNavVisRange = "{23722, 893}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 21872}}";
+ sepNavSelRange = "{11834, 0}";
+ sepNavVisRange = "{11590, 460}";
};
};
6B2AEC5C0FFB8AB0005BE9CC /* PBXTextBookmark */ = {
@@ -2900,9 +2981,9 @@
};
6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 7024}}";
- sepNavSelRange = "{919, 0}";
- sepNavVisRange = "{0, 1274}";
+ sepNavIntBoundsRect = "{{0, 0}, {1219, 7152}}";
+ sepNavSelRange = "{8401, 0}";
+ sepNavVisRange = "{7552, 396}";
};
};
6B555DBD100B236A00247EA3 /* PBXTextBookmark */ = {
@@ -3953,7 +4034,7 @@
fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
name = "Sample_TileMesh.cpp: 88";
rLen = 0;
- rLoc = 2195;
+ rLoc = 2233;
rType = 0;
vrLen = 628;
vrLoc = 2008;
@@ -4091,7 +4172,7 @@
fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
name = "Sample_TileMesh.cpp: 88";
rLen = 0;
- rLoc = 2195;
+ rLoc = 2233;
rType = 0;
vrLen = 628;
vrLoc = 2008;
@@ -4291,7 +4372,7 @@
fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
name = "Sample_TileMesh.cpp: 492";
rLen = 0;
- rLoc = 13338;
+ rLoc = 11518;
rType = 0;
vrLen = 921;
vrLoc = 12886;
@@ -4371,7 +4452,7 @@
fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
name = "Sample_TileMesh.cpp: 492";
rLen = 0;
- rLoc = 13338;
+ rLoc = 11518;
rType = 0;
vrLen = 921;
vrLoc = 12886;
@@ -4751,7 +4832,7 @@
fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
name = "Sample_TileMesh.cpp: 493";
rLen = 0;
- rLoc = 13424;
+ rLoc = 11604;
rType = 0;
vrLen = 879;
vrLoc = 12888;
@@ -4881,7 +4962,7 @@
fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
name = "Sample_TileMesh.cpp: 493";
rLen = 0;
- rLoc = 13424;
+ rLoc = 11604;
rType = 0;
vrLen = 879;
vrLoc = 12888;
@@ -5501,7 +5582,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTileNavMesh.h: 70";
rLen = 0;
- rLoc = 2716;
+ rLoc = 2714;
rType = 0;
vrLen = 620;
vrLoc = 2419;
@@ -5511,7 +5592,7 @@
fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
name = "DetourStatNavMesh.h: 179";
rLen = 95;
- rLoc = 7147;
+ rLoc = 7149;
rType = 0;
vrLen = 1013;
vrLoc = 6323;
@@ -5619,7 +5700,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTileNavMesh.h: 70";
rLen = 0;
- rLoc = 2716;
+ rLoc = 2714;
rType = 0;
vrLen = 620;
vrLoc = 2419;
@@ -5649,7 +5730,7 @@
fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
name = "DetourStatNavMesh.h: 179";
rLen = 95;
- rLoc = 7147;
+ rLoc = 7149;
rType = 0;
vrLen = 1013;
vrLoc = 6323;
@@ -5709,7 +5790,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 381";
rLen = 0;
- rLoc = 10668;
+ rLoc = 10352;
rType = 0;
vrLen = 402;
vrLoc = 9892;
@@ -5767,7 +5848,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 426";
rLen = 0;
- rLoc = 11437;
+ rLoc = 11589;
rType = 0;
vrLen = 444;
vrLoc = 10615;
@@ -5787,7 +5868,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 382";
rLen = 0;
- rLoc = 10669;
+ rLoc = 10353;
rType = 0;
vrLen = 370;
vrLoc = 9892;
@@ -5807,7 +5888,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 381";
rLen = 0;
- rLoc = 10668;
+ rLoc = 10352;
rType = 0;
vrLen = 402;
vrLoc = 9892;
@@ -5857,7 +5938,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTileNavMesh.h: 61";
rLen = 0;
- rLoc = 2613;
+ rLoc = 2611;
rType = 0;
vrLen = 1040;
vrLoc = 6136;
@@ -5867,7 +5948,7 @@
comments = "error: expected `;' before ')' token";
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
rLen = 1;
- rLoc = 283;
+ rLoc = 278;
rType = 1;
};
6B555F45100B4C5800247EA3 /* PBXTextBookmark */ = {
@@ -5885,7 +5966,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTileNavMesh.h: 61";
rLen = 0;
- rLoc = 2613;
+ rLoc = 2611;
rType = 0;
vrLen = 576;
vrLoc = 2212;
@@ -5895,7 +5976,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 376";
rLen = 0;
- rLoc = 10580;
+ rLoc = 10262;
rType = 0;
vrLen = 693;
vrLoc = 9654;
@@ -5905,7 +5986,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTileNavMesh.h: 61";
rLen = 0;
- rLoc = 2613;
+ rLoc = 2611;
rType = 0;
vrLen = 781;
vrLoc = 2058;
@@ -5915,7 +5996,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 378";
rLen = 0;
- rLoc = 10610;
+ rLoc = 10292;
rType = 0;
vrLen = 548;
vrLoc = 9654;
@@ -5934,8 +6015,8 @@
isa = PBXTextBookmark;
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 923";
- rLen = 222;
- rLoc = 23882;
+ rLen = 0;
+ rLoc = 12201;
rType = 0;
vrLen = 926;
vrLoc = 22891;
@@ -5955,7 +6036,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 922";
rLen = 0;
- rLoc = 23848;
+ rLoc = 12201;
rType = 0;
vrLen = 926;
vrLoc = 22891;
@@ -5965,7 +6046,7 @@
fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
name = "DetourTileNavMesh.h: 61";
rLen = 0;
- rLoc = 2613;
+ rLoc = 2611;
rType = 0;
vrLen = 1040;
vrLoc = 6136;
@@ -5975,7 +6056,7 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 275";
rLen = 0;
- rLoc = 7462;
+ rLoc = 7347;
rType = 0;
vrLen = 803;
vrLoc = 7247;
@@ -5985,11 +6066,815 @@
fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
name = "DetourTileNavMesh.cpp: 943";
rLen = 0;
- rLoc = 24104;
+ rLoc = 12201;
rType = 0;
vrLen = 893;
vrLoc = 23722;
};
+ 6B555F5C100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
+ name = "DetourStatNavMesh.h: 67";
+ rLen = 0;
+ rLoc = 1901;
+ rType = 0;
+ vrLen = 1236;
+ vrLoc = 1851;
+ };
+ 6B555F5D100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 636";
+ rLen = 0;
+ rLoc = 14069;
+ rType = 0;
+ vrLen = 712;
+ vrLoc = 16084;
+ };
+ 6B555F5E100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E070F91113800904EEF /* DetourDebugDraw.cpp */;
+ name = "DetourDebugDraw.cpp: 394";
+ rLen = 0;
+ rLoc = 10003;
+ rType = 0;
+ vrLen = 771;
+ vrLoc = 9621;
+ };
+ 6B555F5F100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 241";
+ rLen = 0;
+ rLoc = 9819;
+ rType = 0;
+ vrLen = 1166;
+ vrLoc = 9275;
+ };
+ 6B555F60100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ comments = "error: 'getNeighbourTile' was not declared in this scope";
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ rLen = 1;
+ rLoc = 381;
+ rType = 1;
+ };
+ 6B555F61100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 349";
+ rLen = 0;
+ rLoc = 8059;
+ rType = 0;
+ vrLen = 869;
+ vrLoc = 8419;
+ };
+ 6B555F62100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 114";
+ rLen = 0;
+ rLoc = 4092;
+ rType = 0;
+ vrLen = 981;
+ vrLoc = 3430;
+ };
+ 6B555F63100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 327";
+ rLen = 0;
+ rLoc = 8926;
+ rType = 0;
+ vrLen = 776;
+ vrLoc = 8618;
+ };
+ 6B555F64100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 116";
+ rLen = 0;
+ rLoc = 4091;
+ rType = 0;
+ vrLen = 1052;
+ vrLoc = 3452;
+ };
+ 6B555F65100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 329";
+ rLen = 0;
+ rLoc = 9009;
+ rType = 0;
+ vrLen = 873;
+ vrLoc = 9008;
+ };
+ 6B555F66100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 127";
+ rLen = 0;
+ rLoc = 4729;
+ rType = 0;
+ vrLen = 1086;
+ vrLoc = 3462;
+ };
+ 6B555F67100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 437";
+ rLen = 0;
+ rLoc = 11982;
+ rType = 0;
+ vrLen = 616;
+ vrLoc = 10849;
+ };
+ 6B555F68100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 127";
+ rLen = 0;
+ rLoc = 4729;
+ rType = 0;
+ vrLen = 1086;
+ vrLoc = 3462;
+ };
+ 6B555F69100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 434";
+ rLen = 0;
+ rLoc = 11941;
+ rType = 0;
+ vrLen = 539;
+ vrLoc = 10824;
+ };
+ 6B555F6A100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 128";
+ rLen = 0;
+ rLoc = 4730;
+ rType = 0;
+ vrLen = 1113;
+ vrLoc = 3462;
+ };
+ 6B555F6B100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 439";
+ rLen = 0;
+ rLoc = 11982;
+ rType = 0;
+ vrLen = 581;
+ vrLoc = 10824;
+ };
+ 6B555F6C100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 144";
+ rLen = 0;
+ rLoc = 5258;
+ rType = 0;
+ vrLen = 1338;
+ vrLoc = 4292;
+ };
+ 6B555F6D100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 92";
+ rLen = 0;
+ rLoc = 3021;
+ rType = 0;
+ vrLen = 705;
+ vrLoc = 2528;
+ };
+ 6B555F6E100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 636";
+ rLen = 0;
+ rLoc = 14069;
+ rType = 0;
+ vrLen = 712;
+ vrLoc = 16084;
+ };
+ 6B555F6F100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E070F91113800904EEF /* DetourDebugDraw.cpp */;
+ name = "DetourDebugDraw.cpp: 394";
+ rLen = 0;
+ rLoc = 10003;
+ rType = 0;
+ vrLen = 771;
+ vrLoc = 9621;
+ };
+ 6B555F70100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 143";
+ rLen = 0;
+ rLoc = 5219;
+ rType = 0;
+ vrLen = 1302;
+ vrLoc = 4292;
+ };
+ 6B555F71100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 1322";
+ rLen = 0;
+ rLoc = 12201;
+ rType = 0;
+ vrLen = 686;
+ vrLoc = 33504;
+ };
+ 6B555F72100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 241";
+ rLen = 0;
+ rLoc = 9819;
+ rType = 0;
+ vrLen = 1166;
+ vrLoc = 9275;
+ };
+ 6B555F73100B53F500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 370";
+ rLen = 0;
+ rLoc = 10294;
+ rType = 0;
+ vrLen = 506;
+ vrLoc = 9725;
+ };
+ 6B555F74100B541500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 369";
+ rLen = 0;
+ rLoc = 10291;
+ rType = 0;
+ vrLen = 535;
+ vrLoc = 9788;
+ };
+ 6B555F75100B541900247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */;
+ name = "imguiRenderGL.cpp: 360";
+ rLen = 0;
+ rLoc = 8401;
+ rType = 0;
+ vrLen = 396;
+ vrLoc = 7552;
+ };
+ 6B555F76100B541900247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 369";
+ rLen = 0;
+ rLoc = 10291;
+ rType = 0;
+ vrLen = 296;
+ vrLoc = 9863;
+ };
+ 6B555F77100B54CE00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 368";
+ rLen = 0;
+ rLoc = 10262;
+ rType = 0;
+ vrLen = 426;
+ vrLoc = 10066;
+ };
+ 6B555F78100B54CE00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 259";
+ rLen = 0;
+ rLoc = 10547;
+ rType = 0;
+ vrLen = 1206;
+ vrLoc = 9497;
+ };
+ 6B555F79100B54CE00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 368";
+ rLen = 0;
+ rLoc = 10262;
+ rType = 0;
+ vrLen = 426;
+ vrLoc = 10066;
+ };
+ 6B555F7A100B54CE00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 259";
+ rLen = 0;
+ rLoc = 10547;
+ rType = 0;
+ vrLen = 1206;
+ vrLoc = 9497;
+ };
+ 6B555F7B100B54CE00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 368";
+ rLen = 0;
+ rLoc = 10262;
+ rType = 0;
+ vrLen = 426;
+ vrLoc = 10066;
+ };
+ 6B555F7C100B54CE00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 275";
+ rLen = 0;
+ rLoc = 11211;
+ rType = 0;
+ vrLen = 1011;
+ vrLoc = 10070;
+ };
+ 6B555F82100B557700247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 87";
+ rLen = 0;
+ rLoc = 2997;
+ rType = 0;
+ vrLen = 680;
+ vrLoc = 2751;
+ };
+ 6B555F83100B557700247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ comments = "error: 'encodeId' was not declared in this scope";
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ rLen = 0;
+ rLoc = 490;
+ rType = 1;
+ };
+ 6B555F84100B557700247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 87";
+ rLen = 0;
+ rLoc = 2997;
+ rType = 0;
+ vrLen = 680;
+ vrLoc = 2751;
+ };
+ 6B555F85100B557700247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 441";
+ rLen = 0;
+ rLoc = 12049;
+ rType = 0;
+ vrLen = 650;
+ vrLoc = 11119;
+ };
+ 6B555F88100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E080F91113800904EEF /* DetourStatNavMesh.cpp */;
+ name = "DetourStatNavMesh.cpp: 46";
+ rLen = 8;
+ rLoc = 1455;
+ rType = 0;
+ vrLen = 650;
+ vrLoc = 1708;
+ };
+ 6B555F89100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
+ name = "DetourStatNavMesh.h: 71";
+ rLen = 0;
+ rLoc = 2105;
+ rType = 0;
+ vrLen = 1005;
+ vrLoc = 1851;
+ };
+ 6B555F8A100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 631";
+ rLen = 0;
+ rLoc = 13994;
+ rType = 0;
+ vrLen = 591;
+ vrLoc = 16086;
+ };
+ 6B555F8B100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 124";
+ rLen = 0;
+ rLoc = 4189;
+ rType = 0;
+ vrLen = 1240;
+ vrLoc = 3741;
+ };
+ 6B555F8C100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 83";
+ rLen = 0;
+ rLoc = 2739;
+ rType = 0;
+ vrLen = 551;
+ vrLoc = 2447;
+ };
+ 6B555F8D100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 441";
+ rLen = 0;
+ rLoc = 12049;
+ rType = 0;
+ vrLen = 650;
+ vrLoc = 11119;
+ };
+ 6B555F8E100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
+ name = "DetourStatNavMesh.h: 67";
+ rLen = 0;
+ rLoc = 1901;
+ rType = 0;
+ vrLen = 1003;
+ vrLoc = 1851;
+ };
+ 6B555F8F100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 441";
+ rLen = 0;
+ rLoc = 12049;
+ rType = 0;
+ vrLen = 650;
+ vrLoc = 11119;
+ };
+ 6B555F90100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 83";
+ rLen = 0;
+ rLoc = 2892;
+ rType = 0;
+ vrLen = 418;
+ vrLoc = 2613;
+ };
+ 6B555F91100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
+ name = "DetourStatNavMesh.h: 71";
+ rLen = 83;
+ rLoc = 2039;
+ rType = 0;
+ vrLen = 997;
+ vrLoc = 1851;
+ };
+ 6B555F92100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E080F91113800904EEF /* DetourStatNavMesh.cpp */;
+ name = "DetourStatNavMesh.cpp: 706";
+ rLen = 0;
+ rLoc = 17464;
+ rType = 0;
+ vrLen = 1261;
+ vrLoc = 17259;
+ };
+ 6B555F93100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
+ name = "DetourStatNavMesh.h: 73";
+ rLen = 0;
+ rLoc = 2184;
+ rType = 0;
+ vrLen = 997;
+ vrLoc = 1851;
+ };
+ 6B555F94100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E080F91113800904EEF /* DetourStatNavMesh.cpp */;
+ name = "DetourStatNavMesh.cpp: 46";
+ rLen = 8;
+ rLoc = 1455;
+ rType = 0;
+ vrLen = 650;
+ vrLoc = 1708;
+ };
+ 6B555F95100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 126";
+ rLen = 8;
+ rLoc = 4301;
+ rType = 0;
+ vrLen = 1276;
+ vrLoc = 3705;
+ };
+ 6B555F96100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */;
+ name = "DetourStatNavMesh.h: 71";
+ rLen = 0;
+ rLoc = 2105;
+ rType = 0;
+ vrLen = 1005;
+ vrLoc = 1851;
+ };
+ 6B555F97100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 124";
+ rLen = 0;
+ rLoc = 4189;
+ rType = 0;
+ vrLen = 1240;
+ vrLoc = 3741;
+ };
+ 6B555F98100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 83";
+ rLen = 0;
+ rLoc = 2739;
+ rType = 0;
+ vrLen = 622;
+ vrLoc = 2376;
+ };
+ 6B555F99100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 631";
+ rLen = 0;
+ rLoc = 13994;
+ rType = 0;
+ vrLen = 591;
+ vrLoc = 16086;
+ };
+ 6B555F9A100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC580FFB8A68005BE9CC /* DetourTileNavMesh.h */;
+ name = "DetourTileNavMesh.h: 124";
+ rLen = 0;
+ rLoc = 4189;
+ rType = 0;
+ vrLen = 1240;
+ vrLoc = 3741;
+ };
+ 6B555F9B100B577A00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 446";
+ rLen = 0;
+ rLoc = 11713;
+ rType = 0;
+ vrLen = 483;
+ vrLoc = 11267;
+ };
+ 6B555F9E100B57B500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 446";
+ rLen = 0;
+ rLoc = 11713;
+ rType = 0;
+ vrLen = 483;
+ vrLoc = 11267;
+ };
+ 6B555F9F100B57B500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ comments = "error: no matching function for call to 'dtTiledNavMesh::addTileAt(const int&, const int&, unsigned char*&, int&)'";
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ rLen = 1;
+ rLoc = 549;
+ rType = 1;
+ };
+ 6B555FA0100B57B500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 446";
+ rLen = 0;
+ rLoc = 11713;
+ rType = 0;
+ vrLen = 483;
+ vrLoc = 11267;
+ };
+ 6B555FA1100B57B500247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 606";
+ rLen = 0;
+ rLoc = 14034;
+ rType = 0;
+ vrLen = 627;
+ vrLoc = 15489;
+ };
+ 6B555FA2100B57CA00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 608";
+ rLen = 0;
+ rLoc = 14069;
+ rType = 0;
+ vrLen = 681;
+ vrLoc = 15489;
+ };
+ 6B555FA3100B57CC00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 380";
+ rLen = 0;
+ rLoc = 10291;
+ rType = 0;
+ vrLen = 534;
+ vrLoc = 9692;
+ };
+ 6B555FA4100B57CC00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 608";
+ rLen = 0;
+ rLoc = 14069;
+ rType = 0;
+ vrLen = 431;
+ vrLoc = 15559;
+ };
+ 6B555FA8100B589200247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 469";
+ rLen = 0;
+ rLoc = 11834;
+ rType = 0;
+ vrLen = 460;
+ vrLoc = 11590;
+ };
+ 6B555FA9100B589200247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 608";
+ rLen = 0;
+ rLoc = 14069;
+ rType = 0;
+ vrLen = 681;
+ vrLoc = 15489;
+ };
+ 6B555FAA100B589200247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 608";
+ rLen = 0;
+ rLoc = 14069;
+ rType = 0;
+ vrLen = 681;
+ vrLoc = 15489;
+ };
+ 6B555FAB100B589200247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC590FFB8A7A005BE9CC /* DetourTileNavMesh.cpp */;
+ name = "DetourTileNavMesh.cpp: 469";
+ rLen = 0;
+ rLoc = 11834;
+ rType = 0;
+ vrLen = 460;
+ vrLoc = 11590;
+ };
+ 6B555FAC100B589200247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 605";
+ rLen = 0;
+ rLoc = 13992;
+ rType = 0;
+ vrLen = 655;
+ vrLoc = 15489;
+ };
+ 6B555FB0100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC550FFB89E7005BE9CC /* Sample_StatMeshTiled.cpp */;
+ name = "Sample_StatMeshTiled.cpp: 175";
+ rLen = 89;
+ rLoc = 5369;
+ rType = 0;
+ vrLen = 630;
+ vrLoc = 4879;
+ };
+ 6B555FB1100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B25B6150FFA62BE004F1BC4 /* Sample_StatMesh.cpp */;
+ name = "Sample_StatMesh.cpp: 303";
+ rLen = 0;
+ rLoc = 7561;
+ rType = 0;
+ vrLen = 728;
+ vrLoc = 7958;
+ };
+ 6B555FB2100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B25B6160FFA62BE004F1BC4 /* Sample_StatMeshSimple.cpp */;
+ name = "Sample_StatMeshSimple.cpp: 130";
+ rLen = 49;
+ rLoc = 4247;
+ rType = 0;
+ vrLen = 719;
+ vrLoc = 3933;
+ };
+ 6B555FB3100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 207";
+ rLen = 0;
+ rLoc = 5427;
+ rType = 0;
+ vrLen = 600;
+ vrLoc = 4992;
+ };
+ 6B555FB4100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 207";
+ rLen = 0;
+ rLoc = 5427;
+ rType = 0;
+ vrLen = 621;
+ vrLoc = 4992;
+ };
+ 6B555FB5100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B25B6150FFA62BE004F1BC4 /* Sample_StatMesh.cpp */;
+ name = "Sample_StatMesh.cpp: 303";
+ rLen = 0;
+ rLoc = 7561;
+ rType = 0;
+ vrLen = 728;
+ vrLoc = 7958;
+ };
+ 6B555FB6100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B25B6160FFA62BE004F1BC4 /* Sample_StatMeshSimple.cpp */;
+ name = "Sample_StatMeshSimple.cpp: 130";
+ rLen = 49;
+ rLoc = 4247;
+ rType = 0;
+ vrLen = 719;
+ vrLoc = 3933;
+ };
+ 6B555FB7100B595C00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 210";
+ rLen = 0;
+ rLoc = 5423;
+ rType = 0;
+ vrLen = 582;
+ vrLoc = 4992;
+ };
+ 6B555FBA100B598E00247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 210";
+ rLen = 0;
+ rLoc = 5364;
+ rType = 0;
+ vrLen = 601;
+ vrLoc = 4992;
+ };
+ 6B555FBD100B59B600247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 209";
+ rLen = 0;
+ rLoc = 5285;
+ rType = 0;
+ vrLen = 594;
+ vrLoc = 4992;
+ };
+ 6B555FBF100B5A0000247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 572";
+ rLen = 0;
+ rLoc = 14636;
+ rType = 0;
+ vrLen = 719;
+ vrLoc = 14230;
+ };
+ 6B555FC0100B5A3300247EA3 /* PBXTextBookmark */ = {
+ isa = PBXTextBookmark;
+ fRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */;
+ name = "Sample_TileMesh.cpp: 575";
+ rLen = 0;
+ rLoc = 14722;
+ rType = 0;
+ vrLen = 802;
+ vrLoc = 14230;
+ };
6B7707B90FBD66CF00D21BAE /* PBXTextBookmark */ = {
isa = PBXTextBookmark;
fRef = 6B137C6D0F7FCBBB00459200 /* MeshLoaderObj.cpp */;
@@ -6479,9 +7364,9 @@
};
6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 3424}}";
- sepNavSelRange = "{7147, 95}";
- sepNavVisRange = "{6323, 1013}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 3488}}";
+ sepNavSelRange = "{2105, 0}";
+ sepNavVisRange = "{1851, 1005}";
};
};
6BDD9E060F91112200904EEF /* DetourStatNavMeshBuilder.h */ = {
@@ -6493,16 +7378,16 @@
};
6BDD9E070F91113800904EEF /* DetourDebugDraw.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 6752}}";
- sepNavSelRange = "{4897, 0}";
- sepNavVisRange = "{4634, 519}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 6568}}";
+ sepNavSelRange = "{10003, 0}";
+ sepNavVisRange = "{9621, 835}";
};
};
6BDD9E080F91113800904EEF /* DetourStatNavMesh.cpp */ = {
uiCtxt = {
- sepNavIntBoundsRect = "{{0, 0}, {915, 12688}}";
- sepNavSelRange = "{17533, 0}";
- sepNavVisRange = "{17287, 1201}";
+ sepNavIntBoundsRect = "{{0, 0}, {915, 12400}}";
+ sepNavSelRange = "{1455, 8}";
+ sepNavVisRange = "{1708, 650}";
};
};
6BDD9E090F91113800904EEF /* DetourStatNavMeshBuilder.cpp */ = {
diff --git a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3 b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3
index 910458e..9a1016b 100644
--- a/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3
+++ b/RecastDemo/Build/Xcode/Recast.xcodeproj/memon.perspectivev3
@@ -270,6 +270,7 @@
080E96DDFE201D6D7F000001
6BDD9E030F91110C00904EEF
6B137C7D0F7FCBE800459200
+ 6B555DF5100B25FC00247EA3
29B97315FDCFA39411CA2CEA
29B97317FDCFA39411CA2CEA
1C37FBAC04509CD000000102
@@ -278,14 +279,14 @@
PBXSmartGroupTreeModuleOutlineStateSelectionKey
- 11
- 3
+ 36
+ 32
1
0
PBXSmartGroupTreeModuleOutlineStateVisibleRectKey
- {{0, 0}, {282, 628}}
+ {{0, 104}, {282, 628}}
PBXTopSmartGroupGIDs
@@ -320,7 +321,7 @@
PBXProjectModuleGUID
6B8632A30F78115100E2684A
PBXProjectModuleLabel
- DetourTileNavMesh.cpp
+ Sample_TileMesh.cpp
PBXSplitModuleInNavigatorKey
Split0
@@ -328,11 +329,11 @@
PBXProjectModuleGUID
6B8632A40F78115100E2684A
PBXProjectModuleLabel
- DetourTileNavMesh.cpp
+ Sample_TileMesh.cpp
_historyCapacity
0
bookmark
- 6B555F52100B4CE300247EA3
+ 6B555FC0100B5A3300247EA3
history
6BB87E0B0F9DE8A300E33F12
@@ -385,16 +386,16 @@
6B555F11100B473F00247EA3
6B555F12100B473F00247EA3
6B555F13100B473F00247EA3
- 6B555F15100B473F00247EA3
- 6B555F2A100B499000247EA3
- 6B555F2B100B499000247EA3
- 6B555F2C100B499000247EA3
- 6B555F2D100B499000247EA3
- 6B555F40100B4C5800247EA3
- 6B555F41100B4C5800247EA3
6B555F42100B4C5800247EA3
- 6B555F43100B4C5800247EA3
- 6B555F44100B4C5800247EA3
+ 6B555F5E100B53F500247EA3
+ 6B555F88100B577A00247EA3
+ 6B555F89100B577A00247EA3
+ 6B555F8B100B577A00247EA3
+ 6B555FA8100B589200247EA3
+ 6B555FB0100B595C00247EA3
+ 6B555FB1100B595C00247EA3
+ 6B555FB2100B595C00247EA3
+ 6B555FB3100B595C00247EA3
prevStack
@@ -435,7 +436,6 @@
6B0249051001EABD00CF7107
6B02498D1003751300CF7107
6B024A721004A2FE00CF7107
- 6B024BBB1005DF5700CF7107
6B024BCF1005DFAB00CF7107
6B024C041006098300CF7107
6B024C1310060C7600CF7107
@@ -445,7 +445,6 @@
6B1186401006945C0018F96F
6B1186411006945C0018F96F
6B1186581006945C0018F96F
- 6B1186591006945C0018F96F
6B118672100694C40018F96F
6B555D15100B125300247EA3
6B555D26100B136A00247EA3
@@ -465,7 +464,6 @@
6B555D50100B175F00247EA3
6B555D53100B175F00247EA3
6B555D54100B175F00247EA3
- 6B555D55100B175F00247EA3
6B555D5D100B17DB00247EA3
6B555D5E100B17DB00247EA3
6B555D5F100B17DB00247EA3
@@ -482,7 +480,6 @@
6B555D97100B1B6900247EA3
6B555D9E100B1C2400247EA3
6B555DA0100B1C2400247EA3
- 6B555DAB100B1E6500247EA3
6B555DC3100B236A00247EA3
6B555DC4100B236A00247EA3
6B555DC5100B236A00247EA3
@@ -519,7 +516,6 @@
6B555E09100B285300247EA3
6B555E0A100B285300247EA3
6B555E0B100B285300247EA3
- 6B555E0C100B285300247EA3
6B555E0D100B285300247EA3
6B555E0E100B285300247EA3
6B555E0F100B285300247EA3
@@ -537,7 +533,6 @@
6B555E47100B311B00247EA3
6B555E48100B311B00247EA3
6B555E49100B311B00247EA3
- 6B555E4A100B311B00247EA3
6B555E4B100B311B00247EA3
6B555E4C100B311B00247EA3
6B555E4D100B311B00247EA3
@@ -554,7 +549,6 @@
6B555E67100B334900247EA3
6B555E68100B334900247EA3
6B555E69100B334900247EA3
- 6B555E6A100B334900247EA3
6B555E6B100B334900247EA3
6B555E6C100B334900247EA3
6B555E6D100B334900247EA3
@@ -581,7 +575,6 @@
6B555EA9100B37AB00247EA3
6B555EAA100B37AB00247EA3
6B555EAB100B37AB00247EA3
- 6B555EAC100B37AB00247EA3
6B555EAF100B37AB00247EA3
6B555EB1100B37AB00247EA3
6B555EB2100B37AB00247EA3
@@ -600,29 +593,45 @@
6B555F1D100B473F00247EA3
6B555F1E100B473F00247EA3
6B555F1F100B473F00247EA3
- 6B555F20100B473F00247EA3
6B555F21100B473F00247EA3
6B555F22100B473F00247EA3
6B555F23100B473F00247EA3
6B555F30100B499000247EA3
6B555F31100B499000247EA3
- 6B555F32100B499000247EA3
6B555F33100B499000247EA3
- 6B555F34100B499000247EA3
6B555F35100B499000247EA3
- 6B555F36100B499000247EA3
6B555F37100B499000247EA3
- 6B555F38100B499000247EA3
6B555F45100B4C5800247EA3
- 6B555F46100B4C5800247EA3
- 6B555F47100B4C5800247EA3
- 6B555F48100B4C5800247EA3
- 6B555F49100B4C5800247EA3
6B555F4A100B4C5800247EA3
- 6B555F4B100B4C5800247EA3
6B555F4C100B4C5800247EA3
- 6B555F4D100B4C5800247EA3
- 6B555F4E100B4C5800247EA3
+ 6B555F63100B53F500247EA3
+ 6B555F65100B53F500247EA3
+ 6B555F67100B53F500247EA3
+ 6B555F69100B53F500247EA3
+ 6B555F6B100B53F500247EA3
+ 6B555F6D100B53F500247EA3
+ 6B555F6F100B53F500247EA3
+ 6B555F71100B53F500247EA3
+ 6B555F79100B54CE00247EA3
+ 6B555F7B100B54CE00247EA3
+ 6B555F8D100B577A00247EA3
+ 6B555F8E100B577A00247EA3
+ 6B555F8F100B577A00247EA3
+ 6B555F90100B577A00247EA3
+ 6B555F91100B577A00247EA3
+ 6B555F92100B577A00247EA3
+ 6B555F93100B577A00247EA3
+ 6B555F94100B577A00247EA3
+ 6B555F95100B577A00247EA3
+ 6B555F96100B577A00247EA3
+ 6B555F97100B577A00247EA3
+ 6B555F98100B577A00247EA3
+ 6B555F9A100B577A00247EA3
+ 6B555FA0100B57B500247EA3
+ 6B555FAB100B589200247EA3
+ 6B555FB4100B595C00247EA3
+ 6B555FB5100B595C00247EA3
+ 6B555FB6100B595C00247EA3
SplitCount
@@ -636,18 +645,18 @@
GeometryConfiguration
Frame
- {{0, 0}, {976, 443}}
+ {{0, 0}, {976, 462}}
RubberWindowFrame
0 91 1280 687 0 0 1280 778
Module
PBXNavigatorGroup
Proportion
- 443pt
+ 462pt
Proportion
- 198pt
+ 179pt
Tabs
@@ -661,7 +670,7 @@
GeometryConfiguration
Frame
- {{10, 27}, {976, -27}}
+ {{10, 27}, {976, 85}}
Module
XCDetailModule
@@ -677,7 +686,7 @@
GeometryConfiguration
Frame
- {{10, 27}, {976, 244}}
+ {{10, 27}, {976, 196}}
Module
PBXProjectFindModule
@@ -715,7 +724,7 @@
GeometryConfiguration
Frame
- {{10, 27}, {976, 171}}
+ {{10, 27}, {976, 152}}
RubberWindowFrame
0 91 1280 687 0 0 1280 778
diff --git a/RecastDemo/Include/Sample.h b/RecastDemo/Include/Sample.h
new file mode 100644
index 0000000..7706f8a
--- /dev/null
+++ b/RecastDemo/Include/Sample.h
@@ -0,0 +1,50 @@
+#ifndef RECASTSAMPLE_H
+#define RECASTSAMPLE_H
+
+
+class Sample
+{
+protected:
+ const float* m_verts;
+ int m_nverts;
+ const int* m_tris;
+ const float* m_trinorms;
+ int m_ntris;
+ float m_bmin[3], m_bmax[3];
+
+ float m_cellSize;
+ float m_cellHeight;
+ float m_agentHeight;
+ float m_agentRadius;
+ float m_agentMaxClimb;
+ float m_agentMaxSlope;
+ float m_regionMinSize;
+ float m_regionMergeSize;
+ float m_edgeMaxLen;
+ float m_edgeMaxError;
+ float m_vertsPerPoly;
+
+public:
+ Sample();
+ virtual ~Sample();
+
+ virtual void handleSettings();
+ virtual void handleTools();
+ virtual void handleDebugMode();
+
+ virtual void setToolStartPos(const float* p);
+ virtual void setToolEndPos(const float* p);
+
+ virtual void handleRender();
+ virtual void handleRenderOverlay(double* proj, double* model, int* view);
+ virtual void handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax);
+ virtual bool handleBuild();
+
+ void resetCommonSettings();
+ void handleCommonSettings();
+};
+
+
+#endif // RECASTSAMPLE_H
diff --git a/RecastDemo/Include/Sample_StatMesh.h b/RecastDemo/Include/Sample_StatMesh.h
new file mode 100644
index 0000000..59e0c70
--- /dev/null
+++ b/RecastDemo/Include/Sample_StatMesh.h
@@ -0,0 +1,70 @@
+#ifndef RECASTSAMPLESTATMESH_H
+#define RECASTSAMPLESTATMESH_H
+
+#include "Sample.h"
+#include "DetourStatNavMesh.h"
+#include "Recast.h"
+#include "RecastLog.h"
+
+class Sample_StatMesh : public Sample
+{
+protected:
+
+ dtStatNavMesh* m_navMesh;
+
+ enum ToolMode
+ {
+ TOOLMODE_PATHFIND,
+ TOOLMODE_RAYCAST,
+ TOOLMODE_DISTANCE_TO_WALL,
+ TOOLMODE_FIND_POLYS_AROUND,
+ };
+
+ ToolMode m_toolMode;
+
+ static const int MAX_POLYS = 256;
+
+ dtStatPolyRef m_startRef;
+ dtStatPolyRef m_endRef;
+ dtStatPolyRef m_polys[MAX_POLYS];
+ dtStatPolyRef m_parent[MAX_POLYS];
+ int m_npolys;
+ float m_straightPath[MAX_POLYS*3];
+ int m_nstraightPath;
+ float m_polyPickExt[3];
+
+ float m_spos[3];
+ float m_epos[3];
+ float m_hitPos[3];
+ float m_hitNormal[3];
+ float m_distanceToWall;
+ bool m_sposSet;
+ bool m_eposSet;
+
+ enum ToolRenderFlags
+ {
+ NAVMESH_POLYS = 0x01,
+ NAVMESH_BVTREE = 0x02,
+ NAVMESH_TOOLS = 0x04,
+ };
+
+ void toolCleanup();
+ void toolReset();
+ void toolRecalc();
+ void toolRender(int flags);
+ void toolRenderOverlay(double* proj, double* model, int* view);
+
+ void drawAgent(const float* pos, float r, float h, float c, const float* col);
+
+
+public:
+ Sample_StatMesh();
+ virtual ~Sample_StatMesh();
+
+ virtual void handleTools();
+ virtual void setToolStartPos(const float* p);
+ virtual void setToolEndPos(const float* p);
+};
+
+
+#endif // RECASTSAMPLESTATMESH_H
diff --git a/RecastDemo/Include/Sample_StatMeshSimple.h b/RecastDemo/Include/Sample_StatMeshSimple.h
new file mode 100644
index 0000000..c381df6
--- /dev/null
+++ b/RecastDemo/Include/Sample_StatMeshSimple.h
@@ -0,0 +1,63 @@
+#ifndef RECASTSAMPLESTATMESHSIMPLE_H
+#define RECASTSAMPLESTATMESHSIMPLE_H
+
+#include "Sample_StatMesh.h"
+#include "DetourStatNavMesh.h"
+#include "Recast.h"
+#include "RecastLog.h"
+
+class Sample_StatMeshSimple : public Sample_StatMesh
+{
+protected:
+
+ bool m_keepInterResults;
+ rcBuildTimes m_buildTimes;
+
+ unsigned char* m_triflags;
+ rcHeightfield* m_solid;
+ rcCompactHeightfield* m_chf;
+ rcContourSet* m_cset;
+ rcPolyMesh* m_polyMesh;
+ rcConfig m_cfg;
+
+ enum DrawMode
+ {
+ DRAWMODE_NAVMESH,
+ DRAWMODE_NAVMESH_TRANS,
+ DRAWMODE_NAVMESH_BVTREE,
+ DRAWMODE_NAVMESH_INVIS,
+ DRAWMODE_MESH,
+ DRAWMODE_VOXELS,
+ DRAWMODE_VOXELS_WALKABLE,
+ DRAWMODE_COMPACT,
+ DRAWMODE_COMPACT_DISTANCE,
+ DRAWMODE_COMPACT_REGIONS,
+ DRAWMODE_REGION_CONNECTIONS,
+ DRAWMODE_RAW_CONTOURS,
+ DRAWMODE_BOTH_CONTOURS,
+ DRAWMODE_CONTOURS,
+ DRAWMODE_POLYMESH,
+ MAX_DRAWMODE
+ };
+
+ DrawMode m_drawMode;
+
+ void cleanup();
+
+public:
+ Sample_StatMeshSimple();
+ virtual ~Sample_StatMeshSimple();
+
+ virtual void handleSettings();
+ virtual void handleDebugMode();
+
+ virtual void handleRender();
+ virtual void handleRenderOverlay(double* proj, double* model, int* view);
+ virtual void handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax);
+ virtual bool handleBuild();
+};
+
+
+#endif // RECASTSAMPLESTATMESHSIMPLE_H
diff --git a/RecastDemo/Include/Sample_StatMeshTiled.h b/RecastDemo/Include/Sample_StatMeshTiled.h
new file mode 100644
index 0000000..0db0bb0
--- /dev/null
+++ b/RecastDemo/Include/Sample_StatMeshTiled.h
@@ -0,0 +1,91 @@
+#ifndef RECASTSAMPLESTATMESHTILED_H
+#define RECASTSAMPLESTATMESHTILED_H
+
+#include "Sample_StatMesh.h"
+#include "DetourStatNavMesh.h"
+#include "Recast.h"
+#include "RecastLog.h"
+#include "ChunkyTriMesh.h"
+
+class Sample_StatMeshTiled : public Sample_StatMesh
+{
+protected:
+
+ struct Tile
+ {
+ inline Tile() : chf(0), cset(0), solid(0), buildTime(0) {}
+ inline ~Tile() { delete chf; delete cset; delete solid; }
+ rcCompactHeightfield* chf;
+ rcHeightfield* solid;
+ rcContourSet* cset;
+ int buildTime;
+ };
+
+ struct TileSet
+ {
+ inline TileSet() : width(0), height(0), tiles(0) {}
+ inline ~TileSet() { delete [] tiles; }
+ int width, height;
+ float bmin[3], bmax[3];
+ float cs, ch;
+ Tile* tiles;
+ };
+
+ bool m_measurePerTileTimings;
+ bool m_keepInterResults;
+ float m_tileSize;
+ rcBuildTimes m_buildTimes;
+
+ rcChunkyTriMesh* m_chunkyMesh;
+ rcPolyMesh* m_polyMesh;
+ rcConfig m_cfg;
+ TileSet* m_tileSet;
+
+ static const int MAX_STAT_BUCKETS = 1000;
+ int m_statPolysPerTile[MAX_STAT_BUCKETS];
+ int m_statPolysPerTileSamples;
+ int m_statTimePerTile[MAX_STAT_BUCKETS];
+ int m_statTimePerTileSamples;
+
+
+ enum DrawMode
+ {
+ DRAWMODE_NAVMESH,
+ DRAWMODE_NAVMESH_TRANS,
+ DRAWMODE_NAVMESH_BVTREE,
+ DRAWMODE_NAVMESH_INVIS,
+ DRAWMODE_MESH,
+ DRAWMODE_VOXELS,
+ DRAWMODE_VOXELS_WALKABLE,
+ DRAWMODE_COMPACT,
+ DRAWMODE_COMPACT_DISTANCE,
+ DRAWMODE_COMPACT_REGIONS,
+ DRAWMODE_REGION_CONNECTIONS,
+ DRAWMODE_RAW_CONTOURS,
+ DRAWMODE_BOTH_CONTOURS,
+ DRAWMODE_CONTOURS,
+ DRAWMODE_POLYMESH,
+ MAX_DRAWMODE
+ };
+
+ DrawMode m_drawMode;
+
+ void cleanup();
+
+public:
+ Sample_StatMeshTiled();
+ virtual ~Sample_StatMeshTiled();
+
+ virtual void handleSettings();
+ virtual void handleDebugMode();
+
+ virtual void handleRender();
+ virtual void handleRenderOverlay(double* proj, double* model, int* view);
+ virtual void handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax);
+ virtual bool handleBuild();
+};
+
+
+#endif // RECASTSAMPLESTATMESHTILED_H
diff --git a/RecastDemo/Include/Sample_TileMesh.h b/RecastDemo/Include/Sample_TileMesh.h
new file mode 100644
index 0000000..b957312
--- /dev/null
+++ b/RecastDemo/Include/Sample_TileMesh.h
@@ -0,0 +1,113 @@
+//
+// Copyright (c) 2009 Mikko Mononen memon@inside.org
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+
+#ifndef RECASTSAMPLETILEDMESH_H
+#define RECASTSAMPLETILEDMESH_H
+
+#include "Sample.h"
+#include "DetourTileNavMesh.h"
+#include "Recast.h"
+#include "RecastLog.h"
+#include "ChunkyTriMesh.h"
+
+class Sample_TileMesh : public Sample
+{
+protected:
+
+ bool m_keepInterResults;
+ rcBuildTimes m_buildTimes;
+
+ dtTiledNavMesh* m_navMesh;
+ rcChunkyTriMesh* m_chunkyMesh;
+ unsigned char* m_triflags;
+ rcHeightfield* m_solid;
+ rcCompactHeightfield* m_chf;
+ rcContourSet* m_cset;
+ rcPolyMesh* m_polyMesh;
+ rcConfig m_cfg;
+
+ float m_tileSize;
+
+ float m_spos[3];
+ float m_epos[3];
+ bool m_sposSet;
+ bool m_eposSet;
+
+ float m_tileCol[4];
+ float m_tileBmin[3];
+ float m_tileBmax[3];
+ float m_tileBuildTime;
+ float m_tileMemUsage;
+ int m_tileTriCount;
+
+ enum ToolMode
+ {
+ TOOLMODE_CREATE_TILES,
+ TOOLMODE_PATHFIND,
+ TOOLMODE_RAYCAST,
+ TOOLMODE_DISTANCE_TO_WALL,
+ TOOLMODE_FIND_POLYS_AROUND,
+ };
+
+ dtTilePolyRef m_startRef;
+ dtTilePolyRef m_endRef;
+ float m_polyPickExt[3];
+
+ static const int MAX_POLYS = 256;
+
+ dtTilePolyRef m_polys[MAX_POLYS];
+ dtTilePolyRef m_parent[MAX_POLYS];
+ int m_npolys;
+ float m_straightPath[MAX_POLYS*3];
+ int m_nstraightPath;
+ float m_hitPos[3];
+ float m_hitNormal[3];
+ float m_distanceToWall;
+
+ ToolMode m_toolMode;
+
+ void toolRecalc();
+
+ void buildTile(const float* pos);
+ void removeTile(const float* pos);
+
+ unsigned char* buildTileMesh(const float* bmin, const float* bmax, int& dataSize);
+
+ void cleanup();
+
+public:
+ Sample_TileMesh();
+ virtual ~Sample_TileMesh();
+
+ virtual void handleSettings();
+ virtual void handleTools();
+ virtual void handleDebugMode();
+
+ virtual void setToolStartPos(const float* p);
+ virtual void setToolEndPos(const float* p);
+
+ virtual void handleRender();
+ virtual void handleRenderOverlay(double* proj, double* model, int* view);
+ virtual void handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax);
+ virtual bool handleBuild();
+};
+
+
+#endif // RECASTBUILDERTILEDMESH_H
diff --git a/RecastDemo/Source/Sample.cpp b/RecastDemo/Source/Sample.cpp
new file mode 100644
index 0000000..1219547
--- /dev/null
+++ b/RecastDemo/Source/Sample.cpp
@@ -0,0 +1,123 @@
+#define _USE_MATH_DEFINES
+#include
+#include
+#include "Sample.h"
+#include "Recast.h"
+#include "RecastDebugDraw.h"
+#include "imgui.h"
+
+#ifdef WIN32
+# define snprintf _snprintf
+#endif
+
+
+Sample::Sample() :
+ m_verts(0), m_nverts(0), m_tris(0), m_trinorms(0), m_ntris(0)
+{
+ resetCommonSettings();
+}
+
+Sample::~Sample()
+{
+}
+
+void Sample::handleSettings()
+{
+}
+
+void Sample::handleTools()
+{
+}
+
+void Sample::handleDebugMode()
+{
+}
+
+void Sample::handleRender()
+{
+ if (!m_verts || !m_tris || !m_trinorms)
+ return;
+ // Draw mesh
+ rcDebugDrawMesh(m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
+ // Draw bounds
+ float col[4] = {1,1,1,0.5f};
+ rcDebugDrawBoxWire(m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
+}
+
+void Sample::handleRenderOverlay(double* proj, double* model, int* view)
+{
+}
+
+void Sample::handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax)
+{
+ m_verts = verts;
+ m_nverts = nverts;
+ m_tris = tris;
+ m_trinorms = trinorms;
+ m_ntris = ntris;
+ vcopy(m_bmin, bmin);
+ vcopy(m_bmax, bmax);
+}
+
+void Sample::resetCommonSettings()
+{
+ m_cellSize = 0.3f;
+ m_cellHeight = 0.2f;
+ m_agentHeight = 2.0f;
+ m_agentRadius = 0.6f;
+ m_agentMaxClimb = 0.9f;
+ m_agentMaxSlope = 45.0f;
+ m_regionMinSize = 50;
+ m_regionMergeSize = 20;
+ m_edgeMaxLen = 12.0f;
+ m_edgeMaxError = 1.3f;
+ m_vertsPerPoly = 6.0f;
+}
+
+void Sample::handleCommonSettings()
+{
+ imguiLabel("Rasterization");
+ imguiSlider("Cell Size", &m_cellSize, 0.1f, 1.0f, 0.01f);
+ imguiSlider("Cell Height", &m_cellHeight, 0.1f, 1.0f, 0.01f);
+
+ int gw = 0, gh = 0;
+ rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
+ char text[64];
+ snprintf(text, 64, "Voxels %d x %d", gw, gh);
+ imguiValue(text);
+
+ imguiSeparator();
+ imguiLabel("Agent");
+ imguiSlider("Height", &m_agentHeight, 0.1f, 5.0f, 0.1f);
+ imguiSlider("Radius", &m_agentRadius, 0.0f, 5.0f, 0.1f);
+ imguiSlider("Max Climb", &m_agentMaxClimb, 0.1f, 5.0f, 0.1f);
+ imguiSlider("Max Slope", &m_agentMaxSlope, 0.0f, 90.0f, 1.0f);
+
+ imguiSeparator();
+ imguiLabel("Region");
+ imguiSlider("Min Region Size", &m_regionMinSize, 0.0f, 150.0f, 1.0f);
+ imguiSlider("Merged Region Size", &m_regionMergeSize, 0.0f, 150.0f, 1.0f);
+
+ imguiSeparator();
+ imguiLabel("Polygonization");
+ imguiSlider("Max Edge Length", &m_edgeMaxLen, 0.0f, 50.0f, 1.0f);
+ imguiSlider("Max Edge Error", &m_edgeMaxError, 0.1f, 3.0f, 0.1f);
+ imguiSlider("Verts Per Poly", &m_vertsPerPoly, 3.0f, 12.0f, 1.0f);
+
+ imguiSeparator();
+}
+
+void Sample::setToolStartPos(const float* p)
+{
+}
+
+void Sample::setToolEndPos(const float* p)
+{
+}
+
+bool Sample::handleBuild()
+{
+ return true;
+}
diff --git a/RecastDemo/Source/Sample_StatMesh.cpp b/RecastDemo/Source/Sample_StatMesh.cpp
new file mode 100644
index 0000000..4063389
--- /dev/null
+++ b/RecastDemo/Source/Sample_StatMesh.cpp
@@ -0,0 +1,336 @@
+#define _USE_MATH_DEFINES
+#include
+#include
+#include
+#include "SDL.h"
+#include "SDL_Opengl.h"
+#include "imgui.h"
+#include "Sample.h"
+#include "Sample_StatMesh.h"
+#include "Recast.h"
+#include "RecastTimer.h"
+#include "RecastDebugDraw.h"
+#include "DetourStatNavMesh.h"
+#include "DetourStatNavMeshBuilder.h"
+#include "DetourDebugDraw.h"
+
+#ifdef WIN32
+# define snprintf _snprintf
+#endif
+
+Sample_StatMesh::Sample_StatMesh() :
+ m_navMesh(0),
+ m_toolMode(TOOLMODE_PATHFIND),
+ m_sposSet(false),
+ m_eposSet(false)
+{
+ toolReset();
+ m_polyPickExt[0] = 2;
+ m_polyPickExt[1] = 4;
+ m_polyPickExt[2] = 2;
+}
+
+Sample_StatMesh::~Sample_StatMesh()
+{
+ toolCleanup();
+}
+
+void Sample_StatMesh::handleTools()
+{
+ if (imguiCheck("Pathfind", m_toolMode == TOOLMODE_PATHFIND))
+ {
+ m_toolMode = TOOLMODE_PATHFIND;
+ toolRecalc();
+ }
+ if (imguiCheck("Distance to Wall", m_toolMode == TOOLMODE_DISTANCE_TO_WALL))
+ {
+ m_toolMode = TOOLMODE_DISTANCE_TO_WALL;
+ toolRecalc();
+ }
+ if (imguiCheck("Raycast", m_toolMode == TOOLMODE_RAYCAST))
+ {
+ m_toolMode = TOOLMODE_RAYCAST;
+ toolRecalc();
+ }
+ if (imguiCheck("Find Polys Around", m_toolMode == TOOLMODE_FIND_POLYS_AROUND))
+ {
+ m_toolMode = TOOLMODE_FIND_POLYS_AROUND;
+ toolRecalc();
+ }
+}
+
+void Sample_StatMesh::setToolStartPos(const float* p)
+{
+ m_sposSet = true;
+ vcopy(m_spos, p);
+ toolRecalc();
+}
+
+void Sample_StatMesh::setToolEndPos(const float* p)
+{
+ m_eposSet = true;
+ vcopy(m_epos, p);
+ toolRecalc();
+}
+
+void Sample_StatMesh::toolCleanup()
+{
+ delete m_navMesh;
+ m_navMesh = 0;
+}
+
+void Sample_StatMesh::toolReset()
+{
+ m_startRef = 0;
+ m_endRef = 0;
+ m_npolys = 0;
+ m_nstraightPath = 0;
+ memset(m_hitPos, 0, sizeof(m_hitPos));
+ memset(m_hitNormal, 0, sizeof(m_hitNormal));
+ m_distanceToWall = 0;
+}
+
+void Sample_StatMesh::toolRecalc()
+{
+ if (!m_navMesh)
+ return;
+
+ if (m_sposSet)
+ m_startRef = m_navMesh->findNearestPoly(m_spos, m_polyPickExt);
+ else
+ m_startRef = 0;
+
+ if (m_eposSet)
+ m_endRef = m_navMesh->findNearestPoly(m_epos, m_polyPickExt);
+ else
+ m_endRef = 0;
+
+ if (m_toolMode == TOOLMODE_PATHFIND)
+ {
+ if (m_sposSet && m_eposSet && m_startRef && m_endRef)
+ {
+ m_npolys = m_navMesh->findPath(m_startRef, m_endRef, m_polys, MAX_POLYS);
+ if (m_npolys)
+ m_nstraightPath = m_navMesh->findStraightPath(m_spos, m_epos, m_polys, m_npolys, m_straightPath, MAX_POLYS);
+ }
+ else
+ {
+ m_npolys = 0;
+ m_nstraightPath = 0;
+ }
+ }
+ else if (m_toolMode == TOOLMODE_RAYCAST)
+ {
+ m_nstraightPath = 0;
+ if (m_sposSet && m_eposSet && m_startRef)
+ {
+ float t = 0;
+ m_npolys = 0;
+ m_nstraightPath = 2;
+ m_straightPath[0] = m_spos[0];
+ m_straightPath[1] = m_spos[1];
+ m_straightPath[2] = m_spos[2];
+ m_npolys = m_navMesh->raycast(m_startRef, m_spos, m_epos, t, m_polys, MAX_POLYS);
+ if (t < 1)
+ {
+ m_straightPath[3] = m_spos[0] + (m_epos[0] - m_spos[0]) * t;
+ m_straightPath[4] = m_spos[1] + (m_epos[1] - m_spos[1]) * t;
+ m_straightPath[5] = m_spos[2] + (m_epos[2] - m_spos[2]) * t;
+ }
+ else
+ {
+ m_straightPath[3] = m_epos[0];
+ m_straightPath[4] = m_epos[1];
+ m_straightPath[5] = m_epos[2];
+ }
+ }
+ }
+ else if (m_toolMode == TOOLMODE_DISTANCE_TO_WALL)
+ {
+ m_distanceToWall = 0;
+ if (m_sposSet && m_startRef)
+ m_distanceToWall = m_navMesh->findDistanceToWall(m_startRef, m_spos, 100.0f, m_hitPos, m_hitNormal);
+ }
+ else if (m_toolMode == TOOLMODE_FIND_POLYS_AROUND)
+ {
+ if (m_sposSet && m_startRef && m_eposSet)
+ {
+ const float dx = m_epos[0] - m_spos[0];
+ const float dz = m_epos[2] - m_spos[2];
+ float dist = sqrtf(dx*dx + dz*dz);
+ m_npolys = m_navMesh->findPolysAround(m_startRef, m_spos, dist, m_polys, m_parent, 0, MAX_POLYS);
+ }
+ }
+}
+
+static void getPolyCenter(dtStatNavMesh* navMesh, dtStatPolyRef ref, float* center)
+{
+ const dtStatPoly* p = navMesh->getPolyByRef(ref);
+ if (!p) return;
+ center[0] = 0;
+ center[1] = 0;
+ center[2] = 0;
+ for (int i = 0; i < (int)p->nv; ++i)
+ {
+ const float* v = navMesh->getVertex(p->v[i]);
+ center[0] += v[0];
+ center[1] += v[1];
+ center[2] += v[2];
+ }
+ const float s = 1.0f / p->nv;
+ center[0] *= s;
+ center[1] *= s;
+ center[2] *= s;
+}
+
+void Sample_StatMesh::toolRender(int flags)
+{
+ if (!m_navMesh)
+ return;
+
+ static const float startCol[4] = { 0.5f, 0.1f, 0.0f, 0.75f };
+ static const float endCol[4] = { 0.2f, 0.4f, 0.0f, 0.75f };
+ static const float pathCol[4] = {0,0,0,0.25f};
+
+ glDepthMask(GL_FALSE);
+
+ if (flags & NAVMESH_POLYS)
+ dtDebugDrawStatNavMesh(m_navMesh);
+
+ if (flags & NAVMESH_BVTREE)
+ dtDebugDrawStatNavMeshBVTree(m_navMesh);
+
+ if (flags & NAVMESH_TOOLS)
+ {
+ if (m_toolMode == TOOLMODE_PATHFIND)
+ {
+ dtDebugDrawStatNavMeshPoly(m_navMesh, m_startRef, startCol);
+ dtDebugDrawStatNavMeshPoly(m_navMesh, m_endRef, endCol);
+
+ if (m_npolys)
+ {
+ for (int i = 1; i < m_npolys-1; ++i)
+ dtDebugDrawStatNavMeshPoly(m_navMesh, m_polys[i], pathCol);
+ }
+ if (m_nstraightPath)
+ {
+ glColor4ub(128,16,0,220);
+ glLineWidth(3.0f);
+ glBegin(GL_LINE_STRIP);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glLineWidth(1.0f);
+ glPointSize(4.0f);
+ glBegin(GL_POINTS);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glPointSize(1.0f);
+ }
+ }
+ else if (m_toolMode == TOOLMODE_RAYCAST)
+ {
+ dtDebugDrawStatNavMeshPoly(m_navMesh, m_startRef, startCol);
+
+ if (m_nstraightPath)
+ {
+ for (int i = 1; i < m_npolys; ++i)
+ dtDebugDrawStatNavMeshPoly(m_navMesh, m_polys[i], pathCol);
+
+ glColor4ub(128,16,0,220);
+ glLineWidth(3.0f);
+ glBegin(GL_LINE_STRIP);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glLineWidth(1.0f);
+ glPointSize(4.0f);
+ glBegin(GL_POINTS);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glPointSize(1.0f);
+ }
+ }
+ else if (m_toolMode == TOOLMODE_DISTANCE_TO_WALL)
+ {
+ dtDebugDrawStatNavMeshPoly(m_navMesh, m_startRef, startCol);
+ const float col[4] = {1,1,1,0.5f};
+ rcDebugDrawCylinderWire(m_spos[0]-m_distanceToWall, m_spos[1]+0.02f, m_spos[2]-m_distanceToWall,
+ m_spos[0]+m_distanceToWall, m_spos[1]+m_agentHeight, m_spos[2]+m_distanceToWall, col);
+ glLineWidth(3.0f);
+ glColor4fv(col);
+ glBegin(GL_LINES);
+ glVertex3f(m_hitPos[0], m_hitPos[1] + 0.02f, m_hitPos[2]);
+ glVertex3f(m_hitPos[0], m_hitPos[1] + m_agentHeight, m_hitPos[2]);
+ glEnd();
+ glLineWidth(1.0f);
+ }
+ else if (m_toolMode == TOOLMODE_FIND_POLYS_AROUND)
+ {
+ glLineWidth(2.0f);
+ for (int i = 0; i < m_npolys; ++i)
+ {
+ dtDebugDrawStatNavMeshPoly(m_navMesh, m_polys[i], pathCol);
+ if (m_parent[i])
+ {
+ float p0[3], p1[3];
+ getPolyCenter(m_navMesh, m_polys[i], p0);
+ getPolyCenter(m_navMesh, m_parent[i], p1);
+ glColor4ub(0,0,0,128);
+ rcDrawArc(p0, p1);
+ }
+ }
+ glLineWidth(1.0f);
+
+ const float dx = m_epos[0] - m_spos[0];
+ const float dz = m_epos[2] - m_spos[2];
+ float dist = sqrtf(dx*dx + dz*dz);
+ const float col[4] = {1,1,1,0.5f};
+ rcDebugDrawCylinderWire(m_spos[0]-dist, m_spos[1]+0.02f, m_spos[2]-dist,
+ m_spos[0]+dist, m_spos[1]+m_agentHeight, m_spos[2]+dist, col);
+ }
+ }
+
+ glDepthMask(GL_TRUE);
+}
+
+void Sample_StatMesh::toolRenderOverlay(double* proj, double* model, int* view)
+{
+ GLdouble x, y, z;
+
+ // Draw start and end point labels
+ if (m_sposSet && gluProject((GLdouble)m_spos[0], (GLdouble)m_spos[1], (GLdouble)m_spos[2],
+ model, proj, view, &x, &y, &z))
+ {
+ imguiDrawText((int)x, (int)(y-25), IMGUI_ALIGN_CENTER, "Start", imguiRGBA(0,0,0,220));
+ }
+ if (m_eposSet && gluProject((GLdouble)m_epos[0], (GLdouble)m_epos[1], (GLdouble)m_epos[2],
+ model, proj, view, &x, &y, &z))
+ {
+ imguiDrawText((int)x, (float)(y-25), IMGUI_ALIGN_CENTER, "End", imguiRGBA(0,0,0,220));
+ }
+}
+
+void Sample_StatMesh::drawAgent(const float* pos, float r, float h, float c, const float* col)
+{
+ glDepthMask(GL_FALSE);
+
+ // Agent dimensions.
+ glLineWidth(2.0f);
+ rcDebugDrawCylinderWire(pos[0]-r, pos[1]+0.02f, pos[2]-r, pos[0]+r, pos[1]+h, pos[2]+r, col);
+ glLineWidth(1.0f);
+
+ glColor4ub(0,0,0,196);
+ glBegin(GL_LINES);
+ glVertex3f(pos[0], pos[1]-c, pos[2]);
+ glVertex3f(pos[0], pos[1]+c, pos[2]);
+ glVertex3f(pos[0]-r/2, pos[1]+0.02f, pos[2]);
+ glVertex3f(pos[0]+r/2, pos[1]+0.02f, pos[2]);
+ glVertex3f(pos[0], pos[1]+0.02f, pos[2]-r/2);
+ glVertex3f(pos[0], pos[1]+0.02f, pos[2]+r/2);
+ glEnd();
+
+ glDepthMask(GL_TRUE);
+}
diff --git a/RecastDemo/Source/Sample_StatMeshSimple.cpp b/RecastDemo/Source/Sample_StatMeshSimple.cpp
new file mode 100644
index 0000000..9decb0a
--- /dev/null
+++ b/RecastDemo/Source/Sample_StatMeshSimple.cpp
@@ -0,0 +1,499 @@
+#define _USE_MATH_DEFINES
+#include
+#include
+#include
+#include "SDL.h"
+#include "SDL_Opengl.h"
+#include "imgui.h"
+#include "Sample.h"
+#include "Sample_StatMeshSimple.h"
+#include "Recast.h"
+#include "RecastTimer.h"
+#include "RecastDebugDraw.h"
+#include "DetourStatNavMesh.h"
+#include "DetourStatNavMeshBuilder.h"
+#include "DetourDebugDraw.h"
+
+#ifdef WIN32
+# define snprintf _snprintf
+#endif
+
+Sample_StatMeshSimple::Sample_StatMeshSimple() :
+ m_keepInterResults(false),
+ m_triflags(0),
+ m_solid(0),
+ m_chf(0),
+ m_cset(0),
+ m_polyMesh(0),
+ m_drawMode(DRAWMODE_NAVMESH)
+{
+}
+
+Sample_StatMeshSimple::~Sample_StatMeshSimple()
+{
+ cleanup();
+}
+
+void Sample_StatMeshSimple::cleanup()
+{
+ delete [] m_triflags;
+ m_triflags = 0;
+ delete m_solid;
+ m_solid = 0;
+ delete m_chf;
+ m_chf = 0;
+ delete m_cset;
+ m_cset = 0;
+ delete m_polyMesh;
+ m_polyMesh = 0;
+ toolCleanup();
+}
+
+void Sample_StatMeshSimple::handleSettings()
+{
+ Sample::handleCommonSettings();
+
+ if (imguiCheck("Keep Itermediate Results", m_keepInterResults))
+ m_keepInterResults = !m_keepInterResults;
+
+ imguiSeparator();
+}
+
+void Sample_StatMeshSimple::handleDebugMode()
+{
+ // Check which modes are valid.
+ bool valid[MAX_DRAWMODE];
+ for (int i = 0; i < MAX_DRAWMODE; ++i)
+ valid[i] = false;
+
+ if (m_verts && m_tris)
+ {
+ valid[DRAWMODE_NAVMESH] = m_navMesh != 0;
+ valid[DRAWMODE_NAVMESH_TRANS] = m_navMesh != 0;
+ valid[DRAWMODE_NAVMESH_BVTREE] = m_navMesh != 0;
+ valid[DRAWMODE_NAVMESH_INVIS] = m_navMesh != 0;
+ valid[DRAWMODE_MESH] = true;
+ valid[DRAWMODE_VOXELS] = m_solid != 0;
+ valid[DRAWMODE_VOXELS_WALKABLE] = m_solid != 0;
+ valid[DRAWMODE_COMPACT] = m_chf != 0;
+ valid[DRAWMODE_COMPACT_DISTANCE] = m_chf != 0;
+ valid[DRAWMODE_COMPACT_REGIONS] = m_chf != 0;
+ valid[DRAWMODE_REGION_CONNECTIONS] = m_cset != 0;
+ valid[DRAWMODE_RAW_CONTOURS] = m_cset != 0;
+ valid[DRAWMODE_BOTH_CONTOURS] = m_cset != 0;
+ valid[DRAWMODE_CONTOURS] = m_cset != 0;
+ valid[DRAWMODE_POLYMESH] = m_polyMesh != 0;
+ }
+
+ int unavail = 0;
+ for (int i = 0; i < MAX_DRAWMODE; ++i)
+ if (!valid[i]) unavail++;
+
+ if (unavail == MAX_DRAWMODE)
+ return;
+
+ imguiLabel("Draw");
+ if (imguiCheck("Input Mesh", m_drawMode == DRAWMODE_MESH, valid[DRAWMODE_MESH]))
+ m_drawMode = DRAWMODE_MESH;
+ if (imguiCheck("Navmesh", m_drawMode == DRAWMODE_NAVMESH, valid[DRAWMODE_NAVMESH]))
+ m_drawMode = DRAWMODE_NAVMESH;
+ if (imguiCheck("Navmesh Invis", m_drawMode == DRAWMODE_NAVMESH_INVIS, valid[DRAWMODE_NAVMESH_INVIS]))
+ m_drawMode = DRAWMODE_NAVMESH_INVIS;
+ if (imguiCheck("Navmesh Trans", m_drawMode == DRAWMODE_NAVMESH_TRANS, valid[DRAWMODE_NAVMESH_TRANS]))
+ m_drawMode = DRAWMODE_NAVMESH_TRANS;
+ if (imguiCheck("Navmesh BVTree", m_drawMode == DRAWMODE_NAVMESH_BVTREE, valid[DRAWMODE_NAVMESH_BVTREE]))
+ m_drawMode = DRAWMODE_NAVMESH_BVTREE;
+ if (imguiCheck("Voxels", m_drawMode == DRAWMODE_VOXELS, valid[DRAWMODE_VOXELS]))
+ m_drawMode = DRAWMODE_VOXELS;
+ if (imguiCheck("Walkable Voxels", m_drawMode == DRAWMODE_VOXELS_WALKABLE, valid[DRAWMODE_VOXELS_WALKABLE]))
+ m_drawMode = DRAWMODE_VOXELS_WALKABLE;
+ if (imguiCheck("Compact", m_drawMode == DRAWMODE_COMPACT, valid[DRAWMODE_COMPACT]))
+ m_drawMode = DRAWMODE_COMPACT;
+ if (imguiCheck("Compact Distance", m_drawMode == DRAWMODE_COMPACT_DISTANCE, valid[DRAWMODE_COMPACT_DISTANCE]))
+ m_drawMode = DRAWMODE_COMPACT_DISTANCE;
+ if (imguiCheck("Compact Regions", m_drawMode == DRAWMODE_COMPACT_REGIONS, valid[DRAWMODE_COMPACT_REGIONS]))
+ m_drawMode = DRAWMODE_COMPACT_REGIONS;
+ if (imguiCheck("Region Connections", m_drawMode == DRAWMODE_REGION_CONNECTIONS, valid[DRAWMODE_REGION_CONNECTIONS]))
+ m_drawMode = DRAWMODE_REGION_CONNECTIONS;
+ if (imguiCheck("Raw Contours", m_drawMode == DRAWMODE_RAW_CONTOURS, valid[DRAWMODE_RAW_CONTOURS]))
+ m_drawMode = DRAWMODE_RAW_CONTOURS;
+ if (imguiCheck("Both Contours", m_drawMode == DRAWMODE_BOTH_CONTOURS, valid[DRAWMODE_BOTH_CONTOURS]))
+ m_drawMode = DRAWMODE_BOTH_CONTOURS;
+ if (imguiCheck("Contours", m_drawMode == DRAWMODE_CONTOURS, valid[DRAWMODE_CONTOURS]))
+ m_drawMode = DRAWMODE_CONTOURS;
+ if (imguiCheck("Poly Mesh", m_drawMode == DRAWMODE_POLYMESH, valid[DRAWMODE_POLYMESH]))
+ m_drawMode = DRAWMODE_POLYMESH;
+
+ if (unavail)
+ {
+ imguiValue("Tick 'Keep Itermediate Results'");
+ imguiValue("to see more debug mode options.");
+ }
+}
+
+void Sample_StatMeshSimple::handleRender()
+{
+ if (!m_verts || !m_tris || !m_trinorms)
+ return;
+
+ float col[4];
+
+ glEnable(GL_FOG);
+ glDepthMask(GL_TRUE);
+
+ if (m_drawMode == DRAWMODE_MESH)
+ {
+ // Draw mesh
+ rcDebugDrawMeshSlope(m_verts, m_nverts, m_tris, m_trinorms, m_ntris, m_agentMaxSlope);
+ }
+ else if (m_drawMode != DRAWMODE_NAVMESH_TRANS)
+ {
+ // Draw mesh
+ rcDebugDrawMesh(m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
+ }
+
+ glDisable(GL_FOG);
+ glDepthMask(GL_FALSE);
+
+ // Draw bounds
+ col[0] = 1; col[1] = 1; col[2] = 1; col[3] = 0.5f;
+ rcDebugDrawBoxWire(m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
+
+ if (m_navMesh &&
+ (m_drawMode == DRAWMODE_NAVMESH ||
+ m_drawMode == DRAWMODE_NAVMESH_TRANS ||
+ m_drawMode == DRAWMODE_NAVMESH_BVTREE ||
+ m_drawMode == DRAWMODE_NAVMESH_INVIS))
+ {
+ int flags = NAVMESH_TOOLS;
+ if (m_drawMode != DRAWMODE_NAVMESH_INVIS)
+ flags |= NAVMESH_POLYS;
+ if (m_drawMode == DRAWMODE_NAVMESH_BVTREE)
+ flags |= NAVMESH_BVTREE;
+ toolRender(flags);
+ }
+
+ glDepthMask(GL_TRUE);
+
+ if (m_chf && m_drawMode == DRAWMODE_COMPACT)
+ rcDebugDrawCompactHeightfieldSolid(*m_chf);
+
+ if (m_chf && m_drawMode == DRAWMODE_COMPACT_DISTANCE)
+ rcDebugDrawCompactHeightfieldDistance(*m_chf);
+ if (m_chf && m_drawMode == DRAWMODE_COMPACT_REGIONS)
+ rcDebugDrawCompactHeightfieldRegions(*m_chf);
+ if (m_solid && m_drawMode == DRAWMODE_VOXELS)
+ {
+ glEnable(GL_FOG);
+ rcDebugDrawHeightfieldSolid(*m_solid);
+ glDisable(GL_FOG);
+ }
+ if (m_solid && m_drawMode == DRAWMODE_VOXELS_WALKABLE)
+ {
+ glEnable(GL_FOG);
+ rcDebugDrawHeightfieldWalkable(*m_solid);
+ glDisable(GL_FOG);
+ }
+ if (m_cset && m_drawMode == DRAWMODE_RAW_CONTOURS)
+ {
+ glDepthMask(GL_FALSE);
+ rcDebugDrawRawContours(*m_cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ glDepthMask(GL_TRUE);
+ }
+ if (m_cset && m_drawMode == DRAWMODE_BOTH_CONTOURS)
+ {
+ glDepthMask(GL_FALSE);
+ rcDebugDrawRawContours(*m_cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch, 0.5f);
+ rcDebugDrawContours(*m_cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ glDepthMask(GL_TRUE);
+ }
+ if (m_cset && m_drawMode == DRAWMODE_CONTOURS)
+ {
+ glDepthMask(GL_FALSE);
+ rcDebugDrawContours(*m_cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ glDepthMask(GL_TRUE);
+ }
+ if (m_chf && m_cset && m_drawMode == DRAWMODE_REGION_CONNECTIONS)
+ {
+ rcDebugDrawCompactHeightfieldRegions(*m_chf);
+
+ glDepthMask(GL_FALSE);
+ rcDebugDrawRegionConnections(*m_cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ glDepthMask(GL_TRUE);
+ }
+ if (m_polyMesh && m_drawMode == DRAWMODE_POLYMESH)
+ {
+ glDepthMask(GL_FALSE);
+ rcDebugDrawPolyMesh(*m_polyMesh);
+ glDepthMask(GL_TRUE);
+ }
+
+ static const float startCol[4] = { 0.5f, 0.1f, 0.0f, 0.75f };
+ static const float endCol[4] = { 0.2f, 0.4f, 0.0f, 0.75f };
+ if (m_sposSet)
+ drawAgent(m_spos, m_agentRadius, m_agentHeight, m_agentMaxClimb, startCol);
+ if (m_eposSet)
+ drawAgent(m_epos, m_agentRadius, m_agentHeight, m_agentMaxClimb, endCol);
+
+}
+
+void Sample_StatMeshSimple::handleRenderOverlay(double* proj, double* model, int* view)
+{
+ toolRenderOverlay(proj, model, view);
+}
+
+void Sample_StatMeshSimple::handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax)
+{
+ Sample::handleMeshChanged(verts, nverts, tris, trinorms, ntris, bmin, bmax);
+ toolCleanup();
+ toolReset();
+}
+
+bool Sample_StatMeshSimple::handleBuild()
+{
+ if (!m_verts || ! m_tris)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
+ return false;
+ }
+
+ cleanup();
+ toolCleanup();
+
+ // Init build configuration from GUI
+ memset(&m_cfg, 0, sizeof(m_cfg));
+ m_cfg.cs = m_cellSize;
+ m_cfg.ch = m_cellHeight;
+ m_cfg.walkableSlopeAngle = m_agentMaxSlope;
+ m_cfg.walkableHeight = (int)ceilf(m_agentHeight / m_cfg.ch);
+ m_cfg.walkableClimb = (int)ceilf(m_agentMaxClimb / m_cfg.ch);
+ m_cfg.walkableRadius = (int)ceilf(m_agentRadius / m_cfg.cs);
+ m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
+ m_cfg.maxSimplificationError = m_edgeMaxError;
+ m_cfg.minRegionSize = (int)rcSqr(m_regionMinSize);
+ m_cfg.mergeRegionSize = (int)rcSqr(m_regionMergeSize);
+ m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
+
+ // Set the area where the navigation will be build.
+ // Here the bounds of the input mesh are used, but the
+ // area could be specified by an user defined box, etc.
+ vcopy(m_cfg.bmin, m_bmin);
+ vcopy(m_cfg.bmax, m_bmax);
+ rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
+
+ // Reset build times gathering.
+ memset(&m_buildTimes, 0, sizeof(m_buildTimes));
+ rcSetBuildTimes(&m_buildTimes);
+
+ // Start the build process.
+ rcTimeVal totStartTime = rcGetPerformanceTimer();
+
+ if (rcGetLog())
+ {
+ rcGetLog()->log(RC_LOG_PROGRESS, "Building navigation:");
+ rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", m_nverts/1000.0f, m_ntris/1000.0f);
+ }
+
+ // Allocate voxel heighfield where we rasterize our input data to.
+ m_solid = new rcHeightfield;
+ if (!m_solid)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'solid'.");
+ return false;
+ }
+ if (!rcCreateHeightfield(*m_solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not create solid heightfield.");
+ return false;
+ }
+
+ // Allocate array that can hold triangle flags.
+ // If you have multiple meshes you need to process, allocate
+ // and array which can hold the max number of triangles you need to process.
+ m_triflags = new unsigned char[m_ntris];
+ if (!m_triflags)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'triangleFlags' (%d).", m_ntris);
+ return false;
+ }
+
+
+ // Find triangles which are walkable based on their slope and rasterize them.
+ // If your input data is multiple meshes, you can transform them here, calculate
+ // the flags for each of the meshes and rasterize them.
+ memset(m_triflags, 0, m_ntris*sizeof(unsigned char));
+ rcMarkWalkableTriangles(m_cfg.walkableSlopeAngle, m_verts, m_nverts, m_tris, m_ntris, m_triflags);
+ rcRasterizeTriangles(m_verts, m_nverts, m_tris, m_triflags, m_ntris, *m_solid);
+
+ if (!m_keepInterResults)
+ {
+ delete [] m_triflags;
+ m_triflags = 0;
+ }
+
+ // Once all geoemtry is rasterized, we do initial pass of filtering to
+ // remove unwanted overhangs caused by the conservative rasterization
+ // as well as filter spans where the character cannot possibly stand.
+ rcFilterLedgeSpans(m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid);
+ rcFilterWalkableLowHeightSpans(m_cfg.walkableHeight, *m_solid);
+
+ // Compact the heightfield so that it is faster to handle from now on.
+ // This will result more cache coherent data as well as the neighbours
+ // between walkable cells will be calculated.
+ m_chf = new rcCompactHeightfield;
+ if (!m_chf)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'chf'.");
+ return false;
+ }
+ if (!rcBuildCompactHeightfield(m_cfg.walkableHeight, m_cfg.walkableClimb, RC_WALKABLE, *m_solid, *m_chf))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not build compact data.");
+ return false;
+ }
+
+ if (!m_keepInterResults)
+ {
+ delete m_solid;
+ m_solid = 0;
+ }
+
+ // Prepare for region partitioning, by calculating distance field along the walkable surface.
+ if (!rcBuildDistanceField(*m_chf))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
+ return false;
+ }
+
+ // Partition the walkable surface into simple regions without holes.
+ if (!rcBuildRegions(*m_chf, m_cfg.walkableRadius, m_cfg.borderSize, m_cfg.minRegionSize, m_cfg.mergeRegionSize))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
+ }
+
+ // Create contours.
+ m_cset = new rcContourSet;
+ if (!m_cset)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'cset'.");
+ return false;
+ }
+ if (!rcBuildContours(*m_chf, m_cfg.maxSimplificationError, m_cfg.maxEdgeLen, *m_cset))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not create contours.");
+ return false;
+ }
+
+ if (!m_keepInterResults)
+ {
+ delete m_chf;
+ m_chf = 0;
+ }
+
+ // Build polygon navmesh from the contours.
+ m_polyMesh = new rcPolyMesh;
+ if (!m_polyMesh)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'polyMesh'.");
+ return false;
+ }
+ if (!rcBuildPolyMesh(*m_cset, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch, m_cfg.maxVertsPerPoly, *m_polyMesh))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not triangulate contours.");
+ return false;
+ }
+
+ if (!m_keepInterResults)
+ {
+ delete m_cset;
+ m_cset = 0;
+ }
+
+ if (m_cfg.maxVertsPerPoly == DT_STAT_VERTS_PER_POLYGON)
+ {
+ unsigned char* navData = 0;
+ int navDataSize = 0;
+ if (!dtCreateNavMeshData(m_polyMesh->verts, m_polyMesh->nverts,
+ m_polyMesh->polys, m_polyMesh->npolys, m_polyMesh->nvp,
+ m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch, &navData, &navDataSize))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
+ return false;
+ }
+
+ m_navMesh = new dtStatNavMesh;
+ if (!m_navMesh)
+ {
+ delete [] navData;
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "Could not create Detour navmesh");
+ return false;
+ }
+
+ if (!m_navMesh->init(navData, navDataSize, true))
+ {
+ delete [] navData;
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "Could not init Detour navmesh");
+ return false;
+ }
+ }
+
+ rcTimeVal totEndTime = rcGetPerformanceTimer();
+
+ // Show performance stats.
+ if (rcGetLog())
+ {
+ const float pc = 100.0f / rcGetDeltaTimeUsec(totStartTime, totEndTime);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Rasterize: %.1fms (%.1f%%)", m_buildTimes.rasterizeTriangles/1000.0f, m_buildTimes.rasterizeTriangles*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Compact: %.1fms (%.1f%%)", m_buildTimes.buildCompact/1000.0f, m_buildTimes.buildCompact*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Border: %.1fms (%.1f%%)", m_buildTimes.filterBorder/1000.0f, m_buildTimes.filterBorder*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Walkable: %.1fms (%.1f%%)", m_buildTimes.filterWalkable/1000.0f, m_buildTimes.filterWalkable*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Reachable: %.1fms (%.1f%%)", m_buildTimes.filterMarkReachable/1000.0f, m_buildTimes.filterMarkReachable*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Distancefield: %.1fms (%.1f%%)", m_buildTimes.buildDistanceField/1000.0f, m_buildTimes.buildDistanceField*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - distance: %.1fms (%.1f%%)", m_buildTimes.buildDistanceFieldDist/1000.0f, m_buildTimes.buildDistanceFieldDist*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - blur: %.1fms (%.1f%%)", m_buildTimes.buildDistanceFieldBlur/1000.0f, m_buildTimes.buildDistanceFieldBlur*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Regions: %.1fms (%.1f%%)", m_buildTimes.buildRegions/1000.0f, m_buildTimes.buildRegions*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - watershed: %.1fms (%.1f%%)", m_buildTimes.buildRegionsReg/1000.0f, m_buildTimes.buildRegionsReg*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - expand: %.1fms (%.1f%%)", m_buildTimes.buildRegionsExp/1000.0f, m_buildTimes.buildRegionsExp*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - find catchment basins: %.1fms (%.1f%%)", m_buildTimes.buildRegionsFlood/1000.0f, m_buildTimes.buildRegionsFlood*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - filter: %.1fms (%.1f%%)", m_buildTimes.buildRegionsFilter/1000.0f, m_buildTimes.buildRegionsFilter*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Contours: %.1fms (%.1f%%)", m_buildTimes.buildContours/1000.0f, m_buildTimes.buildContours*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - trace: %.1fms (%.1f%%)", m_buildTimes.buildContoursTrace/1000.0f, m_buildTimes.buildContoursTrace*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - simplify: %.1fms (%.1f%%)", m_buildTimes.buildContoursSimplify/1000.0f, m_buildTimes.buildContoursSimplify*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Fixup contours: %.1fms (%.1f%%)", m_buildTimes.fixupContours/1000.0f, m_buildTimes.fixupContours*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Polymesh: %.1fms (%.1f%%)", m_buildTimes.buildPolymesh/1000.0f, m_buildTimes.buildPolymesh*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Polymesh: Verts:%d Polys:%d", m_polyMesh->nverts, m_polyMesh->npolys);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "TOTAL: %.1fms", rcGetDeltaTimeUsec(totStartTime, totEndTime)/1000.0f);
+ }
+
+ toolRecalc();
+
+ return true;
+}
diff --git a/RecastDemo/Source/Sample_StatMeshTiled.cpp b/RecastDemo/Source/Sample_StatMeshTiled.cpp
new file mode 100644
index 0000000..c245a89
--- /dev/null
+++ b/RecastDemo/Source/Sample_StatMeshTiled.cpp
@@ -0,0 +1,973 @@
+#define _USE_MATH_DEFINES
+#include
+#include
+#include
+#include "SDL.h"
+#include "SDL_Opengl.h"
+#include "imgui.h"
+#include "Sample.h"
+#include "Sample_StatMeshTiled.h"
+#include "Recast.h"
+#include "RecastTimer.h"
+#include "RecastDebugDraw.h"
+#include "DetourStatNavMesh.h"
+#include "DetourStatNavMeshBuilder.h"
+#include "DetourDebugDraw.h"
+
+#ifdef WIN32
+# define snprintf _snprintf
+#endif
+
+Sample_StatMeshTiled::Sample_StatMeshTiled() :
+ m_keepInterResults(false),
+ m_measurePerTileTimings(false),
+ m_tileSize(64),
+ m_chunkyMesh(0),
+ m_tileSet(0),
+ m_polyMesh(0),
+ m_drawMode(DRAWMODE_NAVMESH),
+ m_statTimePerTileSamples(0),
+ m_statPolysPerTileSamples(0)
+{
+}
+
+Sample_StatMeshTiled::~Sample_StatMeshTiled()
+{
+ cleanup();
+}
+
+void Sample_StatMeshTiled::cleanup()
+{
+ delete m_chunkyMesh;
+ m_chunkyMesh = 0;
+ delete m_tileSet;
+ m_tileSet = 0;
+ delete m_polyMesh;
+ m_polyMesh = 0;
+ toolCleanup();
+ m_statTimePerTileSamples = 0;
+ m_statPolysPerTileSamples = 0;
+}
+
+void Sample_StatMeshTiled::handleSettings()
+{
+ Sample::handleCommonSettings();
+
+ imguiLabel("Tiling");
+ imguiSlider("TileSize", &m_tileSize, 16.0f, 1024.0f, 16.0f);
+
+ char text[64];
+ int gw = 0, gh = 0;
+ rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
+ const int ts = (int)m_tileSize;
+ const int tw = (gw + ts-1) / ts;
+ const int th = (gh + ts-1) / ts;
+ snprintf(text, 64, "Tiles %d x %d", tw, th);
+ imguiValue(text);
+
+ imguiSeparator();
+ if (imguiCheck("Keep Itermediate Results", m_keepInterResults))
+ m_keepInterResults = !m_keepInterResults;
+ if (imguiCheck("Measure Per Tile Timings", m_measurePerTileTimings))
+ m_measurePerTileTimings = !m_measurePerTileTimings;
+
+ imguiSeparator();
+}
+
+void Sample_StatMeshTiled::handleDebugMode()
+{
+ // Check which modes are valid.
+ bool valid[MAX_DRAWMODE];
+ for (int i = 0; i < MAX_DRAWMODE; ++i)
+ valid[i] = false;
+
+ bool hasChf = false;
+ bool hasSolid = false;
+ bool hasCset = false;
+ if (m_tileSet)
+ {
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].solid) hasSolid = true;
+ if (m_tileSet->tiles[i].chf) hasChf = true;
+ if (m_tileSet->tiles[i].cset) hasCset = true;
+ }
+ }
+
+ if (m_verts && m_tris)
+ {
+ valid[DRAWMODE_NAVMESH] = m_navMesh != 0;
+ valid[DRAWMODE_NAVMESH_TRANS] = m_navMesh != 0;
+ valid[DRAWMODE_NAVMESH_BVTREE] = m_navMesh != 0;
+ valid[DRAWMODE_NAVMESH_INVIS] = m_navMesh != 0;
+ valid[DRAWMODE_MESH] = true;
+ valid[DRAWMODE_VOXELS] = hasSolid;
+ valid[DRAWMODE_VOXELS_WALKABLE] = hasSolid;
+ valid[DRAWMODE_COMPACT] = hasChf;
+ valid[DRAWMODE_COMPACT_DISTANCE] = hasChf;
+ valid[DRAWMODE_COMPACT_REGIONS] = hasChf;
+ valid[DRAWMODE_REGION_CONNECTIONS] = hasCset;
+ valid[DRAWMODE_RAW_CONTOURS] = hasCset;
+ valid[DRAWMODE_BOTH_CONTOURS] = hasCset;
+ valid[DRAWMODE_CONTOURS] = hasCset;
+ valid[DRAWMODE_POLYMESH] = m_polyMesh != 0;
+ }
+
+ int unavail = 0;
+ for (int i = 0; i < MAX_DRAWMODE; ++i)
+ if (!valid[i]) unavail++;
+
+ if (unavail == MAX_DRAWMODE)
+ return;
+
+ imguiLabel("Draw");
+ if (imguiCheck("Input Mesh", m_drawMode == DRAWMODE_MESH, valid[DRAWMODE_MESH]))
+ m_drawMode = DRAWMODE_MESH;
+ if (imguiCheck("Navmesh", m_drawMode == DRAWMODE_NAVMESH, valid[DRAWMODE_NAVMESH]))
+ m_drawMode = DRAWMODE_NAVMESH;
+ if (imguiCheck("Navmesh Invis", m_drawMode == DRAWMODE_NAVMESH_INVIS, valid[DRAWMODE_NAVMESH_INVIS]))
+ m_drawMode = DRAWMODE_NAVMESH_INVIS;
+ if (imguiCheck("Navmesh Trans", m_drawMode == DRAWMODE_NAVMESH_TRANS, valid[DRAWMODE_NAVMESH_TRANS]))
+ m_drawMode = DRAWMODE_NAVMESH_TRANS;
+ if (imguiCheck("Navmesh BVTree", m_drawMode == DRAWMODE_NAVMESH_BVTREE, valid[DRAWMODE_NAVMESH_BVTREE]))
+ m_drawMode = DRAWMODE_NAVMESH_BVTREE;
+ if (imguiCheck("Voxels", m_drawMode == DRAWMODE_VOXELS, valid[DRAWMODE_VOXELS]))
+ m_drawMode = DRAWMODE_VOXELS;
+ if (imguiCheck("Walkable Voxels", m_drawMode == DRAWMODE_VOXELS_WALKABLE, valid[DRAWMODE_VOXELS_WALKABLE]))
+ m_drawMode = DRAWMODE_VOXELS_WALKABLE;
+ if (imguiCheck("Compact", m_drawMode == DRAWMODE_COMPACT, valid[DRAWMODE_COMPACT]))
+ m_drawMode = DRAWMODE_COMPACT;
+ if (imguiCheck("Compact Distance", m_drawMode == DRAWMODE_COMPACT_DISTANCE, valid[DRAWMODE_COMPACT_DISTANCE]))
+ m_drawMode = DRAWMODE_COMPACT_DISTANCE;
+ if (imguiCheck("Compact Regions", m_drawMode == DRAWMODE_COMPACT_REGIONS, valid[DRAWMODE_COMPACT_REGIONS]))
+ m_drawMode = DRAWMODE_COMPACT_REGIONS;
+ if (imguiCheck("Region Connections", m_drawMode == DRAWMODE_REGION_CONNECTIONS, valid[DRAWMODE_REGION_CONNECTIONS]))
+ m_drawMode = DRAWMODE_REGION_CONNECTIONS;
+ if (imguiCheck("Raw Contours", m_drawMode == DRAWMODE_RAW_CONTOURS, valid[DRAWMODE_RAW_CONTOURS]))
+ m_drawMode = DRAWMODE_RAW_CONTOURS;
+ if (imguiCheck("Both Contours", m_drawMode == DRAWMODE_BOTH_CONTOURS, valid[DRAWMODE_BOTH_CONTOURS]))
+ m_drawMode = DRAWMODE_BOTH_CONTOURS;
+ if (imguiCheck("Contours", m_drawMode == DRAWMODE_CONTOURS, valid[DRAWMODE_CONTOURS]))
+ m_drawMode = DRAWMODE_CONTOURS;
+ if (imguiCheck("Poly Mesh", m_drawMode == DRAWMODE_POLYMESH, valid[DRAWMODE_POLYMESH]))
+ m_drawMode = DRAWMODE_POLYMESH;
+
+ if (unavail)
+ {
+ imguiValue("Tick 'Keep Itermediate Results'");
+ imguiValue("to see more debug mode options.");
+ }
+}
+
+void Sample_StatMeshTiled::handleRender()
+{
+ if (!m_verts || !m_tris || !m_trinorms)
+ return;
+
+ float col[4];
+
+ glEnable(GL_FOG);
+ glDepthMask(GL_TRUE);
+
+ if (m_drawMode == DRAWMODE_MESH)
+ {
+ // Draw mesh
+ rcDebugDrawMeshSlope(m_verts, m_nverts, m_tris, m_trinorms, m_ntris, m_agentMaxSlope);
+ }
+ else if (m_drawMode != DRAWMODE_NAVMESH_TRANS)
+ {
+ // Draw mesh
+ rcDebugDrawMesh(m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
+ }
+
+ glDisable(GL_FOG);
+ glDepthMask(GL_FALSE);
+
+ // Draw bounds
+ col[0] = 1; col[1] = 1; col[2] = 1; col[3] = 0.5f;
+ rcDebugDrawBoxWire(m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
+
+ // Tiling grid.
+ const int ts = (int)m_tileSize;
+ int gw = 0, gh = 0;
+ rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
+ int tw = (gw + ts-1) / ts;
+ int th = (gh + ts-1) / ts;
+ const float s = ts*m_cellSize;
+ glBegin(GL_LINES);
+ glColor4ub(0,0,0,64);
+ for (int y = 0; y < th; ++y)
+ {
+ for (int x = 0; x < tw; ++x)
+ {
+ float fx, fy, fz;
+ fx = m_bmin[0] + x*s;
+ fy = m_bmin[1];
+ fz = m_bmin[2] + y*s;
+
+ glVertex3f(fx,fy,fz);
+ glVertex3f(fx+s,fy,fz);
+ glVertex3f(fx,fy,fz);
+ glVertex3f(fx,fy,fz+s);
+
+ if (x+1 >= tw)
+ {
+ glVertex3f(fx+s,fy,fz);
+ glVertex3f(fx+s,fy,fz+s);
+ }
+ if (y+1 >= th)
+ {
+ glVertex3f(fx,fy,fz+s);
+ glVertex3f(fx+s,fy,fz+s);
+ }
+ }
+ }
+ glEnd();
+
+
+ if (m_navMesh &&
+ (m_drawMode == DRAWMODE_NAVMESH ||
+ m_drawMode == DRAWMODE_NAVMESH_TRANS ||
+ m_drawMode == DRAWMODE_NAVMESH_BVTREE ||
+ m_drawMode == DRAWMODE_NAVMESH_INVIS))
+ {
+ int flags = NAVMESH_TOOLS;
+ if (m_drawMode != DRAWMODE_NAVMESH_INVIS)
+ flags |= NAVMESH_POLYS;
+ if (m_drawMode == DRAWMODE_NAVMESH_BVTREE)
+ flags |= NAVMESH_BVTREE;
+ toolRender(flags);
+ }
+
+ glDepthMask(GL_TRUE);
+
+ if (m_tileSet)
+ {
+ if (m_drawMode == DRAWMODE_COMPACT)
+ {
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].chf)
+ rcDebugDrawCompactHeightfieldSolid(*m_tileSet->tiles[i].chf);
+ }
+ }
+
+ if (m_drawMode == DRAWMODE_COMPACT_DISTANCE)
+ {
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].chf)
+ rcDebugDrawCompactHeightfieldDistance(*m_tileSet->tiles[i].chf);
+ }
+ }
+ if (m_drawMode == DRAWMODE_COMPACT_REGIONS)
+ {
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].chf)
+ rcDebugDrawCompactHeightfieldRegions(*m_tileSet->tiles[i].chf);
+ }
+ }
+
+ if (m_drawMode == DRAWMODE_VOXELS)
+ {
+ glEnable(GL_FOG);
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].solid)
+ rcDebugDrawHeightfieldSolid(*m_tileSet->tiles[i].solid);
+ }
+ glDisable(GL_FOG);
+ }
+ if (m_drawMode == DRAWMODE_VOXELS_WALKABLE)
+ {
+ glEnable(GL_FOG);
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].solid)
+ rcDebugDrawHeightfieldWalkable(*m_tileSet->tiles[i].solid);
+ }
+ glDisable(GL_FOG);
+ }
+ if (m_drawMode == DRAWMODE_RAW_CONTOURS)
+ {
+ glDepthMask(GL_FALSE);
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].cset)
+ rcDebugDrawRawContours(*m_tileSet->tiles[i].cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ }
+ glDepthMask(GL_TRUE);
+ }
+ if (m_drawMode == DRAWMODE_BOTH_CONTOURS)
+ {
+ glDepthMask(GL_FALSE);
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].cset)
+ {
+ rcDebugDrawRawContours(*m_tileSet->tiles[i].cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch, 0.5f);
+ rcDebugDrawContours(*m_tileSet->tiles[i].cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ }
+ }
+ glDepthMask(GL_TRUE);
+ }
+ if (m_drawMode == DRAWMODE_CONTOURS)
+ {
+ glDepthMask(GL_FALSE);
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].cset)
+ rcDebugDrawContours(*m_tileSet->tiles[i].cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ }
+ glDepthMask(GL_TRUE);
+ }
+ if (m_drawMode == DRAWMODE_REGION_CONNECTIONS)
+ {
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].chf)
+ rcDebugDrawCompactHeightfieldRegions(*m_tileSet->tiles[i].chf);
+ }
+
+ glDepthMask(GL_FALSE);
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].cset)
+ rcDebugDrawRegionConnections(*m_tileSet->tiles[i].cset, m_cfg.bmin, m_cfg.cs, m_cfg.ch);
+ }
+ glDepthMask(GL_TRUE);
+ }
+ if (m_polyMesh && m_drawMode == DRAWMODE_POLYMESH)
+ {
+ glDepthMask(GL_FALSE);
+ rcDebugDrawPolyMesh(*m_polyMesh);
+ glDepthMask(GL_TRUE);
+ }
+ }
+
+ static const float startCol[4] = { 0.5f, 0.1f, 0.0f, 0.75f };
+ static const float endCol[4] = { 0.2f, 0.4f, 0.0f, 0.75f };
+ if (m_sposSet)
+ drawAgent(m_spos, m_agentRadius, m_agentHeight, m_agentMaxClimb, startCol);
+ if (m_eposSet)
+ drawAgent(m_epos, m_agentRadius, m_agentHeight, m_agentMaxClimb, endCol);
+
+}
+
+static float nicenum(float x, int round)
+{
+ float expv = floorf(log10f(x));
+ float f = x / powf(10.0f, expv);
+ float nf;
+ if (round)
+ {
+ if (f < 1.5f) nf = 1.0f;
+ else if (f < 3.0f) nf = 2.0f;
+ else if (f < 7.0f) nf = 5.0f;
+ else nf = 10.0f;
+ }
+ else
+ {
+ if (f <= 1.0f) nf = 1.0f;
+ else if (f <= 2.0f) nf = 2.0f;
+ else if (f <= 5.0f) nf = 5.0f;
+ else nf = 10.0f;
+ }
+ return nf*powf(10.0f, expv);
+}
+
+static void drawLabels(int x, int y, int w, int h,
+ int nticks, float vmin, float vmax, const char* unit)
+{
+ char str[8], temp[32];
+
+ float range = nicenum(vmax-vmin, 0);
+ float d = nicenum(range/(float)(nticks-1), 1);
+ float graphmin = floorf(vmin/d)*d;
+ float graphmax = ceilf(vmax/d)*d;
+ int nfrac = (int)-floorf(log10f(d));
+ if (nfrac < 0) nfrac = 0;
+ snprintf(str, 6, "%%.%df %%s", nfrac);
+
+ for (float v = graphmin; v < graphmax+d/2; v += d)
+ {
+ float lx = x + (v-vmin)/(vmax-vmin)*w;
+ if (lx < 0 || lx > w) continue;
+ snprintf(temp, 20, str, v, unit);
+ imguiDrawText((int)lx+2, (int)y+2, IMGUI_ALIGN_LEFT, temp, imguiRGBA(255,255,255));
+ glColor4ub(0,0,0,64);
+ glBegin(GL_LINES);
+ glVertex2f(lx,(float)y);
+ glVertex2f(lx,(float)(y+h));
+ glEnd();
+ }
+}
+
+static void drawGraph(const char* name, int x, int y, int w, int h, float sd,
+ const int* samples, int n, int nsamples, const char* unit)
+{
+ char text[64];
+ int first, last, maxval;
+ first = 0;
+ last = n-1;
+ while (first < n && samples[first] == 0)
+ first++;
+ while (last >= 0 && samples[last] == 0)
+ last--;
+ if (first == last)
+ return;
+ maxval = 1;
+ for (int i = first; i <= last; ++i)
+ {
+ if (samples[i] > maxval)
+ maxval = samples[i];
+ }
+ const float sx = (float)w / (float)(last-first);
+ const float sy = (float)h / (float)maxval;
+
+ glBegin(GL_QUADS);
+ glColor4ub(32,32,32,64);
+ glVertex2i(x,y);
+ glVertex2i(x+w,y);
+ glVertex2i(x+w,y+h);
+ glVertex2i(x,y+h);
+ glEnd();
+
+ glColor4ub(255,255,255,64);
+ glBegin(GL_LINES);
+ for (int i = 0; i <= 4; ++i)
+ {
+ int yy = y+i*h/4;
+ glVertex2i(x,yy);
+ glVertex2i(x+w,yy);
+ }
+ glEnd();
+
+ glColor4ub(0,196,255,255);
+ glBegin(GL_LINE_STRIP);
+ for (int i = first; i <= last; ++i)
+ {
+ float fx = x + (i-first)*sx;
+ float fy = y + samples[i]*sy;
+ glVertex2f(fx,fy);
+ }
+ glEnd();
+
+ snprintf(text,64,"%d", maxval);
+ imguiDrawText((int)x+w-2, (int)y+h-20, IMGUI_ALIGN_RIGHT, text, imguiRGBA(0,0,0));
+ imguiDrawText((int)x+2, (int)y+h-20, IMGUI_ALIGN_LEFT, name, imguiRGBA(255,255,255));
+
+ drawLabels(x, y, w, h, 10, first*sd, last*sd, unit);
+}
+
+void Sample_StatMeshTiled::handleRenderOverlay(double* proj, double* model, int* view)
+{
+ toolRenderOverlay(proj, model, view);
+
+ if (m_measurePerTileTimings)
+ {
+ if (m_statTimePerTileSamples)
+ drawGraph("Build Time/Tile", 10, 10, 500, 100, 1.0f, m_statTimePerTile, MAX_STAT_BUCKETS, m_statTimePerTileSamples, "ms");
+
+ if (m_statPolysPerTileSamples)
+ drawGraph("Polygons/Tile", 10, 120, 500, 100, 1.0f, m_statPolysPerTile, MAX_STAT_BUCKETS, m_statPolysPerTileSamples, "");
+
+ int validTiles = 0;
+ if (m_tileSet)
+ {
+ for (int i = 0; i < m_tileSet->width*m_tileSet->height; ++i)
+ {
+ if (m_tileSet->tiles[i].buildTime > 0)
+ validTiles++;
+ }
+ }
+ char text[64];
+ snprintf(text,64,"Tiles %d\n", validTiles);
+ imguiDrawText(10, 240, IMGUI_ALIGN_LEFT, text, imguiRGBA(255,255,255));
+ }
+}
+
+void Sample_StatMeshTiled::handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax)
+{
+ Sample::handleMeshChanged(verts, nverts, tris, trinorms, ntris, bmin, bmax);
+ toolCleanup();
+ toolReset();
+ m_statTimePerTileSamples = 0;
+ m_statPolysPerTileSamples = 0;
+}
+
+bool Sample_StatMeshTiled::handleBuild()
+{
+ if (!m_verts || ! m_tris)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
+ return false;
+ }
+
+ if (m_measurePerTileTimings)
+ {
+ memset(m_statPolysPerTile, 0, sizeof(m_statPolysPerTile));
+ memset(m_statTimePerTile, 0, sizeof(m_statTimePerTile));
+ m_statPolysPerTileSamples = 0;
+ m_statTimePerTileSamples = 0;
+ }
+
+ cleanup();
+ toolCleanup();
+ toolReset();
+
+ // Init build configuration from GUI
+ memset(&m_cfg, 0, sizeof(m_cfg));
+ m_cfg.cs = m_cellSize;
+ m_cfg.ch = m_cellHeight;
+ m_cfg.walkableSlopeAngle = m_agentMaxSlope;
+ m_cfg.walkableHeight = (int)ceilf(m_agentHeight / m_cfg.ch);
+ m_cfg.walkableClimb = (int)ceilf(m_agentMaxClimb / m_cfg.ch);
+ m_cfg.walkableRadius = (int)ceilf(m_agentRadius / m_cfg.cs);
+ m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
+ m_cfg.maxSimplificationError = m_edgeMaxError;
+ m_cfg.minRegionSize = (int)rcSqr(m_regionMinSize);
+ m_cfg.mergeRegionSize = (int)rcSqr(m_regionMergeSize);
+ m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
+ m_cfg.tileSize = (int)m_tileSize;
+ m_cfg.borderSize = m_cfg.walkableRadius*2 + 2; // Reserve enough padding.
+
+ // Set the area where the navigation will be build.
+ // Here the bounds of the input mesh are used, but the
+ // area could be specified by an user defined box, etc.
+ vcopy(m_cfg.bmin, m_bmin);
+ vcopy(m_cfg.bmax, m_bmax);
+ rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
+
+ // Reset build times gathering.
+ memset(&m_buildTimes, 0, sizeof(m_buildTimes));
+ rcSetBuildTimes(&m_buildTimes);
+
+ // Start the build process.
+ rcTimeVal totStartTime = rcGetPerformanceTimer();
+
+ // Calculate the number of tiles in the output and initialize tiles.
+ m_tileSet = new TileSet;
+ if (!m_tileSet)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'tileSet'.");
+ return false;
+ }
+ vcopy(m_tileSet->bmin, m_cfg.bmin);
+ vcopy(m_tileSet->bmax, m_cfg.bmax);
+ m_tileSet->cs = m_cfg.cs;
+ m_tileSet->ch = m_cfg.ch;
+ m_tileSet->width = (m_cfg.width + m_cfg.tileSize-1) / m_cfg.tileSize;
+ m_tileSet->height = (m_cfg.height + m_cfg.tileSize-1) / m_cfg.tileSize;
+ m_tileSet->tiles = new Tile[m_tileSet->height * m_tileSet->width];
+ if (!m_tileSet->tiles)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'tileSet->tiles' (%d).", m_tileSet->height * m_tileSet->width);
+ return false;
+ }
+
+ // Build chunky trimesh for local polygon queries.
+ rcTimeVal chunkyStartTime = rcGetPerformanceTimer();
+ m_chunkyMesh = new rcChunkyTriMesh;
+ if (!m_chunkyMesh)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'm_chunkyMesh'.");
+ return false;
+ }
+ if (!rcCreateChunkyTriMesh(m_verts, m_tris, m_ntris, 256, m_chunkyMesh))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not build chunky mesh.");
+ return false;
+ }
+ rcTimeVal chunkyEndTime = rcGetPerformanceTimer();
+
+ if (rcGetLog())
+ {
+ rcGetLog()->log(RC_LOG_PROGRESS, "Building navigation:");
+ rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d tiles", m_tileSet->width, m_tileSet->height);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - %.1f verts, %.1f tris", m_nverts/1000.0f, m_ntris/1000.0f);
+ }
+
+ // Initialize per tile config.
+ rcConfig tileCfg;
+ memcpy(&tileCfg, &m_cfg, sizeof(rcConfig));
+ tileCfg.width = m_cfg.tileSize + m_cfg.borderSize*2;
+ tileCfg.height = m_cfg.tileSize + m_cfg.borderSize*2;
+
+ // Allocate array that can hold triangle flags for all geom chunks.
+ unsigned char* triangleFlags = new unsigned char[m_chunkyMesh->maxTrisPerChunk];
+ if (!triangleFlags)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'triangleFlags' (%d).", m_chunkyMesh->maxTrisPerChunk);
+ return false;
+ }
+
+ rcHeightfield* solid = 0;
+ rcCompactHeightfield* chf = 0;
+ rcContourSet* cset = 0;
+
+ for (int y = 0; y < m_tileSet->height; ++y)
+ {
+ for (int x = 0; x < m_tileSet->width; ++x)
+ {
+ rcTimeVal startTime = rcGetPerformanceTimer();
+
+ Tile& tile = m_tileSet->tiles[x + y*m_tileSet->width];
+
+ // Calculate the per tile bounding box.
+ tileCfg.bmin[0] = m_cfg.bmin[0] + (x*m_cfg.tileSize - m_cfg.borderSize)*m_cfg.cs;
+ tileCfg.bmin[2] = m_cfg.bmin[2] + (y*m_cfg.tileSize - m_cfg.borderSize)*m_cfg.cs;
+ tileCfg.bmax[0] = m_cfg.bmin[0] + ((x+1)*m_cfg.tileSize + m_cfg.borderSize)*m_cfg.cs;
+ tileCfg.bmax[2] = m_cfg.bmin[2] + ((y+1)*m_cfg.tileSize + m_cfg.borderSize)*m_cfg.cs;
+
+ delete solid;
+ delete chf;
+ solid = 0;
+ chf = 0;
+
+ float tbmin[2], tbmax[2];
+ tbmin[0] = tileCfg.bmin[0];
+ tbmin[1] = tileCfg.bmin[2];
+ tbmax[0] = tileCfg.bmax[0];
+ tbmax[1] = tileCfg.bmax[2];
+ int cid[256];// TODO: Make grow when returning too many items.
+ const int ncid = rcGetChunksInRect(m_chunkyMesh, tbmin, tbmax, cid, 256);
+ if (!ncid)
+ continue;
+
+ solid = new rcHeightfield;
+ if (!solid)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Out of memory 'solid'.", x, y);
+ continue;
+ }
+ if (!rcCreateHeightfield(*solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not create solid heightfield.", x, y);
+ continue;
+ }
+
+ for (int i = 0; i < ncid; ++i)
+ {
+ const rcChunkyTriMeshNode& node = m_chunkyMesh->nodes[cid[i]];
+ const int* tris = &m_chunkyMesh->tris[node.i*3];
+ const int ntris = node.n;
+
+ memset(triangleFlags, 0, ntris*sizeof(unsigned char));
+ rcMarkWalkableTriangles(tileCfg.walkableSlopeAngle,
+ m_verts, m_nverts, tris, ntris, triangleFlags);
+
+ rcRasterizeTriangles(m_verts, m_nverts, tris, triangleFlags, ntris, *solid);
+ }
+
+ rcFilterLedgeSpans(tileCfg.walkableHeight, tileCfg.walkableClimb, *solid);
+
+ rcFilterWalkableLowHeightSpans(tileCfg.walkableHeight, *solid);
+
+ chf = new rcCompactHeightfield;
+ if (!chf)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Out of memory 'chf'.", x, y);
+ continue;
+ }
+ if (!rcBuildCompactHeightfield(tileCfg.walkableHeight, tileCfg.walkableClimb,
+ RC_WALKABLE, *solid, *chf))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not build compact data.", x, y);
+ continue;
+ }
+
+ if (!rcBuildDistanceField(*chf))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not build distance fields.", x, y);
+ continue;
+ }
+
+ if (!rcBuildRegions(*chf, tileCfg.walkableRadius, tileCfg.borderSize, tileCfg.minRegionSize, tileCfg.mergeRegionSize))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not build regions.", x, y);
+ continue;
+ }
+
+ cset = new rcContourSet;
+ if (!cset)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Out of memory 'cset'.", x, y);
+ continue;
+ }
+ if (!rcBuildContours(*chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *cset))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not create contours.", x, y);
+ continue;
+ }
+
+ if (m_keepInterResults)
+ {
+ tile.solid = solid;
+ solid = 0;
+ tile.chf = chf;
+ chf = 0;
+ }
+
+ if (!cset->nconts)
+ {
+ delete cset;
+ cset = 0;
+ continue;
+ }
+
+ tile.cset = cset;
+ // Offset the vertices in the cset.
+ rcTranslateContours(tile.cset, x*tileCfg.tileSize - tileCfg.borderSize, 0, y*tileCfg.tileSize - tileCfg.borderSize);
+
+ rcTimeVal endTime = rcGetPerformanceTimer();
+ tile.buildTime += rcGetDeltaTimeUsec(startTime, endTime);
+ }
+ }
+
+ delete [] triangleFlags;
+ delete solid;
+ delete chf;
+
+
+ // Some extra code to measure some per tile statistics,
+ // such as build time and how many polygons there are per tile.
+ if (m_measurePerTileTimings)
+ {
+ for (int y = 0; y < m_tileSet->height; ++y)
+ {
+ for (int x = 0; x < m_tileSet->width; ++x)
+ {
+ Tile& tile = m_tileSet->tiles[x + y*m_tileSet->width];
+
+ if (!tile.cset)
+ continue;
+
+ rcTimeVal startTime = rcGetPerformanceTimer();
+ rcPolyMesh* polyMesh = new rcPolyMesh;
+ if (!polyMesh)
+ continue;
+ if (rcBuildPolyMesh(*tile.cset, m_cfg.bmin, m_cfg.bmax,
+ m_cfg.cs, m_cfg.ch, m_cfg.maxVertsPerPoly, *polyMesh))
+ {
+ int bucket = polyMesh->npolys;
+ if (bucket < 0) bucket = 0;
+ if (bucket >= MAX_STAT_BUCKETS) bucket = MAX_STAT_BUCKETS-1;
+ m_statPolysPerTile[bucket]++;
+ m_statPolysPerTileSamples++;
+ }
+ delete polyMesh;
+
+ rcTimeVal endTime = rcGetPerformanceTimer();
+ int time = tile.buildTime += rcGetDeltaTimeUsec(startTime, endTime);
+
+ int bucket = (time+500)/1000;
+ if (bucket < 0) bucket = 0;
+ if (bucket >= MAX_STAT_BUCKETS) bucket = MAX_STAT_BUCKETS-1;
+ m_statTimePerTile[bucket]++;
+ m_statTimePerTileSamples++;
+ }
+ }
+ }
+
+ // Make sure that the vertices along the tile edges match,
+ // so that they can be later properly stitched together.
+ for (int y = 0; y < m_tileSet->height; ++y)
+ {
+ for (int x = 0; x < m_tileSet->width; ++x)
+ {
+ rcTimeVal startTime = rcGetPerformanceTimer();
+ if ((x+1) < m_tileSet->width)
+ {
+ if (!rcFixupAdjacentContours(m_tileSet->tiles[x + y*m_tileSet->width].cset,
+ m_tileSet->tiles[x+1 + y*m_tileSet->width].cset,
+ m_cfg.walkableClimb, (x+1)*m_cfg.tileSize, -1))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not fixup x+1.", x, y);
+ return false;
+ }
+ }
+
+ if ((y+1) < m_tileSet->height)
+ {
+ if (!rcFixupAdjacentContours(m_tileSet->tiles[x + y*m_tileSet->width].cset,
+ m_tileSet->tiles[x + (y+1)*m_tileSet->width].cset,
+ m_cfg.walkableClimb, -1, (y+1)*m_cfg.tileSize))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not fixup y+1.", x, y);
+ return false;
+ }
+ }
+ rcTimeVal endTime = rcGetPerformanceTimer();
+ m_tileSet->tiles[x+y*m_tileSet->width].buildTime += rcGetDeltaTimeUsec(startTime, endTime);
+ }
+ }
+
+
+ // Combine contours.
+ rcContourSet combSet;
+
+ combSet.nconts = 0;
+ for (int y = 0; y < m_tileSet->height; ++y)
+ {
+ for (int x = 0; x < m_tileSet->width; ++x)
+ {
+ Tile& tile = m_tileSet->tiles[x + y*m_tileSet->width];
+ if (!tile.cset) continue;
+ combSet.nconts += tile.cset->nconts;
+ }
+ }
+ combSet.conts = new rcContour[combSet.nconts];
+ if (!combSet.conts)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'combSet.conts' (%d).", combSet.nconts);
+ return false;
+ }
+ int n = 0;
+ for (int y = 0; y < m_tileSet->height; ++y)
+ {
+ for (int x = 0; x < m_tileSet->width; ++x)
+ {
+ Tile& tile = m_tileSet->tiles[x + y*m_tileSet->width];
+ if (!tile.cset) continue;
+ for (int i = 0; i < tile.cset->nconts; ++i)
+ {
+ combSet.conts[n].verts = tile.cset->conts[i].verts;
+ combSet.conts[n].nverts = tile.cset->conts[i].nverts;
+ combSet.conts[n].reg = tile.cset->conts[i].reg;
+ n++;
+ }
+ }
+ }
+
+ m_polyMesh = new rcPolyMesh;
+ if (!m_polyMesh)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'polyMesh'.");
+ return false;
+ }
+
+ bool polyRes = rcBuildPolyMesh(combSet, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch, m_cfg.maxVertsPerPoly, *m_polyMesh);
+
+ // Remove vertex binding to avoid double deletion.
+ for (int i = 0; i < combSet.nconts; ++i)
+ {
+ combSet.conts[i].verts = 0;
+ combSet.conts[i].nverts = 0;
+ }
+
+ if (!polyRes)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not triangulate contours.");
+ return false;
+ }
+
+ if (!m_keepInterResults)
+ {
+ for (int y = 0; y < m_tileSet->height; ++y)
+ {
+ for (int x = 0; x < m_tileSet->width; ++x)
+ {
+ Tile& tile = m_tileSet->tiles[x + y*m_tileSet->width];
+ delete tile.cset;
+ tile.cset = 0;
+ }
+ }
+ }
+
+ if (m_cfg.maxVertsPerPoly == DT_STAT_VERTS_PER_POLYGON)
+ {
+ unsigned char* navData = 0;
+ int navDataSize = 0;
+ if (!dtCreateNavMeshData(m_polyMesh->verts, m_polyMesh->nverts,
+ m_polyMesh->polys, m_polyMesh->npolys, m_polyMesh->nvp,
+ m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch, &navData, &navDataSize))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
+ return false;
+ }
+
+ m_navMesh = new dtStatNavMesh;
+ if (!m_navMesh)
+ {
+ delete [] navData;
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "Could not create Detour navmesh");
+ return false;
+ }
+
+ if (!m_navMesh->init(navData, navDataSize, true))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "Could not init Detour navmesh");
+ return false;
+ }
+ }
+
+ rcTimeVal totEndTime = rcGetPerformanceTimer();
+
+ if (rcGetLog())
+ {
+ const float pc = 100.0f / rcGetDeltaTimeUsec(totStartTime, totEndTime);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Chunky Mesh: %.1fms (%.1f%%)", rcGetDeltaTimeUsec(chunkyStartTime, chunkyEndTime)/1000.0f, rcGetDeltaTimeUsec(chunkyStartTime, chunkyEndTime)*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Rasterize: %.1fms (%.1f%%)", m_buildTimes.rasterizeTriangles/1000.0f, m_buildTimes.rasterizeTriangles*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Compact: %.1fms (%.1f%%)", m_buildTimes.buildCompact/1000.0f, m_buildTimes.buildCompact*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Border: %.1fms (%.1f%%)", m_buildTimes.filterBorder/1000.0f, m_buildTimes.filterBorder*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Walkable: %.1fms (%.1f%%)", m_buildTimes.filterWalkable/1000.0f, m_buildTimes.filterWalkable*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Reachable: %.1fms (%.1f%%)", m_buildTimes.filterMarkReachable/1000.0f, m_buildTimes.filterMarkReachable*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Distancefield: %.1fms (%.1f%%)", m_buildTimes.buildDistanceField/1000.0f, m_buildTimes.buildDistanceField*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - distance: %.1fms (%.1f%%)", m_buildTimes.buildDistanceFieldDist/1000.0f, m_buildTimes.buildDistanceFieldDist*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - blur: %.1fms (%.1f%%)", m_buildTimes.buildDistanceFieldBlur/1000.0f, m_buildTimes.buildDistanceFieldBlur*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Regions: %.1fms (%.1f%%)", m_buildTimes.buildRegions/1000.0f, m_buildTimes.buildRegions*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - watershed: %.1fms (%.1f%%)", m_buildTimes.buildRegionsReg/1000.0f, m_buildTimes.buildRegionsReg*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - expand: %.1fms (%.1f%%)", m_buildTimes.buildRegionsExp/1000.0f, m_buildTimes.buildRegionsExp*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - find catchment basins: %.1fms (%.1f%%)", m_buildTimes.buildRegionsFlood/1000.0f, m_buildTimes.buildRegionsFlood*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - filter: %.1fms (%.1f%%)", m_buildTimes.buildRegionsFilter/1000.0f, m_buildTimes.buildRegionsFilter*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Contours: %.1fms (%.1f%%)", m_buildTimes.buildContours/1000.0f, m_buildTimes.buildContours*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - trace: %.1fms (%.1f%%)", m_buildTimes.buildContoursTrace/1000.0f, m_buildTimes.buildContoursTrace*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - simplify: %.1fms (%.1f%%)", m_buildTimes.buildContoursSimplify/1000.0f, m_buildTimes.buildContoursSimplify*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Fixup contours: %.1fms (%.1f%%)", m_buildTimes.fixupContours/1000.0f, m_buildTimes.fixupContours*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Polymesh: %.1fms (%.1f%%)", m_buildTimes.buildPolymesh/1000.0f, m_buildTimes.buildPolymesh*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Polymesh: Verts:%d Polys:%d", m_polyMesh->nverts, m_polyMesh->npolys);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "TOTAL: %.1fms", rcGetDeltaTimeUsec(totStartTime, totEndTime)/1000.0f);
+ }
+
+ toolRecalc();
+
+ return true;
+}
diff --git a/RecastDemo/Source/Sample_TileMesh.cpp b/RecastDemo/Source/Sample_TileMesh.cpp
new file mode 100644
index 0000000..5f23106
--- /dev/null
+++ b/RecastDemo/Source/Sample_TileMesh.cpp
@@ -0,0 +1,847 @@
+//
+// Copyright (c) 2009 Mikko Mononen memon@inside.org
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+
+#define _USE_MATH_DEFINES
+#include
+#include
+#include
+#include "SDL.h"
+#include "SDL_Opengl.h"
+#include "imgui.h"
+#include "Sample.h"
+#include "Sample_TileMesh.h"
+#include "Recast.h"
+#include "RecastTimer.h"
+#include "RecastDebugDraw.h"
+#include "DetourTileNavMesh.h"
+#include "DetourTileNavMeshBuilder.h"
+#include "DetourDebugDraw.h"
+
+#ifdef WIN32
+# define snprintf _snprintf
+#endif
+
+Sample_TileMesh::Sample_TileMesh() :
+ m_tileSize(32),
+ m_navMesh(0),
+ m_chunkyMesh(0),
+ m_keepInterResults(true),
+ m_tileBuildTime(0),
+ m_tileMemUsage(0),
+ m_triflags(0),
+ m_solid(0),
+ m_chf(0),
+ m_cset(0),
+ m_polyMesh(0),
+ m_tileTriCount(0),
+ m_toolMode(TOOLMODE_CREATE_TILES),
+ m_startRef(0),
+ m_endRef(0),
+ m_npolys(0),
+ m_nstraightPath(0),
+ m_sposSet(false),
+ m_eposSet(false)
+{
+ resetCommonSettings();
+ memset(m_tileBmin, 0, sizeof(m_tileBmin));
+ memset(m_tileBmax, 0, sizeof(m_tileBmax));
+ m_polyPickExt[0] = 2;
+ m_polyPickExt[1] = 4;
+ m_polyPickExt[2] = 2;
+}
+
+Sample_TileMesh::~Sample_TileMesh()
+{
+ cleanup();
+ delete m_navMesh;
+ delete m_chunkyMesh;
+}
+
+void Sample_TileMesh::cleanup()
+{
+ delete [] m_triflags;
+ m_triflags = 0;
+ delete m_solid;
+ m_solid = 0;
+ delete m_chf;
+ m_chf = 0;
+ delete m_cset;
+ m_cset = 0;
+ delete m_polyMesh;
+ m_polyMesh = 0;
+}
+
+void Sample_TileMesh::handleSettings()
+{
+ Sample::handleCommonSettings();
+
+ imguiLabel("Tiling");
+ imguiSlider("TileSize", &m_tileSize, 16.0f, 1024.0f, 16.0f);
+
+ char text[64];
+ int gw = 0, gh = 0;
+ rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
+ const int ts = (int)m_tileSize;
+ const int tw = (gw + ts-1) / ts;
+ const int th = (gh + ts-1) / ts;
+ snprintf(text, 64, "Tiles %d x %d", tw, th);
+ imguiValue(text);
+}
+
+void Sample_TileMesh::toolRecalc()
+{
+ m_startRef = 0;
+ if (m_sposSet)
+ m_startRef = m_navMesh->findNearestPoly(m_spos, m_polyPickExt);
+
+ m_endRef = 0;
+ if (m_eposSet)
+ m_endRef = m_navMesh->findNearestPoly(m_epos, m_polyPickExt);
+
+ if (m_toolMode == TOOLMODE_PATHFIND)
+ {
+ if (m_sposSet && m_eposSet && m_startRef && m_endRef)
+ {
+ m_npolys = m_navMesh->findPath(m_startRef, m_endRef, m_polys, MAX_POLYS);
+ if (m_npolys)
+ m_nstraightPath = m_navMesh->findStraightPath(m_spos, m_epos, m_polys, m_npolys, m_straightPath, MAX_POLYS);
+ }
+ else
+ {
+ m_npolys = 0;
+ m_nstraightPath = 0;
+ }
+ }
+ else if (m_toolMode == TOOLMODE_RAYCAST)
+ {
+ m_nstraightPath = 0;
+ if (m_sposSet && m_eposSet && m_startRef)
+ {
+ float t = 0;
+ m_npolys = 0;
+ m_nstraightPath = 2;
+ m_straightPath[0] = m_spos[0];
+ m_straightPath[1] = m_spos[1];
+ m_straightPath[2] = m_spos[2];
+ m_npolys = m_navMesh->raycast(m_startRef, m_spos, m_epos, t, m_polys, MAX_POLYS);
+ if (m_npolys && t < 1)
+ {
+ m_straightPath[3] = m_spos[0] + (m_epos[0] - m_spos[0]) * t;
+ m_straightPath[4] = m_spos[1] + (m_epos[1] - m_spos[1]) * t;
+ m_straightPath[5] = m_spos[2] + (m_epos[2] - m_spos[2]) * t;
+ }
+ else
+ {
+ m_straightPath[3] = m_epos[0];
+ m_straightPath[4] = m_epos[1];
+ m_straightPath[5] = m_epos[2];
+ }
+ }
+ }
+ else if (m_toolMode == TOOLMODE_DISTANCE_TO_WALL)
+ {
+ m_distanceToWall = 0;
+ if (m_sposSet && m_startRef)
+ m_distanceToWall = m_navMesh->findDistanceToWall(m_startRef, m_spos, 100.0f, m_hitPos, m_hitNormal);
+ }
+ else if (m_toolMode == TOOLMODE_FIND_POLYS_AROUND)
+ {
+ if (m_sposSet && m_startRef && m_eposSet)
+ {
+ const float dx = m_epos[0] - m_spos[0];
+ const float dz = m_epos[2] - m_spos[2];
+ float dist = sqrtf(dx*dx + dz*dz);
+ m_npolys = m_navMesh->findPolysAround(m_startRef, m_spos, dist, m_polys, m_parent, 0, MAX_POLYS);
+ }
+ }
+
+}
+
+void Sample_TileMesh::handleTools()
+{
+ if (imguiCheck("Create Tiles", m_toolMode == TOOLMODE_CREATE_TILES))
+ {
+ m_toolMode = TOOLMODE_CREATE_TILES;
+ toolRecalc();
+ }
+ if (imguiCheck("Pathfind", m_toolMode == TOOLMODE_PATHFIND))
+ {
+ m_toolMode = TOOLMODE_PATHFIND;
+ toolRecalc();
+ }
+ if (imguiCheck("Distance to Wall", m_toolMode == TOOLMODE_DISTANCE_TO_WALL))
+ {
+ m_toolMode = TOOLMODE_DISTANCE_TO_WALL;
+ toolRecalc();
+ }
+ if (imguiCheck("Raycast", m_toolMode == TOOLMODE_RAYCAST))
+ {
+ m_toolMode = TOOLMODE_RAYCAST;
+ toolRecalc();
+ }
+ if (imguiCheck("Find Polys Around", m_toolMode == TOOLMODE_FIND_POLYS_AROUND))
+ {
+ m_toolMode = TOOLMODE_FIND_POLYS_AROUND;
+ toolRecalc();
+ }
+}
+
+void Sample_TileMesh::handleDebugMode()
+{
+ if (m_navMesh)
+ {
+ imguiValue("Navmesh ready.");
+ imguiValue("Use 'Create Tiles' tool to experiment.");
+ imguiValue("LMB: (Re)Create tiles.");
+ imguiValue("LMB+SHIFT: Remove tiles.");
+ }
+
+}
+
+static void getPolyCenter(dtTiledNavMesh* navMesh, dtTilePolyRef ref, float* center)
+{
+ const dtTilePoly* p = navMesh->getPolyByRef(ref);
+ if (!p) return;
+ const float* verts = navMesh->getPolyVertsByRef(ref);
+ center[0] = 0;
+ center[1] = 0;
+ center[2] = 0;
+ for (int i = 0; i < (int)p->nv; ++i)
+ {
+ const float* v = &verts[p->v[i]*3];
+ center[0] += v[0];
+ center[1] += v[1];
+ center[2] += v[2];
+ }
+ const float s = 1.0f / p->nv;
+ center[0] *= s;
+ center[1] *= s;
+ center[2] *= s;
+}
+
+void Sample_TileMesh::handleRender()
+{
+ if (!m_verts || !m_tris || !m_trinorms)
+ return;
+
+ // Draw mesh
+ if (m_navMesh)
+ rcDebugDrawMesh(m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
+ else
+ rcDebugDrawMeshSlope(m_verts, m_nverts, m_tris, m_trinorms, m_ntris, m_agentMaxSlope);
+
+ glDepthMask(GL_FALSE);
+
+ // Draw bounds
+ float col[4] = {1,1,1,0.5f};
+ rcDebugDrawBoxWire(m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
+
+ // Tiling grid.
+ const int ts = (int)m_tileSize;
+ int gw = 0, gh = 0;
+ rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
+ int tw = (gw + ts-1) / ts;
+ int th = (gh + ts-1) / ts;
+ const float s = ts*m_cellSize;
+ glBegin(GL_LINES);
+ glColor4ub(0,0,0,64);
+ for (int y = 0; y < th; ++y)
+ {
+ for (int x = 0; x < tw; ++x)
+ {
+ float fx, fy, fz;
+ fx = m_bmin[0] + x*s;
+ fy = m_bmin[1];
+ fz = m_bmin[2] + y*s;
+
+ glVertex3f(fx,fy,fz);
+ glVertex3f(fx+s,fy,fz);
+ glVertex3f(fx,fy,fz);
+ glVertex3f(fx,fy,fz+s);
+
+ if (x+1 >= tw)
+ {
+ glVertex3f(fx+s,fy,fz);
+ glVertex3f(fx+s,fy,fz+s);
+ }
+ if (y+1 >= th)
+ {
+ glVertex3f(fx,fy,fz+s);
+ glVertex3f(fx+s,fy,fz+s);
+ }
+ }
+ }
+ glEnd();
+
+ // Draw active tile
+ rcDebugDrawBoxWire(m_tileBmin[0],m_tileBmin[1],m_tileBmin[2], m_tileBmax[0],m_tileBmax[1],m_tileBmax[2], m_tileCol);
+
+ if (m_navMesh)
+ dtDebugDrawTiledNavMesh(m_navMesh);
+
+ if (m_sposSet)
+ {
+ const float s = 0.5f;
+ glColor4ub(128,0,0,255);
+ glBegin(GL_LINES);
+ glVertex3f(m_spos[0]-s,m_spos[1],m_spos[2]);
+ glVertex3f(m_spos[0]+s,m_spos[1],m_spos[2]);
+ glVertex3f(m_spos[0],m_spos[1]-s,m_spos[2]);
+ glVertex3f(m_spos[0],m_spos[1]+s,m_spos[2]);
+ glVertex3f(m_spos[0],m_spos[1],m_spos[2]-s);
+ glVertex3f(m_spos[0],m_spos[1],m_spos[2]+s);
+ glEnd();
+ }
+ if (m_eposSet)
+ {
+ const float s = 0.5f;
+ glColor4ub(0,128,0,255);
+ glBegin(GL_LINES);
+ glVertex3f(m_epos[0]-s,m_epos[1],m_epos[2]);
+ glVertex3f(m_epos[0]+s,m_epos[1],m_epos[2]);
+ glVertex3f(m_epos[0],m_epos[1]-s,m_epos[2]);
+ glVertex3f(m_epos[0],m_epos[1]+s,m_epos[2]);
+ glVertex3f(m_epos[0],m_epos[1],m_epos[2]-s);
+ glVertex3f(m_epos[0],m_epos[1],m_epos[2]+s);
+ glEnd();
+ }
+
+ static const float startCol[4] = { 0.5f, 0.1f, 0.0f, 0.75f };
+ static const float endCol[4] = { 0.2f, 0.4f, 0.0f, 0.75f };
+ static const float pathCol[4] = {0,0,0,0.25f};
+
+ if (m_toolMode == TOOLMODE_PATHFIND)
+ {
+ dtDebugDrawTiledNavMeshPoly(m_navMesh, m_startRef, startCol);
+ dtDebugDrawTiledNavMeshPoly(m_navMesh, m_endRef, endCol);
+
+ if (m_npolys)
+ {
+ for (int i = 1; i < m_npolys-1; ++i)
+ dtDebugDrawTiledNavMeshPoly(m_navMesh, m_polys[i], pathCol);
+ }
+ if (m_nstraightPath)
+ {
+ glColor4ub(128,16,0,220);
+ glLineWidth(3.0f);
+ glBegin(GL_LINE_STRIP);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glLineWidth(1.0f);
+ glPointSize(4.0f);
+ glBegin(GL_POINTS);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glPointSize(1.0f);
+ }
+ }
+ else if (m_toolMode == TOOLMODE_RAYCAST)
+ {
+ dtDebugDrawTiledNavMeshPoly(m_navMesh, m_startRef, startCol);
+
+ if (m_nstraightPath)
+ {
+ for (int i = 1; i < m_npolys; ++i)
+ dtDebugDrawTiledNavMeshPoly(m_navMesh, m_polys[i], pathCol);
+
+ glColor4ub(128,16,0,220);
+ glLineWidth(3.0f);
+ glBegin(GL_LINE_STRIP);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glLineWidth(1.0f);
+ glPointSize(4.0f);
+ glBegin(GL_POINTS);
+ for (int i = 0; i < m_nstraightPath; ++i)
+ glVertex3f(m_straightPath[i*3], m_straightPath[i*3+1]+0.4f, m_straightPath[i*3+2]);
+ glEnd();
+ glPointSize(1.0f);
+ }
+ }
+ else if (m_toolMode == TOOLMODE_DISTANCE_TO_WALL)
+ {
+ dtDebugDrawTiledNavMeshPoly(m_navMesh, m_startRef, startCol);
+ const float col[4] = {1,1,1,0.5f};
+ rcDebugDrawCylinderWire(m_spos[0]-m_distanceToWall, m_spos[1]+0.02f, m_spos[2]-m_distanceToWall,
+ m_spos[0]+m_distanceToWall, m_spos[1]+m_agentHeight, m_spos[2]+m_distanceToWall, col);
+ glLineWidth(3.0f);
+ glColor4fv(col);
+ glBegin(GL_LINES);
+ glVertex3f(m_hitPos[0], m_hitPos[1] + 0.02f, m_hitPos[2]);
+ glVertex3f(m_hitPos[0], m_hitPos[1] + m_agentHeight, m_hitPos[2]);
+ glEnd();
+ glLineWidth(1.0f);
+ }
+ else if (m_toolMode == TOOLMODE_FIND_POLYS_AROUND)
+ {
+ glLineWidth(2.0f);
+ for (int i = 0; i < m_npolys; ++i)
+ {
+ dtDebugDrawTiledNavMeshPoly(m_navMesh, m_polys[i], pathCol);
+ if (m_parent[i])
+ {
+ float p0[3], p1[3];
+ getPolyCenter(m_navMesh, m_polys[i], p0);
+ getPolyCenter(m_navMesh, m_parent[i], p1);
+ glColor4ub(0,0,0,128);
+ rcDrawArc(p0, p1);
+ }
+ }
+ glLineWidth(1.0f);
+
+ const float dx = m_epos[0] - m_spos[0];
+ const float dz = m_epos[2] - m_spos[2];
+ float dist = sqrtf(dx*dx + dz*dz);
+ const float col[4] = {1,1,1,0.5f};
+ rcDebugDrawCylinderWire(m_spos[0]-dist, m_spos[1]+0.02f, m_spos[2]-dist,
+ m_spos[0]+dist, m_spos[1]+m_agentHeight, m_spos[2]+dist, col);
+ }
+
+ glDepthMask(GL_TRUE);
+
+}
+
+void Sample_TileMesh::handleRenderOverlay(double* proj, double* model, int* view)
+{
+ GLdouble x, y, z;
+
+ // Draw start and end point labels
+ if (m_tileBuildTime > 0.0f && gluProject((GLdouble)(m_tileBmin[0]+m_tileBmax[0])/2, (GLdouble)(m_tileBmin[1]+m_tileBmax[1])/2, (GLdouble)(m_tileBmin[2]+m_tileBmax[2])/2,
+ model, proj, view, &x, &y, &z))
+ {
+ char text[32];
+ snprintf(text,32,"%.3fms / %dTris / %.1fkB", m_tileBuildTime, m_tileTriCount, m_tileMemUsage);
+ imguiDrawText((int)x, (int)y-25, IMGUI_ALIGN_CENTER, text, imguiRGBA(0,0,0,220));
+ }
+}
+
+void Sample_TileMesh::handleMeshChanged(const float* verts, int nverts,
+ const int* tris, const float* trinorms, int ntris,
+ const float* bmin, const float* bmax)
+{
+ m_verts = verts;
+ m_nverts = nverts;
+ m_tris = tris;
+ m_trinorms = trinorms;
+ m_ntris = ntris;
+ vcopy(m_bmin, bmin);
+ vcopy(m_bmax, bmax);
+
+ delete m_chunkyMesh;
+ m_chunkyMesh = 0;
+ delete m_navMesh;
+ m_navMesh = 0;
+ cleanup();
+}
+
+void Sample_TileMesh::setToolStartPos(const float* p)
+{
+ m_sposSet = true;
+ vcopy(m_spos, p);
+
+ if (m_toolMode == TOOLMODE_CREATE_TILES)
+ removeTile(m_spos);
+ else
+ toolRecalc();
+}
+
+void Sample_TileMesh::setToolEndPos(const float* p)
+{
+ if (!m_navMesh)
+ return;
+
+ m_eposSet = true;
+ vcopy(m_epos, p);
+
+ if (m_toolMode == TOOLMODE_CREATE_TILES)
+ buildTile(m_epos);
+ else
+ toolRecalc();
+}
+
+bool Sample_TileMesh::handleBuild()
+{
+ if (!m_verts || !m_tris)
+ {
+ printf("No verts or tris\n");
+ return false;
+ }
+
+ delete m_navMesh;
+ m_navMesh = new dtTiledNavMesh;
+ if (!m_navMesh)
+ {
+ printf("Could not allocate navmehs\n");
+ return false;
+ }
+ if (!m_navMesh->init(m_bmin, m_tileSize*m_cellSize, m_agentMaxClimb*m_cellHeight))
+ {
+ printf("Could not init navmesh\n");
+ return false;
+ }
+
+ // Build chunky mesh.
+ delete m_chunkyMesh;
+ m_chunkyMesh = new rcChunkyTriMesh;
+ if (!m_chunkyMesh)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'm_chunkyMesh'.");
+ return false;
+ }
+ if (!rcCreateChunkyTriMesh(m_verts, m_tris, m_ntris, 256, m_chunkyMesh))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not build chunky mesh.");
+ return false;
+ }
+
+ return true;
+}
+
+void Sample_TileMesh::buildTile(const float* pos)
+{
+ if (!m_navMesh)
+ return;
+
+ const float ts = m_tileSize*m_cellSize;
+ const int tx = (int)floorf((pos[0]-m_bmin[0]) / ts);
+ const int ty = (int)floorf((pos[2]-m_bmin[2]) / ts);
+ if (tx < 0 || ty < 0)
+ return;
+
+ m_tileBmin[0] = m_bmin[0] + tx*ts;
+ m_tileBmin[1] = m_bmin[1];
+ m_tileBmin[2] = m_bmin[2] + ty*ts;
+
+ m_tileBmax[0] = m_bmin[0] + (tx+1)*ts;
+ m_tileBmax[1] = m_bmax[1];
+ m_tileBmax[2] = m_bmin[2] + (ty+1)*ts;
+
+ m_tileCol[0] = 0.3f; m_tileCol[1] = 0.8f; m_tileCol[2] = 0; m_tileCol[3] = 1;
+
+ int dataSize = 0;
+ unsigned char* data = buildTileMesh(m_tileBmin, m_tileBmax, dataSize);
+
+ if (data)
+ {
+ // Remove any previous data (navmesh owns and deletes the data).
+ m_navMesh->removeTileAt(tx,ty,0,0);
+
+ // Let the navmesh own the data.
+ if (!m_navMesh->addTileAt(tx,ty,data,dataSize,true))
+ delete [] data;
+ }
+}
+
+void Sample_TileMesh::removeTile(const float* pos)
+{
+ if (!m_navMesh)
+ return;
+
+ const float ts = m_tileSize*m_cellSize;
+ const int tx = (int)floorf((pos[0]-m_bmin[0]) / ts);
+ const int ty = (int)floorf((pos[2]-m_bmin[2]) / ts);
+
+ m_tileBmin[0] = m_bmin[0] + tx*ts;
+ m_tileBmin[1] = m_bmin[1];
+ m_tileBmin[2] = m_bmin[2] + ty*ts;
+
+ m_tileBmax[0] = m_bmin[0] + (tx+1)*ts;
+ m_tileBmax[1] = m_bmax[1];
+ m_tileBmax[2] = m_bmin[2] + (ty+1)*ts;
+
+ m_tileCol[0] = 0.8f; m_tileCol[1] = 0.1f; m_tileCol[2] = 0; m_tileCol[3] = 1;
+
+ unsigned char* rdata = 0;
+ int rdataSize = 0;
+ if (m_navMesh->removeTileAt(tx,ty,&rdata,&rdataSize))
+ delete [] rdata;
+}
+
+unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bmax, int& dataSize)
+{
+ if (!m_verts || ! m_tris)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
+ return 0;
+ }
+
+ cleanup();
+
+ // Init build configuration from GUI
+ memset(&m_cfg, 0, sizeof(m_cfg));
+ m_cfg.cs = m_cellSize;
+ m_cfg.ch = m_cellHeight;
+ m_cfg.walkableSlopeAngle = m_agentMaxSlope;
+ m_cfg.walkableHeight = (int)ceilf(m_agentHeight / m_cfg.ch);
+ m_cfg.walkableClimb = (int)ceilf(m_agentMaxClimb / m_cfg.ch);
+ m_cfg.walkableRadius = (int)ceilf(m_agentRadius / m_cfg.cs);
+ m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
+ m_cfg.maxSimplificationError = m_edgeMaxError;
+ m_cfg.minRegionSize = (int)rcSqr(m_regionMinSize);
+ m_cfg.mergeRegionSize = (int)rcSqr(m_regionMergeSize);
+ m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
+ m_cfg.tileSize = (int)m_tileSize;
+ m_cfg.borderSize = m_cfg.walkableRadius*2 + 2; // Reserve enough padding.
+ m_cfg.width = m_cfg.tileSize + m_cfg.borderSize*2;
+ m_cfg.height = m_cfg.tileSize + m_cfg.borderSize*2;
+
+/* if (m_cfg.maxVertsPerPoly == DT_VERTS_PER_POLYGON)
+ m_drawMode = DRAWMODE_NAVMESH;
+ else
+ m_drawMode = DRAWMODE_POLYMESH;*/
+
+ vcopy(m_cfg.bmin, bmin);
+ vcopy(m_cfg.bmax, bmax);
+ m_cfg.bmin[0] -= m_cfg.borderSize*m_cfg.cs;
+ m_cfg.bmin[2] -= m_cfg.borderSize*m_cfg.cs;
+ m_cfg.bmax[0] += m_cfg.borderSize*m_cfg.cs;
+ m_cfg.bmax[2] += m_cfg.borderSize*m_cfg.cs;
+
+ // Reset build times gathering.
+ memset(&m_buildTimes, 0, sizeof(m_buildTimes));
+ rcSetBuildTimes(&m_buildTimes);
+
+ // Start the build process.
+ rcTimeVal totStartTime = rcGetPerformanceTimer();
+
+ if (rcGetLog())
+ {
+ rcGetLog()->log(RC_LOG_PROGRESS, "Building navigation:");
+ rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", m_nverts/1000.0f, m_ntris/1000.0f);
+ }
+
+ // Allocate voxel heighfield where we rasterize our input data to.
+ m_solid = new rcHeightfield;
+ if (!m_solid)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'solid'.");
+ return 0;
+ }
+ if (!rcCreateHeightfield(*m_solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not create solid heightfield.");
+ return 0;
+ }
+
+ // Allocate array that can hold triangle flags.
+ // If you have multiple meshes you need to process, allocate
+ // and array which can hold the max number of triangles you need to process.
+ m_triflags = new unsigned char[m_chunkyMesh->maxTrisPerChunk];
+ if (!m_triflags)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'triangleFlags' (%d).", m_chunkyMesh->maxTrisPerChunk);
+ return 0;
+ }
+
+
+ float tbmin[2], tbmax[2];
+ tbmin[0] = m_cfg.bmin[0];
+ tbmin[1] = m_cfg.bmin[2];
+ tbmax[0] = m_cfg.bmax[0];
+ tbmax[1] = m_cfg.bmax[2];
+ int cid[256];// TODO: Make grow when returning too many items.
+ const int ncid = rcGetChunksInRect(m_chunkyMesh, tbmin, tbmax, cid, 256);
+ if (!ncid)
+ return 0;
+
+ m_tileTriCount = 0;
+
+ for (int i = 0; i < ncid; ++i)
+ {
+ const rcChunkyTriMeshNode& node = m_chunkyMesh->nodes[cid[i]];
+ const int* tris = &m_chunkyMesh->tris[node.i*3];
+ const int ntris = node.n;
+
+ m_tileTriCount += ntris;
+
+ memset(m_triflags, 0, ntris*sizeof(unsigned char));
+ rcMarkWalkableTriangles(m_cfg.walkableSlopeAngle,
+ m_verts, m_nverts, tris, ntris, m_triflags);
+
+ rcRasterizeTriangles(m_verts, m_nverts, tris, m_triflags, ntris, *m_solid);
+ }
+
+ if (!m_keepInterResults)
+ {
+ delete [] m_triflags;
+ m_triflags = 0;
+ }
+
+ // Once all geoemtry is rasterized, we do initial pass of filtering to
+ // remove unwanted overhangs caused by the conservative rasterization
+ // as well as filter spans where the character cannot possibly stand.
+ rcFilterLedgeSpans(m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid);
+ rcFilterWalkableLowHeightSpans(m_cfg.walkableHeight, *m_solid);
+
+ // Compact the heightfield so that it is faster to handle from now on.
+ // This will result more cache coherent data as well as the neighbours
+ // between walkable cells will be calculated.
+ m_chf = new rcCompactHeightfield;
+ if (!m_chf)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'chf'.");
+ return 0;
+ }
+ if (!rcBuildCompactHeightfield(m_cfg.walkableHeight, m_cfg.walkableClimb, RC_WALKABLE, *m_solid, *m_chf))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not build compact data.");
+ return 0;
+ }
+
+ if (!m_keepInterResults)
+ {
+ delete m_solid;
+ m_solid = 0;
+ }
+
+ // Prepare for region partitioning, by calculating distance field along the walkable surface.
+ if (!rcBuildDistanceField(*m_chf))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
+ return 0;
+ }
+
+ // Partition the walkable surface into simple regions without holes.
+ if (!rcBuildRegions(*m_chf, m_cfg.walkableRadius, m_cfg.borderSize, m_cfg.minRegionSize, m_cfg.mergeRegionSize))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
+ return 0;
+ }
+
+ // Create contours.
+ m_cset = new rcContourSet;
+ if (!m_cset)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'cset'.");
+ return 0;
+ }
+ if (!rcBuildContours(*m_chf, m_cfg.maxSimplificationError, m_cfg.maxEdgeLen, *m_cset))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not create contours.");
+ return 0;
+ }
+
+ if (!m_keepInterResults)
+ {
+ delete m_chf;
+ m_chf = 0;
+ }
+
+ // Build polygon navmesh from the contours.
+ m_polyMesh = new rcPolyMesh;
+ if (!m_polyMesh)
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'polyMesh'.");
+ return 0;
+ }
+ if (!rcBuildPolyMesh(*m_cset, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch, m_cfg.maxVertsPerPoly, *m_polyMesh))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Could not triangulate contours.");
+ return 0;
+ }
+
+ if (!m_keepInterResults)
+ {
+ delete m_cset;
+ m_cset = 0;
+ }
+
+ unsigned char* navData = 0;
+ int navDataSize = 0;
+ if (m_cfg.maxVertsPerPoly == DT_TILE_VERTS_PER_POLYGON)
+ {
+ // Remove padding from the polymesh data.
+ for (int i = 0; i < m_polyMesh->nverts; ++i)
+ {
+ unsigned short* v = &m_polyMesh->verts[i*3];
+ v[0] -= (unsigned short)m_cfg.borderSize;
+ v[2] -= (unsigned short)m_cfg.borderSize;
+ }
+
+ if (!dtCreateNavMeshTileData(m_polyMesh->verts, m_polyMesh->nverts,
+ m_polyMesh->polys, m_polyMesh->npolys, m_polyMesh->nvp,
+ bmin, bmax, m_cfg.cs, m_cfg.ch, m_cfg.tileSize, m_cfg.walkableClimb, &navData, &navDataSize))
+ {
+ if (rcGetLog())
+ rcGetLog()->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
+ return 0;
+ }
+ }
+ m_tileMemUsage = navDataSize/1024.0f;
+
+ rcTimeVal totEndTime = rcGetPerformanceTimer();
+
+ // Show performance stats.
+ if (rcGetLog())
+ {
+ const float pc = 100.0f / rcGetDeltaTimeUsec(totStartTime, totEndTime);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Rasterize: %.1fms (%.1f%%)", m_buildTimes.rasterizeTriangles/1000.0f, m_buildTimes.rasterizeTriangles*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Compact: %.1fms (%.1f%%)", m_buildTimes.buildCompact/1000.0f, m_buildTimes.buildCompact*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Border: %.1fms (%.1f%%)", m_buildTimes.filterBorder/1000.0f, m_buildTimes.filterBorder*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Walkable: %.1fms (%.1f%%)", m_buildTimes.filterWalkable/1000.0f, m_buildTimes.filterWalkable*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, "Filter Reachable: %.1fms (%.1f%%)", m_buildTimes.filterMarkReachable/1000.0f, m_buildTimes.filterMarkReachable*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Distancefield: %.1fms (%.1f%%)", m_buildTimes.buildDistanceField/1000.0f, m_buildTimes.buildDistanceField*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - distance: %.1fms (%.1f%%)", m_buildTimes.buildDistanceFieldDist/1000.0f, m_buildTimes.buildDistanceFieldDist*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - blur: %.1fms (%.1f%%)", m_buildTimes.buildDistanceFieldBlur/1000.0f, m_buildTimes.buildDistanceFieldBlur*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Regions: %.1fms (%.1f%%)", m_buildTimes.buildRegions/1000.0f, m_buildTimes.buildRegions*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - watershed: %.1fms (%.1f%%)", m_buildTimes.buildRegionsReg/1000.0f, m_buildTimes.buildRegionsReg*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - expand: %.1fms (%.1f%%)", m_buildTimes.buildRegionsExp/1000.0f, m_buildTimes.buildRegionsExp*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - find catchment basins: %.1fms (%.1f%%)", m_buildTimes.buildRegionsFlood/1000.0f, m_buildTimes.buildRegionsFlood*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - filter: %.1fms (%.1f%%)", m_buildTimes.buildRegionsFilter/1000.0f, m_buildTimes.buildRegionsFilter*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Contours: %.1fms (%.1f%%)", m_buildTimes.buildContours/1000.0f, m_buildTimes.buildContours*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - trace: %.1fms (%.1f%%)", m_buildTimes.buildContoursTrace/1000.0f, m_buildTimes.buildContoursTrace*pc);
+ rcGetLog()->log(RC_LOG_PROGRESS, " - simplify: %.1fms (%.1f%%)", m_buildTimes.buildContoursSimplify/1000.0f, m_buildTimes.buildContoursSimplify*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Fixup contours: %.1fms (%.1f%%)", m_buildTimes.fixupContours/1000.0f, m_buildTimes.fixupContours*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Build Polymesh: %.1fms (%.1f%%)", m_buildTimes.buildPolymesh/1000.0f, m_buildTimes.buildPolymesh*pc);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "Polymesh: Verts:%d Polys:%d", m_polyMesh->nverts, m_polyMesh->npolys);
+
+ rcGetLog()->log(RC_LOG_PROGRESS, "TOTAL: %.1fms", rcGetDeltaTimeUsec(totStartTime, totEndTime)/1000.0f);
+ }
+
+ m_tileBuildTime = rcGetDeltaTimeUsec(totStartTime, totEndTime)/1000.0f;
+
+ dataSize = navDataSize;
+ return navData;
+}