コード例 #1
0
    private static void OutputParent(TextWriter writer, ParentNode node, GravityNode rootNode, string prefix1, string prefix2)
    {
        writer.Write(prefix1);
        writer.Write("Total Mass: ");
        writer.Write(node.Mass);
        writer.Write("\tCentre of mass: ");
        writer.Write(node.CentreOfMass);
        writer.Write("\tCell Size: ");
        writer.WriteLine(node.Size);

        int range = 7;

        while (range > 0 && node.SubNodes[range] == null)
        {
            range--;
        }

        for (int index = 0; index <= range; index++)
        {
            if (node.SubNodes[index] != null)
            {
                if (index == range)
                {
                    Output(writer, node.SubNodes[index], rootNode, prefix2 + LAST_PREFIX, prefix2 + SPACING);
                }
                else
                {
                    Output(writer, node.SubNodes[index], rootNode, prefix2 + NEXT_PREFIX, prefix2 + CONT_PREFIX);
                }
            }
        }
    }
コード例 #2
0
 public GravityNode(GameObject item)
 {
     this.item = item;
     this.SetScript();
     next     = null;
     previous = null;
 }
コード例 #3
0
 /// <summary>
 /// Initialize base variables of gravity frame, to be used with player position
 /// when player has entered the level.
 /// </summary>
 ///  <param name="playerPosition">Position of player.</param>
 public void Initialize(Vector3 playerPosition)
 {
     // initialize
     firstClosestNode         = FindFirstClosestNode(playerPosition);
     secondClosestNode        = FindSecondClosestNode(playerPosition);
     closestPointOnFrameLine  = FindClosestPointOnFrame(playerPosition);
     closestPointOnFramePlane = FindClosestPointOnFramePlane(playerPosition);
 }
コード例 #4
0
    public static void Output(TextWriter writer, GravityNode node, string prefix1, string prefix2)
    {
        if (node == null)
        {
            return;
        }

        Output(writer, node, node, prefix1, prefix2);
    }
コード例 #5
0
 private static void OutputLeaf(TextWriter writer, LeafNode node, GravityNode rootNode, string prefix1, string prefix2)
 {
     writer.Write(prefix1);
     writer.Write("Mass: ");
     writer.Write(node.Mass);
     writer.Write("\tCentre of mass: ");
     writer.Write(node.CentreOfMass);
     writer.Write("\tForce: ");
     writer.WriteLine(GravityManager.CalculateTreeForce(node, rootNode));
 }
コード例 #6
0
    public void Enqueue(GameObject item)
    {
        GravityNode temp = new GravityNode(item);

        if (!this.IsEmpty())
        {
            temp.SetNext(first);
            first.SetPrevious(temp);
        }

        first = temp;
    }
コード例 #7
0
    public static Vector3 CalculateForce(GravityNode target, GravityNode tree)
    {
        if (target == tree)
        {
            return(Vector3.zero);
        }

        var difference = tree.CentreOfMass - target.CentreOfMass;
        var distance   = difference.magnitude;

        return((difference * target.Mass * tree.Mass * G) / Mathf.Pow(distance, 3));
    }
コード例 #8
0
    //Removes item from the list, along with its script. Returns false if list doesn't contain item, true otherwise.
    public bool Dequeue(GameObject item)
    {
        if (this.Contains(item))
        {
            if (current.HasNext())
            {
                if (current.HasPrevious())
                {
                    //Set the previous node's next node to be the current node's next node.
                    current.GetPrevious().SetNext(current.GetNext());
                    //Set the next node's previous node to be the current node's previous node.
                    current.GetNext().SetPrevious(current.GetPrevious());
                    //Set the current node to be the previous node.
                    current = current.GetPrevious();

                    return(true);
                }
                else                //it must be the first node if there isn't a previous node
                {
                    //Set the second node's previous node to null.
                    current.GetNext().SetPrevious(null);
                    //Set the second node to now be the first node.
                    first = current.GetNext();
                    //Set current to the new first node.
                    current = first;

                    return(true);
                }
            }
            else            //it must be the last node if there is no next node
            {
                if (current.HasPrevious())
                {
                    //Sets the previous node's next node to null.
                    current.GetPrevious().SetNext(null);
                    //Sets current to the previous node.
                    current = current.GetPrevious();

                    return(true);
                }
                else                //it must be the only node
                {
                    current = null;
                    first   = null;

                    return(true);
                }
            }
        }

        return(false);
    }
