private void ResetLinkedVoxelSpans() { int len = linkedSpans.Length; linkedSpanCount = width*depth; LinkedVoxelSpan df = new LinkedVoxelSpan(InvalidSpanValue,InvalidSpanValue,-1,-1); for (int i=0;i<len;) { // 16x unrolling, actually improves performance linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; } removedStackCount = 0; }
public VoxelArea(int width, int depth) { this.width = width; this.depth = depth; int wd = width * depth; compactCells = new CompactVoxelCell[wd]; #if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST // & ~0xF ensures it is a multiple of 16. Required for unrolling linkedSpans = new LinkedVoxelSpan[((int)(wd * AvgSpanLayerCountEstimate) + 15) & ~0xF]; ResetLinkedVoxelSpans(); #else cells = new VoxelCell[wd]; #endif DirectionX = new int[4] { -1, 0, 1, 0 }; DirectionZ = new int[4] { 0, width, 0, -width }; VectorDirection = new Vector3[4] { Vector3.left, Vector3.forward, Vector3.right, Vector3.back }; }
public static void DeserializeVoxelAreaData(byte[] bytes, VoxelArea target) { #if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(); System.IO.MemoryStream stream = new System.IO.MemoryStream(); stream.Write(bytes,0,bytes.Length); stream.Position = 0; zip = Ionic.Zip.ZipFile.Read(stream); System.IO.MemoryStream stream2 = new System.IO.MemoryStream(); zip["data"].Extract (stream2); stream2.Position = 0; System.IO.BinaryReader reader = new System.IO.BinaryReader(stream2); int width = reader.ReadInt32(); int depth = reader.ReadInt32(); if (target.width != width) throw new System.ArgumentException ("target VoxelArea has a different width than the data ("+target.width + " != " + width + ")"); if (target.depth != depth) throw new System.ArgumentException ("target VoxelArea has a different depth than the data ("+target.depth + " != " + depth + ")"); LinkedVoxelSpan[] spans = new LinkedVoxelSpan[reader.ReadInt32()]; for (int i=0;i<spans.Length;i++) { spans[i].area = reader.ReadInt32(); spans[i].bottom = reader.ReadUInt32(); spans[i].next = reader.ReadInt32(); spans[i].top = reader.ReadUInt32(); } target.linkedSpans = spans; #else throw new System.NotImplementedException ("This method only works with !ASTAR_RECAST_CLASS_BASED_LINKED_LIST"); #endif }
public static void DeserializeVoxelAreaData(byte[] bytes, VoxelArea target) { Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(); System.IO.MemoryStream stream = new System.IO.MemoryStream(); stream.Write(bytes, 0, bytes.Length); stream.Position = 0; zip = Ionic.Zip.ZipFile.Read(stream); System.IO.MemoryStream stream2 = new System.IO.MemoryStream(); zip["data"].Extract(stream2); stream2.Position = 0; System.IO.BinaryReader reader = new System.IO.BinaryReader(stream2); int width = reader.ReadInt32(); int depth = reader.ReadInt32(); if (target.width != width) { throw new System.ArgumentException("target VoxelArea has a different width than the data (" + target.width + " != " + width + ")"); } if (target.depth != depth) { throw new System.ArgumentException("target VoxelArea has a different depth than the data (" + target.depth + " != " + depth + ")"); } LinkedVoxelSpan[] spans = new LinkedVoxelSpan[reader.ReadInt32()]; for (int i = 0; i < spans.Length; i++) { spans[i].area = reader.ReadInt32(); spans[i].bottom = reader.ReadUInt32(); spans[i].next = reader.ReadInt32(); spans[i].top = reader.ReadUInt32(); } target.linkedSpans = spans; }
private void ResetLinkedVoxelSpans() { int num = this.linkedSpans.Length; this.linkedSpanCount = this.width * this.depth; LinkedVoxelSpan linkedVoxelSpan = new LinkedVoxelSpan(uint.MaxValue, uint.MaxValue, -1, -1); for (int i = 0; i < num; i++) { this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; } this.removedStackCount = 0; }
public static void DeserializeVoxelAreaData (byte[] bytes, VoxelArea target) { #if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(); System.IO.MemoryStream stream = new System.IO.MemoryStream(); stream.Write(bytes,0,bytes.Length); stream.Position = 0; zip = Ionic.Zip.ZipFile.Read(stream); System.IO.MemoryStream stream2 = new System.IO.MemoryStream(); zip["data"].Extract (stream2); stream2.Position = 0; System.IO.BinaryReader reader = new System.IO.BinaryReader(stream2); int width = reader.ReadInt32(); int depth = reader.ReadInt32(); if (target.width != width) throw new System.ArgumentException ("target VoxelArea has a different width than the data ("+target.width + " != " + width + ")"); if (target.depth != depth) throw new System.ArgumentException ("target VoxelArea has a different depth than the data ("+target.depth + " != " + depth + ")"); LinkedVoxelSpan[] spans = new LinkedVoxelSpan[reader.ReadInt32()]; for (int i=0;i<spans.Length;i++) { spans[i].area = reader.ReadInt32(); spans[i].bottom = reader.ReadUInt32(); spans[i].next = reader.ReadInt32(); spans[i].top = reader.ReadUInt32(); } target.linkedSpans = spans; #else throw new System.NotImplementedException ("This method only works with !ASTAR_RECAST_CLASS_BASED_LINKED_LIST"); #endif }
public void AddLinkedSpan (int index, uint bottom, uint top, int area, int voxelWalkableClimb) { #if ASTAR_RECAST_CLASS_BASED_LINKED_LIST cells[index].AddSpan(bottom,top,area,voxelWalkableClimb); #else // linkedSpans[index] is the span with the lowest y-coordinate at the position x,z such that index=x+z*width // i.e linkedSpans is a 2D array laid out in a 1D array (for performance and simplicity) // Check if there is a root span, otherwise we can just add a new (valid) span and exit if (linkedSpans[index].bottom == InvalidSpanValue) { linkedSpans[index] = new LinkedVoxelSpan(bottom,top,area); return; } int prev = -1; // Original index, the first span we visited int oindex = index; while (index != -1) { if (linkedSpans[index].bottom > top) { // If the current span's bottom higher up than the span we want to insert's top, then they do not intersect // and we should just insert a new span here break; } else if (linkedSpans[index].top < bottom) { // The current span and the span we want to insert do not intersect // so just skip to the next span (it might intersect) prev = index; index = linkedSpans[index].next; } else { // Intersection! Merge the spans // Find the new bottom and top for the merged span bottom = System.Math.Min (linkedSpans[index].bottom, bottom); top = System.Math.Max (linkedSpans[index].top, top); // voxelWalkableClimb is flagMergeDistance, when a walkable flag is favored before an unwalkable one // So if a walkable span intersects an unwalkable span, the walkable span can be up to voxelWalkableClimb // below the unwalkable span and the merged span will still be walkable if (System.Math.Abs ((int)top - (int)linkedSpans[index].top) <= voxelWalkableClimb) { // linkedSpans[index] is the lowest span, but we might use that span's area anyway if it is walkable area = System.Math.Max (area,linkedSpans[index].area); } // Find the next span in the linked list int next = linkedSpans[index].next; if (prev != -1) { // There is a previous span // Remove this span from the linked list linkedSpans[prev].next = next; // Add this span index to a list for recycling PushToSpanRemovedStack (index); // Move to the next span in the list index = next; } else if (next != -1) { // This was the root span and there is a span left in the linked list // Remove this span from the linked list by assigning the next span as the root span linkedSpans[oindex] = linkedSpans[next]; // Recycle the old span index PushToSpanRemovedStack (next); // Move to the next span in the list // NOP since we just removed the current span, the next span // we want to visit will have the same index as we are on now (i.e oindex) } else { // This was the root span and there are no other spans in the linked list // Just replace the root span with the merged span and exit linkedSpans[oindex] = new LinkedVoxelSpan(bottom,top,area); return; } } } // We now have a merged span that needs to be inserted // and connected with the existing spans // The new merged span will be inserted right after 'prev' (if it exists, otherwise before index) // Make sure that we have enough room in our array if (linkedSpanCount >= linkedSpans.Length) { LinkedVoxelSpan[] tmp = linkedSpans; int count = linkedSpanCount; int popped = removedStackCount; linkedSpans = new LinkedVoxelSpan[linkedSpans.Length*2]; ResetLinkedVoxelSpans(); linkedSpanCount = count; removedStackCount = popped; for (int i=0;i<linkedSpanCount;i++) { linkedSpans[i] = tmp[i]; } Debug.Log ("Layer estimate too low, doubling size of buffer.\nThis message is harmless."); } // Take a node from the recycling stack if possible // Otherwise create a new node (well, just a new index really) int nextIndex; if (removedStackCount > 0) { removedStackCount--; nextIndex = removedStack[removedStackCount]; } else { nextIndex = linkedSpanCount; linkedSpanCount++; } if (prev != -1) { //span.next = prev.next; //prev.next = span; linkedSpans[nextIndex] = new LinkedVoxelSpan(bottom,top,area,linkedSpans[prev].next); linkedSpans[prev].next = nextIndex; } else { //span.next = firstSpan; //firstSpan = span; linkedSpans[nextIndex] = linkedSpans[oindex]; linkedSpans[oindex] = new LinkedVoxelSpan(bottom,top,area,nextIndex); } #endif }
public VoxelArea (int width, int depth) { this.width = width; this.depth = depth; int wd = width*depth; compactCells = new CompactVoxelCell[wd]; #if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST // & ~0xF ensures it is a multiple of 16. Required for unrolling linkedSpans = new LinkedVoxelSpan[((int)(wd*AvgSpanLayerCountEstimate) + 15)& ~0xF]; ResetLinkedVoxelSpans(); #else cells = new VoxelCell[wd]; #endif DirectionX = new int[4] {-1,0,1,0}; DirectionZ = new int[4] {0,width,0,-width}; VectorDirection = new Vector3[4] {Vector3.left, Vector3.forward,Vector3.right, Vector3.back}; }
private void ResetLinkedVoxelSpans () { int len = linkedSpans.Length; linkedSpanCount = width*depth; LinkedVoxelSpan df = new LinkedVoxelSpan(InvalidSpanValue,InvalidSpanValue,-1,-1); for (int i=0;i<len;) { // 16x unrolling, actually improves performance linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; linkedSpans[i] = df;i++; } removedStackCount = 0; }
public void AddLinkedSpan(int index, uint bottom, uint top, int area, int voxelWalkableClimb) { #if ASTAR_RECAST_CLASS_BASED_LINKED_LIST cells[index].AddSpan(bottom,top,area,voxelWalkableClimb); #else // linkedSpans[index] is the span with the lowest y-coordinate at the position x,z such that index=x+z*width // i.e linkedSpans is a 2D array laid out in a 1D array (for performance and simplicity) // Check if there is a root span, otherwise we can just add a new (valid) span and exit if (linkedSpans[index].bottom == InvalidSpanValue) { linkedSpans[index] = new LinkedVoxelSpan(bottom,top,area); return; } int prev = -1; // Original index, the first span we visited int oindex = index; while (index != -1) { if (linkedSpans[index].bottom > top) { // If the current span's bottom higher up than the span we want to insert's top, then they do not intersect // and we should just insert a new span here break; } else if (linkedSpans[index].top < bottom) { // The current span and the span we want to insert do not intersect // so just skip to the next span (it might intersect) prev = index; index = linkedSpans[index].next; } else { // Intersection! Merge the spans // Find the new bottom and top for the merged span bottom = System.Math.Min (linkedSpans[index].bottom, bottom); top = System.Math.Max (linkedSpans[index].top, top); // voxelWalkableClimb is flagMergeDistance, when a walkable flag is favored before an unwalkable one // So if a walkable span intersects an unwalkable span, the walkable span can be up to voxelWalkableClimb // below the unwalkable span and the merged span will still be walkable if (System.Math.Abs ((int)top - (int)linkedSpans[index].top) <= voxelWalkableClimb) { // linkedSpans[index] is the lowest span, but we might use that span's area anyway if it is walkable area = System.Math.Max (area,linkedSpans[index].area); } // Find the next span in the linked list int next = linkedSpans[index].next; if (prev != -1) { // There is a previous span // Remove this span from the linked list linkedSpans[prev].next = next; // Add this span index to a list for recycling PushToSpanRemovedStack (index); // Move to the next span in the list index = next; } else if (next != -1) { // This was the root span and there is a span left in the linked list // Remove this span from the linked list by assigning the next span as the root span linkedSpans[oindex] = linkedSpans[next]; // Recycle the old span index PushToSpanRemovedStack (next); // Move to the next span in the list // NOP since we just removed the current span, the next span // we want to visit will have the same index as we are on now (i.e oindex) } else { // This was the root span and there are no other spans in the linked list // Just replace the root span with the merged span and exit linkedSpans[oindex] = new LinkedVoxelSpan(bottom,top,area); return; } } } // We now have a merged span that needs to be inserted // and connected with the existing spans // The new merged span will be inserted right after 'prev' (if it exists, otherwise before index) // Make sure that we have enough room in our array if (linkedSpanCount >= linkedSpans.Length) { LinkedVoxelSpan[] tmp = linkedSpans; int count = linkedSpanCount; int popped = removedStackCount; linkedSpans = new LinkedVoxelSpan[linkedSpans.Length*2]; ResetLinkedVoxelSpans(); linkedSpanCount = count; removedStackCount = popped; for (int i=0;i<linkedSpanCount;i++) { linkedSpans[i] = tmp[i]; } Debug.Log ("Layer estimate too low, doubling size of buffer.\nThis message is harmless."); } // Take a node from the recycling stack if possible // Otherwise create a new node (well, just a new index really) int nextIndex; if (removedStackCount > 0) { removedStackCount--; nextIndex = removedStack[removedStackCount]; } else { nextIndex = linkedSpanCount; linkedSpanCount++; } if (prev != -1) { //span.next = prev.next; //prev.next = span; linkedSpans[nextIndex] = new LinkedVoxelSpan(bottom,top,area,linkedSpans[prev].next); linkedSpans[prev].next = nextIndex; } else { //span.next = firstSpan; //firstSpan = span; linkedSpans[nextIndex] = linkedSpans[oindex]; linkedSpans[oindex] = new LinkedVoxelSpan(bottom,top,area,nextIndex); } #endif }
public void AddLinkedSpan (int index, uint bottom, uint top, int area, int voxelWalkableClimb) { #if !ASTAR_RECAST_ARRAY_BASED_LINKED_LIST cells[index].AddSpan(bottom,top,area,voxelWalkableClimb); #else /* Check if the span is valid, otherwise we can replace it with a new (valid) span */ if (linkedSpans[index].bottom == InvalidSpanValue) { linkedSpans[index] = new LinkedVoxelSpan(bottom,top,area); return; } int prev = -1; int oindex = index; while (index != -1) { if (linkedSpans[index].bottom > top) { break; } else if (linkedSpans[index].top < bottom) { prev = index; index = linkedSpans[index].next; } else { if (linkedSpans[index].bottom < bottom) { bottom = linkedSpans[index].bottom; } if (linkedSpans[index].top > top) { top = linkedSpans[index].top; } //1 is flagMergeDistance, when a walkable flag is favored before an unwalkable one if (AstarMath.Abs ((int)top - (int)linkedSpans[index].top) <= voxelWalkableClimb) { area = AstarMath.Max (area,linkedSpans[index].area); } int next = linkedSpans[index].next; if (prev != -1) { linkedSpans[prev].next = next; if (removedStackCount == removedStack.Length) { int[] st2 = new int[removedStackCount*4]; System.Buffer.BlockCopy(removedStack,0,st2,0,removedStackCount*sizeof(int)); removedStack = st2; } removedStack[removedStackCount] = index; removedStackCount++; index = next; } else if (next != -1) { linkedSpans[oindex] = linkedSpans[next]; if (removedStackCount == removedStack.Length) { int[] st2 = new int[removedStackCount*4]; System.Buffer.BlockCopy(removedStack,0,st2,0,removedStackCount*sizeof(int)); removedStack = st2; } removedStack[removedStackCount] = next; removedStackCount++; index = linkedSpans[oindex].next; } else { linkedSpans[oindex] = new LinkedVoxelSpan(bottom,top,area); return; } } } if (linkedSpanCount >= linkedSpans.Length) { LinkedVoxelSpan[] tmp = linkedSpans; int count = linkedSpanCount; int popped = removedStackCount; linkedSpans = new LinkedVoxelSpan[linkedSpans.Length*2]; ResetLinkedVoxelSpans(); linkedSpanCount = count; removedStackCount = popped; for (int i=0;i<linkedSpanCount;i++) { linkedSpans[i] = tmp[i]; } Debug.Log ("Layer estimate too low, doubling size of buffer.\nThis message is harmless."); } int nextIndex; if (removedStackCount > 0) { removedStackCount--; nextIndex = removedStack[removedStackCount]; } else { nextIndex = linkedSpanCount; linkedSpanCount++; } if (prev != -1) { //span.next = prev.next; //prev.next = span; linkedSpans[nextIndex] = new LinkedVoxelSpan(bottom,top,area,linkedSpans[prev].next); linkedSpans[prev].next = nextIndex; } else { //span.next = firstSpan; //firstSpan = span; linkedSpans[nextIndex] = linkedSpans[oindex]; linkedSpans[oindex] = new LinkedVoxelSpan(bottom,top,area,nextIndex); } #endif }
public void AddLinkedSpan(int index, uint bottom, uint top, int area, int voxelWalkableClimb) { #if !ASTAR_RECAST_ARRAY_BASED_LINKED_LIST cells[index].AddSpan(bottom, top, area, voxelWalkableClimb); #else /* Check if the span is valid, otherwise we can replace it with a new (valid) span */ if (linkedSpans[index].bottom == InvalidSpanValue) { linkedSpans[index] = new LinkedVoxelSpan(bottom, top, area); return; } int prev = -1; int oindex = index; while (index != -1) { if (linkedSpans[index].bottom > top) { break; } else if (linkedSpans[index].top < bottom) { prev = index; index = linkedSpans[index].next; } else { if (linkedSpans[index].bottom < bottom) { bottom = linkedSpans[index].bottom; } if (linkedSpans[index].top > top) { top = linkedSpans[index].top; } //1 is flagMergeDistance, when a walkable flag is favored before an unwalkable one if (AstarMath.Abs((int)top - (int)linkedSpans[index].top) <= voxelWalkableClimb) { area = AstarMath.Max(area, linkedSpans[index].area); } int next = linkedSpans[index].next; if (prev != -1) { linkedSpans[prev].next = next; if (removedStackCount == removedStack.Length) { int[] st2 = new int[removedStackCount * 4]; System.Buffer.BlockCopy(removedStack, 0, st2, 0, removedStackCount * sizeof(int)); removedStack = st2; } removedStack[removedStackCount] = index; removedStackCount++; index = next; } else if (next != -1) { linkedSpans[oindex] = linkedSpans[next]; if (removedStackCount == removedStack.Length) { int[] st2 = new int[removedStackCount * 4]; System.Buffer.BlockCopy(removedStack, 0, st2, 0, removedStackCount * sizeof(int)); removedStack = st2; } removedStack[removedStackCount] = next; removedStackCount++; index = linkedSpans[oindex].next; } else { linkedSpans[oindex] = new LinkedVoxelSpan(bottom, top, area); return; } } } if (linkedSpanCount >= linkedSpans.Length) { LinkedVoxelSpan[] tmp = linkedSpans; int count = linkedSpanCount; int popped = removedStackCount; linkedSpans = new LinkedVoxelSpan[linkedSpans.Length * 2]; ResetLinkedVoxelSpans(); linkedSpanCount = count; removedStackCount = popped; for (int i = 0; i < linkedSpanCount; i++) { linkedSpans[i] = tmp[i]; } Debug.Log("Layer estimate too low, doubling size of buffer.\nThis message is harmless."); } int nextIndex; if (removedStackCount > 0) { removedStackCount--; nextIndex = removedStack[removedStackCount]; } else { nextIndex = linkedSpanCount; linkedSpanCount++; } if (prev != -1) { //span.next = prev.next; //prev.next = span; linkedSpans[nextIndex] = new LinkedVoxelSpan(bottom, top, area, linkedSpans[prev].next); linkedSpans[prev].next = nextIndex; } else { //span.next = firstSpan; //firstSpan = span; linkedSpans[nextIndex] = linkedSpans[oindex]; linkedSpans[oindex] = new LinkedVoxelSpan(bottom, top, area, nextIndex); } #endif }
private void ResetLinkedVoxelSpans() { int num = this.linkedSpans.Length; this.linkedSpanCount = this.width * this.depth; LinkedVoxelSpan linkedVoxelSpan = new LinkedVoxelSpan(4294967295u, 4294967295u, -1, -1); for (int i = 0; i < num; i++) { this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; i++; this.linkedSpans[i] = linkedVoxelSpan; } this.removedStackCount = 0; }