예제 #1
0
 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);
 }
예제 #4
0
        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);
        }
예제 #5
0
        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(); }
        }
예제 #6
0
 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;
 }
예제 #7
0
        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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #8
0
        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();
            }
        }