예제 #1
0
    public void largestNodesFirst(List <VoronoiNode> workingVoronoi)
    {
        List <VoronoiNode> toWorkWith = new List <VoronoiNode>();

        foreach (VoronoiNode node in workingVoronoi)
        {
            toWorkWith.Add(node);
        }

        toWorkWith.Sort(new nodeRadiusComparer());

        while (toWorkWith.Count > 0)
        {
            VoronoiNode masterNode = toWorkWith[0];
            toWorkWith.RemoveAt(0);

            List <VoronoiNode> toCull = new List <VoronoiNode>();

            foreach (VoronoiNode node in toWorkWith)
            {
                if (radiusOverlap(masterNode, node))
                {
                    linkRemove(node, masterNode);

                    toCull.Add(node);
                }
            }

            foreach (VoronoiNode node in toCull)
            {
                workingVoronoi.Remove(node);
                toWorkWith.Remove(node);
            }
        }
    }
    public static VoronoiEdgeNode GetLeftParentEdge(VoronoiNode node)
    {
        VoronoiNode returnNode    = node.mParent;
        VoronoiNode travelledNode = node;

        if (returnNode == null)
        {
            Debug.Log("null");
        }
        while (returnNode.mLeft == travelledNode)
        {
            if (returnNode.mParent == null)
            {
                return(null);
            }
            travelledNode = returnNode;
            returnNode    = returnNode.mParent;
        }
        if (returnNode.GetType() == typeof(VoronoiEdgeNode))
        {
            return((VoronoiEdgeNode)returnNode);
        }
        else
        {
            Debug.Log("Failed to get EdgeNode from GetLeftParentArc");
            return(null);
        }
    }
예제 #3
0
    public void CompleteEdge(VoronoiNode node)
    {
        if (!node.hasChildren())
        {
            return;
        }
        VoronoiEdgeNode edge   = (VoronoiEdgeNode)node;
        float           height = Camera.main.orthographicSize;
        float           width  = height * Camera.main.aspect;
        float           max;

        if (edge.mDirection.x > 0.0f)
        {
            max = Mathf.Max(width, edge.mStartVertex.x);
        }
        else
        {
            max = Mathf.Min(-width, edge.mStartVertex.x);
        }

        Vector2 endVertex = new Vector2(max, max * edge.slope + edge.yIntercept);

        edge.mEndVertex = endVertex;

        VoronoiEdge newRenderEdge = Instantiate(voronoiEdgePrefab, new Vector2(), Quaternion.identity).GetComponent <VoronoiEdge>();

        newRenderEdge.SetPosition(edge.mStartVertex, edge.mEndVertex);
        edges.Add(newRenderEdge);

        CompleteEdge(node.mLeft);
        CompleteEdge(node.mRight);
    }
예제 #4
0
    void Update()
    {
        List <Site> sites        = new List <Site>(siteGenerator.Sites);
        float       newMouseYpos = Camera.main.ScreenToWorldPoint(Input.mousePosition).y;

        if (Input.GetKeyDown(KeyCode.G))
        {
            renderParabolas = !renderParabolas;
            foreach (Site site in sites)
            {
                site.mParabola.SetParabolaRender(renderParabolas);
            }
        }

        if (sites.Count != 0 && renderParabolas && newMouseYpos != mouseYpos)
        {
            root = null;
            foreach (VoronoiEdge oldEdge in edges)
            {
                Destroy(oldEdge.gameObject);
            }
            edges.Clear();
            mouseYpos = newMouseYpos;
            foreach (Site site in sites)
            {
                site.mParabola.CalculateParabola(site, newMouseYpos);
            }
            eventQueue = new SortedSet <VoronoiEvent>(new EventComparer());
            foreach (Site site in sites)
            {
                if (site.transform.position.y <= mouseYpos)
                {
                    eventQueue.Add(new SiteEvent(site.transform.position));
                }
            }
            while (eventQueue.Count != 0)
            {
                VoronoiEvent popEvent = eventQueue.Min;
                eventQueue.Remove(popEvent);
                sweepY = popEvent.yCoord;
                if (removed.Contains(popEvent))
                {
                    removed.Remove(popEvent);
                    continue;
                }
                if (popEvent.GetType() == typeof(SiteEvent))
                {
                    AddArc(((SiteEvent)popEvent).mSite);
                }
                else
                {
                    RemoveArc((SqueezeEvent)popEvent);
                }
            }
            if (root != null)
            {
                CompleteEdge(root);
            }
        }
    }
