< Summary

Information
Class: GridForge.Grids.Storage.SparseVoxelGridStorage
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Grids/Storage/SparseVoxelGridStorage.cs
Line coverage
100%
Covered lines: 302
Uncovered lines: 0
Coverable lines: 302
Total lines: 628
Line coverage: 100%
Branch coverage
100%
Covered branches: 156
Total branches: 156
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/GridForge/GridForge/src/GridForge/Grids/Storage/SparseVoxelGridStorage.cs

#LineLine coverage
 1//=======================================================================
 2// SparseVoxelGridStorage.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Buffers;
 10using System.Collections.Generic;
 11using System.Runtime.CompilerServices;
 12using FixedMathSharp;
 13using GridForge.Spatial;
 14using SwiftCollections;
 15using SwiftCollections.Query;
 16
 17namespace GridForge.Grids.Storage;
 18
 19internal sealed class SparseVoxelGridStorage : IVoxelGridStorage
 20{
 21    public GridStorageKind Kind
 22    {
 23        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 26824        get => GridStorageKind.Sparse;
 25    }
 26
 27    public int ConfiguredVoxelCount { get; private set; }
 28
 29    public SwiftSparseMap<ScanCell>? ScanCells { get; private set; }
 30
 31    private SwiftSparseMap<SparseVoxelBlock>? _blocks;
 32    private Voxel[]? _voxels;
 33    private int _scanCellSize;
 34    private int _scanWidth;
 35    private int _scanHeight;
 36    private int _scanLength;
 37    private int _scanLayerSize;
 38    private SwiftFixedBVH<Voxel>? _closestVoxelTree;
 39    private int[]? _closestQueryStack;
 40
 41    public void Initialize(VoxelGrid grid, VoxelIndex[] configuredVoxels)
 42    {
 10343        _scanCellSize = grid.ScanCellSize;
 10344        _scanWidth = grid.ScanWidth;
 10345        _scanHeight = grid.ScanHeight;
 10346        _scanLength = grid.ScanLength;
 10347        _scanLayerSize = grid.ScanWidth * grid.ScanHeight;
 48
 10349        ConfiguredVoxelCount = configuredVoxels.Length;
 10350        if (ConfiguredVoxelCount == 0)
 3151            return;
 52
 7253        SwiftDictionary<int, int> blockCapacities = Pools.SparseVoxelBlockCapacityPool.Rent();
 54        try
 55        {
 7256            CountConfiguredVoxelsPerBlock(grid, configuredVoxels, blockCapacities);
 7257            ScanCells = Pools.ScanCellMapPool.Rent();
 7258            _blocks = Pools.SparseVoxelBlockMapPool.Rent();
 7259            _voxels = ArrayPool<Voxel>.Shared.Rent(ConfiguredVoxelCount);
 7260            _closestVoxelTree = new SwiftFixedBVH<Voxel>(GetClosestVoxelTreeCapacity(ConfiguredVoxelCount));
 61
 35262            for (int i = 0; i < configuredVoxels.Length; i++)
 63            {
 10464                VoxelIndex index = configuredVoxels[i];
 10465                int cellKey = grid.GetScanCellKey(index);
 66
 10467                if (!_blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 68                {
 8169                    block = Pools.SparseVoxelBlockPool.Rent();
 8170                    block.Initialize(grid, cellKey, blockCapacities[cellKey]);
 8171                    _blocks.Add(cellKey, block);
 8172                    ScanCells.Add(cellKey, block.ScanCell!);
 73                }
 74
 10475                Voxel voxel = block.AddPreparedVoxel(grid, index);
 10476                _voxels[i] = voxel;
 10477                AddVoxelToClosestTree(voxel, ConfiguredVoxelCount);
 78            }
 7279        }
 80        finally
 81        {
 7282            Pools.SparseVoxelBlockCapacityPool.Release(blockCapacities);
 7283        }
 7284    }
 85
 86    public void Reset(VoxelGrid grid)
 87    {
 10488        ReleaseBlocks(grid);
 10489        ReleaseScanCells();
 10490        ReleaseVoxelCache();
 10491        ReleaseClosestVoxelTree();
 92
 10493        ConfiguredVoxelCount = 0;
 10494    }
 95
 96    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 97    public bool TryGetVoxel(int x, int y, int z, out Voxel? result)
 98    {
 24499        result = null;
 100
 244101        if (_blocks == null)
 42102            return false;
 103
 202104        VoxelIndex index = new(x, y, z);
 202105        int cellKey = GetScanCellKey(x, y, z);
 202106        return cellKey >= 0
 202107            && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block)
 202108            && block.TryGetVoxel(index, out result);
 109    }
 110
 111    public bool TryGetClosestVoxel(
 112        VoxelGrid grid,
 113        VoxelIndex closestIndex,
 114        Vector3d position,
 115        out Voxel? result,
 116        out Fixed64 distanceSquared)
 117    {
 12118        result = null;
 12119        distanceSquared = Fixed64.MaxValue;
 120
 12121        if (_voxels == null || ConfiguredVoxelCount == 0)
 1122            return false;
 123
 11124        if (TryGetVoxel(closestIndex.x, closestIndex.y, closestIndex.z, out result))
 125        {
 2126            distanceSquared = (result!.WorldPosition - position).MagnitudeSquared;
 2127            return true;
 128        }
 129
 9130        return TryGetClosestVoxelFromTree(position, out result, out distanceSquared);
 131    }
 132
 133    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 134    public bool TryGetScanCell(int key, out ScanCell? result)
 135    {
 17136        result = null;
 17137        return ScanCells?.TryGetValue(key, out result) == true;
 138    }
 139
 140    public IEnumerable<Voxel> EnumerateVoxels()
 141    {
 9142        if (_voxels == null)
 5143            yield break;
 144
 102145        for (int i = 0; i < ConfiguredVoxelCount; i++)
 47146            yield return _voxels[i];
 4147    }
 148
 149    public void VisitVoxels<TVisitor>(ref TVisitor visitor)
 150        where TVisitor : struct, IVoxelStorageVisitor
 151    {
 39152        if (_voxels == null)
 1153            return;
 154
 360155        for (int i = 0; i < ConfiguredVoxelCount; i++)
 156        {
 143157            if (!visitor.Visit(_voxels[i]))
 1158                return;
 159        }
 37160    }
 161
 162    public bool TryAddVoxel(VoxelGrid grid, VoxelIndex index, out Voxel? voxel)
 163    {
 39164        voxel = null;
 39165        int cellKey = grid.GetScanCellKey(index);
 39166        if (cellKey < 0)
 1167            return false;
 168
 38169        EnsureStorageMaps();
 170
 38171        if (!_blocks!.TryGetValue(cellKey, out SparseVoxelBlock? block))
 172        {
 8173            block = Pools.SparseVoxelBlockPool.Rent();
 8174            block.Initialize(grid, cellKey, capacity: 1);
 8175            _blocks.Add(cellKey, block);
 8176            ScanCells!.Add(cellKey, block.ScanCell!);
 177        }
 178
 38179        if (!block!.TryAddVoxel(grid, index, out voxel))
 2180            return false;
 181
 36182        AddVoxelToCache(voxel!);
 36183        AddVoxelToClosestTree(voxel!, ConfiguredVoxelCount + 1);
 36184        ConfiguredVoxelCount++;
 36185        return true;
 186    }
 187
 188    public bool TryRemoveVoxel(VoxelGrid grid, VoxelIndex index, out Voxel? voxel)
 189    {
 19190        voxel = null;
 19191        if (_blocks == null)
 1192            return false;
 193
 18194        int cellKey = grid.GetScanCellKey(index);
 18195        if (cellKey < 0)
 1196            return false;
 197
 17198        if (!_blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 1199            return false;
 200
 16201        if (!block!.TryRemoveVoxel(grid, index, out voxel))
 2202            return false;
 203
 14204        RemoveVoxelFromCache(index);
 14205        RemoveVoxelFromClosestTree(voxel!);
 14206        ConfiguredVoxelCount--;
 207
 14208        if (block.Count == 0)
 7209            ReleaseBlock(grid, cellKey, block);
 210
 14211        ReleaseEmptyStorageMapsIfNeeded();
 14212        return true;
 213    }
 214
 215    public void AddVoxelsInIndexRange(
 216        VoxelIndex min,
 217        VoxelIndex max,
 218        SwiftList<Voxel> results,
 219        SwiftHashSet<Voxel> redundancy)
 220    {
 46221        if (_blocks == null || _scanCellSize <= 0)
 4222            return;
 223
 42224        int scanXMin = min.x / _scanCellSize;
 42225        int scanYMin = min.y / _scanCellSize;
 42226        int scanZMin = min.z / _scanCellSize;
 42227        int scanXMax = max.x / _scanCellSize;
 42228        int scanYMax = max.y / _scanCellSize;
 42229        int scanZMax = max.z / _scanCellSize;
 230
 174231        for (long scanX = scanXMin; scanX <= scanXMax; scanX++)
 232        {
 180233            for (long scanY = scanYMin; scanY <= scanYMax; scanY++)
 234            {
 180235                for (long scanZ = scanZMin; scanZ <= scanZMax; scanZ++)
 236                {
 45237                    int cellKey = GetScanCellKeyFromScanCoordinates(
 45238                        (int)scanX,
 45239                        (int)scanY,
 45240                        (int)scanZ);
 45241                    if (cellKey >= 0 && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 41242                        block.AddVoxelsInIndexRange(min, max, results, redundancy);
 243                }
 244            }
 245        }
 42246    }
 247
 248    public void AddScanCellsInRange(
 249        VoxelGrid _,
 250        int xMin,
 251        int yMin,
 252        int zMin,
 253        int xMax,
 254        int yMax,
 255        int zMax,
 256        SwiftList<ScanCell> results,
 257        SwiftHashSet<ScanCell> redundancy)
 258    {
 30259        if (_blocks == null)
 1260            return;
 261
 130262        for (long x = xMin; x <= xMax; x++)
 263        {
 144264            for (long y = yMin; y <= yMax; y++)
 265            {
 172266                for (long z = zMin; z <= zMax; z++)
 267                {
 50268                    int cellKey = GetScanCellKeyFromScanCoordinates(
 50269                        (int)x,
 50270                        (int)y,
 50271                        (int)z);
 50272                    if (cellKey >= 0
 50273                        && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block)
 50274                        && redundancy.Add(block.ScanCell!))
 275                    {
 26276                        results.Add(block.ScanCell!);
 277                    }
 278                }
 279            }
 280        }
 29281    }
 282
 283    private static void CountConfiguredVoxelsPerBlock(
 284        VoxelGrid grid,
 285        VoxelIndex[] configuredVoxels,
 286        SwiftDictionary<int, int> result)
 287    {
 72288        result.EnsureCapacity(configuredVoxels.Length);
 352289        for (int i = 0; i < configuredVoxels.Length; i++)
 290        {
 104291            int key = grid.GetScanCellKey(configuredVoxels[i]);
 104292            if (result.TryGetValue(key, out int count))
 23293                result[key] = count + 1;
 294            else
 81295                result.Add(key, 1);
 296        }
 72297    }
 298
 299    private void EnsureStorageMaps()
 300    {
 38301        ScanCells ??= Pools.ScanCellMapPool.Rent();
 38302        _blocks ??= Pools.SparseVoxelBlockMapPool.Rent();
 38303    }
 304
 305    private void AddVoxelToCache(Voxel voxel)
 306    {
 36307        EnsureVoxelCacheCapacity(ConfiguredVoxelCount + 1);
 36308        TryFindVoxelCacheIndex(voxel.Index, out int insertIndex);
 309
 36310        if (insertIndex < ConfiguredVoxelCount)
 11311            Array.Copy(_voxels!, insertIndex, _voxels!, insertIndex + 1, ConfiguredVoxelCount - insertIndex);
 312
 36313        _voxels![insertIndex] = voxel;
 36314    }
 315
 316    private void AddVoxelToClosestTree(Voxel voxel, int targetVoxelCount)
 317    {
 140318        _closestVoxelTree ??= new SwiftFixedBVH<Voxel>(GetClosestVoxelTreeCapacity(targetVoxelCount));
 140319        _closestVoxelTree.EnsureCapacity(GetClosestVoxelTreeCapacity(targetVoxelCount));
 140320        _closestVoxelTree.Insert(voxel, CreateVoxelPointBounds(voxel));
 140321        EnsureClosestQueryStackCapacity(_closestVoxelTree.NodePool.Length);
 140322    }
 323
 324    private void RemoveVoxelFromClosestTree(Voxel voxel)
 325    {
 14326        _closestVoxelTree!.Remove(voxel);
 14327        if (_closestVoxelTree.Count == 0)
 7328            ReleaseClosestVoxelTree();
 14329    }
 330
 331    private void RemoveVoxelFromCache(VoxelIndex index)
 332    {
 14333        Voxel[] voxels = _voxels!;
 14334        TryFindVoxelCacheIndex(index, out int voxelArrayIndex);
 335
 14336        int moveCount = ConfiguredVoxelCount - voxelArrayIndex - 1;
 14337        if (moveCount > 0)
 2338            Array.Copy(voxels, voxelArrayIndex + 1, voxels, voxelArrayIndex, moveCount);
 339
 14340        voxels[ConfiguredVoxelCount - 1] = null!;
 14341        if (ConfiguredVoxelCount == 1)
 342        {
 7343            ArrayPool<Voxel>.Shared.Return(voxels, clearArray: true);
 7344            _voxels = null;
 345        }
 14346    }
 347
 348    private void EnsureVoxelCacheCapacity(int minCapacity)
 349    {
 36350        if (_voxels != null && _voxels.Length >= minCapacity)
 27351            return;
 352
 9353        int capacity = _voxels == null
 9354            ? minCapacity
 9355            : Math.Max(minCapacity, _voxels.Length << 1);
 9356        Voxel[] replacement = ArrayPool<Voxel>.Shared.Rent(capacity);
 357
 9358        if (_voxels != null)
 359        {
 1360            Array.Copy(_voxels, replacement, ConfiguredVoxelCount);
 1361            ArrayPool<Voxel>.Shared.Return(_voxels, clearArray: true);
 362        }
 363
 9364        _voxels = replacement;
 9365    }
 366
 367    private bool TryFindVoxelCacheIndex(VoxelIndex index, out int voxelArrayIndex)
 368    {
 50369        voxelArrayIndex = 0;
 50370        Voxel[] voxels = _voxels!;
 371
 50372        int min = 0;
 50373        int max = ConfiguredVoxelCount - 1;
 152374        while (min <= max)
 375        {
 105376            int mid = min + ((max - min) >> 1);
 105377            int compare = voxels[mid].Index.CompareTo(index);
 105378            if (compare == 0)
 379            {
 3380                voxelArrayIndex = mid;
 3381                return true;
 382            }
 383
 102384            if (compare < 0)
 87385                min = mid + 1;
 386            else
 15387                max = mid - 1;
 388        }
 389
 47390        voxelArrayIndex = min;
 47391        return false;
 392    }
 393
 394    private bool TryGetClosestVoxelFromTree(
 395        Vector3d position,
 396        out Voxel? result,
 397        out Fixed64 distanceSquared)
 398    {
 9399        result = null;
 9400        distanceSquared = Fixed64.MaxValue;
 401
 9402        int rootNodeIndex = _closestVoxelTree!.RootNodeIndex;
 403
 9404        SwiftBVHNode<Voxel, FixedBoundVolume>[] nodes = _closestVoxelTree.NodePool;
 9405        EnsureClosestQueryStackCapacity(nodes.Length);
 406
 9407        int[] stack = _closestQueryStack!;
 9408        int stackCount = 0;
 9409        stack[stackCount++] = rootNodeIndex;
 410
 30411        while (stackCount > 0)
 412        {
 21413            int nodeIndex = stack[--stackCount];
 21414            ref SwiftBVHNode<Voxel, FixedBoundVolume> node = ref nodes[nodeIndex];
 21415            Fixed64 nodeDistanceSquared = GetDistanceSquaredToBounds(position, node.Bounds);
 21416            if (nodeDistanceSquared > distanceSquared)
 417                continue;
 418
 16419            if (node.IsLeaf)
 420            {
 10421                Voxel candidate = node.Value;
 10422                Fixed64 candidateDistanceSquared = (candidate.WorldPosition - position).MagnitudeSquared;
 10423                if (IsBetterClosestVoxel(candidate, candidateDistanceSquared, result, distanceSquared))
 424                {
 9425                    result = candidate;
 9426                    distanceSquared = candidateDistanceSquared;
 427                }
 428
 9429                continue;
 430            }
 431
 6432            PushClosestChildrenFirst(position, nodes, node, stack, ref stackCount, distanceSquared);
 433        }
 434
 9435        return true;
 436    }
 437
 438    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 439    private static bool IsBetterClosestVoxel(
 440        Voxel candidate,
 441        Fixed64 candidateDistanceSquared,
 442        Voxel? current,
 443        Fixed64 currentDistanceSquared)
 444    {
 13445        if (current == null)
 10446            return true;
 447
 3448        if (candidateDistanceSquared != currentDistanceSquared)
 1449            return candidateDistanceSquared < currentDistanceSquared;
 450
 2451        return candidate.Index.CompareTo(current.Index) < 0;
 452    }
 453
 454    private static void PushClosestChildrenFirst(
 455        Vector3d position,
 456        SwiftBVHNode<Voxel, FixedBoundVolume>[] nodes,
 457        SwiftBVHNode<Voxel, FixedBoundVolume> node,
 458        int[] stack,
 459        ref int stackCount,
 460        Fixed64 bestDistanceSquared)
 461    {
 6462        int leftIndex = node.LeftChildIndex;
 6463        int rightIndex = node.RightChildIndex;
 464
 6465        Fixed64 leftDistanceSquared = GetDistanceSquaredToBounds(position, nodes[leftIndex].Bounds);
 6466        Fixed64 rightDistanceSquared = GetDistanceSquaredToBounds(position, nodes[rightIndex].Bounds);
 467
 6468        if (leftDistanceSquared <= rightDistanceSquared)
 469        {
 5470            PushChildIfWithinBest(rightIndex, rightDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 5471            PushChildIfWithinBest(leftIndex, leftDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 472        }
 473        else
 474        {
 1475            PushChildIfWithinBest(leftIndex, leftDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 1476            PushChildIfWithinBest(rightIndex, rightDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 477        }
 1478    }
 479
 480    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 481    private static void PushChildIfWithinBest(
 482        int childIndex,
 483        Fixed64 childDistanceSquared,
 484        int[] stack,
 485        ref int stackCount,
 486        Fixed64 bestDistanceSquared)
 487    {
 14488        if (childDistanceSquared <= bestDistanceSquared)
 13489            stack[stackCount++] = childIndex;
 14490    }
 491
 492    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 493    private static FixedBoundVolume CreateVoxelPointBounds(Voxel voxel) =>
 140494        new(voxel.WorldPosition, voxel.WorldPosition);
 495
 496    private static Fixed64 GetDistanceSquaredToBounds(Vector3d position, FixedBoundVolume bounds)
 497    {
 33498        Fixed64 x = GetAxisDistance(position.X, bounds.Min.X, bounds.Max.X);
 33499        Fixed64 y = GetAxisDistance(position.Y, bounds.Min.Y, bounds.Max.Y);
 33500        Fixed64 z = GetAxisDistance(position.Z, bounds.Min.Z, bounds.Max.Z);
 33501        return x * x + y * y + z * z;
 502    }
 503
 504    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 505    private static Fixed64 GetAxisDistance(Fixed64 value, Fixed64 min, Fixed64 max)
 506    {
 99507        if (value < min)
 21508            return min - value;
 509
 78510        return value > max ? value - max : Fixed64.Zero;
 511    }
 512
 513    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 514    private static int GetClosestVoxelTreeCapacity(int voxelCapacity)
 515    {
 223516        if (voxelCapacity <= 1)
 115517            return 1;
 518
 108519        return voxelCapacity > int.MaxValue / 2
 108520            ? int.MaxValue
 108521            : voxelCapacity << 1;
 522    }
 523
 524    private void EnsureClosestQueryStackCapacity(int minCapacity)
 525    {
 149526        if (_closestQueryStack != null && _closestQueryStack.Length >= minCapacity)
 67527            return;
 528
 82529        int[] replacement = ArrayPool<int>.Shared.Rent(minCapacity);
 82530        if (_closestQueryStack != null)
 2531            ArrayPool<int>.Shared.Return(_closestQueryStack);
 532
 82533        _closestQueryStack = replacement;
 82534    }
 535
 536    private void ReleaseBlock(VoxelGrid grid, int cellKey, SparseVoxelBlock block)
 537    {
 7538        ScanCells!.Remove(cellKey);
 7539        _blocks!.Remove(cellKey);
 7540        block.Reset(grid);
 7541        Pools.SparseVoxelBlockPool.Release(block);
 7542    }
 543
 544    private void ReleaseEmptyStorageMapsIfNeeded()
 545    {
 14546        if (ConfiguredVoxelCount != 0)
 7547            return;
 548
 7549        Pools.SparseVoxelBlockMapPool.Release(_blocks!);
 7550        _blocks = null;
 551
 7552        Pools.ScanCellMapPool.Release(ScanCells!);
 7553        ScanCells = null;
 7554    }
 555
 556    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 557    private int GetScanCellKey(int x, int y, int z)
 558    {
 202559        int scanX = x / _scanCellSize;
 202560        int scanY = y / _scanCellSize;
 202561        int scanZ = z / _scanCellSize;
 562
 202563        return GetScanCellKeyFromScanCoordinates(scanX, scanY, scanZ);
 564    }
 565
 566    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 567    private int GetScanCellKeyFromScanCoordinates(int scanX, int scanY, int scanZ)
 568    {
 297569        if ((uint)scanX >= (uint)_scanWidth
 297570            || (uint)scanY >= (uint)_scanHeight
 297571            || (uint)scanZ >= (uint)_scanLength)
 572        {
 7573            return -1;
 574        }
 575
 290576        return scanX + scanY * _scanWidth + scanZ * _scanLayerSize;
 577    }
 578
 579    private void ReleaseBlocks(VoxelGrid grid)
 580    {
 104581        if (_blocks == null)
 31582            return;
 583
 73584        Span<SparseVoxelBlock> blocks = _blocks.Values;
 310585        for (int i = 0; i < blocks.Length; i++)
 586        {
 82587            SparseVoxelBlock block = blocks[i];
 82588            block.Reset(grid);
 82589            Pools.SparseVoxelBlockPool.Release(block);
 590        }
 591
 73592        Pools.SparseVoxelBlockMapPool.Release(_blocks);
 73593        _blocks = null;
 73594    }
 595
 596    private void ReleaseScanCells()
 597    {
 104598        if (ScanCells == null)
 31599            return;
 600
 73601        Pools.ScanCellMapPool.Release(ScanCells);
 73602        ScanCells = null;
 73603    }
 604
 605    private void ReleaseVoxelCache()
 606    {
 104607        if (_voxels != null)
 73608            ArrayPool<Voxel>.Shared.Return(_voxels, clearArray: true);
 609
 104610        _voxels = null;
 104611        _scanCellSize = 0;
 104612        _scanWidth = 0;
 104613        _scanHeight = 0;
 104614        _scanLength = 0;
 104615        _scanLayerSize = 0;
 104616    }
 617
 618    private void ReleaseClosestVoxelTree()
 619    {
 111620        _closestVoxelTree?.Clear();
 111621        _closestVoxelTree = null;
 622
 111623        if (_closestQueryStack != null)
 80624            ArrayPool<int>.Shared.Return(_closestQueryStack);
 625
 111626        _closestQueryStack = null;
 111627    }
 628}

Methods/Properties

get_Kind()
Initialize(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex[])
Reset(GridForge.Grids.VoxelGrid)
TryGetVoxel(System.Int32,System.Int32,System.Int32,GridForge.Grids.Voxel&)
TryGetClosestVoxel(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex,FixedMathSharp.Vector3d,GridForge.Grids.Voxel&,FixedMathSharp.Fixed64&)
TryGetScanCell(System.Int32,GridForge.Grids.ScanCell&)
EnumerateVoxels()
VisitVoxels(TVisitor&)
TryAddVoxel(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex,GridForge.Grids.Voxel&)
TryRemoveVoxel(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex,GridForge.Grids.Voxel&)
AddVoxelsInIndexRange(GridForge.Spatial.VoxelIndex,GridForge.Spatial.VoxelIndex,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.Voxel>)
AddScanCellsInRange(GridForge.Grids.VoxelGrid,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,SwiftCollections.SwiftList`1<GridForge.Grids.ScanCell>,SwiftCollections.SwiftHashSet`1<GridForge.Grids.ScanCell>)
CountConfiguredVoxelsPerBlock(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelIndex[],SwiftCollections.SwiftDictionary`2<System.Int32,System.Int32>)
EnsureStorageMaps()
AddVoxelToCache(GridForge.Grids.Voxel)
AddVoxelToClosestTree(GridForge.Grids.Voxel,System.Int32)
RemoveVoxelFromClosestTree(GridForge.Grids.Voxel)
RemoveVoxelFromCache(GridForge.Spatial.VoxelIndex)
EnsureVoxelCacheCapacity(System.Int32)
TryFindVoxelCacheIndex(GridForge.Spatial.VoxelIndex,System.Int32&)
TryGetClosestVoxelFromTree(FixedMathSharp.Vector3d,GridForge.Grids.Voxel&,FixedMathSharp.Fixed64&)
IsBetterClosestVoxel(GridForge.Grids.Voxel,FixedMathSharp.Fixed64,GridForge.Grids.Voxel,FixedMathSharp.Fixed64)
PushClosestChildrenFirst(FixedMathSharp.Vector3d,SwiftCollections.Query.SwiftBVHNode`2<GridForge.Grids.Voxel,SwiftCollections.Query.FixedBoundVolume>[],SwiftCollections.Query.SwiftBVHNode`2<GridForge.Grids.Voxel,SwiftCollections.Query.FixedBoundVolume>,System.Int32[],System.Int32&,FixedMathSharp.Fixed64)
PushChildIfWithinBest(System.Int32,FixedMathSharp.Fixed64,System.Int32[],System.Int32&,FixedMathSharp.Fixed64)
CreateVoxelPointBounds(GridForge.Grids.Voxel)
GetDistanceSquaredToBounds(FixedMathSharp.Vector3d,SwiftCollections.Query.FixedBoundVolume)
GetAxisDistance(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetClosestVoxelTreeCapacity(System.Int32)
EnsureClosestQueryStackCapacity(System.Int32)
ReleaseBlock(GridForge.Grids.VoxelGrid,System.Int32,GridForge.Grids.Storage.SparseVoxelBlock)
ReleaseEmptyStorageMapsIfNeeded()
GetScanCellKey(System.Int32,System.Int32,System.Int32)
GetScanCellKeyFromScanCoordinates(System.Int32,System.Int32,System.Int32)
ReleaseBlocks(GridForge.Grids.VoxelGrid)
ReleaseScanCells()
ReleaseVoxelCache()
ReleaseClosestVoxelTree()