瀏覽代碼

rearranged folders

Ashwini 5 年之前
父節點
當前提交
1524ad0034
共有 69 個文件被更改,包括 200 次插入11496 次删除
  1. 70 91
      makepanda/makepanda.py
  2. 40 64
      makepanda/makepanda.vcproj
  3. 29 0
      panda/src/navigation/Detour/CMakeLists.txt
  4. 0 0
      panda/src/navigation/Detour/Include/DetourAlloc.h
  5. 0 0
      panda/src/navigation/Detour/Include/DetourAssert.h
  6. 0 0
      panda/src/navigation/Detour/Include/DetourCommon.h
  7. 0 0
      panda/src/navigation/Detour/Include/DetourMath.h
  8. 0 0
      panda/src/navigation/Detour/Include/DetourNavMesh.h
  9. 0 0
      panda/src/navigation/Detour/Include/DetourNavMeshBuilder.h
  10. 0 0
      panda/src/navigation/Detour/Include/DetourNavMeshQuery.h
  11. 0 0
      panda/src/navigation/Detour/Include/DetourNode.h
  12. 0 0
      panda/src/navigation/Detour/Include/DetourStatus.h
  13. 0 0
      panda/src/navigation/Detour/Source/DetourAlloc.cpp
  14. 0 0
      panda/src/navigation/Detour/Source/DetourAssert.cpp
  15. 0 0
      panda/src/navigation/Detour/Source/DetourCommon.cpp
  16. 0 0
      panda/src/navigation/Detour/Source/DetourNavMesh.cpp
  17. 0 0
      panda/src/navigation/Detour/Source/DetourNavMeshBuilder.cpp
  18. 0 0
      panda/src/navigation/Detour/Source/DetourNavMeshQuery.cpp
  19. 0 0
      panda/src/navigation/Detour/Source/DetourNode.cpp
  20. 0 0
      panda/src/navigation/InputGeom.cxx
  21. 0 0
      panda/src/navigation/MeshLoaderObj.cxx
  22. 0 0
      panda/src/navigation/NavMeshSample.cxx
  23. 29 0
      panda/src/navigation/Recast/CMakeLists.txt
  24. 0 0
      panda/src/navigation/Recast/Include/Recast.h
  25. 0 0
      panda/src/navigation/Recast/Include/RecastAlloc.h
  26. 0 0
      panda/src/navigation/Recast/Include/RecastAssert.h
  27. 0 0
      panda/src/navigation/Recast/Source/Recast.cpp
  28. 0 0
      panda/src/navigation/Recast/Source/RecastAlloc.cpp
  29. 0 0
      panda/src/navigation/Recast/Source/RecastArea.cpp
  30. 0 0
      panda/src/navigation/Recast/Source/RecastAssert.cpp
  31. 0 0
      panda/src/navigation/Recast/Source/RecastContour.cpp
  32. 0 0
      panda/src/navigation/Recast/Source/RecastFilter.cpp
  33. 0 0
      panda/src/navigation/Recast/Source/RecastLayers.cpp
  34. 0 0
      panda/src/navigation/Recast/Source/RecastMesh.cpp
  35. 0 0
      panda/src/navigation/Recast/Source/RecastMeshDetail.cpp
  36. 0 0
      panda/src/navigation/Recast/Source/RecastRasterization.cpp
  37. 0 0
      panda/src/navigation/Recast/Source/RecastRegion.cpp
  38. 9 9
      panda/src/navigation/config_navigation.cxx
  39. 17 0
      panda/src/navigation/config_navigation.h
  40. 1 1
      panda/src/navigation/p3navigation_composite1.cxx
  41. 5 5
      panda/src/pandabase/pandasymbols.h
  42. 0 612
      panda/src/recastdetour/DebugDraw.cpp
  43. 0 223
      panda/src/recastdetour/DebugDraw.h
  44. 0 1448
      panda/src/recastdetour/DetourCrowd.cpp
  45. 0 460
      panda/src/recastdetour/DetourCrowd.h
  46. 0 864
      panda/src/recastdetour/DetourDebugDraw.cpp
  47. 0 48
      panda/src/recastdetour/DetourDebugDraw.h
  48. 0 137
      panda/src/recastdetour/DetourLocalBoundary.cpp
  49. 0 66
      panda/src/recastdetour/DetourLocalBoundary.h
  50. 0 619
      panda/src/recastdetour/DetourObstacleAvoidance.cpp
  51. 0 159
      panda/src/recastdetour/DetourObstacleAvoidance.h
  52. 0 597
      panda/src/recastdetour/DetourPathCorridor.cpp
  53. 0 151
      panda/src/recastdetour/DetourPathCorridor.h
  54. 0 200
      panda/src/recastdetour/DetourPathQueue.cpp
  55. 0 79
      panda/src/recastdetour/DetourPathQueue.h
  56. 0 194
      panda/src/recastdetour/DetourProximityGrid.cpp
  57. 0 74
      panda/src/recastdetour/DetourProximityGrid.h
  58. 0 820
      panda/src/recastdetour/DetourTileCache.cpp
  59. 0 262
      panda/src/recastdetour/DetourTileCache.h
  60. 0 2250
      panda/src/recastdetour/DetourTileCacheBuilder.cpp
  61. 0 156
      panda/src/recastdetour/DetourTileCacheBuilder.h
  62. 0 135
      panda/src/recastdetour/InputGeom.h
  63. 0 50
      panda/src/recastdetour/MeshLoaderObj.h
  64. 0 105
      panda/src/recastdetour/NavMeshSample.h
  65. 0 1064
      panda/src/recastdetour/RecastDebugDraw.cpp
  66. 0 42
      panda/src/recastdetour/RecastDebugDraw.h
  67. 0 451
      panda/src/recastdetour/RecastDump.cpp
  68. 0 43
      panda/src/recastdetour/RecastDump.h
  69. 0 17
      panda/src/recastdetour/config_recastdetour.h

+ 70 - 91
makepanda/makepanda.py

@@ -95,7 +95,7 @@ PkgListSet(["PYTHON", "DIRECT",                        # Python support
   "PANDAPARTICLESYSTEM",                               # Built in particle system
   "CONTRIB",                                           # Experimental
   "SSE2", "NEON",                                      # Compiler features
-  "RECASTDETOUR",				       # Recast Detour Toolset
+  "NAVIGATION",				       # Recast Detour Toolset
 ])
 
 CheckPandaSourceTree()
@@ -2640,8 +2640,8 @@ if not PkgSkip("DIRECT"):
     panda_modules.append('direct')
 if not PkgSkip("VISION"):
     panda_modules.append('vision')
-if not PkgSkip("RECASTDETOUR"):
-    panda_modules.append('recastdetour')
+if not PkgSkip("NAVIGATION"):
+    panda_modules.append('navigation')
 if not PkgSkip("SKEL"):
     panda_modules.append('skel')
 if not PkgSkip("EGG"):
@@ -3047,8 +3047,9 @@ CopyAllHeaders('panda/src/text')
 CopyAllHeaders('panda/src/grutil')
 if (PkgSkip("VISION")==0):
     CopyAllHeaders('panda/src/vision')
-if (PkgSkip("RECASTDETOUR")==0):
-    CopyAllHeaders('panda/src/recastdetour')
+if (PkgSkip("NAVIGATION")==0):
+    CopyAllHeaders('panda/src/navigation/Recast/Include')
+    CopyAllHeaders('panda/src/navigation/Detour/Include')
 if (PkgSkip("FFMPEG")==0):
     CopyAllHeaders('panda/src/ffmpeg')
 CopyAllHeaders('panda/src/tform')
@@ -4126,92 +4127,70 @@ if (PkgSkip("VISION") == 0):
   PyTargetAdd('vision.pyd', input=COMMON_PANDA_LIBS)
 
 #
-# DIRECTORY: panda/src/recastdetour/
-#
-
-if (PkgSkip("RECASTDETOUR") == 0):
-  OPTS=['DIR:panda/src/recastdetour', 'BUILDING:RECASTDETOUR']
-  TargetAdd('p3recastdetour_composite1.obj', opts=OPTS, input='p3recastdetour_composite1.cxx')
-  TargetAdd('p3recastdetour_DebugDraw.obj', opts=OPTS,  input='DebugDraw.cpp')
-  TargetAdd('p3recastdetour_DetourAlloc.obj', opts=OPTS,  input='DetourAlloc.cpp')
-  TargetAdd('p3recastdetour_DetourAssert.obj', opts=OPTS,  input='DetourAssert.cpp')
-  TargetAdd('p3recastdetour_DetourCommon.obj', opts=OPTS,  input='DetourCommon.cpp')
-  TargetAdd('p3recastdetour_DetourCrowd.obj', opts=OPTS,  input='DetourCrowd.cpp')
-  TargetAdd('p3recastdetour_DetourDebugDraw.obj', opts=OPTS,  input='DetourDebugDraw.cpp')
-  TargetAdd('p3recastdetour_DetourLocalBoundary.obj', opts=OPTS,  input='DetourLocalBoundary.cpp')
-  TargetAdd('p3recastdetour_DetourNavMesh.obj', opts=OPTS,  input='DetourNavMesh.cpp')
-  TargetAdd('p3recastdetour_DetourNavMeshBuilder.obj', opts=OPTS,  input='DetourNavMeshBuilder.cpp')
-  TargetAdd('p3recastdetour_DetourNavMeshQuery.obj', opts=OPTS,  input='DetourNavMeshQuery.cpp')
-  TargetAdd('p3recastdetour_DetourNode.obj', opts=OPTS,  input='DetourNode.cpp')
-  TargetAdd('p3recastdetour_DetourObstacleAvoidance.obj', opts=OPTS,  input='DetourObstacleAvoidance.cpp')
-  TargetAdd('p3recastdetour_DetourPathCorridor.obj', opts=OPTS,  input='DetourPathCorridor.cpp')
-  TargetAdd('p3recastdetour_DetourPathQueue.obj', opts=OPTS,  input='DetourPathQueue.cpp')
-  TargetAdd('p3recastdetour_DetourProximityGrid.obj', opts=OPTS,  input='DetourProximityGrid.cpp')
-  TargetAdd('p3recastdetour_DetourTileCache.obj', opts=OPTS,  input='DetourTileCache.cpp')
-  TargetAdd('p3recastdetour_DetourTileCacheBuilder.obj', opts=OPTS,  input='DetourTileCacheBuilder.cpp')
-  TargetAdd('p3recastdetour_Recast.obj', opts=OPTS,  input='Recast.cpp')
-  TargetAdd('p3recastdetour_RecastAlloc.obj', opts=OPTS,  input='RecastAlloc.cpp')
-  TargetAdd('p3recastdetour_RecastArea.obj', opts=OPTS,  input='RecastArea.cpp')
-  TargetAdd('p3recastdetour_RecastAssert.obj', opts=OPTS,  input='RecastAssert.cpp')
-  TargetAdd('p3recastdetour_RecastContour.obj', opts=OPTS,  input='RecastContour.cpp')
-  TargetAdd('p3recastdetour_RecastDebugDraw.obj', opts=OPTS,  input='RecastDebugDraw.cpp')
-  TargetAdd('p3recastdetour_RecastDump.obj', opts=OPTS,  input='RecastDump.cpp')
-  TargetAdd('p3recastdetour_RecastFilter.obj', opts=OPTS,  input='RecastFilter.cpp')
-  TargetAdd('p3recastdetour_RecastLayers.obj', opts=OPTS,  input='RecastLayers.cpp')
-  TargetAdd('p3recastdetour_RecastMesh.obj', opts=OPTS,  input='RecastMesh.cpp')
-  TargetAdd('p3recastdetour_RecastMeshDetail.obj', opts=OPTS,  input='RecastMeshDetail.cpp')
-  TargetAdd('p3recastdetour_RecastRasterization.obj', opts=OPTS,  input='RecastRasterization.cpp')
-  TargetAdd('p3recastdetour_RecastRegion.obj', opts=OPTS,  input='RecastRegion.cpp')
-
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_composite1.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DebugDraw.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourAlloc.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourAssert.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourCommon.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourCrowd.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourDebugDraw.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourLocalBoundary.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourNavMesh.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourNavMeshBuilder.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourNavMeshQuery.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourNode.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourObstacleAvoidance.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourPathCorridor.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourPathQueue.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourProximityGrid.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourTileCache.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_DetourTileCacheBuilder.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_Recast.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastAlloc.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastArea.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastAssert.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastContour.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastDebugDraw.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastDump.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastFilter.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastLayers.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastMesh.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastMeshDetail.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastRasterization.obj')
-  TargetAdd('libp3recastdetour.dll', input='p3recastdetour_RecastRegion.obj')
-  TargetAdd('libp3recastdetour.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libp3recastdetour.dll', opts=OPTS)
-
-  OPTS=['DIR:panda/src/recastdetour']
-  IGATEFILES = ["config_recastdetour.h", "p3recastdetour_composite1.cxx"]
-  TargetAdd('libp3recastdetour.in', opts=OPTS, input=IGATEFILES)
-  TargetAdd('libp3recastdetour.in', opts=['IMOD:panda3d.recastdetour', 'ILIB:libp3recastdetour', 'SRCDIR:panda/src/recastdetour'])
-
-
-  PyTargetAdd('recastdetour_module.obj', input='libp3recastdetour.in')
-  PyTargetAdd('recastdetour_module.obj', opts=OPTS)
-  PyTargetAdd('recastdetour_module.obj', opts=['IMOD:panda3d.recastdetour', 'ILIB:recastdetour', 'IMPORT:panda3d.core'])
-
-  PyTargetAdd('recastdetour.pyd', input='recastdetour_module.obj')
-  PyTargetAdd('recastdetour.pyd', input='libp3recastdetour_igate.obj')
-  PyTargetAdd('recastdetour.pyd', input='libp3recastdetour.dll')
-  PyTargetAdd('recastdetour.pyd', input='libp3interrogatedb.dll')
-  PyTargetAdd('recastdetour.pyd', input=COMMON_PANDA_LIBS)
+# DIRECTORY: panda/src/navigation/
+#
+
+if (PkgSkip("NAVIGATION") == 0):
+  OPTS=['DIR:panda/src/navigation', 'BUILDING:NAVIGATION']
+  TargetAdd('p3navigation_composite1.obj', opts=OPTS, input='p3navigation_composite1.cxx')
+  OPTS=['DIR:panda/src/navigation/Detour/Source', 'BUILDING:NAVIGATION']
+  TargetAdd('p3navigation_DetourAlloc.obj', opts=OPTS,  input='DetourAlloc.cpp')
+  TargetAdd('p3navigation_DetourAssert.obj', opts=OPTS,  input='DetourAssert.cpp')
+  TargetAdd('p3navigation_DetourCommon.obj', opts=OPTS,  input='DetourCommon.cpp')
+  TargetAdd('p3navigation_DetourNavMesh.obj', opts=OPTS,  input='DetourNavMesh.cpp')
+  TargetAdd('p3navigation_DetourNavMeshBuilder.obj', opts=OPTS,  input='DetourNavMeshBuilder.cpp')
+  TargetAdd('p3navigation_DetourNavMeshQuery.obj', opts=OPTS,  input='DetourNavMeshQuery.cpp')
+  TargetAdd('p3navigation_DetourNode.obj', opts=OPTS,  input='DetourNode.cpp')
+  OPTS=['DIR:panda/src/navigation/Recast/Source', 'BUILDING:NAVIGATION']
+  TargetAdd('p3navigation_Recast.obj', opts=OPTS,  input='Recast.cpp')
+  TargetAdd('p3navigation_RecastAlloc.obj', opts=OPTS,  input='RecastAlloc.cpp')
+  TargetAdd('p3navigation_RecastArea.obj', opts=OPTS,  input='RecastArea.cpp')
+  TargetAdd('p3navigation_RecastAssert.obj', opts=OPTS,  input='RecastAssert.cpp')
+  TargetAdd('p3navigation_RecastContour.obj', opts=OPTS,  input='RecastContour.cpp')
+  TargetAdd('p3navigation_RecastFilter.obj', opts=OPTS,  input='RecastFilter.cpp')
+  TargetAdd('p3navigation_RecastLayers.obj', opts=OPTS,  input='RecastLayers.cpp')
+  TargetAdd('p3navigation_RecastMesh.obj', opts=OPTS,  input='RecastMesh.cpp')
+  TargetAdd('p3navigation_RecastMeshDetail.obj', opts=OPTS,  input='RecastMeshDetail.cpp')
+  TargetAdd('p3navigation_RecastRasterization.obj', opts=OPTS,  input='RecastRasterization.cpp')
+  TargetAdd('p3navigation_RecastRegion.obj', opts=OPTS,  input='RecastRegion.cpp')
+
+  TargetAdd('libp3navigation.dll', input='p3navigation_composite1.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_DetourAlloc.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_DetourAssert.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_DetourCommon.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_DetourNavMesh.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_DetourNavMeshBuilder.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_DetourNavMeshQuery.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_DetourNode.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_Recast.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastAlloc.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastArea.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastAssert.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastContour.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastFilter.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastLayers.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastMesh.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastMeshDetail.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastRasterization.obj')
+  TargetAdd('libp3navigation.dll', input='p3navigation_RecastRegion.obj')
+  TargetAdd('libp3navigation.dll', input=COMMON_PANDA_LIBS)
+  TargetAdd('libp3navigation.dll', opts=OPTS)
+
+  OPTS=['DIR:panda/src/navigation']
+  IGATEFILES = ["config_navigation.h", "p3navigation_composite1.cxx"]
+  TargetAdd('libp3navigation.in', opts=OPTS, input=IGATEFILES)
+  TargetAdd('libp3navigation.in', opts=['IMOD:panda3d.navigation', 'ILIB:libp3navigation', 'SRCDIR:panda/src/navigation'])
+
+
+  PyTargetAdd('navigation_module.obj', input='libp3navigation.in')
+  PyTargetAdd('navigation_module.obj', opts=OPTS)
+  PyTargetAdd('navigation_module.obj', opts=['IMOD:panda3d.navigation', 'ILIB:navigation', 'IMPORT:panda3d.core'])
+
+  PyTargetAdd('navigation.pyd', input='navigation_module.obj')
+  PyTargetAdd('navigation.pyd', input='libp3navigation_igate.obj')
+  PyTargetAdd('navigation.pyd', input='libp3navigation.dll')
+  PyTargetAdd('navigation.pyd', input='libp3interrogatedb.dll')
+  PyTargetAdd('navigation.pyd', input=COMMON_PANDA_LIBS)
 
 
 #

+ 40 - 64
makepanda/makepanda.vcproj

@@ -648,70 +648,46 @@
 				<File RelativePath="..\panda\src\vision\webcamVideo.cxx"></File>
 				<File RelativePath="..\panda\src\vision\arToolKit.cxx"></File>
 			</Filter>
-			<Filter Name="recastdetour">
-				<File RelativePath="..\panda\src\recastdetour\InputGeom.cxx"></File>
-				<File RelativePath="..\panda\src\recastdetour\InputGeom.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\MeshLoaderObj.cxx"></File>
-				<File RelativePath="..\panda\src\recastdetour\MeshLoaderObj.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\NavMeshSample.cxx"></File>
-				<File RelativePath="..\panda\src\recastdetour\NavMeshSample.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DebugDraw.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DebugDraw.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourAlloc.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourAlloc.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourAssert.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourAssert.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourCommon.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourCommon.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourCrowd.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourCrowd.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourDebugDraw.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourDebugDraw.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourLocalBoundary.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourLocalBoundary.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourMath.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNavMesh.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNavMesh.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNavMeshBuilder.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNavMeshBuilder.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNavMeshQuery.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNavMeshQuery.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNode.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourNode.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourObstacleAvoidance.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourObstacleAvoidance.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourPathCorridor.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourPathCorridor.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourPathQueue.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourPathQueue.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourProximityGrid.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourProximityGrid.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourStatus.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourTileCache.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourTileCache.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourTileCacheBuilder.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\DetourTileCacheBuilder.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\Recast.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\Recast.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastAlloc.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastAlloc.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastArea.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastAssert.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastAssert.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastContour.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastDebugDraw.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastDebugDraw.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastDump.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastDump.h"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastFilter.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastLayers.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastMesh.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastMeshDetail.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastRasterization.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\RecastRegion.cpp"></File>
-				<File RelativePath="..\panda\src\recastdetour\recastdetour_composite1.cxx"></File>
-				<File RelativePath="..\panda\src\recastdetour\config_recastdetour.cxx"></File>
-				<File RelativePath="..\panda\src\recastdetour\config_recastdetour.h"></File>
+			<Filter Name="navigation">
+				<File RelativePath="..\panda\src\navigation\InputGeom.cxx"></File>
+				<File RelativePath="..\panda\src\navigation\InputGeom.h"></File>
+				<File RelativePath="..\panda\src\navigation\MeshLoaderObj.cxx"></File>
+				<File RelativePath="..\panda\src\navigation\MeshLoaderObj.h"></File>
+				<File RelativePath="..\panda\src\navigation\NavMeshSample.cxx"></File>
+				<File RelativePath="..\panda\src\navigation\NavMeshSample.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Source\DetourAlloc.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Source\DetourAssert.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Source\DetourCommon.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Source\DetourNavMesh.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Source\DetourNavMeshBuilder.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Source\DetourNavMeshQuery.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Source\DetourNode.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourAlloc.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourAssert.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourCommon.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourMath.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourNavMesh.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourNavMeshBuilder.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourNavMeshQuery.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourNode.h"></File>
+				<File RelativePath="..\panda\src\navigation\Detour\Include\DetourStatus.h"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\Recast.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastAlloc.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastArea.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastAssert.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastContour.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastFilter.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastLayers.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastMesh.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastMeshDetail.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastRasterization.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Source\RecastRegion.cpp"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Include\Recast.h"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Include\RecastAlloc.h"></File>
+				<File RelativePath="..\panda\src\navigation\Recast\Include\RecastAssert.h"></File>
+				<File RelativePath="..\panda\src\navigation\navigation_composite1.cxx"></File>
+				<File RelativePath="..\panda\src\navigation\config_navigation.cxx"></File>
+				<File RelativePath="..\panda\src\navigation\config_navigation.h"></File>
 			</Filter>
 			<Filter Name="gobj">
 				<File RelativePath="..\panda\src\gobj\geomEnums.cxx"></File>

+ 29 - 0
panda/src/navigation/Detour/CMakeLists.txt

@@ -0,0 +1,29 @@
+file(GLOB SOURCES Source/*.cpp)
+
+if(RECASTNAVIGATION_STATIC)
+    add_library(Detour STATIC ${SOURCES})
+else()
+    add_library(Detour SHARED ${SOURCES})
+endif()
+
+add_library(RecastNavigation::Detour ALIAS Detour)
+
+set(Detour_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include")
+
+target_include_directories(Detour PUBLIC
+    "$<BUILD_INTERFACE:${Detour_INCLUDE_DIR}>"
+)
+
+set_target_properties(Detour PROPERTIES
+        SOVERSION ${SOVERSION}
+        VERSION ${VERSION}
+        )
+
+install(TARGETS Detour
+        ARCHIVE DESTINATION lib
+        LIBRARY DESTINATION lib
+        COMPONENT library
+        )
+
+file(GLOB INCLUDES Include/*.h)
+install(FILES ${INCLUDES} DESTINATION include)

+ 0 - 0
panda/src/recastdetour/DetourAlloc.h → panda/src/navigation/Detour/Include/DetourAlloc.h


+ 0 - 0
panda/src/recastdetour/DetourAssert.h → panda/src/navigation/Detour/Include/DetourAssert.h


+ 0 - 0
panda/src/recastdetour/DetourCommon.h → panda/src/navigation/Detour/Include/DetourCommon.h


+ 0 - 0
panda/src/recastdetour/DetourMath.h → panda/src/navigation/Detour/Include/DetourMath.h


+ 0 - 0
panda/src/recastdetour/DetourNavMesh.h → panda/src/navigation/Detour/Include/DetourNavMesh.h


+ 0 - 0
panda/src/recastdetour/DetourNavMeshBuilder.h → panda/src/navigation/Detour/Include/DetourNavMeshBuilder.h


+ 0 - 0
panda/src/recastdetour/DetourNavMeshQuery.h → panda/src/navigation/Detour/Include/DetourNavMeshQuery.h


+ 0 - 0
panda/src/recastdetour/DetourNode.h → panda/src/navigation/Detour/Include/DetourNode.h


+ 0 - 0
panda/src/recastdetour/DetourStatus.h → panda/src/navigation/Detour/Include/DetourStatus.h


+ 0 - 0
panda/src/recastdetour/DetourAlloc.cpp → panda/src/navigation/Detour/Source/DetourAlloc.cpp


+ 0 - 0
panda/src/recastdetour/DetourAssert.cpp → panda/src/navigation/Detour/Source/DetourAssert.cpp


+ 0 - 0
panda/src/recastdetour/DetourCommon.cpp → panda/src/navigation/Detour/Source/DetourCommon.cpp


+ 0 - 0
panda/src/recastdetour/DetourNavMesh.cpp → panda/src/navigation/Detour/Source/DetourNavMesh.cpp


+ 0 - 0
panda/src/recastdetour/DetourNavMeshBuilder.cpp → panda/src/navigation/Detour/Source/DetourNavMeshBuilder.cpp


+ 0 - 0
panda/src/recastdetour/DetourNavMeshQuery.cpp → panda/src/navigation/Detour/Source/DetourNavMeshQuery.cpp


+ 0 - 0
panda/src/recastdetour/DetourNode.cpp → panda/src/navigation/Detour/Source/DetourNode.cpp


+ 0 - 0
panda/src/recastdetour/InputGeom.cxx → panda/src/navigation/InputGeom.cxx


+ 0 - 0
panda/src/recastdetour/MeshLoaderObj.cxx → panda/src/navigation/MeshLoaderObj.cxx


+ 0 - 0
panda/src/recastdetour/NavMeshSample.cxx → panda/src/navigation/NavMeshSample.cxx


+ 29 - 0
panda/src/navigation/Recast/CMakeLists.txt

@@ -0,0 +1,29 @@
+file(GLOB SOURCES Source/*.cpp)
+
+if (RECASTNAVIGATION_STATIC)
+    add_library(Recast STATIC ${SOURCES})
+else ()
+    add_library(Recast SHARED ${SOURCES})
+endif ()
+
+add_library(RecastNavigation::Recast ALIAS Recast)
+
+set(Recast_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include")
+
+target_include_directories(Recast PUBLIC
+    "$<BUILD_INTERFACE:${Recast_INCLUDE_DIR}>"
+)
+
+set_target_properties(Recast PROPERTIES
+        SOVERSION ${SOVERSION}
+        VERSION ${VERSION}
+        )
+
+install(TARGETS Recast
+        ARCHIVE DESTINATION lib
+        LIBRARY DESTINATION lib
+        COMPONENT library
+        )
+
+file(GLOB INCLUDES Include/*.h)
+install(FILES ${INCLUDES} DESTINATION include)

+ 0 - 0
panda/src/recastdetour/Recast.h → panda/src/navigation/Recast/Include/Recast.h


+ 0 - 0
panda/src/recastdetour/RecastAlloc.h → panda/src/navigation/Recast/Include/RecastAlloc.h


+ 0 - 0
panda/src/recastdetour/RecastAssert.h → panda/src/navigation/Recast/Include/RecastAssert.h


+ 0 - 0
panda/src/recastdetour/Recast.cpp → panda/src/navigation/Recast/Source/Recast.cpp


+ 0 - 0
panda/src/recastdetour/RecastAlloc.cpp → panda/src/navigation/Recast/Source/RecastAlloc.cpp


+ 0 - 0
panda/src/recastdetour/RecastArea.cpp → panda/src/navigation/Recast/Source/RecastArea.cpp


+ 0 - 0
panda/src/recastdetour/RecastAssert.cpp → panda/src/navigation/Recast/Source/RecastAssert.cpp


+ 0 - 0
panda/src/recastdetour/RecastContour.cpp → panda/src/navigation/Recast/Source/RecastContour.cpp


+ 0 - 0
panda/src/recastdetour/RecastFilter.cpp → panda/src/navigation/Recast/Source/RecastFilter.cpp


+ 0 - 0
panda/src/recastdetour/RecastLayers.cpp → panda/src/navigation/Recast/Source/RecastLayers.cpp


+ 0 - 0
panda/src/recastdetour/RecastMesh.cpp → panda/src/navigation/Recast/Source/RecastMesh.cpp


+ 0 - 0
panda/src/recastdetour/RecastMeshDetail.cpp → panda/src/navigation/Recast/Source/RecastMeshDetail.cpp


+ 0 - 0
panda/src/recastdetour/RecastRasterization.cpp → panda/src/navigation/Recast/Source/RecastRasterization.cpp


+ 0 - 0
panda/src/recastdetour/RecastRegion.cpp → panda/src/navigation/Recast/Source/RecastRegion.cpp


+ 9 - 9
panda/src/recastdetour/config_recastdetour.cxx → panda/src/navigation/config_navigation.cxx

@@ -1,6 +1,6 @@
 
 
-#include "config_recastdetour.h"
+#include "config_navigation.h"
 
 #include "pandaSystem.h"
 #include "dconfig.h"
@@ -9,18 +9,18 @@
 #include "NavMeshSample.h"
 
 #if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_RECASTDETOUR)
-  #error Buildsystem error: BUILDING_RECASTDETOUR not defined
+  #error Buildsystem error: BUILDING_NAVIGATION not defined
 #endif
 
-Configure(config_recastdetour);
-NotifyCategoryDef(recastdetour, "");
+Configure(config_navigation);
+NotifyCategoryDef(navigation, "");
 
-ConfigureFn(config_recastdetour) {
-  init_librecastdetour();
+ConfigureFn(config_navigation) {
+  init_libnavigation();
 }
 
-ConfigVariableInt recastdetour_sample_config_variable
-("recastdetour-sample-config-variable", 25);
+ConfigVariableInt navigation_sample_config_variable
+("navigation-sample-config-variable", 25);
 
 /**
  * Initializes the library.  This must be called at least once before any of
@@ -29,7 +29,7 @@ ConfigVariableInt recastdetour_sample_config_variable
  * special cases exist.
  */
 void
-init_librecastdetour() {
+init_libnavigation() {
   static bool initialized = false;
   if (initialized) {
     return;

+ 17 - 0
panda/src/navigation/config_navigation.h

@@ -0,0 +1,17 @@
+
+#ifndef CONFIG_NAVIGATION_H
+#define CONFIG_NAVIGATION_H
+
+#include "pandabase.h"
+#include "notifyCategoryProxy.h"
+#include "configVariableDouble.h"
+#include "configVariableString.h"
+#include "configVariableInt.h"
+
+NotifyCategoryDecl(navigation, EXPCL_NAVIGATION, EXPTP_NAVIGATION);
+
+extern ConfigVariableInt    navigation_sample_config_variable;
+
+extern EXPCL_NAVIGATION void init_libnavigation();
+
+#endif

+ 1 - 1
panda/src/recastdetour/p3recastdetour_composite1.cxx → panda/src/navigation/p3navigation_composite1.cxx

@@ -1,4 +1,4 @@
-#include "config_recastdetour.cxx"
+#include "config_navigation.cxx"
 #include "InputGeom.cxx"
 #include "MeshLoaderObj.cxx"
 #include "NavMeshSample.cxx"

+ 5 - 5
panda/src/pandabase/pandasymbols.h

@@ -579,12 +579,12 @@
   #define EXPTP_VISION IMPORT_TEMPL
 #endif
 
-#ifdef BUILDING_RECASTDETOUR
-  #define EXPCL_RECASTDETOUR EXPORT_CLASS
-  #define EXPTP_RECASTDETOUR EXPORT_TEMPL
+#ifdef BUILDING_NAVIGATION
+  #define EXPCL_NAVIGATION EXPORT_CLASS
+  #define EXPTP_NAVIGATION EXPORT_TEMPL
 #else
-  #define EXPCL_RECASTDETOUR IMPORT_CLASS
-  #define EXPTP_RECASTDETOUR IMPORT_TEMPL
+  #define EXPCL_NAVIGATION IMPORT_CLASS
+  #define EXPTP_NAVIGATION IMPORT_TEMPL
 #endif
 
 #ifdef BUILDING_VRPN

+ 0 - 612
panda/src/recastdetour/DebugDraw.cpp

@@ -1,612 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 <string.h>
-#include "DebugDraw.h"
-#include "DetourMath.h"
-#include "DetourNavMesh.h"
-
-
-duDebugDraw::~duDebugDraw()
-{
-	// Empty
-}
-
-unsigned int duDebugDraw::areaToCol(unsigned int area)
-{
-	if (area == 0)
-	{
-		// Treat zero area type as default.
-		return duRGBA(0, 192, 255, 255);
-	}
-	else
-	{
-		return duIntToCol(area, 255);
-	}
-}
-
-inline int bit(int a, int b)
-{
-	return (a & (1 << b)) >> b;
-}
-
-unsigned int duIntToCol(int i, int a)
-{
-	int	r = bit(i, 1) + bit(i, 3) * 2 + 1;
-	int	g = bit(i, 2) + bit(i, 4) * 2 + 1;
-	int	b = bit(i, 0) + bit(i, 5) * 2 + 1;
-	return duRGBA(r*63,g*63,b*63,a);
-}
-
-void duIntToCol(int i, float* col)
-{
-	int	r = bit(i, 0) + bit(i, 3) * 2 + 1;
-	int	g = bit(i, 1) + bit(i, 4) * 2 + 1;
-	int	b = bit(i, 2) + bit(i, 5) * 2 + 1;
-	col[0] = 1 - r*63.0f/255.0f;
-	col[1] = 1 - g*63.0f/255.0f;
-	col[2] = 1 - b*63.0f/255.0f;
-}
-
-void duCalcBoxColors(unsigned int* colors, unsigned int colTop, unsigned int colSide)
-{
-	if (!colors) return;
-	
-	colors[0] = duMultCol(colTop, 250);
-	colors[1] = duMultCol(colSide, 140);
-	colors[2] = duMultCol(colSide, 165);
-	colors[3] = duMultCol(colSide, 217);
-	colors[4] = duMultCol(colSide, 165);
-	colors[5] = duMultCol(colSide, 217);
-}
-
-void duDebugDrawCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-							 float maxx, float maxy, float maxz, unsigned int col, const float lineWidth)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_LINES, lineWidth);
-	duAppendCylinderWire(dd, minx,miny,minz, maxx,maxy,maxz, col);
-	dd->end();
-}
-
-void duDebugDrawBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-						float maxx, float maxy, float maxz, unsigned int col, const float lineWidth)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_LINES, lineWidth);
-	duAppendBoxWire(dd, minx,miny,minz, maxx,maxy,maxz, col);
-	dd->end();
-}
-
-void duDebugDrawArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-					const float x1, const float y1, const float z1, const float h,
-					const float as0, const float as1, unsigned int col, const float lineWidth)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_LINES, lineWidth);
-	duAppendArc(dd, x0,y0,z0, x1,y1,z1, h, as0, as1, col);
-	dd->end();
-}
-
-void duDebugDrawArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-					  const float x1, const float y1, const float z1,
-					  const float as0, const float as1, unsigned int col, const float lineWidth)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_LINES, lineWidth);
-	duAppendArrow(dd, x0,y0,z0, x1,y1,z1, as0, as1, col);
-	dd->end();
-}
-
-void duDebugDrawCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
-					   const float r, unsigned int col, const float lineWidth)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_LINES, lineWidth);
-	duAppendCircle(dd, x,y,z, r, col);
-	dd->end();
-}
-
-void duDebugDrawCross(struct duDebugDraw* dd, const float x, const float y, const float z,
-					  const float size, unsigned int col, const float lineWidth)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_LINES, lineWidth);
-	duAppendCross(dd, x,y,z, size, col);
-	dd->end();
-}
-
-void duDebugDrawBox(struct duDebugDraw* dd, float minx, float miny, float minz,
-					float maxx, float maxy, float maxz, const unsigned int* fcol)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_QUADS);
-	duAppendBox(dd, minx,miny,minz, maxx,maxy,maxz, fcol);
-	dd->end();
-}
-
-void duDebugDrawCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
-						 float maxx, float maxy, float maxz, unsigned int col)
-{
-	if (!dd) return;
-	
-	dd->begin(DU_DRAW_TRIS);
-	duAppendCylinder(dd, minx,miny,minz, maxx,maxy,maxz, col);
-	dd->end();
-}
-
-void duDebugDrawGridXZ(struct duDebugDraw* dd, const float ox, const float oy, const float oz,
-					   const int w, const int h, const float size,
-					   const unsigned int col, const float lineWidth)
-{
-	if (!dd) return;
-
-	dd->begin(DU_DRAW_LINES, lineWidth);
-	for (int i = 0; i <= h; ++i)
-	{
-		dd->vertex(ox,oy,oz+i*size, col);
-		dd->vertex(ox+w*size,oy,oz+i*size, col);
-	}
-	for (int i = 0; i <= w; ++i)
-	{
-		dd->vertex(ox+i*size,oy,oz, col);
-		dd->vertex(ox+i*size,oy,oz+h*size, col);
-	}
-	dd->end();
-}
-		 
-
-void duAppendCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-						  float maxx, float maxy, float maxz, unsigned int col)
-{
-	if (!dd) return;
-
-	static const int NUM_SEG = 16;
-	static float dir[NUM_SEG*2];
-	static bool init = false;
-	if (!init)
-	{
-		init = true;
-		for (int i = 0; i < NUM_SEG; ++i)
-		{
-			const float a = (float)i/(float)NUM_SEG*DU_PI*2;
-			dir[i*2] = dtMathCosf(a);
-			dir[i*2+1] = dtMathSinf(a);
-		}
-	}
-	
-	const float cx = (maxx + minx)/2;
-	const float cz = (maxz + minz)/2;
-	const float rx = (maxx - minx)/2;
-	const float rz = (maxz - minz)/2;
-	
-	for (int i = 0, j = NUM_SEG-1; i < NUM_SEG; j = i++)
-	{
-		dd->vertex(cx+dir[j*2+0]*rx, miny, cz+dir[j*2+1]*rz, col);
-		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col);
-		dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col);
-		dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, col);
-	}
-	for (int i = 0; i < NUM_SEG; i += NUM_SEG/4)
-	{
-		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col);
-		dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, col);
-	}
-}
-
-void duAppendBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-					 float maxx, float maxy, float maxz, unsigned int col)
-{
-	if (!dd) return;
-	// Top
-	dd->vertex(minx, miny, minz, col);
-	dd->vertex(maxx, miny, minz, col);
-	dd->vertex(maxx, miny, minz, col);
-	dd->vertex(maxx, miny, maxz, col);
-	dd->vertex(maxx, miny, maxz, col);
-	dd->vertex(minx, miny, maxz, col);
-	dd->vertex(minx, miny, maxz, col);
-	dd->vertex(minx, miny, minz, col);
-	
-	// bottom
-	dd->vertex(minx, maxy, minz, col);
-	dd->vertex(maxx, maxy, minz, col);
-	dd->vertex(maxx, maxy, minz, col);
-	dd->vertex(maxx, maxy, maxz, col);
-	dd->vertex(maxx, maxy, maxz, col);
-	dd->vertex(minx, maxy, maxz, col);
-	dd->vertex(minx, maxy, maxz, col);
-	dd->vertex(minx, maxy, minz, col);
-	
-	// Sides
-	dd->vertex(minx, miny, minz, col);
-	dd->vertex(minx, maxy, minz, col);
-	dd->vertex(maxx, miny, minz, col);
-	dd->vertex(maxx, maxy, minz, col);
-	dd->vertex(maxx, miny, maxz, col);
-	dd->vertex(maxx, maxy, maxz, col);
-	dd->vertex(minx, miny, maxz, col);
-	dd->vertex(minx, maxy, maxz, col);
-}
-
-void duAppendBoxPoints(struct duDebugDraw* dd, float minx, float miny, float minz,
-					   float maxx, float maxy, float maxz, unsigned int col)
-{
-	if (!dd) return;
-	// Top
-	dd->vertex(minx, miny, minz, col);
-	dd->vertex(maxx, miny, minz, col);
-	dd->vertex(maxx, miny, minz, col);
-	dd->vertex(maxx, miny, maxz, col);
-	dd->vertex(maxx, miny, maxz, col);
-	dd->vertex(minx, miny, maxz, col);
-	dd->vertex(minx, miny, maxz, col);
-	dd->vertex(minx, miny, minz, col);
-	
-	// bottom
-	dd->vertex(minx, maxy, minz, col);
-	dd->vertex(maxx, maxy, minz, col);
-	dd->vertex(maxx, maxy, minz, col);
-	dd->vertex(maxx, maxy, maxz, col);
-	dd->vertex(maxx, maxy, maxz, col);
-	dd->vertex(minx, maxy, maxz, col);
-	dd->vertex(minx, maxy, maxz, col);
-	dd->vertex(minx, maxy, minz, col);
-}
-
-void duAppendBox(struct duDebugDraw* dd, float minx, float miny, float minz,
-				 float maxx, float maxy, float maxz, const unsigned int* fcol)
-{
-	if (!dd) return;
-	const float verts[8*3] =
-	{
-		minx, miny, minz,
-		maxx, miny, minz,
-		maxx, miny, maxz,
-		minx, miny, maxz,
-		minx, maxy, minz,
-		maxx, maxy, minz,
-		maxx, maxy, maxz,
-		minx, maxy, maxz,
-	};
-	static const unsigned char inds[6*4] =
-	{
-		7, 6, 5, 4,
-		0, 1, 2, 3,
-		1, 5, 6, 2,
-		3, 7, 4, 0,
-		2, 6, 7, 3,
-		0, 4, 5, 1,
-	};
-	
-	const unsigned char* in = inds;
-	for (int i = 0; i < 6; ++i)
-	{
-		dd->vertex(&verts[*in*3], fcol[i]); in++;
-		dd->vertex(&verts[*in*3], fcol[i]); in++;
-		dd->vertex(&verts[*in*3], fcol[i]); in++;
-		dd->vertex(&verts[*in*3], fcol[i]); in++;
-	}
-}
-
-void duAppendCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
-					  float maxx, float maxy, float maxz, unsigned int col)
-{
-	if (!dd) return;
-	
-	static const int NUM_SEG = 16;
-	static float dir[NUM_SEG*2];
-	static bool init = false;
-	if (!init)
-	{
-		init = true;
-		for (int i = 0; i < NUM_SEG; ++i)
-		{
-			const float a = (float)i/(float)NUM_SEG*DU_PI*2;
-			dir[i*2] = cosf(a);
-			dir[i*2+1] = sinf(a);
-		}
-	}
-	
-	unsigned int col2 = duMultCol(col, 160);
-	
-	const float cx = (maxx + minx)/2;
-	const float cz = (maxz + minz)/2;
-	const float rx = (maxx - minx)/2;
-	const float rz = (maxz - minz)/2;
-
-	for (int i = 2; i < NUM_SEG; ++i)
-	{
-		const int a = 0, b = i-1, c = i;
-		dd->vertex(cx+dir[a*2+0]*rx, miny, cz+dir[a*2+1]*rz, col2);
-		dd->vertex(cx+dir[b*2+0]*rx, miny, cz+dir[b*2+1]*rz, col2);
-		dd->vertex(cx+dir[c*2+0]*rx, miny, cz+dir[c*2+1]*rz, col2);
-	}
-	for (int i = 2; i < NUM_SEG; ++i)
-	{
-		const int a = 0, b = i, c = i-1;
-		dd->vertex(cx+dir[a*2+0]*rx, maxy, cz+dir[a*2+1]*rz, col);
-		dd->vertex(cx+dir[b*2+0]*rx, maxy, cz+dir[b*2+1]*rz, col);
-		dd->vertex(cx+dir[c*2+0]*rx, maxy, cz+dir[c*2+1]*rz, col);
-	}
-	for (int i = 0, j = NUM_SEG-1; i < NUM_SEG; j = i++)
-	{
-		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col2);
-		dd->vertex(cx+dir[j*2+0]*rx, miny, cz+dir[j*2+1]*rz, col2);
-		dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col);
-
-		dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col2);
-		dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col);
-		dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, col);
-	}
-}
-
-
-inline void evalArc(const float x0, const float y0, const float z0,
-					const float dx, const float dy, const float dz,
-					const float h, const float u, float* res)
-{
-	res[0] = x0 + dx * u;
-	res[1] = y0 + dy * u + h * (1-(u*2-1)*(u*2-1));
-	res[2] = z0 + dz * u;
-}
-
-
-inline void vcross(float* dest, const float* v1, const float* v2)
-{
-	dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
-	dest[1] = v1[2]*v2[0] - v1[0]*v2[2];
-	dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; 
-}
-
-inline void vnormalize(float* v)
-{
-	float d = 1.0f / sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
-	v[0] *= d;
-	v[1] *= d;
-	v[2] *= d;
-}
-
-inline void vsub(float* dest, const float* v1, const float* v2)
-{
-	dest[0] = v1[0]-v2[0];
-	dest[1] = v1[1]-v2[1];
-	dest[2] = v1[2]-v2[2];
-}
-
-inline float vdistSqr(const float* v1, const float* v2)
-{
-	const float x = v1[0]-v2[0];
-	const float y = v1[1]-v2[1];
-	const float z = v1[2]-v2[2];
-	return x*x + y*y + z*z;
-}
-
-
-void appendArrowHead(struct duDebugDraw* dd, const float* p, const float* q,
-					 const float s, unsigned int col)
-{
-	const float eps = 0.001f;
-	if (!dd) return;
-	if (vdistSqr(p,q) < eps*eps) return;
-	float ax[3], ay[3] = {0,1,0}, az[3];
-	vsub(az, q, p);
-	vnormalize(az);
-	vcross(ax, ay, az);
-	vcross(ay, az, ax);
-	vnormalize(ay);
-
-	dd->vertex(p, col);
-//	dd->vertex(p[0]+az[0]*s+ay[0]*s/2, p[1]+az[1]*s+ay[1]*s/2, p[2]+az[2]*s+ay[2]*s/2, col);
-	dd->vertex(p[0]+az[0]*s+ax[0]*s/3, p[1]+az[1]*s+ax[1]*s/3, p[2]+az[2]*s+ax[2]*s/3, col);
-
-	dd->vertex(p, col);
-//	dd->vertex(p[0]+az[0]*s-ay[0]*s/2, p[1]+az[1]*s-ay[1]*s/2, p[2]+az[2]*s-ay[2]*s/2, col);
-	dd->vertex(p[0]+az[0]*s-ax[0]*s/3, p[1]+az[1]*s-ax[1]*s/3, p[2]+az[2]*s-ax[2]*s/3, col);
-	
-}
-
-void duAppendArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-				 const float x1, const float y1, const float z1, const float h,
-				 const float as0, const float as1, unsigned int col)
-{
-	if (!dd) return;
-	static const int NUM_ARC_PTS = 8;
-	static const float PAD = 0.05f;
-	static const float ARC_PTS_SCALE = (1.0f-PAD*2) / (float)NUM_ARC_PTS;
-	const float dx = x1 - x0;
-	const float dy = y1 - y0;
-	const float dz = z1 - z0;
-	const float len = sqrtf(dx*dx + dy*dy + dz*dz);
-	float prev[3];
-	evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD, prev);
-	for (int i = 1; i <= NUM_ARC_PTS; ++i)
-	{
-		const float u = PAD + i * ARC_PTS_SCALE;
-		float pt[3];
-		evalArc(x0,y0,z0, dx,dy,dz, len*h, u, pt);
-		dd->vertex(prev[0],prev[1],prev[2], col);
-		dd->vertex(pt[0],pt[1],pt[2], col);
-		prev[0] = pt[0]; prev[1] = pt[1]; prev[2] = pt[2];
-	}
-	
-	// End arrows
-	if (as0 > 0.001f)
-	{
-		float p[3], q[3];
-		evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD, p);
-		evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD+0.05f, q);
-		appendArrowHead(dd, p, q, as0, col);
-	}
-
-	if (as1 > 0.001f)
-	{
-		float p[3], q[3];
-		evalArc(x0,y0,z0, dx,dy,dz, len*h, 1-PAD, p);
-		evalArc(x0,y0,z0, dx,dy,dz, len*h, 1-(PAD+0.05f), q);
-		appendArrowHead(dd, p, q, as1, col);
-	}
-}
-
-void duAppendArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-				   const float x1, const float y1, const float z1,
-				   const float as0, const float as1, unsigned int col)
-{
-	if (!dd) return;
-
-	dd->vertex(x0,y0,z0, col);
-	dd->vertex(x1,y1,z1, col);
-	
-	// End arrows
-	const float p[3] = {x0,y0,z0}, q[3] = {x1,y1,z1};
-	if (as0 > 0.001f)
-		appendArrowHead(dd, p, q, as0, col);
-	if (as1 > 0.001f)
-		appendArrowHead(dd, q, p, as1, col);
-}
-
-void duAppendCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
-					const float r, unsigned int col)
-{
-	if (!dd) return;
-	static const int NUM_SEG = 40;
-	static float dir[40*2];
-	static bool init = false;
-	if (!init)
-	{
-		init = true;
-		for (int i = 0; i < NUM_SEG; ++i)
-		{
-			const float a = (float)i/(float)NUM_SEG*DU_PI*2;
-			dir[i*2] = cosf(a);
-			dir[i*2+1] = sinf(a);
-		}
-	}
-	
-	for (int i = 0, j = NUM_SEG-1; i < NUM_SEG; j = i++)
-	{
-		dd->vertex(x+dir[j*2+0]*r, y, z+dir[j*2+1]*r, col);
-		dd->vertex(x+dir[i*2+0]*r, y, z+dir[i*2+1]*r, col);
-	}
-}
-
-void duAppendCross(struct duDebugDraw* dd, const float x, const float y, const float z,
-				   const float s, unsigned int col)
-{
-	if (!dd) return;
-	dd->vertex(x-s,y,z, col);
-	dd->vertex(x+s,y,z, col);
-	dd->vertex(x,y-s,z, col);
-	dd->vertex(x,y+s,z, col);
-	dd->vertex(x,y,z-s, col);
-	dd->vertex(x,y,z+s, col);
-}
-
-duDisplayList::duDisplayList(int cap) :
-	m_pos(0),
-	m_color(0),
-	m_size(0),
-	m_cap(0),
-	m_depthMask(true),
-	m_prim(DU_DRAW_LINES),
-	m_primSize(1.0f)
-{
-	if (cap < 8)
-		cap = 8;
-	resize(cap);
-}
-
-duDisplayList::~duDisplayList()
-{
-	delete [] m_pos;
-	delete [] m_color;
-}
-
-void duDisplayList::resize(int cap)
-{
-	float* newPos = new float[cap*3];
-	if (m_size)
-		memcpy(newPos, m_pos, sizeof(float)*3*m_size);
-	delete [] m_pos;
-	m_pos = newPos;
-
-	unsigned int* newColor = new unsigned int[cap];
-	if (m_size)
-		memcpy(newColor, m_color, sizeof(unsigned int)*m_size);
-	delete [] m_color;
-	m_color = newColor;
-	
-	m_cap = cap;
-}
-
-void duDisplayList::clear()
-{
-	m_size = 0;
-}
-
-void duDisplayList::depthMask(bool state)
-{
-	m_depthMask = state;
-}
-
-void duDisplayList::begin(duDebugDrawPrimitives prim, float size)
-{
-	clear();
-	m_prim = prim;
-	m_primSize = size;
-}
-
-void duDisplayList::vertex(const float x, const float y, const float z, unsigned int color)
-{
-	if (m_size+1 >= m_cap)
-		resize(m_cap*2);
-	float* p = &m_pos[m_size*3];
-	p[0] = x;
-	p[1] = y;
-	p[2] = z;
-	m_color[m_size] = color;
-	m_size++;
-}
-
-void duDisplayList::vertex(const float* pos, unsigned int color)
-{
-	vertex(pos[0],pos[1],pos[2],color);
-}
-
-void duDisplayList::end()
-{
-}
-
-void duDisplayList::draw(struct duDebugDraw* dd)
-{
-	if (!dd) return;
-	if (!m_size) return;
-	dd->depthMask(m_depthMask);
-	dd->begin(m_prim, m_primSize);
-	for (int i = 0; i < m_size; ++i)
-		dd->vertex(&m_pos[i*3], m_color[i]);
-	dd->end();
-}

+ 0 - 223
panda/src/recastdetour/DebugDraw.h

@@ -1,223 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DEBUGDRAW_H
-#define DEBUGDRAW_H
-
-// Some math headers don't have PI defined.
-static const float DU_PI = 3.14159265f;
-
-enum duDebugDrawPrimitives
-{
-	DU_DRAW_POINTS,
-	DU_DRAW_LINES,
-	DU_DRAW_TRIS,
-	DU_DRAW_QUADS,	
-};
-
-/// Abstract debug draw interface.
-struct duDebugDraw
-{
-	virtual ~duDebugDraw() = 0;
-	
-	virtual void depthMask(bool state) = 0;
-
-	virtual void texture(bool state) = 0;
-
-	/// Begin drawing primitives.
-	///  @param prim [in] primitive type to draw, one of rcDebugDrawPrimitives.
-	///  @param size [in] size of a primitive, applies to point size and line width only.
-	virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f) = 0;
-
-	/// Submit a vertex
-	///  @param pos [in] position of the verts.
-	///  @param color [in] color of the verts.
-	virtual void vertex(const float* pos, unsigned int color) = 0;
-
-	/// Submit a vertex
-	///  @param x,y,z [in] position of the verts.
-	///  @param color [in] color of the verts.
-	virtual void vertex(const float x, const float y, const float z, unsigned int color) = 0;
-
-	/// Submit a vertex
-	///  @param pos [in] position of the verts.
-	///  @param color [in] color of the verts.
-	virtual void vertex(const float* pos, unsigned int color, const float* uv) = 0;
-	
-	/// Submit a vertex
-	///  @param x,y,z [in] position of the verts.
-	///  @param color [in] color of the verts.
-	virtual void vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v) = 0;
-	
-	/// End drawing primitives.
-	virtual void end() = 0;
-
-	/// Compute a color for given area.
-	virtual unsigned int areaToCol(unsigned int area);
-};
-
-inline unsigned int duRGBA(int r, int g, int b, int a)
-{
-	return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24);
-}
-
-inline unsigned int duRGBAf(float fr, float fg, float fb, float fa)
-{
-	unsigned char r = (unsigned char)(fr*255.0f);
-	unsigned char g = (unsigned char)(fg*255.0f);
-	unsigned char b = (unsigned char)(fb*255.0f);
-	unsigned char a = (unsigned char)(fa*255.0f);
-	return duRGBA(r,g,b,a);
-}
-
-unsigned int duIntToCol(int i, int a);
-void duIntToCol(int i, float* col);
-
-inline unsigned int duMultCol(const unsigned int col, const unsigned int d)
-{
-	const unsigned int r = col & 0xff;
-	const unsigned int g = (col >> 8) & 0xff;
-	const unsigned int b = (col >> 16) & 0xff;
-	const unsigned int a = (col >> 24) & 0xff;
-	return duRGBA((r*d) >> 8, (g*d) >> 8, (b*d) >> 8, a);
-}
-
-inline unsigned int duDarkenCol(unsigned int col)
-{
-	return ((col >> 1) & 0x007f7f7f) | (col & 0xff000000);
-}
-
-inline unsigned int duLerpCol(unsigned int ca, unsigned int cb, unsigned int u)
-{
-	const unsigned int ra = ca & 0xff;
-	const unsigned int ga = (ca >> 8) & 0xff;
-	const unsigned int ba = (ca >> 16) & 0xff;
-	const unsigned int aa = (ca >> 24) & 0xff;
-	const unsigned int rb = cb & 0xff;
-	const unsigned int gb = (cb >> 8) & 0xff;
-	const unsigned int bb = (cb >> 16) & 0xff;
-	const unsigned int ab = (cb >> 24) & 0xff;
-	
-	unsigned int r = (ra*(255-u) + rb*u)/255;
-	unsigned int g = (ga*(255-u) + gb*u)/255;
-	unsigned int b = (ba*(255-u) + bb*u)/255;
-	unsigned int a = (aa*(255-u) + ab*u)/255;
-	return duRGBA(r,g,b,a);
-}
-
-inline unsigned int duTransCol(unsigned int c, unsigned int a)
-{
-	return (a<<24) | (c & 0x00ffffff);
-}
-
-
-void duCalcBoxColors(unsigned int* colors, unsigned int colTop, unsigned int colSide);
-
-void duDebugDrawCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-							 float maxx, float maxy, float maxz, unsigned int col, const float lineWidth);
-
-void duDebugDrawBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-						float maxx, float maxy, float maxz, unsigned int col, const float lineWidth);
-
-void duDebugDrawArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-					const float x1, const float y1, const float z1, const float h,
-					const float as0, const float as1, unsigned int col, const float lineWidth);
-
-void duDebugDrawArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-					  const float x1, const float y1, const float z1,
-					  const float as0, const float as1, unsigned int col, const float lineWidth);
-
-void duDebugDrawCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
-					   const float r, unsigned int col, const float lineWidth);
-
-void duDebugDrawCross(struct duDebugDraw* dd, const float x, const float y, const float z,
-					  const float size, unsigned int col, const float lineWidth);
-
-void duDebugDrawBox(struct duDebugDraw* dd, float minx, float miny, float minz,
-					float maxx, float maxy, float maxz, const unsigned int* fcol);
-
-void duDebugDrawCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
-						 float maxx, float maxy, float maxz, unsigned int col);
-
-void duDebugDrawGridXZ(struct duDebugDraw* dd, const float ox, const float oy, const float oz,
-					   const int w, const int h, const float size,
-					   const unsigned int col, const float lineWidth);
-
-
-// Versions without begin/end, can be used to draw multiple primitives.
-void duAppendCylinderWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-						  float maxx, float maxy, float maxz, unsigned int col);
-
-void duAppendBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz,
-					 float maxx, float maxy, float maxz, unsigned int col);
-
-void duAppendBoxPoints(struct duDebugDraw* dd, float minx, float miny, float minz,
-					   float maxx, float maxy, float maxz, unsigned int col);
-
-void duAppendArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-				 const float x1, const float y1, const float z1, const float h,
-				 const float as0, const float as1, unsigned int col);
-
-void duAppendArrow(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
-				   const float x1, const float y1, const float z1,
-				   const float as0, const float as1, unsigned int col);
-
-void duAppendCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
-					const float r, unsigned int col);
-
-void duAppendCross(struct duDebugDraw* dd, const float x, const float y, const float z,
-				   const float size, unsigned int col);
-
-void duAppendBox(struct duDebugDraw* dd, float minx, float miny, float minz,
-				 float maxx, float maxy, float maxz, const unsigned int* fcol);
-
-void duAppendCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
-					  float maxx, float maxy, float maxz, unsigned int col);
-
-
-class duDisplayList : public duDebugDraw
-{
-	float* m_pos;
-	unsigned int* m_color;
-	int m_size;
-	int m_cap;
-
-	bool m_depthMask;
-	duDebugDrawPrimitives m_prim;
-	float m_primSize;
-	
-	void resize(int cap);
-	
-public:
-	duDisplayList(int cap = 512);
-	~duDisplayList();
-	virtual void depthMask(bool state);
-	virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f);
-	virtual void vertex(const float x, const float y, const float z, unsigned int color);
-	virtual void vertex(const float* pos, unsigned int color);
-	virtual void end();
-	void clear();
-	void draw(struct duDebugDraw* dd);
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	duDisplayList(const duDisplayList&);
-	duDisplayList& operator=(const duDisplayList&);
-};
-
-
-#endif // DEBUGDRAW_H

+ 0 - 1448
panda/src/recastdetour/DetourCrowd.cpp

@@ -1,1448 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 <string.h>
-#include <float.h>
-#include <stdlib.h>
-#include <new>
-#include "DetourCrowd.h"
-#include "DetourNavMesh.h"
-#include "DetourNavMeshQuery.h"
-#include "DetourObstacleAvoidance.h"
-#include "DetourCommon.h"
-#include "DetourMath.h"
-#include "DetourAssert.h"
-#include "DetourAlloc.h"
-
-
-dtCrowd* dtAllocCrowd()
-{
-	void* mem = dtAlloc(sizeof(dtCrowd), DT_ALLOC_PERM);
-	if (!mem) return 0;
-	return new(mem) dtCrowd;
-}
-
-void dtFreeCrowd(dtCrowd* ptr)
-{
-	if (!ptr) return;
-	ptr->~dtCrowd();
-	dtFree(ptr);
-}
-
-
-static const int MAX_ITERS_PER_UPDATE = 100;
-
-static const int MAX_PATHQUEUE_NODES = 4096;
-static const int MAX_COMMON_NODES = 512;
-
-inline float tween(const float t, const float t0, const float t1)
-{
-	return dtClamp((t-t0) / (t1-t0), 0.0f, 1.0f);
-}
-
-static void integrate(dtCrowdAgent* ag, const float dt)
-{
-	// Fake dynamic constraint.
-	const float maxDelta = ag->params.maxAcceleration * dt;
-	float dv[3];
-	dtVsub(dv, ag->nvel, ag->vel);
-	float ds = dtVlen(dv);
-	if (ds > maxDelta)
-		dtVscale(dv, dv, maxDelta/ds);
-	dtVadd(ag->vel, ag->vel, dv);
-	
-	// Integrate
-	if (dtVlen(ag->vel) > 0.0001f)
-		dtVmad(ag->npos, ag->npos, ag->vel, dt);
-	else
-		dtVset(ag->vel,0,0,0);
-}
-
-static bool overOffmeshConnection(const dtCrowdAgent* ag, const float radius)
-{
-	if (!ag->ncorners)
-		return false;
-	
-	const bool offMeshConnection = (ag->cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ? true : false;
-	if (offMeshConnection)
-	{
-		const float distSq = dtVdist2DSqr(ag->npos, &ag->cornerVerts[(ag->ncorners-1)*3]);
-		if (distSq < radius*radius)
-			return true;
-	}
-	
-	return false;
-}
-
-static float getDistanceToGoal(const dtCrowdAgent* ag, const float range)
-{
-	if (!ag->ncorners)
-		return range;
-	
-	const bool endOfPath = (ag->cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_END) ? true : false;
-	if (endOfPath)
-		return dtMin(dtVdist2D(ag->npos, &ag->cornerVerts[(ag->ncorners-1)*3]), range);
-	
-	return range;
-}
-
-static void calcSmoothSteerDirection(const dtCrowdAgent* ag, float* dir)
-{
-	if (!ag->ncorners)
-	{
-		dtVset(dir, 0,0,0);
-		return;
-	}
-	
-	const int ip0 = 0;
-	const int ip1 = dtMin(1, ag->ncorners-1);
-	const float* p0 = &ag->cornerVerts[ip0*3];
-	const float* p1 = &ag->cornerVerts[ip1*3];
-	
-	float dir0[3], dir1[3];
-	dtVsub(dir0, p0, ag->npos);
-	dtVsub(dir1, p1, ag->npos);
-	dir0[1] = 0;
-	dir1[1] = 0;
-	
-	float len0 = dtVlen(dir0);
-	float len1 = dtVlen(dir1);
-	if (len1 > 0.001f)
-		dtVscale(dir1,dir1,1.0f/len1);
-	
-	dir[0] = dir0[0] - dir1[0]*len0*0.5f;
-	dir[1] = 0;
-	dir[2] = dir0[2] - dir1[2]*len0*0.5f;
-	
-	dtVnormalize(dir);
-}
-
-static void calcStraightSteerDirection(const dtCrowdAgent* ag, float* dir)
-{
-	if (!ag->ncorners)
-	{
-		dtVset(dir, 0,0,0);
-		return;
-	}
-	dtVsub(dir, &ag->cornerVerts[0], ag->npos);
-	dir[1] = 0;
-	dtVnormalize(dir);
-}
-
-static int addNeighbour(const int idx, const float dist,
-						dtCrowdNeighbour* neis, const int nneis, const int maxNeis)
-{
-	// Insert neighbour based on the distance.
-	dtCrowdNeighbour* nei = 0;
-	if (!nneis)
-	{
-		nei = &neis[nneis];
-	}
-	else if (dist >= neis[nneis-1].dist)
-	{
-		if (nneis >= maxNeis)
-			return nneis;
-		nei = &neis[nneis];
-	}
-	else
-	{
-		int i;
-		for (i = 0; i < nneis; ++i)
-			if (dist <= neis[i].dist)
-				break;
-		
-		const int tgt = i+1;
-		const int n = dtMin(nneis-i, maxNeis-tgt);
-		
-		dtAssert(tgt+n <= maxNeis);
-		
-		if (n > 0)
-			memmove(&neis[tgt], &neis[i], sizeof(dtCrowdNeighbour)*n);
-		nei = &neis[i];
-	}
-	
-	memset(nei, 0, sizeof(dtCrowdNeighbour));
-	
-	nei->idx = idx;
-	nei->dist = dist;
-	
-	return dtMin(nneis+1, maxNeis);
-}
-
-static int getNeighbours(const float* pos, const float height, const float range,
-						 const dtCrowdAgent* skip, dtCrowdNeighbour* result, const int maxResult,
-						 dtCrowdAgent** agents, const int /*nagents*/, dtProximityGrid* grid)
-{
-	int n = 0;
-	
-	static const int MAX_NEIS = 32;
-	unsigned short ids[MAX_NEIS];
-	int nids = grid->queryItems(pos[0]-range, pos[2]-range,
-								pos[0]+range, pos[2]+range,
-								ids, MAX_NEIS);
-	
-	for (int i = 0; i < nids; ++i)
-	{
-		const dtCrowdAgent* ag = agents[ids[i]];
-		
-		if (ag == skip) continue;
-		
-		// Check for overlap.
-		float diff[3];
-		dtVsub(diff, pos, ag->npos);
-		if (dtMathFabsf(diff[1]) >= (height+ag->params.height)/2.0f)
-			continue;
-		diff[1] = 0;
-		const float distSqr = dtVlenSqr(diff);
-		if (distSqr > dtSqr(range))
-			continue;
-		
-		n = addNeighbour(ids[i], distSqr, result, n, maxResult);
-	}
-	return n;
-}
-
-static int addToOptQueue(dtCrowdAgent* newag, dtCrowdAgent** agents, const int nagents, const int maxAgents)
-{
-	// Insert neighbour based on greatest time.
-	int slot = 0;
-	if (!nagents)
-	{
-		slot = nagents;
-	}
-	else if (newag->topologyOptTime <= agents[nagents-1]->topologyOptTime)
-	{
-		if (nagents >= maxAgents)
-			return nagents;
-		slot = nagents;
-	}
-	else
-	{
-		int i;
-		for (i = 0; i < nagents; ++i)
-			if (newag->topologyOptTime >= agents[i]->topologyOptTime)
-				break;
-		
-		const int tgt = i+1;
-		const int n = dtMin(nagents-i, maxAgents-tgt);
-		
-		dtAssert(tgt+n <= maxAgents);
-		
-		if (n > 0)
-			memmove(&agents[tgt], &agents[i], sizeof(dtCrowdAgent*)*n);
-		slot = i;
-	}
-	
-	agents[slot] = newag;
-	
-	return dtMin(nagents+1, maxAgents);
-}
-
-static int addToPathQueue(dtCrowdAgent* newag, dtCrowdAgent** agents, const int nagents, const int maxAgents)
-{
-	// Insert neighbour based on greatest time.
-	int slot = 0;
-	if (!nagents)
-	{
-		slot = nagents;
-	}
-	else if (newag->targetReplanTime <= agents[nagents-1]->targetReplanTime)
-	{
-		if (nagents >= maxAgents)
-			return nagents;
-		slot = nagents;
-	}
-	else
-	{
-		int i;
-		for (i = 0; i < nagents; ++i)
-			if (newag->targetReplanTime >= agents[i]->targetReplanTime)
-				break;
-		
-		const int tgt = i+1;
-		const int n = dtMin(nagents-i, maxAgents-tgt);
-		
-		dtAssert(tgt+n <= maxAgents);
-		
-		if (n > 0)
-			memmove(&agents[tgt], &agents[i], sizeof(dtCrowdAgent*)*n);
-		slot = i;
-	}
-	
-	agents[slot] = newag;
-	
-	return dtMin(nagents+1, maxAgents);
-}
-
-
-/**
-@class dtCrowd
-@par
-
-This is the core class of the @ref crowd module.  See the @ref crowd documentation for a summary
-of the crowd features.
-
-A common method for setting up the crowd is as follows:
-
--# Allocate the crowd using #dtAllocCrowd.
--# Initialize the crowd using #init().
--# Set the avoidance configurations using #setObstacleAvoidanceParams().
--# Add agents using #addAgent() and make an initial movement request using #requestMoveTarget().
-
-A common process for managing the crowd is as follows:
-
--# Call #update() to allow the crowd to manage its agents.
--# Retrieve agent information using #getActiveAgents().
--# Make movement requests using #requestMoveTarget() when movement goal changes.
--# Repeat every frame.
-
-Some agent configuration settings can be updated using #updateAgentParameters().  But the crowd owns the
-agent position.  So it is not possible to update an active agent's position.  If agent position
-must be fed back into the crowd, the agent must be removed and re-added.
-
-Notes: 
-
-- Path related information is available for newly added agents only after an #update() has been
-  performed.
-- Agent objects are kept in a pool and re-used.  So it is important when using agent objects to check the value of
-  #dtCrowdAgent::active to determine if the agent is actually in use or not.
-- This class is meant to provide 'local' movement. There is a limit of 256 polygons in the path corridor.  
-  So it is not meant to provide automatic pathfinding services over long distances.
-
-@see dtAllocCrowd(), dtFreeCrowd(), init(), dtCrowdAgent
-
-*/
-
-dtCrowd::dtCrowd() :
-	m_maxAgents(0),
-	m_agents(0),
-	m_activeAgents(0),
-	m_agentAnims(0),
-	m_obstacleQuery(0),
-	m_grid(0),
-	m_pathResult(0),
-	m_maxPathResult(0),
-	m_maxAgentRadius(0),
-	m_velocitySampleCount(0),
-	m_navquery(0)
-{
-}
-
-dtCrowd::~dtCrowd()
-{
-	purge();
-}
-
-void dtCrowd::purge()
-{
-	for (int i = 0; i < m_maxAgents; ++i)
-		m_agents[i].~dtCrowdAgent();
-	dtFree(m_agents);
-	m_agents = 0;
-	m_maxAgents = 0;
-	
-	dtFree(m_activeAgents);
-	m_activeAgents = 0;
-
-	dtFree(m_agentAnims);
-	m_agentAnims = 0;
-	
-	dtFree(m_pathResult);
-	m_pathResult = 0;
-	
-	dtFreeProximityGrid(m_grid);
-	m_grid = 0;
-
-	dtFreeObstacleAvoidanceQuery(m_obstacleQuery);
-	m_obstacleQuery = 0;
-	
-	dtFreeNavMeshQuery(m_navquery);
-	m_navquery = 0;
-}
-
-/// @par
-///
-/// May be called more than once to purge and re-initialize the crowd.
-bool dtCrowd::init(const int maxAgents, const float maxAgentRadius, dtNavMesh* nav)
-{
-	purge();
-	
-	m_maxAgents = maxAgents;
-	m_maxAgentRadius = maxAgentRadius;
-
-	// Larger than agent radius because it is also used for agent recovery.
-	dtVset(m_agentPlacementHalfExtents, m_maxAgentRadius*2.0f, m_maxAgentRadius*1.5f, m_maxAgentRadius*2.0f);
-	
-	m_grid = dtAllocProximityGrid();
-	if (!m_grid)
-		return false;
-	if (!m_grid->init(m_maxAgents*4, maxAgentRadius*3))
-		return false;
-	
-	m_obstacleQuery = dtAllocObstacleAvoidanceQuery();
-	if (!m_obstacleQuery)
-		return false;
-	if (!m_obstacleQuery->init(6, 8))
-		return false;
-
-	// Init obstacle query params.
-	memset(m_obstacleQueryParams, 0, sizeof(m_obstacleQueryParams));
-	for (int i = 0; i < DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS; ++i)
-	{
-		dtObstacleAvoidanceParams* params = &m_obstacleQueryParams[i];
-		params->velBias = 0.4f;
-		params->weightDesVel = 2.0f;
-		params->weightCurVel = 0.75f;
-		params->weightSide = 0.75f;
-		params->weightToi = 2.5f;
-		params->horizTime = 2.5f;
-		params->gridSize = 33;
-		params->adaptiveDivs = 7;
-		params->adaptiveRings = 2;
-		params->adaptiveDepth = 5;
-	}
-	
-	// Allocate temp buffer for merging paths.
-	m_maxPathResult = 256;
-	m_pathResult = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*m_maxPathResult, DT_ALLOC_PERM);
-	if (!m_pathResult)
-		return false;
-	
-	if (!m_pathq.init(m_maxPathResult, MAX_PATHQUEUE_NODES, nav))
-		return false;
-	
-	m_agents = (dtCrowdAgent*)dtAlloc(sizeof(dtCrowdAgent)*m_maxAgents, DT_ALLOC_PERM);
-	if (!m_agents)
-		return false;
-	
-	m_activeAgents = (dtCrowdAgent**)dtAlloc(sizeof(dtCrowdAgent*)*m_maxAgents, DT_ALLOC_PERM);
-	if (!m_activeAgents)
-		return false;
-
-	m_agentAnims = (dtCrowdAgentAnimation*)dtAlloc(sizeof(dtCrowdAgentAnimation)*m_maxAgents, DT_ALLOC_PERM);
-	if (!m_agentAnims)
-		return false;
-	
-	for (int i = 0; i < m_maxAgents; ++i)
-	{
-		new(&m_agents[i]) dtCrowdAgent();
-		m_agents[i].active = false;
-		if (!m_agents[i].corridor.init(m_maxPathResult))
-			return false;
-	}
-
-	for (int i = 0; i < m_maxAgents; ++i)
-	{
-		m_agentAnims[i].active = false;
-	}
-
-	// The navquery is mostly used for local searches, no need for large node pool.
-	m_navquery = dtAllocNavMeshQuery();
-	if (!m_navquery)
-		return false;
-	if (dtStatusFailed(m_navquery->init(nav, MAX_COMMON_NODES)))
-		return false;
-	
-	return true;
-}
-
-void dtCrowd::setObstacleAvoidanceParams(const int idx, const dtObstacleAvoidanceParams* params)
-{
-	if (idx >= 0 && idx < DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS)
-		memcpy(&m_obstacleQueryParams[idx], params, sizeof(dtObstacleAvoidanceParams));
-}
-
-const dtObstacleAvoidanceParams* dtCrowd::getObstacleAvoidanceParams(const int idx) const
-{
-	if (idx >= 0 && idx < DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS)
-		return &m_obstacleQueryParams[idx];
-	return 0;
-}
-
-int dtCrowd::getAgentCount() const
-{
-	return m_maxAgents;
-}
-
-/// @par
-/// 
-/// Agents in the pool may not be in use.  Check #dtCrowdAgent.active before using the returned object.
-const dtCrowdAgent* dtCrowd::getAgent(const int idx)
-{
-	if (idx < 0 || idx >= m_maxAgents)
-		return 0;
-	return &m_agents[idx];
-}
-
-/// 
-/// Agents in the pool may not be in use.  Check #dtCrowdAgent.active before using the returned object.
-dtCrowdAgent* dtCrowd::getEditableAgent(const int idx)
-{
-	if (idx < 0 || idx >= m_maxAgents)
-		return 0;
-	return &m_agents[idx];
-}
-
-void dtCrowd::updateAgentParameters(const int idx, const dtCrowdAgentParams* params)
-{
-	if (idx < 0 || idx >= m_maxAgents)
-		return;
-	memcpy(&m_agents[idx].params, params, sizeof(dtCrowdAgentParams));
-}
-
-/// @par
-///
-/// The agent's position will be constrained to the surface of the navigation mesh.
-int dtCrowd::addAgent(const float* pos, const dtCrowdAgentParams* params)
-{
-	// Find empty slot.
-	int idx = -1;
-	for (int i = 0; i < m_maxAgents; ++i)
-	{
-		if (!m_agents[i].active)
-		{
-			idx = i;
-			break;
-		}
-	}
-	if (idx == -1)
-		return -1;
-	
-	dtCrowdAgent* ag = &m_agents[idx];		
-
-	updateAgentParameters(idx, params);
-	
-	// Find nearest position on navmesh and place the agent there.
-	float nearest[3];
-	dtPolyRef ref = 0;
-	dtVcopy(nearest, pos);
-	dtStatus status = m_navquery->findNearestPoly(pos, m_agentPlacementHalfExtents, &m_filters[ag->params.queryFilterType], &ref, nearest);
-	if (dtStatusFailed(status))
-	{
-		dtVcopy(nearest, pos);
-		ref = 0;
-	}
-	
-	ag->corridor.reset(ref, nearest);
-	ag->boundary.reset();
-	ag->partial = false;
-
-	ag->topologyOptTime = 0;
-	ag->targetReplanTime = 0;
-	ag->nneis = 0;
-	
-	dtVset(ag->dvel, 0,0,0);
-	dtVset(ag->nvel, 0,0,0);
-	dtVset(ag->vel, 0,0,0);
-	dtVcopy(ag->npos, nearest);
-	
-	ag->desiredSpeed = 0;
-
-	if (ref)
-		ag->state = DT_CROWDAGENT_STATE_WALKING;
-	else
-		ag->state = DT_CROWDAGENT_STATE_INVALID;
-	
-	ag->targetState = DT_CROWDAGENT_TARGET_NONE;
-	
-	ag->active = true;
-
-	return idx;
-}
-
-/// @par
-///
-/// The agent is deactivated and will no longer be processed.  Its #dtCrowdAgent object
-/// is not removed from the pool.  It is marked as inactive so that it is available for reuse.
-void dtCrowd::removeAgent(const int idx)
-{
-	if (idx >= 0 && idx < m_maxAgents)
-	{
-		m_agents[idx].active = false;
-	}
-}
-
-bool dtCrowd::requestMoveTargetReplan(const int idx, dtPolyRef ref, const float* pos)
-{
-	if (idx < 0 || idx >= m_maxAgents)
-		return false;
-	
-	dtCrowdAgent* ag = &m_agents[idx];
-	
-	// Initialize request.
-	ag->targetRef = ref;
-	dtVcopy(ag->targetPos, pos);
-	ag->targetPathqRef = DT_PATHQ_INVALID;
-	ag->targetReplan = true;
-	if (ag->targetRef)
-		ag->targetState = DT_CROWDAGENT_TARGET_REQUESTING;
-	else
-		ag->targetState = DT_CROWDAGENT_TARGET_FAILED;
-	
-	return true;
-}
-
-/// @par
-/// 
-/// This method is used when a new target is set.
-/// 
-/// The position will be constrained to the surface of the navigation mesh.
-///
-/// The request will be processed during the next #update().
-bool dtCrowd::requestMoveTarget(const int idx, dtPolyRef ref, const float* pos)
-{
-	if (idx < 0 || idx >= m_maxAgents)
-		return false;
-	if (!ref)
-		return false;
-
-	dtCrowdAgent* ag = &m_agents[idx];
-	
-	// Initialize request.
-	ag->targetRef = ref;
-	dtVcopy(ag->targetPos, pos);
-	ag->targetPathqRef = DT_PATHQ_INVALID;
-	ag->targetReplan = false;
-	if (ag->targetRef)
-		ag->targetState = DT_CROWDAGENT_TARGET_REQUESTING;
-	else
-		ag->targetState = DT_CROWDAGENT_TARGET_FAILED;
-
-	return true;
-}
-
-bool dtCrowd::requestMoveVelocity(const int idx, const float* vel)
-{
-	if (idx < 0 || idx >= m_maxAgents)
-		return false;
-	
-	dtCrowdAgent* ag = &m_agents[idx];
-	
-	// Initialize request.
-	ag->targetRef = 0;
-	dtVcopy(ag->targetPos, vel);
-	ag->targetPathqRef = DT_PATHQ_INVALID;
-	ag->targetReplan = false;
-	ag->targetState = DT_CROWDAGENT_TARGET_VELOCITY;
-	
-	return true;
-}
-
-bool dtCrowd::resetMoveTarget(const int idx)
-{
-	if (idx < 0 || idx >= m_maxAgents)
-		return false;
-	
-	dtCrowdAgent* ag = &m_agents[idx];
-	
-	// Initialize request.
-	ag->targetRef = 0;
-	dtVset(ag->targetPos, 0,0,0);
-	dtVset(ag->dvel, 0,0,0);
-	ag->targetPathqRef = DT_PATHQ_INVALID;
-	ag->targetReplan = false;
-	ag->targetState = DT_CROWDAGENT_TARGET_NONE;
-	
-	return true;
-}
-
-int dtCrowd::getActiveAgents(dtCrowdAgent** agents, const int maxAgents)
-{
-	int n = 0;
-	for (int i = 0; i < m_maxAgents; ++i)
-	{
-		if (!m_agents[i].active) continue;
-		if (n < maxAgents)
-			agents[n++] = &m_agents[i];
-	}
-	return n;
-}
-
-
-void dtCrowd::updateMoveRequest(const float /*dt*/)
-{
-	const int PATH_MAX_AGENTS = 8;
-	dtCrowdAgent* queue[PATH_MAX_AGENTS];
-	int nqueue = 0;
-	
-	// Fire off new requests.
-	for (int i = 0; i < m_maxAgents; ++i)
-	{
-		dtCrowdAgent* ag = &m_agents[i];
-		if (!ag->active)
-			continue;
-		if (ag->state == DT_CROWDAGENT_STATE_INVALID)
-			continue;
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-			continue;
-
-		if (ag->targetState == DT_CROWDAGENT_TARGET_REQUESTING)
-		{
-			const dtPolyRef* path = ag->corridor.getPath();
-			const int npath = ag->corridor.getPathCount();
-			dtAssert(npath);
-
-			static const int MAX_RES = 32;
-			float reqPos[3];
-			dtPolyRef reqPath[MAX_RES];	// The path to the request location
-			int reqPathCount = 0;
-
-			// Quick search towards the goal.
-			static const int MAX_ITER = 20;
-			m_navquery->initSlicedFindPath(path[0], ag->targetRef, ag->npos, ag->targetPos, &m_filters[ag->params.queryFilterType]);
-			m_navquery->updateSlicedFindPath(MAX_ITER, 0);
-			dtStatus status = 0;
-			if (ag->targetReplan) // && npath > 10)
-			{
-				// Try to use existing steady path during replan if possible.
-				status = m_navquery->finalizeSlicedFindPathPartial(path, npath, reqPath, &reqPathCount, MAX_RES);
-			}
-			else
-			{
-				// Try to move towards target when goal changes.
-				status = m_navquery->finalizeSlicedFindPath(reqPath, &reqPathCount, MAX_RES);
-			}
-
-			if (!dtStatusFailed(status) && reqPathCount > 0)
-			{
-				// In progress or succeed.
-				if (reqPath[reqPathCount-1] != ag->targetRef)
-				{
-					// Partial path, constrain target position inside the last polygon.
-					status = m_navquery->closestPointOnPoly(reqPath[reqPathCount-1], ag->targetPos, reqPos, 0);
-					if (dtStatusFailed(status))
-						reqPathCount = 0;
-				}
-				else
-				{
-					dtVcopy(reqPos, ag->targetPos);
-				}
-			}
-			else
-			{
-				reqPathCount = 0;
-			}
-				
-			if (!reqPathCount)
-			{
-				// Could not find path, start the request from current location.
-				dtVcopy(reqPos, ag->npos);
-				reqPath[0] = path[0];
-				reqPathCount = 1;
-			}
-
-			ag->corridor.setCorridor(reqPos, reqPath, reqPathCount);
-			ag->boundary.reset();
-			ag->partial = false;
-
-			if (reqPath[reqPathCount-1] == ag->targetRef)
-			{
-				ag->targetState = DT_CROWDAGENT_TARGET_VALID;
-				ag->targetReplanTime = 0.0;
-			}
-			else
-			{
-				// The path is longer or potentially unreachable, full plan.
-				ag->targetState = DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE;
-			}
-		}
-		
-		if (ag->targetState == DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE)
-		{
-			nqueue = addToPathQueue(ag, queue, nqueue, PATH_MAX_AGENTS);
-		}
-	}
-
-	for (int i = 0; i < nqueue; ++i)
-	{
-		dtCrowdAgent* ag = queue[i];
-		ag->targetPathqRef = m_pathq.request(ag->corridor.getLastPoly(), ag->targetRef,
-											 ag->corridor.getTarget(), ag->targetPos, &m_filters[ag->params.queryFilterType]);
-		if (ag->targetPathqRef != DT_PATHQ_INVALID)
-			ag->targetState = DT_CROWDAGENT_TARGET_WAITING_FOR_PATH;
-	}
-
-	
-	// Update requests.
-	m_pathq.update(MAX_ITERS_PER_UPDATE);
-
-	dtStatus status;
-
-	// Process path results.
-	for (int i = 0; i < m_maxAgents; ++i)
-	{
-		dtCrowdAgent* ag = &m_agents[i];
-		if (!ag->active)
-			continue;
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-			continue;
-		
-		if (ag->targetState == DT_CROWDAGENT_TARGET_WAITING_FOR_PATH)
-		{
-			// Poll path queue.
-			status = m_pathq.getRequestStatus(ag->targetPathqRef);
-			if (dtStatusFailed(status))
-			{
-				// Path find failed, retry if the target location is still valid.
-				ag->targetPathqRef = DT_PATHQ_INVALID;
-				if (ag->targetRef)
-					ag->targetState = DT_CROWDAGENT_TARGET_REQUESTING;
-				else
-					ag->targetState = DT_CROWDAGENT_TARGET_FAILED;
-				ag->targetReplanTime = 0.0;
-			}
-			else if (dtStatusSucceed(status))
-			{
-				const dtPolyRef* path = ag->corridor.getPath();
-				const int npath = ag->corridor.getPathCount();
-				dtAssert(npath);
-				
-				// Apply results.
-				float targetPos[3];
-				dtVcopy(targetPos, ag->targetPos);
-				
-				dtPolyRef* res = m_pathResult;
-				bool valid = true;
-				int nres = 0;
-				status = m_pathq.getPathResult(ag->targetPathqRef, res, &nres, m_maxPathResult);
-				if (dtStatusFailed(status) || !nres)
-					valid = false;
-
-				if (dtStatusDetail(status, DT_PARTIAL_RESULT))
-					ag->partial = true;
-				else
-					ag->partial = false;
-
-				// Merge result and existing path.
-				// The agent might have moved whilst the request is
-				// being processed, so the path may have changed.
-				// We assume that the end of the path is at the same location
-				// where the request was issued.
-				
-				// The last ref in the old path should be the same as
-				// the location where the request was issued..
-				if (valid && path[npath-1] != res[0])
-					valid = false;
-				
-				if (valid)
-				{
-					// Put the old path infront of the old path.
-					if (npath > 1)
-					{
-						// Make space for the old path.
-						if ((npath-1)+nres > m_maxPathResult)
-							nres = m_maxPathResult - (npath-1);
-						
-						memmove(res+npath-1, res, sizeof(dtPolyRef)*nres);
-						// Copy old path in the beginning.
-						memcpy(res, path, sizeof(dtPolyRef)*(npath-1));
-						nres += npath-1;
-						
-						// Remove trackbacks
-						for (int j = 0; j < nres; ++j)
-						{
-							if (j-1 >= 0 && j+1 < nres)
-							{
-								if (res[j-1] == res[j+1])
-								{
-									memmove(res+(j-1), res+(j+1), sizeof(dtPolyRef)*(nres-(j+1)));
-									nres -= 2;
-									j -= 2;
-								}
-							}
-						}
-						
-					}
-					
-					// Check for partial path.
-					if (res[nres-1] != ag->targetRef)
-					{
-						// Partial path, constrain target position inside the last polygon.
-						float nearest[3];
-						status = m_navquery->closestPointOnPoly(res[nres-1], targetPos, nearest, 0);
-						if (dtStatusSucceed(status))
-							dtVcopy(targetPos, nearest);
-						else
-							valid = false;
-					}
-				}
-				
-				if (valid)
-				{
-					// Set current corridor.
-					ag->corridor.setCorridor(targetPos, res, nres);
-					// Force to update boundary.
-					ag->boundary.reset();
-					ag->targetState = DT_CROWDAGENT_TARGET_VALID;
-				}
-				else
-				{
-					// Something went wrong.
-					ag->targetState = DT_CROWDAGENT_TARGET_FAILED;
-				}
-
-				ag->targetReplanTime = 0.0;
-			}
-		}
-	}
-	
-}
-
-
-void dtCrowd::updateTopologyOptimization(dtCrowdAgent** agents, const int nagents, const float dt)
-{
-	if (!nagents)
-		return;
-	
-	const float OPT_TIME_THR = 0.5f; // seconds
-	const int OPT_MAX_AGENTS = 1;
-	dtCrowdAgent* queue[OPT_MAX_AGENTS];
-	int nqueue = 0;
-	
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-			continue;
-		if ((ag->params.updateFlags & DT_CROWD_OPTIMIZE_TOPO) == 0)
-			continue;
-		ag->topologyOptTime += dt;
-		if (ag->topologyOptTime >= OPT_TIME_THR)
-			nqueue = addToOptQueue(ag, queue, nqueue, OPT_MAX_AGENTS);
-	}
-
-	for (int i = 0; i < nqueue; ++i)
-	{
-		dtCrowdAgent* ag = queue[i];
-		ag->corridor.optimizePathTopology(m_navquery, &m_filters[ag->params.queryFilterType]);
-		ag->topologyOptTime = 0;
-	}
-
-}
-
-void dtCrowd::checkPathValidity(dtCrowdAgent** agents, const int nagents, const float dt)
-{
-	static const int CHECK_LOOKAHEAD = 10;
-	static const float TARGET_REPLAN_DELAY = 1.0; // seconds
-	
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-			
-		ag->targetReplanTime += dt;
-
-		bool replan = false;
-
-		// First check that the current location is valid.
-		const int idx = getAgentIndex(ag);
-		float agentPos[3];
-		dtPolyRef agentRef = ag->corridor.getFirstPoly();
-		dtVcopy(agentPos, ag->npos);
-		if (!m_navquery->isValidPolyRef(agentRef, &m_filters[ag->params.queryFilterType]))
-		{
-			// Current location is not valid, try to reposition.
-			// TODO: this can snap agents, how to handle that?
-			float nearest[3];
-			dtVcopy(nearest, agentPos);
-			agentRef = 0;
-			m_navquery->findNearestPoly(ag->npos, m_agentPlacementHalfExtents, &m_filters[ag->params.queryFilterType], &agentRef, nearest);
-			dtVcopy(agentPos, nearest);
-
-			if (!agentRef)
-			{
-				// Could not find location in navmesh, set state to invalid.
-				ag->corridor.reset(0, agentPos);
-				ag->partial = false;
-				ag->boundary.reset();
-				ag->state = DT_CROWDAGENT_STATE_INVALID;
-				continue;
-			}
-
-			// Make sure the first polygon is valid, but leave other valid
-			// polygons in the path so that replanner can adjust the path better.
-			ag->corridor.fixPathStart(agentRef, agentPos);
-//			ag->corridor.trimInvalidPath(agentRef, agentPos, m_navquery, &m_filter);
-			ag->boundary.reset();
-			dtVcopy(ag->npos, agentPos);
-
-			replan = true;
-		}
-
-		// If the agent does not have move target or is controlled by velocity, no need to recover the target nor replan.
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-			continue;
-
-		// Try to recover move request position.
-		if (ag->targetState != DT_CROWDAGENT_TARGET_NONE && ag->targetState != DT_CROWDAGENT_TARGET_FAILED)
-		{
-			if (!m_navquery->isValidPolyRef(ag->targetRef, &m_filters[ag->params.queryFilterType]))
-			{
-				// Current target is not valid, try to reposition.
-				float nearest[3];
-				dtVcopy(nearest, ag->targetPos);
-				ag->targetRef = 0;
-				m_navquery->findNearestPoly(ag->targetPos, m_agentPlacementHalfExtents, &m_filters[ag->params.queryFilterType], &ag->targetRef, nearest);
-				dtVcopy(ag->targetPos, nearest);
-				replan = true;
-			}
-			if (!ag->targetRef)
-			{
-				// Failed to reposition target, fail moverequest.
-				ag->corridor.reset(agentRef, agentPos);
-				ag->partial = false;
-				ag->targetState = DT_CROWDAGENT_TARGET_NONE;
-			}
-		}
-
-		// If nearby corridor is not valid, replan.
-		if (!ag->corridor.isValid(CHECK_LOOKAHEAD, m_navquery, &m_filters[ag->params.queryFilterType]))
-		{
-			// Fix current path.
-//			ag->corridor.trimInvalidPath(agentRef, agentPos, m_navquery, &m_filter);
-//			ag->boundary.reset();
-			replan = true;
-		}
-		
-		// If the end of the path is near and it is not the requested location, replan.
-		if (ag->targetState == DT_CROWDAGENT_TARGET_VALID)
-		{
-			if (ag->targetReplanTime > TARGET_REPLAN_DELAY &&
-				ag->corridor.getPathCount() < CHECK_LOOKAHEAD &&
-				ag->corridor.getLastPoly() != ag->targetRef)
-				replan = true;
-		}
-
-		// Try to replan path to goal.
-		if (replan)
-		{
-			if (ag->targetState != DT_CROWDAGENT_TARGET_NONE)
-			{
-				requestMoveTargetReplan(idx, ag->targetRef, ag->targetPos);
-			}
-		}
-	}
-}
-	
-void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug)
-{
-	m_velocitySampleCount = 0;
-	
-	const int debugIdx = debug ? debug->idx : -1;
-	
-	dtCrowdAgent** agents = m_activeAgents;
-	int nagents = getActiveAgents(agents, m_maxAgents);
-
-	// Check that all agents still have valid paths.
-	checkPathValidity(agents, nagents, dt);
-	
-	// Update async move request and path finder.
-	updateMoveRequest(dt);
-
-	// Optimize path topology.
-	updateTopologyOptimization(agents, nagents, dt);
-	
-	// Register agents to proximity grid.
-	m_grid->clear();
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		const float* p = ag->npos;
-		const float r = ag->params.radius;
-		m_grid->addItem((unsigned short)i, p[0]-r, p[2]-r, p[0]+r, p[2]+r);
-	}
-	
-	// Get nearby navmesh segments and agents to collide with.
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-
-		// Update the collision boundary after certain distance has been passed or
-		// if it has become invalid.
-		const float updateThr = ag->params.collisionQueryRange*0.25f;
-		if (dtVdist2DSqr(ag->npos, ag->boundary.getCenter()) > dtSqr(updateThr) ||
-			!ag->boundary.isValid(m_navquery, &m_filters[ag->params.queryFilterType]))
-		{
-			ag->boundary.update(ag->corridor.getFirstPoly(), ag->npos, ag->params.collisionQueryRange,
-								m_navquery, &m_filters[ag->params.queryFilterType]);
-		}
-		// Query neighbour agents
-		ag->nneis = getNeighbours(ag->npos, ag->params.height, ag->params.collisionQueryRange,
-								  ag, ag->neis, DT_CROWDAGENT_MAX_NEIGHBOURS,
-								  agents, nagents, m_grid);
-		for (int j = 0; j < ag->nneis; j++)
-			ag->neis[j].idx = getAgentIndex(agents[ag->neis[j].idx]);
-	}
-	
-	// Find next corner to steer to.
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-			continue;
-		
-		// Find corners for steering
-		ag->ncorners = ag->corridor.findCorners(ag->cornerVerts, ag->cornerFlags, ag->cornerPolys,
-												DT_CROWDAGENT_MAX_CORNERS, m_navquery, &m_filters[ag->params.queryFilterType]);
-		
-		// Check to see if the corner after the next corner is directly visible,
-		// and short cut to there.
-		if ((ag->params.updateFlags & DT_CROWD_OPTIMIZE_VIS) && ag->ncorners > 0)
-		{
-			const float* target = &ag->cornerVerts[dtMin(1,ag->ncorners-1)*3];
-			ag->corridor.optimizePathVisibility(target, ag->params.pathOptimizationRange, m_navquery, &m_filters[ag->params.queryFilterType]);
-			
-			// Copy data for debug purposes.
-			if (debugIdx == i)
-			{
-				dtVcopy(debug->optStart, ag->corridor.getPos());
-				dtVcopy(debug->optEnd, target);
-			}
-		}
-		else
-		{
-			// Copy data for debug purposes.
-			if (debugIdx == i)
-			{
-				dtVset(debug->optStart, 0,0,0);
-				dtVset(debug->optEnd, 0,0,0);
-			}
-		}
-	}
-	
-	// Trigger off-mesh connections (depends on corners).
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-			continue;
-		
-		// Check 
-		const float triggerRadius = ag->params.radius*2.25f;
-		if (overOffmeshConnection(ag, triggerRadius))
-		{
-			// Prepare to off-mesh connection.
-			const int idx = (int)(ag - m_agents);
-			dtCrowdAgentAnimation* anim = &m_agentAnims[idx];
-			
-			// Adjust the path over the off-mesh connection.
-			dtPolyRef refs[2];
-			if (ag->corridor.moveOverOffmeshConnection(ag->cornerPolys[ag->ncorners-1], refs,
-													   anim->startPos, anim->endPos, m_navquery))
-			{
-				dtVcopy(anim->initPos, ag->npos);
-				anim->polyRef = refs[1];
-				anim->active = true;
-				anim->t = 0.0f;
-				anim->tmax = (dtVdist2D(anim->startPos, anim->endPos) / ag->params.maxSpeed) * 0.5f;
-				
-				ag->state = DT_CROWDAGENT_STATE_OFFMESH;
-				ag->ncorners = 0;
-				ag->nneis = 0;
-				continue;
-			}
-			else
-			{
-				// Path validity check will ensure that bad/blocked connections will be replanned.
-			}
-		}
-	}
-		
-	// Calculate steering.
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE)
-			continue;
-		
-		float dvel[3] = {0,0,0};
-
-		if (ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-		{
-			dtVcopy(dvel, ag->targetPos);
-			ag->desiredSpeed = dtVlen(ag->targetPos);
-		}
-		else
-		{
-			// Calculate steering direction.
-			if (ag->params.updateFlags & DT_CROWD_ANTICIPATE_TURNS)
-				calcSmoothSteerDirection(ag, dvel);
-			else
-				calcStraightSteerDirection(ag, dvel);
-			
-			// Calculate speed scale, which tells the agent to slowdown at the end of the path.
-			const float slowDownRadius = ag->params.radius*2;	// TODO: make less hacky.
-			const float speedScale = getDistanceToGoal(ag, slowDownRadius) / slowDownRadius;
-				
-			ag->desiredSpeed = ag->params.maxSpeed;
-			dtVscale(dvel, dvel, ag->desiredSpeed * speedScale);
-		}
-
-		// Separation
-		if (ag->params.updateFlags & DT_CROWD_SEPARATION)
-		{
-			const float separationDist = ag->params.collisionQueryRange; 
-			const float invSeparationDist = 1.0f / separationDist; 
-			const float separationWeight = ag->params.separationWeight;
-			
-			float w = 0;
-			float disp[3] = {0,0,0};
-			
-			for (int j = 0; j < ag->nneis; ++j)
-			{
-				const dtCrowdAgent* nei = &m_agents[ag->neis[j].idx];
-				
-				float diff[3];
-				dtVsub(diff, ag->npos, nei->npos);
-				diff[1] = 0;
-				
-				const float distSqr = dtVlenSqr(diff);
-				if (distSqr < 0.00001f)
-					continue;
-				if (distSqr > dtSqr(separationDist))
-					continue;
-				const float dist = dtMathSqrtf(distSqr);
-				const float weight = separationWeight * (1.0f - dtSqr(dist*invSeparationDist));
-				
-				dtVmad(disp, disp, diff, weight/dist);
-				w += 1.0f;
-			}
-			
-			if (w > 0.0001f)
-			{
-				// Adjust desired velocity.
-				dtVmad(dvel, dvel, disp, 1.0f/w);
-				// Clamp desired velocity to desired speed.
-				const float speedSqr = dtVlenSqr(dvel);
-				const float desiredSqr = dtSqr(ag->desiredSpeed);
-				if (speedSqr > desiredSqr)
-					dtVscale(dvel, dvel, desiredSqr/speedSqr);
-			}
-		}
-		
-		// Set the desired velocity.
-		dtVcopy(ag->dvel, dvel);
-	}
-	
-	// Velocity planning.	
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-		
-		if (ag->params.updateFlags & DT_CROWD_OBSTACLE_AVOIDANCE)
-		{
-			m_obstacleQuery->reset();
-			
-			// Add neighbours as obstacles.
-			for (int j = 0; j < ag->nneis; ++j)
-			{
-				const dtCrowdAgent* nei = &m_agents[ag->neis[j].idx];
-				m_obstacleQuery->addCircle(nei->npos, nei->params.radius, nei->vel, nei->dvel);
-			}
-
-			// Append neighbour segments as obstacles.
-			for (int j = 0; j < ag->boundary.getSegmentCount(); ++j)
-			{
-				const float* s = ag->boundary.getSegment(j);
-				if (dtTriArea2D(ag->npos, s, s+3) < 0.0f)
-					continue;
-				m_obstacleQuery->addSegment(s, s+3);
-			}
-
-			dtObstacleAvoidanceDebugData* vod = 0;
-			if (debugIdx == i) 
-				vod = debug->vod;
-			
-			// Sample new safe velocity.
-			bool adaptive = true;
-			int ns = 0;
-
-			const dtObstacleAvoidanceParams* params = &m_obstacleQueryParams[ag->params.obstacleAvoidanceType];
-				
-			if (adaptive)
-			{
-				ns = m_obstacleQuery->sampleVelocityAdaptive(ag->npos, ag->params.radius, ag->desiredSpeed,
-															 ag->vel, ag->dvel, ag->nvel, params, vod);
-			}
-			else
-			{
-				ns = m_obstacleQuery->sampleVelocityGrid(ag->npos, ag->params.radius, ag->desiredSpeed,
-														 ag->vel, ag->dvel, ag->nvel, params, vod);
-			}
-			m_velocitySampleCount += ns;
-		}
-		else
-		{
-			// If not using velocity planning, new velocity is directly the desired velocity.
-			dtVcopy(ag->nvel, ag->dvel);
-		}
-	}
-
-	// Integrate.
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-		integrate(ag, dt);
-	}
-	
-	// Handle collisions.
-	static const float COLLISION_RESOLVE_FACTOR = 0.7f;
-	
-	for (int iter = 0; iter < 4; ++iter)
-	{
-		for (int i = 0; i < nagents; ++i)
-		{
-			dtCrowdAgent* ag = agents[i];
-			const int idx0 = getAgentIndex(ag);
-			
-			if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-				continue;
-
-			dtVset(ag->disp, 0,0,0);
-			
-			float w = 0;
-
-			for (int j = 0; j < ag->nneis; ++j)
-			{
-				const dtCrowdAgent* nei = &m_agents[ag->neis[j].idx];
-				const int idx1 = getAgentIndex(nei);
-
-				float diff[3];
-				dtVsub(diff, ag->npos, nei->npos);
-				diff[1] = 0;
-				
-				float dist = dtVlenSqr(diff);
-				if (dist > dtSqr(ag->params.radius + nei->params.radius))
-					continue;
-				dist = dtMathSqrtf(dist);
-				float pen = (ag->params.radius + nei->params.radius) - dist;
-				if (dist < 0.0001f)
-				{
-					// Agents on top of each other, try to choose diverging separation directions.
-					if (idx0 > idx1)
-						dtVset(diff, -ag->dvel[2],0,ag->dvel[0]);
-					else
-						dtVset(diff, ag->dvel[2],0,-ag->dvel[0]);
-					pen = 0.01f;
-				}
-				else
-				{
-					pen = (1.0f/dist) * (pen*0.5f) * COLLISION_RESOLVE_FACTOR;
-				}
-				
-				dtVmad(ag->disp, ag->disp, diff, pen);			
-				
-				w += 1.0f;
-			}
-			
-			if (w > 0.0001f)
-			{
-				const float iw = 1.0f / w;
-				dtVscale(ag->disp, ag->disp, iw);
-			}
-		}
-		
-		for (int i = 0; i < nagents; ++i)
-		{
-			dtCrowdAgent* ag = agents[i];
-			if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-				continue;
-			
-			dtVadd(ag->npos, ag->npos, ag->disp);
-		}
-	}
-	
-	for (int i = 0; i < nagents; ++i)
-	{
-		dtCrowdAgent* ag = agents[i];
-		if (ag->state != DT_CROWDAGENT_STATE_WALKING)
-			continue;
-		
-		// Move along navmesh.
-		ag->corridor.movePosition(ag->npos, m_navquery, &m_filters[ag->params.queryFilterType]);
-		// Get valid constrained position back.
-		dtVcopy(ag->npos, ag->corridor.getPos());
-
-		// If not using path, truncate the corridor to just one poly.
-		if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
-		{
-			ag->corridor.reset(ag->corridor.getFirstPoly(), ag->npos);
-			ag->partial = false;
-		}
-
-	}
-	
-	// Update agents using off-mesh connection.
-	for (int i = 0; i < m_maxAgents; ++i)
-	{
-		dtCrowdAgentAnimation* anim = &m_agentAnims[i];
-		if (!anim->active)
-			continue;
-		dtCrowdAgent* ag = agents[i];
-
-		anim->t += dt;
-		if (anim->t > anim->tmax)
-		{
-			// Reset animation
-			anim->active = false;
-			// Prepare agent for walking.
-			ag->state = DT_CROWDAGENT_STATE_WALKING;
-			continue;
-		}
-		
-		// Update position
-		const float ta = anim->tmax*0.15f;
-		const float tb = anim->tmax;
-		if (anim->t < ta)
-		{
-			const float u = tween(anim->t, 0.0, ta);
-			dtVlerp(ag->npos, anim->initPos, anim->startPos, u);
-		}
-		else
-		{
-			const float u = tween(anim->t, ta, tb);
-			dtVlerp(ag->npos, anim->startPos, anim->endPos, u);
-		}
-			
-		// Update velocity.
-		dtVset(ag->vel, 0,0,0);
-		dtVset(ag->dvel, 0,0,0);
-	}
-	
-}

+ 0 - 460
panda/src/recastdetour/DetourCrowd.h

@@ -1,460 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOURCROWD_H
-#define DETOURCROWD_H
-
-#include "DetourNavMeshQuery.h"
-#include "DetourObstacleAvoidance.h"
-#include "DetourLocalBoundary.h"
-#include "DetourPathCorridor.h"
-#include "DetourProximityGrid.h"
-#include "DetourPathQueue.h"
-
-/// The maximum number of neighbors that a crowd agent can take into account
-/// for steering decisions.
-/// @ingroup crowd
-static const int DT_CROWDAGENT_MAX_NEIGHBOURS = 6;
-
-/// The maximum number of corners a crowd agent will look ahead in the path.
-/// This value is used for sizing the crowd agent corner buffers.
-/// Due to the behavior of the crowd manager, the actual number of useful
-/// corners will be one less than this number.
-/// @ingroup crowd
-static const int DT_CROWDAGENT_MAX_CORNERS = 4;
-
-/// The maximum number of crowd avoidance configurations supported by the
-/// crowd manager.
-/// @ingroup crowd
-/// @see dtObstacleAvoidanceParams, dtCrowd::setObstacleAvoidanceParams(), dtCrowd::getObstacleAvoidanceParams(),
-///		 dtCrowdAgentParams::obstacleAvoidanceType
-static const int DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS = 8;
-
-/// The maximum number of query filter types supported by the crowd manager.
-/// @ingroup crowd
-/// @see dtQueryFilter, dtCrowd::getFilter() dtCrowd::getEditableFilter(),
-///		dtCrowdAgentParams::queryFilterType
-static const int DT_CROWD_MAX_QUERY_FILTER_TYPE = 16;
-
-/// Provides neighbor data for agents managed by the crowd.
-/// @ingroup crowd
-/// @see dtCrowdAgent::neis, dtCrowd
-struct dtCrowdNeighbour
-{
-	int idx;		///< The index of the neighbor in the crowd.
-	float dist;		///< The distance between the current agent and the neighbor.
-};
-
-/// The type of navigation mesh polygon the agent is currently traversing.
-/// @ingroup crowd
-enum CrowdAgentState
-{
-	DT_CROWDAGENT_STATE_INVALID,		///< The agent is not in a valid state.
-	DT_CROWDAGENT_STATE_WALKING,		///< The agent is traversing a normal navigation mesh polygon.
-	DT_CROWDAGENT_STATE_OFFMESH,		///< The agent is traversing an off-mesh connection.
-};
-
-/// Configuration parameters for a crowd agent.
-/// @ingroup crowd
-struct dtCrowdAgentParams
-{
-	float radius;						///< Agent radius. [Limit: >= 0]
-	float height;						///< Agent height. [Limit: > 0]
-	float maxAcceleration;				///< Maximum allowed acceleration. [Limit: >= 0]
-	float maxSpeed;						///< Maximum allowed speed. [Limit: >= 0]
-
-	/// Defines how close a collision element must be before it is considered for steering behaviors. [Limits: > 0]
-	float collisionQueryRange;
-
-	float pathOptimizationRange;		///< The path visibility optimization range. [Limit: > 0]
-
-	/// How aggresive the agent manager should be at avoiding collisions with this agent. [Limit: >= 0]
-	float separationWeight;
-
-	/// Flags that impact steering behavior. (See: #UpdateFlags)
-	unsigned char updateFlags;
-
-	/// The index of the avoidance configuration to use for the agent. 
-	/// [Limits: 0 <= value <= #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
-	unsigned char obstacleAvoidanceType;	
-
-	/// The index of the query filter used by this agent.
-	unsigned char queryFilterType;
-
-	/// User defined data attached to the agent.
-	void* userData;
-};
-
-enum MoveRequestState
-{
-	DT_CROWDAGENT_TARGET_NONE = 0,
-	DT_CROWDAGENT_TARGET_FAILED,
-	DT_CROWDAGENT_TARGET_VALID,
-	DT_CROWDAGENT_TARGET_REQUESTING,
-	DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE,
-	DT_CROWDAGENT_TARGET_WAITING_FOR_PATH,
-	DT_CROWDAGENT_TARGET_VELOCITY,
-};
-
-/// Represents an agent managed by a #dtCrowd object.
-/// @ingroup crowd
-struct dtCrowdAgent
-{
-	/// True if the agent is active, false if the agent is in an unused slot in the agent pool.
-	bool active;
-
-	/// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState)
-	unsigned char state;
-
-	/// True if the agent has valid path (targetState == DT_CROWDAGENT_TARGET_VALID) and the path does not lead to the requested position, else false.
-	bool partial;
-
-	/// The path corridor the agent is using.
-	dtPathCorridor corridor;
-
-	/// The local boundary data for the agent.
-	dtLocalBoundary boundary;
-	
-	/// Time since the agent's path corridor was optimized.
-	float topologyOptTime;
-	
-	/// The known neighbors of the agent.
-	dtCrowdNeighbour neis[DT_CROWDAGENT_MAX_NEIGHBOURS];
-
-	/// The number of neighbors.
-	int nneis;
-	
-	/// The desired speed.
-	float desiredSpeed;
-
-	float npos[3];		///< The current agent position. [(x, y, z)]
-	float disp[3];		///< A temporary value used to accumulate agent displacement during iterative collision resolution. [(x, y, z)]
-	float dvel[3];		///< The desired velocity of the agent. Based on the current path, calculated from scratch each frame. [(x, y, z)]
-	float nvel[3];		///< The desired velocity adjusted by obstacle avoidance, calculated from scratch each frame. [(x, y, z)]
-	float vel[3];		///< The actual velocity of the agent. The change from nvel -> vel is constrained by max acceleration. [(x, y, z)]
-
-	/// The agent's configuration parameters.
-	dtCrowdAgentParams params;
-
-	/// The local path corridor corners for the agent. (Staight path.) [(x, y, z) * #ncorners]
-	float cornerVerts[DT_CROWDAGENT_MAX_CORNERS*3];
-
-	/// The local path corridor corner flags. (See: #dtStraightPathFlags) [(flags) * #ncorners]
-	unsigned char cornerFlags[DT_CROWDAGENT_MAX_CORNERS];
-
-	/// The reference id of the polygon being entered at the corner. [(polyRef) * #ncorners]
-	dtPolyRef cornerPolys[DT_CROWDAGENT_MAX_CORNERS];
-
-	/// The number of corners.
-	int ncorners;
-	
-	unsigned char targetState;			///< State of the movement request.
-	dtPolyRef targetRef;				///< Target polyref of the movement request.
-	float targetPos[3];					///< Target position of the movement request (or velocity in case of DT_CROWDAGENT_TARGET_VELOCITY).
-	dtPathQueueRef targetPathqRef;		///< Path finder ref.
-	bool targetReplan;					///< Flag indicating that the current path is being replanned.
-	float targetReplanTime;				/// <Time since the agent's target was replanned.
-};
-
-struct dtCrowdAgentAnimation
-{
-	bool active;
-	float initPos[3], startPos[3], endPos[3];
-	dtPolyRef polyRef;
-	float t, tmax;
-};
-
-/// Crowd agent update flags.
-/// @ingroup crowd
-/// @see dtCrowdAgentParams::updateFlags
-enum UpdateFlags
-{
-	DT_CROWD_ANTICIPATE_TURNS = 1,
-	DT_CROWD_OBSTACLE_AVOIDANCE = 2,
-	DT_CROWD_SEPARATION = 4,
-	DT_CROWD_OPTIMIZE_VIS = 8,			///< Use #dtPathCorridor::optimizePathVisibility() to optimize the agent path.
-	DT_CROWD_OPTIMIZE_TOPO = 16,		///< Use dtPathCorridor::optimizePathTopology() to optimize the agent path.
-};
-
-struct dtCrowdAgentDebugInfo
-{
-	int idx;
-	float optStart[3], optEnd[3];
-	dtObstacleAvoidanceDebugData* vod;
-};
-
-/// Provides local steering behaviors for a group of agents. 
-/// @ingroup crowd
-class dtCrowd
-{
-	int m_maxAgents;
-	dtCrowdAgent* m_agents;
-	dtCrowdAgent** m_activeAgents;
-	dtCrowdAgentAnimation* m_agentAnims;
-	
-	dtPathQueue m_pathq;
-
-	dtObstacleAvoidanceParams m_obstacleQueryParams[DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS];
-	dtObstacleAvoidanceQuery* m_obstacleQuery;
-	
-	dtProximityGrid* m_grid;
-	
-	dtPolyRef* m_pathResult;
-	int m_maxPathResult;
-	
-	float m_agentPlacementHalfExtents[3];
-
-	dtQueryFilter m_filters[DT_CROWD_MAX_QUERY_FILTER_TYPE];
-
-	float m_maxAgentRadius;
-
-	int m_velocitySampleCount;
-
-	dtNavMeshQuery* m_navquery;
-
-	void updateTopologyOptimization(dtCrowdAgent** agents, const int nagents, const float dt);
-	void updateMoveRequest(const float dt);
-	void checkPathValidity(dtCrowdAgent** agents, const int nagents, const float dt);
-
-	inline int getAgentIndex(const dtCrowdAgent* agent) const  { return (int)(agent - m_agents); }
-
-	bool requestMoveTargetReplan(const int idx, dtPolyRef ref, const float* pos);
-
-	void purge();
-	
-public:
-	dtCrowd();
-	~dtCrowd();
-	
-	/// Initializes the crowd.  
-	///  @param[in]		maxAgents		The maximum number of agents the crowd can manage. [Limit: >= 1]
-	///  @param[in]		maxAgentRadius	The maximum radius of any agent that will be added to the crowd. [Limit: > 0]
-	///  @param[in]		nav				The navigation mesh to use for planning.
-	/// @return True if the initialization succeeded.
-	bool init(const int maxAgents, const float maxAgentRadius, dtNavMesh* nav);
-	
-	/// Sets the shared avoidance configuration for the specified index.
-	///  @param[in]		idx		The index. [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
-	///  @param[in]		params	The new configuration.
-	void setObstacleAvoidanceParams(const int idx, const dtObstacleAvoidanceParams* params);
-
-	/// Gets the shared avoidance configuration for the specified index.
-	///  @param[in]		idx		The index of the configuration to retreive. 
-	///							[Limits:  0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
-	/// @return The requested configuration.
-	const dtObstacleAvoidanceParams* getObstacleAvoidanceParams(const int idx) const;
-	
-	/// Gets the specified agent from the pool.
-	///	 @param[in]		idx		The agent index. [Limits: 0 <= value < #getAgentCount()]
-	/// @return The requested agent.
-	const dtCrowdAgent* getAgent(const int idx);
-
-	/// Gets the specified agent from the pool.
-	///	 @param[in]		idx		The agent index. [Limits: 0 <= value < #getAgentCount()]
-	/// @return The requested agent.
-	dtCrowdAgent* getEditableAgent(const int idx);
-
-	/// The maximum number of agents that can be managed by the object.
-	/// @return The maximum number of agents.
-	int getAgentCount() const;
-	
-	/// Adds a new agent to the crowd.
-	///  @param[in]		pos		The requested position of the agent. [(x, y, z)]
-	///  @param[in]		params	The configutation of the agent.
-	/// @return The index of the agent in the agent pool. Or -1 if the agent could not be added.
-	int addAgent(const float* pos, const dtCrowdAgentParams* params);
-
-	/// Updates the specified agent's configuration.
-	///  @param[in]		idx		The agent index. [Limits: 0 <= value < #getAgentCount()]
-	///  @param[in]		params	The new agent configuration.
-	void updateAgentParameters(const int idx, const dtCrowdAgentParams* params);
-
-	/// Removes the agent from the crowd.
-	///  @param[in]		idx		The agent index. [Limits: 0 <= value < #getAgentCount()]
-	void removeAgent(const int idx);
-	
-	/// Submits a new move request for the specified agent.
-	///  @param[in]		idx		The agent index. [Limits: 0 <= value < #getAgentCount()]
-	///  @param[in]		ref		The position's polygon reference.
-	///  @param[in]		pos		The position within the polygon. [(x, y, z)]
-	/// @return True if the request was successfully submitted.
-	bool requestMoveTarget(const int idx, dtPolyRef ref, const float* pos);
-
-	/// Submits a new move request for the specified agent.
-	///  @param[in]		idx		The agent index. [Limits: 0 <= value < #getAgentCount()]
-	///  @param[in]		vel		The movement velocity. [(x, y, z)]
-	/// @return True if the request was successfully submitted.
-	bool requestMoveVelocity(const int idx, const float* vel);
-
-	/// Resets any request for the specified agent.
-	///  @param[in]		idx		The agent index. [Limits: 0 <= value < #getAgentCount()]
-	/// @return True if the request was successfully reseted.
-	bool resetMoveTarget(const int idx);
-
-	/// Gets the active agents int the agent pool.
-	///  @param[out]	agents		An array of agent pointers. [(#dtCrowdAgent *) * maxAgents]
-	///  @param[in]		maxAgents	The size of the crowd agent array.
-	/// @return The number of agents returned in @p agents.
-	int getActiveAgents(dtCrowdAgent** agents, const int maxAgents);
-
-	/// Updates the steering and positions of all agents.
-	///  @param[in]		dt		The time, in seconds, to update the simulation. [Limit: > 0]
-	///  @param[out]	debug	A debug object to load with debug information. [Opt]
-	void update(const float dt, dtCrowdAgentDebugInfo* debug);
-	
-	/// Gets the filter used by the crowd.
-	/// @return The filter used by the crowd.
-	inline const dtQueryFilter* getFilter(const int i) const { return (i >= 0 && i < DT_CROWD_MAX_QUERY_FILTER_TYPE) ? &m_filters[i] : 0; }
-	
-	/// Gets the filter used by the crowd.
-	/// @return The filter used by the crowd.
-	inline dtQueryFilter* getEditableFilter(const int i) { return (i >= 0 && i < DT_CROWD_MAX_QUERY_FILTER_TYPE) ? &m_filters[i] : 0; }
-
-	/// Gets the search halfExtents [(x, y, z)] used by the crowd for query operations. 
-	/// @return The search halfExtents used by the crowd. [(x, y, z)]
-	const float* getQueryHalfExtents() const { return m_agentPlacementHalfExtents; }
-
-	/// Same as getQueryHalfExtents. Left to maintain backwards compatibility.
-	/// @return The search halfExtents used by the crowd. [(x, y, z)]
-	const float* getQueryExtents() const { return m_agentPlacementHalfExtents; }
-	
-	/// Gets the velocity sample count.
-	/// @return The velocity sample count.
-	inline int getVelocitySampleCount() const { return m_velocitySampleCount; }
-	
-	/// Gets the crowd's proximity grid.
-	/// @return The crowd's proximity grid.
-	const dtProximityGrid* getGrid() const { return m_grid; }
-
-	/// Gets the crowd's path request queue.
-	/// @return The crowd's path request queue.
-	const dtPathQueue* getPathQueue() const { return &m_pathq; }
-
-	/// Gets the query object used by the crowd.
-	const dtNavMeshQuery* getNavMeshQuery() const { return m_navquery; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtCrowd(const dtCrowd&);
-	dtCrowd& operator=(const dtCrowd&);
-};
-
-/// Allocates a crowd object using the Detour allocator.
-/// @return A crowd object that is ready for initialization, or null on failure.
-///  @ingroup crowd
-dtCrowd* dtAllocCrowd();
-
-/// Frees the specified crowd object using the Detour allocator.
-///  @param[in]		ptr		A crowd object allocated using #dtAllocCrowd
-///  @ingroup crowd
-void dtFreeCrowd(dtCrowd* ptr);
-
-
-#endif // DETOURCROWD_H
-
-///////////////////////////////////////////////////////////////////////////
-
-// This section contains detailed documentation for members that don't have
-// a source file. It reduces clutter in the main section of the header.
-
-/**
-
-@defgroup crowd Crowd
-
-Members in this module implement local steering and dynamic avoidance features.
-
-The crowd is the big beast of the navigation features. It not only handles a 
-lot of the path management for you, but also local steering and dynamic 
-avoidance between members of the crowd. I.e. It can keep your agents from 
-running into each other.
-
-Main class: #dtCrowd
-
-The #dtNavMeshQuery and #dtPathCorridor classes provide perfectly good, easy 
-to use path planning features. But in the end they only give you points that 
-your navigation client should be moving toward. When it comes to deciding things 
-like agent velocity and steering to avoid other agents, that is up to you to 
-implement. Unless, of course, you decide to use #dtCrowd.
-
-Basically, you add an agent to the crowd, providing various configuration 
-settings such as maximum speed and acceleration. You also provide a local 
-target to more toward. The crowd manager then provides, with every update, the 
-new agent position and velocity for the frame. The movement will be 
-constrained to the navigation mesh, and steering will be applied to ensure 
-agents managed by the crowd do not collide with each other.
-
-This is very powerful feature set. But it comes with limitations.
-
-The biggest limitation is that you must give control of the agent's position 
-completely over to the crowd manager. You can update things like maximum speed 
-and acceleration. But in order for the crowd manager to do its thing, it can't 
-allow you to constantly be giving it overrides to position and velocity. So 
-you give up direct control of the agent's movement. It belongs to the crowd.
-
-The second biggest limitation revolves around the fact that the crowd manager 
-deals with local planning. So the agent's target should never be more than 
-256 polygons aways from its current position. If it is, you risk 
-your agent failing to reach its target. So you may still need to do long 
-distance planning and provide the crowd manager with intermediate targets.
-
-Other significant limitations:
-
-- All agents using the crowd manager will use the same #dtQueryFilter.
-- Crowd management is relatively expensive. The maximum agents under crowd 
-  management at any one time is between 20 and 30.  A good place to start
-  is a maximum of 25 agents for 0.5ms per frame.
-
-@note This is a summary list of members.  Use the index or search 
-feature to find minor members.
-
-@struct dtCrowdAgentParams
-@see dtCrowdAgent, dtCrowd::addAgent(), dtCrowd::updateAgentParameters()
-
-@var dtCrowdAgentParams::obstacleAvoidanceType
-@par
-
-#dtCrowd permits agents to use different avoidance configurations.  This value 
-is the index of the #dtObstacleAvoidanceParams within the crowd.
-
-@see dtObstacleAvoidanceParams, dtCrowd::setObstacleAvoidanceParams(), 
-	 dtCrowd::getObstacleAvoidanceParams()
-
-@var dtCrowdAgentParams::collisionQueryRange
-@par
-
-Collision elements include other agents and navigation mesh boundaries.
-
-This value is often based on the agent radius and/or maximum speed. E.g. radius * 8
-
-@var dtCrowdAgentParams::pathOptimizationRange
-@par
-
-Only applicalbe if #updateFlags includes the #DT_CROWD_OPTIMIZE_VIS flag.
-
-This value is often based on the agent radius. E.g. radius * 30
-
-@see dtPathCorridor::optimizePathVisibility()
-
-@var dtCrowdAgentParams::separationWeight
-@par
-
-A higher value will result in agents trying to stay farther away from each other at 
-the cost of more difficult steering in tight spaces.
-
-*/
-

+ 0 - 864
panda/src/recastdetour/DetourDebugDraw.cpp

@@ -1,864 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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.
-//
-
-#include "DebugDraw.h"
-#include "DetourDebugDraw.h"
-#include "DetourNavMesh.h"
-#include "DetourCommon.h"
-#include "DetourNode.h"
-
-
-static float distancePtLine2d(const float* pt, const float* p, const float* q)
-{
-	float pqx = q[0] - p[0];
-	float pqz = q[2] - p[2];
-	float dx = pt[0] - p[0];
-	float dz = pt[2] - p[2];
-	float d = pqx*pqx + pqz*pqz;
-	float t = pqx*dx + pqz*dz;
-	if (d != 0) t /= d;
-	dx = p[0] + t*pqx - pt[0];
-	dz = p[2] + t*pqz - pt[2];
-	return dx*dx + dz*dz;
-}
-
-static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile,
-							   const unsigned int col, const float linew,
-							   bool inner)
-{
-	static const float thr = 0.01f*0.01f;
-
-	dd->begin(DU_DRAW_LINES, linew);
-
-	for (int i = 0; i < tile->header->polyCount; ++i)
-	{
-		const dtPoly* p = &tile->polys[i];
-		
-		if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) continue;
-		
-		const dtPolyDetail* pd = &tile->detailMeshes[i];
-		
-		for (int j = 0, nj = (int)p->vertCount; j < nj; ++j)
-		{
-			unsigned int c = col;
-			if (inner)
-			{
-				if (p->neis[j] == 0) continue;
-				if (p->neis[j] & DT_EXT_LINK)
-				{
-					bool con = false;
-					for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
-					{
-						if (tile->links[k].edge == j)
-						{
-							con = true;
-							break;
-						}
-					}
-					if (con)
-						c = duRGBA(255,255,255,48);
-					else
-						c = duRGBA(0,0,0,48);
-				}
-				else
-					c = duRGBA(0,48,64,32);
-			}
-			else
-			{
-				if (p->neis[j] != 0) continue;
-			}
-			
-			const float* v0 = &tile->verts[p->verts[j]*3];
-			const float* v1 = &tile->verts[p->verts[(j+1) % nj]*3];
-			
-			// Draw detail mesh edges which align with the actual poly edge.
-			// This is really slow.
-			for (int k = 0; k < pd->triCount; ++k)
-			{
-				const unsigned char* t = &tile->detailTris[(pd->triBase+k)*4];
-				const float* tv[3];
-				for (int m = 0; m < 3; ++m)
-				{
-					if (t[m] < p->vertCount)
-						tv[m] = &tile->verts[p->verts[t[m]]*3];
-					else
-						tv[m] = &tile->detailVerts[(pd->vertBase+(t[m]-p->vertCount))*3];
-				}
-				for (int m = 0, n = 2; m < 3; n=m++)
-				{
-					if ((dtGetDetailTriEdgeFlags(t[3], n) & DT_DETAIL_EDGE_BOUNDARY) == 0)
-						continue;
-
-					if (distancePtLine2d(tv[n],v0,v1) < thr &&
-						distancePtLine2d(tv[m],v0,v1) < thr)
-					{
-						dd->vertex(tv[n], c);
-						dd->vertex(tv[m], c);
-					}
-				}
-			}
-		}
-	}
-	dd->end();
-}
-
-static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query,
-						 const dtMeshTile* tile, unsigned char flags)
-{
-	dtPolyRef base = mesh.getPolyRefBase(tile);
-
-	int tileNum = mesh.decodePolyIdTile(base);
-	const unsigned int tileColor = duIntToCol(tileNum, 128);
-	
-	dd->depthMask(false);
-
-	dd->begin(DU_DRAW_TRIS);
-	for (int i = 0; i < tile->header->polyCount; ++i)
-	{
-		const dtPoly* p = &tile->polys[i];
-		if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)	// Skip off-mesh links.
-			continue;
-			
-		const dtPolyDetail* pd = &tile->detailMeshes[i];
-
-		unsigned int col;
-		if (query && query->isInClosedList(base | (dtPolyRef)i))
-			col = duRGBA(255,196,0,64);
-		else
-		{
-			if (flags & DU_DRAWNAVMESH_COLOR_TILES)
-				col = tileColor;
-			else
-				col = duTransCol(dd->areaToCol(p->getArea()), 64);
-		}
-		
-		for (int j = 0; j < pd->triCount; ++j)
-		{
-			const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
-			for (int k = 0; k < 3; ++k)
-			{
-				if (t[k] < p->vertCount)
-					dd->vertex(&tile->verts[p->verts[t[k]]*3], col);
-				else
-					dd->vertex(&tile->detailVerts[(pd->vertBase+t[k]-p->vertCount)*3], col);
-			}
-		}
-	}
-	dd->end();
-	
-	// Draw inter poly boundaries
-	drawPolyBoundaries(dd, tile, duRGBA(0,48,64,32), 1.5f, true);
-	
-	// Draw outer poly boundaries
-	drawPolyBoundaries(dd, tile, duRGBA(0,48,64,220), 2.5f, false);
-
-	if (flags & DU_DRAWNAVMESH_OFFMESHCONS)
-	{
-		dd->begin(DU_DRAW_LINES, 2.0f);
-		for (int i = 0; i < tile->header->polyCount; ++i)
-		{
-			const dtPoly* p = &tile->polys[i];
-			if (p->getType() != DT_POLYTYPE_OFFMESH_CONNECTION)	// Skip regular polys.
-				continue;
-			
-			unsigned int col, col2;
-			if (query && query->isInClosedList(base | (dtPolyRef)i))
-				col = duRGBA(255,196,0,220);
-			else
-				col = duDarkenCol(duTransCol(dd->areaToCol(p->getArea()), 220));
-
-			const dtOffMeshConnection* con = &tile->offMeshCons[i - tile->header->offMeshBase];
-			const float* va = &tile->verts[p->verts[0]*3];
-			const float* vb = &tile->verts[p->verts[1]*3];
-
-			// Check to see if start and end end-points have links.
-			bool startSet = false;
-			bool endSet = false;
-			for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
-			{
-				if (tile->links[k].edge == 0)
-					startSet = true;
-				if (tile->links[k].edge == 1)
-					endSet = true;
-			}
-			
-			// End points and their on-mesh locations.
-			dd->vertex(va[0],va[1],va[2], col);
-			dd->vertex(con->pos[0],con->pos[1],con->pos[2], col);
-			col2 = startSet ? col : duRGBA(220,32,16,196);
-			duAppendCircle(dd, con->pos[0],con->pos[1]+0.1f,con->pos[2], con->rad, col2);
-
-			dd->vertex(vb[0],vb[1],vb[2], col);
-			dd->vertex(con->pos[3],con->pos[4],con->pos[5], col);
-			col2 = endSet ? col : duRGBA(220,32,16,196);
-			duAppendCircle(dd, con->pos[3],con->pos[4]+0.1f,con->pos[5], con->rad, col2);
-			
-			// End point vertices.
-			dd->vertex(con->pos[0],con->pos[1],con->pos[2], duRGBA(0,48,64,196));
-			dd->vertex(con->pos[0],con->pos[1]+0.2f,con->pos[2], duRGBA(0,48,64,196));
-			
-			dd->vertex(con->pos[3],con->pos[4],con->pos[5], duRGBA(0,48,64,196));
-			dd->vertex(con->pos[3],con->pos[4]+0.2f,con->pos[5], duRGBA(0,48,64,196));
-			
-			// Connection arc.
-			duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
-						(con->flags & 1) ? 0.6f : 0, 0.6f, col);
-		}
-		dd->end();
-	}
-	
-	const unsigned int vcol = duRGBA(0,0,0,196);
-	dd->begin(DU_DRAW_POINTS, 3.0f);
-	for (int i = 0; i < tile->header->vertCount; ++i)
-	{
-		const float* v = &tile->verts[i*3];
-		dd->vertex(v[0], v[1], v[2], vcol);
-	}
-	dd->end();
-
-	dd->depthMask(true);
-}
-
-void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh& mesh, unsigned char flags)
-{
-	if (!dd) return;
-	
-	for (int i = 0; i < mesh.getMaxTiles(); ++i)
-	{
-		const dtMeshTile* tile = mesh.getTile(i);
-		if (!tile->header) continue;
-		drawMeshTile(dd, mesh, 0, tile, flags);
-	}
-}
-
-void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, unsigned char flags)
-{
-	if (!dd) return;
-
-	const dtNavMeshQuery* q = (flags & DU_DRAWNAVMESH_CLOSEDLIST) ? &query : 0;
-	
-	for (int i = 0; i < mesh.getMaxTiles(); ++i)
-	{
-		const dtMeshTile* tile = mesh.getTile(i);
-		if (!tile->header) continue;
-		drawMeshTile(dd, mesh, q, tile, flags);
-	}
-}
-
-void duDebugDrawNavMeshNodes(struct duDebugDraw* dd, const dtNavMeshQuery& query)
-{
-	if (!dd) return;
-	
-	const dtNodePool* pool = query.getNodePool();
-	if (pool)
-	{
-		const float off = 0.5f;
-		dd->begin(DU_DRAW_POINTS, 4.0f);
-		for (int i = 0; i < pool->getHashSize(); ++i)
-		{
-			for (dtNodeIndex j = pool->getFirst(i); j != DT_NULL_IDX; j = pool->getNext(j))
-			{
-				const dtNode* node = pool->getNodeAtIdx(j+1);
-				if (!node) continue;
-				dd->vertex(node->pos[0],node->pos[1]+off,node->pos[2], duRGBA(255,192,0,255));
-			}
-		}
-		dd->end();
-		
-		dd->begin(DU_DRAW_LINES, 2.0f);
-		for (int i = 0; i < pool->getHashSize(); ++i)
-		{
-			for (dtNodeIndex j = pool->getFirst(i); j != DT_NULL_IDX; j = pool->getNext(j))
-			{
-				const dtNode* node = pool->getNodeAtIdx(j+1);
-				if (!node) continue;
-				if (!node->pidx) continue;
-				const dtNode* parent = pool->getNodeAtIdx(node->pidx);
-				if (!parent) continue;
-				dd->vertex(node->pos[0],node->pos[1]+off,node->pos[2], duRGBA(255,192,0,128));
-				dd->vertex(parent->pos[0],parent->pos[1]+off,parent->pos[2], duRGBA(255,192,0,128));
-			}
-		}
-		dd->end();
-	}
-}
-
-
-static void drawMeshTileBVTree(duDebugDraw* dd, const dtMeshTile* tile)
-{
-	// Draw BV nodes.
-	const float cs = 1.0f / tile->header->bvQuantFactor;
-	dd->begin(DU_DRAW_LINES, 1.0f);
-	for (int i = 0; i < tile->header->bvNodeCount; ++i)
-	{
-		const dtBVNode* n = &tile->bvTree[i];
-		if (n->i < 0) // Leaf indices are positive.
-			continue;
-		duAppendBoxWire(dd, tile->header->bmin[0] + n->bmin[0]*cs,
-						tile->header->bmin[1] + n->bmin[1]*cs,
-						tile->header->bmin[2] + n->bmin[2]*cs,
-						tile->header->bmin[0] + n->bmax[0]*cs,
-						tile->header->bmin[1] + n->bmax[1]*cs,
-						tile->header->bmin[2] + n->bmax[2]*cs,
-						duRGBA(255,255,255,128));
-	}
-	dd->end();
-}
-
-void duDebugDrawNavMeshBVTree(duDebugDraw* dd, const dtNavMesh& mesh)
-{
-	if (!dd) return;
-	
-	for (int i = 0; i < mesh.getMaxTiles(); ++i)
-	{
-		const dtMeshTile* tile = mesh.getTile(i);
-		if (!tile->header) continue;
-		drawMeshTileBVTree(dd, tile);
-	}
-}
-
-static void drawMeshTilePortal(duDebugDraw* dd, const dtMeshTile* tile)
-{
-	// Draw portals
-	const float padx = 0.04f;
-	const float pady = tile->header->walkableClimb;
-
-	dd->begin(DU_DRAW_LINES, 2.0f);
-
-	for (int side = 0; side < 8; ++side)
-	{
-		unsigned short m = DT_EXT_LINK | (unsigned short)side;
-		
-		for (int i = 0; i < tile->header->polyCount; ++i)
-		{
-			dtPoly* poly = &tile->polys[i];
-			
-			// Create new links.
-			const int nv = poly->vertCount;
-			for (int j = 0; j < nv; ++j)
-			{
-				// Skip edges which do not point to the right side.
-				if (poly->neis[j] != m)
-					continue;
-				
-				// Create new links
-				const float* va = &tile->verts[poly->verts[j]*3];
-				const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3];
-				
-				if (side == 0 || side == 4)
-				{
-					unsigned int col = side == 0 ? duRGBA(128,0,0,128) : duRGBA(128,0,128,128);
-
-					const float x = va[0] + ((side == 0) ? -padx : padx);
-					
-					dd->vertex(x,va[1]-pady,va[2], col);
-					dd->vertex(x,va[1]+pady,va[2], col);
-
-					dd->vertex(x,va[1]+pady,va[2], col);
-					dd->vertex(x,vb[1]+pady,vb[2], col);
-
-					dd->vertex(x,vb[1]+pady,vb[2], col);
-					dd->vertex(x,vb[1]-pady,vb[2], col);
-
-					dd->vertex(x,vb[1]-pady,vb[2], col);
-					dd->vertex(x,va[1]-pady,va[2], col);
-				}
-				else if (side == 2 || side == 6)
-				{
-					unsigned int col = side == 2 ? duRGBA(0,128,0,128) : duRGBA(0,128,128,128);
-
-					const float z = va[2] + ((side == 2) ? -padx : padx);
-					
-					dd->vertex(va[0],va[1]-pady,z, col);
-					dd->vertex(va[0],va[1]+pady,z, col);
-					
-					dd->vertex(va[0],va[1]+pady,z, col);
-					dd->vertex(vb[0],vb[1]+pady,z, col);
-					
-					dd->vertex(vb[0],vb[1]+pady,z, col);
-					dd->vertex(vb[0],vb[1]-pady,z, col);
-					
-					dd->vertex(vb[0],vb[1]-pady,z, col);
-					dd->vertex(va[0],va[1]-pady,z, col);
-				}
-
-			}
-		}
-	}
-	
-	dd->end();
-}
-
-void duDebugDrawNavMeshPortals(duDebugDraw* dd, const dtNavMesh& mesh)
-{
-	if (!dd) return;
-	
-	for (int i = 0; i < mesh.getMaxTiles(); ++i)
-	{
-		const dtMeshTile* tile = mesh.getTile(i);
-		if (!tile->header) continue;
-		drawMeshTilePortal(dd, tile);
-	}
-}
-
-void duDebugDrawNavMeshPolysWithFlags(struct duDebugDraw* dd, const dtNavMesh& mesh,
-									  const unsigned short polyFlags, const unsigned int col)
-{
-	if (!dd) return;
-	
-	for (int i = 0; i < mesh.getMaxTiles(); ++i)
-	{
-		const dtMeshTile* tile = mesh.getTile(i);
-		if (!tile->header) continue;
-		dtPolyRef base = mesh.getPolyRefBase(tile);
-
-		for (int j = 0; j < tile->header->polyCount; ++j)
-		{
-			const dtPoly* p = &tile->polys[j];
-			if ((p->flags & polyFlags) == 0) continue;
-			duDebugDrawNavMeshPoly(dd, mesh, base|(dtPolyRef)j, col);
-		}
-	}
-}
-
-void duDebugDrawNavMeshPoly(duDebugDraw* dd, const dtNavMesh& mesh, dtPolyRef ref, const unsigned int col)
-{
-	if (!dd) return;
-	
-	const dtMeshTile* tile = 0;
-	const dtPoly* poly = 0;
-	if (dtStatusFailed(mesh.getTileAndPolyByRef(ref, &tile, &poly)))
-		return;
-	
-	dd->depthMask(false);
-	
-	const unsigned int c = duTransCol(col, 64);
-	const unsigned int ip = (unsigned int)(poly - tile->polys);
-
-	if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
-	{
-		dtOffMeshConnection* con = &tile->offMeshCons[ip - tile->header->offMeshBase];
-
-		dd->begin(DU_DRAW_LINES, 2.0f);
-
-		// Connection arc.
-		duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
-					(con->flags & 1) ? 0.6f : 0.0f, 0.6f, c);
-		
-		dd->end();
-	}
-	else
-	{
-		const dtPolyDetail* pd = &tile->detailMeshes[ip];
-
-		dd->begin(DU_DRAW_TRIS);
-		for (int i = 0; i < pd->triCount; ++i)
-		{
-			const unsigned char* t = &tile->detailTris[(pd->triBase+i)*4];
-			for (int j = 0; j < 3; ++j)
-			{
-				if (t[j] < poly->vertCount)
-					dd->vertex(&tile->verts[poly->verts[t[j]]*3], c);
-				else
-					dd->vertex(&tile->detailVerts[(pd->vertBase+t[j]-poly->vertCount)*3], c);
-			}
-		}
-		dd->end();
-	}
-	
-	dd->depthMask(true);
-
-}
-
-static void debugDrawTileCachePortals(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
-{
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	const float* bmin = layer.header->bmin;
-
-	// Portals
-	unsigned int pcol = duRGBA(255,255,255,255);
-	
-	const int segs[4*4] = {0,0,0,1, 0,1,1,1, 1,1,1,0, 1,0,0,0};
-	
-	// Layer portals
-	dd->begin(DU_DRAW_LINES, 2.0f);
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			const int idx = x+y*w;
-			const int lh = (int)layer.heights[idx];
-			if (lh == 0xff) continue;
-			
-			for (int dir = 0; dir < 4; ++dir)
-			{
-				if (layer.cons[idx] & (1<<(dir+4)))
-				{
-					const int* seg = &segs[dir*4];
-					const float ax = bmin[0] + (x+seg[0])*cs;
-					const float ay = bmin[1] + (lh+2)*ch;
-					const float az = bmin[2] + (y+seg[1])*cs;
-					const float bx = bmin[0] + (x+seg[2])*cs;
-					const float by = bmin[1] + (lh+2)*ch;
-					const float bz = bmin[2] + (y+seg[3])*cs;
-					dd->vertex(ax, ay, az, pcol);
-					dd->vertex(bx, by, bz, pcol);
-				}
-			}
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawTileCacheLayerAreas(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
-{
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	const float* bmin = layer.header->bmin;
-	const float* bmax = layer.header->bmax;
-	const int idx = layer.header->tlayer;
-	
-	unsigned int color = duIntToCol(idx+1, 255);
-	
-	// Layer bounds
-	float lbmin[3], lbmax[3];
-	lbmin[0] = bmin[0] + layer.header->minx*cs;
-	lbmin[1] = bmin[1];
-	lbmin[2] = bmin[2] + layer.header->miny*cs;
-	lbmax[0] = bmin[0] + (layer.header->maxx+1)*cs;
-	lbmax[1] = bmax[1];
-	lbmax[2] = bmin[2] + (layer.header->maxy+1)*cs;
-	duDebugDrawBoxWire(dd, lbmin[0],lbmin[1],lbmin[2], lbmax[0],lbmax[1],lbmax[2], duTransCol(color,128), 2.0f);
-	
-	// Layer height
-	dd->begin(DU_DRAW_QUADS);
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			const int lidx = x+y*w;
-			const int lh = (int)layer.heights[lidx];
-			if (lh == 0xff) continue;
-
-			const unsigned char area = layer.areas[lidx];
-			unsigned int col;
-			if (area == 63)
-				col = duLerpCol(color, duRGBA(0,192,255,64), 32);
-			else if (area == 0)
-				col = duLerpCol(color, duRGBA(0,0,0,64), 32);
-			else
-				col = duLerpCol(color, dd->areaToCol(area), 32);
-			
-			const float fx = bmin[0] + x*cs;
-			const float fy = bmin[1] + (lh+1)*ch;
-			const float fz = bmin[2] + y*cs;
-			
-			dd->vertex(fx, fy, fz, col);
-			dd->vertex(fx, fy, fz+cs, col);
-			dd->vertex(fx+cs, fy, fz+cs, col);
-			dd->vertex(fx+cs, fy, fz, col);
-		}
-	}
-	dd->end();
-	
-	debugDrawTileCachePortals(dd, layer, cs, ch);
-}
-
-void duDebugDrawTileCacheLayerRegions(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch)
-{
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	const float* bmin = layer.header->bmin;
-	const float* bmax = layer.header->bmax;
-	const int idx = layer.header->tlayer;
-	
-	unsigned int color = duIntToCol(idx+1, 255);
-	
-	// Layer bounds
-	float lbmin[3], lbmax[3];
-	lbmin[0] = bmin[0] + layer.header->minx*cs;
-	lbmin[1] = bmin[1];
-	lbmin[2] = bmin[2] + layer.header->miny*cs;
-	lbmax[0] = bmin[0] + (layer.header->maxx+1)*cs;
-	lbmax[1] = bmax[1];
-	lbmax[2] = bmin[2] + (layer.header->maxy+1)*cs;
-	duDebugDrawBoxWire(dd, lbmin[0],lbmin[1],lbmin[2], lbmax[0],lbmax[1],lbmax[2], duTransCol(color,128), 2.0f);
-	
-	// Layer height
-	dd->begin(DU_DRAW_QUADS);
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			const int lidx = x+y*w;
-			const int lh = (int)layer.heights[lidx];
-			if (lh == 0xff) continue;
-			const unsigned char reg = layer.regs[lidx];
-			
-			unsigned int col = duLerpCol(color, duIntToCol(reg, 255), 192);
-			
-			const float fx = bmin[0] + x*cs;
-			const float fy = bmin[1] + (lh+1)*ch;
-			const float fz = bmin[2] + y*cs;
-			
-			dd->vertex(fx, fy, fz, col);
-			dd->vertex(fx, fy, fz+cs, col);
-			dd->vertex(fx+cs, fy, fz+cs, col);
-			dd->vertex(fx+cs, fy, fz, col);
-		}
-	}
-	dd->end();
-	
-	debugDrawTileCachePortals(dd, layer, cs, ch);
-}
-
-
-
-
-/*struct dtTileCacheContour
-{
-	int nverts;
-	unsigned char* verts;
-	unsigned char reg;
-	unsigned char area;
-};
-
-struct dtTileCacheContourSet
-{
-	int nconts;
-	dtTileCacheContour* conts;
-};*/
-
-void duDebugDrawTileCacheContours(duDebugDraw* dd, const struct dtTileCacheContourSet& lcset,
-								  const float* orig, const float cs, const float ch)
-{
-	if (!dd) return;
-	
-	const unsigned char a = 255;// (unsigned char)(alpha*255.0f);
-	
-	const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
-	
-	dd->begin(DU_DRAW_LINES, 2.0f);
-	
-	for (int i = 0; i < lcset.nconts; ++i)
-	{
-		const dtTileCacheContour& c = lcset.conts[i];
-		unsigned int color = 0;
-		
-		color = duIntToCol(i, a);
-		
-		for (int j = 0; j < c.nverts; ++j)
-		{
-			const int k = (j+1) % c.nverts;
-			const unsigned char* va = &c.verts[j*4];
-			const unsigned char* vb = &c.verts[k*4];
-			const float ax = orig[0] + va[0]*cs;
-			const float ay = orig[1] + (va[1]+1+(i&1))*ch;
-			const float az = orig[2] + va[2]*cs;
-			const float bx = orig[0] + vb[0]*cs;
-			const float by = orig[1] + (vb[1]+1+(i&1))*ch;
-			const float bz = orig[2] + vb[2]*cs;
-			unsigned int col = color;
-			if ((va[3] & 0xf) != 0xf)
-			{
-				// Portal segment
-				col = duRGBA(255,255,255,128);
-				int d = va[3] & 0xf;
-				
-				const float cx = (ax+bx)*0.5f;
-				const float cy = (ay+by)*0.5f;
-				const float cz = (az+bz)*0.5f;
-				
-				const float dx = cx + offs[d*2+0]*2*cs;
-				const float dy = cy;
-				const float dz = cz + offs[d*2+1]*2*cs;
-				
-				dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
-				dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
-			}
-			
-			duAppendArrow(dd, ax,ay,az, bx,by,bz, 0.0f, cs*0.5f, col);
-		}
-	}
-	dd->end();
-	
-	dd->begin(DU_DRAW_POINTS, 4.0f);	
-	
-	for (int i = 0; i < lcset.nconts; ++i)
-	{
-		const dtTileCacheContour& c = lcset.conts[i];
-		unsigned int color = 0;
-		
-		for (int j = 0; j < c.nverts; ++j)
-		{
-			const unsigned char* va = &c.verts[j*4];
-			
-			color = duDarkenCol(duIntToCol(i, a));
-			if (va[3] & 0x80)
-			{
-				// Border vertex
-				color = duRGBA(255,0,0,255);
-			}
-			
-			float fx = orig[0] + va[0]*cs;
-			float fy = orig[1] + (va[1]+1+(i&1))*ch;
-			float fz = orig[2] + va[2]*cs;
-			dd->vertex(fx,fy,fz, color);
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawTileCachePolyMesh(duDebugDraw* dd, const struct dtTileCachePolyMesh& lmesh,
-								  const float* orig, const float cs, const float ch)
-{
-	if (!dd) return;
-	
-	const int nvp = lmesh.nvp;
-	
-	const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
-	
-	dd->begin(DU_DRAW_TRIS);
-	
-	for (int i = 0; i < lmesh.npolys; ++i)
-	{
-		const unsigned short* p = &lmesh.polys[i*nvp*2];
-		const unsigned char area = lmesh.areas[i];
-		
-		unsigned int color;
-		if (area == DT_TILECACHE_WALKABLE_AREA)
-			color = duRGBA(0,192,255,64);
-		else if (area == DT_TILECACHE_NULL_AREA)
-			color = duRGBA(0,0,0,64);
-		else
-			color = dd->areaToCol(area);
-		
-		unsigned short vi[3];
-		for (int j = 2; j < nvp; ++j)
-		{
-			if (p[j] == DT_TILECACHE_NULL_IDX) break;
-			vi[0] = p[0];
-			vi[1] = p[j-1];
-			vi[2] = p[j];
-			for (int k = 0; k < 3; ++k)
-			{
-				const unsigned short* v = &lmesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x,y,z, color);
-			}
-		}
-	}
-	dd->end();
-	
-	// Draw neighbours edges
-	const unsigned int coln = duRGBA(0,48,64,32);
-	dd->begin(DU_DRAW_LINES, 1.5f);
-	for (int i = 0; i < lmesh.npolys; ++i)
-	{
-		const unsigned short* p = &lmesh.polys[i*nvp*2];
-		for (int j = 0; j < nvp; ++j)
-		{
-			if (p[j] == DT_TILECACHE_NULL_IDX) break;
-			if (p[nvp+j] & 0x8000) continue;
-			const int nj = (j+1 >= nvp || p[j+1] == DT_TILECACHE_NULL_IDX) ? 0 : j+1; 
-			int vi[2] = {p[j], p[nj]};
-			
-			for (int k = 0; k < 2; ++k)
-			{
-				const unsigned short* v = &lmesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x, y, z, coln);
-			}
-		}
-	}
-	dd->end();
-	
-	// Draw boundary edges
-	const unsigned int colb = duRGBA(0,48,64,220);
-	dd->begin(DU_DRAW_LINES, 2.5f);
-	for (int i = 0; i < lmesh.npolys; ++i)
-	{
-		const unsigned short* p = &lmesh.polys[i*nvp*2];
-		for (int j = 0; j < nvp; ++j)
-		{
-			if (p[j] == DT_TILECACHE_NULL_IDX) break;
-			if ((p[nvp+j] & 0x8000) == 0) continue;
-			const int nj = (j+1 >= nvp || p[j+1] == DT_TILECACHE_NULL_IDX) ? 0 : j+1; 
-			int vi[2] = {p[j], p[nj]};
-			
-			unsigned int col = colb;
-			if ((p[nvp+j] & 0xf) != 0xf)
-			{
-				const unsigned short* va = &lmesh.verts[vi[0]*3];
-				const unsigned short* vb = &lmesh.verts[vi[1]*3];
-				
-				const float ax = orig[0] + va[0]*cs;
-				const float ay = orig[1] + (va[1]+1+(i&1))*ch;
-				const float az = orig[2] + va[2]*cs;
-				const float bx = orig[0] + vb[0]*cs;
-				const float by = orig[1] + (vb[1]+1+(i&1))*ch;
-				const float bz = orig[2] + vb[2]*cs;
-				
-				const float cx = (ax+bx)*0.5f;
-				const float cy = (ay+by)*0.5f;
-				const float cz = (az+bz)*0.5f;
-				
-				int d = p[nvp+j] & 0xf;
-				
-				const float dx = cx + offs[d*2+0]*2*cs;
-				const float dy = cy;
-				const float dz = cz + offs[d*2+1]*2*cs;
-				
-				dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
-				dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
-				
-				col = duRGBA(255,255,255,128);
-			}
-			
-			for (int k = 0; k < 2; ++k)
-			{
-				const unsigned short* v = &lmesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x, y, z, col);
-			}
-		}
-	}
-	dd->end();
-	
-	dd->begin(DU_DRAW_POINTS, 3.0f);
-	const unsigned int colv = duRGBA(0,0,0,220);
-	for (int i = 0; i < lmesh.nverts; ++i)
-	{
-		const unsigned short* v = &lmesh.verts[i*3];
-		const float x = orig[0] + v[0]*cs;
-		const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-		const float z = orig[2] + v[2]*cs;
-		dd->vertex(x,y,z, colv);
-	}
-	dd->end();
-}
-
-
-

+ 0 - 48
panda/src/recastdetour/DetourDebugDraw.h

@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOURDEBUGDRAW_H
-#define DETOURDEBUGDRAW_H
-
-#include "DetourNavMesh.h"
-#include "DetourNavMeshQuery.h"
-#include "DetourTileCacheBuilder.h"
-
-enum DrawNavMeshFlags
-{
-	DU_DRAWNAVMESH_OFFMESHCONS = 0x01,
-	DU_DRAWNAVMESH_CLOSEDLIST = 0x02,
-	DU_DRAWNAVMESH_COLOR_TILES = 0x04,
-};
-
-void duDebugDrawNavMesh(struct duDebugDraw* dd, const dtNavMesh& mesh, unsigned char flags);
-void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, unsigned char flags);
-void duDebugDrawNavMeshNodes(struct duDebugDraw* dd, const dtNavMeshQuery& query);
-void duDebugDrawNavMeshBVTree(struct duDebugDraw* dd, const dtNavMesh& mesh);
-void duDebugDrawNavMeshPortals(struct duDebugDraw* dd, const dtNavMesh& mesh);
-void duDebugDrawNavMeshPolysWithFlags(struct duDebugDraw* dd, const dtNavMesh& mesh, const unsigned short polyFlags, const unsigned int col);
-void duDebugDrawNavMeshPoly(struct duDebugDraw* dd, const dtNavMesh& mesh, dtPolyRef ref, const unsigned int col);
-
-void duDebugDrawTileCacheLayerAreas(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch);
-void duDebugDrawTileCacheLayerRegions(struct duDebugDraw* dd, const dtTileCacheLayer& layer, const float cs, const float ch);
-void duDebugDrawTileCacheContours(duDebugDraw* dd, const struct dtTileCacheContourSet& lcset,
-								  const float* orig, const float cs, const float ch);
-void duDebugDrawTileCachePolyMesh(duDebugDraw* dd, const struct dtTileCachePolyMesh& lmesh,
-								  const float* orig, const float cs, const float ch);
-
-#endif // DETOURDEBUGDRAW_H

+ 0 - 137
panda/src/recastdetour/DetourLocalBoundary.cpp

@@ -1,137 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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.
-//
-
-#include <float.h>
-#include <string.h>
-#include "DetourLocalBoundary.h"
-#include "DetourNavMeshQuery.h"
-#include "DetourCommon.h"
-#include "DetourAssert.h"
-
-
-dtLocalBoundary::dtLocalBoundary() :
-	m_nsegs(0),
-	m_npolys(0)
-{
-	dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX);
-}
-
-dtLocalBoundary::~dtLocalBoundary()
-{
-}
-
-void dtLocalBoundary::reset()
-{
-	dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX);
-	m_npolys = 0;
-	m_nsegs = 0;
-}
-
-void dtLocalBoundary::addSegment(const float dist, const float* s)
-{
-	// Insert neighbour based on the distance.
-	Segment* seg = 0;
-	if (!m_nsegs)
-	{
-		// First, trivial accept.
-		seg = &m_segs[0];
-	}
-	else if (dist >= m_segs[m_nsegs-1].d)
-	{
-		// Further than the last segment, skip.
-		if (m_nsegs >= MAX_LOCAL_SEGS)
-			return;
-		// Last, trivial accept.
-		seg = &m_segs[m_nsegs];
-	}
-	else
-	{
-		// Insert inbetween.
-		int i;
-		for (i = 0; i < m_nsegs; ++i)
-			if (dist <= m_segs[i].d)
-				break;
-		const int tgt = i+1;
-		const int n = dtMin(m_nsegs-i, MAX_LOCAL_SEGS-tgt);
-		dtAssert(tgt+n <= MAX_LOCAL_SEGS);
-		if (n > 0)
-			memmove(&m_segs[tgt], &m_segs[i], sizeof(Segment)*n);
-		seg = &m_segs[i];
-	}
-	
-	seg->d = dist;
-	memcpy(seg->s, s, sizeof(float)*6);
-	
-	if (m_nsegs < MAX_LOCAL_SEGS)
-		m_nsegs++;
-}
-
-void dtLocalBoundary::update(dtPolyRef ref, const float* pos, const float collisionQueryRange,
-							 dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	static const int MAX_SEGS_PER_POLY = DT_VERTS_PER_POLYGON*3;
-	
-	if (!ref)
-	{
-		dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX);
-		m_nsegs = 0;
-		m_npolys = 0;
-		return;
-	}
-	
-	dtVcopy(m_center, pos);
-	
-	// First query non-overlapping polygons.
-	navquery->findLocalNeighbourhood(ref, pos, collisionQueryRange,
-									 filter, m_polys, 0, &m_npolys, MAX_LOCAL_POLYS);
-	
-	// Secondly, store all polygon edges.
-	m_nsegs = 0;
-	float segs[MAX_SEGS_PER_POLY*6];
-	int nsegs = 0;
-	for (int j = 0; j < m_npolys; ++j)
-	{
-		navquery->getPolyWallSegments(m_polys[j], filter, segs, 0, &nsegs, MAX_SEGS_PER_POLY);
-		for (int k = 0; k < nsegs; ++k)
-		{
-			const float* s = &segs[k*6];
-			// Skip too distant segments.
-			float tseg;
-			const float distSqr = dtDistancePtSegSqr2D(pos, s, s+3, tseg);
-			if (distSqr > dtSqr(collisionQueryRange))
-				continue;
-			addSegment(distSqr, s);
-		}
-	}
-}
-
-bool dtLocalBoundary::isValid(dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	if (!m_npolys)
-		return false;
-	
-	// Check that all polygons still pass query filter.
-	for (int i = 0; i < m_npolys; ++i)
-	{
-		if (!navquery->isValidPolyRef(m_polys[i], filter))
-			return false;
-	}
-	
-	return true;
-}
-

+ 0 - 66
panda/src/recastdetour/DetourLocalBoundary.h

@@ -1,66 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOURLOCALBOUNDARY_H
-#define DETOURLOCALBOUNDARY_H
-
-#include "DetourNavMeshQuery.h"
-
-
-class dtLocalBoundary
-{
-	static const int MAX_LOCAL_SEGS = 8;
-	static const int MAX_LOCAL_POLYS = 16;
-	
-	struct Segment
-	{
-		float s[6];	///< Segment start/end
-		float d;	///< Distance for pruning.
-	};
-	
-	float m_center[3];
-	Segment m_segs[MAX_LOCAL_SEGS];
-	int m_nsegs;
-	
-	dtPolyRef m_polys[MAX_LOCAL_POLYS];
-	int m_npolys;
-
-	void addSegment(const float dist, const float* s);
-	
-public:
-	dtLocalBoundary();
-	~dtLocalBoundary();
-	
-	void reset();
-	
-	void update(dtPolyRef ref, const float* pos, const float collisionQueryRange,
-				dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	bool isValid(dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	inline const float* getCenter() const { return m_center; }
-	inline int getSegmentCount() const { return m_nsegs; }
-	inline const float* getSegment(int i) const { return m_segs[i].s; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtLocalBoundary(const dtLocalBoundary&);
-	dtLocalBoundary& operator=(const dtLocalBoundary&);
-};
-
-#endif // DETOURLOCALBOUNDARY_H

+ 0 - 619
panda/src/recastdetour/DetourObstacleAvoidance.cpp

@@ -1,619 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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.
-//
-
-#include "DetourObstacleAvoidance.h"
-#include "DetourCommon.h"
-#include "DetourMath.h"
-#include "DetourAlloc.h"
-#include "DetourAssert.h"
-#include <string.h>
-#include <float.h>
-#include <new>
-
-static const float DT_PI = 3.14159265f;
-
-static int sweepCircleCircle(const float* c0, const float r0, const float* v,
-							 const float* c1, const float r1,
-							 float& tmin, float& tmax)
-{
-	static const float EPS = 0.0001f;
-	float s[3];
-	dtVsub(s,c1,c0);
-	float r = r0+r1;
-	float c = dtVdot2D(s,s) - r*r;
-	float a = dtVdot2D(v,v);
-	if (a < EPS) return 0;	// not moving
-	
-	// Overlap, calc time to exit.
-	float b = dtVdot2D(v,s);
-	float d = b*b - a*c;
-	if (d < 0.0f) return 0; // no intersection.
-	a = 1.0f / a;
-	const float rd = dtMathSqrtf(d);
-	tmin = (b - rd) * a;
-	tmax = (b + rd) * a;
-	return 1;
-}
-
-static int isectRaySeg(const float* ap, const float* u,
-					   const float* bp, const float* bq,
-					   float& t)
-{
-	float v[3], w[3];
-	dtVsub(v,bq,bp);
-	dtVsub(w,ap,bp);
-	float d = dtVperp2D(u,v);
-	if (dtMathFabsf(d) < 1e-6f) return 0;
-	d = 1.0f/d;
-	t = dtVperp2D(v,w) * d;
-	if (t < 0 || t > 1) return 0;
-	float s = dtVperp2D(u,w) * d;
-	if (s < 0 || s > 1) return 0;
-	return 1;
-}
-
-
-
-dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData()
-{
-	void* mem = dtAlloc(sizeof(dtObstacleAvoidanceDebugData), DT_ALLOC_PERM);
-	if (!mem) return 0;
-	return new(mem) dtObstacleAvoidanceDebugData;
-}
-
-void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr)
-{
-	if (!ptr) return;
-	ptr->~dtObstacleAvoidanceDebugData();
-	dtFree(ptr);
-}
-
-
-dtObstacleAvoidanceDebugData::dtObstacleAvoidanceDebugData() :
-	m_nsamples(0),
-	m_maxSamples(0),
-	m_vel(0),
-	m_ssize(0),
-	m_pen(0),
-	m_vpen(0),
-	m_vcpen(0),
-	m_spen(0),
-	m_tpen(0)
-{
-}
-
-dtObstacleAvoidanceDebugData::~dtObstacleAvoidanceDebugData()
-{
-	dtFree(m_vel);
-	dtFree(m_ssize);
-	dtFree(m_pen);
-	dtFree(m_vpen);
-	dtFree(m_vcpen);
-	dtFree(m_spen);
-	dtFree(m_tpen);
-}
-		
-bool dtObstacleAvoidanceDebugData::init(const int maxSamples)
-{
-	dtAssert(maxSamples);
-	m_maxSamples = maxSamples;
-
-	m_vel = (float*)dtAlloc(sizeof(float)*3*m_maxSamples, DT_ALLOC_PERM);
-	if (!m_vel)
-		return false;
-	m_pen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
-	if (!m_pen)
-		return false;
-	m_ssize = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
-	if (!m_ssize)
-		return false;
-	m_vpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
-	if (!m_vpen)
-		return false;
-	m_vcpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
-	if (!m_vcpen)
-		return false;
-	m_spen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
-	if (!m_spen)
-		return false;
-	m_tpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
-	if (!m_tpen)
-		return false;
-	
-	return true;
-}
-
-void dtObstacleAvoidanceDebugData::reset()
-{
-	m_nsamples = 0;
-}
-
-void dtObstacleAvoidanceDebugData::addSample(const float* vel, const float ssize, const float pen,
-											 const float vpen, const float vcpen, const float spen, const float tpen)
-{
-	if (m_nsamples >= m_maxSamples)
-		return;
-	dtAssert(m_vel);
-	dtAssert(m_ssize);
-	dtAssert(m_pen);
-	dtAssert(m_vpen);
-	dtAssert(m_vcpen);
-	dtAssert(m_spen);
-	dtAssert(m_tpen);
-	dtVcopy(&m_vel[m_nsamples*3], vel);
-	m_ssize[m_nsamples] = ssize;
-	m_pen[m_nsamples] = pen;
-	m_vpen[m_nsamples] = vpen;
-	m_vcpen[m_nsamples] = vcpen;
-	m_spen[m_nsamples] = spen;
-	m_tpen[m_nsamples] = tpen;
-	m_nsamples++;
-}
-
-static void normalizeArray(float* arr, const int n)
-{
-	// Normalize penaly range.
-	float minPen = FLT_MAX;
-	float maxPen = -FLT_MAX;
-	for (int i = 0; i < n; ++i)
-	{
-		minPen = dtMin(minPen, arr[i]);
-		maxPen = dtMax(maxPen, arr[i]);
-	}
-	const float penRange = maxPen-minPen;
-	const float s = penRange > 0.001f ? (1.0f / penRange) : 1;
-	for (int i = 0; i < n; ++i)
-		arr[i] = dtClamp((arr[i]-minPen)*s, 0.0f, 1.0f);
-}
-
-void dtObstacleAvoidanceDebugData::normalizeSamples()
-{
-	normalizeArray(m_pen, m_nsamples);
-	normalizeArray(m_vpen, m_nsamples);
-	normalizeArray(m_vcpen, m_nsamples);
-	normalizeArray(m_spen, m_nsamples);
-	normalizeArray(m_tpen, m_nsamples);
-}
-
-
-dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery()
-{
-	void* mem = dtAlloc(sizeof(dtObstacleAvoidanceQuery), DT_ALLOC_PERM);
-	if (!mem) return 0;
-	return new(mem) dtObstacleAvoidanceQuery;
-}
-
-void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr)
-{
-	if (!ptr) return;
-	ptr->~dtObstacleAvoidanceQuery();
-	dtFree(ptr);
-}
-
-
-dtObstacleAvoidanceQuery::dtObstacleAvoidanceQuery() :
-	m_invHorizTime(0),
-	m_vmax(0),
-	m_invVmax(0),
-	m_maxCircles(0),
-	m_circles(0),
-	m_ncircles(0),
-	m_maxSegments(0),
-	m_segments(0),
-	m_nsegments(0)
-{
-}
-
-dtObstacleAvoidanceQuery::~dtObstacleAvoidanceQuery()
-{
-	dtFree(m_circles);
-	dtFree(m_segments);
-}
-
-bool dtObstacleAvoidanceQuery::init(const int maxCircles, const int maxSegments)
-{
-	m_maxCircles = maxCircles;
-	m_ncircles = 0;
-	m_circles = (dtObstacleCircle*)dtAlloc(sizeof(dtObstacleCircle)*m_maxCircles, DT_ALLOC_PERM);
-	if (!m_circles)
-		return false;
-	memset(m_circles, 0, sizeof(dtObstacleCircle)*m_maxCircles);
-
-	m_maxSegments = maxSegments;
-	m_nsegments = 0;
-	m_segments = (dtObstacleSegment*)dtAlloc(sizeof(dtObstacleSegment)*m_maxSegments, DT_ALLOC_PERM);
-	if (!m_segments)
-		return false;
-	memset(m_segments, 0, sizeof(dtObstacleSegment)*m_maxSegments);
-	
-	return true;
-}
-
-void dtObstacleAvoidanceQuery::reset()
-{
-	m_ncircles = 0;
-	m_nsegments = 0;
-}
-
-void dtObstacleAvoidanceQuery::addCircle(const float* pos, const float rad,
-										 const float* vel, const float* dvel)
-{
-	if (m_ncircles >= m_maxCircles)
-		return;
-		
-	dtObstacleCircle* cir = &m_circles[m_ncircles++];
-	dtVcopy(cir->p, pos);
-	cir->rad = rad;
-	dtVcopy(cir->vel, vel);
-	dtVcopy(cir->dvel, dvel);
-}
-
-void dtObstacleAvoidanceQuery::addSegment(const float* p, const float* q)
-{
-	if (m_nsegments >= m_maxSegments)
-		return;
-	
-	dtObstacleSegment* seg = &m_segments[m_nsegments++];
-	dtVcopy(seg->p, p);
-	dtVcopy(seg->q, q);
-}
-
-void dtObstacleAvoidanceQuery::prepare(const float* pos, const float* dvel)
-{
-	// Prepare obstacles
-	for (int i = 0; i < m_ncircles; ++i)
-	{
-		dtObstacleCircle* cir = &m_circles[i];
-		
-		// Side
-		const float* pa = pos;
-		const float* pb = cir->p;
-		
-		const float orig[3] = {0,0,0};
-		float dv[3];
-		dtVsub(cir->dp,pb,pa);
-		dtVnormalize(cir->dp);
-		dtVsub(dv, cir->dvel, dvel);
-		
-		const float a = dtTriArea2D(orig, cir->dp,dv);
-		if (a < 0.01f)
-		{
-			cir->np[0] = -cir->dp[2];
-			cir->np[2] = cir->dp[0];
-		}
-		else
-		{
-			cir->np[0] = cir->dp[2];
-			cir->np[2] = -cir->dp[0];
-		}
-	}	
-
-	for (int i = 0; i < m_nsegments; ++i)
-	{
-		dtObstacleSegment* seg = &m_segments[i];
-		
-		// Precalc if the agent is really close to the segment.
-		const float r = 0.01f;
-		float t;
-		seg->touch = dtDistancePtSegSqr2D(pos, seg->p, seg->q, t) < dtSqr(r);
-	}	
-}
-
-
-/* Calculate the collision penalty for a given velocity vector
- * 
- * @param vcand sampled velocity
- * @param dvel desired velocity
- * @param minPenalty threshold penalty for early out
- */
-float dtObstacleAvoidanceQuery::processSample(const float* vcand, const float cs,
-											  const float* pos, const float rad,
-											  const float* vel, const float* dvel,
-											  const float minPenalty,
-											  dtObstacleAvoidanceDebugData* debug)
-{
-	// penalty for straying away from the desired and current velocities
-	const float vpen = m_params.weightDesVel * (dtVdist2D(vcand, dvel) * m_invVmax);
-	const float vcpen = m_params.weightCurVel * (dtVdist2D(vcand, vel) * m_invVmax);
-
-	// find the threshold hit time to bail out based on the early out penalty
-	// (see how the penalty is calculated below to understnad)
-	float minPen = minPenalty - vpen - vcpen;
-	float tThresold = (m_params.weightToi / minPen - 0.1f) * m_params.horizTime;
-	if (tThresold - m_params.horizTime > -FLT_EPSILON)
-		return minPenalty; // already too much
-
-	// Find min time of impact and exit amongst all obstacles.
-	float tmin = m_params.horizTime;
-	float side = 0;
-	int nside = 0;
-	
-	for (int i = 0; i < m_ncircles; ++i)
-	{
-		const dtObstacleCircle* cir = &m_circles[i];
-			
-		// RVO
-		float vab[3];
-		dtVscale(vab, vcand, 2);
-		dtVsub(vab, vab, vel);
-		dtVsub(vab, vab, cir->vel);
-		
-		// Side
-		side += dtClamp(dtMin(dtVdot2D(cir->dp,vab)*0.5f+0.5f, dtVdot2D(cir->np,vab)*2), 0.0f, 1.0f);
-		nside++;
-		
-		float htmin = 0, htmax = 0;
-		if (!sweepCircleCircle(pos,rad, vab, cir->p,cir->rad, htmin, htmax))
-			continue;
-		
-		// Handle overlapping obstacles.
-		if (htmin < 0.0f && htmax > 0.0f)
-		{
-			// Avoid more when overlapped.
-			htmin = -htmin * 0.5f;
-		}
-		
-		if (htmin >= 0.0f)
-		{
-			// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
-			if (htmin < tmin)
-			{
-				tmin = htmin;
-				if (tmin < tThresold)
-					return minPenalty;
-			}
-		}
-	}
-
-	for (int i = 0; i < m_nsegments; ++i)
-	{
-		const dtObstacleSegment* seg = &m_segments[i];
-		float htmin = 0;
-		
-		if (seg->touch)
-		{
-			// Special case when the agent is very close to the segment.
-			float sdir[3], snorm[3];
-			dtVsub(sdir, seg->q, seg->p);
-			snorm[0] = -sdir[2];
-			snorm[2] = sdir[0];
-			// If the velocity is pointing towards the segment, no collision.
-			if (dtVdot2D(snorm, vcand) < 0.0f)
-				continue;
-			// Else immediate collision.
-			htmin = 0.0f;
-		}
-		else
-		{
-			if (!isectRaySeg(pos, vcand, seg->p, seg->q, htmin))
-				continue;
-		}
-		
-		// Avoid less when facing walls.
-		htmin *= 2.0f;
-		
-		// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
-		if (htmin < tmin)
-		{
-			tmin = htmin;
-			if (tmin < tThresold)
-				return minPenalty;
-		}
-	}
-	
-	// Normalize side bias, to prevent it dominating too much.
-	if (nside)
-		side /= nside;
-	
-	const float spen = m_params.weightSide * side;
-	const float tpen = m_params.weightToi * (1.0f/(0.1f+tmin*m_invHorizTime));
-	
-	const float penalty = vpen + vcpen + spen + tpen;
-	
-	// Store different penalties for debug viewing
-	if (debug)
-		debug->addSample(vcand, cs, penalty, vpen, vcpen, spen, tpen);
-	
-	return penalty;
-}
-
-int dtObstacleAvoidanceQuery::sampleVelocityGrid(const float* pos, const float rad, const float vmax,
-												 const float* vel, const float* dvel, float* nvel,
-												 const dtObstacleAvoidanceParams* params,
-												 dtObstacleAvoidanceDebugData* debug)
-{
-	prepare(pos, dvel);
-	
-	memcpy(&m_params, params, sizeof(dtObstacleAvoidanceParams));
-	m_invHorizTime = 1.0f / m_params.horizTime;
-	m_vmax = vmax;
-	m_invVmax = vmax > 0 ? 1.0f / vmax : FLT_MAX;
-	
-	dtVset(nvel, 0,0,0);
-	
-	if (debug)
-		debug->reset();
-
-	const float cvx = dvel[0] * m_params.velBias;
-	const float cvz = dvel[2] * m_params.velBias;
-	const float cs = vmax * 2 * (1 - m_params.velBias) / (float)(m_params.gridSize-1);
-	const float half = (m_params.gridSize-1)*cs*0.5f;
-		
-	float minPenalty = FLT_MAX;
-	int ns = 0;
-		
-	for (int y = 0; y < m_params.gridSize; ++y)
-	{
-		for (int x = 0; x < m_params.gridSize; ++x)
-		{
-			float vcand[3];
-			vcand[0] = cvx + x*cs - half;
-			vcand[1] = 0;
-			vcand[2] = cvz + y*cs - half;
-			
-			if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+cs/2)) continue;
-			
-			const float penalty = processSample(vcand, cs, pos,rad,vel,dvel, minPenalty, debug);
-			ns++;
-			if (penalty < minPenalty)
-			{
-				minPenalty = penalty;
-				dtVcopy(nvel, vcand);
-			}
-		}
-	}
-	
-	return ns;
-}
-
-
-// vector normalization that ignores the y-component.
-inline void dtNormalize2D(float* v)
-{
-	float d = dtMathSqrtf(v[0] * v[0] + v[2] * v[2]);
-	if (d==0)
-		return;
-	d = 1.0f / d;
-	v[0] *= d;
-	v[2] *= d;
-}
-
-// vector normalization that ignores the y-component.
-inline void dtRorate2D(float* dest, const float* v, float ang)
-{
-	float c = cosf(ang);
-	float s = sinf(ang);
-	dest[0] = v[0]*c - v[2]*s;
-	dest[2] = v[0]*s + v[2]*c;
-	dest[1] = v[1];
-}
-
-
-int dtObstacleAvoidanceQuery::sampleVelocityAdaptive(const float* pos, const float rad, const float vmax,
-													 const float* vel, const float* dvel, float* nvel,
-													 const dtObstacleAvoidanceParams* params,
-													 dtObstacleAvoidanceDebugData* debug)
-{
-	prepare(pos, dvel);
-	
-	memcpy(&m_params, params, sizeof(dtObstacleAvoidanceParams));
-	m_invHorizTime = 1.0f / m_params.horizTime;
-	m_vmax = vmax;
-	m_invVmax = vmax > 0 ? 1.0f / vmax : FLT_MAX;
-	
-	dtVset(nvel, 0,0,0);
-	
-	if (debug)
-		debug->reset();
-
-	// Build sampling pattern aligned to desired velocity.
-	float pat[(DT_MAX_PATTERN_DIVS*DT_MAX_PATTERN_RINGS+1)*2];
-	int npat = 0;
-
-	const int ndivs = (int)m_params.adaptiveDivs;
-	const int nrings= (int)m_params.adaptiveRings;
-	const int depth = (int)m_params.adaptiveDepth;
-	
-	const int nd = dtClamp(ndivs, 1, DT_MAX_PATTERN_DIVS);
-	const int nr = dtClamp(nrings, 1, DT_MAX_PATTERN_RINGS);
-	const float da = (1.0f/nd) * DT_PI*2;
-	const float ca = cosf(da);
-	const float sa = sinf(da);
-
-	// desired direction
-	float ddir[6];
-	dtVcopy(ddir, dvel);
-	dtNormalize2D(ddir);
-	dtRorate2D (ddir+3, ddir, da*0.5f); // rotated by da/2
-
-	// Always add sample at zero
-	pat[npat*2+0] = 0;
-	pat[npat*2+1] = 0;
-	npat++;
-	
-	for (int j = 0; j < nr; ++j)
-	{
-		const float r = (float)(nr-j)/(float)nr;
-		pat[npat*2+0] = ddir[(j%2)*3] * r;
-		pat[npat*2+1] = ddir[(j%2)*3+2] * r;
-		float* last1 = pat + npat*2;
-		float* last2 = last1;
-		npat++;
-
-		for (int i = 1; i < nd-1; i+=2)
-		{
-			// get next point on the "right" (rotate CW)
-			pat[npat*2+0] = last1[0]*ca + last1[1]*sa;
-			pat[npat*2+1] = -last1[0]*sa + last1[1]*ca;
-			// get next point on the "left" (rotate CCW)
-			pat[npat*2+2] = last2[0]*ca - last2[1]*sa;
-			pat[npat*2+3] = last2[0]*sa + last2[1]*ca;
-
-			last1 = pat + npat*2;
-			last2 = last1 + 2;
-			npat += 2;
-		}
-
-		if ((nd&1) == 0)
-		{
-			pat[npat*2+2] = last2[0]*ca - last2[1]*sa;
-			pat[npat*2+3] = last2[0]*sa + last2[1]*ca;
-			npat++;
-		}
-	}
-
-
-	// Start sampling.
-	float cr = vmax * (1.0f - m_params.velBias);
-	float res[3];
-	dtVset(res, dvel[0] * m_params.velBias, 0, dvel[2] * m_params.velBias);
-	int ns = 0;
-
-	for (int k = 0; k < depth; ++k)
-	{
-		float minPenalty = FLT_MAX;
-		float bvel[3];
-		dtVset(bvel, 0,0,0);
-		
-		for (int i = 0; i < npat; ++i)
-		{
-			float vcand[3];
-			vcand[0] = res[0] + pat[i*2+0]*cr;
-			vcand[1] = 0;
-			vcand[2] = res[2] + pat[i*2+1]*cr;
-			
-			if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+0.001f)) continue;
-			
-			const float penalty = processSample(vcand,cr/10, pos,rad,vel,dvel, minPenalty, debug);
-			ns++;
-			if (penalty < minPenalty)
-			{
-				minPenalty = penalty;
-				dtVcopy(bvel, vcand);
-			}
-		}
-
-		dtVcopy(res, bvel);
-
-		cr *= 0.5f;
-	}	
-	
-	dtVcopy(nvel, res);
-	
-	return ns;
-}

+ 0 - 159
panda/src/recastdetour/DetourObstacleAvoidance.h

@@ -1,159 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOUROBSTACLEAVOIDANCE_H
-#define DETOUROBSTACLEAVOIDANCE_H
-
-struct dtObstacleCircle
-{
-	float p[3];				///< Position of the obstacle
-	float vel[3];			///< Velocity of the obstacle
-	float dvel[3];			///< Velocity of the obstacle
-	float rad;				///< Radius of the obstacle
-	float dp[3], np[3];		///< Use for side selection during sampling.
-};
-
-struct dtObstacleSegment
-{
-	float p[3], q[3];		///< End points of the obstacle segment
-	bool touch;
-};
-
-
-class dtObstacleAvoidanceDebugData
-{
-public:
-	dtObstacleAvoidanceDebugData();
-	~dtObstacleAvoidanceDebugData();
-	
-	bool init(const int maxSamples);
-	void reset();
-	void addSample(const float* vel, const float ssize, const float pen,
-				   const float vpen, const float vcpen, const float spen, const float tpen);
-	
-	void normalizeSamples();
-	
-	inline int getSampleCount() const { return m_nsamples; }
-	inline const float* getSampleVelocity(const int i) const { return &m_vel[i*3]; }
-	inline float getSampleSize(const int i) const { return m_ssize[i]; }
-	inline float getSamplePenalty(const int i) const { return m_pen[i]; }
-	inline float getSampleDesiredVelocityPenalty(const int i) const { return m_vpen[i]; }
-	inline float getSampleCurrentVelocityPenalty(const int i) const { return m_vcpen[i]; }
-	inline float getSamplePreferredSidePenalty(const int i) const { return m_spen[i]; }
-	inline float getSampleCollisionTimePenalty(const int i) const { return m_tpen[i]; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtObstacleAvoidanceDebugData(const dtObstacleAvoidanceDebugData&);
-	dtObstacleAvoidanceDebugData& operator=(const dtObstacleAvoidanceDebugData&);
-
-	int m_nsamples;
-	int m_maxSamples;
-	float* m_vel;
-	float* m_ssize;
-	float* m_pen;
-	float* m_vpen;
-	float* m_vcpen;
-	float* m_spen;
-	float* m_tpen;
-};
-
-dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData();
-void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr);
-
-
-static const int DT_MAX_PATTERN_DIVS = 32;	///< Max numver of adaptive divs.
-static const int DT_MAX_PATTERN_RINGS = 4;	///< Max number of adaptive rings.
-
-struct dtObstacleAvoidanceParams
-{
-	float velBias;
-	float weightDesVel;
-	float weightCurVel;
-	float weightSide;
-	float weightToi;
-	float horizTime;
-	unsigned char gridSize;	///< grid
-	unsigned char adaptiveDivs;	///< adaptive
-	unsigned char adaptiveRings;	///< adaptive
-	unsigned char adaptiveDepth;	///< adaptive
-};
-
-class dtObstacleAvoidanceQuery
-{
-public:
-	dtObstacleAvoidanceQuery();
-	~dtObstacleAvoidanceQuery();
-	
-	bool init(const int maxCircles, const int maxSegments);
-	
-	void reset();
-
-	void addCircle(const float* pos, const float rad,
-				   const float* vel, const float* dvel);
-				   
-	void addSegment(const float* p, const float* q);
-
-	int sampleVelocityGrid(const float* pos, const float rad, const float vmax,
-						   const float* vel, const float* dvel, float* nvel,
-						   const dtObstacleAvoidanceParams* params,
-						   dtObstacleAvoidanceDebugData* debug = 0);
-
-	int sampleVelocityAdaptive(const float* pos, const float rad, const float vmax,
-							   const float* vel, const float* dvel, float* nvel,
-							   const dtObstacleAvoidanceParams* params, 
-							   dtObstacleAvoidanceDebugData* debug = 0);
-	
-	inline int getObstacleCircleCount() const { return m_ncircles; }
-	const dtObstacleCircle* getObstacleCircle(const int i) { return &m_circles[i]; }
-
-	inline int getObstacleSegmentCount() const { return m_nsegments; }
-	const dtObstacleSegment* getObstacleSegment(const int i) { return &m_segments[i]; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtObstacleAvoidanceQuery(const dtObstacleAvoidanceQuery&);
-	dtObstacleAvoidanceQuery& operator=(const dtObstacleAvoidanceQuery&);
-
-	void prepare(const float* pos, const float* dvel);
-
-	float processSample(const float* vcand, const float cs,
-						const float* pos, const float rad,
-						const float* vel, const float* dvel,
-						const float minPenalty,
-						dtObstacleAvoidanceDebugData* debug);
-
-	dtObstacleAvoidanceParams m_params;
-	float m_invHorizTime;
-	float m_vmax;
-	float m_invVmax;
-
-	int m_maxCircles;
-	dtObstacleCircle* m_circles;
-	int m_ncircles;
-
-	int m_maxSegments;
-	dtObstacleSegment* m_segments;
-	int m_nsegments;
-};
-
-dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery();
-void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr);
-
-
-#endif // DETOUROBSTACLEAVOIDANCE_H

+ 0 - 597
panda/src/recastdetour/DetourPathCorridor.cpp

@@ -1,597 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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.
-//
-
-#include <string.h>
-#include "DetourPathCorridor.h"
-#include "DetourNavMeshQuery.h"
-#include "DetourCommon.h"
-#include "DetourAssert.h"
-#include "DetourAlloc.h"
-
-
-int dtMergeCorridorStartMoved(dtPolyRef* path, const int npath, const int maxPath,
-							  const dtPolyRef* visited, const int nvisited)
-{
-	int furthestPath = -1;
-	int furthestVisited = -1;
-	
-	// Find furthest common polygon.
-	for (int i = npath-1; i >= 0; --i)
-	{
-		bool found = false;
-		for (int j = nvisited-1; j >= 0; --j)
-		{
-			if (path[i] == visited[j])
-			{
-				furthestPath = i;
-				furthestVisited = j;
-				found = true;
-			}
-		}
-		if (found)
-			break;
-	}
-	
-	// If no intersection found just return current path. 
-	if (furthestPath == -1 || furthestVisited == -1)
-		return npath;
-	
-	// Concatenate paths.	
-	
-	// Adjust beginning of the buffer to include the visited.
-	const int req = nvisited - furthestVisited;
-	const int orig = dtMin(furthestPath+1, npath);
-	int size = dtMax(0, npath-orig);
-	if (req+size > maxPath)
-		size = maxPath-req;
-	if (size)
-		memmove(path+req, path+orig, size*sizeof(dtPolyRef));
-	
-	// Store visited
-	for (int i = 0; i < req; ++i)
-		path[i] = visited[(nvisited-1)-i];				
-	
-	return req+size;
-}
-
-int dtMergeCorridorEndMoved(dtPolyRef* path, const int npath, const int maxPath,
-							const dtPolyRef* visited, const int nvisited)
-{
-	int furthestPath = -1;
-	int furthestVisited = -1;
-	
-	// Find furthest common polygon.
-	for (int i = 0; i < npath; ++i)
-	{
-		bool found = false;
-		for (int j = nvisited-1; j >= 0; --j)
-		{
-			if (path[i] == visited[j])
-			{
-				furthestPath = i;
-				furthestVisited = j;
-				found = true;
-			}
-		}
-		if (found)
-			break;
-	}
-	
-	// If no intersection found just return current path. 
-	if (furthestPath == -1 || furthestVisited == -1)
-		return npath;
-	
-	// Concatenate paths.
-	const int ppos = furthestPath+1;
-	const int vpos = furthestVisited+1;
-	const int count = dtMin(nvisited-vpos, maxPath-ppos);
-	dtAssert(ppos+count <= maxPath);
-	if (count)
-		memcpy(path+ppos, visited+vpos, sizeof(dtPolyRef)*count);
-	
-	return ppos+count;
-}
-
-int dtMergeCorridorStartShortcut(dtPolyRef* path, const int npath, const int maxPath,
-								 const dtPolyRef* visited, const int nvisited)
-{
-	int furthestPath = -1;
-	int furthestVisited = -1;
-	
-	// Find furthest common polygon.
-	for (int i = npath-1; i >= 0; --i)
-	{
-		bool found = false;
-		for (int j = nvisited-1; j >= 0; --j)
-		{
-			if (path[i] == visited[j])
-			{
-				furthestPath = i;
-				furthestVisited = j;
-				found = true;
-			}
-		}
-		if (found)
-			break;
-	}
-	
-	// If no intersection found just return current path. 
-	if (furthestPath == -1 || furthestVisited == -1)
-		return npath;
-	
-	// Concatenate paths.	
-	
-	// Adjust beginning of the buffer to include the visited.
-	const int req = furthestVisited;
-	if (req <= 0)
-		return npath;
-	
-	const int orig = furthestPath;
-	int size = dtMax(0, npath-orig);
-	if (req+size > maxPath)
-		size = maxPath-req;
-	if (size)
-		memmove(path+req, path+orig, size*sizeof(dtPolyRef));
-	
-	// Store visited
-	for (int i = 0; i < req; ++i)
-		path[i] = visited[i];
-	
-	return req+size;
-}
-
-/**
-@class dtPathCorridor
-@par
-
-The corridor is loaded with a path, usually obtained from a #dtNavMeshQuery::findPath() query. The corridor
-is then used to plan local movement, with the corridor automatically updating as needed to deal with inaccurate 
-agent locomotion.
-
-Example of a common use case:
-
--# Construct the corridor object and call #init() to allocate its path buffer.
--# Obtain a path from a #dtNavMeshQuery object.
--# Use #reset() to set the agent's current position. (At the beginning of the path.)
--# Use #setCorridor() to load the path and target.
--# Use #findCorners() to plan movement. (This handles dynamic path straightening.)
--# Use #movePosition() to feed agent movement back into the corridor. (The corridor will automatically adjust as needed.)
--# If the target is moving, use #moveTargetPosition() to update the end of the corridor. 
-   (The corridor will automatically adjust as needed.)
--# Repeat the previous 3 steps to continue to move the agent.
-
-The corridor position and target are always constrained to the navigation mesh.
-
-One of the difficulties in maintaining a path is that floating point errors, locomotion inaccuracies, and/or local 
-steering can result in the agent crossing the boundary of the path corridor, temporarily invalidating the path. 
-This class uses local mesh queries to detect and update the corridor as needed to handle these types of issues. 
-
-The fact that local mesh queries are used to move the position and target locations results in two beahviors that 
-need to be considered:
-
-Every time a move function is used there is a chance that the path will become non-optimial. Basically, the further 
-the target is moved from its original location, and the further the position is moved outside the original corridor, 
-the more likely the path will become non-optimal. This issue can be addressed by periodically running the 
-#optimizePathTopology() and #optimizePathVisibility() methods.
-
-All local mesh queries have distance limitations. (Review the #dtNavMeshQuery methods for details.) So the most accurate 
-use case is to move the position and target in small increments. If a large increment is used, then the corridor 
-may not be able to accurately find the new location.  Because of this limiation, if a position is moved in a large
-increment, then compare the desired and resulting polygon references. If the two do not match, then path replanning 
-may be needed.  E.g. If you move the target, check #getLastPoly() to see if it is the expected polygon.
-
-*/
-
-dtPathCorridor::dtPathCorridor() :
-	m_path(0),
-	m_npath(0),
-	m_maxPath(0)
-{
-}
-
-dtPathCorridor::~dtPathCorridor()
-{
-	dtFree(m_path);
-}
-
-/// @par
-///
-/// @warning Cannot be called more than once.
-bool dtPathCorridor::init(const int maxPath)
-{
-	dtAssert(!m_path);
-	m_path = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*maxPath, DT_ALLOC_PERM);
-	if (!m_path)
-		return false;
-	m_npath = 0;
-	m_maxPath = maxPath;
-	return true;
-}
-
-/// @par
-///
-/// Essentially, the corridor is set of one polygon in size with the target
-/// equal to the position.
-void dtPathCorridor::reset(dtPolyRef ref, const float* pos)
-{
-	dtAssert(m_path);
-	dtVcopy(m_pos, pos);
-	dtVcopy(m_target, pos);
-	m_path[0] = ref;
-	m_npath = 1;
-}
-
-/**
-@par
-
-This is the function used to plan local movement within the corridor. One or more corners can be 
-detected in order to plan movement. It performs essentially the same function as #dtNavMeshQuery::findStraightPath.
-
-Due to internal optimizations, the maximum number of corners returned will be (@p maxCorners - 1) 
-For example: If the buffers are sized to hold 10 corners, the function will never return more than 9 corners. 
-So if 10 corners are needed, the buffers should be sized for 11 corners.
-
-If the target is within range, it will be the last corner and have a polygon reference id of zero.
-*/
-int dtPathCorridor::findCorners(float* cornerVerts, unsigned char* cornerFlags,
-							  dtPolyRef* cornerPolys, const int maxCorners,
-							  dtNavMeshQuery* navquery, const dtQueryFilter* /*filter*/)
-{
-	dtAssert(m_path);
-	dtAssert(m_npath);
-	
-	static const float MIN_TARGET_DIST = 0.01f;
-	
-	int ncorners = 0;
-	navquery->findStraightPath(m_pos, m_target, m_path, m_npath,
-							   cornerVerts, cornerFlags, cornerPolys, &ncorners, maxCorners);
-	
-	// Prune points in the beginning of the path which are too close.
-	while (ncorners)
-	{
-		if ((cornerFlags[0] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
-			dtVdist2DSqr(&cornerVerts[0], m_pos) > dtSqr(MIN_TARGET_DIST))
-			break;
-		ncorners--;
-		if (ncorners)
-		{
-			memmove(cornerFlags, cornerFlags+1, sizeof(unsigned char)*ncorners);
-			memmove(cornerPolys, cornerPolys+1, sizeof(dtPolyRef)*ncorners);
-			memmove(cornerVerts, cornerVerts+3, sizeof(float)*3*ncorners);
-		}
-	}
-	
-	// Prune points after an off-mesh connection.
-	for (int i = 0; i < ncorners; ++i)
-	{
-		if (cornerFlags[i] & DT_STRAIGHTPATH_OFFMESH_CONNECTION)
-		{
-			ncorners = i+1;
-			break;
-		}
-	}
-	
-	return ncorners;
-}
-
-/** 
-@par
-
-Inaccurate locomotion or dynamic obstacle avoidance can force the argent position significantly outside the 
-original corridor. Over time this can result in the formation of a non-optimal corridor. Non-optimal paths can 
-also form near the corners of tiles.
-
-This function uses an efficient local visibility search to try to optimize the corridor 
-between the current position and @p next.
-
-The corridor will change only if @p next is visible from the current position and moving directly toward the point 
-is better than following the existing path.
-
-The more inaccurate the agent movement, the more beneficial this function becomes. Simply adjust the frequency 
-of the call to match the needs to the agent.
-
-This function is not suitable for long distance searches.
-*/
-void dtPathCorridor::optimizePathVisibility(const float* next, const float pathOptimizationRange,
-										  dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	dtAssert(m_path);
-	
-	// Clamp the ray to max distance.
-	float goal[3];
-	dtVcopy(goal, next);
-	float dist = dtVdist2D(m_pos, goal);
-	
-	// If too close to the goal, do not try to optimize.
-	if (dist < 0.01f)
-		return;
-	
-	// Overshoot a little. This helps to optimize open fields in tiled meshes.
-	dist = dtMin(dist+0.01f, pathOptimizationRange);
-	
-	// Adjust ray length.
-	float delta[3];
-	dtVsub(delta, goal, m_pos);
-	dtVmad(goal, m_pos, delta, pathOptimizationRange/dist);
-	
-	static const int MAX_RES = 32;
-	dtPolyRef res[MAX_RES];
-	float t, norm[3];
-	int nres = 0;
-	navquery->raycast(m_path[0], m_pos, goal, filter, &t, norm, res, &nres, MAX_RES);
-	if (nres > 1 && t > 0.99f)
-	{
-		m_npath = dtMergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, nres);
-	}
-}
-
-/**
-@par
-
-Inaccurate locomotion or dynamic obstacle avoidance can force the agent position significantly outside the 
-original corridor. Over time this can result in the formation of a non-optimal corridor. This function will use a 
-local area path search to try to re-optimize the corridor.
-
-The more inaccurate the agent movement, the more beneficial this function becomes. Simply adjust the frequency of 
-the call to match the needs to the agent.
-*/
-bool dtPathCorridor::optimizePathTopology(dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	dtAssert(navquery);
-	dtAssert(filter);
-	dtAssert(m_path);
-	
-	if (m_npath < 3)
-		return false;
-	
-	static const int MAX_ITER = 32;
-	static const int MAX_RES = 32;
-	
-	dtPolyRef res[MAX_RES];
-	int nres = 0;
-	navquery->initSlicedFindPath(m_path[0], m_path[m_npath-1], m_pos, m_target, filter);
-	navquery->updateSlicedFindPath(MAX_ITER, 0);
-	dtStatus status = navquery->finalizeSlicedFindPathPartial(m_path, m_npath, res, &nres, MAX_RES);
-	
-	if (dtStatusSucceed(status) && nres > 0)
-	{
-		m_npath = dtMergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, nres);
-		return true;
-	}
-	
-	return false;
-}
-
-bool dtPathCorridor::moveOverOffmeshConnection(dtPolyRef offMeshConRef, dtPolyRef* refs,
-											   float* startPos, float* endPos,
-											   dtNavMeshQuery* navquery)
-{
-	dtAssert(navquery);
-	dtAssert(m_path);
-	dtAssert(m_npath);
-
-	// Advance the path up to and over the off-mesh connection.
-	dtPolyRef prevRef = 0, polyRef = m_path[0];
-	int npos = 0;
-	while (npos < m_npath && polyRef != offMeshConRef)
-	{
-		prevRef = polyRef;
-		polyRef = m_path[npos];
-		npos++;
-	}
-	if (npos == m_npath)
-	{
-		// Could not find offMeshConRef
-		return false;
-	}
-	
-	// Prune path
-	for (int i = npos; i < m_npath; ++i)
-		m_path[i-npos] = m_path[i];
-	m_npath -= npos;
-
-	refs[0] = prevRef;
-	refs[1] = polyRef;
-	
-	const dtNavMesh* nav = navquery->getAttachedNavMesh();
-	dtAssert(nav);
-
-	dtStatus status = nav->getOffMeshConnectionPolyEndPoints(refs[0], refs[1], startPos, endPos);
-	if (dtStatusSucceed(status))
-	{
-		dtVcopy(m_pos, endPos);
-		return true;
-	}
-
-	return false;
-}
-
-/**
-@par
-
-Behavior:
-
-- The movement is constrained to the surface of the navigation mesh. 
-- The corridor is automatically adjusted (shorted or lengthened) in order to remain valid. 
-- The new position will be located in the adjusted corridor's first polygon.
-
-The expected use case is that the desired position will be 'near' the current corridor. What is considered 'near' 
-depends on local polygon density, query search half extents, etc.
-
-The resulting position will differ from the desired position if the desired position is not on the navigation mesh, 
-or it can't be reached using a local search.
-*/
-bool dtPathCorridor::movePosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	dtAssert(m_path);
-	dtAssert(m_npath);
-	
-	// Move along navmesh and update new position.
-	float result[3];
-	static const int MAX_VISITED = 16;
-	dtPolyRef visited[MAX_VISITED];
-	int nvisited = 0;
-	dtStatus status = navquery->moveAlongSurface(m_path[0], m_pos, npos, filter,
-												 result, visited, &nvisited, MAX_VISITED);
-	if (dtStatusSucceed(status)) {
-		m_npath = dtMergeCorridorStartMoved(m_path, m_npath, m_maxPath, visited, nvisited);
-		
-		// Adjust the position to stay on top of the navmesh.
-		float h = m_pos[1];
-		navquery->getPolyHeight(m_path[0], result, &h);
-		result[1] = h;
-		dtVcopy(m_pos, result);
-		return true;
-	}
-	return false;
-}
-
-/**
-@par
-
-Behavior:
-
-- The movement is constrained to the surface of the navigation mesh. 
-- The corridor is automatically adjusted (shorted or lengthened) in order to remain valid. 
-- The new target will be located in the adjusted corridor's last polygon.
-
-The expected use case is that the desired target will be 'near' the current corridor. What is considered 'near' depends on local polygon density, query search half extents, etc.
-
-The resulting target will differ from the desired target if the desired target is not on the navigation mesh, or it can't be reached using a local search.
-*/
-bool dtPathCorridor::moveTargetPosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	dtAssert(m_path);
-	dtAssert(m_npath);
-	
-	// Move along navmesh and update new position.
-	float result[3];
-	static const int MAX_VISITED = 16;
-	dtPolyRef visited[MAX_VISITED];
-	int nvisited = 0;
-	dtStatus status = navquery->moveAlongSurface(m_path[m_npath-1], m_target, npos, filter,
-												 result, visited, &nvisited, MAX_VISITED);
-	if (dtStatusSucceed(status))
-	{
-		m_npath = dtMergeCorridorEndMoved(m_path, m_npath, m_maxPath, visited, nvisited);
-		// TODO: should we do that?
-		// Adjust the position to stay on top of the navmesh.
-		/*	float h = m_target[1];
-		 navquery->getPolyHeight(m_path[m_npath-1], result, &h);
-		 result[1] = h;*/
-		
-		dtVcopy(m_target, result);
-		
-		return true;
-	}
-	return false;
-}
-
-/// @par
-///
-/// The current corridor position is expected to be within the first polygon in the path. The target 
-/// is expected to be in the last polygon. 
-/// 
-/// @warning The size of the path must not exceed the size of corridor's path buffer set during #init().
-void dtPathCorridor::setCorridor(const float* target, const dtPolyRef* path, const int npath)
-{
-	dtAssert(m_path);
-	dtAssert(npath > 0);
-	dtAssert(npath < m_maxPath);
-	
-	dtVcopy(m_target, target);
-	memcpy(m_path, path, sizeof(dtPolyRef)*npath);
-	m_npath = npath;
-}
-
-bool dtPathCorridor::fixPathStart(dtPolyRef safeRef, const float* safePos)
-{
-	dtAssert(m_path);
-
-	dtVcopy(m_pos, safePos);
-	if (m_npath < 3 && m_npath > 0)
-	{
-		m_path[2] = m_path[m_npath-1];
-		m_path[0] = safeRef;
-		m_path[1] = 0;
-		m_npath = 3;
-	}
-	else
-	{
-		m_path[0] = safeRef;
-		m_path[1] = 0;
-	}
-	
-	return true;
-}
-
-bool dtPathCorridor::trimInvalidPath(dtPolyRef safeRef, const float* safePos,
-									 dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	dtAssert(navquery);
-	dtAssert(filter);
-	dtAssert(m_path);
-	
-	// Keep valid path as far as possible.
-	int n = 0;
-	while (n < m_npath && navquery->isValidPolyRef(m_path[n], filter)) {
-		n++;
-	}
-	
-	if (n == m_npath)
-	{
-		// All valid, no need to fix.
-		return true;
-	}
-	else if (n == 0)
-	{
-		// The first polyref is bad, use current safe values.
-		dtVcopy(m_pos, safePos);
-		m_path[0] = safeRef;
-		m_npath = 1;
-	}
-	else
-	{
-		// The path is partially usable.
-		m_npath = n;
-	}
-	
-	// Clamp target pos to last poly
-	float tgt[3];
-	dtVcopy(tgt, m_target);
-	navquery->closestPointOnPolyBoundary(m_path[m_npath-1], tgt, m_target);
-	
-	return true;
-}
-
-/// @par
-///
-/// The path can be invalidated if there are structural changes to the underlying navigation mesh, or the state of 
-/// a polygon within the path changes resulting in it being filtered out. (E.g. An exclusion or inclusion flag changes.)
-bool dtPathCorridor::isValid(const int maxLookAhead, dtNavMeshQuery* navquery, const dtQueryFilter* filter)
-{
-	// Check that all polygons still pass query filter.
-	const int n = dtMin(m_npath, maxLookAhead);
-	for (int i = 0; i < n; ++i)
-	{
-		if (!navquery->isValidPolyRef(m_path[i], filter))
-			return false;
-	}
-
-	return true;
-}

+ 0 - 151
panda/src/recastdetour/DetourPathCorridor.h

@@ -1,151 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOUTPATHCORRIDOR_H
-#define DETOUTPATHCORRIDOR_H
-
-#include "DetourNavMeshQuery.h"
-
-/// Represents a dynamic polygon corridor used to plan agent movement.
-/// @ingroup crowd, detour
-class dtPathCorridor
-{
-	float m_pos[3];
-	float m_target[3];
-	
-	dtPolyRef* m_path;
-	int m_npath;
-	int m_maxPath;
-	
-public:
-	dtPathCorridor();
-	~dtPathCorridor();
-	
-	/// Allocates the corridor's path buffer. 
-	///  @param[in]		maxPath		The maximum path size the corridor can handle.
-	/// @return True if the initialization succeeded.
-	bool init(const int maxPath);
-	
-	/// Resets the path corridor to the specified position.
-	///  @param[in]		ref		The polygon reference containing the position.
-	///  @param[in]		pos		The new position in the corridor. [(x, y, z)]
-	void reset(dtPolyRef ref, const float* pos);
-	
-	/// Finds the corners in the corridor from the position toward the target. (The straightened path.)
-	///  @param[out]	cornerVerts		The corner vertices. [(x, y, z) * cornerCount] [Size: <= maxCorners]
-	///  @param[out]	cornerFlags		The flag for each corner. [(flag) * cornerCount] [Size: <= maxCorners]
-	///  @param[out]	cornerPolys		The polygon reference for each corner. [(polyRef) * cornerCount] 
-	///  								[Size: <= @p maxCorners]
-	///  @param[in]		maxCorners		The maximum number of corners the buffers can hold.
-	///  @param[in]		navquery		The query object used to build the corridor.
-	///  @param[in]		filter			The filter to apply to the operation.
-	/// @return The number of corners returned in the corner buffers. [0 <= value <= @p maxCorners]
-	int findCorners(float* cornerVerts, unsigned char* cornerFlags,
-					dtPolyRef* cornerPolys, const int maxCorners,
-					dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	/// Attempts to optimize the path if the specified point is visible from the current position.
-	///  @param[in]		next					The point to search toward. [(x, y, z])
-	///  @param[in]		pathOptimizationRange	The maximum range to search. [Limit: > 0]
-	///  @param[in]		navquery				The query object used to build the corridor.
-	///  @param[in]		filter					The filter to apply to the operation.			
-	void optimizePathVisibility(const float* next, const float pathOptimizationRange,
-								dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	/// Attempts to optimize the path using a local area search. (Partial replanning.) 
-	///  @param[in]		navquery	The query object used to build the corridor.
-	///  @param[in]		filter		The filter to apply to the operation.	
-	bool optimizePathTopology(dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	bool moveOverOffmeshConnection(dtPolyRef offMeshConRef, dtPolyRef* refs,
-								   float* startPos, float* endPos,
-								   dtNavMeshQuery* navquery);
-
-	bool fixPathStart(dtPolyRef safeRef, const float* safePos);
-
-	bool trimInvalidPath(dtPolyRef safeRef, const float* safePos,
-						 dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	/// Checks the current corridor path to see if its polygon references remain valid. 
-	///  @param[in]		maxLookAhead	The number of polygons from the beginning of the corridor to search.
-	///  @param[in]		navquery		The query object used to build the corridor.
-	///  @param[in]		filter			The filter to apply to the operation.	
-	bool isValid(const int maxLookAhead, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	/// Moves the position from the current location to the desired location, adjusting the corridor 
-	/// as needed to reflect the change.
-	///  @param[in]		npos		The desired new position. [(x, y, z)]
-	///  @param[in]		navquery	The query object used to build the corridor.
-	///  @param[in]		filter		The filter to apply to the operation.
-	/// @return Returns true if move succeeded.
-	bool movePosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-
-	/// Moves the target from the curent location to the desired location, adjusting the corridor
-	/// as needed to reflect the change. 
-	///  @param[in]		npos		The desired new target position. [(x, y, z)]
-	///  @param[in]		navquery	The query object used to build the corridor.
-	///  @param[in]		filter		The filter to apply to the operation.
-	/// @return Returns true if move succeeded.
-	bool moveTargetPosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
-	
-	/// Loads a new path and target into the corridor.
-	///  @param[in]		target		The target location within the last polygon of the path. [(x, y, z)]
-	///  @param[in]		path		The path corridor. [(polyRef) * @p npolys]
-	///  @param[in]		npath		The number of polygons in the path.
-	void setCorridor(const float* target, const dtPolyRef* polys, const int npath);
-	
-	/// Gets the current position within the corridor. (In the first polygon.)
-	/// @return The current position within the corridor.
-	inline const float* getPos() const { return m_pos; }
-
-	/// Gets the current target within the corridor. (In the last polygon.)
-	/// @return The current target within the corridor.
-	inline const float* getTarget() const { return m_target; }
-	
-	/// The polygon reference id of the first polygon in the corridor, the polygon containing the position.
-	/// @return The polygon reference id of the first polygon in the corridor. (Or zero if there is no path.)
-	inline dtPolyRef getFirstPoly() const { return m_npath ? m_path[0] : 0; }
-
-	/// The polygon reference id of the last polygon in the corridor, the polygon containing the target.
-	/// @return The polygon reference id of the last polygon in the corridor. (Or zero if there is no path.)
-	inline dtPolyRef getLastPoly() const { return m_npath ? m_path[m_npath-1] : 0; }
-	
-	/// The corridor's path.
-	/// @return The corridor's path. [(polyRef) * #getPathCount()]
-	inline const dtPolyRef* getPath() const { return m_path; }
-
-	/// The number of polygons in the current corridor path.
-	/// @return The number of polygons in the current corridor path.
-	inline int getPathCount() const { return m_npath; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtPathCorridor(const dtPathCorridor&);
-	dtPathCorridor& operator=(const dtPathCorridor&);
-};
-
-int dtMergeCorridorStartMoved(dtPolyRef* path, const int npath, const int maxPath,
-							  const dtPolyRef* visited, const int nvisited);
-
-int dtMergeCorridorEndMoved(dtPolyRef* path, const int npath, const int maxPath,
-							const dtPolyRef* visited, const int nvisited);
-
-int dtMergeCorridorStartShortcut(dtPolyRef* path, const int npath, const int maxPath,
-								 const dtPolyRef* visited, const int nvisited);
-
-#endif // DETOUTPATHCORRIDOR_H

+ 0 - 200
panda/src/recastdetour/DetourPathQueue.cpp

@@ -1,200 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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.
-//
-
-#include <string.h>
-#include "DetourPathQueue.h"
-#include "DetourNavMesh.h"
-#include "DetourNavMeshQuery.h"
-#include "DetourAlloc.h"
-#include "DetourCommon.h"
-
-
-dtPathQueue::dtPathQueue() :
-	m_nextHandle(1),
-	m_maxPathSize(0),
-	m_queueHead(0),
-	m_navquery(0)
-{
-	for (int i = 0; i < MAX_QUEUE; ++i)
-		m_queue[i].path = 0;
-}
-
-dtPathQueue::~dtPathQueue()
-{
-	purge();
-}
-
-void dtPathQueue::purge()
-{
-	dtFreeNavMeshQuery(m_navquery);
-	m_navquery = 0;
-	for (int i = 0; i < MAX_QUEUE; ++i)
-	{
-		dtFree(m_queue[i].path);
-		m_queue[i].path = 0;
-	}
-}
-
-bool dtPathQueue::init(const int maxPathSize, const int maxSearchNodeCount, dtNavMesh* nav)
-{
-	purge();
-
-	m_navquery = dtAllocNavMeshQuery();
-	if (!m_navquery)
-		return false;
-	if (dtStatusFailed(m_navquery->init(nav, maxSearchNodeCount)))
-		return false;
-	
-	m_maxPathSize = maxPathSize;
-	for (int i = 0; i < MAX_QUEUE; ++i)
-	{
-		m_queue[i].ref = DT_PATHQ_INVALID;
-		m_queue[i].path = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*m_maxPathSize, DT_ALLOC_PERM);
-		if (!m_queue[i].path)
-			return false;
-	}
-	
-	m_queueHead = 0;
-	
-	return true;
-}
-
-void dtPathQueue::update(const int maxIters)
-{
-	static const int MAX_KEEP_ALIVE = 2; // in update ticks.
-
-	// Update path request until there is nothing to update
-	// or upto maxIters pathfinder iterations has been consumed.
-	int iterCount = maxIters;
-	
-	for (int i = 0; i < MAX_QUEUE; ++i)
-	{
-		PathQuery& q = m_queue[m_queueHead % MAX_QUEUE];
-		
-		// Skip inactive requests.
-		if (q.ref == DT_PATHQ_INVALID)
-		{
-			m_queueHead++;
-			continue;
-		}
-		
-		// Handle completed request.
-		if (dtStatusSucceed(q.status) || dtStatusFailed(q.status))
-		{
-			// If the path result has not been read in few frames, free the slot.
-			q.keepAlive++;
-			if (q.keepAlive > MAX_KEEP_ALIVE)
-			{
-				q.ref = DT_PATHQ_INVALID;
-				q.status = 0;
-			}
-			
-			m_queueHead++;
-			continue;
-		}
-		
-		// Handle query start.
-		if (q.status == 0)
-		{
-			q.status = m_navquery->initSlicedFindPath(q.startRef, q.endRef, q.startPos, q.endPos, q.filter);
-		}		
-		// Handle query in progress.
-		if (dtStatusInProgress(q.status))
-		{
-			int iters = 0;
-			q.status = m_navquery->updateSlicedFindPath(iterCount, &iters);
-			iterCount -= iters;
-		}
-		if (dtStatusSucceed(q.status))
-		{
-			q.status = m_navquery->finalizeSlicedFindPath(q.path, &q.npath, m_maxPathSize);
-		}
-
-		if (iterCount <= 0)
-			break;
-
-		m_queueHead++;
-	}
-}
-
-dtPathQueueRef dtPathQueue::request(dtPolyRef startRef, dtPolyRef endRef,
-									const float* startPos, const float* endPos,
-									const dtQueryFilter* filter)
-{
-	// Find empty slot
-	int slot = -1;
-	for (int i = 0; i < MAX_QUEUE; ++i)
-	{
-		if (m_queue[i].ref == DT_PATHQ_INVALID)
-		{
-			slot = i;
-			break;
-		}
-	}
-	// Could not find slot.
-	if (slot == -1)
-		return DT_PATHQ_INVALID;
-	
-	dtPathQueueRef ref = m_nextHandle++;
-	if (m_nextHandle == DT_PATHQ_INVALID) m_nextHandle++;
-	
-	PathQuery& q = m_queue[slot];
-	q.ref = ref;
-	dtVcopy(q.startPos, startPos);
-	q.startRef = startRef;
-	dtVcopy(q.endPos, endPos);
-	q.endRef = endRef;
-	
-	q.status = 0;
-	q.npath = 0;
-	q.filter = filter;
-	q.keepAlive = 0;
-	
-	return ref;
-}
-
-dtStatus dtPathQueue::getRequestStatus(dtPathQueueRef ref) const
-{
-	for (int i = 0; i < MAX_QUEUE; ++i)
-	{
-		if (m_queue[i].ref == ref)
-			return m_queue[i].status;
-	}
-	return DT_FAILURE;
-}
-
-dtStatus dtPathQueue::getPathResult(dtPathQueueRef ref, dtPolyRef* path, int* pathSize, const int maxPath)
-{
-	for (int i = 0; i < MAX_QUEUE; ++i)
-	{
-		if (m_queue[i].ref == ref)
-		{
-			PathQuery& q = m_queue[i];
-			dtStatus details = q.status & DT_STATUS_DETAIL_MASK;
-			// Free request for reuse.
-			q.ref = DT_PATHQ_INVALID;
-			q.status = 0;
-			// Copy path
-			int n = dtMin(q.npath, maxPath);
-			memcpy(path, q.path, sizeof(dtPolyRef)*n);
-			*pathSize = n;
-			return details | DT_SUCCESS;
-		}
-	}
-	return DT_FAILURE;
-}

+ 0 - 79
panda/src/recastdetour/DetourPathQueue.h

@@ -1,79 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOURPATHQUEUE_H
-#define DETOURPATHQUEUE_H
-
-#include "DetourNavMesh.h"
-#include "DetourNavMeshQuery.h"
-
-static const unsigned int DT_PATHQ_INVALID = 0;
-
-typedef unsigned int dtPathQueueRef;
-
-class dtPathQueue
-{
-	struct PathQuery
-	{
-		dtPathQueueRef ref;
-		/// Path find start and end location.
-		float startPos[3], endPos[3];
-		dtPolyRef startRef, endRef;
-		/// Result.
-		dtPolyRef* path;
-		int npath;
-		/// State.
-		dtStatus status;
-		int keepAlive;
-		const dtQueryFilter* filter; ///< TODO: This is potentially dangerous!
-	};
-	
-	static const int MAX_QUEUE = 8;
-	PathQuery m_queue[MAX_QUEUE];
-	dtPathQueueRef m_nextHandle;
-	int m_maxPathSize;
-	int m_queueHead;
-	dtNavMeshQuery* m_navquery;
-	
-	void purge();
-	
-public:
-	dtPathQueue();
-	~dtPathQueue();
-	
-	bool init(const int maxPathSize, const int maxSearchNodeCount, dtNavMesh* nav);
-	
-	void update(const int maxIters);
-	
-	dtPathQueueRef request(dtPolyRef startRef, dtPolyRef endRef,
-						   const float* startPos, const float* endPos, 
-						   const dtQueryFilter* filter);
-	
-	dtStatus getRequestStatus(dtPathQueueRef ref) const;
-	
-	dtStatus getPathResult(dtPathQueueRef ref, dtPolyRef* path, int* pathSize, const int maxPath);
-	
-	inline const dtNavMeshQuery* getNavQuery() const { return m_navquery; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtPathQueue(const dtPathQueue&);
-	dtPathQueue& operator=(const dtPathQueue&);
-};
-
-#endif // DETOURPATHQUEUE_H

+ 0 - 194
panda/src/recastdetour/DetourProximityGrid.cpp

@@ -1,194 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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.
-//
-
-#include <string.h>
-#include <new>
-#include "DetourProximityGrid.h"
-#include "DetourCommon.h"
-#include "DetourMath.h"
-#include "DetourAlloc.h"
-#include "DetourAssert.h"
-
-
-dtProximityGrid* dtAllocProximityGrid()
-{
-	void* mem = dtAlloc(sizeof(dtProximityGrid), DT_ALLOC_PERM);
-	if (!mem) return 0;
-	return new(mem) dtProximityGrid;
-}
-
-void dtFreeProximityGrid(dtProximityGrid* ptr)
-{
-	if (!ptr) return;
-	ptr->~dtProximityGrid();
-	dtFree(ptr);
-}
-
-
-inline int hashPos2(int x, int y, int n)
-{
-	return ((x*73856093) ^ (y*19349663)) & (n-1);
-}
-
-
-dtProximityGrid::dtProximityGrid() :
-	m_cellSize(0),
-	m_invCellSize(0),
-	m_pool(0),
-	m_poolHead(0),
-	m_poolSize(0),
-	m_buckets(0),
-	m_bucketsSize(0)
-{
-}
-
-dtProximityGrid::~dtProximityGrid()
-{
-	dtFree(m_buckets);
-	dtFree(m_pool);
-}
-
-bool dtProximityGrid::init(const int poolSize, const float cellSize)
-{
-	dtAssert(poolSize > 0);
-	dtAssert(cellSize > 0.0f);
-	
-	m_cellSize = cellSize;
-	m_invCellSize = 1.0f / m_cellSize;
-	
-	// Allocate hashs buckets
-	m_bucketsSize = dtNextPow2(poolSize);
-	m_buckets = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_bucketsSize, DT_ALLOC_PERM);
-	if (!m_buckets)
-		return false;
-	
-	// Allocate pool of items.
-	m_poolSize = poolSize;
-	m_poolHead = 0;
-	m_pool = (Item*)dtAlloc(sizeof(Item)*m_poolSize, DT_ALLOC_PERM);
-	if (!m_pool)
-		return false;
-	
-	clear();
-	
-	return true;
-}
-
-void dtProximityGrid::clear()
-{
-	memset(m_buckets, 0xff, sizeof(unsigned short)*m_bucketsSize);
-	m_poolHead = 0;
-	m_bounds[0] = 0xffff;
-	m_bounds[1] = 0xffff;
-	m_bounds[2] = -0xffff;
-	m_bounds[3] = -0xffff;
-}
-
-void dtProximityGrid::addItem(const unsigned short id,
-							  const float minx, const float miny,
-							  const float maxx, const float maxy)
-{
-	const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
-	const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
-	const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
-	const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
-	
-	m_bounds[0] = dtMin(m_bounds[0], iminx);
-	m_bounds[1] = dtMin(m_bounds[1], iminy);
-	m_bounds[2] = dtMax(m_bounds[2], imaxx);
-	m_bounds[3] = dtMax(m_bounds[3], imaxy);
-	
-	for (int y = iminy; y <= imaxy; ++y)
-	{
-		for (int x = iminx; x <= imaxx; ++x)
-		{
-			if (m_poolHead < m_poolSize)
-			{
-				const int h = hashPos2(x, y, m_bucketsSize);
-				const unsigned short idx = (unsigned short)m_poolHead;
-				m_poolHead++;
-				Item& item = m_pool[idx];
-				item.x = (short)x;
-				item.y = (short)y;
-				item.id = id;
-				item.next = m_buckets[h];
-				m_buckets[h] = idx;
-			}
-		}
-	}
-}
-
-int dtProximityGrid::queryItems(const float minx, const float miny,
-								const float maxx, const float maxy,
-								unsigned short* ids, const int maxIds) const
-{
-	const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
-	const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
-	const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
-	const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
-	
-	int n = 0;
-	
-	for (int y = iminy; y <= imaxy; ++y)
-	{
-		for (int x = iminx; x <= imaxx; ++x)
-		{
-			const int h = hashPos2(x, y, m_bucketsSize);
-			unsigned short idx = m_buckets[h];
-			while (idx != 0xffff)
-			{
-				Item& item = m_pool[idx];
-				if ((int)item.x == x && (int)item.y == y)
-				{
-					// Check if the id exists already.
-					const unsigned short* end = ids + n;
-					unsigned short* i = ids;
-					while (i != end && *i != item.id)
-						++i;
-					// Item not found, add it.
-					if (i == end)
-					{
-						if (n >= maxIds)
-							return n;
-						ids[n++] = item.id;
-					}
-				}
-				idx = item.next;
-			}
-		}
-	}
-	
-	return n;
-}
-
-int dtProximityGrid::getItemCountAt(const int x, const int y) const
-{
-	int n = 0;
-	
-	const int h = hashPos2(x, y, m_bucketsSize);
-	unsigned short idx = m_buckets[h];
-	while (idx != 0xffff)
-	{
-		Item& item = m_pool[idx];
-		if ((int)item.x == x && (int)item.y == y)
-			n++;
-		idx = item.next;
-	}
-	
-	return n;
-}

+ 0 - 74
panda/src/recastdetour/DetourProximityGrid.h

@@ -1,74 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOURPROXIMITYGRID_H
-#define DETOURPROXIMITYGRID_H
-
-class dtProximityGrid
-{
-	float m_cellSize;
-	float m_invCellSize;
-	
-	struct Item
-	{
-		unsigned short id;
-		short x,y;
-		unsigned short next;
-	};
-	Item* m_pool;
-	int m_poolHead;
-	int m_poolSize;
-	
-	unsigned short* m_buckets;
-	int m_bucketsSize;
-	
-	int m_bounds[4];
-	
-public:
-	dtProximityGrid();
-	~dtProximityGrid();
-	
-	bool init(const int poolSize, const float cellSize);
-	
-	void clear();
-	
-	void addItem(const unsigned short id,
-				 const float minx, const float miny,
-				 const float maxx, const float maxy);
-	
-	int queryItems(const float minx, const float miny,
-				   const float maxx, const float maxy,
-				   unsigned short* ids, const int maxIds) const;
-	
-	int getItemCountAt(const int x, const int y) const;
-	
-	inline const int* getBounds() const { return m_bounds; }
-	inline float getCellSize() const { return m_cellSize; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtProximityGrid(const dtProximityGrid&);
-	dtProximityGrid& operator=(const dtProximityGrid&);
-};
-
-dtProximityGrid* dtAllocProximityGrid();
-void dtFreeProximityGrid(dtProximityGrid* ptr);
-
-
-#endif // DETOURPROXIMITYGRID_H
-

+ 0 - 820
panda/src/recastdetour/DetourTileCache.cpp

@@ -1,820 +0,0 @@
-#include "DetourTileCache.h"
-#include "DetourTileCacheBuilder.h"
-#include "DetourNavMeshBuilder.h"
-#include "DetourNavMesh.h"
-#include "DetourCommon.h"
-#include "DetourMath.h"
-#include "DetourAlloc.h"
-#include "DetourAssert.h"
-#include <string.h>
-#include <new>
-
-dtTileCache* dtAllocTileCache()
-{
-	void* mem = dtAlloc(sizeof(dtTileCache), DT_ALLOC_PERM);
-	if (!mem) return 0;
-	return new(mem) dtTileCache;
-}
-
-void dtFreeTileCache(dtTileCache* tc)
-{
-	if (!tc) return;
-	tc->~dtTileCache();
-	dtFree(tc);
-}
-
-static bool contains(const dtCompressedTileRef* a, const int n, const dtCompressedTileRef v)
-{
-	for (int i = 0; i < n; ++i)
-		if (a[i] == v)
-			return true;
-	return false;
-}
-
-inline int computeTileHash(int x, int y, const int mask)
-{
-	const unsigned int h1 = 0x8da6b343; // Large multiplicative constants;
-	const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes
-	unsigned int n = h1 * x + h2 * y;
-	return (int)(n & mask);
-}
-
-
-struct NavMeshTileBuildContext
-{
-	inline NavMeshTileBuildContext(struct dtTileCacheAlloc* a) : layer(0), lcset(0), lmesh(0), alloc(a) {}
-	inline ~NavMeshTileBuildContext() { purge(); }
-	void purge()
-	{
-		dtFreeTileCacheLayer(alloc, layer);
-		layer = 0;
-		dtFreeTileCacheContourSet(alloc, lcset);
-		lcset = 0;
-		dtFreeTileCachePolyMesh(alloc, lmesh);
-		lmesh = 0;
-	}
-	struct dtTileCacheLayer* layer;
-	struct dtTileCacheContourSet* lcset;
-	struct dtTileCachePolyMesh* lmesh;
-	struct dtTileCacheAlloc* alloc;
-};
-
-
-dtTileCache::dtTileCache() :
-	m_tileLutSize(0),
-	m_tileLutMask(0),
-	m_posLookup(0),
-	m_nextFreeTile(0),	
-	m_tiles(0),	
-	m_saltBits(0),
-	m_tileBits(0),
-	m_talloc(0),
-	m_tcomp(0),
-	m_tmproc(0),
-	m_obstacles(0),
-	m_nextFreeObstacle(0),
-	m_nreqs(0),
-	m_nupdate(0)
-{
-	memset(&m_params, 0, sizeof(m_params));
-	memset(m_reqs, 0, sizeof(ObstacleRequest) * MAX_REQUESTS);
-}
-	
-dtTileCache::~dtTileCache()
-{
-	for (int i = 0; i < m_params.maxTiles; ++i)
-	{
-		if (m_tiles[i].flags & DT_COMPRESSEDTILE_FREE_DATA)
-		{
-			dtFree(m_tiles[i].data);
-			m_tiles[i].data = 0;
-		}
-	}
-	dtFree(m_obstacles);
-	m_obstacles = 0;
-	dtFree(m_posLookup);
-	m_posLookup = 0;
-	dtFree(m_tiles);
-	m_tiles = 0;
-	m_nreqs = 0;
-	m_nupdate = 0;
-}
-
-const dtCompressedTile* dtTileCache::getTileByRef(dtCompressedTileRef ref) const
-{
-	if (!ref)
-		return 0;
-	unsigned int tileIndex = decodeTileIdTile(ref);
-	unsigned int tileSalt = decodeTileIdSalt(ref);
-	if ((int)tileIndex >= m_params.maxTiles)
-		return 0;
-	const dtCompressedTile* tile = &m_tiles[tileIndex];
-	if (tile->salt != tileSalt)
-		return 0;
-	return tile;
-}
-
-
-dtStatus dtTileCache::init(const dtTileCacheParams* params,
-						   dtTileCacheAlloc* talloc,
-						   dtTileCacheCompressor* tcomp,
-						   dtTileCacheMeshProcess* tmproc)
-{
-	m_talloc = talloc;
-	m_tcomp = tcomp;
-	m_tmproc = tmproc;
-	m_nreqs = 0;
-	memcpy(&m_params, params, sizeof(m_params));
-	
-	// Alloc space for obstacles.
-	m_obstacles = (dtTileCacheObstacle*)dtAlloc(sizeof(dtTileCacheObstacle)*m_params.maxObstacles, DT_ALLOC_PERM);
-	if (!m_obstacles)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(m_obstacles, 0, sizeof(dtTileCacheObstacle)*m_params.maxObstacles);
-	m_nextFreeObstacle = 0;
-	for (int i = m_params.maxObstacles-1; i >= 0; --i)
-	{
-		m_obstacles[i].salt = 1;
-		m_obstacles[i].next = m_nextFreeObstacle;
-		m_nextFreeObstacle = &m_obstacles[i];
-	}
-	
-	// Init tiles
-	m_tileLutSize = dtNextPow2(m_params.maxTiles/4);
-	if (!m_tileLutSize) m_tileLutSize = 1;
-	m_tileLutMask = m_tileLutSize-1;
-	
-	m_tiles = (dtCompressedTile*)dtAlloc(sizeof(dtCompressedTile)*m_params.maxTiles, DT_ALLOC_PERM);
-	if (!m_tiles)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	m_posLookup = (dtCompressedTile**)dtAlloc(sizeof(dtCompressedTile*)*m_tileLutSize, DT_ALLOC_PERM);
-	if (!m_posLookup)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(m_tiles, 0, sizeof(dtCompressedTile)*m_params.maxTiles);
-	memset(m_posLookup, 0, sizeof(dtCompressedTile*)*m_tileLutSize);
-	m_nextFreeTile = 0;
-	for (int i = m_params.maxTiles-1; i >= 0; --i)
-	{
-		m_tiles[i].salt = 1;
-		m_tiles[i].next = m_nextFreeTile;
-		m_nextFreeTile = &m_tiles[i];
-	}
-	
-	// Init ID generator values.
-	m_tileBits = dtIlog2(dtNextPow2((unsigned int)m_params.maxTiles));
-	// Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
-	m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits);
-	if (m_saltBits < 10)
-		return DT_FAILURE | DT_INVALID_PARAM;
-	
-	return DT_SUCCESS;
-}
-
-int dtTileCache::getTilesAt(const int tx, const int ty, dtCompressedTileRef* tiles, const int maxTiles) const 
-{
-	int n = 0;
-	
-	// Find tile based on hash.
-	int h = computeTileHash(tx,ty,m_tileLutMask);
-	dtCompressedTile* tile = m_posLookup[h];
-	while (tile)
-	{
-		if (tile->header &&
-			tile->header->tx == tx &&
-			tile->header->ty == ty)
-		{
-			if (n < maxTiles)
-				tiles[n++] = getTileRef(tile);
-		}
-		tile = tile->next;
-	}
-	
-	return n;
-}
-
-dtCompressedTile* dtTileCache::getTileAt(const int tx, const int ty, const int tlayer)
-{
-	// Find tile based on hash.
-	int h = computeTileHash(tx,ty,m_tileLutMask);
-	dtCompressedTile* tile = m_posLookup[h];
-	while (tile)
-	{
-		if (tile->header &&
-			tile->header->tx == tx &&
-			tile->header->ty == ty &&
-			tile->header->tlayer == tlayer)
-		{
-			return tile;
-		}
-		tile = tile->next;
-	}
-	return 0;
-}
-
-dtCompressedTileRef dtTileCache::getTileRef(const dtCompressedTile* tile) const
-{
-	if (!tile) return 0;
-	const unsigned int it = (unsigned int)(tile - m_tiles);
-	return (dtCompressedTileRef)encodeTileId(tile->salt, it);
-}
-
-dtObstacleRef dtTileCache::getObstacleRef(const dtTileCacheObstacle* ob) const
-{
-	if (!ob) return 0;
-	const unsigned int idx = (unsigned int)(ob - m_obstacles);
-	return encodeObstacleId(ob->salt, idx);
-}
-
-const dtTileCacheObstacle* dtTileCache::getObstacleByRef(dtObstacleRef ref)
-{
-	if (!ref)
-		return 0;
-	unsigned int idx = decodeObstacleIdObstacle(ref);
-	if ((int)idx >= m_params.maxObstacles)
-		return 0;
-	const dtTileCacheObstacle* ob = &m_obstacles[idx];
-	unsigned int salt = decodeObstacleIdSalt(ref);
-	if (ob->salt != salt)
-		return 0;
-	return ob;
-}
-
-dtStatus dtTileCache::addTile(unsigned char* data, const int dataSize, unsigned char flags, dtCompressedTileRef* result)
-{
-	// Make sure the data is in right format.
-	dtTileCacheLayerHeader* header = (dtTileCacheLayerHeader*)data;
-	if (header->magic != DT_TILECACHE_MAGIC)
-		return DT_FAILURE | DT_WRONG_MAGIC;
-	if (header->version != DT_TILECACHE_VERSION)
-		return DT_FAILURE | DT_WRONG_VERSION;
-	
-	// Make sure the location is free.
-	if (getTileAt(header->tx, header->ty, header->tlayer))
-		return DT_FAILURE;
-	
-	// Allocate a tile.
-	dtCompressedTile* tile = 0;
-	if (m_nextFreeTile)
-	{
-		tile = m_nextFreeTile;
-		m_nextFreeTile = tile->next;
-		tile->next = 0;
-	}
-	
-	// Make sure we could allocate a tile.
-	if (!tile)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	
-	// Insert tile into the position lut.
-	int h = computeTileHash(header->tx, header->ty, m_tileLutMask);
-	tile->next = m_posLookup[h];
-	m_posLookup[h] = tile;
-	
-	// Init tile.
-	const int headerSize = dtAlign4(sizeof(dtTileCacheLayerHeader));
-	tile->header = (dtTileCacheLayerHeader*)data;
-	tile->data = data;
-	tile->dataSize = dataSize;
-	tile->compressed = tile->data + headerSize;
-	tile->compressedSize = tile->dataSize - headerSize;
-	tile->flags = flags;
-	
-	if (result)
-		*result = getTileRef(tile);
-	
-	return DT_SUCCESS;
-}
-
-dtStatus dtTileCache::removeTile(dtCompressedTileRef ref, unsigned char** data, int* dataSize)
-{
-	if (!ref)
-		return DT_FAILURE | DT_INVALID_PARAM;
-	unsigned int tileIndex = decodeTileIdTile(ref);
-	unsigned int tileSalt = decodeTileIdSalt(ref);
-	if ((int)tileIndex >= m_params.maxTiles)
-		return DT_FAILURE | DT_INVALID_PARAM;
-	dtCompressedTile* tile = &m_tiles[tileIndex];
-	if (tile->salt != tileSalt)
-		return DT_FAILURE | DT_INVALID_PARAM;
-	
-	// Remove tile from hash lookup.
-	const int h = computeTileHash(tile->header->tx,tile->header->ty,m_tileLutMask);
-	dtCompressedTile* prev = 0;
-	dtCompressedTile* cur = m_posLookup[h];
-	while (cur)
-	{
-		if (cur == tile)
-		{
-			if (prev)
-				prev->next = cur->next;
-			else
-				m_posLookup[h] = cur->next;
-			break;
-		}
-		prev = cur;
-		cur = cur->next;
-	}
-	
-	// Reset tile.
-	if (tile->flags & DT_COMPRESSEDTILE_FREE_DATA)
-	{
-		// Owns data
-		dtFree(tile->data);
-		tile->data = 0;
-		tile->dataSize = 0;
-		if (data) *data = 0;
-		if (dataSize) *dataSize = 0;
-	}
-	else
-	{
-		if (data) *data = tile->data;
-		if (dataSize) *dataSize = tile->dataSize;
-	}
-	
-	tile->header = 0;
-	tile->data = 0;
-	tile->dataSize = 0;
-	tile->compressed = 0;
-	tile->compressedSize = 0;
-	tile->flags = 0;
-	
-	// Update salt, salt should never be zero.
-	tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
-	if (tile->salt == 0)
-		tile->salt++;
-	
-	// Add to free list.
-	tile->next = m_nextFreeTile;
-	m_nextFreeTile = tile;
-	
-	return DT_SUCCESS;
-}
-
-
-dtStatus dtTileCache::addObstacle(const float* pos, const float radius, const float height, dtObstacleRef* result)
-{
-	if (m_nreqs >= MAX_REQUESTS)
-		return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-	
-	dtTileCacheObstacle* ob = 0;
-	if (m_nextFreeObstacle)
-	{
-		ob = m_nextFreeObstacle;
-		m_nextFreeObstacle = ob->next;
-		ob->next = 0;
-	}
-	if (!ob)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	
-	unsigned short salt = ob->salt;
-	memset(ob, 0, sizeof(dtTileCacheObstacle));
-	ob->salt = salt;
-	ob->state = DT_OBSTACLE_PROCESSING;
-	ob->type = DT_OBSTACLE_CYLINDER;
-	dtVcopy(ob->cylinder.pos, pos);
-	ob->cylinder.radius = radius;
-	ob->cylinder.height = height;
-	
-	ObstacleRequest* req = &m_reqs[m_nreqs++];
-	memset(req, 0, sizeof(ObstacleRequest));
-	req->action = REQUEST_ADD;
-	req->ref = getObstacleRef(ob);
-	
-	if (result)
-		*result = req->ref;
-	
-	return DT_SUCCESS;
-}
-
-dtStatus dtTileCache::addBoxObstacle(const float* bmin, const float* bmax, dtObstacleRef* result)
-{
-	if (m_nreqs >= MAX_REQUESTS)
-		return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-	
-	dtTileCacheObstacle* ob = 0;
-	if (m_nextFreeObstacle)
-	{
-		ob = m_nextFreeObstacle;
-		m_nextFreeObstacle = ob->next;
-		ob->next = 0;
-	}
-	if (!ob)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	
-	unsigned short salt = ob->salt;
-	memset(ob, 0, sizeof(dtTileCacheObstacle));
-	ob->salt = salt;
-	ob->state = DT_OBSTACLE_PROCESSING;
-	ob->type = DT_OBSTACLE_BOX;
-	dtVcopy(ob->box.bmin, bmin);
-	dtVcopy(ob->box.bmax, bmax);
-	
-	ObstacleRequest* req = &m_reqs[m_nreqs++];
-	memset(req, 0, sizeof(ObstacleRequest));
-	req->action = REQUEST_ADD;
-	req->ref = getObstacleRef(ob);
-	
-	if (result)
-		*result = req->ref;
-	
-	return DT_SUCCESS;
-}
-
-dtStatus dtTileCache::addBoxObstacle(const float* center, const float* halfExtents, const float yRadians, dtObstacleRef* result)
-{
-	if (m_nreqs >= MAX_REQUESTS)
-		return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-
-	dtTileCacheObstacle* ob = 0;
-	if (m_nextFreeObstacle)
-	{
-		ob = m_nextFreeObstacle;
-		m_nextFreeObstacle = ob->next;
-		ob->next = 0;
-	}
-	if (!ob)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-
-	unsigned short salt = ob->salt;
-	memset(ob, 0, sizeof(dtTileCacheObstacle));
-	ob->salt = salt;
-	ob->state = DT_OBSTACLE_PROCESSING;
-	ob->type = DT_OBSTACLE_ORIENTED_BOX;
-	dtVcopy(ob->orientedBox.center, center);
-	dtVcopy(ob->orientedBox.halfExtents, halfExtents);
-
-	float coshalf= cosf(0.5f*yRadians);
-	float sinhalf = sinf(-0.5f*yRadians);
-	ob->orientedBox.rotAux[0] = coshalf*sinhalf;
-	ob->orientedBox.rotAux[1] = coshalf*coshalf - 0.5f;
-
-	ObstacleRequest* req = &m_reqs[m_nreqs++];
-	memset(req, 0, sizeof(ObstacleRequest));
-	req->action = REQUEST_ADD;
-	req->ref = getObstacleRef(ob);
-
-	if (result)
-		*result = req->ref;
-
-	return DT_SUCCESS;
-}
-
-dtStatus dtTileCache::removeObstacle(const dtObstacleRef ref)
-{
-	if (!ref)
-		return DT_SUCCESS;
-	if (m_nreqs >= MAX_REQUESTS)
-		return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-	
-	ObstacleRequest* req = &m_reqs[m_nreqs++];
-	memset(req, 0, sizeof(ObstacleRequest));
-	req->action = REQUEST_REMOVE;
-	req->ref = ref;
-	
-	return DT_SUCCESS;
-}
-
-dtStatus dtTileCache::queryTiles(const float* bmin, const float* bmax,
-								 dtCompressedTileRef* results, int* resultCount, const int maxResults) const 
-{
-	const int MAX_TILES = 32;
-	dtCompressedTileRef tiles[MAX_TILES];
-	
-	int n = 0;
-	
-	const float tw = m_params.width * m_params.cs;
-	const float th = m_params.height * m_params.cs;
-	const int tx0 = (int)dtMathFloorf((bmin[0]-m_params.orig[0]) / tw);
-	const int tx1 = (int)dtMathFloorf((bmax[0]-m_params.orig[0]) / tw);
-	const int ty0 = (int)dtMathFloorf((bmin[2]-m_params.orig[2]) / th);
-	const int ty1 = (int)dtMathFloorf((bmax[2]-m_params.orig[2]) / th);
-	
-	for (int ty = ty0; ty <= ty1; ++ty)
-	{
-		for (int tx = tx0; tx <= tx1; ++tx)
-		{
-			const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
-			
-			for (int i = 0; i < ntiles; ++i)
-			{
-				const dtCompressedTile* tile = &m_tiles[decodeTileIdTile(tiles[i])];
-				float tbmin[3], tbmax[3];
-				calcTightTileBounds(tile->header, tbmin, tbmax);
-				
-				if (dtOverlapBounds(bmin,bmax, tbmin,tbmax))
-				{
-					if (n < maxResults)
-						results[n++] = tiles[i];
-				}
-			}
-		}
-	}
-	
-	*resultCount = n;
-	
-	return DT_SUCCESS;
-}
-
-dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh,
-							 bool* upToDate)
-{
-	if (m_nupdate == 0)
-	{
-		// Process requests.
-		for (int i = 0; i < m_nreqs; ++i)
-		{
-			ObstacleRequest* req = &m_reqs[i];
-			
-			unsigned int idx = decodeObstacleIdObstacle(req->ref);
-			if ((int)idx >= m_params.maxObstacles)
-				continue;
-			dtTileCacheObstacle* ob = &m_obstacles[idx];
-			unsigned int salt = decodeObstacleIdSalt(req->ref);
-			if (ob->salt != salt)
-				continue;
-			
-			if (req->action == REQUEST_ADD)
-			{
-				// Find touched tiles.
-				float bmin[3], bmax[3];
-				getObstacleBounds(ob, bmin, bmax);
-
-				int ntouched = 0;
-				queryTiles(bmin, bmax, ob->touched, &ntouched, DT_MAX_TOUCHED_TILES);
-				ob->ntouched = (unsigned char)ntouched;
-				// Add tiles to update list.
-				ob->npending = 0;
-				for (int j = 0; j < ob->ntouched; ++j)
-				{
-					if (m_nupdate < MAX_UPDATE)
-					{
-						if (!contains(m_update, m_nupdate, ob->touched[j]))
-							m_update[m_nupdate++] = ob->touched[j];
-						ob->pending[ob->npending++] = ob->touched[j];
-					}
-				}
-			}
-			else if (req->action == REQUEST_REMOVE)
-			{
-				// Prepare to remove obstacle.
-				ob->state = DT_OBSTACLE_REMOVING;
-				// Add tiles to update list.
-				ob->npending = 0;
-				for (int j = 0; j < ob->ntouched; ++j)
-				{
-					if (m_nupdate < MAX_UPDATE)
-					{
-						if (!contains(m_update, m_nupdate, ob->touched[j]))
-							m_update[m_nupdate++] = ob->touched[j];
-						ob->pending[ob->npending++] = ob->touched[j];
-					}
-				}
-			}
-		}
-		
-		m_nreqs = 0;
-	}
-	
-	dtStatus status = DT_SUCCESS;
-	// Process updates
-	if (m_nupdate)
-	{
-		// Build mesh
-		const dtCompressedTileRef ref = m_update[0];
-		status = buildNavMeshTile(ref, navmesh);
-		m_nupdate--;
-		if (m_nupdate > 0)
-			memmove(m_update, m_update+1, m_nupdate*sizeof(dtCompressedTileRef));
-
-		// Update obstacle states.
-		for (int i = 0; i < m_params.maxObstacles; ++i)
-		{
-			dtTileCacheObstacle* ob = &m_obstacles[i];
-			if (ob->state == DT_OBSTACLE_PROCESSING || ob->state == DT_OBSTACLE_REMOVING)
-			{
-				// Remove handled tile from pending list.
-				for (int j = 0; j < (int)ob->npending; j++)
-				{
-					if (ob->pending[j] == ref)
-					{
-						ob->pending[j] = ob->pending[(int)ob->npending-1];
-						ob->npending--;
-						break;
-					}
-				}
-				
-				// If all pending tiles processed, change state.
-				if (ob->npending == 0)
-				{
-					if (ob->state == DT_OBSTACLE_PROCESSING)
-					{
-						ob->state = DT_OBSTACLE_PROCESSED;
-					}
-					else if (ob->state == DT_OBSTACLE_REMOVING)
-					{
-						ob->state = DT_OBSTACLE_EMPTY;
-						// Update salt, salt should never be zero.
-						ob->salt = (ob->salt+1) & ((1<<16)-1);
-						if (ob->salt == 0)
-							ob->salt++;
-						// Return obstacle to free list.
-						ob->next = m_nextFreeObstacle;
-						m_nextFreeObstacle = ob;
-					}
-				}
-			}
-		}
-	}
-	
-	if (upToDate)
-		*upToDate = m_nupdate == 0 && m_nreqs == 0;
-
-	return status;
-}
-
-
-dtStatus dtTileCache::buildNavMeshTilesAt(const int tx, const int ty, dtNavMesh* navmesh)
-{
-	const int MAX_TILES = 32;
-	dtCompressedTileRef tiles[MAX_TILES];
-	const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
-	
-	for (int i = 0; i < ntiles; ++i)
-	{
-		dtStatus status = buildNavMeshTile(tiles[i], navmesh);
-		if (dtStatusFailed(status))
-			return status;
-	}
-	
-	return DT_SUCCESS;
-}
-
-dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh* navmesh)
-{	
-	dtAssert(m_talloc);
-	dtAssert(m_tcomp);
-	
-	unsigned int idx = decodeTileIdTile(ref);
-	if (idx > (unsigned int)m_params.maxTiles)
-		return DT_FAILURE | DT_INVALID_PARAM;
-	const dtCompressedTile* tile = &m_tiles[idx];
-	unsigned int salt = decodeTileIdSalt(ref);
-	if (tile->salt != salt)
-		return DT_FAILURE | DT_INVALID_PARAM;
-	
-	m_talloc->reset();
-	
-	NavMeshTileBuildContext bc(m_talloc);
-	const int walkableClimbVx = (int)(m_params.walkableClimb / m_params.ch);
-	dtStatus status;
-	
-	// Decompress tile layer data. 
-	status = dtDecompressTileCacheLayer(m_talloc, m_tcomp, tile->data, tile->dataSize, &bc.layer);
-	if (dtStatusFailed(status))
-		return status;
-	
-	// Rasterize obstacles.
-	for (int i = 0; i < m_params.maxObstacles; ++i)
-	{
-		const dtTileCacheObstacle* ob = &m_obstacles[i];
-		if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
-			continue;
-		if (contains(ob->touched, ob->ntouched, ref))
-		{
-			if (ob->type == DT_OBSTACLE_CYLINDER)
-			{
-				dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
-							    ob->cylinder.pos, ob->cylinder.radius, ob->cylinder.height, 0);
-			}
-			else if (ob->type == DT_OBSTACLE_BOX)
-			{
-				dtMarkBoxArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
-					ob->box.bmin, ob->box.bmax, 0);
-			}
-			else if (ob->type == DT_OBSTACLE_ORIENTED_BOX)
-			{
-				dtMarkBoxArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
-					ob->orientedBox.center, ob->orientedBox.halfExtents, ob->orientedBox.rotAux, 0);
-			}
-		}
-	}
-	
-	// Build navmesh
-	status = dtBuildTileCacheRegions(m_talloc, *bc.layer, walkableClimbVx);
-	if (dtStatusFailed(status))
-		return status;
-	
-	bc.lcset = dtAllocTileCacheContourSet(m_talloc);
-	if (!bc.lcset)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	status = dtBuildTileCacheContours(m_talloc, *bc.layer, walkableClimbVx,
-									  m_params.maxSimplificationError, *bc.lcset);
-	if (dtStatusFailed(status))
-		return status;
-	
-	bc.lmesh = dtAllocTileCachePolyMesh(m_talloc);
-	if (!bc.lmesh)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	status = dtBuildTileCachePolyMesh(m_talloc, *bc.lcset, *bc.lmesh);
-	if (dtStatusFailed(status))
-		return status;
-	
-	// Early out if the mesh tile is empty.
-	if (!bc.lmesh->npolys)
-	{
-		// Remove existing tile.
-		navmesh->removeTile(navmesh->getTileRefAt(tile->header->tx,tile->header->ty,tile->header->tlayer),0,0);
-		return DT_SUCCESS;
-	}
-	
-	dtNavMeshCreateParams params;
-	memset(&params, 0, sizeof(params));
-	params.verts = bc.lmesh->verts;
-	params.vertCount = bc.lmesh->nverts;
-	params.polys = bc.lmesh->polys;
-	params.polyAreas = bc.lmesh->areas;
-	params.polyFlags = bc.lmesh->flags;
-	params.polyCount = bc.lmesh->npolys;
-	params.nvp = DT_VERTS_PER_POLYGON;
-	params.walkableHeight = m_params.walkableHeight;
-	params.walkableRadius = m_params.walkableRadius;
-	params.walkableClimb = m_params.walkableClimb;
-	params.tileX = tile->header->tx;
-	params.tileY = tile->header->ty;
-	params.tileLayer = tile->header->tlayer;
-	params.cs = m_params.cs;
-	params.ch = m_params.ch;
-	params.buildBvTree = false;
-	dtVcopy(params.bmin, tile->header->bmin);
-	dtVcopy(params.bmax, tile->header->bmax);
-	
-	if (m_tmproc)
-	{
-		m_tmproc->process(&params, bc.lmesh->areas, bc.lmesh->flags);
-	}
-	
-	unsigned char* navData = 0;
-	int navDataSize = 0;
-	if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
-		return DT_FAILURE;
-
-	// Remove existing tile.
-	navmesh->removeTile(navmesh->getTileRefAt(tile->header->tx,tile->header->ty,tile->header->tlayer),0,0);
-
-	// Add new tile, or leave the location empty.
-	if (navData)
-	{
-		// Let the navmesh own the data.
-		status = navmesh->addTile(navData,navDataSize,DT_TILE_FREE_DATA,0,0);
-		if (dtStatusFailed(status))
-		{
-			dtFree(navData);
-			return status;
-		}
-	}
-	
-	return DT_SUCCESS;
-}
-
-void dtTileCache::calcTightTileBounds(const dtTileCacheLayerHeader* header, float* bmin, float* bmax) const
-{
-	const float cs = m_params.cs;
-	bmin[0] = header->bmin[0] + header->minx*cs;
-	bmin[1] = header->bmin[1];
-	bmin[2] = header->bmin[2] + header->miny*cs;
-	bmax[0] = header->bmin[0] + (header->maxx+1)*cs;
-	bmax[1] = header->bmax[1];
-	bmax[2] = header->bmin[2] + (header->maxy+1)*cs;
-}
-
-void dtTileCache::getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const
-{
-	if (ob->type == DT_OBSTACLE_CYLINDER)
-	{
-		const dtObstacleCylinder &cl = ob->cylinder;
-
-		bmin[0] = cl.pos[0] - cl.radius;
-		bmin[1] = cl.pos[1];
-		bmin[2] = cl.pos[2] - cl.radius;
-		bmax[0] = cl.pos[0] + cl.radius;
-		bmax[1] = cl.pos[1] + cl.height;
-		bmax[2] = cl.pos[2] + cl.radius;
-	}
-	else if (ob->type == DT_OBSTACLE_BOX)
-	{
-		dtVcopy(bmin, ob->box.bmin);
-		dtVcopy(bmax, ob->box.bmax);
-	}
-	else if (ob->type == DT_OBSTACLE_ORIENTED_BOX)
-	{
-		const dtObstacleOrientedBox &orientedBox = ob->orientedBox;
-
-		float maxr = 1.41f*dtMax(orientedBox.halfExtents[0], orientedBox.halfExtents[2]);
-		bmin[0] = orientedBox.center[0] - maxr;
-		bmax[0] = orientedBox.center[0] + maxr;
-		bmin[1] = orientedBox.center[1] - orientedBox.halfExtents[1];
-		bmax[1] = orientedBox.center[1] + orientedBox.halfExtents[1];
-		bmin[2] = orientedBox.center[2] - maxr;
-		bmax[2] = orientedBox.center[2] + maxr;
-	}
-}

+ 0 - 262
panda/src/recastdetour/DetourTileCache.h

@@ -1,262 +0,0 @@
-#ifndef DETOURTILECACHE_H
-#define DETOURTILECACHE_H
-
-#include "DetourStatus.h"
-
-
-
-typedef unsigned int dtObstacleRef;
-
-typedef unsigned int dtCompressedTileRef;
-
-/// Flags for addTile
-enum dtCompressedTileFlags
-{
-	DT_COMPRESSEDTILE_FREE_DATA = 0x01,					///< Navmesh owns the tile memory and should free it.
-};
-
-struct dtCompressedTile
-{
-	unsigned int salt;						///< Counter describing modifications to the tile.
-	struct dtTileCacheLayerHeader* header;
-	unsigned char* compressed;
-	int compressedSize;
-	unsigned char* data;
-	int dataSize;
-	unsigned int flags;
-	dtCompressedTile* next;
-};
-
-enum ObstacleState
-{
-	DT_OBSTACLE_EMPTY,
-	DT_OBSTACLE_PROCESSING,
-	DT_OBSTACLE_PROCESSED,
-	DT_OBSTACLE_REMOVING,
-};
-
-enum ObstacleType
-{
-	DT_OBSTACLE_CYLINDER,
-	DT_OBSTACLE_BOX, // AABB
-	DT_OBSTACLE_ORIENTED_BOX, // OBB
-};
-
-struct dtObstacleCylinder
-{
-	float pos[ 3 ];
-	float radius;
-	float height;
-};
-
-struct dtObstacleBox
-{
-	float bmin[ 3 ];
-	float bmax[ 3 ];
-};
-
-struct dtObstacleOrientedBox
-{
-	float center[ 3 ];
-	float halfExtents[ 3 ];
-	float rotAux[ 2 ]; //{ cos(0.5f*angle)*sin(-0.5f*angle); cos(0.5f*angle)*cos(0.5f*angle) - 0.5 }
-};
-
-static const int DT_MAX_TOUCHED_TILES = 8;
-struct dtTileCacheObstacle
-{
-	union
-	{
-		dtObstacleCylinder cylinder;
-		dtObstacleBox box;
-		dtObstacleOrientedBox orientedBox;
-	};
-
-	dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES];
-	dtCompressedTileRef pending[DT_MAX_TOUCHED_TILES];
-	unsigned short salt;
-	unsigned char type;
-	unsigned char state;
-	unsigned char ntouched;
-	unsigned char npending;
-	dtTileCacheObstacle* next;
-};
-
-struct dtTileCacheParams
-{
-	float orig[3];
-	float cs, ch;
-	int width, height;
-	float walkableHeight;
-	float walkableRadius;
-	float walkableClimb;
-	float maxSimplificationError;
-	int maxTiles;
-	int maxObstacles;
-};
-
-struct dtTileCacheMeshProcess
-{
-	virtual ~dtTileCacheMeshProcess() { }
-
-	virtual void process(struct dtNavMeshCreateParams* params,
-						 unsigned char* polyAreas, unsigned short* polyFlags) = 0;
-};
-
-
-class dtTileCache
-{
-public:
-	dtTileCache();
-	~dtTileCache();
-	
-	struct dtTileCacheAlloc* getAlloc() { return m_talloc; }
-	struct dtTileCacheCompressor* getCompressor() { return m_tcomp; }
-	const dtTileCacheParams* getParams() const { return &m_params; }
-	
-	inline int getTileCount() const { return m_params.maxTiles; }
-	inline const dtCompressedTile* getTile(const int i) const { return &m_tiles[i]; }
-	
-	inline int getObstacleCount() const { return m_params.maxObstacles; }
-	inline const dtTileCacheObstacle* getObstacle(const int i) const { return &m_obstacles[i]; }
-	
-	const dtTileCacheObstacle* getObstacleByRef(dtObstacleRef ref);
-	
-	dtObstacleRef getObstacleRef(const dtTileCacheObstacle* obmin) const;
-	
-	dtStatus init(const dtTileCacheParams* params,
-				  struct dtTileCacheAlloc* talloc,
-				  struct dtTileCacheCompressor* tcomp,
-				  struct dtTileCacheMeshProcess* tmproc);
-	
-	int getTilesAt(const int tx, const int ty, dtCompressedTileRef* tiles, const int maxTiles) const ;
-	
-	dtCompressedTile* getTileAt(const int tx, const int ty, const int tlayer);
-	dtCompressedTileRef getTileRef(const dtCompressedTile* tile) const;
-	const dtCompressedTile* getTileByRef(dtCompressedTileRef ref) const;
-	
-	dtStatus addTile(unsigned char* data, const int dataSize, unsigned char flags, dtCompressedTileRef* result);
-	
-	dtStatus removeTile(dtCompressedTileRef ref, unsigned char** data, int* dataSize);
-	
-	// Cylinder obstacle.
-	dtStatus addObstacle(const float* pos, const float radius, const float height, dtObstacleRef* result);
-
-	// Aabb obstacle.
-	dtStatus addBoxObstacle(const float* bmin, const float* bmax, dtObstacleRef* result);
-
-	// Box obstacle: can be rotated in Y.
-	dtStatus addBoxObstacle(const float* center, const float* halfExtents, const float yRadians, dtObstacleRef* result);
-	
-	dtStatus removeObstacle(const dtObstacleRef ref);
-	
-	dtStatus queryTiles(const float* bmin, const float* bmax,
-						dtCompressedTileRef* results, int* resultCount, const int maxResults) const;
-	
-	/// Updates the tile cache by rebuilding tiles touched by unfinished obstacle requests.
-	///  @param[in]		dt			The time step size. Currently not used.
-	///  @param[in]		navmesh		The mesh to affect when rebuilding tiles.
-	///  @param[out]	upToDate	Whether the tile cache is fully up to date with obstacle requests and tile rebuilds.
-	///  							If the tile cache is up to date another (immediate) call to update will have no effect;
-	///  							otherwise another call will continue processing obstacle requests and tile rebuilds.
-	dtStatus update(const float dt, class dtNavMesh* navmesh, bool* upToDate = 0);
-	
-	dtStatus buildNavMeshTilesAt(const int tx, const int ty, class dtNavMesh* navmesh);
-	
-	dtStatus buildNavMeshTile(const dtCompressedTileRef ref, class dtNavMesh* navmesh);
-	
-	void calcTightTileBounds(const struct dtTileCacheLayerHeader* header, float* bmin, float* bmax) const;
-	
-	void getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const;
-	
-
-	/// Encodes a tile id.
-	inline dtCompressedTileRef encodeTileId(unsigned int salt, unsigned int it) const
-	{
-		return ((dtCompressedTileRef)salt << m_tileBits) | (dtCompressedTileRef)it;
-	}
-	
-	/// Decodes a tile salt.
-	inline unsigned int decodeTileIdSalt(dtCompressedTileRef ref) const
-	{
-		const dtCompressedTileRef saltMask = ((dtCompressedTileRef)1<<m_saltBits)-1;
-		return (unsigned int)((ref >> m_tileBits) & saltMask);
-	}
-	
-	/// Decodes a tile id.
-	inline unsigned int decodeTileIdTile(dtCompressedTileRef ref) const
-	{
-		const dtCompressedTileRef tileMask = ((dtCompressedTileRef)1<<m_tileBits)-1;
-		return (unsigned int)(ref & tileMask);
-	}
-
-	/// Encodes an obstacle id.
-	inline dtObstacleRef encodeObstacleId(unsigned int salt, unsigned int it) const
-	{
-		return ((dtObstacleRef)salt << 16) | (dtObstacleRef)it;
-	}
-	
-	/// Decodes an obstacle salt.
-	inline unsigned int decodeObstacleIdSalt(dtObstacleRef ref) const
-	{
-		const dtObstacleRef saltMask = ((dtObstacleRef)1<<16)-1;
-		return (unsigned int)((ref >> 16) & saltMask);
-	}
-	
-	/// Decodes an obstacle id.
-	inline unsigned int decodeObstacleIdObstacle(dtObstacleRef ref) const
-	{
-		const dtObstacleRef tileMask = ((dtObstacleRef)1<<16)-1;
-		return (unsigned int)(ref & tileMask);
-	}
-	
-	
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	dtTileCache(const dtTileCache&);
-	dtTileCache& operator=(const dtTileCache&);
-
-	enum ObstacleRequestAction
-	{
-		REQUEST_ADD,
-		REQUEST_REMOVE,
-	};
-	
-	struct ObstacleRequest
-	{
-		int action;
-		dtObstacleRef ref;
-	};
-	
-	int m_tileLutSize;						///< Tile hash lookup size (must be pot).
-	int m_tileLutMask;						///< Tile hash lookup mask.
-	
-	dtCompressedTile** m_posLookup;			///< Tile hash lookup.
-	dtCompressedTile* m_nextFreeTile;		///< Freelist of tiles.
-	dtCompressedTile* m_tiles;				///< List of tiles.
-	
-	unsigned int m_saltBits;				///< Number of salt bits in the tile ID.
-	unsigned int m_tileBits;				///< Number of tile bits in the tile ID.
-	
-	dtTileCacheParams m_params;
-	
-	dtTileCacheAlloc* m_talloc;
-	dtTileCacheCompressor* m_tcomp;
-	dtTileCacheMeshProcess* m_tmproc;
-	
-	dtTileCacheObstacle* m_obstacles;
-	dtTileCacheObstacle* m_nextFreeObstacle;
-	
-	static const int MAX_REQUESTS = 64;
-	ObstacleRequest m_reqs[MAX_REQUESTS];
-	int m_nreqs;
-	
-	static const int MAX_UPDATE = 64;
-	dtCompressedTileRef m_update[MAX_UPDATE];
-	int m_nupdate;
-};
-
-dtTileCache* dtAllocTileCache();
-void dtFreeTileCache(dtTileCache* tc);
-
-#endif

+ 0 - 2250
panda/src/recastdetour/DetourTileCacheBuilder.cpp

@@ -1,2250 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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.
-//
-
-#include "DetourCommon.h"
-#include "DetourMath.h"
-#include "DetourStatus.h"
-#include "DetourAssert.h"
-#include "DetourTileCacheBuilder.h"
-#include <string.h>
-
-
-template<class T> class dtFixedArray
-{
-	dtTileCacheAlloc* m_alloc;
-	T* m_ptr;
-	const int m_size;
-	inline void operator=(dtFixedArray<T>& p);
-public:
-	inline dtFixedArray(dtTileCacheAlloc* a, const int s) : m_alloc(a), m_ptr((T*)a->alloc(sizeof(T)*s)), m_size(s) {}
-	inline ~dtFixedArray() { if (m_alloc) m_alloc->free(m_ptr); }
-	inline operator T*() { return m_ptr; }
-	inline int size() const { return m_size; }
-};
-
-inline int getDirOffsetX(int dir)
-{
-	const int offset[4] = { -1, 0, 1, 0, };
-	return offset[dir&0x03];
-}
-
-inline int getDirOffsetY(int dir)
-{
-	const int offset[4] = { 0, 1, 0, -1 };
-	return offset[dir&0x03];
-}
-
-static const int MAX_VERTS_PER_POLY = 6;	// TODO: use the DT_VERTS_PER_POLYGON
-static const int MAX_REM_EDGES = 48;		// TODO: make this an expression.
-
-
-
-dtTileCacheContourSet* dtAllocTileCacheContourSet(dtTileCacheAlloc* alloc)
-{
-	dtAssert(alloc);
-
-	dtTileCacheContourSet* cset = (dtTileCacheContourSet*)alloc->alloc(sizeof(dtTileCacheContourSet));
-	memset(cset, 0, sizeof(dtTileCacheContourSet));
-	return cset;
-}
-
-void dtFreeTileCacheContourSet(dtTileCacheAlloc* alloc, dtTileCacheContourSet* cset)
-{
-	dtAssert(alloc);
-
-	if (!cset) return;
-	for (int i = 0; i < cset->nconts; ++i)
-		alloc->free(cset->conts[i].verts);
-	alloc->free(cset->conts);
-	alloc->free(cset);
-}
-
-dtTileCachePolyMesh* dtAllocTileCachePolyMesh(dtTileCacheAlloc* alloc)
-{
-	dtAssert(alloc);
-
-	dtTileCachePolyMesh* lmesh = (dtTileCachePolyMesh*)alloc->alloc(sizeof(dtTileCachePolyMesh));
-	memset(lmesh, 0, sizeof(dtTileCachePolyMesh));
-	return lmesh;
-}
-
-void dtFreeTileCachePolyMesh(dtTileCacheAlloc* alloc, dtTileCachePolyMesh* lmesh)
-{
-	dtAssert(alloc);
-	
-	if (!lmesh) return;
-	alloc->free(lmesh->verts);
-	alloc->free(lmesh->polys);
-	alloc->free(lmesh->flags);
-	alloc->free(lmesh->areas);
-	alloc->free(lmesh);
-}
-
-
-
-struct dtLayerSweepSpan
-{
-	unsigned short ns;	// number samples
-	unsigned char id;	// region id
-	unsigned char nei;	// neighbour id
-};
-
-static const int DT_LAYER_MAX_NEIS = 16;
-
-struct dtLayerMonotoneRegion
-{
-	int area;
-	unsigned char neis[DT_LAYER_MAX_NEIS];
-	unsigned char nneis;
-	unsigned char regId;
-	unsigned char areaId;
-};
-
-struct dtTempContour
-{
-	inline dtTempContour(unsigned char* vbuf, const int nvbuf,
-						 unsigned short* pbuf, const int npbuf) :
-		verts(vbuf), nverts(0), cverts(nvbuf),
-		poly(pbuf), npoly(0), cpoly(npbuf) 
-	{
-	}
-	unsigned char* verts;
-	int nverts;
-	int cverts;
-	unsigned short* poly;
-	int npoly;
-	int cpoly;
-};
-
-
-
-
-inline bool overlapRangeExl(const unsigned short amin, const unsigned short amax,
-							const unsigned short bmin, const unsigned short bmax)
-{
-	return (amin >= bmax || amax <= bmin) ? false : true;
-}
-
-static void addUniqueLast(unsigned char* a, unsigned char& an, unsigned char v)
-{
-	const int n = (int)an;
-	if (n > 0 && a[n-1] == v) return;
-	a[an] = v;
-	an++;
-}
-
-inline bool isConnected(const dtTileCacheLayer& layer,
-						const int ia, const int ib, const int walkableClimb)
-{
-	if (layer.areas[ia] != layer.areas[ib]) return false;
-	if (dtAbs((int)layer.heights[ia] - (int)layer.heights[ib]) > walkableClimb) return false;
-	return true;
-}
-
-static bool canMerge(unsigned char oldRegId, unsigned char newRegId, const dtLayerMonotoneRegion* regs, const int nregs)
-{
-	int count = 0;
-	for (int i = 0; i < nregs; ++i)
-	{
-		const dtLayerMonotoneRegion& reg = regs[i];
-		if (reg.regId != oldRegId) continue;
-		const int nnei = (int)reg.nneis;
-		for (int j = 0; j < nnei; ++j)
-		{
-			if (regs[reg.neis[j]].regId == newRegId)
-				count++;
-		}
-	}
-	return count == 1;
-}
-
-
-dtStatus dtBuildTileCacheRegions(dtTileCacheAlloc* alloc,
-								 dtTileCacheLayer& layer,
-								 const int walkableClimb)
-{
-	dtAssert(alloc);
-	
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	
-	memset(layer.regs,0xff,sizeof(unsigned char)*w*h);
-	
-	const int nsweeps = w;
-	dtFixedArray<dtLayerSweepSpan> sweeps(alloc, nsweeps);
-	if (!sweeps)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(sweeps,0,sizeof(dtLayerSweepSpan)*nsweeps);
-	
-	// Partition walkable area into monotone regions.
-	unsigned char prevCount[256];
-	unsigned char regId = 0;
-	
-	for (int y = 0; y < h; ++y)
-	{
-		if (regId > 0)
-			memset(prevCount,0,sizeof(unsigned char)*regId);
-		unsigned char sweepId = 0;
-		
-		for (int x = 0; x < w; ++x)
-		{
-			const int idx = x + y*w;
-			if (layer.areas[idx] == DT_TILECACHE_NULL_AREA) continue;
-			
-			unsigned char sid = 0xff;
-			
-			// -x
-			const int xidx = (x-1)+y*w;
-			if (x > 0 && isConnected(layer, idx, xidx, walkableClimb))
-			{
-				if (layer.regs[xidx] != 0xff)
-					sid = layer.regs[xidx];
-			}
-			
-			if (sid == 0xff)
-			{
-				sid = sweepId++;
-				sweeps[sid].nei = 0xff;
-				sweeps[sid].ns = 0;
-			}
-			
-			// -y
-			const int yidx = x+(y-1)*w;
-			if (y > 0 && isConnected(layer, idx, yidx, walkableClimb))
-			{
-				const unsigned char nr = layer.regs[yidx];
-				if (nr != 0xff)
-				{
-					// Set neighbour when first valid neighbour is encoutered.
-					if (sweeps[sid].ns == 0)
-						sweeps[sid].nei = nr;
-					
-					if (sweeps[sid].nei == nr)
-					{
-						// Update existing neighbour
-						sweeps[sid].ns++;
-						prevCount[nr]++;
-					}
-					else
-					{
-						// This is hit if there is nore than one neighbour.
-						// Invalidate the neighbour.
-						sweeps[sid].nei = 0xff;
-					}
-				}
-			}
-			
-			layer.regs[idx] = sid;
-		}
-		
-		// Create unique ID.
-		for (int i = 0; i < sweepId; ++i)
-		{
-			// If the neighbour is set and there is only one continuous connection to it,
-			// the sweep will be merged with the previous one, else new region is created.
-			if (sweeps[i].nei != 0xff && (unsigned short)prevCount[sweeps[i].nei] == sweeps[i].ns)
-			{
-				sweeps[i].id = sweeps[i].nei;
-			}
-			else
-			{
-				if (regId == 255)
-				{
-					// Region ID's overflow.
-					return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-				}
-				sweeps[i].id = regId++;
-			}
-		}
-		
-		// Remap local sweep ids to region ids.
-		for (int x = 0; x < w; ++x)
-		{
-			const int idx = x+y*w;
-			if (layer.regs[idx] != 0xff)
-				layer.regs[idx] = sweeps[layer.regs[idx]].id;
-		}
-	}
-	
-	// Allocate and init layer regions.
-	const int nregs = (int)regId;
-	dtFixedArray<dtLayerMonotoneRegion> regs(alloc, nregs);
-	if (!regs)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-
-	memset(regs, 0, sizeof(dtLayerMonotoneRegion)*nregs);
-	for (int i = 0; i < nregs; ++i)
-		regs[i].regId = 0xff;
-	
-	// Find region neighbours.
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			const int idx = x+y*w;
-			const unsigned char ri = layer.regs[idx];
-			if (ri == 0xff)
-				continue;
-			
-			// Update area.
-			regs[ri].area++;
-			regs[ri].areaId = layer.areas[idx];
-			
-			// Update neighbours
-			const int ymi = x+(y-1)*w;
-			if (y > 0 && isConnected(layer, idx, ymi, walkableClimb))
-			{
-				const unsigned char rai = layer.regs[ymi];
-				if (rai != 0xff && rai != ri)
-				{
-					addUniqueLast(regs[ri].neis, regs[ri].nneis, rai);
-					addUniqueLast(regs[rai].neis, regs[rai].nneis, ri);
-				}
-			}
-		}
-	}
-	
-	for (int i = 0; i < nregs; ++i)
-		regs[i].regId = (unsigned char)i;
-	
-	for (int i = 0; i < nregs; ++i)
-	{
-		dtLayerMonotoneRegion& reg = regs[i];
-		
-		int merge = -1;
-		int mergea = 0;
-		for (int j = 0; j < (int)reg.nneis; ++j)
-		{
-			const unsigned char nei = reg.neis[j];
-			dtLayerMonotoneRegion& regn = regs[nei];
-			if (reg.regId == regn.regId)
-				continue;
-			if (reg.areaId != regn.areaId)
-				continue;
-			if (regn.area > mergea)
-			{
-				if (canMerge(reg.regId, regn.regId, regs, nregs))
-				{
-					mergea = regn.area;
-					merge = (int)nei;
-				}
-			}
-		}
-		if (merge != -1)
-		{
-			const unsigned char oldId = reg.regId;
-			const unsigned char newId = regs[merge].regId;
-			for (int j = 0; j < nregs; ++j)
-				if (regs[j].regId == oldId)
-					regs[j].regId = newId;
-		}
-	}
-	
-	// Compact ids.
-	unsigned char remap[256];
-	memset(remap, 0, 256);
-	// Find number of unique regions.
-	regId = 0;
-	for (int i = 0; i < nregs; ++i)
-		remap[regs[i].regId] = 1;
-	for (int i = 0; i < 256; ++i)
-		if (remap[i])
-			remap[i] = regId++;
-	// Remap ids.
-	for (int i = 0; i < nregs; ++i)
-		regs[i].regId = remap[regs[i].regId];
-	
-	layer.regCount = regId;
-	
-	for (int i = 0; i < w*h; ++i)
-	{
-		if (layer.regs[i] != 0xff)
-			layer.regs[i] = regs[layer.regs[i]].regId;
-	}
-	
-	return DT_SUCCESS;
-}
-
-
-
-static bool appendVertex(dtTempContour& cont, const int x, const int y, const int z, const int r)
-{
-	// Try to merge with existing segments.
-	if (cont.nverts > 1)
-	{
-		unsigned char* pa = &cont.verts[(cont.nverts-2)*4];
-		unsigned char* pb = &cont.verts[(cont.nverts-1)*4];
-		if ((int)pb[3] == r)
-		{
-			if (pa[0] == pb[0] && (int)pb[0] == x)
-			{
-				// The verts are aligned aling x-axis, update z.
-				pb[1] = (unsigned char)y;
-				pb[2] = (unsigned char)z;
-				return true;
-			}
-			else if (pa[2] == pb[2] && (int)pb[2] == z)
-			{
-				// The verts are aligned aling z-axis, update x.
-				pb[0] = (unsigned char)x;
-				pb[1] = (unsigned char)y;
-				return true;
-			}
-		}
-	}
-	
-	// Add new point.
-	if (cont.nverts+1 > cont.cverts)
-		return false;
-	
-	unsigned char* v = &cont.verts[cont.nverts*4];
-	v[0] = (unsigned char)x;
-	v[1] = (unsigned char)y;
-	v[2] = (unsigned char)z;
-	v[3] = (unsigned char)r;
-	cont.nverts++;
-	
-	return true;
-}
-
-
-static unsigned char getNeighbourReg(dtTileCacheLayer& layer,
-									 const int ax, const int ay, const int dir)
-{
-	const int w = (int)layer.header->width;
-	const int ia = ax + ay*w;
-	
-	const unsigned char con = layer.cons[ia] & 0xf;
-	const unsigned char portal = layer.cons[ia] >> 4;
-	const unsigned char mask = (unsigned char)(1<<dir);
-	
-	if ((con & mask) == 0)
-	{
-		// No connection, return portal or hard edge.
-		if (portal & mask)
-			return 0xf8 + (unsigned char)dir;
-		return 0xff;
-	}
-	
-	const int bx = ax + getDirOffsetX(dir);
-	const int by = ay + getDirOffsetY(dir);
-	const int ib = bx + by*w;
-	
-	return layer.regs[ib];
-}
-
-static bool walkContour(dtTileCacheLayer& layer, int x, int y, dtTempContour& cont)
-{
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	
-	cont.nverts = 0;
-	
-	int startX = x;
-	int startY = y;
-	int startDir = -1;
-	
-	for (int i = 0; i < 4; ++i)
-	{
-		const int dir = (i+3)&3;
-		unsigned char rn = getNeighbourReg(layer, x, y, dir);
-		if (rn != layer.regs[x+y*w])
-		{
-			startDir = dir;
-			break;
-		}
-	}
-	if (startDir == -1)
-		return true;
-	
-	int dir = startDir;
-	const int maxIter = w*h;
-	
-	int iter = 0;
-	while (iter < maxIter)
-	{
-		unsigned char rn = getNeighbourReg(layer, x, y, dir);
-		
-		int nx = x;
-		int ny = y;
-		int ndir = dir;
-		
-		if (rn != layer.regs[x+y*w])
-		{
-			// Solid edge.
-			int px = x;
-			int pz = y;
-			switch(dir)
-			{
-				case 0: pz++; break;
-				case 1: px++; pz++; break;
-				case 2: px++; break;
-			}
-			
-			// Try to merge with previous vertex.
-			if (!appendVertex(cont, px, (int)layer.heights[x+y*w], pz,rn))
-				return false;
-			
-			ndir = (dir+1) & 0x3;  // Rotate CW
-		}
-		else
-		{
-			// Move to next.
-			nx = x + getDirOffsetX(dir);
-			ny = y + getDirOffsetY(dir);
-			ndir = (dir+3) & 0x3;	// Rotate CCW
-		}
-		
-		if (iter > 0 && x == startX && y == startY && dir == startDir)
-			break;
-		
-		x = nx;
-		y = ny;
-		dir = ndir;
-		
-		iter++;
-	}
-	
-	// Remove last vertex if it is duplicate of the first one.
-	unsigned char* pa = &cont.verts[(cont.nverts-1)*4];
-	unsigned char* pb = &cont.verts[0];
-	if (pa[0] == pb[0] && pa[2] == pb[2])
-		cont.nverts--;
-	
-	return true;
-}	
-
-
-static float distancePtSeg(const int x, const int z,
-						   const int px, const int pz,
-						   const int qx, const int qz)
-{
-	float pqx = (float)(qx - px);
-	float pqz = (float)(qz - pz);
-	float dx = (float)(x - px);
-	float dz = (float)(z - pz);
-	float d = pqx*pqx + pqz*pqz;
-	float t = pqx*dx + pqz*dz;
-	if (d > 0)
-		t /= d;
-	if (t < 0)
-		t = 0;
-	else if (t > 1)
-		t = 1;
-	
-	dx = px + t*pqx - x;
-	dz = pz + t*pqz - z;
-	
-	return dx*dx + dz*dz;
-}
-
-static void simplifyContour(dtTempContour& cont, const float maxError)
-{
-	cont.npoly = 0;
-	
-	for (int i = 0; i < cont.nverts; ++i)
-	{
-		int j = (i+1) % cont.nverts;
-		// Check for start of a wall segment.
-		unsigned char ra = cont.verts[j*4+3];
-		unsigned char rb = cont.verts[i*4+3];
-		if (ra != rb)
-			cont.poly[cont.npoly++] = (unsigned short)i;
-	}
-	if (cont.npoly < 2)
-	{
-		// If there is no transitions at all,
-		// create some initial points for the simplification process. 
-		// Find lower-left and upper-right vertices of the contour.
-		int llx = cont.verts[0];
-		int llz = cont.verts[2];
-		int lli = 0;
-		int urx = cont.verts[0];
-		int urz = cont.verts[2];
-		int uri = 0;
-		for (int i = 1; i < cont.nverts; ++i)
-		{
-			int x = cont.verts[i*4+0];
-			int z = cont.verts[i*4+2];
-			if (x < llx || (x == llx && z < llz))
-			{
-				llx = x;
-				llz = z;
-				lli = i;
-			}
-			if (x > urx || (x == urx && z > urz))
-			{
-				urx = x;
-				urz = z;
-				uri = i;
-			}
-		}
-		cont.npoly = 0;
-		cont.poly[cont.npoly++] = (unsigned short)lli;
-		cont.poly[cont.npoly++] = (unsigned short)uri;
-	}
-	
-	// Add points until all raw points are within
-	// error tolerance to the simplified shape.
-	for (int i = 0; i < cont.npoly; )
-	{
-		int ii = (i+1) % cont.npoly;
-		
-		const int ai = (int)cont.poly[i];
-		const int ax = (int)cont.verts[ai*4+0];
-		const int az = (int)cont.verts[ai*4+2];
-		
-		const int bi = (int)cont.poly[ii];
-		const int bx = (int)cont.verts[bi*4+0];
-		const int bz = (int)cont.verts[bi*4+2];
-		
-		// Find maximum deviation from the segment.
-		float maxd = 0;
-		int maxi = -1;
-		int ci, cinc, endi;
-		
-		// Traverse the segment in lexilogical order so that the
-		// max deviation is calculated similarly when traversing
-		// opposite segments.
-		if (bx > ax || (bx == ax && bz > az))
-		{
-			cinc = 1;
-			ci = (ai+cinc) % cont.nverts;
-			endi = bi;
-		}
-		else
-		{
-			cinc = cont.nverts-1;
-			ci = (bi+cinc) % cont.nverts;
-			endi = ai;
-		}
-		
-		// Tessellate only outer edges or edges between areas.
-		while (ci != endi)
-		{
-			float d = distancePtSeg(cont.verts[ci*4+0], cont.verts[ci*4+2], ax, az, bx, bz);
-			if (d > maxd)
-			{
-				maxd = d;
-				maxi = ci;
-			}
-			ci = (ci+cinc) % cont.nverts;
-		}
-		
-		
-		// If the max deviation is larger than accepted error,
-		// add new point, else continue to next segment.
-		if (maxi != -1 && maxd > (maxError*maxError))
-		{
-			cont.npoly++;
-			for (int j = cont.npoly-1; j > i; --j)
-				cont.poly[j] = cont.poly[j-1];
-			cont.poly[i+1] = (unsigned short)maxi;
-		}
-		else
-		{
-			++i;
-		}
-	}
-	
-	// Remap vertices
-	int start = 0;
-	for (int i = 1; i < cont.npoly; ++i)
-		if (cont.poly[i] < cont.poly[start])
-			start = i;
-	
-	cont.nverts = 0;
-	for (int i = 0; i < cont.npoly; ++i)
-	{
-		const int j = (start+i) % cont.npoly;
-		unsigned char* src = &cont.verts[cont.poly[j]*4];
-		unsigned char* dst = &cont.verts[cont.nverts*4];
-		dst[0] = src[0];
-		dst[1] = src[1];
-		dst[2] = src[2];
-		dst[3] = src[3];
-		cont.nverts++;
-	}
-}
-
-static unsigned char getCornerHeight(dtTileCacheLayer& layer,
-									 const int x, const int y, const int z,
-									 const int walkableClimb,
-									 bool& shouldRemove)
-{
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	
-	int n = 0;
-	
-	unsigned char portal = 0xf;
-	unsigned char height = 0;
-	unsigned char preg = 0xff;
-	bool allSameReg = true;
-	
-	for (int dz = -1; dz <= 0; ++dz)
-	{
-		for (int dx = -1; dx <= 0; ++dx)
-		{
-			const int px = x+dx;
-			const int pz = z+dz;
-			if (px >= 0 && pz >= 0 && px < w && pz < h)
-			{
-				const int idx  = px + pz*w;
-				const int lh = (int)layer.heights[idx];
-				if (dtAbs(lh-y) <= walkableClimb && layer.areas[idx] != DT_TILECACHE_NULL_AREA)
-				{
-					height = dtMax(height, (unsigned char)lh);
-					portal &= (layer.cons[idx] >> 4);
-					if (preg != 0xff && preg != layer.regs[idx])
-						allSameReg = false;
-					preg = layer.regs[idx]; 
-					n++;
-				}
-			}
-		}
-	}
-	
-	int portalCount = 0;
-	for (int dir = 0; dir < 4; ++dir)
-		if (portal & (1<<dir))
-			portalCount++;
-	
-	shouldRemove = false;
-	if (n > 1 && portalCount == 1 && allSameReg)
-	{
-		shouldRemove = true;
-	}
-	
-	return height;
-}
-
-
-// TODO: move this somewhere else, once the layer meshing is done.
-dtStatus dtBuildTileCacheContours(dtTileCacheAlloc* alloc,
-								  dtTileCacheLayer& layer,
-								  const int walkableClimb, 	const float maxError,
-								  dtTileCacheContourSet& lcset)
-{
-	dtAssert(alloc);
-
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	
-	lcset.nconts = layer.regCount;
-	lcset.conts = (dtTileCacheContour*)alloc->alloc(sizeof(dtTileCacheContour)*lcset.nconts);
-	if (!lcset.conts)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(lcset.conts, 0, sizeof(dtTileCacheContour)*lcset.nconts);
-	
-	// Allocate temp buffer for contour tracing.
-	const int maxTempVerts = (w+h)*2 * 2; // Twice around the layer.
-	
-	dtFixedArray<unsigned char> tempVerts(alloc, maxTempVerts*4);
-	if (!tempVerts)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	
-	dtFixedArray<unsigned short> tempPoly(alloc, maxTempVerts);
-	if (!tempPoly)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-
-	dtTempContour temp(tempVerts, maxTempVerts, tempPoly, maxTempVerts);
-	
-	// Find contours.
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			const int idx = x+y*w;
-			const unsigned char ri = layer.regs[idx];
-			if (ri == 0xff)
-				continue;
-			
-			dtTileCacheContour& cont = lcset.conts[ri];
-			
-			if (cont.nverts > 0)
-				continue;
-			
-			cont.reg = ri;
-			cont.area = layer.areas[idx];
-			
-			if (!walkContour(layer, x, y, temp))
-			{
-				// Too complex contour.
-				// Note: If you hit here ofte, try increasing 'maxTempVerts'.
-				return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-			}
-			
-			simplifyContour(temp, maxError);
-			
-			// Store contour.
-			cont.nverts = temp.nverts;
-			if (cont.nverts > 0)
-			{
-				cont.verts = (unsigned char*)alloc->alloc(sizeof(unsigned char)*4*temp.nverts);
-				if (!cont.verts)
-					return DT_FAILURE | DT_OUT_OF_MEMORY;
-				
-				for (int i = 0, j = temp.nverts-1; i < temp.nverts; j=i++)
-				{
-					unsigned char* dst = &cont.verts[j*4];
-					unsigned char* v = &temp.verts[j*4];
-					unsigned char* vn = &temp.verts[i*4];
-					unsigned char nei = vn[3]; // The neighbour reg is stored at segment vertex of a segment. 
-					bool shouldRemove = false;
-					unsigned char lh = getCornerHeight(layer, (int)v[0], (int)v[1], (int)v[2],
-													   walkableClimb, shouldRemove);
-					
-					dst[0] = v[0];
-					dst[1] = lh;
-					dst[2] = v[2];
-					
-					// Store portal direction and remove status to the fourth component.
-					dst[3] = 0x0f;
-					if (nei != 0xff && nei >= 0xf8)
-						dst[3] = nei - 0xf8;
-					if (shouldRemove)
-						dst[3] |= 0x80;
-				}
-			}
-		}
-	}
-	
-	return DT_SUCCESS;
-}	
-
-
-
-static const int VERTEX_BUCKET_COUNT2 = (1<<8);
-
-inline int computeVertexHash2(int x, int y, int z)
-{
-	const unsigned int h1 = 0x8da6b343; // Large multiplicative constants;
-	const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes
-	const unsigned int h3 = 0xcb1ab31f;
-	unsigned int n = h1 * x + h2 * y + h3 * z;
-	return (int)(n & (VERTEX_BUCKET_COUNT2-1));
-}
-
-static unsigned short addVertex(unsigned short x, unsigned short y, unsigned short z,
-								unsigned short* verts, unsigned short* firstVert, unsigned short* nextVert, int& nv)
-{
-	int bucket = computeVertexHash2(x, 0, z);
-	unsigned short i = firstVert[bucket];
-	
-	while (i != DT_TILECACHE_NULL_IDX)
-	{
-		const unsigned short* v = &verts[i*3];
-		if (v[0] == x && v[2] == z && (dtAbs(v[1] - y) <= 2))
-			return i;
-		i = nextVert[i]; // next
-	}
-	
-	// Could not find, create new.
-	i = (unsigned short)nv; nv++;
-	unsigned short* v = &verts[i*3];
-	v[0] = x;
-	v[1] = y;
-	v[2] = z;
-	nextVert[i] = firstVert[bucket];
-	firstVert[bucket] = i;
-	
-	return (unsigned short)i;
-}
-
-
-struct rcEdge
-{
-	unsigned short vert[2];
-	unsigned short polyEdge[2];
-	unsigned short poly[2];
-};
-
-static bool buildMeshAdjacency(dtTileCacheAlloc* alloc,
-							   unsigned short* polys, const int npolys,
-							   const unsigned short* verts, const int nverts,
-							   const dtTileCacheContourSet& lcset)
-{
-	// Based on code by Eric Lengyel from:
-	// http://www.terathon.com/code/edges.php
-	
-	const int maxEdgeCount = npolys*MAX_VERTS_PER_POLY;
-	dtFixedArray<unsigned short> firstEdge(alloc, nverts + maxEdgeCount);
-	if (!firstEdge)
-		return false;
-	unsigned short* nextEdge = firstEdge + nverts;
-	int edgeCount = 0;
-	
-	dtFixedArray<rcEdge> edges(alloc, maxEdgeCount);
-	if (!edges)
-		return false;
-	
-	for (int i = 0; i < nverts; i++)
-		firstEdge[i] = DT_TILECACHE_NULL_IDX;
-	
-	for (int i = 0; i < npolys; ++i)
-	{
-		unsigned short* t = &polys[i*MAX_VERTS_PER_POLY*2];
-		for (int j = 0; j < MAX_VERTS_PER_POLY; ++j)
-		{
-			if (t[j] == DT_TILECACHE_NULL_IDX) break;
-			unsigned short v0 = t[j];
-			unsigned short v1 = (j+1 >= MAX_VERTS_PER_POLY || t[j+1] == DT_TILECACHE_NULL_IDX) ? t[0] : t[j+1];
-			if (v0 < v1)
-			{
-				rcEdge& edge = edges[edgeCount];
-				edge.vert[0] = v0;
-				edge.vert[1] = v1;
-				edge.poly[0] = (unsigned short)i;
-				edge.polyEdge[0] = (unsigned short)j;
-				edge.poly[1] = (unsigned short)i;
-				edge.polyEdge[1] = 0xff;
-				// Insert edge
-				nextEdge[edgeCount] = firstEdge[v0];
-				firstEdge[v0] = (unsigned short)edgeCount;
-				edgeCount++;
-			}
-		}
-	}
-	
-	for (int i = 0; i < npolys; ++i)
-	{
-		unsigned short* t = &polys[i*MAX_VERTS_PER_POLY*2];
-		for (int j = 0; j < MAX_VERTS_PER_POLY; ++j)
-		{
-			if (t[j] == DT_TILECACHE_NULL_IDX) break;
-			unsigned short v0 = t[j];
-			unsigned short v1 = (j+1 >= MAX_VERTS_PER_POLY || t[j+1] == DT_TILECACHE_NULL_IDX) ? t[0] : t[j+1];
-			if (v0 > v1)
-			{
-				bool found = false;
-				for (unsigned short e = firstEdge[v1]; e != DT_TILECACHE_NULL_IDX; e = nextEdge[e])
-				{
-					rcEdge& edge = edges[e];
-					if (edge.vert[1] == v0 && edge.poly[0] == edge.poly[1])
-					{
-						edge.poly[1] = (unsigned short)i;
-						edge.polyEdge[1] = (unsigned short)j;
-						found = true;
-						break;
-					}
-				}
-				if (!found)
-				{
-					// Matching edge not found, it is an open edge, add it.
-					rcEdge& edge = edges[edgeCount];
-					edge.vert[0] = v1;
-					edge.vert[1] = v0;
-					edge.poly[0] = (unsigned short)i;
-					edge.polyEdge[0] = (unsigned short)j;
-					edge.poly[1] = (unsigned short)i;
-					edge.polyEdge[1] = 0xff;
-					// Insert edge
-					nextEdge[edgeCount] = firstEdge[v1];
-					firstEdge[v1] = (unsigned short)edgeCount;
-					edgeCount++;
-				}
-			}
-		}
-	}
-	
-	// Mark portal edges.
-	for (int i = 0; i < lcset.nconts; ++i)
-	{
-		dtTileCacheContour& cont = lcset.conts[i];
-		if (cont.nverts < 3)
-			continue;
-		
-		for (int j = 0, k = cont.nverts-1; j < cont.nverts; k=j++)
-		{
-			const unsigned char* va = &cont.verts[k*4];
-			const unsigned char* vb = &cont.verts[j*4];
-			const unsigned char dir = va[3] & 0xf;
-			if (dir == 0xf)
-				continue;
-			
-			if (dir == 0 || dir == 2)
-			{
-				// Find matching vertical edge
-				const unsigned short x = (unsigned short)va[0];
-				unsigned short zmin = (unsigned short)va[2];
-				unsigned short zmax = (unsigned short)vb[2];
-				if (zmin > zmax)
-					dtSwap(zmin, zmax);
-				
-				for (int m = 0; m < edgeCount; ++m)
-				{
-					rcEdge& e = edges[m];
-					// Skip connected edges.
-					if (e.poly[0] != e.poly[1])
-						continue;
-					const unsigned short* eva = &verts[e.vert[0]*3];
-					const unsigned short* evb = &verts[e.vert[1]*3];
-					if (eva[0] == x && evb[0] == x)
-					{
-						unsigned short ezmin = eva[2];
-						unsigned short ezmax = evb[2];
-						if (ezmin > ezmax)
-							dtSwap(ezmin, ezmax);
-						if (overlapRangeExl(zmin,zmax, ezmin, ezmax))
-						{
-							// Reuse the other polyedge to store dir.
-							e.polyEdge[1] = dir;
-						}
-					}
-				}
-			}
-			else
-			{
-				// Find matching vertical edge
-				const unsigned short z = (unsigned short)va[2];
-				unsigned short xmin = (unsigned short)va[0];
-				unsigned short xmax = (unsigned short)vb[0];
-				if (xmin > xmax)
-					dtSwap(xmin, xmax);
-				for (int m = 0; m < edgeCount; ++m)
-				{
-					rcEdge& e = edges[m];
-					// Skip connected edges.
-					if (e.poly[0] != e.poly[1])
-						continue;
-					const unsigned short* eva = &verts[e.vert[0]*3];
-					const unsigned short* evb = &verts[e.vert[1]*3];
-					if (eva[2] == z && evb[2] == z)
-					{
-						unsigned short exmin = eva[0];
-						unsigned short exmax = evb[0];
-						if (exmin > exmax)
-							dtSwap(exmin, exmax);
-						if (overlapRangeExl(xmin,xmax, exmin, exmax))
-						{
-							// Reuse the other polyedge to store dir.
-							e.polyEdge[1] = dir;
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	
-	// Store adjacency
-	for (int i = 0; i < edgeCount; ++i)
-	{
-		const rcEdge& e = edges[i];
-		if (e.poly[0] != e.poly[1])
-		{
-			unsigned short* p0 = &polys[e.poly[0]*MAX_VERTS_PER_POLY*2];
-			unsigned short* p1 = &polys[e.poly[1]*MAX_VERTS_PER_POLY*2];
-			p0[MAX_VERTS_PER_POLY + e.polyEdge[0]] = e.poly[1];
-			p1[MAX_VERTS_PER_POLY + e.polyEdge[1]] = e.poly[0];
-		}
-		else if (e.polyEdge[1] != 0xff)
-		{
-			unsigned short* p0 = &polys[e.poly[0]*MAX_VERTS_PER_POLY*2];
-			p0[MAX_VERTS_PER_POLY + e.polyEdge[0]] = 0x8000 | (unsigned short)e.polyEdge[1];
-		}
-		
-	}
-	
-	return true;
-}
-
-
-// Last time I checked the if version got compiled using cmov, which was a lot faster than module (with idiv).
-inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; }
-inline int next(int i, int n) { return i+1 < n ? i+1 : 0; }
-
-inline int area2(const unsigned char* a, const unsigned char* b, const unsigned char* c)
-{
-	return ((int)b[0] - (int)a[0]) * ((int)c[2] - (int)a[2]) - ((int)c[0] - (int)a[0]) * ((int)b[2] - (int)a[2]);
-}
-
-//	Exclusive or: true iff exactly one argument is true.
-//	The arguments are negated to ensure that they are 0/1
-//	values.  Then the bitwise Xor operator may apply.
-//	(This idea is due to Michael Baldwin.)
-inline bool xorb(bool x, bool y)
-{
-	return !x ^ !y;
-}
-
-// Returns true iff c is strictly to the left of the directed
-// line through a to b.
-inline bool left(const unsigned char* a, const unsigned char* b, const unsigned char* c)
-{
-	return area2(a, b, c) < 0;
-}
-
-inline bool leftOn(const unsigned char* a, const unsigned char* b, const unsigned char* c)
-{
-	return area2(a, b, c) <= 0;
-}
-
-inline bool collinear(const unsigned char* a, const unsigned char* b, const unsigned char* c)
-{
-	return area2(a, b, c) == 0;
-}
-
-//	Returns true iff ab properly intersects cd: they share
-//	a point interior to both segments.  The properness of the
-//	intersection is ensured by using strict leftness.
-static bool intersectProp(const unsigned char* a, const unsigned char* b,
-						  const unsigned char* c, const unsigned char* d)
-{
-	// Eliminate improper cases.
-	if (collinear(a,b,c) || collinear(a,b,d) ||
-		collinear(c,d,a) || collinear(c,d,b))
-		return false;
-	
-	return xorb(left(a,b,c), left(a,b,d)) && xorb(left(c,d,a), left(c,d,b));
-}
-
-// Returns T iff (a,b,c) are collinear and point c lies 
-// on the closed segement ab.
-static bool between(const unsigned char* a, const unsigned char* b, const unsigned char* c)
-{
-	if (!collinear(a, b, c))
-		return false;
-	// If ab not vertical, check betweenness on x; else on y.
-	if (a[0] != b[0])
-		return ((a[0] <= c[0]) && (c[0] <= b[0])) || ((a[0] >= c[0]) && (c[0] >= b[0]));
-	else
-		return ((a[2] <= c[2]) && (c[2] <= b[2])) || ((a[2] >= c[2]) && (c[2] >= b[2]));
-}
-
-// Returns true iff segments ab and cd intersect, properly or improperly.
-static bool intersect(const unsigned char* a, const unsigned char* b,
-					  const unsigned char* c, const unsigned char* d)
-{
-	if (intersectProp(a, b, c, d))
-		return true;
-	else if (between(a, b, c) || between(a, b, d) ||
-			 between(c, d, a) || between(c, d, b))
-		return true;
-	else
-		return false;
-}
-
-static bool vequal(const unsigned char* a, const unsigned char* b)
-{
-	return a[0] == b[0] && a[2] == b[2];
-}
-
-// Returns T iff (v_i, v_j) is a proper internal *or* external
-// diagonal of P, *ignoring edges incident to v_i and v_j*.
-static bool diagonalie(int i, int j, int n, const unsigned char* verts, const unsigned short* indices)
-{
-	const unsigned char* d0 = &verts[(indices[i] & 0x7fff) * 4];
-	const unsigned char* d1 = &verts[(indices[j] & 0x7fff) * 4];
-	
-	// For each edge (k,k+1) of P
-	for (int k = 0; k < n; k++)
-	{
-		int k1 = next(k, n);
-		// Skip edges incident to i or j
-		if (!((k == i) || (k1 == i) || (k == j) || (k1 == j)))
-		{
-			const unsigned char* p0 = &verts[(indices[k] & 0x7fff) * 4];
-			const unsigned char* p1 = &verts[(indices[k1] & 0x7fff) * 4];
-			
-			if (vequal(d0, p0) || vequal(d1, p0) || vequal(d0, p1) || vequal(d1, p1))
-				continue;
-			
-			if (intersect(d0, d1, p0, p1))
-				return false;
-		}
-	}
-	return true;
-}
-
-// Returns true iff the diagonal (i,j) is strictly internal to the 
-// polygon P in the neighborhood of the i endpoint.
-static bool	inCone(int i, int j, int n, const unsigned char* verts, const unsigned short* indices)
-{
-	const unsigned char* pi = &verts[(indices[i] & 0x7fff) * 4];
-	const unsigned char* pj = &verts[(indices[j] & 0x7fff) * 4];
-	const unsigned char* pi1 = &verts[(indices[next(i, n)] & 0x7fff) * 4];
-	const unsigned char* pin1 = &verts[(indices[prev(i, n)] & 0x7fff) * 4];
-	
-	// If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
-	if (leftOn(pin1, pi, pi1))
-		return left(pi, pj, pin1) && left(pj, pi, pi1);
-	// Assume (i-1,i,i+1) not collinear.
-	// else P[i] is reflex.
-	return !(leftOn(pi, pj, pi1) && leftOn(pj, pi, pin1));
-}
-
-// Returns T iff (v_i, v_j) is a proper internal
-// diagonal of P.
-static bool diagonal(int i, int j, int n, const unsigned char* verts, const unsigned short* indices)
-{
-	return inCone(i, j, n, verts, indices) && diagonalie(i, j, n, verts, indices);
-}
-
-static int triangulate(int n, const unsigned char* verts, unsigned short* indices, unsigned short* tris)
-{
-	int ntris = 0;
-	unsigned short* dst = tris;
-	
-	// The last bit of the index is used to indicate if the vertex can be removed.
-	for (int i = 0; i < n; i++)
-	{
-		int i1 = next(i, n);
-		int i2 = next(i1, n);
-		if (diagonal(i, i2, n, verts, indices))
-			indices[i1] |= 0x8000;
-	}
-	
-	while (n > 3)
-	{
-		int minLen = -1;
-		int mini = -1;
-		for (int i = 0; i < n; i++)
-		{
-			int i1 = next(i, n);
-			if (indices[i1] & 0x8000)
-			{
-				const unsigned char* p0 = &verts[(indices[i] & 0x7fff) * 4];
-				const unsigned char* p2 = &verts[(indices[next(i1, n)] & 0x7fff) * 4];
-				
-				const int dx = (int)p2[0] - (int)p0[0];
-				const int dz = (int)p2[2] - (int)p0[2];
-				const int len = dx*dx + dz*dz;
-				if (minLen < 0 || len < minLen)
-				{
-					minLen = len;
-					mini = i;
-				}
-			}
-		}
-		
-		if (mini == -1)
-		{
-			// Should not happen.
-			/*			printf("mini == -1 ntris=%d n=%d\n", ntris, n);
-			 for (int i = 0; i < n; i++)
-			 {
-			 printf("%d ", indices[i] & 0x0fffffff);
-			 }
-			 printf("\n");*/
-			return -ntris;
-		}
-		
-		int i = mini;
-		int i1 = next(i, n);
-		int i2 = next(i1, n);
-		
-		*dst++ = indices[i] & 0x7fff;
-		*dst++ = indices[i1] & 0x7fff;
-		*dst++ = indices[i2] & 0x7fff;
-		ntris++;
-		
-		// Removes P[i1] by copying P[i+1]...P[n-1] left one index.
-		n--;
-		for (int k = i1; k < n; k++)
-			indices[k] = indices[k+1];
-		
-		if (i1 >= n) i1 = 0;
-		i = prev(i1,n);
-		// Update diagonal flags.
-		if (diagonal(prev(i, n), i1, n, verts, indices))
-			indices[i] |= 0x8000;
-		else
-			indices[i] &= 0x7fff;
-		
-		if (diagonal(i, next(i1, n), n, verts, indices))
-			indices[i1] |= 0x8000;
-		else
-			indices[i1] &= 0x7fff;
-	}
-	
-	// Append the remaining triangle.
-	*dst++ = indices[0] & 0x7fff;
-	*dst++ = indices[1] & 0x7fff;
-	*dst++ = indices[2] & 0x7fff;
-	ntris++;
-	
-	return ntris;
-}
-
-
-static int countPolyVerts(const unsigned short* p)
-{
-	for (int i = 0; i < MAX_VERTS_PER_POLY; ++i)
-		if (p[i] == DT_TILECACHE_NULL_IDX)
-			return i;
-	return MAX_VERTS_PER_POLY;
-}
-
-inline bool uleft(const unsigned short* a, const unsigned short* b, const unsigned short* c)
-{
-	return ((int)b[0] - (int)a[0]) * ((int)c[2] - (int)a[2]) -
-	((int)c[0] - (int)a[0]) * ((int)b[2] - (int)a[2]) < 0;
-}
-
-static int getPolyMergeValue(unsigned short* pa, unsigned short* pb,
-							 const unsigned short* verts, int& ea, int& eb)
-{
-	const int na = countPolyVerts(pa);
-	const int nb = countPolyVerts(pb);
-	
-	// If the merged polygon would be too big, do not merge.
-	if (na+nb-2 > MAX_VERTS_PER_POLY)
-		return -1;
-	
-	// Check if the polygons share an edge.
-	ea = -1;
-	eb = -1;
-	
-	for (int i = 0; i < na; ++i)
-	{
-		unsigned short va0 = pa[i];
-		unsigned short va1 = pa[(i+1) % na];
-		if (va0 > va1)
-			dtSwap(va0, va1);
-		for (int j = 0; j < nb; ++j)
-		{
-			unsigned short vb0 = pb[j];
-			unsigned short vb1 = pb[(j+1) % nb];
-			if (vb0 > vb1)
-				dtSwap(vb0, vb1);
-			if (va0 == vb0 && va1 == vb1)
-			{
-				ea = i;
-				eb = j;
-				break;
-			}
-		}
-	}
-	
-	// No common edge, cannot merge.
-	if (ea == -1 || eb == -1)
-		return -1;
-	
-	// Check to see if the merged polygon would be convex.
-	unsigned short va, vb, vc;
-	
-	va = pa[(ea+na-1) % na];
-	vb = pa[ea];
-	vc = pb[(eb+2) % nb];
-	if (!uleft(&verts[va*3], &verts[vb*3], &verts[vc*3]))
-		return -1;
-	
-	va = pb[(eb+nb-1) % nb];
-	vb = pb[eb];
-	vc = pa[(ea+2) % na];
-	if (!uleft(&verts[va*3], &verts[vb*3], &verts[vc*3]))
-		return -1;
-	
-	va = pa[ea];
-	vb = pa[(ea+1)%na];
-	
-	int dx = (int)verts[va*3+0] - (int)verts[vb*3+0];
-	int dy = (int)verts[va*3+2] - (int)verts[vb*3+2];
-	
-	return dx*dx + dy*dy;
-}
-
-static void mergePolys(unsigned short* pa, unsigned short* pb, int ea, int eb)
-{
-	unsigned short tmp[MAX_VERTS_PER_POLY*2];
-	
-	const int na = countPolyVerts(pa);
-	const int nb = countPolyVerts(pb);
-	
-	// Merge polygons.
-	memset(tmp, 0xff, sizeof(unsigned short)*MAX_VERTS_PER_POLY*2);
-	int n = 0;
-	// Add pa
-	for (int i = 0; i < na-1; ++i)
-		tmp[n++] = pa[(ea+1+i) % na];
-	// Add pb
-	for (int i = 0; i < nb-1; ++i)
-		tmp[n++] = pb[(eb+1+i) % nb];
-	
-	memcpy(pa, tmp, sizeof(unsigned short)*MAX_VERTS_PER_POLY);
-}
-
-
-static void pushFront(unsigned short v, unsigned short* arr, int& an)
-{
-	an++;
-	for (int i = an-1; i > 0; --i)
-		arr[i] = arr[i-1];
-	arr[0] = v;
-}
-
-static void pushBack(unsigned short v, unsigned short* arr, int& an)
-{
-	arr[an] = v;
-	an++;
-}
-
-static bool canRemoveVertex(dtTileCachePolyMesh& mesh, const unsigned short rem)
-{
-	// Count number of polygons to remove.
-	int numRemovedVerts = 0;
-	int numTouchedVerts = 0;
-	int numRemainingEdges = 0;
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		unsigned short* p = &mesh.polys[i*MAX_VERTS_PER_POLY*2];
-		const int nv = countPolyVerts(p);
-		int numRemoved = 0;
-		int numVerts = 0;
-		for (int j = 0; j < nv; ++j)
-		{
-			if (p[j] == rem)
-			{
-				numTouchedVerts++;
-				numRemoved++;
-			}
-			numVerts++;
-		}
-		if (numRemoved)
-		{
-			numRemovedVerts += numRemoved;
-			numRemainingEdges += numVerts-(numRemoved+1);
-		}
-	}
-	
-	// There would be too few edges remaining to create a polygon.
-	// This can happen for example when a tip of a triangle is marked
-	// as deletion, but there are no other polys that share the vertex.
-	// In this case, the vertex should not be removed.
-	if (numRemainingEdges <= 2)
-		return false;
-	
-	// Check that there is enough memory for the test.
-	const int maxEdges = numTouchedVerts*2;
-	if (maxEdges > MAX_REM_EDGES)
-		return false;
-	
-	// Find edges which share the removed vertex.
-	unsigned short edges[MAX_REM_EDGES];
-	int nedges = 0;
-	
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		unsigned short* p = &mesh.polys[i*MAX_VERTS_PER_POLY*2];
-		const int nv = countPolyVerts(p);
-		
-		// Collect edges which touches the removed vertex.
-		for (int j = 0, k = nv-1; j < nv; k = j++)
-		{
-			if (p[j] == rem || p[k] == rem)
-			{
-				// Arrange edge so that a=rem.
-				int a = p[j], b = p[k];
-				if (b == rem)
-					dtSwap(a,b);
-				
-				// Check if the edge exists
-				bool exists = false;
-				for (int m = 0; m < nedges; ++m)
-				{
-					unsigned short* e = &edges[m*3];
-					if (e[1] == b)
-					{
-						// Exists, increment vertex share count.
-						e[2]++;
-						exists = true;
-					}
-				}
-				// Add new edge.
-				if (!exists)
-				{
-					unsigned short* e = &edges[nedges*3];
-					e[0] = (unsigned short)a;
-					e[1] = (unsigned short)b;
-					e[2] = 1;
-					nedges++;
-				}
-			}
-		}
-	}
-	
-	// There should be no more than 2 open edges.
-	// This catches the case that two non-adjacent polygons
-	// share the removed vertex. In that case, do not remove the vertex.
-	int numOpenEdges = 0;
-	for (int i = 0; i < nedges; ++i)
-	{
-		if (edges[i*3+2] < 2)
-			numOpenEdges++;
-	}
-	if (numOpenEdges > 2)
-		return false;
-	
-	return true;
-}
-
-static dtStatus removeVertex(dtTileCachePolyMesh& mesh, const unsigned short rem, const int maxTris)
-{
-	// Count number of polygons to remove.
-	int numRemovedVerts = 0;
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		unsigned short* p = &mesh.polys[i*MAX_VERTS_PER_POLY*2];
-		const int nv = countPolyVerts(p);
-		for (int j = 0; j < nv; ++j)
-		{
-			if (p[j] == rem)
-				numRemovedVerts++;
-		}
-	}
-	
-	int nedges = 0;
-	unsigned short edges[MAX_REM_EDGES*3];
-	int nhole = 0;
-	unsigned short hole[MAX_REM_EDGES];
-	int nharea = 0;
-	unsigned short harea[MAX_REM_EDGES];
-	
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		unsigned short* p = &mesh.polys[i*MAX_VERTS_PER_POLY*2];
-		const int nv = countPolyVerts(p);
-		bool hasRem = false;
-		for (int j = 0; j < nv; ++j)
-			if (p[j] == rem) hasRem = true;
-		if (hasRem)
-		{
-			// Collect edges which does not touch the removed vertex.
-			for (int j = 0, k = nv-1; j < nv; k = j++)
-			{
-				if (p[j] != rem && p[k] != rem)
-				{
-					if (nedges >= MAX_REM_EDGES)
-						return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-					unsigned short* e = &edges[nedges*3];
-					e[0] = p[k];
-					e[1] = p[j];
-					e[2] = mesh.areas[i];
-					nedges++;
-				}
-			}
-			// Remove the polygon.
-			unsigned short* p2 = &mesh.polys[(mesh.npolys-1)*MAX_VERTS_PER_POLY*2];
-			memcpy(p,p2,sizeof(unsigned short)*MAX_VERTS_PER_POLY);
-			memset(p+MAX_VERTS_PER_POLY,0xff,sizeof(unsigned short)*MAX_VERTS_PER_POLY);
-			mesh.areas[i] = mesh.areas[mesh.npolys-1];
-			mesh.npolys--;
-			--i;
-		}
-	}
-	
-	// Remove vertex.
-	for (int i = (int)rem; i < mesh.nverts; ++i)
-	{
-		mesh.verts[i*3+0] = mesh.verts[(i+1)*3+0];
-		mesh.verts[i*3+1] = mesh.verts[(i+1)*3+1];
-		mesh.verts[i*3+2] = mesh.verts[(i+1)*3+2];
-	}
-	mesh.nverts--;
-	
-	// Adjust indices to match the removed vertex layout.
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		unsigned short* p = &mesh.polys[i*MAX_VERTS_PER_POLY*2];
-		const int nv = countPolyVerts(p);
-		for (int j = 0; j < nv; ++j)
-			if (p[j] > rem) p[j]--;
-	}
-	for (int i = 0; i < nedges; ++i)
-	{
-		if (edges[i*3+0] > rem) edges[i*3+0]--;
-		if (edges[i*3+1] > rem) edges[i*3+1]--;
-	}
-	
-	if (nedges == 0)
-		return DT_SUCCESS;
-	
-	// Start with one vertex, keep appending connected
-	// segments to the start and end of the hole.
-	pushBack(edges[0], hole, nhole);
-	pushBack(edges[2], harea, nharea);
-	
-	while (nedges)
-	{
-		bool match = false;
-		
-		for (int i = 0; i < nedges; ++i)
-		{
-			const unsigned short ea = edges[i*3+0];
-			const unsigned short eb = edges[i*3+1];
-			const unsigned short a = edges[i*3+2];
-			bool add = false;
-			if (hole[0] == eb)
-			{
-				// The segment matches the beginning of the hole boundary.
-				if (nhole >= MAX_REM_EDGES)
-					return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-				pushFront(ea, hole, nhole);
-				pushFront(a, harea, nharea);
-				add = true;
-			}
-			else if (hole[nhole-1] == ea)
-			{
-				// The segment matches the end of the hole boundary.
-				if (nhole >= MAX_REM_EDGES)
-					return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-				pushBack(eb, hole, nhole);
-				pushBack(a, harea, nharea);
-				add = true;
-			}
-			if (add)
-			{
-				// The edge segment was added, remove it.
-				edges[i*3+0] = edges[(nedges-1)*3+0];
-				edges[i*3+1] = edges[(nedges-1)*3+1];
-				edges[i*3+2] = edges[(nedges-1)*3+2];
-				--nedges;
-				match = true;
-				--i;
-			}
-		}
-		
-		if (!match)
-			break;
-	}
-	
-	
-	unsigned short tris[MAX_REM_EDGES*3];
-	unsigned char tverts[MAX_REM_EDGES*3];
-	unsigned short tpoly[MAX_REM_EDGES*3];
-	
-	// Generate temp vertex array for triangulation.
-	for (int i = 0; i < nhole; ++i)
-	{
-		const unsigned short pi = hole[i];
-		tverts[i*4+0] = (unsigned char)mesh.verts[pi*3+0];
-		tverts[i*4+1] = (unsigned char)mesh.verts[pi*3+1];
-		tverts[i*4+2] = (unsigned char)mesh.verts[pi*3+2];
-		tverts[i*4+3] = 0;
-		tpoly[i] = (unsigned short)i;
-	}
-	
-	// Triangulate the hole.
-	int ntris = triangulate(nhole, tverts, tpoly, tris);
-	if (ntris < 0)
-	{
-		// TODO: issue warning!
-		ntris = -ntris;
-	}
-	
-	if (ntris > MAX_REM_EDGES)
-		return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-	
-	unsigned short polys[MAX_REM_EDGES*MAX_VERTS_PER_POLY];
-	unsigned char pareas[MAX_REM_EDGES];
-	
-	// Build initial polygons.
-	int npolys = 0;
-	memset(polys, 0xff, ntris*MAX_VERTS_PER_POLY*sizeof(unsigned short));
-	for (int j = 0; j < ntris; ++j)
-	{
-		unsigned short* t = &tris[j*3];
-		if (t[0] != t[1] && t[0] != t[2] && t[1] != t[2])
-		{
-			polys[npolys*MAX_VERTS_PER_POLY+0] = hole[t[0]];
-			polys[npolys*MAX_VERTS_PER_POLY+1] = hole[t[1]];
-			polys[npolys*MAX_VERTS_PER_POLY+2] = hole[t[2]];
-			pareas[npolys] = (unsigned char)harea[t[0]];
-			npolys++;
-		}
-	}
-	if (!npolys)
-		return DT_SUCCESS;
-	
-	// Merge polygons.
-	int maxVertsPerPoly = MAX_VERTS_PER_POLY;
-	if (maxVertsPerPoly > 3)
-	{
-		for (;;)
-		{
-			// Find best polygons to merge.
-			int bestMergeVal = 0;
-			int bestPa = 0, bestPb = 0, bestEa = 0, bestEb = 0;
-			
-			for (int j = 0; j < npolys-1; ++j)
-			{
-				unsigned short* pj = &polys[j*MAX_VERTS_PER_POLY];
-				for (int k = j+1; k < npolys; ++k)
-				{
-					unsigned short* pk = &polys[k*MAX_VERTS_PER_POLY];
-					int ea, eb;
-					int v = getPolyMergeValue(pj, pk, mesh.verts, ea, eb);
-					if (v > bestMergeVal)
-					{
-						bestMergeVal = v;
-						bestPa = j;
-						bestPb = k;
-						bestEa = ea;
-						bestEb = eb;
-					}
-				}
-			}
-			
-			if (bestMergeVal > 0)
-			{
-				// Found best, merge.
-				unsigned short* pa = &polys[bestPa*MAX_VERTS_PER_POLY];
-				unsigned short* pb = &polys[bestPb*MAX_VERTS_PER_POLY];
-				mergePolys(pa, pb, bestEa, bestEb);
-				memcpy(pb, &polys[(npolys-1)*MAX_VERTS_PER_POLY], sizeof(unsigned short)*MAX_VERTS_PER_POLY);
-				pareas[bestPb] = pareas[npolys-1];
-				npolys--;
-			}
-			else
-			{
-				// Could not merge any polygons, stop.
-				break;
-			}
-		}
-	}
-	
-	// Store polygons.
-	for (int i = 0; i < npolys; ++i)
-	{
-		if (mesh.npolys >= maxTris) break;
-		unsigned short* p = &mesh.polys[mesh.npolys*MAX_VERTS_PER_POLY*2];
-		memset(p,0xff,sizeof(unsigned short)*MAX_VERTS_PER_POLY*2);
-		for (int j = 0; j < MAX_VERTS_PER_POLY; ++j)
-			p[j] = polys[i*MAX_VERTS_PER_POLY+j];
-		mesh.areas[mesh.npolys] = pareas[i];
-		mesh.npolys++;
-		if (mesh.npolys > maxTris)
-			return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-	}
-	
-	return DT_SUCCESS;
-}
-
-
-dtStatus dtBuildTileCachePolyMesh(dtTileCacheAlloc* alloc,
-								  dtTileCacheContourSet& lcset,
-								  dtTileCachePolyMesh& mesh)
-{
-	dtAssert(alloc);
-	
-	int maxVertices = 0;
-	int maxTris = 0;
-	int maxVertsPerCont = 0;
-	for (int i = 0; i < lcset.nconts; ++i)
-	{
-		// Skip null contours.
-		if (lcset.conts[i].nverts < 3) continue;
-		maxVertices += lcset.conts[i].nverts;
-		maxTris += lcset.conts[i].nverts - 2;
-		maxVertsPerCont = dtMax(maxVertsPerCont, lcset.conts[i].nverts);
-	}
-
-	// TODO: warn about too many vertices?
-	
-	mesh.nvp = MAX_VERTS_PER_POLY;
-	
-	dtFixedArray<unsigned char> vflags(alloc, maxVertices);
-	if (!vflags)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(vflags, 0, maxVertices);
-	
-	mesh.verts = (unsigned short*)alloc->alloc(sizeof(unsigned short)*maxVertices*3);
-	if (!mesh.verts)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	
-	mesh.polys = (unsigned short*)alloc->alloc(sizeof(unsigned short)*maxTris*MAX_VERTS_PER_POLY*2);
-	if (!mesh.polys)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-
-	mesh.areas = (unsigned char*)alloc->alloc(sizeof(unsigned char)*maxTris);
-	if (!mesh.areas)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-
-	mesh.flags = (unsigned short*)alloc->alloc(sizeof(unsigned short)*maxTris);
-	if (!mesh.flags)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-
-	// Just allocate and clean the mesh flags array. The user is resposible for filling it.
-	memset(mesh.flags, 0, sizeof(unsigned short) * maxTris);
-		
-	mesh.nverts = 0;
-	mesh.npolys = 0;
-	
-	memset(mesh.verts, 0, sizeof(unsigned short)*maxVertices*3);
-	memset(mesh.polys, 0xff, sizeof(unsigned short)*maxTris*MAX_VERTS_PER_POLY*2);
-	memset(mesh.areas, 0, sizeof(unsigned char)*maxTris);
-	
-	unsigned short firstVert[VERTEX_BUCKET_COUNT2];
-	for (int i = 0; i < VERTEX_BUCKET_COUNT2; ++i)
-		firstVert[i] = DT_TILECACHE_NULL_IDX;
-	
-	dtFixedArray<unsigned short> nextVert(alloc, maxVertices);
-	if (!nextVert)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(nextVert, 0, sizeof(unsigned short)*maxVertices);
-	
-	dtFixedArray<unsigned short> indices(alloc, maxVertsPerCont);
-	if (!indices)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	
-	dtFixedArray<unsigned short> tris(alloc, maxVertsPerCont*3);
-	if (!tris)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-
-	dtFixedArray<unsigned short> polys(alloc, maxVertsPerCont*MAX_VERTS_PER_POLY);
-	if (!polys)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	
-	for (int i = 0; i < lcset.nconts; ++i)
-	{
-		dtTileCacheContour& cont = lcset.conts[i];
-		
-		// Skip null contours.
-		if (cont.nverts < 3)
-			continue;
-		
-		// Triangulate contour
-		for (int j = 0; j < cont.nverts; ++j)
-			indices[j] = (unsigned short)j;
-		
-		int ntris = triangulate(cont.nverts, cont.verts, &indices[0], &tris[0]);
-		if (ntris <= 0)
-		{
-			// TODO: issue warning!
-			ntris = -ntris;
-		}
-		
-		// Add and merge vertices.
-		for (int j = 0; j < cont.nverts; ++j)
-		{
-			const unsigned char* v = &cont.verts[j*4];
-			indices[j] = addVertex((unsigned short)v[0], (unsigned short)v[1], (unsigned short)v[2],
-								   mesh.verts, firstVert, nextVert, mesh.nverts);
-			if (v[3] & 0x80)
-			{
-				// This vertex should be removed.
-				vflags[indices[j]] = 1;
-			}
-		}
-		
-		// Build initial polygons.
-		int npolys = 0;
-		memset(polys, 0xff, sizeof(unsigned short) * maxVertsPerCont * MAX_VERTS_PER_POLY);
-		for (int j = 0; j < ntris; ++j)
-		{
-			const unsigned short* t = &tris[j*3];
-			if (t[0] != t[1] && t[0] != t[2] && t[1] != t[2])
-			{
-				polys[npolys*MAX_VERTS_PER_POLY+0] = indices[t[0]];
-				polys[npolys*MAX_VERTS_PER_POLY+1] = indices[t[1]];
-				polys[npolys*MAX_VERTS_PER_POLY+2] = indices[t[2]];
-				npolys++;
-			}
-		}
-		if (!npolys)
-			continue;
-		
-		// Merge polygons.
-		int maxVertsPerPoly =MAX_VERTS_PER_POLY ;
-		if (maxVertsPerPoly > 3)
-		{
-			for(;;)
-			{
-				// Find best polygons to merge.
-				int bestMergeVal = 0;
-				int bestPa = 0, bestPb = 0, bestEa = 0, bestEb = 0;
-				
-				for (int j = 0; j < npolys-1; ++j)
-				{
-					unsigned short* pj = &polys[j*MAX_VERTS_PER_POLY];
-					for (int k = j+1; k < npolys; ++k)
-					{
-						unsigned short* pk = &polys[k*MAX_VERTS_PER_POLY];
-						int ea, eb;
-						int v = getPolyMergeValue(pj, pk, mesh.verts, ea, eb);
-						if (v > bestMergeVal)
-						{
-							bestMergeVal = v;
-							bestPa = j;
-							bestPb = k;
-							bestEa = ea;
-							bestEb = eb;
-						}
-					}
-				}
-				
-				if (bestMergeVal > 0)
-				{
-					// Found best, merge.
-					unsigned short* pa = &polys[bestPa*MAX_VERTS_PER_POLY];
-					unsigned short* pb = &polys[bestPb*MAX_VERTS_PER_POLY];
-					mergePolys(pa, pb, bestEa, bestEb);
-					memcpy(pb, &polys[(npolys-1)*MAX_VERTS_PER_POLY], sizeof(unsigned short)*MAX_VERTS_PER_POLY);
-					npolys--;
-				}
-				else
-				{
-					// Could not merge any polygons, stop.
-					break;
-				}
-			}
-		}
-		
-		// Store polygons.
-		for (int j = 0; j < npolys; ++j)
-		{
-			unsigned short* p = &mesh.polys[mesh.npolys*MAX_VERTS_PER_POLY*2];
-			unsigned short* q = &polys[j*MAX_VERTS_PER_POLY];
-			for (int k = 0; k < MAX_VERTS_PER_POLY; ++k)
-				p[k] = q[k];
-			mesh.areas[mesh.npolys] = cont.area;
-			mesh.npolys++;
-			if (mesh.npolys > maxTris)
-				return DT_FAILURE | DT_BUFFER_TOO_SMALL;
-		}
-	}
-	
-	
-	// Remove edge vertices.
-	for (int i = 0; i < mesh.nverts; ++i)
-	{
-		if (vflags[i])
-		{
-			if (!canRemoveVertex(mesh, (unsigned short)i))
-				continue;
-			dtStatus status = removeVertex(mesh, (unsigned short)i, maxTris);
-			if (dtStatusFailed(status))
-				return status;
-			// Remove vertex
-			// Note: mesh.nverts is already decremented inside removeVertex()!
-			for (int j = i; j < mesh.nverts; ++j)
-				vflags[j] = vflags[j+1];
-			--i;
-		}
-	}
-	
-	// Calculate adjacency.
-	if (!buildMeshAdjacency(alloc, mesh.polys, mesh.npolys, mesh.verts, mesh.nverts, lcset))
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-		
-	return DT_SUCCESS;
-}
-
-dtStatus dtMarkCylinderArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
-							const float* pos, const float radius, const float height, const unsigned char areaId)
-{
-	float bmin[3], bmax[3];
-	bmin[0] = pos[0] - radius;
-	bmin[1] = pos[1];
-	bmin[2] = pos[2] - radius;
-	bmax[0] = pos[0] + radius;
-	bmax[1] = pos[1] + height;
-	bmax[2] = pos[2] + radius;
-	const float r2 = dtSqr(radius/cs + 0.5f);
-
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	const float ics = 1.0f/cs;
-	const float ich = 1.0f/ch;
-	
-	const float px = (pos[0]-orig[0])*ics;
-	const float pz = (pos[2]-orig[2])*ics;
-	
-	int minx = (int)dtMathFloorf((bmin[0]-orig[0])*ics);
-	int miny = (int)dtMathFloorf((bmin[1]-orig[1])*ich);
-	int minz = (int)dtMathFloorf((bmin[2]-orig[2])*ics);
-	int maxx = (int)dtMathFloorf((bmax[0]-orig[0])*ics);
-	int maxy = (int)dtMathFloorf((bmax[1]-orig[1])*ich);
-	int maxz = (int)dtMathFloorf((bmax[2]-orig[2])*ics);
-
-	if (maxx < 0) return DT_SUCCESS;
-	if (minx >= w) return DT_SUCCESS;
-	if (maxz < 0) return DT_SUCCESS;
-	if (minz >= h) return DT_SUCCESS;
-	
-	if (minx < 0) minx = 0;
-	if (maxx >= w) maxx = w-1;
-	if (minz < 0) minz = 0;
-	if (maxz >= h) maxz = h-1;
-	
-	for (int z = minz; z <= maxz; ++z)
-	{
-		for (int x = minx; x <= maxx; ++x)
-		{
-			const float dx = (float)(x+0.5f) - px;
-			const float dz = (float)(z+0.5f) - pz;
-			if (dx*dx + dz*dz > r2)
-				continue;
-			const int y = layer.heights[x+z*w];
-			if (y < miny || y > maxy)
-				continue;
-			layer.areas[x+z*w] = areaId;
-		}
-	}
-
-	return DT_SUCCESS;
-}
-
-dtStatus dtMarkBoxArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
-					   const float* bmin, const float* bmax, const unsigned char areaId)
-{
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	const float ics = 1.0f/cs;
-	const float ich = 1.0f/ch;
-
-	int minx = (int)floorf((bmin[0]-orig[0])*ics);
-	int miny = (int)floorf((bmin[1]-orig[1])*ich);
-	int minz = (int)floorf((bmin[2]-orig[2])*ics);
-	int maxx = (int)floorf((bmax[0]-orig[0])*ics);
-	int maxy = (int)floorf((bmax[1]-orig[1])*ich);
-	int maxz = (int)floorf((bmax[2]-orig[2])*ics);
-	
-	if (maxx < 0) return DT_SUCCESS;
-	if (minx >= w) return DT_SUCCESS;
-	if (maxz < 0) return DT_SUCCESS;
-	if (minz >= h) return DT_SUCCESS;
-
-	if (minx < 0) minx = 0;
-	if (maxx >= w) maxx = w-1;
-	if (minz < 0) minz = 0;
-	if (maxz >= h) maxz = h-1;
-	
-	for (int z = minz; z <= maxz; ++z)
-	{
-		for (int x = minx; x <= maxx; ++x)
-		{
-			const int y = layer.heights[x+z*w];
-			if (y < miny || y > maxy)
-				continue;
-			layer.areas[x+z*w] = areaId;
-		}
-	}
-
-	return DT_SUCCESS;
-}
-
-dtStatus dtMarkBoxArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
-					   const float* center, const float* halfExtents, const float* rotAux, const unsigned char areaId)
-{
-	const int w = (int)layer.header->width;
-	const int h = (int)layer.header->height;
-	const float ics = 1.0f/cs;
-	const float ich = 1.0f/ch;
-
-	float cx = (center[0] - orig[0])*ics;
-	float cz = (center[2] - orig[2])*ics;
-	
-	float maxr = 1.41f*dtMax(halfExtents[0], halfExtents[2]);
-	int minx = (int)floorf(cx - maxr*ics);
-	int maxx = (int)floorf(cx + maxr*ics);
-	int minz = (int)floorf(cz - maxr*ics);
-	int maxz = (int)floorf(cz + maxr*ics);
-	int miny = (int)floorf((center[1]-halfExtents[1]-orig[1])*ich);
-	int maxy = (int)floorf((center[1]+halfExtents[1]-orig[1])*ich);
-
-	if (maxx < 0) return DT_SUCCESS;
-	if (minx >= w) return DT_SUCCESS;
-	if (maxz < 0) return DT_SUCCESS;
-	if (minz >= h) return DT_SUCCESS;
-
-	if (minx < 0) minx = 0;
-	if (maxx >= w) maxx = w-1;
-	if (minz < 0) minz = 0;
-	if (maxz >= h) maxz = h-1;
-	
-	float xhalf = halfExtents[0]*ics + 0.5f;
-	float zhalf = halfExtents[2]*ics + 0.5f;
-
-	for (int z = minz; z <= maxz; ++z)
-	{
-		for (int x = minx; x <= maxx; ++x)
-		{			
-			float x2 = 2.0f*(float(x) - cx);
-			float z2 = 2.0f*(float(z) - cz);
-			float xrot = rotAux[1]*x2 + rotAux[0]*z2;
-			if (xrot > xhalf || xrot < -xhalf)
-				continue;
-			float zrot = rotAux[1]*z2 - rotAux[0]*x2;
-			if (zrot > zhalf || zrot < -zhalf)
-				continue;
-			const int y = layer.heights[x+z*w];
-			if (y < miny || y > maxy)
-				continue;
-			layer.areas[x+z*w] = areaId;
-		}
-	}
-
-	return DT_SUCCESS;
-}
-
-dtStatus dtBuildTileCacheLayer(dtTileCacheCompressor* comp,
-							   dtTileCacheLayerHeader* header,
-							   const unsigned char* heights,
-							   const unsigned char* areas,
-							   const unsigned char* cons,
-							   unsigned char** outData, int* outDataSize)
-{
-	const int headerSize = dtAlign4(sizeof(dtTileCacheLayerHeader));
-	const int gridSize = (int)header->width * (int)header->height;
-	const int maxDataSize = headerSize + comp->maxCompressedSize(gridSize*3);
-	unsigned char* data = (unsigned char*)dtAlloc(maxDataSize, DT_ALLOC_PERM);
-	if (!data)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(data, 0, maxDataSize);
-	
-	// Store header
-	memcpy(data, header, sizeof(dtTileCacheLayerHeader));
-	
-	// Concatenate grid data for compression.
-	const int bufferSize = gridSize*3;
-	unsigned char* buffer = (unsigned char*)dtAlloc(bufferSize, DT_ALLOC_TEMP);
-	if (!buffer)
-	{
-		dtFree(data);
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	}
-
-	memcpy(buffer, heights, gridSize);
-	memcpy(buffer+gridSize, areas, gridSize);
-	memcpy(buffer+gridSize*2, cons, gridSize);
-	
-	// Compress
-	unsigned char* compressed = data + headerSize;
-	const int maxCompressedSize = maxDataSize - headerSize;
-	int compressedSize = 0;
-	dtStatus status = comp->compress(buffer, bufferSize, compressed, maxCompressedSize, &compressedSize);
-	if (dtStatusFailed(status))
-	{
-		dtFree(buffer);
-		dtFree(data);
-		return status;
-	}
-
-	*outData = data;
-	*outDataSize = headerSize + compressedSize;
-	
-	dtFree(buffer);
-	
-	return DT_SUCCESS;
-}
-
-void dtFreeTileCacheLayer(dtTileCacheAlloc* alloc, dtTileCacheLayer* layer)
-{
-	dtAssert(alloc);
-	// The layer is allocated as one conitguous blob of data.
-	alloc->free(layer);
-}
-
-dtStatus dtDecompressTileCacheLayer(dtTileCacheAlloc* alloc, dtTileCacheCompressor* comp,
-									unsigned char* compressed, const int compressedSize,
-									dtTileCacheLayer** layerOut)
-{
-	dtAssert(alloc);
-	dtAssert(comp);
-
-	if (!layerOut)
-		return DT_FAILURE | DT_INVALID_PARAM;
-	if (!compressed)
-		return DT_FAILURE | DT_INVALID_PARAM;
-
-	*layerOut = 0;
-
-	dtTileCacheLayerHeader* compressedHeader = (dtTileCacheLayerHeader*)compressed;
-	if (compressedHeader->magic != DT_TILECACHE_MAGIC)
-		return DT_FAILURE | DT_WRONG_MAGIC;
-	if (compressedHeader->version != DT_TILECACHE_VERSION)
-		return DT_FAILURE | DT_WRONG_VERSION;
-	
-	const int layerSize = dtAlign4(sizeof(dtTileCacheLayer));
-	const int headerSize = dtAlign4(sizeof(dtTileCacheLayerHeader));
-	const int gridSize = (int)compressedHeader->width * (int)compressedHeader->height;
-	const int bufferSize = layerSize + headerSize + gridSize*4;
-	
-	unsigned char* buffer = (unsigned char*)alloc->alloc(bufferSize);
-	if (!buffer)
-		return DT_FAILURE | DT_OUT_OF_MEMORY;
-	memset(buffer, 0, bufferSize);
-
-	dtTileCacheLayer* layer = (dtTileCacheLayer*)buffer;
-	dtTileCacheLayerHeader* header = (dtTileCacheLayerHeader*)(buffer + layerSize);
-	unsigned char* grids = buffer + layerSize + headerSize;
-	const int gridsSize = bufferSize - (layerSize + headerSize); 
-	
-	// Copy header
-	memcpy(header, compressedHeader, headerSize);
-	// Decompress grid.
-	int size = 0;
-	dtStatus status = comp->decompress(compressed+headerSize, compressedSize-headerSize,
-									   grids, gridsSize, &size);
-	if (dtStatusFailed(status))
-	{
-		alloc->free(buffer);
-		return status;
-	}
-	
-	layer->header = header;
-	layer->heights = grids;
-	layer->areas = grids + gridSize;
-	layer->cons = grids + gridSize*2;
-	layer->regs = grids + gridSize*3;
-	
-	*layerOut = layer;
-	
-	return DT_SUCCESS;
-}
-
-
-
-bool dtTileCacheHeaderSwapEndian(unsigned char* data, const int dataSize)
-{
-	dtIgnoreUnused(dataSize);
-	dtTileCacheLayerHeader* header = (dtTileCacheLayerHeader*)data;
-	
-	int swappedMagic = DT_TILECACHE_MAGIC;
-	int swappedVersion = DT_TILECACHE_VERSION;
-	dtSwapEndian(&swappedMagic);
-	dtSwapEndian(&swappedVersion);
-	
-	if ((header->magic != DT_TILECACHE_MAGIC || header->version != DT_TILECACHE_VERSION) &&
-		(header->magic != swappedMagic || header->version != swappedVersion))
-	{
-		return false;
-	}
-	
-	dtSwapEndian(&header->magic);
-	dtSwapEndian(&header->version);
-	dtSwapEndian(&header->tx);
-	dtSwapEndian(&header->ty);
-	dtSwapEndian(&header->tlayer);
-	dtSwapEndian(&header->bmin[0]);
-	dtSwapEndian(&header->bmin[1]);
-	dtSwapEndian(&header->bmin[2]);
-	dtSwapEndian(&header->bmax[0]);
-	dtSwapEndian(&header->bmax[1]);
-	dtSwapEndian(&header->bmax[2]);
-	dtSwapEndian(&header->hmin);
-	dtSwapEndian(&header->hmax);
-	
-	// width, height, minx, maxx, miny, maxy are unsigned char, no need to swap.
-	
-	return true;
-}
-

+ 0 - 156
panda/src/recastdetour/DetourTileCacheBuilder.h

@@ -1,156 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 DETOURTILECACHEBUILDER_H
-#define DETOURTILECACHEBUILDER_H
-
-#include "DetourAlloc.h"
-#include "DetourStatus.h"
-
-static const int DT_TILECACHE_MAGIC = 'D'<<24 | 'T'<<16 | 'L'<<8 | 'R'; ///< 'DTLR';
-static const int DT_TILECACHE_VERSION = 1;
-
-static const unsigned char DT_TILECACHE_NULL_AREA = 0;
-static const unsigned char DT_TILECACHE_WALKABLE_AREA = 63;
-static const unsigned short DT_TILECACHE_NULL_IDX = 0xffff;
-
-struct dtTileCacheLayerHeader
-{
-	int magic;								///< Data magic
-	int version;							///< Data version
-	int tx,ty,tlayer;
-	float bmin[3], bmax[3];
-	unsigned short hmin, hmax;				///< Height min/max range
-	unsigned char width, height;			///< Dimension of the layer.
-	unsigned char minx, maxx, miny, maxy;	///< Usable sub-region.
-};
-
-struct dtTileCacheLayer
-{
-	dtTileCacheLayerHeader* header;
-	unsigned char regCount;					///< Region count.
-	unsigned char* heights;
-	unsigned char* areas;
-	unsigned char* cons;
-	unsigned char* regs;
-};
-
-struct dtTileCacheContour
-{
-	int nverts;
-	unsigned char* verts;
-	unsigned char reg;
-	unsigned char area;
-};
-
-struct dtTileCacheContourSet
-{
-	int nconts;
-	dtTileCacheContour* conts;
-};
-
-struct dtTileCachePolyMesh
-{
-	int nvp;
-	int nverts;				///< Number of vertices.
-	int npolys;				///< Number of polygons.
-	unsigned short* verts;	///< Vertices of the mesh, 3 elements per vertex.
-	unsigned short* polys;	///< Polygons of the mesh, nvp*2 elements per polygon.
-	unsigned short* flags;	///< Per polygon flags.
-	unsigned char* areas;	///< Area ID of polygons.
-};
-
-
-struct dtTileCacheAlloc
-{
-	virtual ~dtTileCacheAlloc() {}
-
-	virtual void reset() {}
-	
-	virtual void* alloc(const size_t size)
-	{
-		return dtAlloc(size, DT_ALLOC_TEMP);
-	}
-	
-	virtual void free(void* ptr)
-	{
-		dtFree(ptr);
-	}
-};
-
-struct dtTileCacheCompressor
-{
-	virtual ~dtTileCacheCompressor() { }
-
-	virtual int maxCompressedSize(const int bufferSize) = 0;
-	virtual dtStatus compress(const unsigned char* buffer, const int bufferSize,
-							  unsigned char* compressed, const int maxCompressedSize, int* compressedSize) = 0;
-	virtual dtStatus decompress(const unsigned char* compressed, const int compressedSize,
-								unsigned char* buffer, const int maxBufferSize, int* bufferSize) = 0;
-};
-
-
-dtStatus dtBuildTileCacheLayer(dtTileCacheCompressor* comp,
-							   dtTileCacheLayerHeader* header,
-							   const unsigned char* heights,
-							   const unsigned char* areas,
-							   const unsigned char* cons,
-							   unsigned char** outData, int* outDataSize);
-
-void dtFreeTileCacheLayer(dtTileCacheAlloc* alloc, dtTileCacheLayer* layer);
-
-dtStatus dtDecompressTileCacheLayer(dtTileCacheAlloc* alloc, dtTileCacheCompressor* comp,
-									unsigned char* compressed, const int compressedSize,
-									dtTileCacheLayer** layerOut);
-
-dtTileCacheContourSet* dtAllocTileCacheContourSet(dtTileCacheAlloc* alloc);
-void dtFreeTileCacheContourSet(dtTileCacheAlloc* alloc, dtTileCacheContourSet* cset);
-
-dtTileCachePolyMesh* dtAllocTileCachePolyMesh(dtTileCacheAlloc* alloc);
-void dtFreeTileCachePolyMesh(dtTileCacheAlloc* alloc, dtTileCachePolyMesh* lmesh);
-
-dtStatus dtMarkCylinderArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
-							const float* pos, const float radius, const float height, const unsigned char areaId);
-
-dtStatus dtMarkBoxArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
-					   const float* bmin, const float* bmax, const unsigned char areaId);
-
-dtStatus dtMarkBoxArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
-					   const float* center, const float* halfExtents, const float* rotAux, const unsigned char areaId);
-
-dtStatus dtBuildTileCacheRegions(dtTileCacheAlloc* alloc,
-								 dtTileCacheLayer& layer,
-								 const int walkableClimb);
-
-dtStatus dtBuildTileCacheContours(dtTileCacheAlloc* alloc,
-								  dtTileCacheLayer& layer,
-								  const int walkableClimb, 	const float maxError,
-								  dtTileCacheContourSet& lcset);
-
-dtStatus dtBuildTileCachePolyMesh(dtTileCacheAlloc* alloc,
-								  dtTileCacheContourSet& lcset,
-								  dtTileCachePolyMesh& mesh);
-
-/// Swaps the endianess of the compressed tile data's header (#dtTileCacheLayerHeader).
-/// Tile layer data does not need endian swapping as it consits only of bytes.
-///  @param[in,out]	data		The tile data array.
-///  @param[in]		dataSize	The size of the data array.
-bool dtTileCacheHeaderSwapEndian(unsigned char* data, const int dataSize);
-
-
-#endif // DETOURTILECACHEBUILDER_H

+ 0 - 135
panda/src/recastdetour/InputGeom.h

@@ -1,135 +0,0 @@
-
-
-#ifndef INPUTGEOM_H
-#define INPUTGEOM_H
-
-#include "MeshLoaderObj.h"
-
-static const int MAX_CONVEXVOL_PTS = 12;
-struct ConvexVolume
-{
-	float verts[MAX_CONVEXVOL_PTS * 3];
-	float hmin, hmax;
-	int nverts;
-	int area;
-};
-
-struct BuildSettings
-{
-	// Cell size in world units
-	float cellSize;
-	// Cell height in world units
-	float cellHeight;
-	// Agent height in world units
-	float agentHeight;
-	// Agent radius in world units
-	float agentRadius;
-	// Agent max climb in world units
-	float agentMaxClimb;
-	// Agent max slope in degrees
-	float agentMaxSlope;
-	// Region minimum size in voxels.
-	// regionMinSize = sqrt(regionMinArea)
-	float regionMinSize;
-	// Region merge size in voxels.
-	// regionMergeSize = sqrt(regionMergeArea)
-	float regionMergeSize;
-	// Edge max length in world units
-	float edgeMaxLen;
-	// Edge max error in voxels
-	float edgeMaxError;
-	float vertsPerPoly;
-	// Detail sample distance in voxels
-	float detailSampleDist;
-	// Detail sample max error in voxel heights.
-	float detailSampleMaxError;
-	// Partition type, see SamplePartitionType
-	int partitionType;
-	// Bounds of the area to mesh
-	float navMeshBMin[3];
-	float navMeshBMax[3];
-	// Size of the tiles in voxels
-	float tileSize;
-};
-
-class InputGeom
-{
-	rcMeshLoaderObj* m_mesh;
-	float m_meshBMin[3], m_meshBMax[3];
-	BuildSettings m_buildSettings;
-	bool m_hasBuildSettings;
-
-	/// @name Off-Mesh connections.
-	///@{
-	static const int MAX_OFFMESH_CONNECTIONS = 256;
-	float m_offMeshConVerts[MAX_OFFMESH_CONNECTIONS * 3 * 2];
-	float m_offMeshConRads[MAX_OFFMESH_CONNECTIONS];
-	unsigned char m_offMeshConDirs[MAX_OFFMESH_CONNECTIONS];
-	unsigned char m_offMeshConAreas[MAX_OFFMESH_CONNECTIONS];
-	unsigned short m_offMeshConFlags[MAX_OFFMESH_CONNECTIONS];
-	unsigned int m_offMeshConId[MAX_OFFMESH_CONNECTIONS];
-	int m_offMeshConCount;
-	///@}
-
-	/// @name Convex Volumes.
-	///@{
-	static const int MAX_VOLUMES = 256;
-	ConvexVolume m_volumes[MAX_VOLUMES];
-	int m_volumeCount;
-	///@}
-
-	bool loadMesh(class rcContext* ctx, const std::string& filepath);
-	bool loadMesh(class rcContext* ctx, NodePath node);
-	bool loadGeomSet(class rcContext* ctx, const std::string& filepath);
-public:
-	InputGeom();
-	~InputGeom();
-
-
-	bool load(class rcContext* ctx, const std::string& filepath);
-	bool load(class rcContext* ctx, NodePath node);
-	bool saveGeomSet(const BuildSettings* settings);
-
-
-
-	/// Method to return static mesh data.
-	const rcMeshLoaderObj* getMesh() const { return m_mesh; }
-	const float* getMeshBoundsMin() const { return m_meshBMin; }
-	const float* getMeshBoundsMax() const { return m_meshBMax; }
-	const float* getNavMeshBoundsMin() const { return m_hasBuildSettings ? m_buildSettings.navMeshBMin : m_meshBMin; }
-	const float* getNavMeshBoundsMax() const { return m_hasBuildSettings ? m_buildSettings.navMeshBMax : m_meshBMax; }
-	const BuildSettings* getBuildSettings() const { return m_hasBuildSettings ? &m_buildSettings : 0; }
-	bool raycastMesh(float* src, float* dst, float& tmin);
-
-	/// @name Off-Mesh connections.
-	///@{
-	int getOffMeshConnectionCount() const { return m_offMeshConCount; }
-	const float* getOffMeshConnectionVerts() const { return m_offMeshConVerts; }
-	const float* getOffMeshConnectionRads() const { return m_offMeshConRads; }
-	const unsigned char* getOffMeshConnectionDirs() const { return m_offMeshConDirs; }
-	const unsigned char* getOffMeshConnectionAreas() const { return m_offMeshConAreas; }
-	const unsigned short* getOffMeshConnectionFlags() const { return m_offMeshConFlags; }
-	const unsigned int* getOffMeshConnectionId() const { return m_offMeshConId; }
-	void addOffMeshConnection(const float* spos, const float* epos, const float rad,
-		unsigned char bidir, unsigned char area, unsigned short flags);
-	void deleteOffMeshConnection(int i);
-	void drawOffMeshConnections(struct duDebugDraw* dd, bool hilight = false);
-	///@}
-
-	/// @name Box Volumes.
-	///@{
-	int getConvexVolumeCount() const { return m_volumeCount; }
-	const ConvexVolume* getConvexVolumes() const { return m_volumes; }
-	void addConvexVolume(const float* verts, const int nverts,
-		const float minh, const float maxh, unsigned char area);
-	void deleteConvexVolume(int i);
-	void drawConvexVolumes(struct duDebugDraw* dd, bool hilight = false);
-	///@}
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	InputGeom(const InputGeom&);
-	InputGeom& operator=(const InputGeom&);
-};
-
-#endif // INPUTGEOM_H

+ 0 - 50
panda/src/recastdetour/MeshLoaderObj.h

@@ -1,50 +0,0 @@
-
-
-#ifndef MESHLOADER_OBJ
-#define MESHLOADER_OBJ
-
-#include <string>
-#include "geom.h"
-
-class rcMeshLoaderObj
-{
-public:
-	rcMeshLoaderObj();
-	~rcMeshLoaderObj();
-
-	bool load(const std::string& fileName);
-	bool load(NodePath node);
-
-	const float* getVerts() const { return m_verts; }
-	const float* getNormals() const { return m_normals; }
-	const int* getTris() const { return m_tris; }
-	int getVertCount() const { return m_vertCount; }
-	int getTriCount() const { return m_triCount; }
-	const std::string& getFileName() const { return m_filename; }
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	rcMeshLoaderObj(const rcMeshLoaderObj&);
-	rcMeshLoaderObj& operator=(const rcMeshLoaderObj&);
-
-	void addVertex(float x, float y, float z, int& cap);
-	void addTriangle(int a, int b, int c, int& cap);
-
-
-	void processGeomNode(GeomNode *geomnode, int& vcap, int& tcap);
-	void processGeom(CPT(Geom) geom, int& vcap, int& tcap);
-	void processVertexData(const GeomVertexData *vdata, int& vcap);
-	void processPrimitive(const GeomPrimitive *orig_prim, const GeomVertexData *vdata, int& tcap);
-
-	std::string m_filename;
-	float m_scale;
-	float* m_verts;
-	int* m_tris;
-	float* m_normals;
-	int m_vertCount;
-	int m_triCount;
-
-	int temp_vcount;
-};
-
-#endif // MESHLOADER_OBJ

+ 0 - 105
panda/src/recastdetour/NavMeshSample.h

@@ -1,105 +0,0 @@
-#ifndef NAVMESHSAMPLE_H
-#define NAVMESHSAMPLE_H
-
-#ifndef CPPPARSER
-#include "Recast.h"
-#else
-class rcContext;
-struct rcHeightfield;
-struct rcCompactHeightfield;
-struct rcContourSet;
-struct rcPolyMesh;
-struct rcConfig;
-struct rcPolyMeshDetail;
-#endif
-
-#include "InputGeom.h"
-#include <string>
-#include "geom.h"
-#include "geomNode.h"
-#include "nodePath.h"
-
-class NavMeshSample
-{
-protected:
-	class InputGeom* m_geom;
-	class dtNavMesh* m_navMesh;
-	class dtNavMeshQuery* m_navQuery;
-	class dtCrowd* m_crowd;
-
-	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;
-	float m_detailSampleDist;
-	float m_detailSampleMaxError;
-	int m_partitionType;
-
-	bool m_filterLowHangingObstacles;
-	bool m_filterLedgeSpans;
-	bool m_filterWalkableLowHeightSpans;
-
-
-	rcContext* m_ctx;
-
-	dtNavMesh* loadAll(const std::string& path);
-	void saveAll(const std::string& path, const dtNavMesh* mesh);
-
-	unsigned char* m_triareas;
-	rcHeightfield* m_solid;
-	rcCompactHeightfield* m_chf;
-	rcContourSet* m_cset;
-	rcPolyMesh* m_pmesh;
-	rcConfig m_cfg;
-	rcPolyMeshDetail* m_dmesh;
-
-	void cleanup();
-
-public:
-
-	NavMeshSample();
-	~NavMeshSample();
-	void setContext(rcContext* ctx) { m_ctx = ctx; }
-	
-	virtual void collectSettings(struct BuildSettings& settings);
-
-	void resetCommonSettings();
-	void handleCommonSettings();
-
-	bool handleBuild();
-	void LoadGeom(const std::string& filepath)
-	{ 
-		m_geom = new InputGeom;
-		m_geom->load(m_ctx, filepath);
-	}
-	void LoadGeom(NodePath node)
-	{
-		m_geom = new InputGeom;
-		m_geom->load(m_ctx, node);
-	}
-
-	PT(GeomNode) getPolyMeshGeom();
-
-
-
-private:
-	// Explicitly disabled copy constructor and copy assignment operator.
-	NavMeshSample(const NavMeshSample&);
-	NavMeshSample& operator=(const NavMeshSample&);
-};
-
-enum SamplePartitionType
-{
-	SAMPLE_PARTITION_WATERSHED,
-	SAMPLE_PARTITION_MONOTONE,
-	SAMPLE_PARTITION_LAYERS,
-};
-
-#endif // NAVMESHSAMPLE_H

+ 0 - 1064
panda/src/recastdetour/RecastDebugDraw.cpp

@@ -1,1064 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 <math.h>
-#include "DebugDraw.h"
-#include "RecastDebugDraw.h"
-#include "Recast.h"
-
-void duDebugDrawTriMesh(duDebugDraw* dd, const float* verts, int /*nverts*/,
-						const int* tris, const float* normals, int ntris,
-						const unsigned char* flags, const float texScale)
-{
-	if (!dd) return;
-	if (!verts) return;
-	if (!tris) return;
-	if (!normals) return;
-
-	float uva[2];
-	float uvb[2];
-	float uvc[2];
-
-	const unsigned int unwalkable = duRGBA(192,128,0,255);
-
-	dd->texture(true);
-
-	dd->begin(DU_DRAW_TRIS);
-	for (int i = 0; i < ntris*3; i += 3)
-	{
-		const float* norm = &normals[i];
-		unsigned int color;
-		unsigned char a = (unsigned char)(220*(2+norm[0]+norm[1])/4);
-		if (flags && !flags[i/3])
-			color = duLerpCol(duRGBA(a,a,a,255), unwalkable, 64);
-		else
-			color = duRGBA(a,a,a,255);
-
-		const float* va = &verts[tris[i+0]*3];
-		const float* vb = &verts[tris[i+1]*3];
-		const float* vc = &verts[tris[i+2]*3];
-		
-		int ax = 0, ay = 0;
-		if (rcAbs(norm[1]) > rcAbs(norm[ax]))
-			ax = 1;
-		if (rcAbs(norm[2]) > rcAbs(norm[ax]))
-			ax = 2;
-		ax = (1<<ax)&3; // +1 mod 3
-		ay = (1<<ax)&3; // +1 mod 3
-
-		uva[0] = va[ax]*texScale;
-		uva[1] = va[ay]*texScale;
-		uvb[0] = vb[ax]*texScale;
-		uvb[1] = vb[ay]*texScale;
-		uvc[0] = vc[ax]*texScale;
-		uvc[1] = vc[ay]*texScale;
-		
-		dd->vertex(va, color, uva);
-		dd->vertex(vb, color, uvb);
-		dd->vertex(vc, color, uvc);
-	}
-	dd->end();
-	dd->texture(false);
-}
-
-void duDebugDrawTriMeshSlope(duDebugDraw* dd, const float* verts, int /*nverts*/,
-							 const int* tris, const float* normals, int ntris,
-							 const float walkableSlopeAngle, const float texScale)
-{
-	if (!dd) return;
-	if (!verts) return;
-	if (!tris) return;
-	if (!normals) return;
-	
-	const float walkableThr = cosf(walkableSlopeAngle/180.0f*DU_PI);
-	
-	float uva[2];
-	float uvb[2];
-	float uvc[2];
-	
-	dd->texture(true);
-
-	const unsigned int unwalkable = duRGBA(192,128,0,255);
-	
-	dd->begin(DU_DRAW_TRIS);
-	for (int i = 0; i < ntris*3; i += 3)
-	{
-		const float* norm = &normals[i];
-		unsigned int color;
-		unsigned char a = (unsigned char)(220*(2+norm[0]+norm[1])/4);
-		if (norm[1] < walkableThr)
-			color = duLerpCol(duRGBA(a,a,a,255), unwalkable, 64);
-		else
-			color = duRGBA(a,a,a,255);
-		
-		const float* va = &verts[tris[i+0]*3];
-		const float* vb = &verts[tris[i+1]*3];
-		const float* vc = &verts[tris[i+2]*3];
-		
-		int ax = 0, ay = 0;
-		if (rcAbs(norm[1]) > rcAbs(norm[ax]))
-			ax = 1;
-		if (rcAbs(norm[2]) > rcAbs(norm[ax]))
-			ax = 2;
-		ax = (1<<ax)&3; // +1 mod 3
-		ay = (1<<ax)&3; // +1 mod 3
-		
-		uva[0] = va[ax]*texScale;
-		uva[1] = va[ay]*texScale;
-		uvb[0] = vb[ax]*texScale;
-		uvb[1] = vb[ay]*texScale;
-		uvc[0] = vc[ax]*texScale;
-		uvc[1] = vc[ay]*texScale;
-		
-		dd->vertex(va, color, uva);
-		dd->vertex(vb, color, uvb);
-		dd->vertex(vc, color, uvc);
-	}
-	dd->end();
-
-	dd->texture(false);
-}
-
-void duDebugDrawHeightfieldSolid(duDebugDraw* dd, const rcHeightfield& hf)
-{
-	if (!dd) return;
-
-	const float* orig = hf.bmin;
-	const float cs = hf.cs;
-	const float ch = hf.ch;
-	
-	const int w = hf.width;
-	const int h = hf.height;
-		
-	unsigned int fcol[6];
-	duCalcBoxColors(fcol, duRGBA(255,255,255,255), duRGBA(255,255,255,255));
-	
-	dd->begin(DU_DRAW_QUADS);
-	
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			float fx = orig[0] + x*cs;
-			float fz = orig[2] + y*cs;
-			const rcSpan* s = hf.spans[x + y*w];
-			while (s)
-			{
-				duAppendBox(dd, fx, orig[1]+s->smin*ch, fz, fx+cs, orig[1] + s->smax*ch, fz+cs, fcol);
-				s = s->next;
-			}
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawHeightfieldWalkable(duDebugDraw* dd, const rcHeightfield& hf)
-{
-	if (!dd) return;
-
-	const float* orig = hf.bmin;
-	const float cs = hf.cs;
-	const float ch = hf.ch;
-	
-	const int w = hf.width;
-	const int h = hf.height;
-	
-	unsigned int fcol[6];
-	duCalcBoxColors(fcol, duRGBA(255,255,255,255), duRGBA(217,217,217,255));
-
-	dd->begin(DU_DRAW_QUADS);
-	
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			float fx = orig[0] + x*cs;
-			float fz = orig[2] + y*cs;
-			const rcSpan* s = hf.spans[x + y*w];
-			while (s)
-			{
-				if (s->area == RC_WALKABLE_AREA)
-					fcol[0] = duRGBA(64,128,160,255);
-				else if (s->area == RC_NULL_AREA)
-					fcol[0] = duRGBA(64,64,64,255);
-				else
-					fcol[0] = duMultCol(dd->areaToCol(s->area), 200);
-				
-				duAppendBox(dd, fx, orig[1]+s->smin*ch, fz, fx+cs, orig[1] + s->smax*ch, fz+cs, fcol);
-				s = s->next;
-			}
-		}
-	}
-	
-	dd->end();
-}
-
-void duDebugDrawCompactHeightfieldSolid(duDebugDraw* dd, const rcCompactHeightfield& chf)
-{
-	if (!dd) return;
-
-	const float cs = chf.cs;
-	const float ch = chf.ch;
-
-	dd->begin(DU_DRAW_QUADS);
-	
-	for (int y = 0; y < chf.height; ++y)
-	{
-		for (int x = 0; x < chf.width; ++x)
-		{
-			const float fx = chf.bmin[0] + x*cs;
-			const float fz = chf.bmin[2] + y*cs;
-			const rcCompactCell& c = chf.cells[x+y*chf.width];
-
-			for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
-			{
-				const rcCompactSpan& s = chf.spans[i];
-
-				const unsigned char area = chf.areas[i];
-				unsigned int color;
-				if (area == RC_WALKABLE_AREA)
-					color = duRGBA(0,192,255,64);
-				else if (area == RC_NULL_AREA)
-					color = duRGBA(0,0,0,64);
-				else
-					color = dd->areaToCol(area);
-				
-				const float fy = chf.bmin[1] + (s.y+1)*ch;
-				dd->vertex(fx, fy, fz, color);
-				dd->vertex(fx, fy, fz+cs, color);
-				dd->vertex(fx+cs, fy, fz+cs, color);
-				dd->vertex(fx+cs, fy, fz, color);
-			}
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawCompactHeightfieldRegions(duDebugDraw* dd, const rcCompactHeightfield& chf)
-{
-	if (!dd) return;
-
-	const float cs = chf.cs;
-	const float ch = chf.ch;
-
-	dd->begin(DU_DRAW_QUADS);
-
-	for (int y = 0; y < chf.height; ++y)
-	{
-		for (int x = 0; x < chf.width; ++x)
-		{
-			const float fx = chf.bmin[0] + x*cs;
-			const float fz = chf.bmin[2] + y*cs;
-			const rcCompactCell& c = chf.cells[x+y*chf.width];
-			
-			for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
-			{
-				const rcCompactSpan& s = chf.spans[i];
-				const float fy = chf.bmin[1] + (s.y)*ch;
-				unsigned int color;
-				if (s.reg)
-					color = duIntToCol(s.reg, 192);
-				else
-					color = duRGBA(0,0,0,64);
-
-				dd->vertex(fx, fy, fz, color);
-				dd->vertex(fx, fy, fz+cs, color);
-				dd->vertex(fx+cs, fy, fz+cs, color);
-				dd->vertex(fx+cs, fy, fz, color);
-			}
-		}
-	}
-	
-	dd->end();
-}
-
-
-void duDebugDrawCompactHeightfieldDistance(duDebugDraw* dd, const rcCompactHeightfield& chf)
-{
-	if (!dd) return;
-	if (!chf.dist) return;
-		
-	const float cs = chf.cs;
-	const float ch = chf.ch;
-			
-	float maxd = chf.maxDistance;
-	if (maxd < 1.0f) maxd = 1;
-	const float dscale = 255.0f / maxd;
-	
-	dd->begin(DU_DRAW_QUADS);
-	
-	for (int y = 0; y < chf.height; ++y)
-	{
-		for (int x = 0; x < chf.width; ++x)
-		{
-			const float fx = chf.bmin[0] + x*cs;
-			const float fz = chf.bmin[2] + y*cs;
-			const rcCompactCell& c = chf.cells[x+y*chf.width];
-			
-			for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
-			{
-				const rcCompactSpan& s = chf.spans[i];
-				const float fy = chf.bmin[1] + (s.y+1)*ch;
-				const unsigned char cd = (unsigned char)(chf.dist[i] * dscale);
-				const unsigned int color = duRGBA(cd,cd,cd,255);
-				dd->vertex(fx, fy, fz, color);
-				dd->vertex(fx, fy, fz+cs, color);
-				dd->vertex(fx+cs, fy, fz+cs, color);
-				dd->vertex(fx+cs, fy, fz, color);
-			}
-		}
-	}
-	dd->end();
-}
-
-static void drawLayerPortals(duDebugDraw* dd, const rcHeightfieldLayer* layer)
-{
-	const float cs = layer->cs;
-	const float ch = layer->ch;
-	const int w = layer->width;
-	const int h = layer->height;
-	
-	unsigned int pcol = duRGBA(255,255,255,255);
-	
-	const int segs[4*4] = {0,0,0,1, 0,1,1,1, 1,1,1,0, 1,0,0,0};
-	
-	// Layer portals
-	dd->begin(DU_DRAW_LINES, 2.0f);
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			const int idx = x+y*w;
-			const int lh = (int)layer->heights[idx];
-			if (lh == 255) continue;
-			
-			for (int dir = 0; dir < 4; ++dir)
-			{
-				if (layer->cons[idx] & (1<<(dir+4)))
-				{
-					const int* seg = &segs[dir*4];
-					const float ax = layer->bmin[0] + (x+seg[0])*cs;
-					const float ay = layer->bmin[1] + (lh+2)*ch;
-					const float az = layer->bmin[2] + (y+seg[1])*cs;
-					const float bx = layer->bmin[0] + (x+seg[2])*cs;
-					const float by = layer->bmin[1] + (lh+2)*ch;
-					const float bz = layer->bmin[2] + (y+seg[3])*cs;
-					dd->vertex(ax, ay, az, pcol);
-					dd->vertex(bx, by, bz, pcol);
-				}
-			}
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawHeightfieldLayer(duDebugDraw* dd, const struct rcHeightfieldLayer& layer, const int idx)
-{
-	const float cs = layer.cs;
-	const float ch = layer.ch;
-	const int w = layer.width;
-	const int h = layer.height;
-	
-	unsigned int color = duIntToCol(idx+1, 255);
-	
-	// Layer bounds
-	float bmin[3], bmax[3];
-	bmin[0] = layer.bmin[0] + layer.minx*cs;
-	bmin[1] = layer.bmin[1];
-	bmin[2] = layer.bmin[2] + layer.miny*cs;
-	bmax[0] = layer.bmin[0] + (layer.maxx+1)*cs;
-	bmax[1] = layer.bmax[1];
-	bmax[2] = layer.bmin[2] + (layer.maxy+1)*cs;
-	duDebugDrawBoxWire(dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], duTransCol(color,128), 2.0f);
-	
-	// Layer height
-	dd->begin(DU_DRAW_QUADS);
-	for (int y = 0; y < h; ++y)
-	{
-		for (int x = 0; x < w; ++x)
-		{
-			const int lidx = x+y*w;
-			const int lh = (int)layer.heights[lidx];
-			if (h == 0xff) continue;
-			const unsigned char area = layer.areas[lidx];
-			
-			unsigned int col;
-			if (area == RC_WALKABLE_AREA)
-				col = duLerpCol(color, duRGBA(0,192,255,64), 32);
-			else if (area == RC_NULL_AREA)
-				col = duLerpCol(color, duRGBA(0,0,0,64), 32);
-			else
-				col = duLerpCol(color, dd->areaToCol(area), 32);
-			
-			const float fx = layer.bmin[0] + x*cs;
-			const float fy = layer.bmin[1] + (lh+1)*ch;
-			const float fz = layer.bmin[2] + y*cs;
-			
-			dd->vertex(fx, fy, fz, col);
-			dd->vertex(fx, fy, fz+cs, col);
-			dd->vertex(fx+cs, fy, fz+cs, col);
-			dd->vertex(fx+cs, fy, fz, col);
-		}
-	}
-	dd->end();
-	
-	// Portals
-	drawLayerPortals(dd, &layer);
-}
-
-void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset)
-{
-	if (!dd) return;
-	for (int i = 0; i < lset.nlayers; ++i)
-		duDebugDrawHeightfieldLayer(dd, lset.layers[i], i);
-}
-
-/*
-void duDebugDrawLayerContours(duDebugDraw* dd, const struct rcLayerContourSet& lcset)
-{
-	if (!dd) return;
-	
-	const float* orig = lcset.bmin;
-	const float cs = lcset.cs;
-	const float ch = lcset.ch;
-	
-	const unsigned char a = 255;// (unsigned char)(alpha*255.0f);
-	
-	const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
-
-	dd->begin(DU_DRAW_LINES, 2.0f);
-	
-	for (int i = 0; i < lcset.nconts; ++i)
-	{
-		const rcLayerContour& c = lcset.conts[i];
-		unsigned int color = 0;
-
-		color = duIntToCol(i, a);
-
-		for (int j = 0; j < c.nverts; ++j)
-		{
-			const int k = (j+1) % c.nverts;
-			const unsigned char* va = &c.verts[j*4];
-			const unsigned char* vb = &c.verts[k*4];
-			const float ax = orig[0] + va[0]*cs;
-			const float ay = orig[1] + (va[1]+1+(i&1))*ch;
-			const float az = orig[2] + va[2]*cs;
-			const float bx = orig[0] + vb[0]*cs;
-			const float by = orig[1] + (vb[1]+1+(i&1))*ch;
-			const float bz = orig[2] + vb[2]*cs;
-			unsigned int col = color;
-			if ((va[3] & 0xf) != 0xf)
-			{
-				col = duRGBA(255,255,255,128);
-				int d = va[3] & 0xf;
-				
-				const float cx = (ax+bx)*0.5f;
-				const float cy = (ay+by)*0.5f;
-				const float cz = (az+bz)*0.5f;
-				
-				const float dx = cx + offs[d*2+0]*2*cs;
-				const float dy = cy;
-				const float dz = cz + offs[d*2+1]*2*cs;
-				
-				dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
-				dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
-			}
-			
-			duAppendArrow(dd, ax,ay,az, bx,by,bz, 0.0f, cs*0.5f, col);
-		}
-	}
-	dd->end();
-	
-	dd->begin(DU_DRAW_POINTS, 4.0f);	
-	
-	for (int i = 0; i < lcset.nconts; ++i)
-	{
-		const rcLayerContour& c = lcset.conts[i];
-		unsigned int color = 0;
-		
-		for (int j = 0; j < c.nverts; ++j)
-		{
-			const unsigned char* va = &c.verts[j*4];
-
-			color = duDarkenCol(duIntToCol(i, a));
-			if (va[3] & 0x80)
-				color = duRGBA(255,0,0,255);
-
-			float fx = orig[0] + va[0]*cs;
-			float fy = orig[1] + (va[1]+1+(i&1))*ch;
-			float fz = orig[2] + va[2]*cs;
-			dd->vertex(fx,fy,fz, color);
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawLayerPolyMesh(duDebugDraw* dd, const struct rcLayerPolyMesh& lmesh)
-{
-	if (!dd) return;
-	
-	const int nvp = lmesh.nvp;
-	const float cs = lmesh.cs;
-	const float ch = lmesh.ch;
-	const float* orig = lmesh.bmin;
-	
-	const int offs[2*4] = {-1,0, 0,1, 1,0, 0,-1};
-
-	dd->begin(DU_DRAW_TRIS);
-	
-	for (int i = 0; i < lmesh.npolys; ++i)
-	{
-		const unsigned short* p = &lmesh.polys[i*nvp*2];
-		
-		unsigned int color;
-		if (lmesh.areas[i] == RC_WALKABLE_AREA)
-			color = duRGBA(0,192,255,64);
-		else if (lmesh.areas[i] == RC_NULL_AREA)
-			color = duRGBA(0,0,0,64);
-		else
-			color = duIntToCol(lmesh.areas[i], 255);
-		
-		unsigned short vi[3];
-		for (int j = 2; j < nvp; ++j)
-		{
-			if (p[j] == RC_MESH_NULL_IDX) break;
-			vi[0] = p[0];
-			vi[1] = p[j-1];
-			vi[2] = p[j];
-			for (int k = 0; k < 3; ++k)
-			{
-				const unsigned short* v = &lmesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x,y,z, color);
-			}
-		}
-	}
-	dd->end();
-	
-	// Draw neighbours edges
-	const unsigned int coln = duRGBA(0,48,64,32);
-	dd->begin(DU_DRAW_LINES, 1.5f);
-	for (int i = 0; i < lmesh.npolys; ++i)
-	{
-		const unsigned short* p = &lmesh.polys[i*nvp*2];
-		for (int j = 0; j < nvp; ++j)
-		{
-			if (p[j] == RC_MESH_NULL_IDX) break;
-			if (p[nvp+j] & 0x8000) continue;
-			const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1; 
-			int vi[2] = {p[j], p[nj]};
-			
-			for (int k = 0; k < 2; ++k)
-			{
-				const unsigned short* v = &lmesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x, y, z, coln);
-			}
-		}
-	}
-	dd->end();
-	
-	// Draw boundary edges
-	const unsigned int colb = duRGBA(0,48,64,220);
-	dd->begin(DU_DRAW_LINES, 2.5f);
-	for (int i = 0; i < lmesh.npolys; ++i)
-	{
-		const unsigned short* p = &lmesh.polys[i*nvp*2];
-		for (int j = 0; j < nvp; ++j)
-		{
-			if (p[j] == RC_MESH_NULL_IDX) break;
-			if ((p[nvp+j] & 0x8000) == 0) continue;
-			const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1; 
-			int vi[2] = {p[j], p[nj]};
-			
-			unsigned int col = colb;
-			if ((p[nvp+j] & 0xf) != 0xf)
-			{
-				const unsigned short* va = &lmesh.verts[vi[0]*3];
-				const unsigned short* vb = &lmesh.verts[vi[1]*3];
-
-				const float ax = orig[0] + va[0]*cs;
-				const float ay = orig[1] + (va[1]+1+(i&1))*ch;
-				const float az = orig[2] + va[2]*cs;
-				const float bx = orig[0] + vb[0]*cs;
-				const float by = orig[1] + (vb[1]+1+(i&1))*ch;
-				const float bz = orig[2] + vb[2]*cs;
-				
-				const float cx = (ax+bx)*0.5f;
-				const float cy = (ay+by)*0.5f;
-				const float cz = (az+bz)*0.5f;
-				
-				int d = p[nvp+j] & 0xf;
-				
-				const float dx = cx + offs[d*2+0]*2*cs;
-				const float dy = cy;
-				const float dz = cz + offs[d*2+1]*2*cs;
-				
-				dd->vertex(cx,cy,cz,duRGBA(255,0,0,255));
-				dd->vertex(dx,dy,dz,duRGBA(255,0,0,255));
-				
-				col = duRGBA(255,255,255,128);
-			}
-							 
-			for (int k = 0; k < 2; ++k)
-			{
-				const unsigned short* v = &lmesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x, y, z, col);
-			}
-		}
-	}
-	dd->end();
-	
-	dd->begin(DU_DRAW_POINTS, 3.0f);
-	const unsigned int colv = duRGBA(0,0,0,220);
-	for (int i = 0; i < lmesh.nverts; ++i)
-	{
-		const unsigned short* v = &lmesh.verts[i*3];
-		const float x = orig[0] + v[0]*cs;
-		const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-		const float z = orig[2] + v[2]*cs;
-		dd->vertex(x,y,z, colv);
-	}
-	dd->end();
-}
-*/
-
-static void getContourCenter(const rcContour* cont, const float* orig, float cs, float ch, float* center)
-{
-	center[0] = 0;
-	center[1] = 0;
-	center[2] = 0;
-	if (!cont->nverts)
-		return;
-	for (int i = 0; i < cont->nverts; ++i)
-	{
-		const int* v = &cont->verts[i*4];
-		center[0] += (float)v[0];
-		center[1] += (float)v[1];
-		center[2] += (float)v[2];
-	}
-	const float s = 1.0f / cont->nverts;
-	center[0] *= s * cs;
-	center[1] *= s * ch;
-	center[2] *= s * cs;
-	center[0] += orig[0];
-	center[1] += orig[1] + 4*ch;
-	center[2] += orig[2];
-}
-
-static const rcContour* findContourFromSet(const rcContourSet& cset, unsigned short reg)
-{
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		if (cset.conts[i].reg == reg)
-			return &cset.conts[i];
-	}
-	return 0;
-}
-
-void duDebugDrawRegionConnections(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
-{
-	if (!dd) return;
-	
-	const float* orig = cset.bmin;
-	const float cs = cset.cs;
-	const float ch = cset.ch;
-	
-	// Draw centers
-	float pos[3], pos2[3];
-
-	unsigned int color = duRGBA(0,0,0,196);
-
-	dd->begin(DU_DRAW_LINES, 2.0f);
-
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		const rcContour* cont = &cset.conts[i];
-		getContourCenter(cont, orig, cs, ch, pos);
-		for (int j = 0; j < cont->nverts; ++j)
-		{
-			const int* v = &cont->verts[j*4];
-			if (v[3] == 0 || (unsigned short)v[3] < cont->reg) continue;
-			const rcContour* cont2 = findContourFromSet(cset, (unsigned short)v[3]);
-			if (cont2)
-			{
-				getContourCenter(cont2, orig, cs, ch, pos2);
-				duAppendArc(dd, pos[0],pos[1],pos[2], pos2[0],pos2[1],pos2[2], 0.25f, 0.6f, 0.6f, color);
-			}
-		}
-	}
-	
-	dd->end();
-
-	unsigned char a = (unsigned char)(alpha * 255.0f);
-
-	dd->begin(DU_DRAW_POINTS, 7.0f);
-
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		const rcContour* cont = &cset.conts[i];
-		unsigned int col = duDarkenCol(duIntToCol(cont->reg,a));
-		getContourCenter(cont, orig, cs, ch, pos);
-		dd->vertex(pos, col);
-	}
-	dd->end();
-}
-
-void duDebugDrawRawContours(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
-{
-	if (!dd) return;
-
-	const float* orig = cset.bmin;
-	const float cs = cset.cs;
-	const float ch = cset.ch;
-	
-	const unsigned char a = (unsigned char)(alpha*255.0f);
-	
-	dd->begin(DU_DRAW_LINES, 2.0f);
-			
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		const rcContour& c = cset.conts[i];
-		unsigned int color = duIntToCol(c.reg, a);
-
-		for (int j = 0; j < c.nrverts; ++j)
-		{
-			const int* v = &c.rverts[j*4];
-			float fx = orig[0] + v[0]*cs;
-			float fy = orig[1] + (v[1]+1+(i&1))*ch;
-			float fz = orig[2] + v[2]*cs;
-			dd->vertex(fx,fy,fz,color);
-			if (j > 0)
-				dd->vertex(fx,fy,fz,color);
-		}
-		// Loop last segment.
-		const int* v = &c.rverts[0];
-		float fx = orig[0] + v[0]*cs;
-		float fy = orig[1] + (v[1]+1+(i&1))*ch;
-		float fz = orig[2] + v[2]*cs;
-		dd->vertex(fx,fy,fz,color);
-	}
-	dd->end();
-
-	dd->begin(DU_DRAW_POINTS, 2.0f);	
-
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		const rcContour& c = cset.conts[i];
-		unsigned int color = duDarkenCol(duIntToCol(c.reg, a));
-		
-		for (int j = 0; j < c.nrverts; ++j)
-		{
-			const int* v = &c.rverts[j*4];
-			float off = 0;
-			unsigned int colv = color;
-			if (v[3] & RC_BORDER_VERTEX)
-			{
-				colv = duRGBA(255,255,255,a);
-				off = ch*2;
-			}
-			
-			float fx = orig[0] + v[0]*cs;
-			float fy = orig[1] + (v[1]+1+(i&1))*ch + off;
-			float fz = orig[2] + v[2]*cs;
-			dd->vertex(fx,fy,fz, colv);
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawContours(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
-{
-	if (!dd) return;
-
-	const float* orig = cset.bmin;
-	const float cs = cset.cs;
-	const float ch = cset.ch;
-	
-	const unsigned char a = (unsigned char)(alpha*255.0f);
-	
-	dd->begin(DU_DRAW_LINES, 2.5f);
-	
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		const rcContour& c = cset.conts[i];
-		if (!c.nverts)
-			continue;
-		const unsigned int color = duIntToCol(c.reg, a);
-		const unsigned int bcolor = duLerpCol(color,duRGBA(255,255,255,a),128);
-		for (int j = 0, k = c.nverts-1; j < c.nverts; k=j++)
-		{
-			const int* va = &c.verts[k*4];
-			const int* vb = &c.verts[j*4];
-			unsigned int col = (va[3] & RC_AREA_BORDER) ? bcolor : color; 
-			float fx,fy,fz;
-			fx = orig[0] + va[0]*cs;
-			fy = orig[1] + (va[1]+1+(i&1))*ch;
-			fz = orig[2] + va[2]*cs;
-			dd->vertex(fx,fy,fz, col);
-			fx = orig[0] + vb[0]*cs;
-			fy = orig[1] + (vb[1]+1+(i&1))*ch;
-			fz = orig[2] + vb[2]*cs;
-			dd->vertex(fx,fy,fz, col);
-		}
-	}
-	dd->end();
-
-	dd->begin(DU_DRAW_POINTS, 3.0f);
-	
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		const rcContour& c = cset.conts[i];
-		unsigned int color = duDarkenCol(duIntToCol(c.reg, a));
-		for (int j = 0; j < c.nverts; ++j)
-		{
-			const int* v = &c.verts[j*4];
-			float off = 0;
-			unsigned int colv = color;
-			if (v[3] & RC_BORDER_VERTEX)
-			{
-				colv = duRGBA(255,255,255,a);
-				off = ch*2;
-			}
-
-			float fx = orig[0] + v[0]*cs;
-			float fy = orig[1] + (v[1]+1+(i&1))*ch + off;
-			float fz = orig[2] + v[2]*cs;
-			dd->vertex(fx,fy,fz, colv);
-		}
-	}
-	dd->end();
-}
-
-void duDebugDrawPolyMesh(duDebugDraw* dd, const struct rcPolyMesh& mesh)
-{
-	if (!dd) return;
-
-	const int nvp = mesh.nvp;
-	const float cs = mesh.cs;
-	const float ch = mesh.ch;
-	const float* orig = mesh.bmin;
-	
-	dd->begin(DU_DRAW_TRIS);
-	
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		const unsigned short* p = &mesh.polys[i*nvp*2];
-		const unsigned char area = mesh.areas[i];
-		
-		unsigned int color;
-		if (area == RC_WALKABLE_AREA)
-			color = duRGBA(0,192,255,64);
-		else if (area == RC_NULL_AREA)
-			color = duRGBA(0,0,0,64);
-		else
-			color = dd->areaToCol(area);
-		
-		unsigned short vi[3];
-		for (int j = 2; j < nvp; ++j)
-		{
-			if (p[j] == RC_MESH_NULL_IDX) break;
-			vi[0] = p[0];
-			vi[1] = p[j-1];
-			vi[2] = p[j];
-			for (int k = 0; k < 3; ++k)
-			{
-				const unsigned short* v = &mesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x,y,z, color);
-			}
-		}
-	}
-	dd->end();
-
-	// Draw neighbours edges
-	const unsigned int coln = duRGBA(0,48,64,32);
-	dd->begin(DU_DRAW_LINES, 1.5f);
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		const unsigned short* p = &mesh.polys[i*nvp*2];
-		for (int j = 0; j < nvp; ++j)
-		{
-			if (p[j] == RC_MESH_NULL_IDX) break;
-			if (p[nvp+j] & 0x8000) continue;
-			const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1; 
-			const int vi[2] = {p[j], p[nj]};
-			
-			for (int k = 0; k < 2; ++k)
-			{
-				const unsigned short* v = &mesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x, y, z, coln);
-			}
-		}
-	}
-	dd->end();
-	
-	// Draw boundary edges
-	const unsigned int colb = duRGBA(0,48,64,220);
-	dd->begin(DU_DRAW_LINES, 2.5f);
-	for (int i = 0; i < mesh.npolys; ++i)
-	{
-		const unsigned short* p = &mesh.polys[i*nvp*2];
-		for (int j = 0; j < nvp; ++j)
-		{
-			if (p[j] == RC_MESH_NULL_IDX) break;
-			if ((p[nvp+j] & 0x8000) == 0) continue;
-			const int nj = (j+1 >= nvp || p[j+1] == RC_MESH_NULL_IDX) ? 0 : j+1; 
-			const int vi[2] = {p[j], p[nj]};
-			
-			unsigned int col = colb;
-			if ((p[nvp+j] & 0xf) != 0xf)
-				col = duRGBA(255,255,255,128);
-			for (int k = 0; k < 2; ++k)
-			{
-				const unsigned short* v = &mesh.verts[vi[k]*3];
-				const float x = orig[0] + v[0]*cs;
-				const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-				const float z = orig[2] + v[2]*cs;
-				dd->vertex(x, y, z, col);
-			}
-		}
-	}
-	dd->end();
-	
-	dd->begin(DU_DRAW_POINTS, 3.0f);
-	const unsigned int colv = duRGBA(0,0,0,220);
-	for (int i = 0; i < mesh.nverts; ++i)
-	{
-		const unsigned short* v = &mesh.verts[i*3];
-		const float x = orig[0] + v[0]*cs;
-		const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-		const float z = orig[2] + v[2]*cs;
-		dd->vertex(x,y,z, colv);
-	}
-	dd->end();
-}
-
-void duDebugDrawPolyMeshDetail(duDebugDraw* dd, const struct rcPolyMeshDetail& dmesh)
-{
-	if (!dd) return;
-
-	dd->begin(DU_DRAW_TRIS);
-	
-	for (int i = 0; i < dmesh.nmeshes; ++i)
-	{
-		const unsigned int* m = &dmesh.meshes[i*4];
-		const unsigned int bverts = m[0];
-		const unsigned int btris = m[2];
-		const int ntris = (int)m[3];
-		const float* verts = &dmesh.verts[bverts*3];
-		const unsigned char* tris = &dmesh.tris[btris*4];
-
-		unsigned int color = duIntToCol(i, 192);
-
-		for (int j = 0; j < ntris; ++j)
-		{
-			dd->vertex(&verts[tris[j*4+0]*3], color);
-			dd->vertex(&verts[tris[j*4+1]*3], color);
-			dd->vertex(&verts[tris[j*4+2]*3], color);
-		}
-	}
-	dd->end();
-
-	// Internal edges.
-	dd->begin(DU_DRAW_LINES, 1.0f);
-	const unsigned int coli = duRGBA(0,0,0,64);
-	for (int i = 0; i < dmesh.nmeshes; ++i)
-	{
-		const unsigned int* m = &dmesh.meshes[i*4];
-		const unsigned int bverts = m[0];
-		const unsigned int btris = m[2];
-		const int ntris = (int)m[3];
-		const float* verts = &dmesh.verts[bverts*3];
-		const unsigned char* tris = &dmesh.tris[btris*4];
-		
-		for (int j = 0; j < ntris; ++j)
-		{
-			const unsigned char* t = &tris[j*4];
-			for (int k = 0, kp = 2; k < 3; kp=k++)
-			{
-				unsigned char ef = (t[3] >> (kp*2)) & 0x3;
-				if (ef == 0)
-				{
-					// Internal edge
-					if (t[kp] < t[k])
-					{
-						dd->vertex(&verts[t[kp]*3], coli);
-						dd->vertex(&verts[t[k]*3], coli);
-					}
-				}
-			}
-		}
-	}
-	dd->end();
-	
-	// External edges.
-	dd->begin(DU_DRAW_LINES, 2.0f);
-	const unsigned int cole = duRGBA(0,0,0,64);
-	for (int i = 0; i < dmesh.nmeshes; ++i)
-	{
-		const unsigned int* m = &dmesh.meshes[i*4];
-		const unsigned int bverts = m[0];
-		const unsigned int btris = m[2];
-		const int ntris = (int)m[3];
-		const float* verts = &dmesh.verts[bverts*3];
-		const unsigned char* tris = &dmesh.tris[btris*4];
-		
-		for (int j = 0; j < ntris; ++j)
-		{
-			const unsigned char* t = &tris[j*4];
-			for (int k = 0, kp = 2; k < 3; kp=k++)
-			{
-				unsigned char ef = (t[3] >> (kp*2)) & 0x3;
-				if (ef != 0)
-				{
-					// Ext edge
-					dd->vertex(&verts[t[kp]*3], cole);
-					dd->vertex(&verts[t[k]*3], cole);
-				}
-			}
-		}
-	}
-	dd->end();
-	
-	dd->begin(DU_DRAW_POINTS, 3.0f);
-	const unsigned int colv = duRGBA(0,0,0,64);
-	for (int i = 0; i < dmesh.nmeshes; ++i)
-	{
-		const unsigned int* m = &dmesh.meshes[i*4];
-		const unsigned int bverts = m[0];
-		const int nverts = (int)m[1];
-		const float* verts = &dmesh.verts[bverts*3];
-		for (int j = 0; j < nverts; ++j)
-			dd->vertex(&verts[j*3], colv);
-	}
-	dd->end();
-}

+ 0 - 42
panda/src/recastdetour/RecastDebugDraw.h

@@ -1,42 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 RECAST_DEBUGDRAW_H
-#define RECAST_DEBUGDRAW_H
-
-void duDebugDrawTriMesh(struct duDebugDraw* dd, const float* verts, int nverts, const int* tris, const float* normals, int ntris, const unsigned char* flags, const float texScale);
-void duDebugDrawTriMeshSlope(struct duDebugDraw* dd, const float* verts, int nverts, const int* tris, const float* normals, int ntris, const float walkableSlopeAngle, const float texScale);
-
-void duDebugDrawHeightfieldSolid(struct duDebugDraw* dd, const struct rcHeightfield& hf);
-void duDebugDrawHeightfieldWalkable(struct duDebugDraw* dd, const struct rcHeightfield& hf);
-
-void duDebugDrawCompactHeightfieldSolid(struct duDebugDraw* dd, const struct rcCompactHeightfield& chf);
-void duDebugDrawCompactHeightfieldRegions(struct duDebugDraw* dd, const struct rcCompactHeightfield& chf);
-void duDebugDrawCompactHeightfieldDistance(struct duDebugDraw* dd, const struct rcCompactHeightfield& chf);
-
-void duDebugDrawHeightfieldLayer(duDebugDraw* dd, const struct rcHeightfieldLayer& layer, const int idx);
-void duDebugDrawHeightfieldLayers(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset);
-void duDebugDrawHeightfieldLayersRegions(duDebugDraw* dd, const struct rcHeightfieldLayerSet& lset);
-
-void duDebugDrawRegionConnections(struct duDebugDraw* dd, const struct rcContourSet& cset, const float alpha = 1.0f);
-void duDebugDrawRawContours(struct duDebugDraw* dd, const struct rcContourSet& cset, const float alpha = 1.0f);
-void duDebugDrawContours(struct duDebugDraw* dd, const struct rcContourSet& cset, const float alpha = 1.0f);
-void duDebugDrawPolyMesh(struct duDebugDraw* dd, const struct rcPolyMesh& mesh);
-void duDebugDrawPolyMeshDetail(struct duDebugDraw* dd, const struct rcPolyMeshDetail& dmesh);
-
-#endif // RECAST_DEBUGDRAW_H

+ 0 - 451
panda/src/recastdetour/RecastDump.cpp

@@ -1,451 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 <math.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include "Recast.h"
-#include "RecastAlloc.h"
-#include "RecastDump.h"
-
-
-duFileIO::~duFileIO()
-{
-	// Empty
-}
-	
-static void ioprintf(duFileIO* io, const char* format, ...)
-{
-	char line[256];
-	va_list ap;
-	va_start(ap, format);
-	const int n = vsnprintf(line, sizeof(line), format, ap);
-	va_end(ap);
-	if (n > 0)
-		io->write(line, sizeof(char)*n);
-}
-
-bool duDumpPolyMeshToObj(rcPolyMesh& pmesh, duFileIO* io)
-{
-	if (!io)
-	{
-		printf("duDumpPolyMeshToObj: input IO is null.\n"); 
-		return false;
-	}
-	if (!io->isWriting())
-	{
-		printf("duDumpPolyMeshToObj: input IO not writing.\n"); 
-		return false;
-	}
-	
-	const int nvp = pmesh.nvp;
-	const float cs = pmesh.cs;
-	const float ch = pmesh.ch;
-	const float* orig = pmesh.bmin;
-	
-	ioprintf(io, "# Recast Navmesh\n");
-	ioprintf(io, "o NavMesh\n");
-
-	ioprintf(io, "\n");
-	
-	for (int i = 0; i < pmesh.nverts; ++i)
-	{
-		const unsigned short* v = &pmesh.verts[i*3];
-		const float x = orig[0] + v[0]*cs;
-		const float y = orig[1] + (v[1]+1)*ch + 0.1f;
-		const float z = orig[2] + v[2]*cs;
-		ioprintf(io, "v %f %f %f\n", x,y,z);
-	}
-
-	ioprintf(io, "\n");
-
-	for (int i = 0; i < pmesh.npolys; ++i)
-	{
-		const unsigned short* p = &pmesh.polys[i*nvp*2];
-		for (int j = 2; j < nvp; ++j)
-		{
-			if (p[j] == RC_MESH_NULL_IDX) break;
-			ioprintf(io, "f %d %d %d\n", p[0]+1, p[j-1]+1, p[j]+1); 
-		}
-	}
-	
-	return true;
-}
-
-bool duDumpPolyMeshDetailToObj(rcPolyMeshDetail& dmesh, duFileIO* io)
-{
-	if (!io)
-	{
-		printf("duDumpPolyMeshDetailToObj: input IO is null.\n"); 
-		return false;
-	}
-	if (!io->isWriting())
-	{
-		printf("duDumpPolyMeshDetailToObj: input IO not writing.\n"); 
-		return false;
-	}
-	
-	ioprintf(io, "# Recast Navmesh\n");
-	ioprintf(io, "o NavMesh\n");
-	
-	ioprintf(io, "\n");
-
-	for (int i = 0; i < dmesh.nverts; ++i)
-	{
-		const float* v = &dmesh.verts[i*3];
-		ioprintf(io, "v %f %f %f\n", v[0],v[1],v[2]);
-	}
-	
-	ioprintf(io, "\n");
-	
-	for (int i = 0; i < dmesh.nmeshes; ++i)
-	{
-		const unsigned int* m = &dmesh.meshes[i*4];
-		const unsigned int bverts = m[0];
-		const unsigned int btris = m[2];
-		const unsigned int ntris = m[3];
-		const unsigned char* tris = &dmesh.tris[btris*4];
-		for (unsigned int j = 0; j < ntris; ++j)
-		{
-			ioprintf(io, "f %d %d %d\n",
-					(int)(bverts+tris[j*4+0])+1,
-					(int)(bverts+tris[j*4+1])+1,
-					(int)(bverts+tris[j*4+2])+1);
-		}
-	}
-	
-	return true;
-}
-
-static const int CSET_MAGIC = ('c' << 24) | ('s' << 16) | ('e' << 8) | 't';
-static const int CSET_VERSION = 2;
-
-bool duDumpContourSet(struct rcContourSet& cset, duFileIO* io)
-{
-	if (!io)
-	{
-		printf("duDumpContourSet: input IO is null.\n"); 
-		return false;
-	}
-	if (!io->isWriting())
-	{
-		printf("duDumpContourSet: input IO not writing.\n"); 
-		return false;
-	}
-	
-	io->write(&CSET_MAGIC, sizeof(CSET_MAGIC));
-	io->write(&CSET_VERSION, sizeof(CSET_VERSION));
-
-	io->write(&cset.nconts, sizeof(cset.nconts));
-	
-	io->write(cset.bmin, sizeof(cset.bmin));
-	io->write(cset.bmax, sizeof(cset.bmax));
-	
-	io->write(&cset.cs, sizeof(cset.cs));
-	io->write(&cset.ch, sizeof(cset.ch));
-
-	io->write(&cset.width, sizeof(cset.width));
-	io->write(&cset.height, sizeof(cset.height));
-	io->write(&cset.borderSize, sizeof(cset.borderSize));
-
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		const rcContour& cont = cset.conts[i];
-		io->write(&cont.nverts, sizeof(cont.nverts));
-		io->write(&cont.nrverts, sizeof(cont.nrverts));
-		io->write(&cont.reg, sizeof(cont.reg));
-		io->write(&cont.area, sizeof(cont.area));
-		io->write(cont.verts, sizeof(int)*4*cont.nverts);
-		io->write(cont.rverts, sizeof(int)*4*cont.nrverts);
-	}
-
-	return true;
-}
-
-bool duReadContourSet(struct rcContourSet& cset, duFileIO* io)
-{
-	if (!io)
-	{
-		printf("duReadContourSet: input IO is null.\n"); 
-		return false;
-	}
-	if (!io->isReading())
-	{
-		printf("duReadContourSet: input IO not reading.\n"); 
-		return false;
-	}
-	
-	int magic = 0;
-	int version = 0;
-	
-	io->read(&magic, sizeof(magic));
-	io->read(&version, sizeof(version));
-	
-	if (magic != CSET_MAGIC)
-	{
-		printf("duReadContourSet: Bad voodoo.\n");
-		return false;
-	}
-	if (version != CSET_VERSION)
-	{
-		printf("duReadContourSet: Bad version.\n");
-		return false;
-	}
-	
-	io->read(&cset.nconts, sizeof(cset.nconts));
-
-	cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*cset.nconts, RC_ALLOC_PERM);
-	if (!cset.conts)
-	{
-		printf("duReadContourSet: Could not alloc contours (%d)\n", cset.nconts);
-		return false;
-	}
-	memset(cset.conts, 0, sizeof(rcContour)*cset.nconts);
-	
-	io->read(cset.bmin, sizeof(cset.bmin));
-	io->read(cset.bmax, sizeof(cset.bmax));
-	
-	io->read(&cset.cs, sizeof(cset.cs));
-	io->read(&cset.ch, sizeof(cset.ch));
-	
-	io->read(&cset.width, sizeof(cset.width));
-	io->read(&cset.height, sizeof(cset.height));
-	io->read(&cset.borderSize, sizeof(cset.borderSize));
-	
-	for (int i = 0; i < cset.nconts; ++i)
-	{
-		rcContour& cont = cset.conts[i];
-		io->read(&cont.nverts, sizeof(cont.nverts));
-		io->read(&cont.nrverts, sizeof(cont.nrverts));
-		io->read(&cont.reg, sizeof(cont.reg));
-		io->read(&cont.area, sizeof(cont.area));
-
-		cont.verts = (int*)rcAlloc(sizeof(int)*4*cont.nverts, RC_ALLOC_PERM);
-		if (!cont.verts)
-		{
-			printf("duReadContourSet: Could not alloc contour verts (%d)\n", cont.nverts);
-			return false;
-		}
-		cont.rverts = (int*)rcAlloc(sizeof(int)*4*cont.nrverts, RC_ALLOC_PERM);
-		if (!cont.rverts)
-		{
-			printf("duReadContourSet: Could not alloc contour rverts (%d)\n", cont.nrverts);
-			return false;
-		}
-		
-		io->read(cont.verts, sizeof(int)*4*cont.nverts);
-		io->read(cont.rverts, sizeof(int)*4*cont.nrverts);
-	}
-	
-	return true;
-}
-	
-
-static const int CHF_MAGIC = ('r' << 24) | ('c' << 16) | ('h' << 8) | 'f';
-static const int CHF_VERSION = 3;
-
-bool duDumpCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io)
-{
-	if (!io)
-	{
-		printf("duDumpCompactHeightfield: input IO is null.\n"); 
-		return false;
-	}
-	if (!io->isWriting())
-	{
-		printf("duDumpCompactHeightfield: input IO not writing.\n"); 
-		return false;
-	}
-	
-	io->write(&CHF_MAGIC, sizeof(CHF_MAGIC));
-	io->write(&CHF_VERSION, sizeof(CHF_VERSION));
-	
-	io->write(&chf.width, sizeof(chf.width));
-	io->write(&chf.height, sizeof(chf.height));
-	io->write(&chf.spanCount, sizeof(chf.spanCount));
-
-	io->write(&chf.walkableHeight, sizeof(chf.walkableHeight));
-	io->write(&chf.walkableClimb, sizeof(chf.walkableClimb));
-	io->write(&chf.borderSize, sizeof(chf.borderSize));
-
-	io->write(&chf.maxDistance, sizeof(chf.maxDistance));
-	io->write(&chf.maxRegions, sizeof(chf.maxRegions));
-
-	io->write(chf.bmin, sizeof(chf.bmin));
-	io->write(chf.bmax, sizeof(chf.bmax));
-
-	io->write(&chf.cs, sizeof(chf.cs));
-	io->write(&chf.ch, sizeof(chf.ch));
-
-	int tmp = 0;
-	if (chf.cells) tmp |= 1;
-	if (chf.spans) tmp |= 2;
-	if (chf.dist) tmp |= 4;
-	if (chf.areas) tmp |= 8;
-
-	io->write(&tmp, sizeof(tmp));
-
-	if (chf.cells)
-		io->write(chf.cells, sizeof(rcCompactCell)*chf.width*chf.height);
-	if (chf.spans)
-		io->write(chf.spans, sizeof(rcCompactSpan)*chf.spanCount);
-	if (chf.dist)
-		io->write(chf.dist, sizeof(unsigned short)*chf.spanCount);
-	if (chf.areas)
-		io->write(chf.areas, sizeof(unsigned char)*chf.spanCount);
-
-	return true;
-}
-
-bool duReadCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io)
-{
-	if (!io)
-	{
-		printf("duReadCompactHeightfield: input IO is null.\n"); 
-		return false;
-	}
-	if (!io->isReading())
-	{
-		printf("duReadCompactHeightfield: input IO not reading.\n"); 
-		return false;
-	}
-
-	int magic = 0;
-	int version = 0;
-	
-	io->read(&magic, sizeof(magic));
-	io->read(&version, sizeof(version));
-	
-	if (magic != CHF_MAGIC)
-	{
-		printf("duReadCompactHeightfield: Bad voodoo.\n");
-		return false;
-	}
-	if (version != CHF_VERSION)
-	{
-		printf("duReadCompactHeightfield: Bad version.\n");
-		return false;
-	}
-	
-	io->read(&chf.width, sizeof(chf.width));
-	io->read(&chf.height, sizeof(chf.height));
-	io->read(&chf.spanCount, sizeof(chf.spanCount));
-	
-	io->read(&chf.walkableHeight, sizeof(chf.walkableHeight));
-	io->read(&chf.walkableClimb, sizeof(chf.walkableClimb));
-	io->read(&chf.borderSize, sizeof(chf.borderSize));
-
-	io->read(&chf.maxDistance, sizeof(chf.maxDistance));
-	io->read(&chf.maxRegions, sizeof(chf.maxRegions));
-	
-	io->read(chf.bmin, sizeof(chf.bmin));
-	io->read(chf.bmax, sizeof(chf.bmax));
-	
-	io->read(&chf.cs, sizeof(chf.cs));
-	io->read(&chf.ch, sizeof(chf.ch));
-	
-	int tmp = 0;
-	io->read(&tmp, sizeof(tmp));
-	
-	if (tmp & 1)
-	{
-		chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*chf.width*chf.height, RC_ALLOC_PERM);
-		if (!chf.cells)
-		{
-			printf("duReadCompactHeightfield: Could not alloc cells (%d)\n", chf.width*chf.height);
-			return false;
-		}
-		io->read(chf.cells, sizeof(rcCompactCell)*chf.width*chf.height);
-	}
-	if (tmp & 2)
-	{
-		chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*chf.spanCount, RC_ALLOC_PERM);
-		if (!chf.spans)
-		{
-			printf("duReadCompactHeightfield: Could not alloc spans (%d)\n", chf.spanCount);
-			return false;
-		}
-		io->read(chf.spans, sizeof(rcCompactSpan)*chf.spanCount);
-	}
-	if (tmp & 4)
-	{
-		chf.dist = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_PERM);
-		if (!chf.dist)
-		{
-			printf("duReadCompactHeightfield: Could not alloc dist (%d)\n", chf.spanCount);
-			return false;
-		}
-		io->read(chf.dist, sizeof(unsigned short)*chf.spanCount);
-	}
-	if (tmp & 8)
-	{
-		chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_PERM);
-		if (!chf.areas)
-		{
-			printf("duReadCompactHeightfield: Could not alloc areas (%d)\n", chf.spanCount);
-			return false;
-		}
-		io->read(chf.areas, sizeof(unsigned char)*chf.spanCount);
-	}
-	
-	return true;
-}
-
-
-static void logLine(rcContext& ctx, rcTimerLabel label, const char* name, const float pc)
-{
-	const int t = ctx.getAccumulatedTime(label);
-	if (t < 0) return;
-	ctx.log(RC_LOG_PROGRESS, "%s:\t%.2fms\t(%.1f%%)", name, t/1000.0f, t*pc);
-}
-
-void duLogBuildTimes(rcContext& ctx, const int totalTimeUsec)
-{
-	const float pc = 100.0f / totalTimeUsec;
- 
-	ctx.log(RC_LOG_PROGRESS, "Build Times");
-	logLine(ctx, RC_TIMER_RASTERIZE_TRIANGLES,		"- Rasterize", pc);
-	logLine(ctx, RC_TIMER_BUILD_COMPACTHEIGHTFIELD,	"- Build Compact", pc);
-	logLine(ctx, RC_TIMER_FILTER_BORDER,				"- Filter Border", pc);
-	logLine(ctx, RC_TIMER_FILTER_WALKABLE,			"- Filter Walkable", pc);
-	logLine(ctx, RC_TIMER_ERODE_AREA,				"- Erode Area", pc);
-	logLine(ctx, RC_TIMER_MEDIAN_AREA,				"- Median Area", pc);
-	logLine(ctx, RC_TIMER_MARK_BOX_AREA,				"- Mark Box Area", pc);
-	logLine(ctx, RC_TIMER_MARK_CONVEXPOLY_AREA,		"- Mark Convex Area", pc);
-	logLine(ctx, RC_TIMER_MARK_CYLINDER_AREA,		"- Mark Cylinder Area", pc);
-	logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD,		"- Build Distance Field", pc);
-	logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD_DIST,	"    - Distance", pc);
-	logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD_BLUR,	"    - Blur", pc);
-	logLine(ctx, RC_TIMER_BUILD_REGIONS,				"- Build Regions", pc);
-	logLine(ctx, RC_TIMER_BUILD_REGIONS_WATERSHED,	"    - Watershed", pc);
-	logLine(ctx, RC_TIMER_BUILD_REGIONS_EXPAND,		"      - Expand", pc);
-	logLine(ctx, RC_TIMER_BUILD_REGIONS_FLOOD,		"      - Find Basins", pc);
-	logLine(ctx, RC_TIMER_BUILD_REGIONS_FILTER,		"    - Filter", pc);
-	logLine(ctx, RC_TIMER_BUILD_LAYERS,				"- Build Layers", pc);
-	logLine(ctx, RC_TIMER_BUILD_CONTOURS,			"- Build Contours", pc);
-	logLine(ctx, RC_TIMER_BUILD_CONTOURS_TRACE,		"    - Trace", pc);
-	logLine(ctx, RC_TIMER_BUILD_CONTOURS_SIMPLIFY,	"    - Simplify", pc);
-	logLine(ctx, RC_TIMER_BUILD_POLYMESH,			"- Build Polymesh", pc);
-	logLine(ctx, RC_TIMER_BUILD_POLYMESHDETAIL,		"- Build Polymesh Detail", pc);
-	logLine(ctx, RC_TIMER_MERGE_POLYMESH,			"- Merge Polymeshes", pc);
-	logLine(ctx, RC_TIMER_MERGE_POLYMESHDETAIL,		"- Merge Polymesh Details", pc);
-	ctx.log(RC_LOG_PROGRESS, "=== TOTAL:\t%.2fms", totalTimeUsec/1000.0f);
-}
-

+ 0 - 43
panda/src/recastdetour/RecastDump.h

@@ -1,43 +0,0 @@
-//
-// Copyright (c) 2009-2010 Mikko Mononen [email protected]
-//
-// 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 RECAST_DUMP_H
-#define RECAST_DUMP_H
-
-struct duFileIO
-{
-	virtual ~duFileIO() = 0;
-	virtual bool isWriting() const = 0;
-	virtual bool isReading() const = 0;
-	virtual bool write(const void* ptr, const size_t size) = 0;
-	virtual bool read(void* ptr, const size_t size) = 0;
-};
-
-bool duDumpPolyMeshToObj(struct rcPolyMesh& pmesh, duFileIO* io);
-bool duDumpPolyMeshDetailToObj(struct rcPolyMeshDetail& dmesh, duFileIO* io);
-
-bool duDumpContourSet(struct rcContourSet& cset, duFileIO* io);
-bool duReadContourSet(struct rcContourSet& cset, duFileIO* io);
-
-bool duDumpCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io);
-bool duReadCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io);
-
-void duLogBuildTimes(rcContext& ctx, const int totalTileUsec);
-
-
-#endif // RECAST_DUMP_H

+ 0 - 17
panda/src/recastdetour/config_recastdetour.h

@@ -1,17 +0,0 @@
-
-#ifndef CONFIG_RECASTDETOUR_H
-#define CONFIG_RECASTDETOUR_H
-
-#include "pandabase.h"
-#include "notifyCategoryProxy.h"
-#include "configVariableDouble.h"
-#include "configVariableString.h"
-#include "configVariableInt.h"
-
-NotifyCategoryDecl(recastdetour, EXPCL_RECASTDETOUR, EXPTP_RECASTDETOUR);
-
-extern ConfigVariableInt    recastdetour_sample_config_variable;
-
-extern EXPCL_RECASTDETOUR void init_librecastdetour();
-
-#endif