예제 #5
0
    public void SqueezeEvent(VoronoiArcNode node)
    {
        VoronoiEdgeNode leftEdge  = VoronoiNode.GetLeftParentEdge(node);
        VoronoiEdgeNode rightEdge = VoronoiNode.GetRightParentEdge(node);

        VoronoiArcNode leftArc  = VoronoiNode.GetLeftChildArc(leftEdge);
        VoronoiArcNode rightArc = VoronoiNode.GetRightChildArc(rightEdge);

        if (leftArc == null || rightArc == null || leftArc.mFocus == rightArc.mFocus)
        {
            return;
        }

        Vector2 intersection = GetIntersection(leftEdge, rightEdge);

        if (intersection.Equals(new Vector2(-10000, -10000)))
        {
            return;
        }

        float circleX = leftArc.mFocus.x - intersection.x;
        float circleY = leftArc.mFocus.y - intersection.y;
        float radius  = Mathf.Sqrt((circleX * circleX) + (circleY * circleY));

        if (intersection.y - radius >= sweepY)
        {
            return;
        }


        SqueezeEvent squeezeEvent = new SqueezeEvent(intersection, node);

        node.squeezeEvent = squeezeEvent;
        eventQueue.Add(squeezeEvent);
    }
예제 #6
0
    // Start is called before the first frame update
    void Start()
    {
        //this is just for the test version, in the actual model we should just load the mesh in with the normal unity componenet
        MeshFilter mf   = GetComponent <MeshFilter> ();
        Mesh       mesh = new Mesh();

        mf.mesh = mesh;

        Vector3[] vertices = new Vector3[4];
        vertices[0]   = new Vector3(0, 0, 0);
        vertices[1]   = new Vector3(1, 0, 0);
        vertices[2]   = new Vector3(0, 0, 1);
        vertices[3]   = new Vector3(0, 1, 0);
        mesh.vertices = vertices;

        //add the points to the tris in groups of 3 in(ccw?) rotational order,
        //if the normal is wrong change the order
        int[] tris = new int[] {
            0, 1, 2,
            1, 0, 3,
            0, 2, 3,
            2, 1, 3
        };
        mesh.triangles = tris;

        //normals are by vertex and a pain in the ass to figure out, just use default
        mesh.RecalculateNormals();


        rootNode = new VoronoiNode(0);
        VoronoiNode n1 = new VoronoiNode(1);
        VoronoiNode n2 = new VoronoiNode(2);
        VoronoiNode n3 = new VoronoiNode(3);
    }
예제 #7
0
    public VoronoiArcNode GetParabolaUnderNew(float newSiteX)
    {
        VoronoiNode checkNode = root;
        float       xCoord    = 0.0f;

        while (checkNode.hasChildren())
        {
            xCoord = GetXCoord(checkNode, sweepY);
            if (xCoord > newSiteX)
            {
                checkNode = checkNode.mLeft;
            }
            else
            {
                checkNode = checkNode.mRight;
            }
        }

        if (checkNode.GetType() == typeof(VoronoiArcNode))
        {
            return((VoronoiArcNode)checkNode);
        }
        else
        {
            Debug.Log("Failed to get ArcNode on GetParabolaUnderNew");
            return(null);
        }
    }
예제 #8
0
        private float GetVoronoiValue(List <VoronoiNode> points, int x, int y)
        {
            Vector2 xVec = new Vector2(x, y);

            float       minDist = float.MaxValue;
            VoronoiNode maxNode = null;

            for (int i = 0; i < points.Count; i++)
            {
                VoronoiNode vor = points[i];
                vor.dist = MathFunctions.PointLineDistance2D(vor.pointA, vor.pointB, xVec);

                if (vor.dist < minDist)
                {
                    minDist = vor.dist;
                    maxNode = vor;
                }
            }

            if (maxNode == null)
            {
                return(1.0f);
            }

            return((float)(1e-2 * (maxNode.dist / Overworld.Width)));
        }
예제 #9
0
    void GetPathToRandom()
    {
        VoronoiNode end = mesh3.nodes[RandomIndex()];

        currentPath  = AStarNavMesh.GetPath(lastPosition, end);
        lastPosition = end;
        CheckForBadPath();
    }
