示例#1
0
        public static unsafe void ReplaceValues <TKey>(Dictionary <TKey, MyOctreeNode> nodeCollection, Dictionary <byte, byte> oldToNewValueMap)
        {
            KeyValuePair <TKey, MyOctreeNode>[] pairArray = nodeCollection.ToArray <KeyValuePair <TKey, MyOctreeNode> >();
            int index = 0;

            while (index < pairArray.Length)
            {
                KeyValuePair <TKey, MyOctreeNode> pair = pairArray[index];
                MyOctreeNode node = pair.Value;
                int          num2 = 0;
                while (true)
                {
                    byte num3;
                    if (num2 >= 8)
                    {
                        nodeCollection[pair.Key] = node;
                        index++;
                        break;
                    }
                    if (oldToNewValueMap.TryGetValue(&node.Data.FixedElementField[num2], out num3))
                    {
                        &node.Data.FixedElementField[num2] = num3;
                    }
                    num2++;
                }
            }
        }
示例#2
0
        private unsafe void WriteRange <TOperator>(MyCellCoord cell, byte defaultData, ref TOperator source, MyStorageDataTypeEnum type, ref Vector3I readOffset, ref Vector3I min, ref Vector3I max) where TOperator : struct, IVoxelOperator
        {
            MyOctreeNode node;
            uint         key = cell.PackId32();

            if (!this.m_nodes.TryGetValue(key, out node))
            {
                for (int i = 0; i < 8; i++)
                {
                    &node.Data.FixedElementField[i] = defaultData;
                }
            }
            if (cell.Lod == 0)
            {
                Vector3I vectori = cell.CoordInLod << 1;
                for (int i = 0; i < 8; i++)
                {
                    Vector3I vectori2;
                    this.ComputeChildCoord(i, out vectori2);
                    Vector3I position = (Vector3I)(vectori + vectori2);
                    if (position.IsInsideInclusiveEnd(ref min, ref max))
                    {
                        position = (Vector3I)((position - min) + readOffset);
                        source.Op(ref position, type, ref (byte)ref (&node.Data.FixedElementField + i));
                    }
                }
                this.m_nodes[key] = node;
            }
            else
            {
                Vector3I vectori4 = cell.CoordInLod << 1;
                Vector3I vectori6 = (min >> cell.Lod) - vectori4;
                Vector3I vectori7 = (max >> cell.Lod) - vectori4;
                for (int i = 0; i < 8; i++)
                {
                    Vector3I vectori5;
                    this.ComputeChildCoord(i, out vectori5);
                    if (vectori5.IsInsideInclusiveEnd(ref vectori6, ref vectori7))
                    {
                        MyCellCoord coord = new MyCellCoord(cell.Lod - 1, (Vector3I)(vectori4 + vectori5));
                        this.WriteRange <TOperator>(coord, &node.Data.FixedElementField[i], ref source, type, ref readOffset, ref min, ref max);
                        uint         num5  = coord.PackId32();
                        MyOctreeNode node2 = this.m_nodes[num5];
                        if (node2.HasChildren || !MyOctreeNode.AllDataSame(&node2.Data.FixedElementField))
                        {
                            node.SetChild(i, true);
                            &node.Data.FixedElementField[i] = this.m_nodeFilter(&node2.Data.FixedElementField, cell.Lod);
                        }
                        else
                        {
                            node.SetChild(i, false);
                            &node.Data.FixedElementField[i] = node2.Data.FixedElementField;
                            this.m_nodes.Remove(num5);
                        }
                    }
                }
                this.m_nodes[key] = node;
            }
        }
