//public System.Object lockObject; public void AddSpan (uint bottom, uint top, int area, int voxelWalkableClimb) { VoxelSpan span = new VoxelSpan (bottom,top,area); if (firstSpan == null) { firstSpan = span; return; } VoxelSpan prev = null; VoxelSpan cSpan = firstSpan; while (cSpan != null) { if (cSpan.bottom > span.top) { break; } else if (cSpan.top < span.bottom) { prev = cSpan; cSpan = cSpan.next; } else { if (cSpan.bottom < bottom) { span.bottom = cSpan.bottom; } if (cSpan.top > top) { span.top = cSpan.top; } //1 is flagMergeDistance, when a walkable flag is favored before an unwalkable one if (AstarMath.Abs ((int)span.top - (int)cSpan.top) <= voxelWalkableClimb) { span.area = AstarMath.Max (span.area,cSpan.area); } VoxelSpan next = cSpan.next; if (prev != null) { prev.next = next; } else { firstSpan = next; } cSpan = next; } } if (prev != null) { span.next = prev.next; prev.next = span; } else { span.next = firstSpan; firstSpan = span; } }
public void BuildCompactField() { AstarProfiler.StartProfile("Build Compact Voxel Field"); //Build compact representation int spanCount = voxelArea.GetSpanCount(); voxelArea.compactSpanCount = spanCount; if (voxelArea.compactSpans == null || voxelArea.compactSpans.Length < spanCount) { voxelArea.compactSpans = new CompactVoxelSpan[spanCount]; voxelArea.areaTypes = new int[spanCount]; } uint idx = 0; int w = voxelArea.width; int d = voxelArea.depth; int wd = w * d; if (this.voxelWalkableHeight >= 0xFFFF) { Debug.LogWarning("Too high walkable height to guarantee correctness. Increase voxel height or lower walkable height."); } #if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST LinkedVoxelSpan[] spans = voxelArea.linkedSpans; #endif //Parallel.For (0, voxelArea.depth, delegate (int pz) { for (int z = 0, pz = 0; z < wd; z += w, pz++) { for (int x = 0; x < w; x++) { #if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST int spanIndex = x + z; if (spans[spanIndex].bottom == VoxelArea.InvalidSpanValue) { voxelArea.compactCells[x + z] = new CompactVoxelCell(0, 0); continue; } uint index = idx; uint count = 0; //Vector3 p = new Vector3(x,0,pz)*cellSize+voxelOffset; while (spanIndex != -1) { if (spans[spanIndex].area != UnwalkableArea) { int bottom = (int)spans[spanIndex].top; int next = spans[spanIndex].next; int top = next != -1 ? (int)spans[next].bottom : VoxelArea.MaxHeightInt; voxelArea.compactSpans[idx] = new CompactVoxelSpan((ushort)(bottom > 0xFFFF ? 0xFFFF : bottom), (uint)(top - bottom > 0xFFFF ? 0xFFFF : top - bottom)); voxelArea.areaTypes[idx] = spans[spanIndex].area; idx++; count++; } spanIndex = spans[spanIndex].next; } voxelArea.compactCells[x + z] = new CompactVoxelCell(index, count); #else VoxelSpan s = voxelArea.cells[x + z].firstSpan; if (s == null) { voxelArea.compactCells[x + z] = new CompactVoxelCell(0, 0); continue; } uint index = idx; uint count = 0; //Vector3 p = new Vector3(x,0,pz)*cellSize+voxelOffset; while (s != null) { if (s.area != UnwalkableArea) { int bottom = (int)s.top; int top = s.next != null ? (int)s.next.bottom : VoxelArea.MaxHeightInt; voxelArea.compactSpans[idx] = new CompactVoxelSpan((ushort)Mathf.Clamp(bottom, 0, 0xffff), (uint)Mathf.Clamp(top - bottom, 0, 0xffff)); voxelArea.areaTypes[idx] = s.area; idx++; count++; } s = s.next; } voxelArea.compactCells[x + z] = new CompactVoxelCell(index, count); #endif } } AstarProfiler.EndProfile("Build Compact Voxel Field"); }