Beispiel #1
0
        void ClearVoxel(Vector3Int pos, CellIndexUpdateInfo cellInfo)
        {
            Vector3Int vx_min, vx_max;

            ClipToIndexSpace(pos, GetVoxelSubdivLevel(), out vx_min, out vx_max, cellInfo);
            UpdatePhysicalIndex(vx_min, vx_max, -1, cellInfo);
        }
Beispiel #2
0
        internal bool AssignIndexChunksToCell(int bricksCount, ref CellIndexUpdateInfo cellUpdateInfo)
        {
            // We need to better handle the case where the chunks are full, this is where streaming will need to come into place swapping in/out
            // Also the current way to find an empty spot might be sub-optimal, when streaming is in place it'd be nice to have this more efficient
            // if it is meant to happen frequently.

            int numberOfChunks = Mathf.CeilToInt((float)bricksCount / kIndexChunkSize);

            // Search for the first empty element with enough space.
            int firstValidChunk = -1;

            for (int i = 0; i < m_IndexInChunks; ++i)
            {
                if (!m_IndexChunks[i] && (i + numberOfChunks) < m_IndexInChunks)
                {
                    int emptySlotsStartingHere = 0;
                    for (int k = i; k < (i + numberOfChunks); ++k)
                    {
                        if (!m_IndexChunks[k])
                        {
                            emptySlotsStartingHere++;
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (emptySlotsStartingHere == numberOfChunks)
                    {
                        firstValidChunk = i;
                        break;
                    }
                }
            }

            if (firstValidChunk < 0)
            {
                Debug.LogError("APV Index Allocation failed.");
                return(false);
            }

            // This assert will need to go away or do something else when streaming is allowed (we need to find holes in available chunks or stream out stuff)
            cellUpdateInfo.firstChunkIndex = firstValidChunk;
            cellUpdateInfo.numberOfChunks  = numberOfChunks;
            for (int i = firstValidChunk; i < (firstValidChunk + numberOfChunks); ++i)
            {
                Debug.Assert(!m_IndexChunks[i]);
                m_IndexChunks[i] = true;
            }

            m_NextFreeChunk += Mathf.Max(0, (firstValidChunk + numberOfChunks) - m_NextFreeChunk);

            m_AvailableChunkCount -= numberOfChunks;

            return(true);
        }
Beispiel #3
0
        void UpdateIndexForVoxel(Vector3Int voxel, CellIndexUpdateInfo cellInfo)
        {
            ClearVoxel(voxel, cellInfo);
            List <VoxelMeta> vm_list = m_VoxelToBricks[voxel];

            foreach (var vm in vm_list)
            {
                // get the list of bricks and indices
                List <ReservedBrick> bricks = m_BricksToVoxels[vm.cell].bricks;
                List <ushort>        indcs  = vm.brickIndices;
                UpdateIndexForVoxel(voxel, bricks, indcs, cellInfo);
            }
        }
Beispiel #4
0
        void UpdatePhysicalIndex(Vector3Int brickMin, Vector3Int brickMax, int value, CellIndexUpdateInfo cellInfo)
        {
            // We need to do our calculations in local space to the cell, so we move the brick to local space as a first step.
            // Reminder that at this point we are still operating at highest resolution possible, not necessarily the one that will be
            // the final resolution for the chunk.
            brickMin = brickMin - cellInfo.cellPositionInBricksAtMaxRes;
            brickMax = brickMax - cellInfo.cellPositionInBricksAtMaxRes;

            // Since the index is spurious (not same resolution, but varying per cell) we need to bring to the output resolution the brick coordinates
            // Before finding the locations inside the Index for the current cell/chunk.

            brickMin /= ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell);
            brickMax /= ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell);

            // Verify we are actually in local space now.
            int maxCellSizeInOutputRes = ProbeReferenceVolume.CellSize(ProbeReferenceVolume.instance.GetMaxSubdivision() - 1 - cellInfo.minSubdivInCell);

            Debug.Assert(brickMin.x >= 0 && brickMin.y >= 0 && brickMin.z >= 0 && brickMax.x >= 0 && brickMax.y >= 0 && brickMax.z >= 0);
            Debug.Assert(brickMin.x < maxCellSizeInOutputRes && brickMin.y < maxCellSizeInOutputRes && brickMin.z < maxCellSizeInOutputRes && brickMax.x <= maxCellSizeInOutputRes && brickMax.y <= maxCellSizeInOutputRes && brickMax.z <= maxCellSizeInOutputRes);

            // We are now in the right resolution, but still not considering the valid area, so we need to still normalize against that.
            // To do so first let's move back the limits to the desired resolution
            var cellMinIndex = cellInfo.minValidBrickIndexForCellAtMaxRes / ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell);
            var cellMaxIndex = cellInfo.maxValidBrickIndexForCellAtMaxResPlusOne / ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell);

            // Then perform the rescale of the local indices for min and max.
            brickMin -= cellMinIndex;
            brickMax -= cellMinIndex;

            // In theory now we are all positive since we clipped during the voxel stage. Keeping assert for debugging, but can go later.
            Debug.Assert(brickMin.x >= 0 && brickMin.y >= 0 && brickMin.z >= 0 && brickMax.x >= 0 && brickMax.y >= 0 && brickMax.z >= 0);


            // Compute the span of the valid part
            var size = (cellMaxIndex - cellMinIndex);

            // Loop through all touched indices
            int chunkStart = cellInfo.firstChunkIndex * kIndexChunkSize;

            for (int z = brickMin.z; z < brickMax.z; ++z)
            {
                for (int y = brickMin.y; y < brickMax.y; ++y)
                {
                    for (int x = brickMin.x; x < brickMax.x; ++x)
                    {
                        int localFlatIdx = z * (size.x * size.y) + x * size.y + y;
                        int actualIdx    = chunkStart + localFlatIdx;
                        m_PhysicalIndexBufferData[actualIdx] = value;

                        m_UpdateMinIndex = Math.Min(actualIdx, m_UpdateMinIndex);
                        m_UpdateMaxIndex = Math.Max(actualIdx, m_UpdateMaxIndex);
                    }
                }
            }

            m_NeedUpdateIndexComputeBuffer = true;
        }