示例#3
0
 internal unsafe void WriteTo(Stream stream)
 {
     stream.WriteNoAlloc(this.m_treeHeight);
     stream.WriteNoAlloc(this.m_defaultContent);
     foreach (KeyValuePair <uint, MyOctreeNode> pair in this.m_nodes)
     {
         stream.WriteNoAlloc(pair.Key);
         MyOctreeNode node = pair.Value;
         stream.WriteNoAlloc(node.ChildMask);
         stream.WriteNoAlloc(&node.Data.FixedElementField, 0, 8);
     }
 }
            private static unsafe void UpdateLodDataInternal(int lod, byte[] dataArray, MyOctreeNode.FilterFunction filter)
            {
                int offset = 0;
                for (int i = 0; i < lod - 1; ++i)
                {
                    offset += Volume >> (i + i + i);
                }

                var sx = Size >> lod;
                var sy = sx * sx;
                var sz = sy * sx;

                var psx = Size >> (lod - 1);
                var psy = psx * psx;
                var psz = psy * psx;

                ulong dataBit;

                byte* data = (byte*)&dataBit;
                fixed (byte* fixedDataArray = dataArray)
                {
                    byte* voxel = fixedDataArray + offset;

                    byte* store = voxel + psz;

                    for (int z = 0; z < sz; z += sy)
                    {
                        int z0 = z << 3, z1 = (z << 3) + psy;

                        for (int y = 0; y < sy; y += sx)
                        {
                            int y0 = y << 2, y1 = (y << 2) + psx;
                            for (int x = 0; x < sx; ++x)
                            {
                                // precompute corner indices, moar readable
                                int x0 = x << 1, x1 = (x << 1) + 1;

                                data[0] = voxel[z0 + y0 + x0];
                                data[1] = voxel[z0 + y0 + x1];
                                data[2] = voxel[z0 + y1 + x0];
                                data[3] = voxel[z0 + y1 + x1];
                                data[4] = voxel[z1 + y0 + x0];
                                data[5] = voxel[z1 + y0 + x1];
                                data[6] = voxel[z1 + y1 + x0];
                                data[7] = voxel[z1 + y1 + x1];

                                store[x + y + z] = filter(data, lod);
                            }
                        }
                    }
                }
            }
示例#5
0
        private unsafe void BuildNode <TDataEnum>(ref StackData <TDataEnum> stack, out MyOctreeNode builtNode) where TDataEnum : struct, IEnumerator <byte>
        {
            MyOctreeNode defaultNode = stack.DefaultNode;

            if (stack.Cell.Lod == 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    stack.Data.MoveNext();
                    &defaultNode.Data.FixedElementField[i] = stack.Data.Current;
                }
            }
            else
            {
                int *numPtr1 = (int *)ref stack.Cell.Lod;
                numPtr1[0]--;
                Vector3I coordInLod = stack.Cell.CoordInLod;
                Vector3I vectori2   = coordInLod << 1;
                int      childIdx   = 0;
                while (true)
                {
                    Vector3I     vectori3;
                    MyOctreeNode node2;
                    if (childIdx >= 8)
                    {
                        int *numPtr2 = (int *)ref stack.Cell.Lod;
                        numPtr2[0]++;
                        stack.Cell.CoordInLod = coordInLod;
                        break;
                    }
                    this.ComputeChildCoord(childIdx, out vectori3);
                    stack.Cell.CoordInLod = (Vector3I)(vectori2 + vectori3);
                    this.BuildNode <TDataEnum>(ref stack, out node2);
                    if (!node2.HasChildren && MyOctreeNode.AllDataSame(&node2.Data.FixedElementField))
                    {
                        defaultNode.SetChild(childIdx, false);
                        &defaultNode.Data.FixedElementField[childIdx] = node2.Data.FixedElementField;
                    }
                    else
                    {
                        defaultNode.SetChild(childIdx, true);
                        &defaultNode.Data.FixedElementField[childIdx] = this.m_nodeFilter(&node2.Data.FixedElementField, stack.Cell.Lod);
                        this.m_nodes.Add(stack.Cell.PackId32(), node2);
                    }
                    childIdx++;
                }
            }
            builtNode = defaultNode;
        }
