Esempio n. 1
0
        private void RemovePatch(PlanetNode currentNode)
        {
            Vector3 mid = (currentNode.min + currentNode.max) / 2;

            activePatches.Remove(mid);
            SystemCore.GameObjectManager.RemoveObject(currentNode);
        }
Esempio n. 2
0
        internal PlanetNode DetermineHitNode(Ray ray)
        {
            List <PlanetNode> hitNodes = new List <PlanetNode>();

            foreach (var activePatch in activePatches.Values)
            {
                BoundingSphere sphere = activePatch.boundingSphere;
                if (ray.Intersects(sphere).HasValue)
                {
                    hitNodes.Add(activePatch);
                }
            }

            PlanetNode closest         = null;
            float      closestDistance = float.MaxValue;

            foreach (PlanetNode n in hitNodes)
            {
                float distanceToNode = (n.boundingSphere.Center - ray.Position).Length();
                if (distanceToNode < closestDistance)
                {
                    closest         = n;
                    closestDistance = distanceToNode;
                }
            }


            return(closest);
        }
Esempio n. 3
0
        private void AddPatch(PlanetNode finishedNode)
        {
            SystemCore.GameObjectManager.AddAndInitialiseGameObject(finishedNode);
            Vector3 mid = (finishedNode.min + finishedNode.max) / 2;

            activePatches.Add(mid, finishedNode);
            nodesBeingBuilt.Remove(mid);
        }
Esempio n. 4
0
        public static void Enqueue(PlanetNode nodeToBuild)
        {
            if (!finishedNodes.ContainsKey(nodeToBuild.Planet.Name))
            {
                finishedNodes.Add(nodeToBuild.Planet.Name, new ConcurrentQueue <PlanetNode>());
            }

            nodesAwaitingBuilding.Enqueue(nodeToBuild);
        }
Esempio n. 5
0
        public List <Connection> GetConnections(PlanetNode node)
        {
            if (nodeDictionary.ContainsKey(node.GetKeyPoint()))
            {
                return(GetConnections(nodeDictionary[node.GetKeyPoint()]));
            }

            return(new List <Connection>());
        }
Esempio n. 6
0
        public static bool GetBuiltNodes(string planetName, out PlanetNode finishedNode)
        {
            if (finishedNodes.ContainsKey(planetName))
            {
                return(finishedNodes[planetName].TryDequeue(out finishedNode));
            }

            finishedNode = null;
            return(false);
        }
Esempio n. 7
0
        public List <Connection> ThreadSafeGetConnections(PlanetNode node)
        {
            lock (connectionBuffer)
            {
                lock (nodeDictionaryBuffer)
                {
                    if (!nodeDictionaryBuffer.ContainsKey(node.GetKeyPoint()))
                    {
                        return(null);
                    }

                    var key = nodeDictionaryBuffer[node.GetKeyPoint()];


                    if (!connectionBuffer.ContainsKey(key))
                    {
                        return(null);
                    }

                    return(connectionBuffer[key]);
                }
            }
        }
Esempio n. 8
0
        private void AddNodeIfNotPresent(Vector3 normal, float step, int depth, Vector3 min, Vector3 max)
        {
            //don't build if already under way.
            Vector3 mid = (min + max) / 2;

            if (nodesBeingBuilt.ContainsKey(mid))
            {
                return;
            }

            if (activePatches.ContainsKey(mid))
            {
                PlanetNode node = activePatches[mid];
                node.remove = false;
                return;
            }


            var patchBeingBuilt = new PatchMinMax(min, max);

            nodesBeingBuilt.Add(mid, patchBeingBuilt);
            PlanetBuilder.Enqueue(testEffect, module, this, depth, min, max, step, normal, radius);
        }
Esempio n. 9
0
        private void CalculatePatchLOD(Vector3 normal, float step, int depth, Vector3 min, Vector3 max)
        {
            //recurse down through the tree. For each node on the way down, we decide if it should split or not.
            //if it should, calculate the split and move down. Remove the node if it's currently visible.
            if (ShouldSplit(min, max, radius, depth))
            {
                Vector3 se, sw, mid1, mid2, nw, ne, midBottom, midRight, midLeft, midTop;
                PlanetNode.CalculatePatchBoundaries(normal, step, min, max, out se, out sw, out mid1, out mid2, out nw, out ne, out midBottom, out midRight, out midLeft, out midTop);


                CalculatePatchLOD(normal, step / 2, depth + 1, se, mid1);
                CalculatePatchLOD(normal, step / 2, depth + 1, mid2, nw);
                CalculatePatchLOD(normal, step / 2, depth + 1, midBottom, midLeft);
                CalculatePatchLOD(normal, step / 2, depth + 1, midRight, midTop);
            }
            else
            {
                if (depth <= maxDepth)
                {
                    AddNodeIfNotPresent(normal, step, depth, min, max);
                }
            }
        }
