Example #1
0
        private static bool ResetVoxelInArea(Vector3D Center, float Radius)
        {
            try
            {
                BoundingSphereD    Sphere = new BoundingSphereD(Center, Radius);
                List <MyVoxelBase> Maps   = MyEntities.GetEntitiesInSphere(ref Sphere).OfType <MyVoxelBase>().ToList();
                if (Maps.Count == 0)
                {
                    return(true);
                }

                foreach (var voxelMap in Maps)
                {
                    using (voxelMap.Pin())
                    {
                        if (voxelMap.MarkedForClose)
                        {
                            continue;
                        }
                        MyShapeSphere shape = new MyShapeSphere();
                        shape.Center = Center;
                        shape.Radius = Radius;
                        Vector3I     minCorner;
                        Vector3I     maxCorner;
                        Vector3I     numCells;
                        BoundingBoxD shapeAabb   = shape.GetWorldBoundaries();
                        Vector3I     StorageSize = voxelMap.Storage.Size;
                        MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Min, out minCorner);
                        MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Max, out maxCorner);
                        minCorner   += voxelMap.StorageMin;
                        maxCorner   += voxelMap.StorageMin;
                        maxCorner   += 1;
                        StorageSize -= 1;
                        Vector3I.Clamp(ref minCorner, ref Vector3I.Zero, ref StorageSize, out minCorner);
                        Vector3I.Clamp(ref maxCorner, ref Vector3I.Zero, ref StorageSize, out maxCorner);
                        numCells = new Vector3I((maxCorner.X - minCorner.X) / 16, (maxCorner.Y - minCorner.Y) / 16, (maxCorner.Z - minCorner.Z) / 16);


                        minCorner = Vector3I.Max(Vector3I.One, minCorner);
                        maxCorner = Vector3I.Max(minCorner, maxCorner - Vector3I.One);
                        voxelMap.Storage.DeleteRange(MyStorageDataTypeFlags.ContentAndMaterial, minCorner, maxCorner, false);
                        BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                        MySandboxGame.Static.Invoke(delegate
                        {
                            if (voxelMap.Storage != null)
                            {
                                voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.ContentAndMaterial);
                                MyVoxelGenerator.NotifyVoxelChanged(MyVoxelBase.OperationType.Revert, voxelMap, ref cutOutBox);
                            }
                        }, "RevertShape notify");
                    }
                }
                return(true);
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Voxel reset failed!");
                return(false);
            }
        }
        protected override void Init(MyObjectBuilder_DefinitionBase ob)
        {
            base.Init(ob);

            var objectBuilder = ob as MyObjectBuilder_BlockNavigationDefinition;

            Debug.Assert(ob != null);
            if (ob == null)
            {
                return;
            }

            if (objectBuilder.NoEntry || objectBuilder.Triangles == null)
            {
                NoEntry = true;
            }
            else
            {
                NoEntry = false;
                var newMesh = new MyGridNavigationMesh(null, null, objectBuilder.Triangles.Length);

                Vector3I maxPos = objectBuilder.Size - Vector3I.One - objectBuilder.Center;
                Vector3I minPos = -(Vector3I)(objectBuilder.Center);

                foreach (var triOb in objectBuilder.Triangles)
                {
                    Vector3 pa = (Vector3)triOb.Points[0];
                    Vector3 pb = (Vector3)triOb.Points[1];
                    Vector3 pc = (Vector3)triOb.Points[2];

                    var tri = newMesh.AddTriangle(ref pa, ref pb, ref pc);

                    var center = (pa + pb + pc) / 3.0f;

                    // We want to move the triangle vertices more towards the triangle center to ensure correct calculation of containing cube
                    Vector3  cvA      = (center - pa) * 0.0001f;
                    Vector3  cvB      = (center - pb) * 0.0001f;
                    Vector3  cvC      = (center - pc) * 0.0001f;
                    Vector3I gridPosA = Vector3I.Round(pa + cvA);
                    Vector3I gridPosB = Vector3I.Round(pb + cvB);
                    Vector3I gridPosC = Vector3I.Round(pc + cvC);
                    Vector3I.Clamp(ref gridPosA, ref minPos, ref maxPos, out gridPosA);
                    Vector3I.Clamp(ref gridPosB, ref minPos, ref maxPos, out gridPosB);
                    Vector3I.Clamp(ref gridPosC, ref minPos, ref maxPos, out gridPosC);
                    Vector3I min, max;
                    Vector3I.Min(ref gridPosA, ref gridPosB, out min);
                    Vector3I.Min(ref min, ref gridPosC, out min);
                    Vector3I.Max(ref gridPosA, ref gridPosB, out max);
                    Vector3I.Max(ref max, ref gridPosC, out max);

                    Vector3I pos = min;
                    for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                    {
                        newMesh.RegisterTriangle(tri, ref pos);
                    }
                }

                m_mesh = newMesh;
            }
        }
Example #3
0
 public static void ClampVoxelCoord(this VRage.ModAPI.IMyStorage self, ref Vector3I voxelCoord, int distance = 1)
 {
     if (self != null)
     {
         Vector3I max = self.Size - distance;
         Vector3I.Clamp(ref voxelCoord, ref Vector3I.Zero, ref max, out voxelCoord);
     }
 }
Example #4
0
        private static void RemoveSmallVoxelsUsingChachedVoxels()
        {
            ProfilerShort.Begin("MyVoxelGenerator::RemoveSmallVoxelsUsingChachedVoxels()");
            Vector3I voxel;
            var      cacheSize    = m_cache.Size3D;
            var      sizeMinusOne = cacheSize - 1;

            for (voxel.X = 0; voxel.X < cacheSize.X; voxel.X++)
            {
                for (voxel.Y = 0; voxel.Y < cacheSize.Y; voxel.Y++)
                {
                    for (voxel.Z = 0; voxel.Z < cacheSize.Z; voxel.Z++)
                    {
                        //  IMPORTANT: When doing transformations on 'content' value, cast it to int always!!!
                        //  It's because you can easily forget that result will be negative and if you put negative into byte, it will
                        //  be overflown and you will be surprised by results!!
                        int content = m_cache.Content(ref voxel);

                        //  Check if this is small/invisible voxel (less than 127), but still not empty (more than 0)
                        if ((content > 0) && (content < MyVoxelConstants.VOXEL_ISO_LEVEL))
                        {
                            Vector3I neighborVoxel;
                            Vector3I neighborVoxelMin = voxel - 1;
                            Vector3I neighborVoxelMax = voxel + 1;
                            Vector3I.Clamp(ref neighborVoxelMin, ref Vector3I.Zero, ref sizeMinusOne, out neighborVoxelMin);
                            Vector3I.Clamp(ref neighborVoxelMax, ref Vector3I.Zero, ref sizeMinusOne, out neighborVoxelMax);

                            bool foundNonEmptyVoxel = false;
                            for (neighborVoxel.X = neighborVoxelMin.X; neighborVoxel.X <= neighborVoxelMax.X; neighborVoxel.X++)
                            {
                                for (neighborVoxel.Y = neighborVoxelMin.Y; neighborVoxel.Y <= neighborVoxelMax.Y; neighborVoxel.Y++)
                                {
                                    for (neighborVoxel.Z = neighborVoxelMin.Z; neighborVoxel.Z <= neighborVoxelMax.Z; neighborVoxel.Z++)
                                    {
                                        int neighborContent = m_cache.Content(ref neighborVoxel);

                                        //  Check if this is small/invisible voxel
                                        if (neighborContent >= MyVoxelConstants.VOXEL_ISO_LEVEL)
                                        {
                                            foundNonEmptyVoxel = true;
                                            goto END_NEIGHBOR_LOOP;
                                        }
                                    }
                                }
                            }

END_NEIGHBOR_LOOP:

                            if (foundNonEmptyVoxel == false)
                            {
                                m_cache.Content(ref voxel, MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                            }
                        }
                    }
                }
            }
            ProfilerShort.End();
        }
Example #5
0
        public static void ClampVoxelCoord(this Sandbox.ModAPI.Interfaces.IMyStorage self, ref Vector3I voxelCoord, int distance = 1)
        {
            if (self == null)
            {
                return;
            }
            var sizeMinusOne = self.Size - distance;

            Vector3I.Clamp(ref voxelCoord, ref Vector3I.Zero, ref sizeMinusOne, out voxelCoord);
        }
Example #6
0
        public static void ClampVoxelCoord(this IMyStorage self, ref Vector3I voxelCoord, int distance = 1)
        {
            if (self == null)
            {
                return;
            }
            Vector3I max = self.Size - distance;

            Vector3I.Clamp(ref voxelCoord, ref Vector3I.Zero, ref max, out voxelCoord);
        }
 private static void ComputeShapeBounds(
     ref BoundingBoxD shapeAabb, Vector3D voxelMapMinCorner, Vector3I storageSize,
     out Vector3I voxelMin, out Vector3I voxelMax)
 {
     MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Min, out voxelMin);
     MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Max, out voxelMax);
     voxelMax    += 1;
     storageSize -= 1;
     Vector3I.Clamp(ref voxelMin, ref Vector3I.Zero, ref storageSize, out voxelMin);
     Vector3I.Clamp(ref voxelMax, ref Vector3I.Zero, ref storageSize, out voxelMax);
 }
        public static void Storage_ClampVoxelCoord(this IMyVoxelBase Voxel, ref Vector3I voxelCoord, int distance = 1)
        {
            if (Voxel == null)
            {
                throw new ArgumentNullException(nameof(Voxel));
            }
            if (Voxel.Storage == null)
            {
                throw new ArgumentException("Voxel.Storage is null");
            }

            Vector3I vector3I = Voxel.Storage.Size - distance;

            Vector3I.Clamp(ref voxelCoord, ref Vector3I.Zero, ref vector3I, out voxelCoord);
        }
Example #9
0
        private static void ComputeShapeBounds(MyVoxelBase voxelMap,
                                               ref BoundingBoxD shapeAabb, Vector3D voxelMapMinCorner, Vector3I storageSize,
                                               out Vector3I voxelMin, out Vector3I voxelMax)
        {
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Min, out voxelMin);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMapMinCorner, ref shapeAabb.Max, out voxelMax);
            voxelMin += voxelMap.StorageMin;
            voxelMax += voxelMap.StorageMin;

            voxelMax += 1; //what? why? Another hack of MK?

            storageSize -= 1;
            Vector3I.Clamp(ref voxelMin, ref Vector3I.Zero, ref storageSize, out voxelMin);
            Vector3I.Clamp(ref voxelMax, ref Vector3I.Zero, ref storageSize, out voxelMax);
        }
            /// <summary>
            /// New clipping routine, call on lowest desired lod with position of camera
            /// Should be later enhanced with spread if desired lod would be lower than 0
            /// Finaly it will be used as hint for structure managing cells to be calculated and rendered
            /// </summary>
            /// <param name="localPosition"></param>
            /// <param name="collector"></param>
            internal void DoClipping(Vector3D localPosition, RequestCollector collector, int spread)
            {
                Vector3I min, max;
                {
                    Vector3I center;
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref localPosition, out center);
                    min = center - spread;
                    max = center + spread;
                    Vector3I.Clamp(ref min, ref Vector3I.Zero, ref m_lodSizeMinusOne, out min);
                    Vector3I.Clamp(ref max, ref Vector3I.Zero, ref m_lodSizeMinusOne, out max);
                }
                var it0    = new Vector3I.RangeIterator(ref min, ref max);
                var ignore = BoundingBox.CreateInvalid();

                DoClipping(collector, min, max, ref ignore);
            }
Example #11
0
        public static void ComputeShapeBounds(MyVoxelBase voxelMap, ref BoundingBoxD shapeAabb,
                                              out Vector3I voxelMin, out Vector3I voxelMax)
        {
            var storageSize = voxelMap.Storage.Size;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Min,
                                                          out voxelMin);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Max,
                                                          out voxelMax);
            voxelMin    += voxelMap.StorageMin;
            voxelMax    += voxelMap.StorageMin;
            voxelMax    += 1;
            storageSize -= 1;
            Vector3I.Clamp(ref voxelMin, ref Vector3I.Zero, ref storageSize, out voxelMin);
            Vector3I.Clamp(ref voxelMax, ref Vector3I.Zero, ref storageSize, out voxelMax);
        }
Example #12
0
        /// <summary>
        /// Invalidates voxel cache
        /// </summary>
        /// <param name="minChanged">Inclusive min</param>
        /// <param name="maxChanged">Inclusive max</param>
        public void InvalidateCache(Vector3I minChanged, Vector3I maxChanged)
        {
            minChanged = Vector3I.Clamp(minChanged, Vector3I.Zero, SizeMinusOne);
            maxChanged = Vector3I.Clamp(maxChanged, Vector3I.Zero, SizeMinusOne);
            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("MyVoxelMap::InvalidateCache()");
            Geometry.InvalidateRange(minChanged, maxChanged);
            MyVoxelCacheRender.RemoveCellForVoxels(this, minChanged, maxChanged);

            if (Physics != null)
            {
                Physics.InvalidateRange(minChanged, maxChanged);
            }

            InvalidateRenderObjects(true);
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
Example #13
0
            public Vector3ILineIterator(Vector3I start, Vector3I end)
            {
                if (start == end)
                {
                    throw new ArgumentException("Start and end cannot be equal");
                }

                _start     = start;
                _end       = end;
                Current    = start;
                _direction = Vector3I.Clamp(end - start, -Vector3I.One, Vector3I.One);

                if (_direction.RectangularLength() > 1)
                {
                    throw new ArgumentException("Start and end are not in a straight line");
                }
            }
Example #14
0
        public void OnStorageChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged)
        {
            ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged");

            minChanged = Vector3I.Clamp(minChanged, m_storageMin, m_storageMax);
            maxChanged = Vector3I.Clamp(maxChanged, m_storageMin, m_storageMax);
            Debug.Assert(minChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax) &&
                         maxChanged.IsInsideInclusive(ref m_storageMin, ref m_storageMax));

            // Physics doesn't care about materials, just shape of things.
            if ((dataChanged & MyStorageDataTypeFlags.Content) != 0 &&
                Physics != null)
            {
                Physics.InvalidateRange(minChanged, maxChanged);
            }

            ProfilerShort.End();
        }
        public static void MyVoxelGenerator_ComputeShapeBounds(this IMyVoxelBase VoxelMap, ref BoundingBoxD shapeAabb, out Vector3I voxelMin, out Vector3I voxelMax)
        {
            if (VoxelMap == null)
            {
                throw new ArgumentNullException(nameof(VoxelMap));
            }
            if (VoxelMap.Storage == null)
            {
                throw new ArgumentException("Voxel.Storage is null");
            }

            MyVoxelBase voxelMap    = VoxelMap as MyVoxelBase;
            Vector3I    storageSize = voxelMap.Storage.Size;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Min, out voxelMin);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeAabb.Max, out voxelMax);
            voxelMin    += voxelMap.StorageMin;
            voxelMax    += voxelMap.StorageMin;
            voxelMax    += 1;
            storageSize -= 1;
            Vector3I.Clamp(ref voxelMin, ref Vector3I.Zero, ref storageSize, out voxelMin);
            Vector3I.Clamp(ref voxelMax, ref Vector3I.Zero, ref storageSize, out voxelMax);
        }
Example #16
0
        public static void CutOutShape(
            MyVoxelMap voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            float removeRatio = 1,
            Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync = true,
            bool onlyCheck  = false)
        {
            Profiler.Begin("MyVoxelGenerator::CutOutShape()");

            if (updateSync && Sync.IsServer)
            {
                shape.SendCutOutRequest(voxelMap.SyncObject, removeRatio);
            }

            int originalSum = 0;
            int removedSum  = 0;

            Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMin());
            Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMax());

            voxelMap.FixVoxelCoord(ref minCorner);
            voxelMap.FixVoxelCoord(ref maxCorner);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            voxelMap.FixVoxelCoord(ref cacheMin);
            voxelMap.FixVoxelCoord(ref cacheMax);
            m_cache.Resize(ref cacheMin, ref cacheMax);
            voxelMap.Storage.ReadRange(m_cache, true, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref cacheMin, ref cacheMax);

            {
                Vector3I exactCenter = voxelMap.GetVoxelCoordinateFromMeters(shape.GetCenter());
                exactCenter  -= cacheMin;
                exactCenter   = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1);
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter));
            }

            Vector3I tempVoxelCoord;

            for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++)
            {
                for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++)
                {
                    for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++)
                    {
                        var relPos   = tempVoxelCoord - cacheMin; // get original amount
                        var original = m_cache.Content(ref relPos);

                        if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                        {
                            continue;
                        }

                        var vpos   = voxelMap.GetVoxelPositionAbsolute(ref tempVoxelCoord);
                        var volume = shape.GetVolume(ref vpos);

                        if (volume == 0f) // if there is no intersection
                        {
                            continue;
                        }

                        var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                        var voxelMat  = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
                        var toRemove  = (int)(maxRemove * removeRatio * voxelMat.DamageRatio);
                        if (voxelMap.Storage is MyCellStorage)
                        {
                            if (toRemove < MyCellStorage.Quantizer.GetMinimumQuantizableValue())
                            {
                                toRemove = MyCellStorage.Quantizer.GetMinimumQuantizableValue();
                            }
                        }
                        var newVal  = MathHelper.Clamp(original - toRemove, 0, maxRemove);
                        var removed = Math.Abs(original - newVal);

                        if (!onlyCheck)
                        {
                            m_cache.Content(ref relPos, (byte)newVal);
                        }

                        originalSum += original;
                        removedSum  += removed;

                        if (exactCutOutMaterials != null)
                        {
                            int value = 0;
                            exactCutOutMaterials.TryGetValue(voxelMat, out value);
                            value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                            exactCutOutMaterials[voxelMat] = value;
                        }
                    }
                }
            }

            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                RemoveSmallVoxelsUsingChachedVoxels();

                voxelMap.Storage.WriteRange(m_cache, true, false, ref cacheMin, ref cacheMax);
                voxelMap.InvalidateCache(cacheMin, cacheMax);
            }
            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;
            Profiler.End();
        }
Example #17
0
            internal void DoClipping(Vector3D localPosition, float farPlaneDistance, RequestCollector collector)
            {
                MyClipmap.ComputeLodViewBounds(m_parent.m_scaleGroup, m_lodIndex, out m_nearDistance, out m_farDistance);

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum)
                {
                    return;
                }

                Vector3I min, max;

                {
                    var minD = localPosition - m_farDistance;
                    var maxD = localPosition + m_farDistance;
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minD, out min);
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxD, out max);
                    Vector3I.Clamp(ref min, ref Vector3I.Zero, ref m_lodSizeMinusOne, out min);
                    Vector3I.Clamp(ref max, ref Vector3I.Zero, ref m_lodSizeMinusOne, out max);
                }

                if (m_lastMin == min && m_lastMax == max && !m_parent.m_updateClipping)
                {
                    return;
                }

                m_lastMin = min;
                m_lastMax = max;

                LodLevel parentLod, childLod;

                GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.
                MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                m_storedCellData.Clear();
                MyCellCoord cell = new MyCellCoord(m_lodIndex, ref min);

                for (var it = new Vector3I.RangeIterator(ref min, ref max);
                     it.IsValid(); it.GetNext(out cell.CoordInLod))
                {
                    if (!WasAncestorCellLoaded(parentLod, ref cell))
                    {
                        continue;
                    }

                    var      cellId = cell.PackId64();
                    CellData data;
                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        data = new CellData();
                    }

                    if (data.State == CellState.Invalid)
                    {
                        collector.AddRequest(cellId, data.WasLoaded);
                        data.State = CellState.Pending;
                    }
                    m_storedCellData.Add(cellId, data);
                }
            }
Example #18
0
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync = false,
            bool onlyCheck  = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial        = null;
                return;
            }

            ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()");

            int originalSum = 0;
            int removedSum  = 0;

            // Some shapes just ignore transforms so we round the bbox conservativelly by converting it to sphere
            var bbox   = shape.GetWorldBoundaries();
            var center = bbox.Center;
            var radius = (center - bbox.Min).Length();

            MatrixD mat = voxelMap.PositionComp.WorldMatrix;
            MatrixD inverse;

            //Vector3D translation = mat.Translation;
            //mat.Translation = Vector3D.Zero;

            // invert is used to bring voxel coordinates back to world.
            inverse = voxelMap.PositionComp.WorldMatrixInvScaled;//MatrixD.Invert(ref mat, out inverse);

            Vector3 offset = voxelMap.StorageMin + voxelMap.SizeInMetresHalf;

            Vector3D.Transform(ref center, ref inverse, out center);

            // The transform is centered, but the code expects voxel local coordinates.
            center += voxelMap.SizeInMetresHalf;

            bbox = new BoundingBoxD(center - radius, center + radius);

            Vector3I minCorner, maxCorner;

            ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax);

            {
                var      shapeCenter = bbox.Center;
                Vector3I exactCenter;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(Vector3.Zero, ref shapeCenter, out exactCenter);
                exactCenter  -= cacheMin;
                exactCenter   = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1);
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter));
            }

            ProfilerShort.Begin("Main loop");
            for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext())
            {
                var relPos   = it.Current - cacheMin; // get original amount
                var original = m_cache.Content(ref relPos);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                {
                    continue;
                }

                Vector3D vpos;
                MyVoxelCoordSystems.VoxelCoordToLocalPosition(ref it.Current, out vpos);

                // center
                vpos -= offset;

                // transform back to world space.
                Vector3D.Transform(ref vpos, ref mat, out vpos);

                var volume = shape.GetVolume(ref vpos);

                if (volume == 0f) // if there is no intersection
                {
                    continue;
                }

                var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var voxelMat  = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
                var toRemove  = (int)(maxRemove * voxelMat.DamageRatio);
                var newVal    = MathHelper.Clamp(original - toRemove, 0, original - maxRemove);
                var removed   = Math.Abs(original - newVal);

                if (!onlyCheck)
                {
                    m_cache.Content(ref relPos, (byte)newVal);
                }

                originalSum += original;
                removedSum  += removed;

                if (exactCutOutMaterials != null)
                {
                    int value = 0;
                    exactCutOutMaterials.TryGetValue(voxelMat, out value);
                    value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                    exactCutOutMaterials[voxelMat] = value;
                }
            }

            if (removedSum > 0 && updateSync && Sync.IsServer)
            {
                shape.SendDrillCutOutRequest(voxelMap);
            }

            ProfilerShort.BeginNextBlock("Write");


            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                RemoveSmallVoxelsUsingChachedVoxels();

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
            }
            ProfilerShort.End();


            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;

            if (removedSum > 0)
            {
                CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape);
            }

            ProfilerShort.End();
        }
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync = false,
            bool onlyCheck  = false)
        {
            ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()");

            int originalSum = 0;
            int removedSum  = 0;

            var      bbox = shape.GetWorldBoundaries();
            Vector3I minCorner, maxCorner;

            ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax);

            {
                var      shapeCenter = bbox.Center;
                Vector3I exactCenter;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeCenter, out exactCenter);
                exactCenter  -= cacheMin;
                exactCenter   = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1);
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter));
            }

            for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext())
            {
                var relPos   = it.Current - cacheMin; // get original amount
                var original = m_cache.Content(ref relPos);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                {
                    continue;
                }

                Vector3D vpos;
                MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                var volume = shape.GetVolume(ref vpos);

                if (volume == 0f) // if there is no intersection
                {
                    continue;
                }

                var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var voxelMat  = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
                var toRemove  = (int)(maxRemove * voxelMat.DamageRatio);
                var newVal    = MathHelper.Clamp(original - toRemove, 0, maxRemove);
                var removed   = Math.Abs(original - newVal);

                if (!onlyCheck)
                {
                    m_cache.Content(ref relPos, (byte)newVal);
                }

                originalSum += original;
                removedSum  += removed;

                if (exactCutOutMaterials != null)
                {
                    int value = 0;
                    exactCutOutMaterials.TryGetValue(voxelMat, out value);
                    value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                    exactCutOutMaterials[voxelMat] = value;
                }
            }

            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                RemoveSmallVoxelsUsingChachedVoxels();

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
            }

            if (removedSum > 0 && updateSync && Sync.IsServer)
            {
                shape.SendDrillCutOutRequest(voxelMap.SyncObject);
            }

            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;
            ProfilerShort.End();
        }
Example #20
0
        private void ClampCellCoord(ref Vector3I cellCoord)
        {
            var dataCellsCountMinusOne = m_cellsCount - 1;

            Vector3I.Clamp(ref cellCoord, ref Vector3I.Zero, ref dataCellsCountMinusOne, out cellCoord);
        }
Example #21
0
        //  If voxel coord0 (in voxel units, not meters) is outside of the voxelmap, we fix its coordinate so it lie in the voxelmap.
        public void FixVoxelCoord(ref Vector3I voxelCoord)
        {
            var sizeMinusOne = Storage.Size - 1;

            Vector3I.Clamp(ref voxelCoord, ref Vector3I.Zero, ref sizeMinusOne, out voxelCoord);
        }
Example #22
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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        public static bool DoGrading(
            IReadOnlyList <IRailGradeComponent> components, Vector3D target, float radius, uint availableForDeposit,
            uint availableForExcavate,
            uint[] excavatedByMaterial, byte materialToDeposit, out uint totalDeposited, out uint totalExcavated,
            bool testDynamic, out bool triedToChange, out bool intersectedDynamic)
        {
            try
            {
                var voxelRadius = (int)Math.Ceiling(radius);
                {
                    _dynamicEntities.Clear();
                    _workingVoxels.Clear();
                    var sphere = new BoundingSphereD(target, voxelRadius + 2);
                    var tmp    = MyEntities.GetEntitiesInSphere(ref sphere);
                    using (tmp.GetClearToken())
                        foreach (var e in tmp)
                        {
                            if (e is MyVoxelBase vox)
                            {
                                _workingVoxels.Add(vox);
                            }
                            if (e.Physics != null && !e.Physics.IsStatic)
                            {
                                _dynamicEntities.Add(e);
                            }
                        }
                }


                totalDeposited     = 0;
                totalExcavated     = 0;
                triedToChange      = false;
                intersectedDynamic = false;

                var fill     = new IGradeShape[components.Count];
                var excavate = new IGradeShape[components.Count];
                for (var i = 0; i < components.Count; i++)
                {
                    components[i].Unblit(out fill[i], out excavate[i]);
                }

                var voxel = MyGamePruningStructureSandbox.GetClosestPlanet(target)?.RootVoxel;
                if (voxel == null)
                {
                    return(false);
                }
                Vector3I center;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref target, out center);
                var voxMin = center - voxelRadius - 1;
                var voxMax = center + voxelRadius + 1;
                _storage.Resize(voxMin, voxMax);
                voxel.Storage.ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, 0, voxMin, voxMax);

                var changed = false;

                #region Mutate

                for (var i = 0;
                     i <= voxelRadius && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0);
                     i++)
                {
                    for (var e = new ShellEnumerator(center - i, center + i);
                         e.MoveNext() && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0);)
                    {
                        var      vCoord    = e.Current;
                        var      dataCoord = e.Current - voxMin;
                        Vector3D worldCoord;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref vCoord,
                                                                      out worldCoord);
                        var cval = _storage.Get(MyStorageDataTypeEnum.Content, ref dataCoord);

                        byte?excavationDensity = null;
                        if (cval > 0 && (!triedToChange || availableForExcavate > 0))
                        {
                            float density = 0;
                            foreach (var c in excavate.Where(x => x != null))
                            {
                                density = Math.Max(density, c.GetDensity(ref worldCoord));
                            }
                            if (density > 0)
                            {
                                excavationDensity = (byte)((1 - density) * byte.MaxValue);
                            }
                        }

                        byte?fillDensity = null;
                        if (cval < byte.MaxValue && (!triedToChange || availableForDeposit > 0))
                        {
                            float density = 0;
                            foreach (var c in fill.Where(x => x != null))
                            {
                                density = Math.Max(density, c.GetDensity(ref worldCoord));
                            }
                            if (density > 0)
                            {
                                fillDensity = (byte)(density * byte.MaxValue);
                            }
                        }

                        if ((!fillDensity.HasValue || cval >= fillDensity.Value) &&
                            (!excavationDensity.HasValue || cval <= excavationDensity.Value))
                        {
                            continue;
                        }

                        if (excavationDensity.HasValue && excavationDensity.Value < cval)
                        {
                            triedToChange = true;
                            var toExtract = (uint)Math.Min(availableForExcavate, cval - excavationDensity.Value);
                            if (toExtract > 0)
                            {
                                var mid = _storage.Get(MyStorageDataTypeEnum.Material, ref dataCoord);
                                if (excavatedByMaterial != null && mid < excavatedByMaterial.Length)
                                {
                                    excavatedByMaterial[mid] += toExtract;
                                }
                                DisableFarming(worldCoord);
                                _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval - toExtract));
                                totalExcavated       += toExtract;
                                availableForExcavate -= toExtract;
                                changed = true;
                            }

                            continue;
                        }

                        if (!fillDensity.HasValue || fillDensity.Value <= cval)
                        {
                            continue;
                        }
                        triedToChange = true;
                        var toFill = Math.Min(availableForDeposit, fillDensity.Value - cval);
                        if (toFill <= 0)
                        {
                            continue;
                        }

                        // would this deposit in midair?
                        {
                            var test = worldCoord;
                            test += 2 * Vector3D.Normalize(
                                MyGravityProviderSystem.CalculateNaturalGravityInPoint(worldCoord));
                            Vector3I vtest;
                            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref test,
                                                                          out vtest);
                            vtest = Vector3I.Clamp(vtest, voxMin, voxMax) - voxMin;
                            if (vtest != vCoord && _storage.Get(MyStorageDataTypeEnum.Content, ref vtest) == 0)
                            {
                                continue;
                            }
                        }

                        // would it touch something dynamic?
                        if (testDynamic)
                        {
                            var box = new BoundingBoxD(worldCoord - 0.25, worldCoord + 0.25);
                            var bad = false;
                            foreach (var k in _dynamicEntities)
                            {
                                if (k.PositionComp.WorldAABB.Contains(box) == ContainmentType.Disjoint)
                                {
                                    continue;
                                }
                                var obb = new OrientedBoundingBoxD(k.PositionComp.LocalAABB, k.WorldMatrix);
                                if (!obb.Intersects(ref box))
                                {
                                    continue;
                                }
                                bad = true;
                                break;
                            }

                            if (bad)
                            {
                                intersectedDynamic = true;
                                continue;
                            }
                        }

                        changed = true;
                        DisableFarming(worldCoord);
                        availableForDeposit = (uint)(availableForDeposit - toFill);
                        totalDeposited     += (uint)toFill;
                        _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval + toFill));
                        if (fillDensity.Value <= cval * 1.25f)
                        {
                            continue;
                        }
                        var t = -Vector3I.One;
                        for (var itrContent = new Vector3I_RangeIterator(ref t, ref Vector3I.One);
                             itrContent.IsValid();
                             itrContent.MoveNext())
                        {
                            var tpos = dataCoord + itrContent.Current;
//                    var state = _storage.Get(MyStorageDataTypeEnum.Content, ref tpos);
//                    if (itrContent.Current == Vector3I.Zero || state == 0)
                            _storage.Set(MyStorageDataTypeEnum.Material, ref tpos, materialToDeposit);
                        }
                    }
                }

                #endregion Mutate

                if (changed)
                {
                    voxel.Storage.WriteRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, voxMin, voxMax);
                }

                return(changed);
            }
            finally
            {
                _dynamicEntities.Clear();
                _workingVoxels.Clear();
            }
        }
Example #24
0
        private void ClampCellCoord(ref Vector3I cellCoord)
        {
            Vector3I max = this.m_cellsCount - 1;

            Vector3I.Clamp(ref cellCoord, ref Vector3I.Zero, ref max, out cellCoord);
        }
Example #25
0
            /// <summary>
            /// Start the reads if it is not already running.
            /// </summary>
            /// <param name="onFinished">Invoked when reads finish, not invoked if already running.</param>
            /// <returns>True if started, false if already running.</returns>
            public void Read()
            {
                Profiler.StartProfileBlock();
                m_throwOutVoxelData = Globals.ElapsedTime + Static.LifeSpan_VoxelData;

                NeedsUpdate = false;
                Vector3D m_oreDetectorPosition = m_oreDetector.GetPosition();
                Vector3D worldMin = m_oreDetectorPosition - m_maxRange;
                Vector3D worldMax = m_oreDetectorPosition + m_maxRange;

                float rangeSquared = m_maxRange * m_maxRange;

                Vector3I odPosVoxelStorage, m_localMin, m_localMax;

                MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref m_oreDetectorPosition, out odPosVoxelStorage);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref worldMin, out m_localMin);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref worldMax, out m_localMax);

                MyVoxelBase vox = m_voxel as MyVoxelBase;

                if (m_voxel == null || m_voxel.Storage == null)
                {
                    Profiler.EndProfileBlock();
                    return;
                }

                m_localMin          = Vector3I.Clamp(m_localMin, vox.StorageMin, vox.StorageMax);
                m_localMax          = Vector3I.Clamp(m_localMax, vox.StorageMin, vox.StorageMax);
                m_localMin        >>= QUERY_LOD;
                m_localMax        >>= QUERY_LOD;
                odPosVoxelStorage >>= QUERY_LOD;
                Log.DebugLog("minLocal: " + m_localMin + ", maxLocal: " + m_localMax + ", odPosVoxelStorage: " + odPosVoxelStorage);

                Vector3I size = m_localMax - m_localMin;

                Log.DebugLog("number of coords in box: " + (size.X + 1) * (size.Y + 1) * (size.Z + 1));
                //ulong processed = 0;
                foreach (List <Vector3I> locations in m_materialLocations2.Values)
                {
                    locations.Clear();
                }

                Vector3I vector = new Vector3I();

                for (vector.X = m_localMin.X; vector.X < m_localMax.X; vector.X += QUERY_STEP)
                {
                    for (vector.Y = m_localMin.Y; vector.Y < m_localMax.Y; vector.Y += QUERY_STEP)
                    {
                        for (vector.Z = m_localMin.Z; vector.Z < m_localMax.Z; vector.Z += QUERY_STEP)
                        {
                            if (vector.DistanceSquared(odPosVoxelStorage) <= rangeSquared)
                            {
                                m_voxel.Storage.ReadRange(m_storage, MyStorageDataTypeFlags.ContentAndMaterial, QUERY_LOD, vector, vector + QUERY_MAX);

                                Vector3I index  = Vector3I.Zero;
                                Vector3I size3D = m_storage.Size3D;
                                for (index.X = 0; index.X < size3D.X; index.X++)
                                {
                                    for (index.Y = 0; index.Y < size3D.Y; index.Y++)
                                    {
                                        for (index.Z = 0; index.Z < size3D.Z; index.Z++)
                                        {
                                            int linear = m_storage.ComputeLinear(ref index);
                                            if (m_storage.Content(linear) > MyVoxelConstants.VOXEL_ISO_LEVEL)
                                            {
                                                byte mat = m_storage.Material(linear);
                                                if (Static.RareMaterials[mat])
                                                {
                                                    //Log.DebugLog("mat: " + mat + ", content: " + m_storage.Content(linear) + ", vector: " + vector + ", position: " + vector + index
                                                    //	+ ", name: " + MyDefinitionManager.Static.GetVoxelMaterialDefinition(mat).MinedOre, "Read()");
                                                    //m_materialLocations[vector + index] = mat;

                                                    List <Vector3I> locations;
                                                    if (!m_materialLocations2.TryGetValue(mat, out locations))
                                                    {
                                                        locations = new List <Vector3I>(1000);
                                                        m_materialLocations2.Add(mat, locations);
                                                    }
                                                    locations.Add(vector + index);

                                                    //processed++;
                                                    goto Finished_Deposit;
                                                }
                                            }
                                        }
                                    }
                                }

                                Finished_Deposit :;
                                //processed++;
                            }
                        }
                    }
                }

                //Log.DebugLog("read " + processed + ", chunks" + ", number of mats: " + m_materialLocations.Count, Logger.severity.DEBUG);
                Profiler.EndProfileBlock();
            }
            /// <summary>
            /// Recursive clipping function requests cells in provided range and
            /// cells needed from parent to wrap the lod safely
            /// </summary>
            /// <param name="collector"></param>
            /// <param name="it0">requested range</param>
            /// <param name="ignore">inner range filled by children</param>
            private void DoClipping(RequestCollector collector, Vector3I min, Vector3I max, ref BoundingBox ignore)
            {
                LodLevel parentLod, clevel;

                GetNearbyLodLevels(out parentLod, out clevel);
                MyCellCoord cell = new MyCellCoord(m_lodIndex, Vector3I.Zero);

                //if (collector.SentRequestsEmpty)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                var it0 = new Vector3I.RangeIterator(ref min, ref max);

                cell.CoordInLod = it0.Current;

                var shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(cell.Lod);
                var parentCell    = parentLod != null ? new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent) : cell;
                var parentIgnore  = new BoundingBox(parentCell.CoordInLod, parentCell.CoordInLod);

                BoundingBox bb = new BoundingBox(cell.CoordInLod, cell.CoordInLod);

                for (; it0.IsValid(); it0.GetNext(out cell.CoordInLod)) //cells to be loaded
                {
                    if (ignore.Contains((Vector3)cell.CoordInLod) == ContainmentType.Contains)
                    {
                        continue; //lower lod requested
                    }

                    if (parentLod != null) //get also their lodcell mates
                    {
                        parentCell = new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent);
                        var it = GetChildrenCoords(this, ref parentCell);
                        bb.Include(it);
                        parentIgnore.Max = parentCell.CoordInLod;
                    }
                }
                if (parentLod != null)
                {
                    Vector3I parentMinI = Vector3I.Round(parentIgnore.Min - Vector3.One);
                    Vector3I parentMaxI = Vector3I.Round(parentIgnore.Max + Vector3.One);
                    //Vector3I.Clamp(ref parentMinI, ref Vector3I.Zero, ref m_lodSizeMinusOne, out parentMinI);
                    //Vector3I.Clamp(ref parentMaxI, ref Vector3I.Zero, ref m_lodSizeMinusOne, out parentMaxI);
                    var parentIterator = new Vector3I.RangeIterator(ref parentMinI, ref parentMaxI);
                    parentLod.DoClipping(collector, parentMinI, parentMaxI, ref parentIgnore);
                }

                Vector3I start, end;

                start = Vector3I.Round(bb.Min); end = Vector3I.Round(bb.Max);
                Vector3I.Clamp(ref start, ref Vector3I.Zero, ref m_lodSizeMinusOne, out start);
                Vector3I.Clamp(ref end, ref Vector3I.Zero, ref m_lodSizeMinusOne, out end);
                it0             = new Vector3I.RangeIterator(ref start, ref end);
                cell.CoordInLod = it0.Current;
                for (; it0.IsValid(); it0.GetNext(out cell.CoordInLod)) //cells to be loaded
                {
                    if (ignore.Contains((Vector3)cell.CoordInLod) == ContainmentType.Contains)
                    {
                        continue; //lower lod requested
                    }

                    var cellId = cell.PackId64();

                    CellData data;
                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);

                        data = CellsCache.Read(clipmapCellId);

                        if (data == null) //cache miss
                        {
                            data = new CellData();
                            ClippingCacheMisses++;
                        }
                        else
                        {
                            //cache hit
                            ClippingCacheHits++;

                            data.InScene = false;
                            if (data.Cell != null)
                            {
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }

                    if (data.State == CellState.Invalid)
                    {
                        if (!TryAddCellRequest(collector, parentLod, cell, cellId, data))
                        {
                            continue;
                        }
                    }
                    if (!m_storedCellData.ContainsKey(cellId))
                    {
                        m_storedCellData.Add(cellId, data);
                    }
                }
            }