Browse Source

Add streaming mode to AS sample 15_Navigation.

Eugene Kozlov 8 years ago
parent
commit
20d2133f13
1 changed files with 77 additions and 0 deletions
  1. 77 0
      bin/Data/Scripts/15_Navigation.as

+ 77 - 0
bin/Data/Scripts/15_Navigation.as

@@ -12,6 +12,12 @@
 Vector3 endPos;
 Vector3 endPos;
 Array<Vector3> currentPath;
 Array<Vector3> currentPath;
 Node@ jackNode;
 Node@ jackNode;
+bool useStreaming = false;
+// Used for streaming only
+const int STREAMING_DISTANCE = 2;
+Array<VectorBuffer> navigationTilesData;
+Array<IntVector2> navigationTilesIdx;
+Array<IntVector2> addedTiles;
 
 
 void Start()
 void Start()
 {
 {
@@ -101,6 +107,8 @@ void CreateScene()
 
 
     // Create a NavigationMesh component to the scene root
     // Create a NavigationMesh component to the scene root
     NavigationMesh@ navMesh = scene_.CreateComponent("NavigationMesh");
     NavigationMesh@ navMesh = scene_.CreateComponent("NavigationMesh");
+    // Set small tiles to show navigation mesh streaming
+    navMesh.tileSize = 32;
     // Create a Navigable component to the scene root. This tags all of the geometry in the scene as being part of the
     // Create a Navigable component to the scene root. This tags all of the geometry in the scene as being part of the
     // navigation mesh. By default this is recursive, but the recursion could be turned off from Navigable
     // navigation mesh. By default this is recursive, but the recursion could be turned off from Navigable
     scene_.CreateComponent("Navigable");
     scene_.CreateComponent("Navigable");
@@ -111,6 +119,15 @@ void CreateScene()
     // physics geometry from the scene nodes, as it often is simpler, but if it can not find any (like in this example)
     // physics geometry from the scene nodes, as it often is simpler, but if it can not find any (like in this example)
     // it will use renderable geometry instead
     // it will use renderable geometry instead
     navMesh.Build();
     navMesh.Build();
+    // Save navigation data (used for streaming only).
+    IntVector2 numTiles = navMesh.numTiles;
+    for (int z = 0; z < numTiles.y; ++z)
+        for (int x = 0; x < numTiles.x; ++x)
+        {
+            IntVector2 idx(x, z);
+            navigationTilesData.Push(navMesh.GetTileData(idx));
+            navigationTilesIdx.Push(idx);
+        }
 
 
     // Create the camera. Limit far clip distance to match the fog
     // Create the camera. Limit far clip distance to match the fog
     cameraNode = scene_.CreateChild("Camera");
     cameraNode = scene_.CreateChild("Camera");
@@ -140,6 +157,7 @@ void CreateUI()
         "Use WASD keys to move, RMB to rotate view\n"
         "Use WASD keys to move, RMB to rotate view\n"
         "LMB to set destination, SHIFT+LMB to teleport\n"
         "LMB to set destination, SHIFT+LMB to teleport\n"
         "MMB or O key to add or remove obstacles\n"
         "MMB or O key to add or remove obstacles\n"
+        "Tab to toggle navigation mesh streaming\n"
         "Space to toggle debug geometry";
         "Space to toggle debug geometry";
     instructionText.SetFont(cache.GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15);
     instructionText.SetFont(cache.GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15);
     // The text has multiple rows. Center them in relation to each other
     // The text has multiple rows. Center them in relation to each other
@@ -341,6 +359,56 @@ void FollowPath(float timeStep)
     }
     }
 }
 }
 
 
+void SwitchStreaming(bool enabled)
+{
+    NavigationMesh@ navMesh = scene_.GetComponent("NavigationMesh");
+    if (enabled)
+    {
+        int maxTiles = (2 * STREAMING_DISTANCE + 1) * (2 * STREAMING_DISTANCE + 1);
+        BoundingBox boundingBox = navMesh.boundingBox;
+        navMesh.Allocate(boundingBox, maxTiles);
+    }
+    else
+        navMesh.Build();
+}
+
+void StreamNavMesh()
+{
+    NavigationMesh@ navMesh = scene_.GetComponent("NavigationMesh");
+
+    // Center the navigation mesh at the jack
+    IntVector2 jackTile = navMesh.GetTileIndex(jackNode.worldPosition);
+    IntVector2 beginTile = VectorMax(IntVector2(0, 0), jackTile - IntVector2(1, 1) * STREAMING_DISTANCE);
+    IntVector2 endTile = VectorMin(jackTile + IntVector2(1, 1) * STREAMING_DISTANCE, navMesh.numTiles - IntVector2(1, 1));
+
+    // Remove tiles
+    for (uint i = 0; i < addedTiles.length;)
+    {
+        IntVector2 tileIdx = addedTiles[i];
+        if (beginTile.x <= tileIdx.x && tileIdx.x <= endTile.x && beginTile.y <= tileIdx.y && tileIdx.y <= endTile.y)
+            ++i;
+        else
+        {
+            addedTiles.Erase(i);
+            navMesh.RemoveTile(tileIdx);
+        }
+    }
+
+    // Add tiles
+    for (int z = beginTile.y; z <= endTile.y; ++z)
+        for (int x = beginTile.x; x <= endTile.x; ++x)
+        {
+            const IntVector2 tileIdx(x, z);
+            int tileDataIdx = navigationTilesIdx.Find(tileIdx);
+            if (!navMesh.HasTile(tileIdx) && tileDataIdx != -1)
+            {
+                addedTiles.Push(tileIdx);
+                navMesh.AddTile(navigationTilesData[tileDataIdx]);
+                Print("Add tile " + tileIdx.ToString());
+            }
+        }
+}
+
 void HandleUpdate(StringHash eventType, VariantMap& eventData)
 void HandleUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
     // Take the frame time step, which is stored as a float
     // Take the frame time step, which is stored as a float
@@ -351,6 +419,15 @@ void HandleUpdate(StringHash eventType, VariantMap& eventData)
 
 
     // Make Jack follow the Detour path
     // Make Jack follow the Detour path
     FollowPath(timeStep);
     FollowPath(timeStep);
+
+    // Update streaming
+    if (input.keyPress[KEY_TAB])
+    {
+        useStreaming = !useStreaming;
+        SwitchStreaming(useStreaming);
+    }
+    if (useStreaming)
+        StreamNavMesh();
 }
 }
 
 
 void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
 void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)