コード例 #9
0
    /// <summary>
    /// Finds node closest to <paramref name="position"/> to <paramref name="position"/> in full
    /// frame, or among nodes in the closeby field of <paramref name="node"/>.
    /// </summary>
    /// <returns>Closest node on frame.</returns>
    /// <param name="position">Position for which to find the closest node.</param>
    /// <param name="node">Optional node with closeby field, use to reduce search space.</param>
    private GravityNode FindFirstClosestNode(Vector3 position, GravityNode node = null)
    {
        // Find closest gravNode to position, either in full frame or among node.closeby
        List <GravityNode> currFrame = node == null ? gravityFrame : node.closeby;
        List <float>       dist      = new List <float>(currFrame.Count);
        int count = 0;

        foreach (GravityNode gn in currFrame)
        {
            dist.Insert(count++, Vector3.Distance(position, gn.position));
        }
        int closestNodeInd = dist.IndexOf(Mathf.Min(dist.ToArray())); //

        return(currFrame[closestNodeInd]);
    }
コード例 #10
0
    private static void Output(TextWriter writer, GravityNode node, GravityNode rootNode, string prefix1, string prefix2)
    {
        if (node == null)
        {
            return;
        }

        if (node.IsLeaf)
        {
            OutputLeaf(writer, (LeafNode)node, rootNode, prefix1, prefix2);
        }
        else
        {
            OutputParent(writer, (ParentNode)node, rootNode, prefix1, prefix2);
        }
    }
コード例 #11
0
 /// <summary>
 /// Updates the variables holding first/second closest nodes and
 /// position on frame of the player.
 /// </summary>
 /// <param name="playerPosition">Position of player.</param>
 public void UpdatePlayerBasedElements(Vector3 playerPosition)
 {
     firstClosestNode         = FindFirstClosestNode(playerPosition, firstClosestNode);
     secondClosestNode        = FindSecondClosestNode(playerPosition);
     closestPointOnFrameLine  = FindClosestPointOnFrame(playerPosition);
     closestPointOnFramePlane = FindClosestPointOnFramePlane(playerPosition);
     ////DEBUG
     //Debug.DrawLine(playerPosition, firstClosestNode.position, Color.gray);
     //Debug.DrawLine(playerPosition, secondClosestNode.position, Color.gray);
     //Debug.DrawLine(playerPosition, closestPointOnFrameLine, Color.yellow);
     //Debug.DrawLine(firstClosestNode.planePoints[0], secondClosestNode.planePoints[0], Color.magenta);
     //Debug.DrawLine(secondClosestNode.planePoints[0], secondClosestNode.planePoints[1], Color.magenta);
     //Debug.DrawLine(secondClosestNode.planePoints[1], firstClosestNode.planePoints[1], Color.magenta);
     //Debug.DrawLine(firstClosestNode.planePoints[1], firstClosestNode.planePoints[0], Color.magenta);
     //Debug.DrawLine(playerPosition, closestPointOnFramePlane, Color.green);
     ////DEBUG
 }
コード例 #12
0
 public void CalculateForces(GravityNode node, GravityNode root)
 {
     if (node.IsLeaf)
     {
         var leaf = (LeafNode)node;
         leaf.Body.Force = CalculateTreeForce(node, root);
     }
     else
     {
         foreach (var subNode in ((ParentNode)node).SubNodes)
         {
             if (subNode != null)
             {
                 CalculateForces(subNode, root);
             }
         }
     }
 }
コード例 #13
0
    public static Vector3 CalculateTreeForce(GravityNode target, GravityNode tree)
    {
        if (tree.IsLeaf || ((ParentNode)tree).Size / Vector3.Distance(target.CentreOfMass, tree.CentreOfMass) < gravityRatio)
        {
            return(CalculateForce(target, tree));
        }
        else
        {
            var force = Vector3.zero;

            foreach (var subNode in ((ParentNode)tree).SubNodes)
            {
                if (subNode != null)
                {
                    force += CalculateTreeForce(target, subNode);
                }
            }

            return(force);
        }
    }