Esempio n. 10
0
        private void RenderConnections(PlanetNode node)
        {
            List <NeighbourTracker.Connection> connections = neighbourTracker.GetConnections(node);
            Color nodeQuadrantColor = Color.Red;

            if (neighbourTracker.nodeDictionary.ContainsKey(node.GetKeyPoint()))
            {
                NeighbourTrackerNode trackerNode = neighbourTracker.nodeDictionary[node.GetKeyPoint()];

                if (trackerNode.quadrant == NeighbourTrackerNode.Quadrant.ne)
                {
                    nodeQuadrantColor = Color.White;
                }
                if (trackerNode.quadrant == NeighbourTrackerNode.Quadrant.nw)
                {
                    nodeQuadrantColor = Color.Green;
                }
                if (trackerNode.quadrant == NeighbourTrackerNode.Quadrant.se)
                {
                    nodeQuadrantColor = Color.Pink;
                }
                if (trackerNode.quadrant == NeighbourTrackerNode.Quadrant.sw)
                {
                    nodeQuadrantColor = Color.Yellow;
                }

                DebugShapeRenderer.AddBoundingSphere(new BoundingSphere(node.GetSurfaceMidPoint(), 100f / trackerNode.depth), nodeQuadrantColor);
            }


            foreach (NeighbourTracker.Connection conn in connections)
            {
                DebugShapeRenderer.AddLine(node.GetSurfaceMidPoint(),
                                           Vector3.Transform(Vector3.Normalize(conn.node.keyPoint) * radius, Transform.AbsoluteTransform), Color.Blue);
            }
        }
Esempio n. 11
0
        public static void Enqueue(Effect effect, IModule module, Planet rootObject, int depth, Vector3 min, Vector3 max, float step, Vector3 normal, float sphereSize)
        {
            var node = new PlanetNode(effect, module, rootObject, depth, min, max, step, normal, sphereSize);

            Enqueue(node);
        }
Esempio n. 12
0
 public List <NeighbourTracker.Connection> GetNeighbours(PlanetNode node)
 {
     return(neighbourTracker.ThreadSafeGetConnections(node));
 }
Esempio n. 13
0
        public void Update(GameTime gameTime)
        {
            Vector3 planetCenter             = Transform.AbsoluteTransform.Translation;
            Vector3 toCenterOfPlanet         = Transform.AbsoluteTransform.Translation - SystemCore.ActiveCamera.Position;
            float   distanceToCenterOfPlanet = toCenterOfPlanet.Length();
            float   surfaceDistance          = distanceToCenterOfPlanet - radius;

            if (HasAtmosphere)
            {
                atmosphere.Update(sunDirection, SystemCore.ActiveCamera.Position, distanceToCenterOfPlanet);
                atmosphericScatteringHelper.Update(distanceToCenterOfPlanet, sunDirection, SystemCore.ActiveCamera.Position - Transform.AbsoluteTransform.Translation);
            }



            float farPlaneMultiplier = MonoMathHelper.MapFloatRange(radius, radius * 2, 0.3f, 1f, surfaceDistance);

            GenerateCustomProjectionMatrix(distanceToCenterOfPlanet * farPlaneMultiplier);
            var frustrum = new BoundingFrustum(SystemCore.ActiveCamera.View * customProjection);

            int activeCount = 0;


            foreach (PlanetNode node in activePatches.Values)
            {
                node.Update();



                //all nodes are flagged for removal every frame.
                //The LOD calculation will unflag if nodes should be kept.
                node.remove = true;

                if (!frustrum.Intersects(node.boundingSphere))
                {
                    node.Disable();
                }
                else
                {
                    if (SystemWarGlobalSettings.RenderQuadtreeConnectivity)
                    {
                        RenderConnections(node);
                    }

                    node.Enable();
                    activeCount++;
                }
            }



            if (SystemWarGlobalSettings.RepairSeams)
            {
                CalculateConnectivity();
            }


            for (int i = 0; i < rootNodes.Count; i++)
            {
                PlanetNode root = rootNodes[i];
                CalculatePatchLOD(root.normal, root.step, root.depth, root.min, root.max);
            }



            //removes nodes that have not had their flags refreshed by the LOD pass
            RemoveStaleNodes();

            int patchCountPerFrame = 10;

            for (int i = 0; i < patchCountPerFrame; i++)
            {
                PlanetNode finishedNode;
                if (PlanetBuilder.GetBuiltNodes(Name, out finishedNode))
                {
                    AddPatch(finishedNode);
                }
            }
        }
