void AStarPath() { AAPrism s = null, f = null; foreach (var item in a) { item.H = (item.Centre - finish.transform.position).sqrMagnitude; item.parent = null; item.state = NodeState.Untested; if (item.bounds.Contains(start.transform.position)) { item.Display(Color.green); s = item; } if (item.bounds.Contains(finish.transform.position)) { item.Display(Color.red); f = item; } } if (PathSearch(s, f)) { ColourPath(f); } else { Debug.Log("Failed to find path!"); } }
void ColourPath(AAPrism s) { if (s.parent == null) { return; } s.parent.Display(Color.magenta); ColourPath(s.parent); }
public void AddNeighbour(AAPrism neighbour) { NeighbourInfo n = new NeighbourInfo(neighbour); if (neighbours.Contains(n)) { return; } neighbours.Add(n); }
bool OutOfBounds(AAPrism current) { bool returnval = false; current.Contract(VoxelSize * .1f); foreach (var point in current.GetCorners()) { if (!bounds.Contains(point)) { returnval = true; } } current.Expand(VoxelSize * .1f); return(returnval); }
public void AddNeighbour(AAPrism neighbour, List <Vector3> points) { Vector3 average = Vector3.zero; foreach (var item in points) { average += item; } average /= points.Count; float d1 = (Centre - average).sqrMagnitude, d2 = (neighbour.Centre - average).sqrMagnitude; NeighbourInfo n = new NeighbourInfo(neighbour, d1 + d2, points); if (neighbours.Contains(n)) { return; } neighbours.Add(n); }
bool KnitStep(AAPrism current, Axis axis, float posneg) { current.Expand(axis, posneg * VoxelSize); current.Contract(VoxelSize * .1f); //This is a little hack to prevent coplanar hits along non-expanding sides //we have to make sure to expand again before exiting foreach (var point in current.GetCorners()) //check if we hit the outside bounds //TODO only do max and min? { if (!bounds.Contains(point)) { current.Expand(VoxelSize * .1f); current.Contract(axis, posneg * VoxelSize); return(false); } } foreach (var item in a) //check if we hit another prism { if (item.Equals(current)) { continue; } if (item.bounds.Intersects(current.bounds)) { current.Expand(VoxelSize * .1f); current.Contract(axis, posneg * VoxelSize); //log the neighbour relation current.AddNeighbour(item); item.AddNeighbour(current); return(false); } } current.Expand(VoxelSize * .1f); if (current.Intersects) //check if we hit an object { current.Contract(axis, posneg * VoxelSize); return(false); } else //no intersections so growth continues, remove all covered seeds { Bounds b = current.bounds; seeds.RemoveAll(item => b.Contains(item.Centre)); //TODO change to just intersection? (can't be full sized) return(true); } }
public List <Vector3> DetermineIntersectionPoints(AAPrism other) { double maxDelta = 1e-5; List <Vector3> points = new List <Vector3>(); Vector3 min = new Vector3(Mathf.Max(bounds.min.x, other.bounds.min.x), Mathf.Max(bounds.min.y, other.bounds.min.y), Mathf.Max(bounds.min.z, other.bounds.min.z)); Vector3 max = new Vector3(Mathf.Min(bounds.max.x, other.bounds.max.x), Mathf.Min(bounds.max.y, other.bounds.max.y), Mathf.Min(bounds.max.z, other.bounds.max.z)); Vector3 diff = max - min; //merge points on the zero dist. axes float[] xvals = Mathf.Abs(diff.x) < maxDelta ? new[] { min.x } : new[] { min.x, max.x }; float[] yvals = Mathf.Abs(diff.y) < maxDelta ? new[] { min.y } : new[] { min.y, max.y }; float[] zvals = Mathf.Abs(diff.z) < maxDelta ? new[] { min.z } : new[] { min.z, max.z }; if (!bounds.Intersects(other.bounds)) //check no intersection case { Debug.Log("No intersection"); //return points; } foreach (var x in xvals) { foreach (var y in yvals) { foreach (var z in zvals) { points.Add(new Vector3(x, y, z)); } } } if (points.Count > 4) //something is wrong, intersection is > 2 dimensional { Debug.Log("Prism intersection is box!"); } return(points); }
bool PathSearch(AAPrism current, AAPrism finish) { current.state = NodeState.Closed; if (current.Equals(finish)) { return(true); } foreach (var item in current.neighbours) { if (item.prism.state == NodeState.Closed) { continue; } if (item.prism.state == NodeState.Open) { if (item.distance < item.prism.G) //if the new g is smaller then the old one { item.prism.parent = current; item.prism.G = item.distance; } } else { item.prism.state = NodeState.Open; item.prism.parent = current; item.prism.G = item.distance; } } current.neighbours.Sort((x, y) => x.prism.F.CompareTo(y.prism.F)); foreach (var node in current.neighbours.Where(x => x.prism.state != NodeState.Closed)) { if (PathSearch(node.prism, finish)) { return(true); } } return(false); }
public NeighbourInfo(AAPrism item) { prism = item; }
public NeighbourInfo(AAPrism item, float dist, List <Vector3> points) { prism = item; distance = dist; intersectionPoints = points; }
List <Vector3> AStarPath(Vector3 s, Vector3 f) { AAPrism startPrism = null, endPrism = null; List <NavNode> list = new List <NavNode>(navNodes); //copy the list so we can modify it non-destructively foreach (var prism in a) //find the containing prism for start and finish { if (prism.bounds.Contains(s)) //TODO optimize with sort and end loop { prism.Display(Color.green); startPrism = prism; } if (prism.bounds.Contains(f)) { prism.Display(Color.red); endPrism = prism; } } //TODO add nullchecking on prisms to see if off grid if (startPrism == endPrism) //if they are in the same prism then we can travel direct { return(new List <Vector3> { s, f }); } NavNode startNode = new NavNode(s); //add start and finish to list NavNode endNode = new NavNode(f); list.Add(startNode); list.Add(endNode); foreach (var location in startPrism.GetAllPoints()) //update neighbours { NavNode node = getNodeAt(list, location); node.AddNeighbour(startNode); startNode.AddNeighbour(node); } foreach (var location in endPrism.GetAllPoints()) { NavNode node = getNodeAt(list, location); node.AddNeighbour(endNode); endNode.AddNeighbour(node); } foreach (var item in list) //prepare to pathfind { item.H = (item.position - endNode.position).sqrMagnitude; //TODO use regular mag to stop exponent growth? item.parent = null; item.state = NodeState.Untested; } List <Vector3> path = new List <Vector3>(); if (PathSearch(startNode, endNode)) //pathfind { Debug.Log("Path found!"); path = ReturnPath(endNode); for (int i = 0; i < path.Count - 1; i++) { DebugExtension.DebugPoint(path[i], Color.magenta, .5f); Debug.DrawLine(path[i], path[i + 1], Color.cyan); } SmoothPath(path); for (int i = 0; i < path.Count - 1; i++) { DebugExtension.DebugPoint(path[i], Color.magenta, .5f); Debug.DrawLine(path[i], path[i + 1], Color.yellow); } } else { Debug.Log("Failed to find path!"); } return(path); }
IEnumerator Knit() { //choose voxel and start growing; when edge hit, stop that edge Debug.Log("Beginning knit"); while (seeds.Count > 0) { Debug.Log("Seeds Remaining: " + seeds.Count); bool[] growing = new[] { true, true, true, true, true, true }; //+x, +y +z -x, -y -z AAPrism current = seeds[rand.Next(0, seeds.Count - 1)]; seeds.Remove(current); a.Add(current); current.isSeed = false; if (delay != 0) { foreach (var seed in seeds) { seed.Display(delay * 10f); } } while (growing[0] || growing[1] || growing[2] || growing[3] || growing[4] || growing[5]) { if (growing[0]) //step x { growing[0] = KnitStep(current, Axis.x, 1); if (delay != 0) { yield return(new WaitForSeconds(delay)); } } if (growing[1]) //step y { growing[1] = KnitStep(current, Axis.y, 1); if (delay != 0) { yield return(new WaitForSeconds(delay)); } } if (growing[2]) //step z { growing[2] = KnitStep(current, Axis.z, 1); if (delay != 0) { yield return(new WaitForSeconds(delay)); } } if (growing[3]) //step -x { growing[3] = KnitStep(current, Axis.x, -1); if (delay != 0) { yield return(new WaitForSeconds(delay)); } } if (growing[4]) //step -y { growing[4] = KnitStep(current, Axis.y, -1); if (delay != 0) { yield return(new WaitForSeconds(delay)); } } if (growing[5]) //step -z { growing[5] = KnitStep(current, Axis.z, -1); if (delay != 0) { yield return(new WaitForSeconds(delay)); } } } if (delay != 0) { yield return(new WaitForSeconds(delay)); } } foreach (var prism in a) { foreach (var neighbour in prism.neighbours) //calculate neighbour intersection points { neighbour.AddIntersectionPoints(prism.DetermineIntersectionPoints(neighbour.prism)); } } foreach (var prism in a) //set up navnodes { prism.drawn = false; List <NavNode> nodes = new List <NavNode>(); foreach (var point in prism.GetAllPoints()) { nodes.Add(new NavNode(point)); } for (int i = 0; i < nodes.Count - 1; i++) { for (int j = i + 1; j < nodes.Count; j++) { nodes[i].AddNeighbour(nodes[j]); nodes[j].AddNeighbour(nodes[i]); } } foreach (var item in nodes) { //if the node is already in the main list, just add neighbours if (navNodes.Any((x) => item.position == x.position)) { int index = navNodes.FindIndex((x) => item.position == x.position); foreach (var neighbour in item.neighbours) { navNodes[index].AddNeighbour(neighbour); } } else { navNodes.Add(item); //otherwise add the node } } } knitDone = true; }