コード例 #14
0
    private GravityNode BuildTree(GravityBody[] bodies, Vector3 origin, int power)
    {
        if (bodies.Length == 1)
        {
            return(new LeafNode(bodies[0]));
        }

        var seperatedBodies = new List <GravityBody> [8];

        foreach (var body in bodies)
        {
            foreach (Region region in Enum.GetValues(typeof(Region)))
            {
                if (IsWithinRegion(origin, body.Position, region, power - 1))
                {
                    if (seperatedBodies[(int)region] == null)
                    {
                        seperatedBodies[(int)region] = new List <GravityBody>();
                    }

                    seperatedBodies[(int)region].Add(body);
                    break;
                }
            }
        }

        var nodes = new GravityNode[8];

        foreach (Region region in Enum.GetValues(typeof(Region)))
        {
            var newOrigin = origin + ((Vector3)region.GetDirection()) * Mathf.Pow(2, power - 2);

            if (seperatedBodies[(int)region] != null)
            {
                nodes[(int)region] = BuildTree(seperatedBodies[(int)region].ToArray(), newOrigin, power - 1);
            }
        }

        return(new ParentNode(nodes, Mathf.Pow(2, power)));
    }
コード例 #15
0
    /// <summary>
    /// Generate gravity frame from maze frame object, should only be used when paths between nodes are perfectly straight.
    /// </summary>
    /// <param name="mazeFrame">MazeFrame object.</param>
    private void GenerateGravityFrameFromMazeObj(MazeFrame mazeFrame, float closebyDist)
    {
        // Generate gravity frame based on maze nodes
        gravityFrame = new List <GravityNode>(mazeFrame.Nodes.Count);

        // First create base list, then add neighbors
        foreach (MazeNode mazeNode in mazeFrame.Nodes)
        {
            // Create gravity node from maze node
            GravityNode gravNode = new GravityNode(mazeNode.Position, mazeNode.Identifier);
            gravityFrame.Add(gravNode);
        }
        for (int i = 0; i < gravityFrame.Count; i++)
        {
            foreach (MazeNode neighbor in mazeFrame.Nodes[i].ConnectedNeighbors)
            {
                gravityFrame[i].neighbors.Add(gravityFrame.Find(x => x.identifier == neighbor.Identifier));
            }
        }

        // Add closeby list to each node
        AddClosebyNodes(closebyDist);
    }
