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); } }
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); }
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); } } }
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); }
// 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); }
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); } }
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))); }
void GetPathToRandom() { VoronoiNode end = mesh3.nodes[RandomIndex()]; currentPath = AStarNavMesh.GetPath(lastPosition, end); lastPosition = end; CheckForBadPath(); }
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); }
public TrackableNode(VoronoiNode node, int j, Connection type) : base(node) { Type = new NodeConnection { J = j, Type = type }; }
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; }
void InitializePath() { if (AStarNavMesh.readyToPathfind == true) { lastPosition = mesh3.nodes[RandomIndex()]; this.transform.position = lastPosition.Position; currentState = State.NONE; initialized = true; } }
// 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(); } } } } }
void InitializeNavmesh() { //AStarNav = gameObject.GetComponent<AStartNavMesh3>(); if (navMesh != null && AStarNav.readyToPathfind) { currentNode = navMesh.nodes[0]; transform.position = currentNode.Position; GenerateRandomPath(); navMeshInitialized = true; } }
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); }
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); }
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; }
public void AddNeighbor(VoronoiNode n) { if (numNeighbors < 3) { neighbors[numNeighbors] = n.Id; numNeighbors++; } else { Debug.Log("Attempt to add 4th neighbor."); } }
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); }
// 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(); }
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); }
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); }
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); }
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); } } }
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); }
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); }