示例#6
0
        private unsafe void BuildNode <TDataEnum>(ref StackData <TDataEnum> stack, out MyOctreeNode builtNode) where TDataEnum : struct, IEnumerator <TLeafData>
        {
            var currentNode = stack.DefaultNode;

            if (stack.Cell.Lod == 0)
            { // bottom level containing leaf data
                for (int i = 0; i < 8; ++i)
                {
                    bool movedNext = stack.Data.MoveNext();
                    Debug.Assert(movedNext);
                    currentNode.Data[i] = stack.Data.Current;
                }
            }
            else
            {
                --stack.Cell.Lod;
                Vector3I     currentPosition = stack.Cell.CoordInLod;
                Vector3I     childBase       = currentPosition << 1;
                Vector3I     childOffset;
                MyOctreeNode childNode;
                for (int i = 0; i < 8; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    stack.Cell.CoordInLod = childBase + childOffset;
                    BuildNode(ref stack, out childNode);
                    if (!childNode.HasChildren && MyOctreeNode.AllDataSame(childNode.Data))
                    {
                        currentNode.SetChild(i, false);
                        currentNode.Data[i] = childNode.Data[0];
                    }
                    else
                    {
                        currentNode.SetChild(i, true);
                        currentNode.Data[i] = m_nodeFilter(childNode.Data, stack.Cell.Lod);
                        m_nodes.Add(stack.Cell.PackId32(), childNode);
                    }
                }
                ++stack.Cell.Lod;
                stack.Cell.CoordInLod = currentPosition;
            }

            builtNode = currentNode;
        }
示例#7
0
        private void CheckData <T>(ref T data, MyCellCoord cell) where T : struct, IEnumerator <byte>
        {
            uint         num  = cell.PackId32();
            MyOctreeNode node = this.m_nodes[num];

            for (int i = 0; i < 8; i++)
            {
                if (node.HasChild(i))
                {
                    Vector3I vectori;
                    this.ComputeChildCoord(i, out vectori);
                }
                else
                {
                    int num3 = 1 << ((3 * cell.Lod) & 0x1f);
                    for (int j = 0; j < num3; j++)
                    {
                    }
                }
            }
        }
