< Summary

Information
Class: GridForge.Grids.Storage.SparseVoxelGridStorage
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Grids/Storage/SparseVoxelGridStorage.cs
Line coverage
99%
Covered lines: 295
Uncovered lines: 2
Coverable lines: 297
Total lines: 623
Line coverage: 99.3%
Branch coverage
96%
Covered branches: 152
Total branches: 158
Branch coverage: 96.2%
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 FixedMathSharp;
 9using GridForge.Spatial;
 10using SwiftCollections;
 11using SwiftCollections.Query;
 12using System;
 13using System.Buffers;
 14using System.Collections.Generic;
 15using System.Runtime.CompilerServices;
 16
 17namespace GridForge.Grids.Storage;
 18
 19internal sealed class SparseVoxelGridStorage : IVoxelGridStorage
 20{
 21    public GridStorageKind Kind
 22    {
 23        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 26024        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    {
 6443        _scanCellSize = grid.ScanCellSize;
 6444        _scanWidth = grid.ScanWidth;
 6445        _scanHeight = grid.ScanHeight;
 6446        _scanLength = grid.ScanLength;
 6447        _scanLayerSize = grid.ScanWidth * grid.ScanHeight;
 48
 6449        ConfiguredVoxelCount = configuredVoxels.Length;
 6450        if (ConfiguredVoxelCount == 0)
 1251            return;
 52
 5253        SwiftDictionary<int, int> blockCapacities = Pools.SparseVoxelBlockCapacityPool.Rent();
 54        try
 55        {
 5256            CountConfiguredVoxelsPerBlock(grid, configuredVoxels, blockCapacities);
 5257            ScanCells = Pools.ScanCellMapPool.Rent();
 5258            _blocks = Pools.SparseVoxelBlockMapPool.Rent();
 5259            _voxels = ArrayPool<Voxel>.Shared.Rent(ConfiguredVoxelCount);
 5260            _closestVoxelTree = new SwiftFixedBVH<Voxel>(GetClosestVoxelTreeCapacity(ConfiguredVoxelCount));
 61
 27062            for (int i = 0; i < configuredVoxels.Length; i++)
 63            {
 8364                VoxelIndex index = configuredVoxels[i];
 8365                int cellKey = grid.GetScanCellKey(index);
 66
 8367                if (!_blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 68                {
 6169                    block = Pools.SparseVoxelBlockPool.Rent();
 6170                    block.Initialize(grid, cellKey, blockCapacities[cellKey]);
 6171                    _blocks.Add(cellKey, block);
 6172                    ScanCells.Add(cellKey, block.ScanCell!);
 73                }
 74
 8375                Voxel voxel = block.AddPreparedVoxel(grid, index);
 8376                _voxels[i] = voxel;
 8377                AddVoxelToClosestTree(voxel, ConfiguredVoxelCount);
 78            }
 5279        }
 80        finally
 81        {
 5282            Pools.SparseVoxelBlockCapacityPool.Release(blockCapacities);
 5283        }
 5284    }
 85
 86    public void Reset(VoxelGrid grid)
 87    {
 6588        ReleaseBlocks(grid);
 6589        ReleaseScanCells();
 6590        ReleaseVoxelCache();
 6591        ReleaseClosestVoxelTree();
 92
 6593        ConfiguredVoxelCount = 0;
 6594    }
 95
 96    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 97    public bool TryGetVoxel(int x, int y, int z, out Voxel? result)
 98    {
 17099        result = null;
 100
 170101        if (_blocks == null)
 11102            return false;
 103
 159104        VoxelIndex index = new(x, y, z);
 159105        int cellKey = GetScanCellKey(x, y, z);
 159106        return cellKey >= 0
 159107            && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block)
 159108            && 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    {
 15136        result = null;
 15137        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    {
 37152        if (_voxels == null)
 0153            return;
 154
 358155        for (int i = 0; i < ConfiguredVoxelCount; i++)
 156        {
 142157            if (!visitor.Visit(_voxels[i]))
 0158                return;
 159        }
 37160    }
 161
 162    public bool TryAddVoxel(VoxelGrid grid, VoxelIndex index, out Voxel? voxel)
 163    {
 36164        voxel = null;
 36165        int cellKey = grid.GetScanCellKey(index);
 36166        if (cellKey < 0)
 1167            return false;
 168
 35169        EnsureStorageMaps();
 170
 35171        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
 35179        if (!block!.TryAddVoxel(grid, index, out voxel))
 2180            return false;
 181
 33182        AddVoxelToCache(voxel!);
 33183        AddVoxelToClosestTree(voxel!, ConfiguredVoxelCount + 1);
 33184        ConfiguredVoxelCount++;
 33185        return true;
 186    }
 187
 188    public bool TryRemoveVoxel(VoxelGrid grid, VoxelIndex index, out Voxel? voxel)
 189    {
 18190        voxel = null;
 18191        if (_blocks == null)
 1192            return false;
 193
 17194        int cellKey = grid.GetScanCellKey(index);
 17195        if (cellKey < 0)
 1196            return false;
 197
 16198        if (!_blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 1199            return false;
 200
 15201        if (!block!.TryRemoveVoxel(grid, index, out voxel))
 2202            return false;
 203
 13204        RemoveVoxelFromCache(index);
 13205        RemoveVoxelFromClosestTree(voxel!);
 13206        ConfiguredVoxelCount--;
 207
 13208        if (block.Count == 0)
 7209            ReleaseBlock(grid, cellKey, block);
 210
 13211        ReleaseEmptyStorageMapsIfNeeded();
 13212        return true;
 213    }
 214
 215    public void AddVoxelsInIndexRange(
 216        VoxelIndex min,
 217        VoxelIndex max,
 218        SwiftList<Voxel> results,
 219        SwiftHashSet<Voxel> redundancy)
 220    {
 15221        if (_blocks == null || _scanCellSize <= 0)
 4222            return;
 223
 11224        int scanXMin = min.x / _scanCellSize;
 11225        int scanYMin = min.y / _scanCellSize;
 11226        int scanZMin = min.z / _scanCellSize;
 11227        int scanXMax = max.x / _scanCellSize;
 11228        int scanYMax = max.y / _scanCellSize;
 11229        int scanZMax = max.z / _scanCellSize;
 230
 48231        for (int scanX = scanXMin; scanX <= scanXMax; scanX++)
 232        {
 52233            for (int scanY = scanYMin; scanY <= scanYMax; scanY++)
 234            {
 52235                for (int scanZ = scanZMin; scanZ <= scanZMax; scanZ++)
 236                {
 13237                    int cellKey = GetScanCellKeyFromScanCoordinates(scanX, scanY, scanZ);
 13238                    if (cellKey >= 0 && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block))
 10239                        block.AddVoxelsInIndexRange(min, max, results, redundancy);
 240                }
 241            }
 242        }
 11243    }
 244
 245    public void AddScanCellsInRange(
 246        VoxelGrid _,
 247        int xMin,
 248        int yMin,
 249        int zMin,
 250        int xMax,
 251        int yMax,
 252        int zMax,
 253        SwiftList<ScanCell> results,
 254        SwiftHashSet<ScanCell> redundancy)
 255    {
 7256        if (_blocks == null)
 1257            return;
 258
 34259        for (int x = xMin; x <= xMax; x++)
 260        {
 44261            for (int y = yMin; y <= yMax; y++)
 262            {
 72263                for (int z = zMin; z <= zMax; z++)
 264                {
 25265                    int cellKey = GetScanCellKeyFromScanCoordinates(x, y, z);
 25266                    if (cellKey >= 0
 25267                        && _blocks.TryGetValue(cellKey, out SparseVoxelBlock? block)
 25268                        && block.ScanCell != null
 25269                        && redundancy.Add(block.ScanCell))
 270                    {
 7271                        results.Add(block.ScanCell);
 272                    }
 273                }
 274            }
 275        }
 6276    }
 277
 278    private static void CountConfiguredVoxelsPerBlock(
 279        VoxelGrid grid,
 280        VoxelIndex[] configuredVoxels,
 281        SwiftDictionary<int, int> result)
 282    {
 52283        result.EnsureCapacity(configuredVoxels.Length);
 270284        for (int i = 0; i < configuredVoxels.Length; i++)
 285        {
 83286            int key = grid.GetScanCellKey(configuredVoxels[i]);
 83287            if (result.TryGetValue(key, out int count))
 22288                result[key] = count + 1;
 289            else
 61290                result.Add(key, 1);
 291        }
 52292    }
 293
 294    private void EnsureStorageMaps()
 295    {
 35296        ScanCells ??= Pools.ScanCellMapPool.Rent();
 35297        _blocks ??= Pools.SparseVoxelBlockMapPool.Rent();
 35298    }
 299
 300    private void AddVoxelToCache(Voxel voxel)
 301    {
 33302        EnsureVoxelCacheCapacity(ConfiguredVoxelCount + 1);
 33303        TryFindVoxelCacheIndex(voxel.Index, out int insertIndex);
 304
 33305        if (insertIndex < ConfiguredVoxelCount)
 11306            Array.Copy(_voxels!, insertIndex, _voxels!, insertIndex + 1, ConfiguredVoxelCount - insertIndex);
 307
 33308        _voxels![insertIndex] = voxel;
 33309    }
 310
 311    private void AddVoxelToClosestTree(Voxel voxel, int targetVoxelCount)
 312    {
 116313        _closestVoxelTree ??= new SwiftFixedBVH<Voxel>(GetClosestVoxelTreeCapacity(targetVoxelCount));
 116314        _closestVoxelTree.EnsureCapacity(GetClosestVoxelTreeCapacity(targetVoxelCount));
 116315        _closestVoxelTree.Insert(voxel, CreateVoxelPointBounds(voxel));
 116316        EnsureClosestQueryStackCapacity(_closestVoxelTree.NodePool.Length);
 116317    }
 318
 319    private void RemoveVoxelFromClosestTree(Voxel voxel)
 320    {
 13321        _closestVoxelTree!.Remove(voxel);
 13322        if (_closestVoxelTree.Count == 0)
 7323            ReleaseClosestVoxelTree();
 13324    }
 325
 326    private void RemoveVoxelFromCache(VoxelIndex index)
 327    {
 13328        Voxel[] voxels = _voxels!;
 13329        TryFindVoxelCacheIndex(index, out int voxelArrayIndex);
 330
 13331        int moveCount = ConfiguredVoxelCount - voxelArrayIndex - 1;
 13332        if (moveCount > 0)
 1333            Array.Copy(voxels, voxelArrayIndex + 1, voxels, voxelArrayIndex, moveCount);
 334
 13335        voxels[ConfiguredVoxelCount - 1] = null!;
 13336        if (ConfiguredVoxelCount == 1)
 337        {
 7338            ArrayPool<Voxel>.Shared.Return(voxels, clearArray: true);
 7339            _voxels = null;
 340        }
 13341    }
 342
 343    private void EnsureVoxelCacheCapacity(int minCapacity)
 344    {
 33345        if (_voxels != null && _voxels.Length >= minCapacity)
 24346            return;
 347
 9348        int capacity = _voxels == null
 9349            ? minCapacity
 9350            : Math.Max(minCapacity, _voxels.Length << 1);
 9351        Voxel[] replacement = ArrayPool<Voxel>.Shared.Rent(capacity);
 352
 9353        if (_voxels != null)
 354        {
 1355            Array.Copy(_voxels, replacement, ConfiguredVoxelCount);
 1356            ArrayPool<Voxel>.Shared.Return(_voxels, clearArray: true);
 357        }
 358
 9359        _voxels = replacement;
 9360    }
 361
 362    private bool TryFindVoxelCacheIndex(VoxelIndex index, out int voxelArrayIndex)
 363    {
 46364        voxelArrayIndex = 0;
 46365        Voxel[] voxels = _voxels!;
 366
 46367        int min = 0;
 46368        int max = ConfiguredVoxelCount - 1;
 144369        while (min <= max)
 370        {
 101371            int mid = min + ((max - min) >> 1);
 101372            int compare = voxels[mid].Index.CompareTo(index);
 101373            if (compare == 0)
 374            {
 3375                voxelArrayIndex = mid;
 3376                return true;
 377            }
 378
 98379            if (compare < 0)
 83380                min = mid + 1;
 381            else
 15382                max = mid - 1;
 383        }
 384
 43385        voxelArrayIndex = min;
 43386        return false;
 387    }
 388
 389    private bool TryGetClosestVoxelFromTree(
 390        Vector3d position,
 391        out Voxel? result,
 392        out Fixed64 distanceSquared)
 393    {
 9394        result = null;
 9395        distanceSquared = Fixed64.MaxValue;
 396
 9397        int rootNodeIndex = _closestVoxelTree!.RootNodeIndex;
 398
 9399        SwiftBVHNode<Voxel, FixedBoundVolume>[] nodes = _closestVoxelTree.NodePool;
 9400        EnsureClosestQueryStackCapacity(nodes.Length);
 401
 9402        int[] stack = _closestQueryStack!;
 9403        int stackCount = 0;
 9404        stack[stackCount++] = rootNodeIndex;
 405
 30406        while (stackCount > 0)
 407        {
 21408            int nodeIndex = stack[--stackCount];
 21409            ref SwiftBVHNode<Voxel, FixedBoundVolume> node = ref nodes[nodeIndex];
 21410            Fixed64 nodeDistanceSquared = GetDistanceSquaredToBounds(position, node.Bounds);
 21411            if (nodeDistanceSquared > distanceSquared)
 412                continue;
 413
 16414            if (node.IsLeaf)
 415            {
 10416                Voxel candidate = node.Value;
 10417                Fixed64 candidateDistanceSquared = (candidate.WorldPosition - position).MagnitudeSquared;
 10418                if (IsBetterClosestVoxel(candidate, candidateDistanceSquared, result, distanceSquared))
 419                {
 9420                    result = candidate;
 9421                    distanceSquared = candidateDistanceSquared;
 422                }
 423
 9424                continue;
 425            }
 426
 6427            PushClosestChildrenFirst(position, nodes, node, stack, ref stackCount, distanceSquared);
 428        }
 429
 9430        return true;
 431    }
 432
 433    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 434    private static bool IsBetterClosestVoxel(
 435        Voxel candidate,
 436        Fixed64 candidateDistanceSquared,
 437        Voxel? current,
 438        Fixed64 currentDistanceSquared)
 439    {
 13440        if (current == null)
 10441            return true;
 442
 3443        if (candidateDistanceSquared != currentDistanceSquared)
 1444            return candidateDistanceSquared < currentDistanceSquared;
 445
 2446        return candidate.Index.CompareTo(current.Index) < 0;
 447    }
 448
 449    private static void PushClosestChildrenFirst(
 450        Vector3d position,
 451        SwiftBVHNode<Voxel, FixedBoundVolume>[] nodes,
 452        SwiftBVHNode<Voxel, FixedBoundVolume> node,
 453        int[] stack,
 454        ref int stackCount,
 455        Fixed64 bestDistanceSquared)
 456    {
 6457        int leftIndex = node.LeftChildIndex;
 6458        int rightIndex = node.RightChildIndex;
 459
 6460        Fixed64 leftDistanceSquared = GetDistanceSquaredToBounds(position, nodes[leftIndex].Bounds);
 6461        Fixed64 rightDistanceSquared = GetDistanceSquaredToBounds(position, nodes[rightIndex].Bounds);
 462
 6463        if (leftDistanceSquared <= rightDistanceSquared)
 464        {
 5465            PushChildIfWithinBest(rightIndex, rightDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 5466            PushChildIfWithinBest(leftIndex, leftDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 467        }
 468        else
 469        {
 1470            PushChildIfWithinBest(leftIndex, leftDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 1471            PushChildIfWithinBest(rightIndex, rightDistanceSquared, stack, ref stackCount, bestDistanceSquared);
 472        }
 1473    }
 474
 475    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 476    private static void PushChildIfWithinBest(
 477        int childIndex,
 478        Fixed64 childDistanceSquared,
 479        int[] stack,
 480        ref int stackCount,
 481        Fixed64 bestDistanceSquared)
 482    {
 14483        if (childDistanceSquared <= bestDistanceSquared)
 13484            stack[stackCount++] = childIndex;
 14485    }
 486
 487    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 488    private static FixedBoundVolume CreateVoxelPointBounds(Voxel voxel) =>
 116489        new(voxel.WorldPosition, voxel.WorldPosition);
 490
 491    private static Fixed64 GetDistanceSquaredToBounds(Vector3d position, FixedBoundVolume bounds)
 492    {
 33493        Fixed64 x = GetAxisDistance(position.X, bounds.Min.X, bounds.Max.X);
 33494        Fixed64 y = GetAxisDistance(position.Y, bounds.Min.Y, bounds.Max.Y);
 33495        Fixed64 z = GetAxisDistance(position.Z, bounds.Min.Z, bounds.Max.Z);
 33496        return x * x + y * y + z * z;
 497    }
 498
 499    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 500    private static Fixed64 GetAxisDistance(Fixed64 value, Fixed64 min, Fixed64 max)
 501    {
 99502        if (value < min)
 21503            return min - value;
 504
 78505        return value > max ? value - max : Fixed64.Zero;
 506    }
 507
 508    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 509    private static int GetClosestVoxelTreeCapacity(int voxelCapacity)
 510    {
 179511        if (voxelCapacity <= 1)
 77512            return 1;
 513
 102514        return voxelCapacity > int.MaxValue / 2
 102515            ? int.MaxValue
 102516            : voxelCapacity << 1;
 517    }
 518
 519    private void EnsureClosestQueryStackCapacity(int minCapacity)
 520    {
 125521        if (_closestQueryStack != null && _closestQueryStack.Length >= minCapacity)
 63522            return;
 523
 62524        int[] replacement = ArrayPool<int>.Shared.Rent(minCapacity);
 62525        if (_closestQueryStack != null)
 2526            ArrayPool<int>.Shared.Return(_closestQueryStack);
 527
 62528        _closestQueryStack = replacement;
 62529    }
 530
 531    private void ReleaseBlock(VoxelGrid grid, int cellKey, SparseVoxelBlock block)
 532    {
 7533        ScanCells!.Remove(cellKey);
 7534        _blocks!.Remove(cellKey);
 7535        block.Reset(grid);
 7536        Pools.SparseVoxelBlockPool.Release(block);
 7537    }
 538
 539    private void ReleaseEmptyStorageMapsIfNeeded()
 540    {
 13541        if (ConfiguredVoxelCount != 0)
 6542            return;
 543
 7544        Pools.SparseVoxelBlockMapPool.Release(_blocks!);
 7545        _blocks = null;
 546
 7547        Pools.ScanCellMapPool.Release(ScanCells!);
 7548        ScanCells = null;
 7549    }
 550
 551    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 552    private int GetScanCellKey(int x, int y, int z)
 553    {
 159554        int scanX = x / _scanCellSize;
 159555        int scanY = y / _scanCellSize;
 159556        int scanZ = z / _scanCellSize;
 557
 159558        return GetScanCellKeyFromScanCoordinates(scanX, scanY, scanZ);
 559    }
 560
 561    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 562    private int GetScanCellKeyFromScanCoordinates(int scanX, int scanY, int scanZ)
 563    {
 197564        if ((uint)scanX >= (uint)_scanWidth
 197565            || (uint)scanY >= (uint)_scanHeight
 197566            || (uint)scanZ >= (uint)_scanLength)
 567        {
 4568            return -1;
 569        }
 570
 193571        return scanX + scanY * _scanWidth + scanZ * _scanLayerSize;
 572    }
 573
 574    private void ReleaseBlocks(VoxelGrid grid)
 575    {
 65576        if (_blocks == null)
 12577            return;
 578
 53579        Span<SparseVoxelBlock> blocks = _blocks.Values;
 230580        for (int i = 0; i < blocks.Length; i++)
 581        {
 62582            SparseVoxelBlock block = blocks[i];
 62583            block.Reset(grid);
 62584            Pools.SparseVoxelBlockPool.Release(block);
 585        }
 586
 53587        Pools.SparseVoxelBlockMapPool.Release(_blocks);
 53588        _blocks = null;
 53589    }
 590
 591    private void ReleaseScanCells()
 592    {
 65593        if (ScanCells == null)
 12594            return;
 595
 53596        Pools.ScanCellMapPool.Release(ScanCells);
 53597        ScanCells = null;
 53598    }
 599
 600    private void ReleaseVoxelCache()
 601    {
 65602        if (_voxels != null)
 53603            ArrayPool<Voxel>.Shared.Return(_voxels, clearArray: true);
 604
 65605        _voxels = null;
 65606        _scanCellSize = 0;
 65607        _scanWidth = 0;
 65608        _scanHeight = 0;
 65609        _scanLength = 0;
 65610        _scanLayerSize = 0;
 65611    }
 612
 613    private void ReleaseClosestVoxelTree()
 614    {
 72615        _closestVoxelTree?.Clear();
 72616        _closestVoxelTree = null;
 617
 72618        if (_closestQueryStack != null)
 60619            ArrayPool<int>.Shared.Return(_closestQueryStack);
 620
 72621        _closestQueryStack = null;
 72622    }
 623}

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()