Esempio n. 14
0
        private void CalculateConnectivity()
        {
            ReinitialiseTracker();

            // have to go through the tree in a breadth first fashion, building connectivity.
            Queue <PatchMinMax> nodesToCheck = new Queue <PatchMinMax>();

            foreach (PlanetNode rootNode in rootNodes)
            {
                nodesToCheck.Enqueue(new PatchMinMax(rootNode.min, rootNode.max, rootNode.depth, rootNode.normal,
                                                     rootNode.step, neighbourTracker.nodeDictionary[(rootNode.min + rootNode.max) / 2].side));
            }


            while (nodesToCheck.Count > 0)
            {
                PatchMinMax next = nodesToCheck.Dequeue();
                if (ShouldSplit(next.Min, next.Max, radius, next.depth))
                {
                    Vector3 se, sw, mid1, mid2, nw, ne, midBottom, midRight, midLeft, midTop;
                    PlanetNode.CalculatePatchBoundaries(next.normal, next.step, next.Min, next.Max, out se, out sw, out mid1, out mid2, out nw, out ne, out midBottom, out midRight, out midLeft, out midTop);

                    //remove this node in the neighbour tracker, generate and connect children
                    NeighbourTrackerNode southEast = new NeighbourTrackerNode(next.depth + 1, se, mid1, next.step / 2, next.normal);
                    southEast.quadrant = NeighbourTrackerNode.Quadrant.se;
                    southEast.side     = next.side;
                    PatchMinMax sePatchMinMax = new PatchMinMax(se, mid1, next.depth + 1, next.normal, next.step / 2, next.side);
                    nodesToCheck.Enqueue(sePatchMinMax);

                    NeighbourTrackerNode northWest = new NeighbourTrackerNode(next.depth + 1, mid2, nw, next.step / 2, next.normal);
                    northWest.quadrant = NeighbourTrackerNode.Quadrant.nw;
                    northWest.side     = next.side;
                    PatchMinMax nwPatchMinMax = new PatchMinMax(mid2, nw, next.depth + 1, next.normal, next.step / 2, next.side);
                    nodesToCheck.Enqueue(nwPatchMinMax);

                    NeighbourTrackerNode southWest = new NeighbourTrackerNode(next.depth + 1, midBottom, midLeft,
                                                                              next.step / 2, next.normal);
                    southWest.quadrant = NeighbourTrackerNode.Quadrant.sw;
                    southWest.side     = next.side;
                    PatchMinMax swPatchMinMax = new PatchMinMax(midBottom, midLeft, next.depth + 1, next.normal, next.step / 2, next.side);
                    nodesToCheck.Enqueue(swPatchMinMax);

                    NeighbourTrackerNode northEast = new NeighbourTrackerNode(next.depth + 1, midRight, midTop, next.step / 2, next.normal);
                    northEast.quadrant = NeighbourTrackerNode.Quadrant.ne;
                    northEast.side     = next.side;
                    PatchMinMax nePatchMinMax = new PatchMinMax(midRight, midTop, next.depth + 1, next.normal, next.step / 2, next.side);
                    nodesToCheck.Enqueue(nePatchMinMax);

                    //if (next.side == NeighbourTrackerNode.CubeSide.right || next.side == NeighbourTrackerNode.CubeSide.back)
                    //{
                    //    southEast.quadrant = NeighbourTrackerNode.Quadrant.sw;
                    //    northEast.quadrant = NeighbourTrackerNode.Quadrant.nw;
                    //    southWest.quadrant = NeighbourTrackerNode.Quadrant.se;
                    //    northWest.quadrant = NeighbourTrackerNode.Quadrant.ne;
                    //}

                    neighbourTracker.ReplaceNodeWithChildren(neighbourTracker.nodeDictionary[(next.Min + next.Max) / 2],
                                                             northWest, southWest, southEast, northEast);
                }
            }


            neighbourTracker.CopyConnectionDataToThreadSafeBuffer();
        }
