static void GrowMemory(ref WorldAllocator storage, int newElementCapacity) { if (storage.elementAllocationCapacity < 0) { throw new InvalidOperationException(); } long extraBytes = UnsafeUtility.SizeOf <RLEElement>() * (newElementCapacity - storage.elementAllocationCapacity); long newBytes = UnsafeUtility.SizeOf <RLEColumn>() * (long)storage.columnCount; newBytes += UnsafeUtility.SizeOf <RLEElement>() * (long)newElementCapacity; void *newPointer = UnsafeUtility.Malloc(newBytes, UnsafeUtility.AlignOf <RLEColumn>(), Allocator.Persistent); if (storage.pointer == null) { UnsafeUtility.MemClear(newPointer, newBytes); } else { UnsafeUtility.MemCpy(newPointer, storage.pointer, newBytes - extraBytes); UnsafeUtility.MemClear((byte *)newPointer + newBytes - extraBytes, extraBytes); UnsafeUtility.Free(storage.pointer, Allocator.Persistent); } storage.pointer = newPointer; storage.elementAllocationCapacity = newElementCapacity; storage.elementsStart = storage.GetColumnPointer(storage.columnCount); }
public unsafe World(int3 dimensions, int lod, void *data) : this() { this.lod = lod; this.dimensions = dimensions; indexingMulX = dimensions.z >> lod; dimensionMaskXZ = dimensions.xz - 1; Storage = WorldAllocator.Allocate(ColumnCount, data); }
public static WorldAllocator Allocate(int columnCount) { WorldAllocator storage = new WorldAllocator(); storage.columnCount = columnCount; storage.allocationLock = new System.Threading.SpinLock(false); GrowMemory(ref storage, columnCount * 4); return(storage); }
public static WorldAllocator Allocate(int columnCount, void *data) { WorldAllocator storage = new WorldAllocator(); storage.columnCount = columnCount; storage.allocationLock = new System.Threading.SpinLock(false); storage.pointer = data; storage.elementsStart = storage.GetColumnPointer(storage.columnCount); storage.elementAllocationCapacity = -1; return(storage); }
// downsample a grid of columns into one column public RLEColumn DownSampleColumn(int xStart, int zStart, RLEElement[] buffer, int extraLods, ref WorldBuilder.RLEColumnBuilder columnBuilder, ref int totalVoxels, ref WorldAllocator newStorage) { // lod 0 = 0, 1 // lod 1 = 0, 2 int stepSize = 1 << lod; int steps = 1 << extraLods; int nextVoxelCountY = (dimensions.y >> (lod + extraLods)) - 1; columnBuilder.Clear(); for (int ix = 0; ix < steps; ix++) { int x = xStart + ix * stepSize; for (int iz = 0; iz < steps; iz++) { int z = zStart + iz * stepSize; DownSamplePartial(x, z, extraLods, ref columnBuilder); } } return(columnBuilder.ToFinalColumn(1 << (lod + extraLods), (short)(nextVoxelCountY), buffer, ref totalVoxels, ref newStorage)); }
public RLEElement *ToPointer(ref WorldAllocator storage) { return(storage.GetElementPointer(this)); }
public RLEElement GetIndex(ref WorldAllocator storage, int idx) { return(ElementGuardStart(ref storage)[idx + 1]); }
public RLEColumn(RLEElement[] buffer, int runCount, int solidCount, int voxelScale, ref WorldAllocator allocator) { this = default; if (runCount <= 0) { throw new ArgumentOutOfRangeException(); } this.runCount = (ushort)runCount; int allocationElementCount = runCount + solidCount + 2; storagePointer = allocator.AllocateElements(allocationElementCount); RLEElement *startPointer = ElementGuardStart(ref allocator); // initialize element guards startPointer[0] = new RLEElement(0, 0); for (int i = 0; i < runCount; i++) { startPointer[i + 1] = buffer[i]; } startPointer[runCount + 1] = new RLEElement(0, 0); int worldMin = int.MaxValue; int worldMax = int.MinValue; int elementBoundsMin = 0; int elementBoundsMax = 0; for (int i = runCount - 1; i >= 0; i--) { RLEElement element = buffer[i]; elementBoundsMin = elementBoundsMax; elementBoundsMax = elementBoundsMin + element.Length; if (element.IsAir) { continue; } worldMin = Mathf.Min(worldMin, elementBoundsMin); worldMax = Mathf.Max(worldMax, elementBoundsMax); } if (worldMin == int.MaxValue) { throw new InvalidOperationException("only air elements in the RLE"); } this.worldMin = (ushort)(worldMin * voxelScale); this.worldMax = (ushort)(worldMax * voxelScale); }
public ColorARGB32 *ColorPointer(ref WorldAllocator storage) { return((ColorARGB32 *)storagePointer.ToPointer(ref storage) + runCount + 2); }
public RLEElement *ElementGuardEnd(ref WorldAllocator storage) { return(storagePointer.ToPointer(ref storage) + runCount + 1); }
public RLEElement *ElementGuardStart(ref WorldAllocator storage) { return(storagePointer.ToPointer(ref storage)); }