Beispiel #5
0
        public void AddBricks(Cell cell, NativeArray <Brick> bricks, List <Chunk> allocations, int allocationSize, int poolWidth, int poolHeight, CellIndexUpdateInfo cellInfo)
        {
            Debug.Assert(bricks.Length <= ushort.MaxValue, "Cannot add more than 65K bricks per RegId.");
            int largest_cell = ProbeReferenceVolume.CellSize(kMaxSubdivisionLevels);

            g_Cell = cell;

            // create a new copy
            BrickMeta bm = m_BrickMetaPool.Get();

            m_BricksToVoxels.Add(cell, bm);

            int brick_idx = 0;

            // find all voxels each brick will touch
            for (int i = 0; i < allocations.Count; i++)
            {
                Chunk alloc = allocations[i];
                int   cnt   = Mathf.Min(allocationSize, bricks.Length - brick_idx);
                for (int j = 0; j < cnt; j++, brick_idx++, alloc.x += ProbeBrickPool.kBrickProbeCountPerDim)
                {
                    Brick brick = bricks[brick_idx];

                    int cellSize = ProbeReferenceVolume.CellSize(brick.subdivisionLevel);
                    Debug.Assert(cellSize <= largest_cell, "Cell sizes are not correctly sorted.");
                    largest_cell = Mathf.Min(largest_cell, cellSize);

                    MapBrickToVoxels(brick, bm.voxels);

                    ReservedBrick rbrick = new ReservedBrick();
                    rbrick.brick        = brick;
                    rbrick.flattenedIdx = MergeIndex(alloc.flattenIndex(poolWidth, poolHeight), brick.subdivisionLevel);
                    bm.bricks.Add(rbrick);

                    foreach (var v in bm.voxels)
                    {
                        List <VoxelMeta> vm_list;
                        if (!m_VoxelToBricks.TryGetValue(v, out vm_list)) // first time the voxel is touched
                        {
                            vm_list = m_VoxelMetaListPool.Get();
                            m_VoxelToBricks.Add(v, vm_list);
                        }

                        VoxelMeta vm     = null;
                        int       vm_idx = vm_list.FindIndex((VoxelMeta lhs) => lhs.cell == g_Cell);
                        if (vm_idx == -1) // first time a brick from this id has touched this voxel
                        {
                            vm      = m_VoxelMetaPool.Get();
                            vm.cell = cell;
                            vm_list.Add(vm);
                        }
                        else
                        {
                            vm = vm_list[vm_idx];
                        }

                        // add this brick to the voxel under its regId
                        vm.brickIndices.Add((ushort)brick_idx);
                    }
                }
            }

            foreach (var voxel in bm.voxels)
            {
                UpdateIndexForVoxel(voxel, cellInfo);
            }
        }
Beispiel #6
0
        internal bool AssignIndexChunksToCell(int bricksCount, ref CellIndexUpdateInfo cellUpdateInfo, bool ignoreErrorLog)
        {
            // We need to better handle the case where the chunks are full, this is where streaming will need to come into place swapping in/out
            // Also the current way to find an empty spot might be sub-optimal, when streaming is in place it'd be nice to have this more efficient
            // if it is meant to happen frequently.

            int numberOfChunks = Mathf.CeilToInt((float)bricksCount / kIndexChunkSize);

            // Search for the first empty element with enough space.
            int firstValidChunk = -1;

            for (int i = 0; i < m_IndexInChunks; ++i)
            {
                if (!m_IndexChunks[i] && (i + numberOfChunks) < m_IndexInChunks)
                {
                    int emptySlotsStartingHere = 0;
                    for (int k = i; k < (i + numberOfChunks); ++k)
                    {
                        if (!m_IndexChunks[k])
                        {
                            emptySlotsStartingHere++;
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (emptySlotsStartingHere == numberOfChunks)
                    {
                        firstValidChunk = i;
                        break;
                    }
                }
            }

            if (firstValidChunk < 0)
            {
                // During baking we know we can hit this when trying to do dilation of all cells at the same time.
                // That can happen because we try to load all cells at the same time. If the budget is not high enough it will fail.
                // In this case we'll iterate separately on each cell and their neighbors.
                // If so, we don't want controlled error message spam during baking so we ignore it.
                // In theory this should never happen with proper streaming/defrag but we keep the message just in case otherwise.
                if (!ignoreErrorLog)
                {
                    Debug.LogError("APV Index Allocation failed.");
                }
                return(false);
            }

            // This assert will need to go away or do something else when streaming is allowed (we need to find holes in available chunks or stream out stuff)
            cellUpdateInfo.firstChunkIndex = firstValidChunk;
            cellUpdateInfo.numberOfChunks  = numberOfChunks;
            for (int i = firstValidChunk; i < (firstValidChunk + numberOfChunks); ++i)
            {
                Debug.Assert(!m_IndexChunks[i]);
                m_IndexChunks[i] = true;
            }

            m_NextFreeChunk += Mathf.Max(0, (firstValidChunk + numberOfChunks) - m_NextFreeChunk);

            m_AvailableChunkCount -= numberOfChunks;

            return(true);
        }