Esempio n. 15
0
        private void Initialise()
        {
            activePatches = new Dictionary <Vector3, PlanetNode>();
            rootNodes     = new List <PlanetNode>();
            float vectorSpacing = 1f;
            float cubeVerts     = 21;
            float sphereSize    = radius;



            //top
            PlanetNode top = new PlanetNode(testEffect, module, this, 1, new Vector3(-cubeVerts / 2, cubeVerts / 2 - 1, -cubeVerts / 2), new Vector3(cubeVerts / 2, cubeVerts / 2 - 1, cubeVerts / 2), vectorSpacing, Vector3.Up, sphereSize);

            top.BuildGeometry();
            AddPatch(top);
            rootNodes.Add(top);
            topNode      = new NeighbourTrackerNode(1, top.min, top.max, vectorSpacing, Vector3.Up);
            topNode.side = NeighbourTrackerNode.CubeSide.top;

            ////bottom
            PlanetNode bottom = new PlanetNode(testEffect, module, this, 1, new Vector3(-cubeVerts / 2, -cubeVerts / 2, -cubeVerts / 2), new Vector3(cubeVerts / 2, -cubeVerts / 2, cubeVerts / 2), vectorSpacing, Vector3.Down, sphereSize);

            bottom.BuildGeometry();
            AddPatch(bottom);
            rootNodes.Add(bottom);
            bottomNode      = new NeighbourTrackerNode(1, bottom.min, bottom.max, vectorSpacing, Vector3.Down);
            bottomNode.side = NeighbourTrackerNode.CubeSide.bottom;

            ////forward
            PlanetNode forward = new PlanetNode(testEffect, module, this, 1, new Vector3(-cubeVerts / 2, -cubeVerts / 2, -cubeVerts / 2), new Vector3(cubeVerts / 2, cubeVerts / 2, cubeVerts / 2), vectorSpacing, Vector3.Forward, sphereSize);

            forward.BuildGeometry();
            AddPatch(forward);
            rootNodes.Add(forward);
            forwardNode      = new NeighbourTrackerNode(1, forward.min, forward.max, vectorSpacing, Vector3.Forward);
            forwardNode.side = NeighbourTrackerNode.CubeSide.front;

            ////backward
            PlanetNode backward = new PlanetNode(testEffect, module, this, 1, new Vector3(-cubeVerts / 2, -cubeVerts / 2, cubeVerts / 2 - 1), new Vector3(cubeVerts / 2, cubeVerts / 2, cubeVerts / 2 - 1), vectorSpacing, Vector3.Backward, sphereSize);

            backward.BuildGeometry();
            AddPatch(backward);
            rootNodes.Add(backward);
            backwardNode      = new NeighbourTrackerNode(1, backward.min, backward.max, vectorSpacing, Vector3.Backward);
            backwardNode.side = NeighbourTrackerNode.CubeSide.back;

            //right
            PlanetNode right = new PlanetNode(testEffect, module, this, 1, new Vector3(-cubeVerts / 2, -cubeVerts / 2, -cubeVerts / 2), new Vector3(-cubeVerts / 2, cubeVerts / 2, cubeVerts / 2), vectorSpacing, Vector3.Right, sphereSize);

            right.BuildGeometry();
            AddPatch(right);
            rootNodes.Add(right);
            rightNode      = new NeighbourTrackerNode(1, right.min, right.max, vectorSpacing, Vector3.Right);
            rightNode.side = NeighbourTrackerNode.CubeSide.right;


            //left
            PlanetNode left = new PlanetNode(testEffect, module, this, 1, new Vector3(cubeVerts / 2 - 1, -cubeVerts / 2, -cubeVerts / 2), new Vector3(cubeVerts / 2 - 1, cubeVerts / 2, cubeVerts / 2), vectorSpacing, Vector3.Left, sphereSize);

            left.BuildGeometry();
            AddPatch(left);
            rootNodes.Add(left);
            leftNode      = new NeighbourTrackerNode(1, left.min, left.max, vectorSpacing, Vector3.Left);
            leftNode.side = NeighbourTrackerNode.CubeSide.left;



            ReinitialiseTracker();
        }