< 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)]
 33924        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    {
 12643        _scanCellSize = grid.ScanCellSize;
 12644        _scanWidth = grid.ScanWidth;
 12645        _scanHeight = grid.ScanHeight;
 12646        _scanLength = grid.ScanLength;
 12647        _scanLayerSize = grid.ScanWidth * grid.ScanHeight;
 48
 12649        ConfiguredVoxelCount = configuredVoxels.Length;
 12650        if (ConfiguredVoxelCount == 0)
 4351            return;
 52
 8353        SwiftDictionary<int, int> blockCapacities = Pools.SparseVoxelBlockCapacityPool.Rent();
 54        try
 55        {
 8356            CountConfiguredVoxelsPerBlock(grid, configuredVoxels, blockCapacities);
 8357            ScanCells = Pools.ScanCellMapPool.Rent();
 8358            _blocks = Pools.SparseVoxelBlockMapPool.Rent();
 8359            _voxels = ArrayPool<Voxel>.Shared.Rent(ConfiguredVoxelCount);
 8360            _closestVoxelTree = new SwiftFixedBVH<Voxel>(GetClosestVoxelTreeCapacity(ConfiguredVoxelCount));
 61
 44062            for (int i = 0; i < configuredVoxels.Length; i++)
 63            {
 13764                VoxelIndex index = configuredVoxels[i];
 13765                int cellKey = grid.GetScanCellKey(index);
 66
 13767                if (!_blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 68                {
 9269                    block = Pools.SparseVoxelBlockPool.Rent();
 9270                    block.Initialize(grid, cellKey, blockCapacities[cellKey]);
 9271                    _blocks.Add(cellKey, block);
 9272                    ScanCells.Add(cellKey, block.ScanCell!);
 73                }
 74
 13775                Voxel voxel = block.AddPreparedVoxel(grid, index);
 13776                _voxels[i] = voxel;
 13777                AddVoxelToClosestTree(voxel, ConfiguredVoxelCount);
 78            }
 8379        }
 80        finally
 81        {
 8382            Pools.SparseVoxelBlockCapacityPool.Release(blockCapacities);
 8383        }
 8384    }
 85
 86    public void Reset(VoxelGrid grid)
 87    {
 12788        ReleaseBlocks(grid);
 12789        ReleaseScanCells();
 12790        ReleaseVoxelCache();
 12791        ReleaseClosestVoxelTree();
 92
 12793        ConfiguredVoxelCount = 0;
 12794    }
 95
 96    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 97    public bool TryGetVoxel(int x, int y, int z, out Voxel? result)
 98    {
 33399        result = null;
 100
 333101        if (_blocks == null)
 51102            return false;
 103
 282104        VoxelIndex index = new(x, y, z);
 282105        int cellKey = GetScanCellKey(x, y, z);
 282106        return cellKey >= 0
 282107            && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block)
 282108            && 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    {
 42152        if (_voxels == null)
 1153            return;
 154
 376155        for (int i = 0; i < ConfiguredVoxelCount; i++)
 156        {
 148157            if (!visitor.Visit(_voxels[i]))
 1158                return;
 159        }
 40160    }
 161
 162    public bool TryAddVoxel(VoxelGrid grid, VoxelIndex index, out Voxel? voxel)
 163    {
 43164        voxel = null;
 43165        int cellKey = grid.GetScanCellKey(index);
 43166        if (cellKey < 0)
 1167            return false;
 168
 42169        EnsureStorageMaps();
 170
 42171        if (!_blocks!.TryGetValue(cellKey, out SparseVoxelBlock? block))
 172        {
 11173            block = Pools.SparseVoxelBlockPool.Rent();
 11174            block.Initialize(grid, cellKey, capacity: 1);
 11175            _blocks.Add(cellKey, block);
 11176            ScanCells!.Add(cellKey, block.ScanCell!);
 177        }
 178
 42179        if (!block!.TryAddVoxel(grid, index, out voxel))
 2180            return false;
 181
 40182        AddVoxelToCache(voxel!);
 40183        AddVoxelToClosestTree(voxel!, ConfiguredVoxelCount + 1);
 40184        ConfiguredVoxelCount++;
 40185        return true;
 186    }
 187
 188    public bool TryRemoveVoxel(VoxelGrid grid, VoxelIndex index, out Voxel? voxel)
 189    {
 21190        voxel = null;
 21191        if (_blocks == null)
 1192            return false;
 193
 20194        int cellKey = grid.GetScanCellKey(index);
 20195        if (cellKey < 0)
 1196            return false;
 197
 19198        if (!_blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 1199            return false;
 200
 18201        if (!block!.TryRemoveVoxel(grid, index, out voxel))
 2202            return false;
 203
 16204        RemoveVoxelFromCache(index);
 16205        RemoveVoxelFromClosestTree(voxel!);
 16206        ConfiguredVoxelCount--;
 207
 16208        if (block.Count == 0)
 8209            ReleaseBlock(grid, cellKey, block);
 210
 16211        ReleaseEmptyStorageMapsIfNeeded();
 16212        return true;
 213    }
 214
 215    public void AddVoxelsInIndexRange(
 216        VoxelIndex min,
 217        VoxelIndex max,
 218        SwiftList<Voxel> results,
 219        SwiftHashSet<Voxel> redundancy)
 220    {
 52221        if (_blocks == null || _scanCellSize <= 0)
 4222            return;
 223
 48224        int scanXMin = min.x / _scanCellSize;
 48225        int scanYMin = min.y / _scanCellSize;
 48226        int scanZMin = min.z / _scanCellSize;
 48227        int scanXMax = max.x / _scanCellSize;
 48228        int scanYMax = max.y / _scanCellSize;
 48229        int scanZMax = max.z / _scanCellSize;
 230
 198231        for (long scanX = scanXMin; scanX <= scanXMax; scanX++)
 232        {
 204233            for (long scanY = scanYMin; scanY <= scanYMax; scanY++)
 234            {
 204235                for (long scanZ = scanZMin; scanZ <= scanZMax; scanZ++)
 236                {
 51237                    int cellKey = GetScanCellKeyFromScanCoordinates(
 51238                        (int)scanX,
 51239                        (int)scanY,
 51240                        (int)scanZ);
 51241                    if (cellKey >= 0 && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 47242                        block.AddVoxelsInIndexRange(min, max, results, redundancy);
 243                }
 244            }
 245        }
 48246    }
 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    {
 83288        result.EnsureCapacity(configuredVoxels.Length);
 440289        for (int i = 0; i < configuredVoxels.Length; i++)
 290        {
 137291            int key = grid.GetScanCellKey(configuredVoxels[i]);
 137292            if (result.TryGetValue(key, out int count))
 45293                result[key] = count + 1;
 294            else
 92295                result.Add(key, 1);
 296        }
 83297    }
 298
 299    private void EnsureStorageMaps()
 300    {
 42301        ScanCells ??= Pools.ScanCellMapPool.Rent();
 42302        _blocks ??= Pools.SparseVoxelBlockMapPool.Rent();
 42303    }
 304
 305    private void AddVoxelToCache(Voxel voxel)
 306    {
 40307        EnsureVoxelCacheCapacity(ConfiguredVoxelCount + 1);
 40308        TryFindVoxelCacheIndex(voxel.Index, out int insertIndex);
 309
 40310        if (insertIndex < ConfiguredVoxelCount)
 11311            Array.Copy(_voxels!, insertIndex, _voxels!, insertIndex + 1, ConfiguredVoxelCount - insertIndex);
 312
 40313        _voxels![insertIndex] = voxel;
 40314    }
 315
 316    private void AddVoxelToClosestTree(Voxel voxel, int targetVoxelCount)
 317    {
 177318        _closestVoxelTree ??= new SwiftFixedBVH<Voxel>(GetClosestVoxelTreeCapacity(targetVoxelCount));
 177319        _closestVoxelTree.EnsureCapacity(GetClosestVoxelTreeCapacity(targetVoxelCount));
 177320        _closestVoxelTree.Insert(voxel, CreateVoxelPointBounds(voxel));
 177321        EnsureClosestQueryStackCapacity(_closestVoxelTree.NodePool.Length);
 177322    }
 323
 324    private void RemoveVoxelFromClosestTree(Voxel voxel)
 325    {
 16326        _closestVoxelTree!.Remove(voxel);
 16327        if (_closestVoxelTree.Count == 0)
 8328            ReleaseClosestVoxelTree();
 16329    }
 330
 331    private void RemoveVoxelFromCache(VoxelIndex index)
 332    {
 16333        Voxel[] voxels = _voxels!;
 16334        TryFindVoxelCacheIndex(index, out int voxelArrayIndex);
 335
 16336        int moveCount = ConfiguredVoxelCount - voxelArrayIndex - 1;
 16337        if (moveCount > 0)
 3338            Array.Copy(voxels, voxelArrayIndex + 1, voxels, voxelArrayIndex, moveCount);
 339
 16340        voxels[ConfiguredVoxelCount - 1] = null!;
 16341        if (ConfiguredVoxelCount == 1)
 342        {
 8343            ArrayPool<Voxel>.Shared.Return(voxels, clearArray: true);
 8344            _voxels = null;
 345        }
 16346    }
 347
 348    private void EnsureVoxelCacheCapacity(int minCapacity)
 349    {
 40350        if (_voxels != null && _voxels.Length >= minCapacity)
 28351            return;
 352
 12353        int capacity = _voxels == null
 12354            ? minCapacity
 12355            : Math.Max(minCapacity, _voxels.Length << 1);
 12356        Voxel[] replacement = ArrayPool<Voxel>.Shared.Rent(capacity);
 357
 12358        if (_voxels != null)
 359        {
 1360            Array.Copy(_voxels, replacement, ConfiguredVoxelCount);
 1361            ArrayPool<Voxel>.Shared.Return(_voxels, clearArray: true);
 362        }
 363
 12364        _voxels = replacement;
 12365    }
 366
 367    private bool TryFindVoxelCacheIndex(VoxelIndex index, out int voxelArrayIndex)
 368    {
 56369        voxelArrayIndex = 0;
 56370        Voxel[] voxels = _voxels!;
 371
 56372        int min = 0;
 56373        int max = ConfiguredVoxelCount - 1;
 160374        while (min <= max)
 375        {
 108376            int mid = min + ((max - min) >> 1);
 108377            int compare = voxels[mid].Index.CompareTo(index);
 108378            if (compare == 0)
 379            {
 4380                voxelArrayIndex = mid;
 4381                return true;
 382            }
 383
 104384            if (compare < 0)
 89385                min = mid + 1;
 386            else
 15387                max = mid - 1;
 388        }
 389
 52390        voxelArrayIndex = min;
 52391        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) =>
 177494        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    {
 274516        if (voxelCapacity <= 1)
 127517            return 1;
 518
 147519        return voxelCapacity > int.MaxValue / 2
 147520            ? int.MaxValue
 147521            : voxelCapacity << 1;
 522    }
 523
 524    private void EnsureClosestQueryStackCapacity(int minCapacity)
 525    {
 186526        if (_closestQueryStack != null && _closestQueryStack.Length >= minCapacity)
 90527            return;
 528
 96529        int[] replacement = ArrayPool<int>.Shared.Rent(minCapacity);
 96530        if (_closestQueryStack != null)
 2531            ArrayPool<int>.Shared.Return(_closestQueryStack);
 532
 96533        _closestQueryStack = replacement;
 96534    }
 535
 536    private void ReleaseBlock(VoxelGrid grid, int cellKey, SparseVoxelBlock block)
 537    {
 8538        ScanCells!.Remove(cellKey);
 8539        _blocks!.Remove(cellKey);
 8540        block.Reset(grid);
 8541        Pools.SparseVoxelBlockPool.Release(block);
 8542    }
 543
 544    private void ReleaseEmptyStorageMapsIfNeeded()
 545    {
 16546        if (ConfiguredVoxelCount != 0)
 8547            return;
 548
 8549        Pools.SparseVoxelBlockMapPool.Release(_blocks!);
 8550        _blocks = null;
 551
 8552        Pools.ScanCellMapPool.Release(ScanCells!);
 8553        ScanCells = null;
 8554    }
 555
 556    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 557    private int GetScanCellKey(int x, int y, int z)
 558    {
 282559        int scanX = x / _scanCellSize;
 282560        int scanY = y / _scanCellSize;
 282561        int scanZ = z / _scanCellSize;
 562
 282563        return GetScanCellKeyFromScanCoordinates(scanX, scanY, scanZ);
 564    }
 565
 566    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 567    private int GetScanCellKeyFromScanCoordinates(int scanX, int scanY, int scanZ)
 568    {
 383569        if ((uint)scanX >= (uint)_scanWidth
 383570            || (uint)scanY >= (uint)_scanHeight
 383571            || (uint)scanZ >= (uint)_scanLength)
 572        {
 7573            return -1;
 574        }
 575
 376576        return scanX + scanY * _scanWidth + scanZ * _scanLayerSize;
 577    }
 578
 579    private void ReleaseBlocks(VoxelGrid grid)
 580    {
 127581        if (_blocks == null)
 41582            return;
 583
 86584        Span<SparseVoxelBlock> blocks = _blocks.Values;
 362585        for (int i = 0; i < blocks.Length; i++)
 586        {
 95587            SparseVoxelBlock block = blocks[i];
 95588            block.Reset(grid);
 95589            Pools.SparseVoxelBlockPool.Release(block);
 590        }
 591
 86592        Pools.SparseVoxelBlockMapPool.Release(_blocks);
 86593        _blocks = null;
 86594    }
 595
 596    private void ReleaseScanCells()
 597    {
 127598        if (ScanCells == null)
 41599            return;
 600
 86601        Pools.ScanCellMapPool.Release(ScanCells);
 86602        ScanCells = null;
 86603    }
 604
 605    private void ReleaseVoxelCache()
 606    {
 127607        if (_voxels != null)
 86608            ArrayPool<Voxel>.Shared.Return(_voxels, clearArray: true);
 609
 127610        _voxels = null;
 127611        _scanCellSize = 0;
 127612        _scanWidth = 0;
 127613        _scanHeight = 0;
 127614        _scanLength = 0;
 127615        _scanLayerSize = 0;
 127616    }
 617
 618    private void ReleaseClosestVoxelTree()
 619    {
 135620        _closestVoxelTree?.Clear();
 135621        _closestVoxelTree = null;
 622
 135623        if (_closestQueryStack != null)
 94624            ArrayPool<int>.Shared.Return(_closestQueryStack);
 625
 135626        _closestQueryStack = null;
 135627    }
 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()