示例#8
0
        private static void WriteRange(
            ref WriteRangeArgs args,
            byte defaultData,
            int lodIdx,
            Vector3I lodCoord,
            ref Vector3I min,
            ref Vector3I max)
        {
            MyOctreeNode node = new MyOctreeNode();
            {
                MyCellCoord leaf = new MyCellCoord(lodIdx - LeafLodCount, ref lodCoord);
                var leafKey = leaf.PackId64();
                if (args.Leaves.ContainsKey(leafKey))
                {
                    args.Leaves.Remove(leafKey);
                    var childBase = lodCoord << 1;
                    Vector3I childOffset;
                    MyCellCoord child = new MyCellCoord();
                    child.Lod = leaf.Lod - 1;
                    var leafSize = LeafSizeInVoxels << child.Lod;
                    for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                    {
                        ComputeChildCoord(i, out childOffset);
                        child.CoordInLod = childBase + childOffset;
                        var childCopy = child;
                        childCopy.Lod += LeafLodCount;
                        IMyOctreeLeafNode octreeLeaf = new MyProviderLeaf(args.Provider, args.DataType, ref childCopy);
                        args.Leaves.Add(child.PackId64(), octreeLeaf);
                        node.SetChild(i, true);
                        node.SetData(i, octreeLeaf.GetFilteredValue());
                    }
                }
                else
                {
                    leaf.Lod -= 1; // changes to node coord instead of leaf coord
                    var nodeKey = leaf.PackId64();

                    if (!args.Nodes.TryGetValue(nodeKey, out node))
                    {
                        for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                            node.SetData(i, defaultData);
                    }
                }
            }

            if (lodIdx == (LeafLodCount + 1))
            {
                MyCellCoord child = new MyCellCoord();
                Vector3I childBase = lodCoord << 1;
                Vector3I minInLod = min >> LeafLodCount;
                Vector3I maxInLod = max >> LeafLodCount;
                Vector3I leafSizeMinusOne = new Vector3I(LeafSizeInVoxels - 1);
                Vector3I childOffset;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    child.CoordInLod = childBase + childOffset;
                    if (!child.CoordInLod.IsInsideInclusive(ref minInLod, ref maxInLod))
                        continue;
                    var childMin = child.CoordInLod << LeafLodCount;
                    var childMax = childMin + LeafSizeInVoxels - 1;
                    Vector3I.Max(ref childMin, ref min, out childMin);
                    Vector3I.Min(ref childMax, ref max, out childMax);
                    var readOffset = childMin - min;
                    IMyOctreeLeafNode leaf;
                    var leafKey = child.PackId64();
                    var startInChild = childMin - (child.CoordInLod << LeafLodCount);
                    var endInChild = childMax - (child.CoordInLod << LeafLodCount);

                    args.Leaves.TryGetValue(leafKey, out leaf);

                    byte uniformValue;
                    bool uniformLeaf;
                    {
                        // ensure leaf exists and is writable
                        // the only writable leaf type is MicroOctree at this point

                        byte childDefaultData = node.GetData(i);

                        if (leaf == null)
                        {
                            var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount));
                            octree.BuildFrom(childDefaultData);
                            leaf = octree;
                        }

                        if (leaf.ReadOnly)
                        {
                            var rangeEnd = new Vector3I(LeafSizeInVoxels - 1);
                            m_temporaryCache.Resize(Vector3I.Zero, rangeEnd);
                            leaf.ReadRange(m_temporaryCache, ref Vector3I.Zero, 0, ref Vector3I.Zero, ref rangeEnd);
                            var inCell = startInChild;
                            for (var it2 = new Vector3I.RangeIterator(ref startInChild, ref endInChild);
                                it2.IsValid(); it2.GetNext(out inCell))
                            {
                                var read = readOffset + (inCell - startInChild);
                                m_temporaryCache.Set(args.DataType, ref inCell, args.Source.Get(args.DataType, ref read));
                            }

                            var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount));
                            octree.BuildFrom(m_temporaryCache);
                            leaf = octree;
                        }
                        else
                        {
                            leaf.WriteRange(args.Source, ref readOffset, ref startInChild, ref endInChild);
                        }

                        uniformLeaf = ((MyMicroOctreeLeaf)leaf).TryGetUniformValue(out uniformValue);
                    }

                    if (!uniformLeaf)
                    {
                        args.Leaves[leafKey] = leaf;
                        node.SetChild(i, true);
                    }
                    else
                    {
                        args.Leaves.Remove(leafKey);
                        node.SetChild(i, false);
                    }

                    node.SetData(i, leaf.GetFilteredValue());
                }
                args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node;
            }
            else
            {
                MyCellCoord child = new MyCellCoord();
                child.Lod = lodIdx - 2 - LeafLodCount;
                var childBase = lodCoord << 1;
                Vector3I childOffset;
                var minInChild = (min >> (lodIdx-1)) - childBase;
                var maxInChild = (max >> (lodIdx-1)) - childBase;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild))
                        continue;

                    child.CoordInLod = childBase + childOffset;
                    WriteRange(ref args, node.GetData(i), lodIdx - 1, child.CoordInLod, ref min, ref max);
                    var childKey = child.PackId64();
                    var childNode = args.Nodes[childKey];
                    if (!childNode.HasChildren && childNode.AllDataSame())
                    {
                        node.SetChild(i, false);
                        node.SetData(i, childNode.GetData(0));
                        args.Nodes.Remove(childKey);
                    }
                    else
                    {
                        node.SetChild(i, true);
                        node.SetData(i, childNode.ComputeFilteredValue(args.DataFilter));
                    }
                }

                args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node;
            }
        }