예제 #10
0
    public void removeNeighbour(VoronoiNode pNeighbour)
    {
        neighbours.Remove(pNeighbour);

        if (neighbours.Count <= 1)
        {
            isLeaf = true;
        }
    }
    public VoronoiNode GetClosestNode(Vector3 position)
    {
        VoronoiNode ClosestNode = openHeap.GetNode(0);

        openHeap.ResetHeap();
        openHeap.Push(0);

        int   numFurther  = 0;
        float closestDist = 10000;

        int MaxNumLoops = 100000;

        while (!openHeap.IsEmpty() && MaxNumLoops > 0)
        {
            MaxNumLoops--;
            VoronoiNode least     = openHeap.Pop();
            float       distToPos = Vector3.SqrMagnitude(least.Position - position);

            if (distToPos < closestDist)
            {
                ClosestNode = least;
                closestDist = distToPos;
                numFurther  = 0;
            }
            else
            {
                numFurther++;
                if (numFurther > 10)
                {
                    return(ClosestNode);
                }
            }

            int[] neighbors = least.GetNeighbors();
            for (int i = 0; i < 3; i++)
            {
                VoronoiNode nbr = openHeap.GetNode(neighbors[i]);
                if (!nbr.Closed && !nbr.Open)
                {
                    openHeap.SetHeuristic(nbr.Id, distToPos);
                    openHeap.SetCost(nbr.Id);
                    openHeap.Push(nbr.Id);
                }
            }
        }

        if (MaxNumLoops == 0)
        {
            Debug.Log("error: exited due to too many iterations in pathfinding loop");
        }
        else
        {
            Debug.Log("error: no path found");
        }

        return(ClosestNode);
    }
예제 #12
0
 public TrackableNode(VoronoiNode node, int j, Connection type)
     : base(node)
 {
     Type = new NodeConnection
     {
         J    = j,
         Type = type
     };
 }
예제 #13
0
    void SwapNodes(int i, int j)
    {
        VoronoiNode tNode = nodeHeap[i];

        nodeHeap[i] = nodeHeap[j];
        nodeHeap[j] = tNode;
        locationMap[nodeHeap[j].Id] = j;
        locationMap[nodeHeap[i].Id] = i;
    }
예제 #14
0
 void InitializePath()
 {
     if (AStarNavMesh.readyToPathfind == true)
     {
         lastPosition            = mesh3.nodes[RandomIndex()];
         this.transform.position = lastPosition.Position;
         currentState            = State.NONE;
         initialized             = true;
     }
 }
예제 #15
0
    // Update is called once per frame
    void Update()
    {
        if (initialized == false)
        {
            InitializePath(); return;
        }

        if (currentState == State.NONE)
        {
            ChangeState();
            DoStateAction();
        }
        else if (currentState != State.LOOKING)
        {
            Vector3 movementDirection = currentPath[pathListIndex] - transform.position;
            if (movementDirection != Vector3.zero)
            {
                Quaternion rot = Quaternion.LookRotation(movementDirection);
                transform.rotation = Quaternion.RotateTowards(transform.rotation, rot, rotSpeed * Time.deltaTime);
            }

            if (wings.activeInHierarchy)
            {
                this.transform.position = Vector3.MoveTowards(this.transform.position, currentPath[pathListIndex], (speed + tempSpeed) * Time.deltaTime) + jumpDirection * Time.deltaTime;
                jumpDirection          *= jumpDecay;
            }
            else
            {
                this.transform.position = Vector3.MoveTowards(this.transform.position, currentPath[pathListIndex], speed * Time.deltaTime);
            }

            if (Vector3.SqrMagnitude(this.transform.position - currentPath[pathListIndex]) <= epsilon)
            {
                wings.SetActive(false);
                // update current position node

                pathListIndex--;
                if (pathListIndex == -1)
                {
                    currentState = State.NONE;
                }
                else
                {
                    //we are pathfinding, but our state has changed, recalc current node and
                    EnemyProximityBehavior.State priorState = currentState;
                    ChangeState();
                    if (currentState != priorState)
                    {
                        lastPosition = AStarNavMesh.GetClosestNode(transform.position);
                        DoStateAction();
                    }
                }
            }
        }
    }
예제 #16
0
 void InitializeNavmesh()
 {
     //AStarNav = gameObject.GetComponent<AStartNavMesh3>();
     if (navMesh != null && AStarNav.readyToPathfind)
     {
         currentNode        = navMesh.nodes[0];
         transform.position = currentNode.Position;
         GenerateRandomPath();
         navMeshInitialized = true;
     }
 }
