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 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 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; // Enqueue 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 }
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; }