示例#9
0
        private unsafe void WriteRange(
            MyCellCoord cell,
            TLeafData defaultData,
            MyStorageData source,
            MyStorageDataTypeEnum type,
            ref Vector3I readOffset,
            ref Vector3I min,
            ref Vector3I max)
        {
            var          nodeKey = cell.PackId32();
            MyOctreeNode node;

            if (!m_nodes.TryGetValue(nodeKey, out node))
            {
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    node.Data[i] = defaultData;
                }
            }

            if (cell.Lod == 0)
            {
                var      childBase = cell.CoordInLod << 1;
                Vector3I childOffset;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    var child = childBase + childOffset;
                    if (!child.IsInsideInclusive(ref min, ref max))
                    {
                        continue;
                    }

                    child       -= min;
                    child       += readOffset;
                    node.Data[i] = source.Get(type, ref child);
                }
                m_nodes[nodeKey] = node;
            }
            else
            {
                var      childBase = cell.CoordInLod << 1;
                Vector3I childOffset;
                var      minInChild = (min >> cell.Lod) - childBase;
                var      maxInChild = (max >> cell.Lod) - childBase;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild))
                    {
                        continue;
                    }

                    var childCell = new MyCellCoord(cell.Lod - 1, childBase + childOffset);
                    WriteRange(childCell, node.Data[i], source, type, ref readOffset, ref min, ref max);
                    var childKey  = childCell.PackId32();
                    var childNode = m_nodes[childKey];
                    if (!childNode.HasChildren && MyOctreeNode.AllDataSame(childNode.Data))
                    {
                        node.SetChild(i, false);
                        node.Data[i] = childNode.Data[0];
                        m_nodes.Remove(childKey);
                    }
                    else
                    {
                        node.SetChild(i, true);
                        node.Data[i] = m_nodeFilter(childNode.Data, cell.Lod);
                    }
                }

                m_nodes[nodeKey] = node;
            }
        }