예제 #17
0
        public override NodeViewModel CreateModel()
        {
            FilterNode result = null;

            switch (filter)
            {
            case NoiseFilter.Pipe:
                result = new PipeNode();
                break;

            case NoiseFilter.SumFractal:
                result = new SumFractalNode();
                break;

            case NoiseFilter.SinFractal:
                result = new SinFractalNode();
                break;

            case NoiseFilter.Billow:
                result = new BillowNode();
                break;

            case NoiseFilter.MultiFractal:
                result = new MultiFractalNode();
                break;

            case NoiseFilter.HeterogeneousMultiFractal:
                result = new HeterogeneousMultiFractalNode();
                break;

            case NoiseFilter.HybridMultiFractal:
                result = new HybridMultiFractalNode();
                break;

            case NoiseFilter.RidgedMultiFractal:
                result = new RidgedMultiFractalNode();
                break;

            case NoiseFilter.Voronoi:
                result = new VoronoiNode();
                break;
            }

            (result.Frequency.Editor as FloatEditorViewModel).Value      = frequency;
            (result.Lacunarity.Editor as FloatEditorViewModel).Value     = lacunarity;
            (result.Octaves.Editor as ValueEditorViewModel <int?>).Value = octaves;
            (result.Offset.Editor as FloatEditorViewModel).Value         = offset;
            (result.Gain.Editor as FloatEditorViewModel).Value           = gain;

            result.Name     = name;
            result.Position = pos;

            return(result);
        }
예제 #18
0
    public VoronoiNode Pop()
    {
        nodeHeap[0].Open   = false;
        nodeHeap[0].Closed = true;
        //could test for size 0 here, but wont for speed
        VoronoiNode top = nodeHeap[0];

        numNodes--;
        SwapNodes(0, numNodes);
        TrickleDown(0);
        return(top);
    }
예제 #19
0
    void FlyAwayFromPlayer()
    {
        //launch away from current surface and land on a node far from the player
        wings.SetActive(true);
        jumpDirection = lastPosition.normal * 2 * tempSpeed;
        Vector3 playerPos = player.transform.position;

        lastPosition = AStarNavMesh.GetFurthestNode(playerPos, 20);
        currentPath  = new List <Vector3>();
        currentPath.Add(lastPosition.Position);
        pathListIndex = 0;
    }
예제 #20
0
 public void AddNeighbor(VoronoiNode n)
 {
     if (numNeighbors < 3)
     {
         neighbors[numNeighbors] = n.Id;
         numNeighbors++;
     }
     else
     {
         Debug.Log("Attempt to add 4th neighbor.");
     }
 }
예제 #21
0
        bool IsPermutation(Map map, VoronoiNodes source, VoronoiNodes target)
        {
            for (int i = 0; i < source.Nodes.Count; ++i)
            {
                VoronoiNode sourceNode = source.Nodes[i];
                VoronoiNode targetNode = target.Nodes[map.GetMapping(i)];
                if ((sourceNode.Position - targetNode.Position).Abs() > 1e-10)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #22
0
    // remove remove from neighbours and link them to by instead
    private void linkRemove(VoronoiNode remove, VoronoiNode by)
    {
        foreach (VoronoiNode neighbour in remove.getNeighbours())
        {
            neighbour.removeNeighbour(remove);

            if (neighbour != by)
            {
                neighbour.addNeighbour(by);
                by.addNeighbour(neighbour);
            }
        }

        remove.removeAllNeighbours();
    }
예제 #23
0
    private void DrawTriangle(VoronoiNode node, Color c)
    {
        Vector3 nl0 = node.vertices[0] - node.Position;

        nl0 = nl0 * .9f + node.Position;
        Vector3 nl1 = node.vertices[1] - node.Position;

        nl1 = nl1 * .9f + node.Position;
        Vector3 nl2 = node.vertices[2] - node.Position;

        nl2 = nl2 * .9f + node.Position;
        Debug.DrawLine(nl0, nl1, c, .25f, true);
        Debug.DrawLine(nl2, nl0, c, .25f, true);
        Debug.DrawLine(nl2, nl1, c, .25f, true);
    }
예제 #24
0
        private void Voronoi(int width, int height, int numVoronoiPoints)
        {
            List <List <Vector2> > vPoints = new List <List <Vector2> >();
            List <float>           rands   = new List <float>();

            for (int i = 0; i < numVoronoiPoints; i++)
            {
                Vector2 v = GetEdgePoint(width, height);

                for (int j = 0; j < 4; j++)
                {
                    List <Vector2> line = new List <Vector2>();
                    rands.Add(1.0f);

                    line.Add(v);
                    v += new Vector2(MathFunctions.Rand() - 0.5f, MathFunctions.Rand() - 0.5f) * Overworld.Width * 0.5f;
                    line.Add(v);
                    vPoints.Add(line);
                }
            }


            List <VoronoiNode> nodes = new List <VoronoiNode>();

            foreach (List <Vector2> pts in vPoints)
            {
                for (int j = 0; j < pts.Count - 1; j++)
                {
                    VoronoiNode node = new VoronoiNode
                    {
                        pointA = pts[j],
                        pointB = pts[j + 1]
                    };
                    nodes.Add(node);
                }
            }

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Overworld.Map.Map[x, y].Faults = GetVoronoiValue(nodes, x, y);
                }
            }

            ScaleMap(Overworld.Map.Map, width, height, OverworldField.Faults);
            OverworldImageOperations.Distort(Overworld.Map.Map, width, height, 20, 0.01f, OverworldField.Faults);
        }