コード例 #16
0
    /// <summary>
    /// Generate  gravity frame from splines fitted to maze frame.
    /// </summary>
    /// <param name="mazeFrameSplines">Splines fitted to maze frames.</param>
    ///// <param name="closebyDist"> Distance at which nodes are considered close by.</param>
    /// <param name="junctionDist"> Distance at which nodes are considered close to junction.</param>
    private void GenerateGravityFrameFromSplines(MazeFrame mazeFrame, MazeFrameSplines mazeFrameSplines, float junctionDist, float planeWidth)
    {
        // Generate gravity frame based on maze frame fitted splines
        int nodeCount = 0;

        foreach (MazeFrameSplines.SplineSegment splineSeg in mazeFrameSplines.SplineSegments)
        {
            nodeCount += splineSeg.spline.NSamplesToUse;
        }
        gravityFrame = new List <GravityNode>(nodeCount);

        // Generate sub frame to use later
        List <List <GravityNode> > segmentSubFrame = new List <List <GravityNode> >(mazeFrameSplines.SplineSegments.Count);

        // Create nodes for each splines
        for (int iSpline = 0; iSpline < mazeFrameSplines.SplineSegments.Count; iSpline++)
        {
            segmentSubFrame.Add(new List <GravityNode>(mazeFrameSplines.SplineSegments[iSpline].spline.NSamplesToUse));
            GravityNode prevNode = null;
            for (int i = 0; i < mazeFrameSplines.SplineSegments[iSpline].spline.NSamplesToUse; i++)
            {
                Vector3   currPos     = mazeFrameSplines.SplineSegments[iSpline].spline.GetPointOnSpline(mazeFrameSplines.SplineSegments[iSpline].spline.SampleIndToT(i));
                Vector3   currTang    = mazeFrameSplines.SplineSegments[iSpline].spline.GetTangentToPointOnSpline(mazeFrameSplines.SplineSegments[iSpline].spline.SampleIndToT(i)).normalized;
                Vector3   currNorm    = mazeFrameSplines.SplineSegments[iSpline].spline.DefaultGetNormalAtT(mazeFrameSplines.SplineSegments[iSpline].spline.SampleIndToT(i)).normalized;
                Vector3   cross       = Vector3.Cross(currTang, currNorm);
                Vector3[] planePoints = new Vector3[2] {
                    currPos + (cross * (planeWidth / 2f)), currPos - (cross * (planeWidth / 2f))
                };
                GravityNode node = new GravityNode(currPos, iSpline + "-" + currPos.ToString(), planePoints);
                if (prevNode != null)
                {
                    node.neighbors.Add(prevNode);
                    prevNode.neighbors.Add(node);
                }
                // Determine if near junction
                if (mazeFrameSplines.SplineSegments[iSpline].startNeighbors.Count > 0)
                {
                    if (Vector3.Distance(currPos, mazeFrameSplines.SplineSegments[iSpline].spline.GetPointOnSpline(0)) < junctionDist)
                    {
                        node.nearJunction = true;
                    }
                }
                if (mazeFrameSplines.SplineSegments[iSpline].endNeighbors.Count > 0)
                {
                    if (Vector3.Distance(currPos, mazeFrameSplines.SplineSegments[iSpline].spline.GetPointOnSpline(1)) < junctionDist)
                    {
                        node.nearJunction = true;
                    }
                }
                // Add to frame
                gravityFrame.Add(node);
                prevNode = node;
                // Add spline segment sub-frame as well
                segmentSubFrame[iSpline].Add(node);
            }
        }
        // Create closeby list from, and connect, neighboring splines
        for (int iSeg = 0; iSeg < mazeFrameSplines.SplineSegments.Count; iSeg++)
        {
            // Add frame to its own closeby
            List <GravityNode> currSubFrame = segmentSubFrame[iSeg];
            foreach (GravityNode node in currSubFrame)
            {
                node.closeby.AddRange(currSubFrame);
            }

            // Start/end of spline
            List <List <MazeFrameSplines.SplineSegment> > segList = new List <List <MazeFrameSplines.SplineSegment> >(2)
            {
                mazeFrameSplines.SplineSegments[iSeg].startNeighbors, mazeFrameSplines.SplineSegments[iSeg].endNeighbors
            };
            for (int iStartEnd = 0; iStartEnd <= 1; iStartEnd++)
            {
                foreach (MazeFrameSplines.SplineSegment neighSeg in segList[iStartEnd])
                {
                    // Get sub frame index
                    List <GravityNode> neighSegSF = segmentSubFrame[mazeFrameSplines.SplineSegments.IndexOf(neighSeg)];

                    // Add to closeby list
                    foreach (GravityNode node in currSubFrame)
                    {
                        node.closeby.AddRange(neighSegSF);
                    }

                    // Connect start/end
                    switch (iStartEnd)
                    {
                    case 0:
                    {
                        if (Vector3.Distance(currSubFrame[0].position, neighSegSF[0].position) <
                            Vector3.Distance(currSubFrame[0].position, neighSegSF[neighSegSF.Count - 1].position))
                        {
                            currSubFrame[0].neighbors.Add(neighSegSF[0]);
                        }
                        else
                        {
                            currSubFrame[0].neighbors.Add(neighSegSF[neighSegSF.Count - 1]);
                        }
                        break;
                    }

                    case 1:
                    {
                        if (Vector3.Distance(currSubFrame[currSubFrame.Count - 1].position, neighSegSF[0].position) <
                            Vector3.Distance(currSubFrame[currSubFrame.Count - 1].position, neighSegSF[neighSegSF.Count - 1].position))
                        {
                            currSubFrame[currSubFrame.Count - 1].neighbors.Add(neighSegSF[0]);
                        }
                        else
                        {
                            currSubFrame[currSubFrame.Count - 1].neighbors.Add(neighSegSF[neighSegSF.Count - 1]);
                        }
                        break;
                    }
                    }
                }
            }
        }
    }
