Exemple #1
0
    public unsafe World DownSample(int extraLods, out int voxelCount)
    {
        World subWorld    = new World(dimensions, lod + extraLods);
        World thisWorld   = this;
        int   step        = 1 << subWorld.lod;
        int   totalVoxels = 0;

        // parallelize downsampling on the X-axis
        System.Threading.Tasks.Parallel.For(0, dimensions.x / step, (int i) =>
        {
            int yVoxels = subWorld.dimensions.y >> subWorld.lod;
            RLEElement[] elementBuffer            = new RLEElement[yVoxels];
            WorldBuilder.RLEColumnBuilder builder = new WorldBuilder.RLEColumnBuilder();

            int x = i * step;
            for (int z = 0; z < subWorld.dimensions.z; z += step)
            {
                // downsample a {step, step} grid of columns into one
                RLEColumn downSampled = thisWorld.DownSampleColumn(x, z, elementBuffer, extraLods, ref builder, ref totalVoxels, ref subWorld.Storage);
                *subWorld.Storage.GetColumnPointer(subWorld.GetIndexKnownInBounds(int2(x, z))) = downSampled;
            }
        });

        voxelCount = totalVoxels;
        return(subWorld);
    }
Exemple #2
0
    /// <summary>
    /// Output a column of data into the columnbuilder; after doing this with all columns the builder will be resolved to a new, merged column
    /// </summary>
    unsafe void DownSamplePartial(int x, int z, int extraLods, ref WorldBuilder.RLEColumnBuilder columnBuilder)
    {
        RLEColumn column = *Storage.GetColumnPointer(GetIndexKnownInBounds(int2(x, z)));

        if (column.RunCount <= 0)
        {
            return;
        }

        int2         elementBounds = dimensions.y >> lod;
        int          nextLod       = lod + extraLods;
        ColorARGB32 *colorPointer  = column.ColorPointer(ref Storage);

        for (int run = 0; run < column.RunCount; run++)
        {
            RLEElement element = column.GetIndex(ref Storage, run);

            elementBounds = int2(elementBounds.x - element.Length, elementBounds.x);

            if (element.IsAir)
            {
                continue;
            }

            for (int i = 0; i < element.Length; i++)
            {
                int Y        = elementBounds.x + i;
                int colorIdx = element.ColorsIndex + element.Length - i - 1;
                columnBuilder.SetVoxel(Y >> nextLod, colorPointer[colorIdx]);
            }
        }
    }
Exemple #3
0
        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);
        }