예제 #25
0
    public List <Vector3> GetBorderPoints(VoronoiNode n)
    {
        List <Vector3> bns = new List <Vector3>();

        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (Vector3.Distance(vertices[i], n.vertices[j]) < .01f)
                {
                    bns.Add(vertices[i]);
                }
            }
        }
        return(bns);
    }
예제 #26
0
    public void triangleCull(List <VoronoiNode> workingVoronoi)
    {
        List <VoronoiNode> toWorkWith = new List <VoronoiNode>();

        copyList(workingVoronoi, toWorkWith);
        toWorkWith.Sort(new nodeDegreeComparer());

        while (toWorkWith.Count > 0)
        {
            VoronoiNode masterNode = toWorkWith[0];
            toWorkWith.RemoveAt(0);

            List <VoronoiNode> removeTriangles = new List <VoronoiNode>();
            copyList(masterNode.getNeighbours(), removeTriangles);


            while (removeTriangles.Count > 0)
            {
                bool hasTriangle            = false;
                List <VoronoiNode> triangle = new List <VoronoiNode>();
                triangle.Add(masterNode);

                foreach (VoronoiNode node in masterNode.getNeighbours())
                {
                    if (removeTriangles[0].getNeighbours().Contains(node))
                    {
                        triangle.Add(node);
                        triangle.Add(removeTriangles[0]);

                        hasTriangle = true;
                        break;
                    }
                }

                if (hasTriangle)
                {
                    triangle.Sort(new nodeRadiusComparer());
                    triangle.Reverse();

                    linkRemove(triangle[0], masterNode);
                    workingVoronoi.Remove(triangle[0]);
                }

                removeTriangles.RemoveAt(0);
            }
        }
    }