コード例 #17
0
 public void SetPrevious(GravityNode previous)
 {
     this.previous = previous;
 }
コード例 #18
0
 public void SetNext(GravityNode next)
 {
     this.next = next;
 }
コード例 #19
0
    /// <summary>
    /// Generate gravity frame from object center line nodes (the output given by <see cref="MazePopulator.PopulateWithCylinders(MazeFrame, float, int)"/>.
    /// </summary>
    /// <param name="objCenterLineNodes">Object center line nodes, given as output from <see cref="MazePopulator.PopulateWithCylinders(MazeFrame, float, int)"/>.</param>
    private void GenerateGravityFrameFromObjCenterLineNodes(Dictionary <string, Vector3> objCenterLineNodes, float closebyDist) // FIXME name parsing below is too complicated, should be easier way
    {
        // Generate gravity frame based on maze nodes
        gravityFrame = new List <GravityNode>(objCenterLineNodes.Count);

        // First create base list with shortened names and separate neighbor dictionary
        Dictionary <string, List <string> > neighbors = new Dictionary <string, List <string> >(objCenterLineNodes.Count);

        foreach (KeyValuePair <string, Vector3> node in objCenterLineNodes)
        {
            // Create gravity node
            GravityNode gravNode = new GravityNode(node.Value, node.Key);
            gravityFrame.Add(gravNode);

            //Parse identifier
            string[] identifier = node.Key.Split(new char[] { '-' }, System.StringSplitOptions.RemoveEmptyEntries);
            if ((identifier[0][0] == 'c') && identifier.Length > 6)
            {
                throw new System.Exception("Node naming in PopulateMaze is incorrect.");
            }
            if ((identifier[0][0] == 'b') && identifier.Length > 3)
            {
                throw new System.Exception("Node naming in PopulateMaze is incorrect.");
            }

            // Generate neighbor identifiers and add to dictionary
            // The naming schemes exist, with specified neighbors:
            // conn-<center_nodeid>-<start_neighid>-<end_neighid>-<num>-<index==0>
            //            --> base-<center_nodeid>-<start_neighid>
            // conn-<center_nodeid>-<start_neighid>-<end_neighid>-<num>-<index==num>
            //            --> base-<center_nodeid>-<end_neighid>
            // conn-<center_nodeid>-<start_neighid>-<end_neighid>-<num>-<index!=0/num>
            //            --> conn-<center_nodeid>-<start_neighid>-<end_neighid>-<num>-<index-1>
            //            --> conn-<center_nodeid>-<start_neighid>-<end_neighid>-<num>-<index+1>
            // base-<nodeid>-<neighid>
            //            --> base-<neighid>-<nodeid>
            // (if exists)--> conn-<nodeid>-<neighid>-<ANY>
            //
            List <string> currNeighbors = new List <string>();
            if (identifier[0][0] == 'b')                                               // isBase
            {
                currNeighbors.Add("base" + "-" + identifier[2] + "-" + identifier[1]); // NEEDS TO ADDED INDIVIDUALLY
            }
            else if (identifier[0][0] == 'c')                                          // isConn
            {
                int curveNum = System.Int32.Parse(identifier[4]);
                int curveInd = System.Int32.Parse(identifier[5]);
                if ((curveInd > (curveNum - 1)) || curveNum < 2)
                {
                    throw new System.Exception("Node naming in PopulateMaze is incorrect.");
                }
                if (curveInd == 0)
                {
                    currNeighbors.Add("base" + "-" + identifier[1] + "-" + identifier[2]); // NEEDS TO ADDED RECIPROCALLY (as the base doesn't if it has a conn) // FIXME reciprocal, or..., using maze for neighbor def
                    currNeighbors.Add("conn" + "-" + identifier[1] + "-" + identifier[2] + "-" + identifier[3] + "-" + identifier[4] + "-" + (1));
                }
                else if (curveInd == (curveNum - 1))
                {
                    currNeighbors.Add("base" + "-" + identifier[1] + "-" + identifier[3]);  // NEEDS TO ADDED RECIPROCALLY (as the base doesn't if it has a conn)
                    currNeighbors.Add("conn" + "-" + identifier[1] + "-" + identifier[2] + "-" + identifier[3] + "-" + identifier[4] + "-" + (curveNum - 2));
                }
                else
                {
                    currNeighbors.Add("conn" + "-" + identifier[1] + "-" + identifier[2] + "-" + identifier[3] + "-" + identifier[4] + "-" + (curveInd - 1));
                    currNeighbors.Add("conn" + "-" + identifier[1] + "-" + identifier[2] + "-" + identifier[3] + "-" + identifier[4] + "-" + (curveInd + 1));
                }
            }
            else
            {
                throw new System.Exception("Node naming in PopulateMaze is incorrect.");
            }
            neighbors.Add(node.Key, currNeighbors);
        }
        // Add neighbors to gravity frame nodes
        foreach (GravityNode node in gravityFrame)
        {
            if (node.identifier[0] == 'b') // isBase
            {
                foreach (string currneighbor in neighbors[node.identifier])
                {
                    node.neighbors.Add(gravityFrame.Find(x => x.identifier == currneighbor));
                }
            }
            if (node.identifier[0] == 'c') // isConn
            {
                foreach (string currneighbor in neighbors[node.identifier])
                {
                    node.neighbors.Add(gravityFrame.Find(x => x.identifier == currneighbor));
                }
                foreach (GravityNode nb in node.neighbors)
                {
                    if (nb.identifier[0] == 'b')
                    {
                        nb.neighbors.Add(node);
                    }                                                        // RECIPROCAL ADDING FOR BASE TO CONN // FIXME could also do with an 'if exists' type of check
                }
            }
        }
        // FIXME not all close nodes are merged
        //// Combine nodes at (nearly) identical positions
        //Stack<GravityNode> toRemove = new Stack<GravityNode>((int)Mathf.Round(gravityFrame.Count / 10f)); // guess...
        //for (int inode1 = 0; inode1 < gravityFrame.Count - 1; inode1++)
        //{
        //    for (int inode2 = inode1 + 1; inode2 < gravityFrame.Count; inode2++)
        //    {
        //        if ((Vector3.Distance(gravityFrame[inode1].position, gravityFrame[inode2].position) < 0.1f) && !toRemove.Contains(gravityFrame[inode2]))
        //        {
        //            // For each neighbor of node2:
        //            // - remove node2 from neighbor.neighbors
        //            // - add neighbor to node1.neighbors (if not already neighbors)
        //            // - add node1 to neigbor.neighbors (if not already neighbors)
        //            foreach (GravityNode neighborlvl2 in gravityFrame[inode2].neighbors)
        //            {
        //                neighborlvl2.neighbors.Remove(gravityFrame[inode2]);
        //                if (!gravityFrame[inode1].neighbors.Contains(neighborlvl2))
        //                {
        //                    gravityFrame[inode1].neighbors.Add(neighborlvl2);
        //                    neighborlvl2.neighbors.Add(gravityFrame[inode1]);
        //                }
        //            }
        //            // Then, remove node2 from node1 and from frame
        //            toRemove.Push(gravityFrame[inode2]);
        //            if (gravityFrame[inode1].neighbors.Contains(gravityFrame[inode2])) { gravityFrame[inode1].neighbors.Remove(gravityFrame[inode2]); }
        //        }
        //    }
        //}
        //while (toRemove.Count > 0)
        //{
        //    GravityNode currNode = toRemove.Pop();
        //    gravityFrame.Remove(currNode);
        //}

        // Add closeby list to each node
        AddClosebyNodes(closebyDist);
    }
コード例 #20
0
 public void Clear()
 {
     current = null;
     first   = null;
 }
コード例 #21
0
 public GravityList()
 {
     first   = null;
     current = null;
 }