internal void ReadFrom(MyOctreeStorage.ChunkHeader header, Stream stream) { if (this.m_octree == null) { this.m_octree = new MySparseOctree(0, (header.ChunkType == MyOctreeStorage.ChunkTypeEnum.ContentLeafOctree) ? MyOctreeNode.ContentFilter : MyOctreeNode.MaterialFilter, 0); } this.m_octree.ReadFrom(header, stream); }
public MyMicroOctreeLeaf(MyStorageDataTypeEnum dataType, int height, Vector3I voxelRangeMin) { Debug.Assert(dataType == MyStorageDataTypeEnum.Content || dataType == MyStorageDataTypeEnum.Material); m_octree = new MySparseOctree(height, dataType == MyStorageDataTypeEnum.Content ? MyOctreeNode.ContentFilter : MyOctreeNode.MaterialFilter); m_dataType = dataType; m_voxelRangeMin = voxelRangeMin; }
internal void ReadFrom(MyOctreeStorage.ChunkHeader header, Stream stream) { if (m_octree == null) { Debug.Assert(header.ChunkType == MyOctreeStorage.ChunkTypeEnum.ContentLeafOctree || header.ChunkType == MyOctreeStorage.ChunkTypeEnum.MaterialLeafOctree); m_octree = new MySparseOctree(0, header.ChunkType == MyOctreeStorage.ChunkTypeEnum.ContentLeafOctree ? MyOctreeNode.ContentFilter : MyOctreeNode.MaterialFilter); } m_octree.ReadFrom(header, stream); }
internal unsafe ContainmentType Intersect(ref BoundingBoxI box, bool lazy) { int stackIdx = 0; int stackSize = MySparseOctree.EstimateStackSize(m_treeHeight); MyCellCoord *stack = stackalloc MyCellCoord[stackSize]; MyCellCoord data = new MyCellCoord(m_treeHeight - 1, ref Vector3I.Zero); stack[stackIdx++] = data; Vector3I minInLod = box.Min; Vector3I maxInLod = box.Max; MyOctreeNode node; Vector3I childPosRelative, min, max, nodePositionInChild; int lodDiff; // TODO(DI): Add support for checking for containment somehow, this needs neighbourhood information which kinda sucks. ContainmentType cont = ContainmentType.Disjoint; while (stackIdx > 0) { Debug.Assert(stackIdx <= stackSize); data = stack[--stackIdx]; node = m_nodes[data.PackId32()]; lodDiff = data.Lod; min = minInLod >> lodDiff; max = maxInLod >> lodDiff; nodePositionInChild = data.CoordInLod << 1; min -= nodePositionInChild; max -= nodePositionInChild; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childPosRelative); if (!childPosRelative.IsInsideInclusive(ref min, ref max)) { continue; } if (data.Lod > 0 && node.HasChild(i)) { Debug.Assert(stackIdx < stackSize); stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative); } else { var nodeData = node.Data[i]; if (lodDiff == 0) { if (nodeData != 0) { return(ContainmentType.Intersects); } } else { BoundingBoxI nodeBox; nodeBox.Min = nodePositionInChild + childPosRelative; nodeBox.Min <<= lodDiff; nodeBox.Max = nodeBox.Min + (1 << lodDiff) - 1; Vector3I.Max(ref nodeBox.Min, ref minInLod, out nodeBox.Min); Vector3I.Min(ref nodeBox.Max, ref maxInLod, out nodeBox.Max); bool res; nodeBox.Intersects(ref nodeBox, out res); if (res) { return(ContainmentType.Intersects); } } } } } return(cont); }
internal unsafe void ReadRange(MyStorageData target, MyStorageDataTypeEnum type, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { ProfilerShort.Begin("MySparseOctree2.ReadRangeToContent"); try { int stackIdx = 0; int stackSize = MySparseOctree.EstimateStackSize(m_treeHeight); MyCellCoord *stack = stackalloc MyCellCoord[stackSize]; MyCellCoord data = new MyCellCoord(m_treeHeight - 1, ref Vector3I.Zero); stack[stackIdx++] = data; MyOctreeNode node; Vector3I childPosRelative, min, max, nodePositionInChild; int lodDiff; while (stackIdx > 0) { Debug.Assert(stackIdx <= stackSize); data = stack[--stackIdx]; node = m_nodes[data.PackId32()]; lodDiff = data.Lod - lodIndex; min = minInLod >> lodDiff; max = maxInLod >> lodDiff; nodePositionInChild = data.CoordInLod << 1; min -= nodePositionInChild; max -= nodePositionInChild; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childPosRelative); if (!childPosRelative.IsInsideInclusive(ref min, ref max)) { continue; } if (lodIndex < data.Lod && node.HasChild(i)) { Debug.Assert(stackIdx < stackSize); stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative); } else { var nodeData = node.Data[i]; var childMin = nodePositionInChild + childPosRelative; if (lodDiff == 0) { var write = writeOffset + childMin - minInLod; target.Set(type, ref write, nodeData); } else { childMin <<= lodDiff; var childMax = childMin + (1 << lodDiff) - 1; Vector3I.Max(ref childMin, ref minInLod, out childMin); Vector3I.Min(ref childMax, ref maxInLod, out childMax); for (int z = childMin.Z; z <= childMax.Z; ++z) { for (int y = childMin.Y; y <= childMax.Y; ++y) { for (int x = childMin.X; x <= childMax.X; ++x) { var write = writeOffset; write.X += x - minInLod.X; write.Y += y - minInLod.Y; write.Z += z - minInLod.Z; target.Set(type, ref write, nodeData); } } } } } } } } finally { ProfilerShort.End(); } }
public MyMicroOctreeLeaf(MyStorageDataTypeEnum dataType, int height, Vector3I voxelRangeMin) { this.m_octree = (dataType != MyStorageDataTypeEnum.Content) ? new MySparseOctree(height, MyOctreeNode.MaterialFilter, 0xff) : new MySparseOctree(height, MyOctreeNode.ContentFilter, 0); this.m_dataType = dataType; this.m_voxelRangeMin = voxelRangeMin; }
private static unsafe void ReadRange( MyStorageDataCache target, ref Vector3I targetWriteOffset, MyStorageDataTypeEnum type, int treeHeight, Dictionary <UInt64, MyOctreeNode> nodes, Dictionary <UInt64, IMyOctreeLeafNode> leaves, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { int stackIdx = 0; int stackSize = MySparseOctree.EstimateStackSize(treeHeight); MyCellCoord *stack = stackalloc MyCellCoord[stackSize]; MyCellCoord data = new MyCellCoord(treeHeight + LeafLodCount, ref Vector3I.Zero); stack[stackIdx++] = data; MyCellCoord cell = new MyCellCoord(); while (stackIdx > 0) { Debug.Assert(stackIdx <= stackSize); data = stack[--stackIdx]; cell.Lod = data.Lod - LeafLodCount; cell.CoordInLod = data.CoordInLod; int lodDiff; IMyOctreeLeafNode leaf; if (leaves.TryGetValue(cell.PackId64(), out leaf)) { lodDiff = data.Lod - lodIndex; var rangeMinInDataLod = minInLod >> lodDiff; var rangeMaxInDataLod = maxInLod >> lodDiff; if (data.CoordInLod.IsInsideInclusive(ref rangeMinInDataLod, ref rangeMaxInDataLod)) { var nodePosInLod = data.CoordInLod << lodDiff; var writeOffset = nodePosInLod - minInLod; Vector3I.Max(ref writeOffset, ref Vector3I.Zero, out writeOffset); writeOffset += targetWriteOffset; var lodSizeMinusOne = new Vector3I((1 << lodDiff) - 1); var minInLeaf = Vector3I.Clamp(minInLod - nodePosInLod, Vector3I.Zero, lodSizeMinusOne); var maxInLeaf = Vector3I.Clamp(maxInLod - nodePosInLod, Vector3I.Zero, lodSizeMinusOne); leaf.ReadRange(target, ref writeOffset, lodIndex, ref minInLeaf, ref maxInLeaf); } continue; } cell.Lod -= 1; lodDiff = data.Lod - 1 - lodIndex; var node = nodes[cell.PackId64()]; var min = minInLod >> lodDiff; var max = maxInLod >> lodDiff; var nodePositionInChild = data.CoordInLod << 1; min -= nodePositionInChild; max -= nodePositionInChild; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { Vector3I childPosRelative; ComputeChildCoord(i, out childPosRelative); if (!childPosRelative.IsInsideInclusive(ref min, ref max)) { continue; } if (lodIndex < data.Lod && node.HasChild(i)) { Debug.Assert(stackIdx < stackSize); stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative); } else { var childMin = nodePositionInChild + childPosRelative; childMin <<= lodDiff; var writeOffset = childMin - minInLod; Vector3I.Max(ref writeOffset, ref Vector3I.Zero, out writeOffset); writeOffset += targetWriteOffset; var nodeData = node.GetData(i); if (lodDiff == 0) { target.Set(type, ref writeOffset, nodeData); } else { var childMax = childMin + ((1 << lodDiff) - 1); Vector3I.Max(ref childMin, ref minInLod, out childMin); Vector3I.Min(ref childMax, ref maxInLod, out childMax); for (int z = childMin.Z; z <= childMax.Z; ++z) { for (int y = childMin.Y; y <= childMax.Y; ++y) { for (int x = childMin.X; x <= childMax.X; ++x) { Vector3I write = writeOffset; write.X += x - childMin.X; write.Y += y - childMin.Y; write.Z += z - childMin.Z; target.Set(type, ref write, nodeData); } } } } } } } }
protected override void LoadInternal(int fileVersion, Stream stream, ref bool isOldFormat) { Debug.Assert(fileVersion == CURRENT_FILE_VERSION); ChunkHeader header = new ChunkHeader(); Dictionary <byte, MyVoxelMaterialDefinition> materialTable = null; HashSet <UInt64> materialLeaves = new HashSet <UInt64>(); HashSet <UInt64> contentLeaves = new HashSet <UInt64>(); while (header.ChunkType != ChunkTypeEnum.EndOfFile) { MyMicroOctreeLeaf contentLeaf; MyMicroOctreeLeaf materialLeaf; UInt64 key; header.ReadFrom(stream); Debug.Assert(Enum.IsDefined(typeof(ChunkTypeEnum), header.ChunkType)); switch (header.ChunkType) { case ChunkTypeEnum.StorageMetaData: ReadStorageMetaData(stream, header, ref isOldFormat); break; case ChunkTypeEnum.MaterialIndexTable: materialTable = ReadMaterialTable(stream, header, ref isOldFormat); break; case ChunkTypeEnum.MacroContentNodes: ReadOctreeNodes(stream, header, ref isOldFormat, m_contentNodes); break; case ChunkTypeEnum.MacroMaterialNodes: ReadOctreeNodes(stream, header, ref isOldFormat, m_materialNodes); break; case ChunkTypeEnum.ContentLeafProvider: ReadProviderLeaf(stream, header, ref isOldFormat, contentLeaves); break; case ChunkTypeEnum.ContentLeafOctree: ReadOctreeLeaf(stream, header, ref isOldFormat, MyStorageDataTypeEnum.Content, out key, out contentLeaf); m_contentLeaves.Add(key, contentLeaf); break; case ChunkTypeEnum.MaterialLeafProvider: ReadProviderLeaf(stream, header, ref isOldFormat, materialLeaves); break; case ChunkTypeEnum.MaterialLeafOctree: ReadOctreeLeaf(stream, header, ref isOldFormat, MyStorageDataTypeEnum.Material, out key, out materialLeaf); m_materialLeaves.Add(key, materialLeaf); break; case ChunkTypeEnum.DataProvider: ReadDataProvider(stream, header, ref isOldFormat, out m_dataProvider); break; case ChunkTypeEnum.EndOfFile: break; default: throw new InvalidBranchException(); } } { // At this point data provider should be loaded too, so have him create leaves MyCellCoord cell = new MyCellCoord(); foreach (var key in contentLeaves) { cell.SetUnpack(key); cell.Lod += LeafLodCount; m_contentLeaves.Add(key, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Content, ref cell)); } foreach (var key in materialLeaves) { cell.SetUnpack(key); cell.Lod += LeafLodCount; m_materialLeaves.Add(key, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Material, ref cell)); } } { // material reindexing when definitions change Debug.Assert(materialTable != null); bool needsReindexing = false; foreach (var entry in materialTable) { if (entry.Key != entry.Value.Index) { needsReindexing = true; } m_oldToNewIndexMap.Add(entry.Key, entry.Value.Index); } if (needsReindexing) { if (m_dataProvider != null) { m_dataProvider.ReindexMaterials(m_oldToNewIndexMap); } foreach (var entry in m_materialLeaves) { entry.Value.ReplaceValues(m_oldToNewIndexMap); } MySparseOctree.ReplaceValues(m_materialNodes, m_oldToNewIndexMap); } m_oldToNewIndexMap.Clear(); } }