예제 #27
0
    private float computeRadius(VoronoiNode node)
    {
        //Create Direction vectorList
        List <Vector3> directionVectors = new List <Vector3>();

        float angleChecks = 360f / numOfDirections;

        for (float i = 0; i < 360; i += angleChecks)
        {
            directionVectors.Add((Quaternion.AngleAxis(i, Vector3.up) * new Vector3(1, 0, 0)));
        }

        //Create Height Dictionary
        Dictionary <Vector3, float> heightCounter = new Dictionary <Vector3, float>();
        float initialHeight = terrain.SampleHeight(node.getPosition());

        foreach (Vector3 vector in directionVectors)
        {
            heightCounter.Add(vector, initialHeight);
        }

        //Compute
        Vector3 initialPosition = node.getPosition();

        for (float i = iterationDistance; i < Mathf.Max(terrainX, terrainY); i += iterationDistance)
        {
            foreach (Vector3 direction in directionVectors)
            {
                Vector3 positionChecking = initialPosition + (direction * i);

                if (positionChecking.x > terrainX || positionChecking.x < 0 || positionChecking.y > terrainY || positionChecking.y < 0)
                {
                    return(i);
                }

                float currentSample = terrain.SampleHeight(positionChecking);
                if (Mathf.Abs(currentSample - heightCounter[direction]) > maxTraversableSlope * (iterationDistance / Mathf.Min(gridXSpacing, gridYSpacing)))
                {
                    return(i);
                }

                heightCounter[direction] = currentSample;
            }
        }

        return(0);
    }
    public void setParent(VoronoiNode node)
    {
        if (node.mParent == null)
        {
            mParent = null;
            return;
        }

        if (node.mParent.mLeft == node)
        {
            node.mParent.setLeftNode(this);
        }
        else
        {
            node.mParent.setRightNode(this);
        }
    }
    public VoronoiNode GetFurthestNode(Vector3 position, float distToFlee)
    {
        VoronoiNode FurthestNode = openHeap.GetNode(Random.Range(0, navMesh.nodes.Length - 1));

        openHeap.ResetHeap();
        openHeap.Push(0);

        int MaxNumLoops = 100000;

        while (!openHeap.IsEmpty() && MaxNumLoops > 0)
        {
            MaxNumLoops--;
            VoronoiNode least     = openHeap.Pop();
            float       distToPos = Vector3.SqrMagnitude(least.Position - position);

            if (distToPos > distToFlee)
            {
                return(FurthestNode);
            }

            int[] neighbors = least.GetNeighbors();
            for (int i = 0; i < 3; i++)
            {
                VoronoiNode nbr = openHeap.GetNode(neighbors[i]);
                if (!nbr.Closed && !nbr.Open)
                {
                    openHeap.SetHeuristic(nbr.Id, 1 / distToPos);
                    openHeap.SetCost(nbr.Id);
                    openHeap.Push(nbr.Id);
                }
            }
        }

        if (MaxNumLoops == 0)
        {
            Debug.Log("error: exited due to too many iterations in pathfinding loop");
        }
        else
        {
            Debug.Log("error: no path found");
        }

        return(FurthestNode);
    }
    public static VoronoiArcNode GetLeftChildArc(VoronoiNode node)
    {
        if (node == null)
        {
            return(null);
        }
        VoronoiNode returnNode = node.mLeft;

        while (returnNode.hasChildren())
        {
            returnNode = returnNode.mRight;
        }
        if (returnNode.GetType() == typeof(VoronoiArcNode))
        {
            return((VoronoiArcNode)returnNode);
        }
        Debug.Log("Failed to get ArcNode from GetLeftChildArc");
        return(null);
    }
예제 #31
0
        private void Voronoi(int width, int height, int numVoronoiPoints)
        {
            List<List<Vector2>> vPoints = new List<List<Vector2>>();
            List<float> rands = new List<float>();

            /*
            List<Vector2> edge = new List<Vector2>
            {
                new Vector2(0, 0),
                new Vector2(width, 0),
                new Vector2(width, height),
                new Vector2(0, height),
                new Vector2(0, 0)
            };

            List<Vector2> randEdge = new List<Vector2>();
            for (int i = 1; i < edge.Count; i++)
            {
                if (MathFunctions.RandEvent(0.5f))
                {
                    randEdge.Add(edge[i]);
                    randEdge.Add(edge[i - 1]);
                }
            }

            vPoints.Add(randEdge);
             */
            for(int i = 0; i < numVoronoiPoints; i++)
            {
                Vector2 v = GetEdgePoint(width, height);

                for(int j = 0; j < 4; j++)
                {
                    List<Vector2> line = new List<Vector2>();
                    rands.Add(1.0f);

                    line.Add(v);
                    v += new Vector2(MathFunctions.Rand() - 0.5f, MathFunctions.Rand() - 0.5f) * Settings.Width * 0.5f;
                    line.Add(v);
                    vPoints.Add(line);
                }
            }

            List<VoronoiNode> nodes = new List<VoronoiNode>();
            foreach (List<Vector2> pts in vPoints)
            {
                for(int j = 0; j < pts.Count - 1; j++)
                {
                    VoronoiNode node = new VoronoiNode
                    {
                        pointA = pts[j],
                        pointB = pts[j + 1]
                    };
                    nodes.Add(node);
                }
            }

            for(int x = 0; x < width; x++)
            {
                for(int y = 0; y < height; y++)
                {
                    Overworld.Map[x, y].Faults = GetVoronoiValue(nodes, x, y);
                }
            }

            ScaleMap(Overworld.Map, width, height, Overworld.ScalarFieldType.Faults);
            Overworld.Distort(width, height, 20, 0.01f, Overworld.ScalarFieldType.Faults);
        }