示例#10
0
 internal unsafe void ReadRange <TOperator>(ref TOperator target, MyStorageDataTypeEnum type, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) where TOperator : struct, IVoxelOperator
 {
     try
     {
         MyCellCoord *coordPtr = (MyCellCoord *)stackalloc byte[(((IntPtr)EstimateStackSize(this.m_treeHeight)) * sizeof(MyCellCoord))];
         MyCellCoord  coord    = new MyCellCoord(this.m_treeHeight - 1, ref Vector3I.Zero);
         int          index    = 0 + 1;
         coordPtr[index] = coord;
         while (index > 0)
         {
             coord = coordPtr[--index];
             MyOctreeNode node     = this.m_nodes[coord.PackId32()];
             int          num3     = coord.Lod - lodIndex;
             Vector3I     vectori4 = coord.CoordInLod << 1;
             Vector3I     min      = (minInLod >> num3) - vectori4;
             Vector3I     max      = (maxInLod >> num3) - vectori4;
             for (int i = 0; i < 8; i++)
             {
                 Vector3I vectori;
                 this.ComputeChildCoord(i, out vectori);
                 if (vectori.IsInsideInclusiveEnd(ref min, ref max))
                 {
                     if ((lodIndex < coord.Lod) && node.HasChild(i))
                     {
                         index++;
                         coordPtr[index] = new MyCellCoord(coord.Lod - 1, (Vector3I)(vectori4 + vectori));
                     }
                     else
                     {
                         byte     inOutContent = &node.Data.FixedElementField[i];
                         Vector3I result       = (Vector3I)(vectori4 + vectori);
                         if (num3 == 0)
                         {
                             Vector3I position = (Vector3I)((writeOffset + result) - minInLod);
                             target.Op(ref position, type, ref inOutContent);
                         }
                         else
                         {
                             result = result << num3;
                             Vector3I  vectori7    = (Vector3I)((result + (1 << (num3 & 0x1f))) - 1);
                             Vector3I *vectoriPtr1 = (Vector3I *)ref result;
                             Vector3I.Max(ref (Vector3I) ref vectoriPtr1, ref minInLod, out result);
                             Vector3I *vectoriPtr2 = (Vector3I *)ref vectori7;
                             Vector3I.Min(ref (Vector3I) ref vectoriPtr2, ref maxInLod, out vectori7);
                             int z = result.Z;
                             while (z <= vectori7.Z)
                             {
                                 int y = result.Y;
                                 while (true)
                                 {
                                     if (y > vectori7.Y)
                                     {
                                         z++;
                                         break;
                                     }
                                     int x = result.X;
                                     while (true)
                                     {
                                         if (x > vectori7.X)
                                         {
                                             y++;
                                             break;
                                         }
                                         Vector3I position = writeOffset;
                                         int *    numPtr1  = (int *)ref position.X;
                                         numPtr1[0] += x - minInLod.X;
                                         int *numPtr2 = (int *)ref position.Y;
                                         numPtr2[0] += y - minInLod.Y;
                                         int *numPtr3 = (int *)ref position.Z;
                                         numPtr3[0] += z - minInLod.Z;
                                         target.Op(ref position, type, ref inOutContent);
                                         x++;
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     finally
     {
     }
 }
示例#11
0
        internal unsafe ContainmentType Intersect(ref BoundingBoxI box, int lod, bool exhaustiveContainmentCheck = true)
        {
            MyCellCoord *coordPtr = (MyCellCoord *)stackalloc byte[(((IntPtr)EstimateStackSize(this.m_treeHeight)) * sizeof(MyCellCoord))];
            MyCellCoord  coord    = new MyCellCoord(this.m_treeHeight - 1, ref Vector3I.Zero);
            int          index    = 0 + 1;

            coordPtr[index] = coord;
            Vector3I        min      = box.Min;
            Vector3I        max      = box.Max;
            ContainmentType disjoint = ContainmentType.Disjoint;

            while (index > 0)
            {
                coord = coordPtr[--index];
                MyOctreeNode node     = this.m_nodes[coord.PackId32()];
                int          num3     = coord.Lod;
                Vector3I     vectori6 = coord.CoordInLod << 1;
                Vector3I     vectori4 = (min >> num3) - vectori6;
                Vector3I     vectori5 = (max >> num3) - vectori6;
                for (int i = 0; i < 8; i++)
                {
                    Vector3I vectori3;
                    this.ComputeChildCoord(i, out vectori3);
                    if (vectori3.IsInsideInclusiveEnd(ref vectori4, ref vectori5))
                    {
                        if ((coord.Lod > 0) && node.HasChild(i))
                        {
                            index++;
                            coordPtr[index] = new MyCellCoord(coord.Lod - 1, (Vector3I)(vectori6 + vectori3));
                        }
                        else
                        {
                            byte num5 = &node.Data.FixedElementField[i];
                            if (num3 == 0)
                            {
                                if (num5 != 0)
                                {
                                    return(ContainmentType.Intersects);
                                }
                            }
                            else
                            {
                                BoundingBoxI xi;
                                bool         flag;
                                xi.Min = (Vector3I)(vectori6 + vectori3);
                                Vector3I *vectoriPtr1 = (Vector3I *)ref xi.Min;
                                vectoriPtr1[0] = vectoriPtr1[0] << num3;
                                BoundingBoxI *xiPtr1 = (BoundingBoxI *)ref xi;
                                xiPtr1->Max = (Vector3I)((xi.Min + (1 << (num3 & 0x1f))) - 1);
                                Vector3I.Max(ref xi.Min, ref min, out xi.Min);
                                Vector3I.Min(ref xi.Max, ref max, out xi.Max);
                                ((BoundingBoxI *)ref xi).Intersects(ref xi, out flag);
                                if (flag)
                                {
                                    return(ContainmentType.Intersects);
                                }
                            }
                        }
                    }
                }
            }
            return(disjoint);
        }
示例#12
0
        internal unsafe byte GetFilteredValue()
        {
            MyOctreeNode node = this.m_nodes[this.ComputeRootKey()];

            return(this.m_nodeFilter(&node.Data.FixedElementField, this.m_treeHeight));
        }
示例#13
0
        internal unsafe void DebugDraw(IMyDebugDrawBatchAabb batch, Vector3 worldPos, MyVoxelDebugDrawMode mode)
        {
            Color?nullable;

            if (mode == MyVoxelDebugDrawMode.Content_MicroNodes)
            {
                foreach (KeyValuePair <uint, MyOctreeNode> pair in this.m_nodes)
                {
                    MyCellCoord coord = new MyCellCoord();
                    coord.SetUnpack(pair.Key);
                    MyOctreeNode node = pair.Value;
                    for (int i = 0; i < 8; i++)
                    {
                        if (!node.HasChild(i) || (coord.Lod == 0))
                        {
                            Vector3I     vectori;
                            BoundingBoxD xd;
                            this.ComputeChildCoord(i, out vectori);
                            Vector3I vectori2 = (Vector3I)((coord.CoordInLod << (coord.Lod + 1)) + (vectori << coord.Lod));
                            xd.Min = worldPos + (vectori2 * 1f);
                            BoundingBoxD *xdPtr1 = (BoundingBoxD *)ref xd;
                            xdPtr1->Max = xd.Min + (1f * (1 << (coord.Lod & 0x1f)));
                            if (node.GetData(i) != 0)
                            {
                                nullable = null;
                                batch.Add(ref xd, nullable);
                            }
                        }
                    }
                }
                return;
            }
            else if (mode != MyVoxelDebugDrawMode.Content_MicroNodesScaled)
            {
                return;
            }
            foreach (KeyValuePair <uint, MyOctreeNode> pair2 in this.m_nodes)
            {
                MyCellCoord coord2 = new MyCellCoord();
                coord2.SetUnpack(pair2.Key);
                MyOctreeNode node2 = pair2.Value;
                for (int i = 0; i < 8; i++)
                {
                    if (!node2.HasChild(i))
                    {
                        Vector3I vectori3;
                        this.ComputeChildCoord(i, out vectori3);
                        float num3 = ((float)node2.GetData(i)) / 255f;
                        if (num3 != 0f)
                        {
                            BoundingBoxD xd2;
                            num3 = (float)Math.Pow(num3 * 1.0, 0.3333);
                            Vector3I vectori4 = (Vector3I)((coord2.CoordInLod << (coord2.Lod + 1)) + (vectori3 << coord2.Lod));
                            float    num4     = 1f * (1 << (coord2.Lod & 0x1f));
                            Vector3  vector   = (worldPos + (vectori4 * 1f)) + (0.5f * num4);
                            xd2.Min  = vector - ((0.5f * num3) * num4);
                            xd2.Max  = vector + ((0.5f * num3) * num4);
                            nullable = null;
                            batch.Add(ref xd2, nullable);
                        }
                    }
                }
            }
        }
示例#14
0
        private static void WriteRange(
            ref WriteRangeArgs args,
            byte defaultData,
            int lodIdx,
            Vector3I lodCoord,
            ref Vector3I min,
            ref Vector3I max)
        {
            MyOctreeNode node = new MyOctreeNode();

            {
                MyCellCoord leaf    = new MyCellCoord(lodIdx - LeafLodCount, ref lodCoord);
                var         leafKey = leaf.PackId64();
                if (args.Leaves.ContainsKey(leafKey))
                {
                    args.Leaves.Remove(leafKey);
                    var         childBase = lodCoord << 1;
                    Vector3I    childOffset;
                    MyCellCoord child = new MyCellCoord();
                    child.Lod = leaf.Lod - 1;
                    var leafSize = LeafSizeInVoxels << child.Lod;
                    for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                    {
                        ComputeChildCoord(i, out childOffset);
                        child.CoordInLod = childBase + childOffset;
                        var childCopy = child;
                        childCopy.Lod += LeafLodCount;
                        IMyOctreeLeafNode octreeLeaf = new MyProviderLeaf(args.Provider, args.DataType, ref childCopy);
                        args.Leaves.Add(child.PackId64(), octreeLeaf);
                        node.SetChild(i, true);
                        node.SetData(i, octreeLeaf.GetFilteredValue());
                    }
                }
                else
                {
                    leaf.Lod -= 1; // changes to node coord instead of leaf coord
                    var nodeKey = leaf.PackId64();

                    if (!args.Nodes.TryGetValue(nodeKey, out node))
                    {
                        for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                        {
                            node.SetData(i, defaultData);
                        }
                    }
                }
            }

            if (lodIdx == (LeafLodCount + 1))
            {
                MyCellCoord child            = new MyCellCoord();
                Vector3I    childBase        = lodCoord << 1;
                Vector3I    minInLod         = min >> LeafLodCount;
                Vector3I    maxInLod         = max >> LeafLodCount;
                Vector3I    leafSizeMinusOne = new Vector3I(LeafSizeInVoxels - 1);
                Vector3I    childOffset;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    child.CoordInLod = childBase + childOffset;
                    if (!child.CoordInLod.IsInsideInclusive(ref minInLod, ref maxInLod))
                    {
                        continue;
                    }
                    var childMin = child.CoordInLod << LeafLodCount;
                    var childMax = childMin + LeafSizeInVoxels - 1;
                    Vector3I.Max(ref childMin, ref min, out childMin);
                    Vector3I.Min(ref childMax, ref max, out childMax);
                    var readOffset = childMin - min;
                    IMyOctreeLeafNode leaf;
                    var leafKey      = child.PackId64();
                    var startInChild = childMin - (child.CoordInLod << LeafLodCount);
                    var endInChild   = childMax - (child.CoordInLod << LeafLodCount);

                    args.Leaves.TryGetValue(leafKey, out leaf);

                    byte uniformValue;
                    bool uniformLeaf;
                    {
                        // ensure leaf exists and is writable
                        // the only writable leaf type is MicroOctree at this point

                        byte childDefaultData = node.GetData(i);

                        if (leaf == null)
                        {
                            var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount));
                            octree.BuildFrom(childDefaultData);
                            leaf = octree;
                        }

                        if (leaf.ReadOnly)
                        {
                            var rangeEnd = new Vector3I(LeafSizeInVoxels - 1);
                            m_temporaryCache.Resize(Vector3I.Zero, rangeEnd);
                            leaf.ReadRange(m_temporaryCache, ref Vector3I.Zero, 0, ref Vector3I.Zero, ref rangeEnd);
                            var inCell = startInChild;
                            for (var it2 = new Vector3I.RangeIterator(ref startInChild, ref endInChild);
                                 it2.IsValid(); it2.GetNext(out inCell))
                            {
                                var read = readOffset + (inCell - startInChild);
                                m_temporaryCache.Set(args.DataType, ref inCell, args.Source.Get(args.DataType, ref read));
                            }

                            var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount));
                            octree.BuildFrom(m_temporaryCache);
                            leaf = octree;
                        }
                        else
                        {
                            leaf.WriteRange(args.Source, ref readOffset, ref startInChild, ref endInChild);
                        }

                        uniformLeaf = ((MyMicroOctreeLeaf)leaf).TryGetUniformValue(out uniformValue);
                    }

                    if (!uniformLeaf)
                    {
                        args.Leaves[leafKey] = leaf;
                        node.SetChild(i, true);
                    }
                    else
                    {
                        args.Leaves.Remove(leafKey);
                        node.SetChild(i, false);
                    }

                    node.SetData(i, leaf.GetFilteredValue());
                }
                args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node;
            }
            else
            {
                MyCellCoord child = new MyCellCoord();
                child.Lod = lodIdx - 2 - LeafLodCount;
                var      childBase = lodCoord << 1;
                Vector3I childOffset;
                var      minInChild = (min >> (lodIdx - 1)) - childBase;
                var      maxInChild = (max >> (lodIdx - 1)) - childBase;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild))
                    {
                        continue;
                    }

                    child.CoordInLod = childBase + childOffset;
                    WriteRange(ref args, node.GetData(i), lodIdx - 1, child.CoordInLod, ref min, ref max);
                    var childKey  = child.PackId64();
                    var childNode = args.Nodes[childKey];
                    if (!childNode.HasChildren && childNode.AllDataSame())
                    {
                        node.SetChild(i, false);
                        node.SetData(i, childNode.GetData(0));
                        args.Nodes.Remove(childKey);
                    }
                    else
                    {
                        node.SetChild(i, true);
                        node.SetData(i, childNode.ComputeFilteredValue(args.DataFilter));
                    }
                }

                args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node;
            }
        }