예제 #1
0
 public unsafe void TryClearCell(ulong packedCoord)
 {
     MyNavmeshComponents.CellInfo info;
     if (this.m_triangleLists.ContainsKey(packedCoord))
     {
         this.ClearCachedCell(packedCoord);
     }
     this.RemoveExplored(packedCoord);
     if (this.m_navmeshComponents.TryGetCell(packedCoord, out info))
     {
         for (int i = 0; i < info.ComponentNum; i++)
         {
             int index = info.StartingIndex + i;
             this.m_mesh.HighLevelGroup.RemovePrimitive(index);
         }
         foreach (Base6Directions.Direction direction in Base6Directions.EnumDirections)
         {
             Base6Directions.DirectionFlags directionFlag = Base6Directions.GetDirectionFlag(direction);
             if (info.ExploredDirections.HasFlag(directionFlag))
             {
                 MyNavmeshComponents.CellInfo info2;
                 Vector3I    intVector = Base6Directions.GetIntVector(direction);
                 MyCellCoord coord     = new MyCellCoord();
                 coord.SetUnpack(packedCoord);
                 MyCellCoord *coordPtr1 = (MyCellCoord *)ref coord;
                 coordPtr1->CoordInLod = (Vector3I)(coord.CoordInLod + intVector);
                 if (this.m_navmeshComponents.TryGetCell(coord.PackId64(), out info2))
                 {
                     Base6Directions.DirectionFlags flags2 = Base6Directions.GetDirectionFlag(Base6Directions.GetFlippedDirection(direction));
                     this.m_navmeshComponents.SetExplored(coord.PackId64(), info2.ExploredDirections & ((byte)~flags2));
                 }
             }
         }
         this.m_navmeshComponents.ClearCell(packedCoord, ref info);
     }
 }
예제 #2
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);
        }
예제 #3
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(); }
        }
예제 #4
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
     {
     }
 }
예제 #5
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);
        }
예제 #6
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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }