示例#1
0
        public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;

            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner);

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos = it.Current - cellMinCorner;

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    float volume = shape.GetVolume(ref vpos);
                    if (volume > 0.5f)
                    {
                        m_cache.Material(ref relPos, materialIdx); // set material
                    }
                }

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner);
            }
        }
示例#2
0
        private static void GetVoxelShapeDimensions(MyVoxelBase voxelMap, MyShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells)
        {
            BoundingBoxD worldBoundaries = shape.GetWorldBoundaries();

            ComputeShapeBounds(voxelMap, ref worldBoundaries, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner);
            numCells = new Vector3I((maxCorner.X - minCorner.X) / 0x10, (maxCorner.Y - minCorner.Y) / 0x10, (maxCorner.Z - minCorner.Z) / 0x10);
        }
        public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape)
        {
            Vector3I minCorner, maxCorner, numCells;

            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);
            ulong changedVolumeAmount = 0;

            for (var itCells = new Vector3I.RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                var cacheMin = cellMinCorner - 1;
                var cacheMax = cellMaxCorner + 1;
                voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
                voxelMap.Storage.ClampVoxelCoord(ref cacheMax);

                ulong removedSum = 0;
                m_cache.Resize(cacheMin, cacheMax);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax);

                for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); 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   toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL));
                    var   newVal   = Math.Min(toRemove, original);
                    ulong removed  = (ulong)Math.Abs(original - newVal);

                    m_cache.Content(ref relPos, (byte)newVal);
                    removedSum += removed;
                }

                if (removedSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
                }

                changedVolumeAmount += removedSum;
            }

            return(changedVolumeAmount);
        }
示例#4
0
 private static void GetVoxelShapeDimensions(MyVoxelBase voxelMap, MyShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells)
 {
     {
         var bbox = shape.GetWorldBoundaries();
         ComputeShapeBounds(voxelMap, ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner);
     }
     numCells = new Vector3I((maxCorner.X - minCorner.X) / CELL_SIZE, (maxCorner.Y - minCorner.Y) / CELL_SIZE, (maxCorner.Z - minCorner.Z) / CELL_SIZE);
 }
示例#5
0
        public static void RequestCutOutShape(IMyVoxelBase voxelMap, IMyVoxelShape voxelShape)
        {
            MyVoxelBase voxelbool = voxelMap as MyVoxelBase;
            MyShape     shape     = voxelShape as MyShape;

            if ((voxelbool != null) && (shape != null))
            {
                shape.SendCutOutRequest(voxelbool);
            }
        }
示例#6
0
        public static void RequestPaintInShape(IMyVoxelBase voxelMap, IMyVoxelShape voxelShape, byte materialIdx)
        {
            MyVoxelBase voxel = voxelMap as MyVoxelBase;
            MyShape     shape = voxelShape as MyShape;

            if ((voxel != null) && (shape != null))
            {
                shape.SendPaintRequest(voxel, materialIdx);
            }
        }
示例#7
0
        public static void RequestRevertShape(IMyVoxelBase voxelMap, IMyVoxelShape voxelShape)
        {
            MyVoxelBase voxel = voxelMap as MyVoxelBase;
            MyShape     shape = voxelShape as MyShape;

            if ((voxel != null) && (shape != null))
            {
                shape.SendRevertRequest(voxel);
            }
        }
示例#8
0
 public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
 {
     using (voxelMap.Pin())
     {
         if (!voxelMap.MarkedForClose)
         {
             Vector3I vectori;
             Vector3I maxCorner;
             Vector3I minCorner;
             GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
             if (m_cache == null)
             {
                 m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
             }
             Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori);
             while (true)
             {
                 Vector3I vectori2;
                 Vector3I vectori3;
                 if (!it.IsValid())
                 {
                     MySandboxGame.Static.Invoke(delegate {
                         if (voxelMap.Storage != null)
                         {
                             voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                         }
                     }, "PaintInShape notify");
                     break;
                 }
                 GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3);
                 m_cache.Resize(vectori2, vectori3);
                 MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;
                 voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent);
                 Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3);
                 while (true)
                 {
                     Vector3D vectord;
                     if (!iterator2.IsValid())
                     {
                         voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, vectori2, vectori3, false, true);
                         it.MoveNext();
                         break;
                     }
                     Vector3I p = iterator2.Current - vectori2;
                     MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord);
                     if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff))
                     {
                         m_cache.Material(ref p, materialIdx);
                     }
                     iterator2.MoveNext();
                 }
             }
         }
     }
 }
示例#9
0
        private static void OnVoxelChanged(OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            if (Sync.IsServer)
            {
                BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                cutOutBox.Inflate(0.25);

                MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList);
                // Check static grids around (possible change to dynamic)
                if (/*MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL &&*/ MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
                {
                    foreach (var entity in m_overlapList)
                    {
                        var grid = entity as MyCubeGrid;
                        if (grid != null && grid.IsStatic)
                        {
                            if (grid.Physics != null && grid.Physics.Shape != null)
                            {
                                grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                            }

                            if (type == OperationType.Cut)
                            {
                                grid.TestDynamic = MyCubeGrid.MyTestDynamicReason.GridSplit;
                            }
                        }
                    }
                }
            }
            var      voxelPhysics = voxelMap as MyVoxelPhysics;
            MyPlanet planet       = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet;

            if (planet != null)
            {
                var planetEnvironment = planet.Components.Get <MyPlanetEnvironmentComponent>();
                if (planetEnvironment != null)
                {
                    var sectors = planetEnvironment.GetSectorsInRange(shape);
                    if (sectors != null)
                    {
                        foreach (var sector in sectors)
                        {
                            sector.DisableItemsInShape(shape);
                        }
                    }
                }
            }
            m_overlapList.Clear();
        }
示例#10
0
 public static void RevertShape(MyVoxelBase voxelMap, MyShape shape)
 {
     using (voxelMap.Pin())
     {
         if (!voxelMap.MarkedForClose)
         {
             Vector3I vectori;
             Vector3I maxCorner;
             Vector3I minCorner;
             GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
             minCorner = Vector3I.Max(Vector3I.One, minCorner);
             maxCorner = Vector3I.Max(minCorner, maxCorner - Vector3I.One);
             voxelMap.Storage.DeleteRange(MyStorageDataTypeFlags.All, minCorner, maxCorner, false);
             BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
             MySandboxGame.Static.Invoke(delegate {
                 if (voxelMap.Storage != null)
                 {
                     voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                     NotifyVoxelChanged(MyVoxelBase.OperationType.Revert, voxelMap, ref cutOutBox);
                 }
             }, "RevertShape notify");
         }
     }
 }
        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();
        }
示例#12
0
        private static void OnVoxelChanged(OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            if (Sync.IsServer)
            {
            BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
            cutOutBox.Inflate(0.25);

            MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList);
            // Check static grids around (possible change to dynamic)
            if (/*MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL &&*/ MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
            {
                foreach (var entity in m_overlapList)
                {
                    var grid = entity as MyCubeGrid;
                    if (grid != null && grid.IsStatic)
                    {
                        if (grid.Physics != null && grid.Physics.Shape != null)
                        {
                            grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                        }

                        if (type == OperationType.Cut)
                            grid.TestDynamic = true;
                    }
                }

            }
            }
            var voxelPhysics = voxelMap as MyVoxelPhysics;
            MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet;
            if (planet != null)
            {
                var planetEnvironment = planet.Components.Get<MyPlanetEnvironmentComponent>();
                if (planetEnvironment != null)
                {
                    var sectors = planetEnvironment.GetSectorsInRange(shape);
                    if (sectors != null)
                        foreach (var sector in sectors)
                            sector.DisableItemsInShape(shape);
                }
            }
            m_overlapList.Clear();
        }
示例#13
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,
            bool applyDamageMaterial = false,
            bool onlyApplyMaterial = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial = null;
                return;
            }

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

            int originalSum = 0;
            int removedSum = 0;
            bool materials = exactCutOutMaterials != null;

            // Bring the shape into voxel space.
            var oldTranmsform = shape.Transformation;
            var newTransf = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled;
            newTransf.Translation += voxelMap.SizeInMetresHalf;
            shape.Transformation = newTransf;

            // This boundary should now be in our local space
            var bbox = shape.GetWorldBoundaries();

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

            bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial;

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

            //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf
            /*const int SHIFT = 4;
            const int REM = (1 << SHIFT) - 1;
            const int MASK = ~REM;
            cacheMin &= MASK;
            cacheMax = (cacheMax + REM) & MASK;*/

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            m_cache.ClearMaterials(0);

            // Advise that the read content shall be cached
            MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache;
            voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags);

            Vector3I center;
            if (materials)
            {
                center = m_cache.Size3D / 2;
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center));
            }
            else
            {
                center = (cacheMin + cacheMax) / 2;
                voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center);
            }

            MyVoxelMaterialDefinition voxelMat = null;

            ProfilerShort.Begin("Main loop");
            Vector3I pos;
            for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X)
                for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y)
                    for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z)
            {
                // get original amount
                var relPos = pos - cacheMin;
                var lin = m_cache.ComputeLinear(ref relPos);
                var original = m_cache.Content(lin);

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

                Vector3D spos = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                var volume = shape.GetVolume(ref spos);

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

                var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var toRemove = maxRemove;// (int)(maxRemove * voxelMat.DamageRatio);
                var newVal = Math.Max(original - toRemove, 0);//MathHelper.Clamp(original - toRemove, 0, original-maxRemove);
                var removed  = original - newVal;

                if (!onlyCheck && !onlyApplyMaterial)
                    m_cache.Content(lin, (byte)newVal);

                originalSum += original;
                removedSum += removed;

                if (readMaterial)
                    voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin));

                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 (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck)
                    m_cache.Material(lin, voxelMat.DamagedMaterialId);
            }

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

            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();

                var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content;
                if (MyFakes.LOG_NAVMESH_GENERATION) MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax);
                voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax);
            }
            ProfilerShort.End();


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

            shape.Transformation = oldTranmsform;

            if (removedSum > 0)
                OnVoxelChanged(OperationType.Cut, voxelMap, shape);

            ProfilerShort.End();
        }
示例#14
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)
        {
            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();
        }
示例#15
0
        private static void CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            // Check static grids around (possible change to dynamic)
            if (Sync.IsServer && MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
            {
                BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                cutOutBox.Inflate(0.25);

                List <MyEntity> boxOverlapList = new List <MyEntity>();
                MyEntities.GetElementsInBox(ref cutOutBox, boxOverlapList);

                foreach (var entity in boxOverlapList)
                {
                    var grid = entity as MyCubeGrid;
                    if (grid != null && grid.IsStatic)
                    {
                        if (grid.Physics != null && grid.Physics.Shape != null)
                        {
                            grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                        }

                        if (type == MyVoxelBase.OperationType.Cut)
                        {
                            grid.TestDynamic = true;
                        }
                    }
                }

                boxOverlapList.Clear();
            }
        }
示例#16
0
 private static bool CanPlaceInArea(PaintType type, MyShape Shape)
 {
     if (type == PaintType.Fill)
     { 
         m_foundElements.Clear();
         BoundingBoxD box = Shape.GetWorldBoundaries();
         MyEntities.GetElementsInBox(ref box, m_foundElements);
         foreach (var entity in m_foundElements)
         {
             if (IsForbiddenEntity(entity))
             {
                 if (entity.PositionComp.WorldAABB.Intersects(box))
                 {
                     return false;
                 }
             }
         }
     }
     return true;
 }
示例#17
0
        private static ulong UpdateVoxelShape(MySyncVoxel sync, PaintType type, MyShape Shape, byte Material)
        {
            var voxel = sync.Entity as MyVoxelBase;
            ulong changedVoxelAmount = 0;
            if (voxel != null)
            {
                switch (type)
                {
                    case PaintType.Paint:
                        MyVoxelGenerator.PaintInShape(voxel, Shape, Material);
                        break;
                    case PaintType.Fill:
                        changedVoxelAmount = MyVoxelGenerator.FillInShape(voxel, Shape, Material);
                        break;
                    case PaintType.Cut:
                        changedVoxelAmount = MyVoxelGenerator.CutOutShape(voxel, Shape);
                        break;
                }
            }

            return changedVoxelAmount;
        }     
示例#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();
        }
示例#19
0
        private static void CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            // Check static grids around (possible change to dynamic)
            if (Sync.IsServer && MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
            {
                BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                cutOutBox.Inflate(0.25);

                List<MyEntity> boxOverlapList = new List<MyEntity>();
                MyEntities.GetElementsInBox(ref cutOutBox, boxOverlapList);

                foreach (var entity in boxOverlapList)
                {
                    var grid = entity as MyCubeGrid;
                    if (grid != null && grid.IsStatic)
                    {
                        if (grid.Physics != null && grid.Physics.Shape != null)
                        {
                            grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                        }

                        if (type == MyVoxelBase.OperationType.Cut)
                            grid.TestDynamic = true;
                    }
                }

                boxOverlapList.Clear();
            }

        }
示例#20
0
 public static void CutOutShape(MyVoxelBase voxelMap, MyShape shape, bool voxelHand = false)
 {
     if (MySession.Static.EnableVoxelDestruction || MySession.Static.HighSimulationQuality)
     {
         using (voxelMap.Pin())
         {
             if (!voxelMap.MarkedForClose)
             {
                 Vector3I vectori;
                 Vector3I maxCorner;
                 Vector3I minCorner;
                 GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
                 ulong num = 0UL;
                 if (m_cache == null)
                 {
                     m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
                 }
                 Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori);
                 while (true)
                 {
                     Vector3I vectori2;
                     Vector3I vectori3;
                     if (!it.IsValid())
                     {
                         if (num > 0L)
                         {
                             BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                             MySandboxGame.Static.Invoke(delegate {
                                 if (voxelMap.Storage != null)
                                 {
                                     voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                                     NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref cutOutBox);
                                 }
                             }, "CutOutShape notify");
                         }
                         break;
                     }
                     GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3);
                     Vector3I voxelCoord = vectori2 - 1;
                     Vector3I vectori5   = (Vector3I)(vectori3 + 1);
                     voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1);
                     voxelMap.Storage.ClampVoxelCoord(ref vectori5, 1);
                     ulong num2 = 0UL;
                     m_cache.Resize(voxelCoord, vectori5);
                     MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;
                     voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, voxelCoord, vectori5, ref considerContent);
                     Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3);
                     while (true)
                     {
                         if (!iterator2.IsValid())
                         {
                             if (num2 > 0L)
                             {
                                 RemoveSmallVoxelsUsingChachedVoxels();
                                 voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, voxelCoord, vectori5, false, true);
                             }
                             num += num2;
                             it.MoveNext();
                             break;
                         }
                         Vector3I p    = iterator2.Current - voxelCoord;
                         byte     num3 = m_cache.Content(ref p);
                         if (num3 != 0)
                         {
                             Vector3D vectord;
                             MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord);
                             float volume = shape.GetVolume(ref vectord);
                             if (volume != 0f)
                             {
                                 int   num5 = Math.Min((int)(255f - (volume * 255f)), num3);
                                 ulong num6 = (ulong)Math.Abs((int)(num3 - num5));
                                 m_cache.Content(ref p, (byte)num5);
                                 if (num5 == 0)
                                 {
                                     m_cache.Material(ref p, 0xff);
                                 }
                                 num2 += num6;
                             }
                         }
                         iterator2.MoveNext();
                     }
                 }
             }
         }
     }
 }
示例#21
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,
            bool applyDamageMaterial = false,
            bool onlyApplyMaterial   = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial        = null;
                return;
            }

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

            int  originalSum = 0;
            int  removedSum  = 0;
            bool materials   = exactCutOutMaterials != null;

            // Bring the shape into voxel space.
            var oldTranmsform = shape.Transformation;
            var newTransf     = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled;

            newTransf.Translation += voxelMap.SizeInMetresHalf;
            shape.Transformation   = newTransf;

            // This boundary should now be in our local space
            var bbox = shape.GetWorldBoundaries();

            Vector3I minCorner, maxCorner;

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

            bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial;

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

            //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf

            /*const int SHIFT = 4;
             * const int REM = (1 << SHIFT) - 1;
             * const int MASK = ~REM;
             * cacheMin &= MASK;
             * cacheMax = (cacheMax + REM) & MASK;*/

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            m_cache.ClearMaterials(0);

            // Advise that the read content shall be cached
            MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache;

            voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags);

            Vector3I center;

            if (materials)
            {
                center        = m_cache.Size3D / 2;
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center));
            }
            else
            {
                center        = (cacheMin + cacheMax) / 2;
                voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center);
            }

            MyVoxelMaterialDefinition voxelMat = null;

            ProfilerShort.Begin("Main loop");
            Vector3I pos;

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

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

                        Vector3D spos   = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                        var      volume = shape.GetVolume(ref spos);

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

                        var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                        var toRemove  = maxRemove;                        // (int)(maxRemove * voxelMat.DamageRatio);
                        var newVal    = Math.Max(original - toRemove, 0); //MathHelper.Clamp(original - toRemove, 0, original-maxRemove);
                        var removed   = original - newVal;

                        if (!onlyCheck && !onlyApplyMaterial)
                        {
                            m_cache.Content(lin, (byte)newVal);
                        }

                        originalSum += original;
                        removedSum  += removed;

                        if (readMaterial)
                        {
                            voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin));
                        }

                        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 (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck)
                        {
                            m_cache.Material(lin, voxelMat.DamagedMaterialId);
                        }
                    }
                }
            }

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

            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();

                var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content;
                if (MyFakes.LOG_NAVMESH_GENERATION)
                {
                    MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax);
                }
                voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax);
            }
            ProfilerShort.End();


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

            shape.Transformation = oldTranmsform;

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

            ProfilerShort.End();
        }
        public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape)
        {
            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);
            ulong changedVolumeAmount = 0;

            for (var itCells = new Vector3I.RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                var cacheMin = cellMinCorner - 1;
                var cacheMax = cellMaxCorner + 1;
                voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
                voxelMap.Storage.ClampVoxelCoord(ref cacheMax);

                ulong removedSum = 0;
                m_cache.Resize(cacheMin, cacheMax);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax);

                for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); 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 toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL));
                    var newVal = Math.Min(toRemove, original);
                    ulong removed = (ulong)Math.Abs(original - newVal);

                    m_cache.Content(ref relPos, (byte)newVal);
                    removedSum += removed;
                }

                if (removedSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
                }

                changedVolumeAmount += removedSum;
            }

            return changedVolumeAmount;
        }
        public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            ulong retValue = 0;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            for (var itCells = new Vector3I.RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                Vector3I originalMinCorner = cellMinCorner;
                Vector3I originalMaxCorner = cellMaxCorner;

                voxelMap.Storage.ClampVoxelCoord(ref cellMinCorner, VOXEL_CLAMP_BORDER_DISTANCE);
                voxelMap.Storage.ClampVoxelCoord(ref cellMaxCorner, VOXEL_CLAMP_BORDER_DISTANCE);

                ClampingInfo minCornerClamping = CheckForClamping(originalMinCorner, cellMinCorner);
                ClampingInfo maxCornerClamping = CheckForClamping(originalMaxCorner, cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cellMinCorner, ref cellMaxCorner);

                ulong filledSum = 0;

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

                    if (original == MyVoxelConstants.VOXEL_CONTENT_FULL) // if there is nothing to add
                        continue;

                    //if there was some claping, fill the clamp region with material 
                    if ((it.Current.X == cellMinCorner.X && minCornerClamping.X) || (it.Current.X == cellMaxCorner.X && maxCornerClamping.X) ||
                        (it.Current.Y == cellMinCorner.Y && minCornerClamping.Y) || (it.Current.Y == cellMaxCorner.Y && maxCornerClamping.Y) ||
                        (it.Current.Z == cellMinCorner.Z && minCornerClamping.Z) || (it.Current.Z == cellMaxCorner.Z && maxCornerClamping.Z))
                    {
                        m_cache.Material(ref relPos, materialIdx);
                        continue;
                    }

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


                    if (volume <= 0f) // there is nothing to fill
                        continue;

                    m_cache.Material(ref relPos, materialIdx); // set material

                    var toFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                    long newVal = MathHelper.Clamp(original + toFill, 0, Math.Max(original, toFill));

                    m_cache.Content(ref relPos, (byte)newVal);
                    filledSum += (ulong)(newVal - original);
                }
                if (filledSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels();
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref cellMinCorner, ref cellMaxCorner);
                }

                retValue += filledSum;
            }

            return retValue;
        }
示例#24
0
 public static unsafe void CutOutShapeWithProperties(MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false, bool applyDamageMaterial = false, bool onlyApplyMaterial = false, bool skipCache = false)
 {
     if ((!MySession.Static.EnableVoxelDestruction || ((voxelMap == null) || (voxelMap.Storage == null))) || (shape == null))
     {
         voxelsCountInPercent = 0f;
         voxelMaterial        = null;
     }
     else
     {
         Vector3I vectori3;
         Vector3I vectori4;
         Vector3I maxCorner;
         Vector3I minCorner;
         int      num            = 0;
         int      num2           = 0;
         MatrixD  transformation = shape.Transformation;
         MatrixD  xd2            = transformation * voxelMap.PositionComp.WorldMatrixInvScaled;
         MatrixD *xdPtr1         = (MatrixD *)ref xd2;
         xdPtr1.Translation  += voxelMap.SizeInMetresHalf;
         shape.Transformation = xd2;
         BoundingBoxD worldBoundaries = shape.GetWorldBoundaries();
         ComputeShapeBounds(voxelMap, ref worldBoundaries, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner);
         bool     flag       = (exactCutOutMaterials != null) | applyDamageMaterial;
         Vector3I voxelCoord = minCorner - 1;
         Vector3I vectori2   = (Vector3I)(maxCorner + 1);
         voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1);
         voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1);
         if (m_cache == null)
         {
             m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
         }
         m_cache.Resize(voxelCoord, vectori2);
         MyVoxelRequestFlags requestFlags = (skipCache ? ((MyVoxelRequestFlags)0) : MyVoxelRequestFlags.AdviseCache) | (flag ? MyVoxelRequestFlags.ConsiderContent : ((MyVoxelRequestFlags)0));
         voxelMap.Storage.ReadRange(m_cache, flag ? MyStorageDataTypeFlags.All : MyStorageDataTypeFlags.Content, 0, voxelCoord, vectori2, ref requestFlags);
         if (exactCutOutMaterials != null)
         {
             vectori3      = (Vector3I)(m_cache.Size3D / 2);
             voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref vectori3));
         }
         else
         {
             vectori3      = (Vector3I)((voxelCoord + vectori2) / 2);
             voxelMaterial = voxelMap.Storage.GetMaterialAt(ref vectori3);
         }
         MyVoxelMaterialDefinition key = null;
         vectori4.X = minCorner.X;
         while (vectori4.X <= maxCorner.X)
         {
             vectori4.Y = minCorner.Y;
             while (true)
             {
                 if (vectori4.Y > maxCorner.Y)
                 {
                     int *numPtr3 = (int *)ref vectori4.X;
                     numPtr3[0]++;
                     break;
                 }
                 vectori4.Z = minCorner.Z;
                 while (true)
                 {
                     if (vectori4.Z > maxCorner.Z)
                     {
                         int *numPtr2 = (int *)ref vectori4.Y;
                         numPtr2[0]++;
                         break;
                     }
                     Vector3I p         = vectori4 - voxelCoord;
                     int      linearIdx = m_cache.ComputeLinear(ref p);
                     byte     num4      = m_cache.Content(linearIdx);
                     if (num4 != 0)
                     {
                         Vector3D voxelPosition = (Vector3D)((vectori4 - voxelMap.StorageMin) * 1.0);
                         float    volume        = shape.GetVolume(ref voxelPosition);
                         if (volume != 0f)
                         {
                             int num7 = Math.Max(num4 - ((int)(volume * 255f)), 0);
                             int num8 = num4 - num7;
                             if ((num4 / 10) != (num7 / 10))
                             {
                                 if (!onlyCheck && !onlyApplyMaterial)
                                 {
                                     m_cache.Content(linearIdx, (byte)num7);
                                 }
                                 num  += num4;
                                 num2 += num8;
                                 byte materialIndex = m_cache.Material(linearIdx);
                                 if (num7 == 0)
                                 {
                                     m_cache.Material(linearIdx, 0xff);
                                 }
                                 if (materialIndex != 0xff)
                                 {
                                     if (flag)
                                     {
                                         key = MyDefinitionManager.Static.GetVoxelMaterialDefinition(materialIndex);
                                     }
                                     if (exactCutOutMaterials != null)
                                     {
                                         int num10;
                                         exactCutOutMaterials.TryGetValue(key, out num10);
                                         exactCutOutMaterials[key] = num10 + (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? ((int)(num8 * 3.9f)) : num8);
                                     }
                                 }
                             }
                         }
                     }
                     int *numPtr1 = (int *)ref vectori4.Z;
                     numPtr1[0]++;
                 }
             }
         }
         if ((((num2 > 0) & updateSync) && Sync.IsServer) && !onlyCheck)
         {
             shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial);
         }
         if ((num2 > 0) && !onlyCheck)
         {
             RemoveSmallVoxelsUsingChachedVoxels();
             MyStorageDataTypeFlags all = MyStorageDataTypeFlags.All;
             if (MyFakes.LOG_NAVMESH_GENERATION && (MyAIComponent.Static.Pathfinding != null))
             {
                 MyAIComponent.Static.Pathfinding.GetPathfindingLog().LogStorageWrite(voxelMap, m_cache, all, voxelCoord, vectori2);
             }
             voxelMap.Storage.WriteRange(m_cache, all, voxelCoord, vectori2, false, skipCache);
         }
         voxelsCountInPercent = (num > 0f) ? (((float)num2) / ((float)num)) : 0f;
         if (num2 > 0)
         {
             BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
             MySandboxGame.Static.Invoke(delegate {
                 if (voxelMap.Storage != null)
                 {
                     voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                     NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref cutOutBox);
                 }
             }, "CutOutShapeWithProperties notify");
         }
         shape.Transformation = transformation;
     }
 }
示例#25
0
 public static unsafe void ChangeMaterialsInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx, bool[] materialsToChange)
 {
     if ((voxelMap != null) && (shape != null))
     {
         using (voxelMap.Pin())
         {
             if (!voxelMap.MarkedForClose)
             {
                 Vector3I vectori;
                 Vector3I vectori2;
                 Vector3I vectori5;
                 MatrixD  xd     = shape.Transformation * voxelMap.PositionComp.WorldMatrixInvScaled;
                 MatrixD *xdPtr1 = (MatrixD *)ref xd;
                 xdPtr1.Translation  += voxelMap.SizeInMetresHalf;
                 shape.Transformation = xd;
                 BoundingBoxD worldBoundaries = shape.GetWorldBoundaries();
                 ComputeShapeBounds(voxelMap, ref worldBoundaries, Vector3.Zero, voxelMap.Storage.Size, out vectori, out vectori2);
                 Vector3I voxelCoord = vectori - 1;
                 Vector3I vectori4   = (Vector3I)(vectori2 + 1);
                 voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1);
                 voxelMap.Storage.ClampVoxelCoord(ref vectori4, 1);
                 if (m_cache == null)
                 {
                     m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
                 }
                 m_cache.Resize(voxelCoord, vectori4);
                 MyVoxelRequestFlags requestFlags = MyVoxelRequestFlags.AdviseCache | MyVoxelRequestFlags.ConsiderContent;
                 voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, voxelCoord, vectori4, ref requestFlags);
                 vectori5.X = vectori.X;
                 while (vectori5.X <= vectori2.X)
                 {
                     vectori5.Y = vectori.Y;
                     while (true)
                     {
                         if (vectori5.Y > vectori2.Y)
                         {
                             int *numPtr3 = (int *)ref vectori5.X;
                             numPtr3[0]++;
                             break;
                         }
                         vectori5.Z = vectori.Z;
                         while (true)
                         {
                             if (vectori5.Z > vectori2.Z)
                             {
                                 int *numPtr2 = (int *)ref vectori5.Y;
                                 numPtr2[0]++;
                                 break;
                             }
                             Vector3I p         = vectori5 - vectori;
                             int      linearIdx = m_cache.ComputeLinear(ref p);
                             byte     index     = m_cache.Material(linearIdx);
                             if (materialsToChange[index])
                             {
                                 Vector3D vectord;
                                 MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref vectori5, out vectord);
                                 if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff))
                                 {
                                     m_cache.Material(ref p, materialIdx);
                                 }
                             }
                             int *numPtr1 = (int *)ref vectori5.Z;
                             numPtr1[0]++;
                         }
                     }
                 }
             }
         }
     }
 }
示例#26
0
 public static void FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
 {
     using (voxelMap.Pin())
     {
         if (!voxelMap.MarkedForClose)
         {
             Vector3I vectori;
             Vector3I maxCorner;
             Vector3I minCorner;
             ulong    num = 0UL;
             GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
             minCorner = Vector3I.Max(Vector3I.One, minCorner);
             maxCorner = Vector3I.Max(minCorner, maxCorner - Vector3I.One);
             if (m_cache == null)
             {
                 m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
             }
             Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori);
             while (true)
             {
                 Vector3I vectori2;
                 Vector3I vectori3;
                 if (!it.IsValid())
                 {
                     if (num > 0L)
                     {
                         BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                         MySandboxGame.Static.Invoke(delegate {
                             if (voxelMap.Storage != null)
                             {
                                 voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                                 NotifyVoxelChanged(MyVoxelBase.OperationType.Fill, voxelMap, ref cutOutBox);
                             }
                         }, "FillInShape Notify");
                     }
                     break;
                 }
                 GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3);
                 Vector3I originalValue = vectori3;
                 voxelMap.Storage.ClampVoxelCoord(ref vectori2, 0);
                 voxelMap.Storage.ClampVoxelCoord(ref vectori3, 0);
                 ClampingInfo info  = CheckForClamping(vectori2, vectori2);
                 ClampingInfo info2 = CheckForClamping(originalValue, vectori3);
                 m_cache.Resize(vectori2, vectori3);
                 MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;
                 voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent);
                 ulong num2 = 0UL;
                 Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3);
                 while (true)
                 {
                     if (!iterator2.IsValid())
                     {
                         if (num2 > 0L)
                         {
                             RemoveSmallVoxelsUsingChachedVoxels();
                             voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, vectori2, vectori3, false, true);
                         }
                         num += num2;
                         it.MoveNext();
                         break;
                     }
                     Vector3I p    = iterator2.Current - vectori2;
                     byte     num3 = m_cache.Content(ref p);
                     if ((num3 != 0xff) || (m_cache.Material(ref p) != materialIdx))
                     {
                         if ((((iterator2.Current.X == vectori2.X) && info.X) || (((iterator2.Current.X == vectori3.X) && info2.X) || (((iterator2.Current.Y == vectori2.Y) && info.Y) || (((iterator2.Current.Y == vectori3.Y) && info2.Y) || ((iterator2.Current.Z == vectori2.Z) && info.Z))))) || ((iterator2.Current.Z == vectori3.Z) && info2.Z))
                         {
                             if (num3 != 0)
                             {
                                 m_cache.Material(ref p, materialIdx);
                             }
                         }
                         else
                         {
                             Vector3D vectord;
                             MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord);
                             float volume = shape.GetVolume(ref vectord);
                             if (volume > 0f)
                             {
                                 long num6 = Math.Max(num3, (int)(volume * 255f));
                                 m_cache.Content(ref p, (byte)num6);
                                 if (num6 != 0)
                                 {
                                     m_cache.Material(ref p, materialIdx);
                                 }
                                 num2 += ((ulong)num6) - num3;
                             }
                         }
                     }
                     iterator2.MoveNext();
                 }
             }
         }
     }
 }
        public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            for (var itCells = new Vector3I.RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner);

                for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos = it.Current - cellMinCorner;

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    float volume = shape.GetVolume(ref vpos);
                    if (volume > 0.5f)
                        m_cache.Material(ref relPos, materialIdx); // set material
                }

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner);
            }
        }
示例#28
0
        public static unsafe void DisableItemsInShape(this MyEnvironmentSector sector, MyShape shape)
        {
            if (sector.DataView == null)
                return;

            for (int sectorInd = 0; sectorInd < sector.DataView.LogicalSectors.Count; sectorInd++)
            {
                var logicalSector = sector.DataView.LogicalSectors[sectorInd];
                var logicalItems = logicalSector.Items;
                var cnt = logicalItems.Count;

                fixed (ItemInfo* items = logicalItems.GetInternalArray())
                    for (int i = 0; i < cnt; ++i)
                    {
                        var worldPos = sector.SectorCenter + items[i].Position;
                        if (shape.GetVolume(ref worldPos) > 0f)
                        {
                            logicalSector.EnableItem(i, false);
                        }
                    }
            }
        }
 private static void GetVoxelShapeDimensions(MyVoxelBase voxelMap, MyShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells, float extent = 0.0f)
 {
     {
         var bbox = shape.GetWorldBoundaries();
         ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner);
     }
     minCorner += voxelMap.StorageMin;
     maxCorner += voxelMap.StorageMin;
     numCells = new Vector3I((maxCorner.X - minCorner.X) / CELL_SIZE, (maxCorner.Y - minCorner.Y) / CELL_SIZE, (maxCorner.Z - minCorner.Z) / CELL_SIZE);
 }
        private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            if (!Sync.IsServer)
                return;
            BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
            cutOutBox.Inflate(0.25);

            MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList);
            // Check static grids around (possible change to dynamic)
            if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
            {
                foreach (var entity in m_overlapList)
                {
                    var grid = entity as MyCubeGrid;
                    if (grid != null && grid.IsStatic)
                    {
                        if (grid.Physics != null && grid.Physics.Shape != null)
                        {
                            grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                        }

                        if (type == MyVoxelBase.OperationType.Cut)
                            grid.TestDynamic = true;
                    }
                }

            }
            var voxelPhysics = voxelMap as MyVoxelPhysics;
            MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet;
            if (planet != null)
            {
                var center = cutOutBox.Center;
                foreach (var environment in planet.GetEnvironmentItemsAtPosition(ref center))
                {
                    environment.RemoveItemsAroundPoint(cutOutBox.Center, cutOutBox.HalfExtents.Max());
                }
            }
            m_overlapList.Clear();
        }
示例#31
0
        private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            if (!Sync.IsServer)
            {
                return;
            }
            BoundingBoxD cutOutBox = shape.GetWorldBoundaries();

            cutOutBox.Inflate(0.25);

            MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList);
            // Check static grids around (possible change to dynamic)
            if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
            {
                foreach (var entity in m_overlapList)
                {
                    var grid = entity as MyCubeGrid;
                    if (grid != null && grid.IsStatic)
                    {
                        if (grid.Physics != null && grid.Physics.Shape != null)
                        {
                            grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                        }

                        if (type == MyVoxelBase.OperationType.Cut)
                        {
                            grid.TestDynamic = true;
                        }
                    }
                }
            }
            var      voxelPhysics = voxelMap as MyVoxelPhysics;
            MyPlanet planet       = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet;

            if (planet != null)
            {
                var center = cutOutBox.Center;
                foreach (var environment in planet.GetEnvironmentItemsAtPosition(ref center))
                {
                    environment.RemoveItemsAroundPoint(cutOutBox.Center, cutOutBox.HalfExtents.Max());
                }
            }
            m_overlapList.Clear();
        }
示例#32
0
 static bool CanPlaceInArea(OperationType type, MyShape Shape)
 {
     if (type == OperationType.Fill)
     {
         m_foundElements.Clear();
         BoundingBoxD box = Shape.GetWorldBoundaries();
         MyEntities.GetElementsInBox(ref box, m_foundElements);
         foreach (var entity in m_foundElements)
         {
             if (IsForbiddenEntity(entity))
             {
                 if (entity.PositionComp.WorldAABB.Intersects(box))
                 {
                     MyHud.Notifications.Add(MyNotificationSingletons.CopyPasteAsteoridObstructed);
                     return false;
                 }
             }
         }
     }
     return true;
 }
示例#33
0
        public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            ulong    retValue = 0;

            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            //voxel must be at least 1 m from side to be closed (e.g. without holes in it)
            minCorner = Vector3I.Max(Vector3I.One, minCorner);
            maxCorner = Vector3I.Max(minCorner, maxCorner);

            for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                Vector3I originalMinCorner = cellMinCorner;
                Vector3I originalMaxCorner = cellMaxCorner;

                voxelMap.Storage.ClampVoxelCoord(ref cellMinCorner, 0);
                voxelMap.Storage.ClampVoxelCoord(ref cellMaxCorner, 0);

                ClampingInfo minCornerClamping = CheckForClamping(originalMinCorner, cellMinCorner);
                ClampingInfo maxCornerClamping = CheckForClamping(originalMaxCorner, cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cellMinCorner, ref cellMaxCorner);

                ulong filledSum = 0;

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos   = it.Current - cellMinCorner; // get original amount
                    var original = m_cache.Content(ref relPos);

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

                    //if there was some claping, fill the clamp region with material
                    if ((it.Current.X == cellMinCorner.X && minCornerClamping.X) || (it.Current.X == cellMaxCorner.X && maxCornerClamping.X) ||
                        (it.Current.Y == cellMinCorner.Y && minCornerClamping.Y) || (it.Current.Y == cellMaxCorner.Y && maxCornerClamping.Y) ||
                        (it.Current.Z == cellMinCorner.Z && minCornerClamping.Z) || (it.Current.Z == cellMaxCorner.Z && maxCornerClamping.Z))
                    {
                        m_cache.Material(ref relPos, materialIdx);
                        continue;
                    }

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


                    if (volume <= 0f) // there is nothing to fill
                    {
                        continue;
                    }

                    m_cache.Material(ref relPos, materialIdx); // set material

                    var  toFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                    long newVal = MathHelper.Clamp(original + toFill, 0, Math.Max(original, toFill));

                    m_cache.Content(ref relPos, (byte)newVal);
                    filledSum += (ulong)(newVal - original);
                }
                if (filledSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels();
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref cellMinCorner, ref cellMaxCorner);
                }

                retValue += filledSum;
            }

            if (retValue > 0)
            {
                OnVoxelChanged(MyVoxelBase.OperationType.Fill, voxelMap, shape);
            }

            return(retValue);
        }
示例#34
0
        private ulong UpdateVoxelShape(OperationType type, MyShape shape, byte Material)
        {
            ulong changedVoxelAmount = 0;

            switch (type)
            {
                case OperationType.Paint:
                    MyVoxelGenerator.PaintInShape(this, shape, Material);
                    break;
                case OperationType.Fill:
                    changedVoxelAmount = MyVoxelGenerator.FillInShape(this, shape, Material);
                    break;
                case OperationType.Cut:
                    changedVoxelAmount = MyVoxelGenerator.CutOutShape(this, shape);
                    break;
            }

            return changedVoxelAmount;
        }
        public IEnumerable<MyEnvironmentSector> GetSectorsInRange(MyShape shape)
        {
            var bb = shape.GetWorldBoundaries();
            var hierarchyComp = Container.Get<MyHierarchyComponentBase>() as MyHierarchyComponent<MyEntity>;
            var entities = new List<MyEntity>();
            hierarchyComp.QueryAABB(ref bb, entities);

            return entities.Cast<MyEnvironmentSector>();
        }
示例#36
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();
        }