Ejemplo n.º 1
0
 internal void Init(MyVoxelMap voxelMap)
 {
     m_voxelMap = voxelMap;
     var size = m_voxelMap.Size;
     m_cellsCount.X = size.X >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
     m_cellsCount.Y = size.Y >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
     m_cellsCount.Z = size.Z >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
 }
Ejemplo n.º 2
0
        public void Init(MyMwcObjectBuilder_VoxelHand_Cylinder objectBuilder, MyVoxelMap parentVoxelMap)
        {
            base.Init(objectBuilder, parentVoxelMap);

            this.Radius1 = objectBuilder.Radius1;
            this.Radius2 = objectBuilder.Radius2;
            this.Length = objectBuilder.Length;

            UpdateLocalVolume();
        }
Ejemplo n.º 3
0
        protected virtual void Init(MyMwcObjectBuilder_VoxelHand_Shape objectBuilder, MyVoxelMap parentVoxelMap)
        {
            base.Init(null, objectBuilder, parentVoxelMap);
            ModeType = objectBuilder.VoxelHandModeType;
            Material = objectBuilder.VoxelHandMaterial;

            SetWorldMatrix(Matrix.CreateWorld(objectBuilder.PositionAndOrientation.Position, objectBuilder.PositionAndOrientation.Forward, objectBuilder.PositionAndOrientation.Up));

            Visible = false;
        }
Ejemplo n.º 4
0
        public MyCellStorage(string name, Vector3I size, MyVoxelMap voxelMap) : base(name)
        {
            base.VoxelMap = voxelMap;

            Size = size;
            m_sizeInMeters = Size * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
            m_dataCellsCount = Size / MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
            m_oreDepositCellsCount = m_dataCellsCount;

            AllocateContents();
        }
Ejemplo n.º 5
0
        public void Init(MyMwcObjectBuilder_VoxelHand_Cuboid objectBuilder, MyVoxelMap parentVoxelMap)
        {
            base.Init(objectBuilder, parentVoxelMap);

            Width1 = objectBuilder.Width1;
            Depth1 = objectBuilder.Depth1;
            Width2 = objectBuilder.Width2;
            Depth2 = objectBuilder.Depth2;
            Length = objectBuilder.Length;

            UpdateLocalVolume();
        }
        internal MyVoxelPhysicsBody(MyVoxelMap voxelMap): base(voxelMap, RigidBodyFlag.RBF_STATIC)
        {
            m_voxelMap = voxelMap;

            var shape = GetHavokShape();
            if (!shape.IsZero)
            {
                CreateFromCollisionObject(shape, -m_voxelMap.SizeInMetresHalf, m_voxelMap.WorldMatrix);
            }
            else
            {
                IsEmpty = true;
            }
        }
Ejemplo n.º 7
0
 public void Init(MyMwcObjectBuilder_VoxelHand_Sphere objectBuilder, MyVoxelMap parentVoxelMap)
 {
     base.Init(objectBuilder, parentVoxelMap);
     this.Radius = objectBuilder.Radius;
     UpdateLocalVolume();
 }
Ejemplo n.º 8
0
        //  When tube/head mounted into voxels and is harvesting
        void StartInVoxel(MyVoxelMap voxelMap)
        {
            //  We found voxel so we stop here
            m_inVoxelMap = voxelMap;
            CurrentState = MyHarvestingDeviceEnum.InVoxel;
            StopTubeMovingCue();
            StartGrindingCue();
            m_lastTimeParticleAdded = null;
            m_parentMinerShip.Physics.Clear();
            m_parentMinerShip.Physics.Immovable = true;

            MyMwcVector3Int tempVoxelCoord = voxelMap.GetVoxelCenterCoordinateFromMeters(ref m_headPositionTransformed);
            m_originalVoxelContent = voxelMap.GetVoxelContent(ref tempVoxelCoord);
            m_voxelMaterial = voxelMap.GetVoxelMaterial(ref tempVoxelCoord);


            m_harvestingParticleEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Harvester_Harvesting);
            m_harvestingParticleEffect.UserBirthMultiplier = 0.25f;
            m_harvestingParticleEffect.UserRadiusMultiplier = 1;
            m_harvestingParticleEffect.UserColorMultiplier = new Vector4(3, 3, 3, 3);
            Matrix dirMatrix = MyMath.MatrixFromDir(WorldMatrix.Forward);
            m_harvestingParticleEffect.WorldMatrix = Matrix.CreateWorld(m_headPositionTransformed, dirMatrix.Forward, dirMatrix.Up);

            //  Empty voxels are problematic and can lead to "extremely fast harvesting". So here we do this
            //  trick and its effect will be that even empty voxels will take few seconds to harvest.
            if (m_originalVoxelContent == 0) m_originalVoxelContent = 1;

            m_actualVoxelContent = (float)m_originalVoxelContent;
            m_harvestingSpeed = m_actualVoxelContent / TIME_TO_HARVEST_WHOLE_VOXEL_IN_UPDATE_TIMES;

            if (!MyVoxelMapOreMaterials.CanBeHarvested(m_voxelMaterial))
            {
                HUD.MyHud.ShowIndestructableAsteroidNotification();
                StartReturningBack();
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Processes an asteroid Voxel using function callbacks.
        /// This allows for muti-threading, and generating content via algorithims.
        /// </summary>
        /// <param name="voxelMap"></param>
        /// <param name="multiThread"></param>
        /// <param name="material"></param>
        /// <param name="func"></param>
        /// <param name="readWrite"></param>
        /// <returns></returns>
        public static void ProcessAsteroid(MyVoxelMap voxelMap, bool multiThread, string material, Action <MyVoxelBuilderArgs> func, bool readWrite = true)
        {
            long    counterTotal = (long)voxelMap.Size.X * (long)voxelMap.Size.Y * (long)voxelMap.Size.Z;
            long    counter      = 0;
            decimal progress     = 0;
            var     timer        = new Stopwatch();

            Debug.Write(string.Format("Building Asteroid : {0:000},", progress));
            Console.Write(string.Format("Building Asteroid : {0:000},", progress));
            Exception threadException = null;

            timer.Start();

            if (!multiThread)
            {
                #region single thread processing

                for (var x = 0; x < voxelMap.Size.X; x++)
                {
                    for (var y = 0; y < voxelMap.Size.Y; y++)
                    {
                        for (var z = 0; z < voxelMap.Size.Z; z++)
                        {
                            var coords = new Vector3I(x, y, z);

                            byte volume       = 0xff;
                            var  cellMaterial = material;

                            if (readWrite)
                            {
                                voxelMap.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume);
                            }

                            var args = new MyVoxelBuilderArgs(voxelMap.Size, coords, cellMaterial, volume, 0xff);

                            try
                            {
                                func(args);
                            }
                            catch (Exception ex)
                            {
                                threadException = ex;
                                break;
                            }

                            if (args.Volume != MyVoxelConstants.VOXEL_CONTENT_FULL)
                            {
                                voxelMap.SetVoxelContent(args.Volume, ref coords);
                            }

                            if (material != args.Material)
                            {
                                voxelMap.SetVoxelMaterialAndIndestructibleContent(args.Material, args.Indestructible, ref coords);
                            }

                            counter++;
                            var prog = Math.Floor(counter / (decimal)counterTotal * 100);
                            if (prog != progress)
                            {
                                progress = prog;
                                Debug.Write(string.Format("{0:000},", progress));
                            }
                        }
                    }
                }

                #endregion
            }
            else
            {
                #region multi thread processing

                // TODO: re-write the multi thread processing to be more stable.
                // But still try and max out the processors.

                long threadCounter = counterTotal / MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE / MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE / MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE;

                var baseCoords = new Vector3I(0, 0, 0);
                for (baseCoords.X = 0; baseCoords.X < voxelMap.Size.X; baseCoords.X += MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE)
                {
                    for (baseCoords.Y = 0; baseCoords.Y < voxelMap.Size.Y; baseCoords.Y += MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE)
                    {
                        for (baseCoords.Z = 0; baseCoords.Z < voxelMap.Size.Z; baseCoords.Z += MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE)
                        {
                            var task = new Task(obj =>
                            {
                                var bgw = (MyVoxelTaskWorker)obj;

                                var coords = new Vector3I(0, 0, 0);
                                for (coords.X = bgw.BaseCoords.X; coords.X < bgw.BaseCoords.X + MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE; coords.X++)
                                {
                                    for (coords.Y = bgw.BaseCoords.Y; coords.Y < bgw.BaseCoords.Y + MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE; coords.Y++)
                                    {
                                        for (coords.Z = bgw.BaseCoords.Z; coords.Z < bgw.BaseCoords.Z + MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE; coords.Z++)
                                        {
                                            byte volume      = 0xff;
                                            var cellMaterial = material;

                                            if (readWrite)
                                            {
                                                voxelMap.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume);
                                            }

                                            var args = new MyVoxelBuilderArgs(voxelMap.Size, coords, cellMaterial, volume, 0xff);
                                            try
                                            {
                                                func(args);
                                            }
                                            catch (Exception ex)
                                            {
                                                threadException = ex;
                                                threadCounter   = 0;
                                                break;
                                            }

                                            if (args.Volume != MyVoxelConstants.VOXEL_CONTENT_FULL)
                                            {
                                                voxelMap.SetVoxelContent(args.Volume, ref coords);
                                            }

                                            if (material != args.Material)
                                            {
                                                voxelMap.SetVoxelMaterialAndIndestructibleContent(args.Material, args.Indestructible, ref coords);
                                            }
                                        }
                                    }
                                }

                                lock (Locker)
                                {
                                    counter += (long)MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE *
                                               MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE *
                                               MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE;
                                    var prog = Math.Floor(counter / (decimal)counterTotal * 100);
                                    if (prog != progress)
                                    {
                                        progress = prog;
                                        Debug.Write(string.Format("{0:000},", progress));
                                        Console.Write(string.Format("{0:000},", progress));
                                        GC.Collect();
                                    }
                                    threadCounter--;
                                }
                            }, new MyVoxelTaskWorker(baseCoords));

                            task.Start();
                        }
                    }
                }

                GC.Collect();

                while (threadCounter > 0)
                {
                    System.Windows.Forms.Application.DoEvents();
                }

                System.Threading.Thread.Sleep(100);
                System.Windows.Forms.Application.DoEvents();

                #endregion
            }

            timer.Stop();

            if (threadException != null)
            {
                throw threadException;
            }

            voxelMap.UpdateContentBounds();

            var count = voxelMap.SumVoxelCells();

            Debug.WriteLine(" Done. | {0}  | VoxCells {1:#,##0}", timer.Elapsed, count);
            Console.WriteLine(" Done. | {0}  | VoxCells {1:#,##0}", timer.Elapsed, count);
        }
Ejemplo n.º 10
0
        public void FillAsteroid(MyVoxelMap asteroid, IMyVoxelFillProperties fillProperties)
        {
            var properties = (AsteroidByteFillProperties)fillProperties;

            IList <byte>            baseAssets;
            Dictionary <byte, long> materialVoxelCells;

            asteroid.CalculateMaterialCellAssets(out baseAssets, out materialVoxelCells);

            var distribution = new List <double> {
                Double.NaN
            };
            var materialSelection = new List <byte> {
                SpaceEngineersCore.Resources.GetMaterialIndex(properties.MainMaterial.Value)
            };

            if (properties.SecondPercent > 0)
            {
                distribution.Add((double)properties.SecondPercent / 100);
                materialSelection.Add(SpaceEngineersCore.Resources.GetMaterialIndex(properties.SecondMaterial.Value));
            }
            if (properties.ThirdPercent > 0)
            {
                distribution.Add((double)properties.ThirdPercent / 100);
                materialSelection.Add(SpaceEngineersCore.Resources.GetMaterialIndex(properties.ThirdMaterial.Value));
            }
            if (properties.FourthPercent > 0)
            {
                distribution.Add((double)properties.FourthPercent / 100);
                materialSelection.Add(SpaceEngineersCore.Resources.GetMaterialIndex(properties.FourthMaterial.Value));
            }
            if (properties.FifthPercent > 0)
            {
                distribution.Add((double)properties.FifthPercent / 100);
                materialSelection.Add(SpaceEngineersCore.Resources.GetMaterialIndex(properties.FifthMaterial.Value));
            }
            if (properties.SixthPercent > 0)
            {
                distribution.Add((double)properties.SixthPercent / 100);
                materialSelection.Add(SpaceEngineersCore.Resources.GetMaterialIndex(properties.SixthMaterial.Value));
            }
            if (properties.SeventhPercent > 0)
            {
                distribution.Add((double)properties.SeventhPercent / 100);
                materialSelection.Add(SpaceEngineersCore.Resources.GetMaterialIndex(properties.SeventhMaterial.Value));
            }

            var newDistributiuon = new List <byte>();
            int count;

            for (var i = 1; i < distribution.Count(); i++)
            {
                count = (int)Math.Floor(distribution[i] * baseAssets.Count); // Round down.
                for (var j = 0; j < count; j++)
                {
                    newDistributiuon.Add(materialSelection[i]);
                }
            }
            count = baseAssets.Count - newDistributiuon.Count;
            for (var j = 0; j < count; j++)
            {
                newDistributiuon.Add(materialSelection[0]);
            }

            newDistributiuon.Shuffle();
            asteroid.SetMaterialAssets(newDistributiuon);
            //asteroid.ForceVoxelFaceMaterial(_dataModel.BaseMaterial.DisplayName);
        }
Ejemplo n.º 11
0
        public void VoxelLoadSaveVx2V1()
        {
            SpaceEngineersCore.LoadDefinitions();
            var materials = SpaceEngineersCore.Resources.GetMaterialList();

            Assert.IsTrue(materials.Count > 0, "Materials should exist. Has the developer got Space Engineers installed?");

            const string fileOriginal = @".\TestAssets\AsteroidV1Format.vx2";
            const string fileNew      = @".\TestOutput\AsteroidV1Format_save.vx2";

            var voxelMap = new MyVoxelMap();

            voxelMap.Load(fileOriginal, materials[0].Id.SubtypeId);

            IList <byte>            materialAssets;
            Dictionary <byte, long> materialVoxelCells;

            voxelMap.CalculateMaterialCellAssets(out materialAssets, out materialVoxelCells);
            Assert.AreEqual(594485, materialAssets.Count, "Asset count should be equal.");

            var asset0 = materialAssets.Where(c => c == 0).ToList();

            Assert.AreEqual(0, asset0.Count, "asset0 count should be equal.");

            var asset1 = materialAssets.Where(c => c == 1).ToList();

            Assert.AreEqual(0, asset1.Count, "asset1 Asset count should be equal.");

            var asset2 = materialAssets.Where(c => c == 2).ToList();

            Assert.AreEqual(0, asset2.Count, "asset2 Asset count should be equal.");

            var asset3 = materialAssets.Where(c => c == 3).ToList();

            Assert.AreEqual(251145, asset3.Count, "asset3 Asset count should be equal.");

            var asset4 = materialAssets.Where(c => c == 4).ToList();

            Assert.AreEqual(0, asset4.Count, "asset4 Asset count should be equal.");

            var asset5 = materialAssets.Where(c => c == 5).ToList();

            Assert.AreEqual(0, asset5.Count, "asset5 Asset count should be equal.");

            var asset6 = materialAssets.Where(c => c == 6).ToList();

            Assert.AreEqual(217283, asset6.Count, "asset6 Asset count should be equal.");

            var asset7 = materialAssets.Where(c => c == 7).ToList();

            Assert.AreEqual(237, asset7.Count, "asset7 Asset count should be equal.");

            var asset8 = materialAssets.Where(c => c == 8).ToList();

            Assert.AreEqual(9608, asset8.Count, "asset8 Asset count should be equal.");

            var asset9 = materialAssets.Where(c => c == 9).ToList();

            Assert.AreEqual(40801, asset9.Count, "asset9 Asset count should be equal.");

            var asset10 = materialAssets.Where(c => c == 10).ToList();

            Assert.AreEqual(152, asset10.Count, "asset10 Asset count should be equal.");

            var assetNameCount = voxelMap.CountAssets(materialAssets);

            Assert.IsTrue(assetNameCount.Count > 0, "Contains assets.");

            voxelMap.Save(fileNew);

            var lengthOriginal = new FileInfo(fileOriginal).Length;
            var lengthNew      = new FileInfo(fileNew).Length;

            Assert.AreEqual(88299, lengthOriginal, "File size must match.");
            Assert.AreEqual(72296, lengthNew, "File size must match.");
        }
 /// <summary>
 /// Adds the vertices from the physical body (rock) that is inside the given OBB
 /// </summary>
 /// <param name="voxelMap"></param>
 /// <param name="border"></param>
 /// <param name="originPosition"></param>
 /// <param name="obb"></param>
 /// <param name="bbList"></param>
 private void AddVoxelVertices(MyVoxelMap voxelMap, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList)
 {
     AddVoxelMesh(voxelMap, voxelMap.Storage, null, border, originPosition, obb, bbList);
 }
Ejemplo n.º 13
0
        public static MyStorageBase Load(MyVoxelMap voxelMap, string name)
        {
            Debug.Assert(name != null, "Name shouldn't be null");

            MyStorageBase result;
            //If there are some voxels from multiplayer, use them (because it appears that we changed to server from client)
            if (!MySession.Static.VoxelMaps.TryGetStorage(name, out result))
            {
                if (Multiplayer.Sync.IsServer && (MyVoxelMaps.MultiplayerVoxelMaps == null || MyVoxelMaps.MultiplayerVoxelMaps.Count == 0))
                {
                    var filePath = Path.Combine(MySession.Static.CurrentPath, name + MyVoxelConstants.FILE_EXTENSION);
                    result = LoadFromFile(voxelMap, filePath);
                }
                else
                {
                    Debug.Assert(MyVoxelMaps.MultiplayerVoxelMaps != null);
                    Debug.Assert(MyVoxelMaps.MultiplayerVoxelMaps.ContainsKey(name));
                    result = Load(voxelMap, MyVoxelMaps.MultiplayerVoxelMaps[name], name);
                }
            }

            return result;
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Processes an asteroid Voxel using function callbacks.
        /// This allows for muti-threading, and generating content via algorithims.
        /// </summary>
        public static void ProcessAsteroid(MyVoxelMap voxelMap, bool multiThread, byte materialIndex, Action <MyVoxelBuilderArgs> func, bool readWrite = true)
        {
            long    counterTotal = (long)voxelMap.Size.X * voxelMap.Size.Y * voxelMap.Size.Z;
            long    counter      = 0;
            decimal progress     = 0;
            var     timer        = new Stopwatch();

            Debug.Write($"Building Asteroid : {progress:000},");
            Console.Write($"Building Asteroid : {progress:000},");
            Exception threadException = null;

            timer.Start();

            if (!multiThread)
            {
                #region single thread processing

                Vector3I  block;
                const int cellSize  = 64;
                var       cacheSize = Vector3I.Min(new Vector3I(cellSize), voxelMap.Storage.Size);
                var       oldCache  = new MyStorageData();

                // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue.
                for (block.Z = 0; block.Z < voxelMap.Storage.Size.Z; block.Z += cellSize)
                {
                    for (block.Y = 0; block.Y < voxelMap.Storage.Size.Y; block.Y += cellSize)
                    {
                        for (block.X = 0; block.X < voxelMap.Storage.Size.X; block.X += cellSize)
                        {
                            oldCache.Resize(cacheSize);
                            // LOD0 is required to read if you intend to write back to the voxel storage.
                            Vector3I maxRange = block + cacheSize - 1;
                            voxelMap.Storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, maxRange);

                            Vector3I p;
                            for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                            {
                                for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                                {
                                    for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                    {
                                        var coords = block + p;

                                        byte volume       = 0x0;
                                        byte cellMaterial = materialIndex;

                                        if (readWrite)
                                        {
                                            volume       = oldCache.Content(ref p);
                                            cellMaterial = oldCache.Material(ref p);
                                        }

                                        var args = new MyVoxelBuilderArgs(voxelMap.Size, coords, cellMaterial, volume);

                                        try
                                        {
                                            func(args);
                                        }
                                        catch (Exception ex)
                                        {
                                            threadException = ex;
                                            break;
                                        }

                                        if (args.Volume != volume)
                                        {
                                            oldCache.Set(MyStorageDataTypeEnum.Content, ref p, args.Volume);
                                        }

                                        if (args.MaterialIndex != cellMaterial)
                                        {
                                            oldCache.Set(MyStorageDataTypeEnum.Material, ref p, args.MaterialIndex);
                                        }

                                        counter++;
                                        var prog = Math.Floor(counter / (decimal)counterTotal * 100);
                                        if (prog != progress)
                                        {
                                            progress = prog;
                                            Debug.Write($"{progress:000},");
                                        }
                                    }
                                }
                            }

                            voxelMap.Storage.WriteRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, block, maxRange);
                        }
                    }
                }

                #endregion
            }
            else
            {
                #region multi thread processing

                // TODO: re-write the multi thread processing to be more stable.
                // But still try and max out the processors.

                Vector3I  block;
                const int cellSize      = 64;
                var       cacheSize     = Vector3I.Min(new Vector3I(cellSize), voxelMap.Storage.Size);
                long      threadCounter = counterTotal / cellSize / cellSize / cellSize;

                for (block.Z = 0; block.Z < voxelMap.Storage.Size.Z; block.Z += cellSize)
                {
                    for (block.Y = 0; block.Y < voxelMap.Storage.Size.Y; block.Y += cellSize)
                    {
                        for (block.X = 0; block.X < voxelMap.Storage.Size.X; block.X += cellSize)
                        {
                            var oldCache = new MyStorageData();
                            oldCache.Resize(cacheSize);
                            // LOD1 is not detailed enough for content information on asteroids.
                            Vector3I maxRange = block + cacheSize - 1;
                            voxelMap.Storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, maxRange);

                            var task = new Task(obj =>
                            {
                                var bgw = (MyVoxelTaskWorker)obj;

                                Vector3I p;
                                for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                                {
                                    for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                                    {
                                        for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                        {
                                            var coords = bgw.BaseCoords + p;

                                            byte volume       = 0x0;
                                            byte cellMaterial = materialIndex;

                                            if (readWrite)
                                            {
                                                // read the existing material and volume into the arguments before passing the to args for processing.
                                                volume       = bgw.VoxelCache.Content(ref p);
                                                cellMaterial = bgw.VoxelCache.Material(ref p);
                                            }

                                            var args = new MyVoxelBuilderArgs(voxelMap.Size, coords, cellMaterial, volume);

                                            try
                                            {
                                                func(args);
                                            }
                                            catch (Exception ex)
                                            {
                                                threadException = ex;
                                                threadCounter   = 0;
                                                break;
                                            }

                                            if (args.Volume != volume)
                                            {
                                                bgw.VoxelCache.Set(MyStorageDataTypeEnum.Content, ref p, args.Volume);
                                            }

                                            if (args.MaterialIndex != cellMaterial)
                                            {
                                                bgw.VoxelCache.Set(MyStorageDataTypeEnum.Material, ref p, args.MaterialIndex);
                                            }

                                            counter++;
                                            var prog = Math.Floor(counter / (decimal)counterTotal * 100);
                                            if (prog != progress)
                                            {
                                                progress = prog;
                                                Debug.Write($"{progress:000},");
                                            }
                                        }
                                    }
                                }

                                lock (Locker)
                                {
                                    var b       = bgw.BaseCoords;
                                    Vector3I mr = bgw.BaseCoords + cacheSize - 1;
                                    voxelMap.Storage.WriteRange(bgw.VoxelCache, MyStorageDataTypeFlags.ContentAndMaterial, b, mr);

                                    counter += (long)cellSize * cellSize * cellSize;
                                    var prog = Math.Floor(counter / (decimal)counterTotal * 100);
                                    if (prog != progress)
                                    {
                                        progress = prog;
                                        Debug.Write($"{progress:000},");
                                        Console.Write($"{progress:000},");
                                        GC.Collect();
                                    }
                                    threadCounter--;
                                }
                            }, new MyVoxelTaskWorker(block, oldCache));

                            task.Start();
                        }
                    }
                }



                GC.Collect();

                while (threadCounter > 0)
                {
                    System.Windows.Forms.Application.DoEvents();
                }

                System.Threading.Thread.Sleep(100);
                System.Windows.Forms.Application.DoEvents();

                #endregion
            }

            timer.Stop();

            if (threadException != null)
            {
                throw threadException;
            }

            voxelMap.RefreshAssets();

            //voxelMap.UpdateContentBounds();

            Debug.WriteLine($" Done. | {timer.Elapsed}  | VoxCells {voxelMap.VoxCells:#,##0}");
            Console.WriteLine($" Done. | {timer.Elapsed}  | VoxCells {voxelMap.VoxCells:#,##0}");
        }
Ejemplo n.º 15
0
        //  Precalculate voxel cell into cache (makes triangles and vertex buffer from voxels)
        public void Precalc(MyVoxelPrecalcTaskItem task)
        {
            Profiler.Begin("MyVoxelPrecalcTask.Precalc");
            m_precalcType = task.Type;

            m_resultVerticesCounter  = 0;
            m_resultTrianglesCounter = 0;
            m_edgeVertexCalcCounter++;
            m_voxelMap   = task.VoxelMap;
            m_voxelStart = task.VoxelStart;

            int lodIdx = MyVoxelGeometry.GetLodIndex(m_precalcType);

            CalcPolygCubeSize(lodIdx);

            //  Copy voxels into temp array
            //using (Stats.Timing.Measure("NewPrecalc.CopyVoxelContents", MyStatTypeEnum.Sum, clearRateMs: TIMEOUT))
            Profiler.Begin("NewPrecalc.CopyVoxelContents");
            bool isMixed = CopyVoxelContents() == MyVoxelRangeType.MIXED;

            Profiler.End();

            //using (Stats.Timing.Measure("Precalc.Geometry generation", MyStatTypeEnum.Sum, clearRateMs: TIMEOUT))
            Profiler.Begin("Precalc.Geometry generation");
            {
                if (isMixed)
                {
                    var cache = ThreadLocalCache;
                    //  Size of voxel or cell (in meters) and size of voxel map / voxel cells
                    ComputeSizeAndOrigin(lodIdx);

                    var      start  = Vector3I.One;
                    var      end    = m_polygCubes - 1;
                    Vector3I coord0 = start;
                    for (var it = new Vector3I.RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0))
                    {
                        //  We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc.
                        int cubeIndex = 0;
                        if (cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 1;
                        }
                        if (cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 2;
                        }
                        if (cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 4;
                        }
                        if (cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 8;
                        }
                        if (cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 16;
                        }
                        if (cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 32;
                        }
                        if (cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 64;
                        }
                        if (cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                        {
                            cubeIndex |= 128;
                        }

                        //  Cube is entirely in/out of the surface
                        if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0)
                        {
                            continue;
                        }

                        //  We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc.
                        Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(cache, ref coord0, cubeIndex);

                        //  Create the triangles
                        CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0);
                    }
                }
            }
            Profiler.End();

            //using (Stats.Timing.Measure("Precalc.PrepareCache", MyStatTypeEnum.Sum, clearRateMs: TIMEOUT))
            Profiler.Begin("Precalc.PrepareCache");
            {
                // Cache the vertices and triangles and precalculate the octree
                task.Cache.PrepareCache(m_resultVertices, m_resultVerticesCounter, m_resultTriangles, m_resultTrianglesCounter, m_positionScale, m_originPosition, task.Type == MyLodTypeEnum.LOD0);
            }
            Profiler.End();

            Profiler.End();
        }
        private bool ExtractStationIntersect(bool tightIntersection)
        {
            // Make a shortlist of station Entities in the bounding box of the asteroid.
            var asteroidWorldAABB = new BoundingBoxD(DataModel.ContentBounds.Min + DataModel.PositionAndOrientation.Value.Position, DataModel.ContentBounds.Max + DataModel.PositionAndOrientation.Value.Position);
            var stations          = MainViewModel.GetIntersectingEntities(asteroidWorldAABB).Where(e => e.ClassType == ClassType.LargeStation).Cast <StructureCubeGridModel>().ToList();

            if (stations.Count == 0)
            {
                return(false);
            }

            var modified   = false;
            var sourceFile = DataModel.SourceVoxelFilepath ?? DataModel.VoxelFilepath;
            var asteroid   = new MyVoxelMap();

            asteroid.Load(sourceFile, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true);

            var total = stations.Sum(s => s.CubeGrid.CubeBlocks.Count);

            MainViewModel.ResetProgress(0, total);

            // Search through station entities cubes for intersection with this voxel.
            foreach (var station in stations)
            {
                var quaternion = station.PositionAndOrientation.Value.ToQuaternion();

                foreach (var cube in station.CubeGrid.CubeBlocks)
                {
                    MainViewModel.IncrementProgress();

                    var definition = SpaceEngineersApi.GetCubeDefinition(cube.TypeId, station.CubeGrid.GridSizeEnum, cube.SubtypeName);

                    var orientSize    = definition.Size.Transform(cube.BlockOrientation).Abs();
                    var min           = cube.Min.ToVector3() * station.CubeGrid.GridSizeEnum.ToLength();
                    var max           = (cube.Min + orientSize) * station.CubeGrid.GridSizeEnum.ToLength();
                    var p1            = Vector3D.Transform(min, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2);
                    var p2            = Vector3D.Transform(max, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2);
                    var cubeWorldAABB = new BoundingBoxD(Vector3.Min(p1, p2), Vector3.Max(p1, p2));

                    // find worldAABB of block.
                    if (asteroidWorldAABB.Intersects(cubeWorldAABB))
                    {
                        var pointMin = new Vector3I(cubeWorldAABB.Min - DataModel.PositionAndOrientation.Value.Position);
                        var pointMax = new Vector3I(cubeWorldAABB.Max - DataModel.PositionAndOrientation.Value.Position);

                        Vector3I coords;
                        for (coords.Z = pointMin.Z; coords.Z <= pointMax.Z; coords.Z++)
                        {
                            for (coords.Y = pointMin.Y; coords.Y <= pointMax.Y; coords.Y++)
                            {
                                for (coords.X = pointMin.X; coords.X <= pointMax.X; coords.X++)
                                {
                                    if (coords.X >= 0 && coords.Y >= 0 && coords.Z >= 0 && coords.X < asteroid.Size.X && coords.Y < asteroid.Size.Y && coords.Z < asteroid.Size.Z)
                                    {
                                        asteroid.SetVoxelContent(0, ref coords);
                                    }
                                }
                            }
                        }

                        modified = true;
                    }
                }
            }

            MainViewModel.ClearProgress();

            if (modified)
            {
                var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);
                asteroid.Save(tempfilename);
                // replaces the existing asteroid file, as it is still the same size and dimentions.
                DataModel.SourceVoxelFilepath = tempfilename;
            }
            return(modified);
        }
Ejemplo n.º 17
0
        private static MyStorageBase Load(MyVoxelMap voxelMap, Stream stream, string name)
        {
            Profiler.Begin("MyStorageBase.Load");
            try
            {
                string storageType = stream.ReadString();
                int version = stream.Read7BitEncodedInt();
                MyStorageBase storage = null;
                MyVoxelStorageAttribute attr;
                if (!m_attributesByName.TryGetValue(storageType, out attr))
                {
                    Debug.Fail(string.Format("Encountered unknown storage type in voxel file: {0}", storageType));
                    return null;
                }
                storage = Activator.CreateInstance(attr.StorageType, name) as MyStorageBase;
                storage.VoxelMap = voxelMap;
                storage.LoadInternal(version, stream);

                return storage;
            }
            finally
            {
                Profiler.End();
            }
        }
Ejemplo n.º 18
0
 private static MyStorageBase Load(MyVoxelMap voxelMap, byte[] memoryBuffer, string name)
 {
     MyStorageBase storage;
     using (var ms = new MemoryStream(memoryBuffer, false))
     using (var gz = new GZipStream(ms, CompressionMode.Decompress))
     {
         storage = Load(voxelMap, gz, name);
     }
     storage.m_compressedData = memoryBuffer;
     return storage;
 }
Ejemplo n.º 19
0
        private void SubtractAsteroidVolumeFrom(ref MyVoxelMap newAsteroid, Vector3D min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3D minPrimary, Vector3D minSecondary)
        {
            var      filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath;
            var      filenamePrimary   = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath;
            Vector3I coords;

            var asteroid = new MyVoxelMap();

            asteroid.Load(filenamePrimary, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true);

            for (coords.Z = (int)modelPrimary.ContentBounds.Min.Z; coords.Z <= modelPrimary.ContentBounds.Max.Z; coords.Z++)
            {
                for (coords.Y = (int)modelPrimary.ContentBounds.Min.Y; coords.Y <= modelPrimary.ContentBounds.Max.Y; coords.Y++)
                {
                    for (coords.X = (int)modelPrimary.ContentBounds.Min.X; coords.X <= modelPrimary.ContentBounds.Max.X; coords.X++)
                    {
                        byte   volume;
                        string cellMaterial;
                        asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume);

                        var newCoord = ((minPrimary - min) + ((Vector3D)coords - modelPrimary.ContentBounds.Min)).RoundToVector3I();
                        newAsteroid.SetVoxelContent(volume, ref newCoord);
                        newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord);
                    }
                }
            }

            asteroid.Load(filenameSecondary, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true);

            for (coords.Z = (int)modelSecondary.ContentBounds.Min.Z; coords.Z <= modelSecondary.ContentBounds.Max.Z; coords.Z++)
            {
                for (coords.Y = (int)modelSecondary.ContentBounds.Min.Y; coords.Y <= modelSecondary.ContentBounds.Max.Y; coords.Y++)
                {
                    for (coords.X = (int)modelSecondary.ContentBounds.Min.X; coords.X <= modelSecondary.ContentBounds.Max.X; coords.X++)
                    {
                        var newCoord = ((minSecondary - min) + ((Vector3D)coords - modelSecondary.ContentBounds.Min)).RoundToVector3I();
                        if (Vector3I.BoxContains(Vector3I.Zero, modelPrimary.Size - 1, newCoord))
                        {
                            byte   volume;
                            string cellMaterial;
                            asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume);

                            if (volume > 0)
                            {
                                byte   existingVolume;
                                string existingCellMaterial;

                                newAsteroid.GetVoxelMaterialContent(ref newCoord, out existingCellMaterial, out existingVolume);

                                if (existingVolume - volume < 0)
                                {
                                    volume = 0;
                                }
                                else
                                {
                                    volume = (byte)(existingVolume - volume);
                                }

                                newAsteroid.SetVoxelContent(volume, ref newCoord);
                            }
                        }
                    }
                }
            }
        }
 public static void CreateExplosionDebris(ref BoundingSphere explosionSphere, MyGroupMask groupMask, MyEntity entity, MyVoxelMap voxelMap)
 {
     CreateExplosionDebris(ref explosionSphere, groupMask, entity, voxelMap, ref entity.GetModelLod0().BoundingBox);
 }
        private bool BuildEntity()
        {
            var filenamepart = Path.GetFileNameWithoutExtension(Filename);
            var filename     = MainViewModel.CreateUniqueVoxelStorageName(filenamepart + MyVoxelMap.V2FileExtension);

            double multiplier;

            if (IsMultipleScale)
            {
                multiplier = MultipleScale;
            }
            else
            {
                multiplier = MaxLengthScale / Math.Max(Math.Max(OriginalModelSize.Height, OriginalModelSize.Width), OriginalModelSize.Depth);
            }

            var scale           = new ScaleTransform3D(multiplier, multiplier, multiplier);
            var rotateTransform = MeshHelper.TransformVector(new System.Windows.Media.Media3D.Vector3D(0, 0, 0), -RotateRoll, RotateYaw - 90, RotatePitch + 90);

            SourceFile = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);

            var model = MeshHelper.Load(Filename, ignoreErrors: true);

            var meshes      = new List <MyVoxelRayTracer.MyMeshModel>();
            var geometeries = new List <MeshGeometry3D>();

            foreach (var model3D in model.Children)
            {
                var gm       = (GeometryModel3D)model3D;
                var geometry = gm.Geometry as MeshGeometry3D;

                if (geometry != null)
                {
                    geometeries.Add(geometry);
                }
            }
            meshes.Add(new MyVoxelRayTracer.MyMeshModel(geometeries.ToArray(), InsideStockMaterial.MaterialIndex, InsideStockMaterial.MaterialIndex));

            #region handle dialogs and process the conversion

            var doCancel = false;

            var progressModel = new ProgressCancelModel {
                Title = Res.WnProgressTitle, SubTitle = Res.WnProgressTitle, DialogText = Res.WnProgressTxtTimeRemain + " " + Res.WnProgressTxtTimeCalculating
            };
            var progressVm = new ProgressCancelViewModel(this, progressModel);
            progressVm.CloseRequested += delegate(object sender, EventArgs e)
            {
                doCancel = true;
            };

            var cancelFunc = (Func <bool>) delegate
            {
                return(doCancel);
            };

            var completedAction = (Action) delegate
            {
                progressVm.Close();
            };

            MyVoxelMap voxelMap = null;

            var action = (Action) delegate
            {
                voxelMap = MyVoxelRayTracer.ReadModelAsteroidVolmetic(model, meshes, scale, rotateTransform, TraceType, TraceCount, TraceDirection,
                                                                      progressModel.ResetProgress, progressModel.IncrementProgress, cancelFunc, completedAction);
            };

            if (RunInLowPrioity)
            {
                System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Idle;
            }

            _dialogService.ShowDialog <WindowProgressCancel>(this, progressVm, action);

            if (RunInLowPrioity)
            {
                System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Normal;
            }

            #endregion

            if (doCancel || voxelMap == null)
            {
                IsValidEntity = false;
                NewEntity     = null;
            }
            else
            {
                voxelMap.ForceShellMaterial(OutsideStockMaterial.Value, (byte)OutsideMaterialDepth);
                voxelMap.Save(SourceFile);

                var position = VRageMath.Vector3D.Zero;
                var forward  = Vector3.Forward;
                var up       = Vector3.Up;

                if (IsAbsolutePosition)
                {
                    position = Position.ToVector3();
                }
                else if (IsInfrontofPlayer)
                {
                    // Figure out where the Character is facing, and plant the new construct centered in front of the Character, but "BuildDistance" units out in front.
                    var lookVector = (VRageMath.Vector3D)_dataModel.CharacterPosition.Forward.ToVector3();
                    lookVector.Normalize();

                    BoundingBoxD       content = voxelMap.BoundingContent.ToBoundingBoxD();
                    VRageMath.Vector3D?boundingIntersectPoint = content.IntersectsRayAt(content.Center, -lookVector * 5000d);

                    if (!boundingIntersectPoint.HasValue)
                    {
                        boundingIntersectPoint = content.Center;
                    }

                    var distance = VRageMath.Vector3D.Distance(boundingIntersectPoint.Value, content.Center) + (float)BuildDistance;
                    VRageMath.Vector3D vector = lookVector * distance;
                    position = VRageMath.Vector3D.Add(_dataModel.CharacterPosition.Position, vector) - content.Center;
                }

                var entity = new MyObjectBuilder_VoxelMap(position, filename)
                {
                    EntityId        = SpaceEngineersApi.GenerateEntityId(IDType.ASTEROID),
                    PersistentFlags = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene,
                    StorageName     = Path.GetFileNameWithoutExtension(filename)
                };

                entity.PositionAndOrientation = new MyPositionAndOrientation
                {
                    Position = position,
                    Forward  = forward,
                    Up       = up
                };

                IsValidEntity = voxelMap.BoundingContent.Size.Volume() > 0;

                NewEntity = entity;

                if (BeepWhenFinished)
                {
                    System.Media.SystemSounds.Asterisk.Play();
                }
            }

            return(!doCancel);
        }
        public static void CreateExplosionDebris(ref BoundingSphere explosionSphere, MyGroupMask groupMask, MyEntity entity, MyVoxelMap voxelMap, ref BoundingBox bb)
        {
            //  Number of debris is random, but not more than size of the offset array
            float scaleMul = explosionSphere.Radius / 4.0f;

            GeneratePositions(bb);

            foreach (Vector3 positionInLocalSpace in m_positions)
            {
                var positionInWorldSpace = Vector3.Transform(positionInLocalSpace, entity.WorldMatrix);

                MyExplosionDebrisModel newObj = m_objectPool.Allocate(true);

                if (newObj == null)
                {
                    continue;
                }

                //  Check if new object won't intersect any existing triangle - because if yes, then it will decrease JLX performace a lot
                float randomNewScale = MyMwcUtils.GetRandomFloat(scaleMul / 4, scaleMul);
                var   sphere         = new BoundingSphere(positionInWorldSpace, newObj.m_modelLod0.BoundingSphere.Radius * randomNewScale);

                MyEntity myEntitiesGetIntersectionWithSphere = MyEntities.GetIntersectionWithSphere(ref sphere);
                if ((myEntitiesGetIntersectionWithSphere == null || myEntitiesGetIntersectionWithSphere == entity) && (voxelMap == null || !voxelMap.DoOverlapSphereTest(sphere.Radius, sphere.Center)))
                {
                    if (Vector3.DistanceSquared(positionInWorldSpace, explosionSphere.Center) > MyMwcMathConstants.EPSILON_SQUARED)
                    {
                        newObj.Start(positionInWorldSpace, randomNewScale, groupMask, true);
                        newObj.Physics.LinearVelocity = GetDirection(positionInWorldSpace, explosionSphere.Center) * MyExplosionsConstants.EXPLOSION_DEBRIS_SPEED;
                        MyEntities.Add(newObj);

                        if (MyExplosion.DEBUG_EXPLOSIONS)
                        {
                            m_debugVoxelSpheres.Add(sphere);
                        }
                    }
                }
                else
                {
                    // Put back to object pool
                    newObj.Close();
                }
            }
        }
Ejemplo n.º 23
0
        public bool ExtractStationIntersect(IMainView mainViewModel, bool tightIntersection)
        {
            // Make a shortlist of station Entities in the bounding box of the asteroid.
            var asteroidWorldAABB = new BoundingBoxD((Vector3D)ContentBounds.Min + PositionAndOrientation.Value.Position, (Vector3D)ContentBounds.Max + PositionAndOrientation.Value.Position);
            var stations          = mainViewModel.GetIntersectingEntities(asteroidWorldAABB).Where(e => e.ClassType == ClassType.LargeStation).Cast <StructureCubeGridModel>().ToList();

            if (stations.Count == 0)
            {
                return(false);
            }

            var modified   = false;
            var sourceFile = SourceVoxelFilepath ?? VoxelFilepath;
            var asteroid   = new MyVoxelMap();

            asteroid.Load(sourceFile);

            var total = stations.Sum(s => s.CubeGrid.CubeBlocks.Count);

            mainViewModel.ResetProgress(0, total);

            // Search through station entities cubes for intersection with this voxel.
            foreach (var station in stations)
            {
                var quaternion = station.PositionAndOrientation.Value.ToQuaternion();

                foreach (var cube in station.CubeGrid.CubeBlocks)
                {
                    mainViewModel.IncrementProgress();

                    var definition = SpaceEngineersApi.GetCubeDefinition(cube.TypeId, station.CubeGrid.GridSizeEnum, cube.SubtypeName);

                    var orientSize    = definition.Size.Transform(cube.BlockOrientation).Abs();
                    var min           = cube.Min.ToVector3() * station.CubeGrid.GridSizeEnum.ToLength();
                    var max           = (cube.Min + orientSize) * station.CubeGrid.GridSizeEnum.ToLength();
                    var p1            = Vector3D.Transform(min, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2);
                    var p2            = Vector3D.Transform(max, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2);
                    var cubeWorldAABB = new BoundingBoxD(Vector3.Min(p1, p2), Vector3.Max(p1, p2));

                    // find worldAABB of block.
                    if (asteroidWorldAABB.Intersects(cubeWorldAABB))
                    {
                        Vector3I block;
                        var      cacheSize = new Vector3I(64);
                        Vector3D position  = PositionAndOrientation.Value.Position;

                        // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue.
                        for (block.Z = 0; block.Z < asteroid.Storage.Size.Z; block.Z += 64)
                        {
                            for (block.Y = 0; block.Y < asteroid.Storage.Size.Y; block.Y += 64)
                            {
                                for (block.X = 0; block.X < asteroid.Storage.Size.X; block.X += 64)
                                {
                                    var cache = new MyStorageData();
                                    cache.Resize(cacheSize);
                                    // LOD1 is not detailed enough for content information on asteroids.
                                    Vector3I maxRange = block + cacheSize - 1;
                                    asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, block, maxRange);

                                    bool     changed = false;
                                    Vector3I p;
                                    for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                                    {
                                        for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                                        {
                                            for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                            {
                                                BoundingBoxD    voxelCellBox = new BoundingBoxD(position + p + block, position + p + block + 1);
                                                ContainmentType contains     = cubeWorldAABB.Contains(voxelCellBox);

                                                // TODO: finish tightIntersection. Will require high interpretation of voxel content volumes.

                                                if (contains == ContainmentType.Contains || contains == ContainmentType.Intersects)
                                                {
                                                    cache.Content(ref p, 0);
                                                    changed = true;
                                                }
                                            }
                                        }
                                    }

                                    if (changed)
                                    {
                                        asteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.Content, block, maxRange);
                                        modified = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            mainViewModel.ClearProgress();

            if (modified)
            {
                var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);
                asteroid.Save(tempfilename);
                // replaces the existing asteroid file, as it is still the same size and dimentions.
                UpdateNewSource(asteroid, tempfilename);
                MaterialAssets = null;
                InitializeAsync();
            }
            return(modified);
        }
        /// <summary>
        /// Returns a position that should be safe to spawn at given the radius and position.
        /// </summary>
        /// <param name="collisionRadius">The radius of the object that is trying to spawn.</param>
        /// <param name="position">The position the object would like to spawn at.</param>
        /// <param name="forward">(Out) The forward vector the object should spawn with.</param>
        /// <param name="up">(Out) The up vector the object should spawn with.</param>
        /// <param name="planetSpawnHeightRatio">The ratio within the planet's max radius and atmosphere radius you are positioned in.</param>
        /// <param name="randomRangeMin">The minimum randomized distance that is added.</param>
        /// <param name="randomRangeMax">The minimum randomized distance that is added.</param>
        public static void GetSpawnPosition(float collisionRadius, ref Vector3D position, out Vector3D forward, out Vector3D up, float planetSpawnHeightRatio = 0.3f, float randomRangeMin = 500, float randomRangeMax = 650)
        {
            // Are we spawning near a planet?
            Vector3 gravity = MyGravityProviderSystem.CalculateNaturalGravityInPoint(position);

            if (gravity.LengthSquared() > 0)
            {
                MyPlanet planet = MyGravityProviderSystem.GetStrongestGravityWell(position);
                if (planet != null)
                {
                    GetSpawnPositionNearPlanet(planet, collisionRadius, ref position, out forward, out up, planetSpawnHeightRatio, randomRangeMin, randomRangeMax);
                    return;
                }
            }

            // Old logic, testing for asteroids and other objects
            double distance = 0;

            foreach (var entity in MyEntities.GetEntities())
            {
                MyVoxelMap voxelMap = entity as MyVoxelMap;

                // Only test against voxels
                if (entity == null)
                {
                    continue;
                }

                distance = MathHelper.Max(distance, entity.PositionComp.WorldVolume.Center.Length() + entity.PositionComp.WorldVolume.Radius);
            }

            // Random range from last voxel
            distance += MyUtils.GetRandomFloat(randomRangeMin, randomRangeMax);

            if (MyEntities.IsWorldLimited())
            {
                distance = Math.Min(distance, MyEntities.WorldSafeHalfExtent());
            }
            else
            {
                distance = Math.Min(distance, 20000); // limited spawn area in infinite worlds
            }
            // Compute random position
            forward = MyUtils.GetRandomVector3Normalized();
            up      = Vector3D.CalculatePerpendicularVector(forward);
            Vector3D randomizedPosition = position + (forward * distance);

            // Test if we can spawn here
            Vector3D?searchPosition = MyEntities.FindFreePlace(randomizedPosition, collisionRadius);

            if (searchPosition.HasValue)
            {
                randomizedPosition = searchPosition.Value;
            }

            // Make sure we didn't randomize into a planet
            gravity = MyGravityProviderSystem.CalculateNaturalGravityInPoint(randomizedPosition);
            if (gravity.LengthSquared() > 0)
            {
                MyPlanet planet = MyGravityProviderSystem.GetStrongestGravityWell(randomizedPosition);
                if (planet != null)
                {
                    GetSpawnPositionNearPlanet(planet, collisionRadius, ref position, out forward, out up, planetSpawnHeightRatio, randomRangeMin, randomRangeMax);
                }
                else
                {
                    position = randomizedPosition;
                }
            }
            else
            {
                position = randomizedPosition;
            }
        }
Ejemplo n.º 25
0
        public void VoxelMaterialAssetsRandom()
        {
            SpaceEngineersCore.LoadDefinitions();
            var materials = SpaceEngineersCore.Resources.GetMaterialList();

            Assert.IsTrue(materials.Count > 0, "Materials should exist. Has the developer got Space Engineers installed?");

            var stoneMaterial = materials.FirstOrDefault(m => m.Id.SubtypeId.Contains("Stone_05"));

            Assert.IsNotNull(stoneMaterial, "Stone material should exist.");
            var goldMaterial = materials.FirstOrDefault(m => m.Id.SubtypeId.Contains("Gold"));

            Assert.IsNotNull(goldMaterial, "Gold material should exist.");
            var uraniumMaterial = materials.FirstOrDefault(m => m.Id.SubtypeId.Contains("Uraninite_01"));

            Assert.IsNotNull(uraniumMaterial, "Uranium material should exist.");

            const string fileOriginal = @".\TestAssets\Arabian_Border_7.vx2";
            const string fileNewVoxel = @".\TestOutput\Arabian_Border_7_mixed.vx2";

            var voxelMap = new MyVoxelMap();

            voxelMap.Load(fileOriginal, materials[0].Id.SubtypeId);
            IList <byte>            materialAssets;
            Dictionary <byte, long> materialVoxelCells;

            voxelMap.CalculateMaterialCellAssets(out materialAssets, out materialVoxelCells);

            Assert.AreEqual(35465, materialAssets.Count, "Asset count should be equal.");

            var distribution      = new[] { Double.NaN, .5, .25 };
            var materialSelection = new[] { SpaceEngineersCore.Resources.GetMaterialIndex(stoneMaterial.Id.SubtypeId), SpaceEngineersCore.Resources.GetMaterialIndex(goldMaterial.Id.SubtypeId), SpaceEngineersCore.Resources.GetMaterialIndex(uraniumMaterial.Id.SubtypeId) };

            var newDistributiuon = new List <byte>();
            int count;

            for (var i = 1; i < distribution.Count(); i++)
            {
                count = (int)Math.Floor(distribution[i] * materialAssets.Count); // Round down.
                for (var j = 0; j < count; j++)
                {
                    newDistributiuon.Add(materialSelection[i]);
                }
            }
            count = materialAssets.Count - newDistributiuon.Count;
            for (var j = 0; j < count; j++)
            {
                newDistributiuon.Add(materialSelection[0]);
            }

            newDistributiuon.Shuffle();

            var assetNameCount = voxelMap.CountAssets(newDistributiuon);

            Assert.AreEqual(3, assetNameCount.Count, "Asset Mertials count should be equal.");
            Assert.AreEqual(8867, assetNameCount[stoneMaterial.Id.SubtypeId], "Asset Mertials count should be equal.");
            Assert.AreEqual(17732, assetNameCount[goldMaterial.Id.SubtypeId], "Asset Mertials count should be equal.");
            Assert.AreEqual(8866, assetNameCount[uraniumMaterial.Id.SubtypeId], "Asset Mertials count should be equal.");

            voxelMap.SetMaterialAssets(newDistributiuon);

            voxelMap.CalculateMaterialCellAssets(out materialAssets, out materialVoxelCells);
            var cellCount = voxelMap.SumVoxelCells();

            voxelMap.Save(fileNewVoxel);
        }
Ejemplo n.º 26
0
        public void FillAsteroid(MyVoxelMap asteroid, IMyVoxelFillProperties fillProperties)
        {
            var properties = (AsteroidSeedFillProperties)fillProperties;

            /* The full history behind this hack/crutch eludes me.
             * There are roids that won't change their materials unless their face materials forced to something other than current value.
             * So we have to do that manually by setting to a usually unused ore (uranium) and then reverting to the one we chose (=old one in case of a flaky roid)
             */
            byte oldMaterial = asteroid.VoxelMaterial;

            asteroid.ForceVoxelFaceMaterial("Uraninite_01");
            asteroid.ForceVoxelFaceMaterial(properties.MainMaterial.Value);

            // Cycle through veins info and add 'spherical' depisits to the voxel cell grid (not voxels themselves)
            int i;

            if (properties.FirstVeins > 0)
            {
                for (i = 0; i < properties.FirstVeins; i++)
                {
                    asteroid.SeedMaterialSphere(properties.FirstMaterial.Value, (byte)properties.FirstRadius);
                }
            }

            if (properties.SecondVeins > 0)
            {
                for (i = 0; i < properties.SecondVeins; i++)
                {
                    asteroid.SeedMaterialSphere(properties.SecondMaterial.Value, (byte)properties.SecondRadius);
                }
            }

            if (properties.ThirdVeins > 0)
            {
                for (i = 0; i < properties.ThirdVeins; i++)
                {
                    asteroid.SeedMaterialSphere(properties.ThirdMaterial.Value, (byte)properties.ThirdRadius);
                }
            }

            if (properties.FourthVeins > 0)
            {
                for (i = 0; i < properties.FourthVeins; i++)
                {
                    asteroid.SeedMaterialSphere(properties.FourthMaterial.Value, (byte)properties.FourthRadius);
                }
            }

            if (properties.FifthVeins > 0)
            {
                for (i = 0; i < properties.FifthVeins; i++)
                {
                    asteroid.SeedMaterialSphere(properties.FifthMaterial.Value, (byte)properties.FifthRadius);
                }
            }

            if (properties.SixthVeins > 0)
            {
                for (i = 0; i < properties.SixthVeins; i++)
                {
                    asteroid.SeedMaterialSphere(properties.SixthMaterial.Value, (byte)properties.SixthRadius);
                }
            }

            if (properties.SeventhVeins > 0)
            {
                for (i = 0; i < properties.SeventhVeins; i++)
                {
                    asteroid.SeedMaterialSphere(properties.SeventhMaterial.Value, (byte)properties.SeventhRadius);
                }
            }

            // Hide the surface materials up to depth of 2 cells.
            asteroid.ForceShellMaterial(properties.MainMaterial.Value, 2);

            // This recovers material assigning ability for most roids (could be something specific to indestructibleContent property?)
            // And not for all, apparently :(
            //asteroid.ForceVoxelFaceMaterial(_dataModel.BaseMaterial.DisplayName); // don't change mattype

            // doesn't help
            //asteroid.ForceIndestructibleContent(0xff);

            // Alt ends
        }
Ejemplo n.º 27
0
        //  This method realy initiates/starts the missile
        //  IMPORTANT: Direction vector must be normalized!
        public void Start(Vector3 position, Vector3 initialVelocity, Vector3 directionNormalized, MyMwcObjectBuilder_SmallShip_Ammo usedAmmo, MySmallShip minerShip)
        {
            m_usedAmmo = usedAmmo;
            m_ammoProperties = MyAmmoConstants.GetAmmoProperties(usedAmmo.AmmoType);
            m_gameplayProperties = MyGameplayConstants.GetGameplayProperties(m_usedAmmo, Faction);
            m_penetratedVoxelMap = null;
            m_wasPenetration = false;
            m_hasExplosion = false;
            m_isExploded = false;
            m_collidedEntity = null;
            m_collisionPoint = null;
                
            Matrix orientation = GetWorldRotation();
            Vector3 pos = position;

            //  Play missile thrust cue (looping)
            m_thrusterCue = MyAudio.AddCue3D(MySoundCuesEnum.WepMissileFly, pos, orientation.Forward, orientation.Up, this.Physics.LinearVelocity);

            m_light = MyLights.AddLight();
            if (m_light != null)
            {
                m_light.Start(MyLight.LightTypeEnum.PointLight, GetPosition(), MyMissileHelperUtil.GetCannonShotLightColor(), 1, MyMissileConstants.MISSILE_LIGHT_RANGE);
            }

            m_diffuseColor = m_ammoProperties.TrailColor;

            switch (usedAmmo.AmmoType)
            {
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Basic:
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_High_Speed:
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Armor_Piercing_Incendiary:
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_SAPHEI:
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Proximity_Explosive:
                    m_explosionType = MyExplosionTypeEnum.MISSILE_EXPLOSION;
                    break;
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_BioChem:
                    m_explosionType = MyExplosionTypeEnum.BIOCHEM_EXPLOSION;
                    break;
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_EMP:
                    m_explosionType = MyExplosionTypeEnum.EMP_EXPLOSION;
                    break;
                case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Tunnel_Buster:
                    m_explosionType = MyExplosionTypeEnum.BLASTER_EXPLOSION;
                    break;
                default:
                    throw new MyMwcExceptionApplicationShouldNotGetHere();
                    break;
            }

            this.Physics.Mass = m_gameplayProperties.WeightPerUnit;

            Vector3? correctedDirection = null;
            if (MyGameplayConstants.GameplayDifficultyProfile.EnableAimCorrection)
            {
                if (minerShip == MinerWars.AppCode.Game.Managers.Session.MySession.PlayerShip)
                {
                    correctedDirection = MyEntities.GetDirectionFromStartPointToHitPointOfNearestObject(minerShip, position, m_ammoProperties.MaxTrajectory);
                }
            }

            if (correctedDirection != null)
                directionNormalized = correctedDirection.Value;

            base.Start(position, initialVelocity, directionNormalized, m_ammoProperties.DesiredSpeed, minerShip);

            if (correctedDirection != null) //override the base class behaviour, update the missile direction
            {
                Matrix ammoWorld = minerShip.WorldMatrix;
                ammoWorld.Translation = position;
                ammoWorld.Forward = correctedDirection.Value;

                SetWorldMatrix(ammoWorld);
            }

            m_smokeEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_CannonShot);
            m_smokeEffect.AutoDelete = false;
            m_smokeEffect.WorldMatrix = WorldMatrix;
        }
Ejemplo n.º 28
0
        public MyNavigationPrimitive FindClosestPrimitive(Vector3D point, bool highLevel, ref double closestDistanceSq, MyVoxelMap voxelMap = null)
        {
            MyNavigationPrimitive retval = null;

            if (voxelMap != null)
            {
                MyVoxelNavigationMesh mesh = null;
                if (m_navigationMeshes.TryGetValue(voxelMap, out mesh))
                {
                    retval = mesh.FindClosestPrimitive(point, highLevel, ref closestDistanceSq);
                }
            }
            else
            {
                foreach (var entry in m_navigationMeshes)
                {
                    MyNavigationPrimitive closest = entry.Value.FindClosestPrimitive(point, highLevel, ref closestDistanceSq);
                    if (closest != null)
                    {
                        retval = closest;
                    }
                }
            }

            return(retval);
        }
Ejemplo n.º 29
0
        public MyObjectBuilder_EntityBase BuildEntity()
        {
            var asteroidCenter = new VRageMath.Vector3D();
            var asteroidSize   = new Vector3I();

            string originalFile = null;

            if (IsStockVoxel)
            {
                var stockfile = StockVoxel.SourceFilename;

                if (StockMaterial == null || StockMaterial.Value == null)
                {
                    SourceFile   = stockfile;
                    originalFile = SourceFile;
                    var asteroid = new MyVoxelMap();
                    asteroid.Load(stockfile);
                    asteroidCenter = asteroid.BoundingContent.Center;
                    asteroidSize   = asteroid.BoundingContent.SizeInt() + 1; // Content size
                }
                else
                {
                    var asteroid = new MyVoxelMap();
                    asteroid.Load(stockfile);
                    asteroid.ForceBaseMaterial(SpaceEngineersCore.Resources.GetDefaultMaterialName(), StockMaterial.Value);
                    SourceFile = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);
                    asteroid.Save(SourceFile);

                    originalFile   = StockVoxel.SourceFilename;
                    asteroidCenter = asteroid.BoundingContent.Center;
                    asteroidSize   = asteroid.BoundingContent.SizeInt() + 1; // Content size
                }
            }
            else if (IsFileVoxel)
            {
                originalFile = SourceFile;

                var asteroid = new MyVoxelMap();
                asteroid.Load(SourceFile);
                asteroidCenter = asteroid.BoundingContent.Center;
                asteroidSize   = asteroid.BoundingContent.SizeInt() + 1; // Content size

                if (StockMaterial != null && StockMaterial.Value != null)
                {
                    asteroid.ForceBaseMaterial(SpaceEngineersCore.Resources.GetDefaultMaterialName(), StockMaterial.Value);
                    SourceFile = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);
                    asteroid.Save(SourceFile);
                }
            }
            else if (IsSphere)
            {
                string material;
                if (StockMaterial != null && StockMaterial.Value != null)
                {
                    material = StockMaterial.Value;
                }
                else
                {
                    material = SpaceEngineersCore.Resources.GetDefaultMaterialName();
                }

                originalFile = string.Format("sphere_{0}_{1}_{2}{3}", material.ToLowerInvariant(), SphereRadius, SphereShellRadius, MyVoxelMap.V2FileExtension);

                var asteroid = MyVoxelBuilder.BuildAsteroidSphere(SphereRadius > 32, SphereRadius, material, material, SphereShellRadius != 0, SphereShellRadius);
                // TODO: progress bar.
                asteroidCenter = asteroid.BoundingContent.Center;
                asteroidSize   = asteroid.BoundingContent.SizeInt() + 1; // Content size
                SourceFile     = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);
                asteroid.Save(SourceFile);
            }

            // automatically number all files, and check for duplicate filenames.
            Filename = MainViewModel.CreateUniqueVoxelStorageName(originalFile);

            // Figure out where the Character is facing, and plant the new constrcut right in front.
            // Calculate the hypotenuse, as it will be the safest distance to place in front.
            double distance = Math.Sqrt(Math.Pow(asteroidSize.X, 2) + Math.Pow(asteroidSize.Y, 2) + Math.Pow(asteroidSize.Z, 2)) / 2;

            var vector = new BindableVector3DModel(_dataModel.CharacterPosition.Forward).Vector3D;

            vector.Normalize();
            vector   = System.Windows.Media.Media3D.Vector3D.Multiply(vector, distance);
            Position = new BindablePoint3DModel(Point3D.Add(new BindablePoint3DModel(_dataModel.CharacterPosition.Position).Point3D, vector));
            //Forward = new BindableVector3DModel(_dataModel.CharacterPosition.Forward);
            //Up = new BindableVector3DModel(_dataModel.CharacterPosition.Up);
            Forward = new BindableVector3DModel(Vector3.Forward);  // Asteroids currently don't have any orientation.
            Up      = new BindableVector3DModel(Vector3.Up);

            var entity = new MyObjectBuilder_VoxelMap
            {
                EntityId               = SpaceEngineersApi.GenerateEntityId(IDType.ASTEROID),
                PersistentFlags        = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene,
                StorageName            = Path.GetFileNameWithoutExtension(Filename),
                PositionAndOrientation = new MyPositionAndOrientation
                {
                    Position = Position.ToVector3D() - asteroidCenter,
                    Forward  = Forward.ToVector3(),
                    Up       = Up.ToVector3()
                }
            };

            return(entity);
        }
Ejemplo n.º 30
0
 private void RegisterVoxelMapEvents(MyVoxelMap voxelMap)
 {
     voxelMap.OnClose += voxelMap_OnClose;
 }
Ejemplo n.º 31
0
        //  Return reference to voxel map that intersects the box. If not voxel map found, null is returned.
        public static MyVoxelMap GetVoxelMapWhoseBoundingBoxIntersectsBox(ref BoundingBox boundingBox, MyVoxelMap ignoreVoxelMap)
        {
            for (int i = 0; i < m_voxelMaps.Count; i++)
            {
                MyVoxelMap voxelMap = m_voxelMaps[i];
                if (voxelMap != ignoreVoxelMap)
                {
                    if (voxelMap.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref boundingBox) == true)
                    {
                        return(voxelMap);
                    }
                }
            }

            //  If we get here, no intersection was found
            return(null);
        }
        private static MyVoxelCacheCellRender LoadCell(MyVoxelMap voxelMap, ref Vector3I renderCellCoord, MyLodTypeEnum cellHashType)
        {
            Profiler.Begin("AddCell");

            MyVoxelCacheCellRender ret = AddCell(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType);

            ret.Begin(voxelMap, ref renderCellCoord);
            ret.CellHashType = cellHashType;

            Profiler.End();

            if (cellHashType == MyLodTypeEnum.LOD0)
            {
                Profiler.Begin("LOD0 - queue cells");
                m_dataCellsQueue.Clear();

                //  Create normal (LOD0) version
                for (int dataX = 0; dataX < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataX++)
                {
                    for (int dataY = 0; dataY < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataY++)
                    {
                        for (int dataZ = 0; dataZ < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataZ++)
                        {
                            //  Don't precalculate this cells now. Store it in queue and calculate all cells at once by MyVoxelPrecalc.PrecalcQueue()
                            Vector3I dataCellCoord =
                                new Vector3I(
                                    renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataX,
                                    renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataY,
                                    renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataZ);
                            MyVoxelGeometry.CellData cachedDataCell = voxelMap.Geometry.GetCellLater(MyLodTypeEnum.LOD0, ref dataCellCoord);
                            if (cachedDataCell != null)
                            {
                                m_dataCellsQueue.Add(cachedDataCell);
                            }
                        }
                    }
                }

                Profiler.BeginNextBlock("LOD0 - PrecalcQueue");

                //  Precalculate all queued data cells in parallel threads - using multiple cores if possible.
                MyVoxelPrecalc.PrecalcQueue();

                Profiler.BeginNextBlock("LOD0 - AddTriangles");
                ret.AddTriangles(m_dataCellsQueue);
                Profiler.End();
            }
            else if (cellHashType == MyLodTypeEnum.LOD1)
            {
                Profiler.Begin("LOD1 - PrecalcImmediatelly");

                m_helperLodCachedDataCell.Reset();

                //  Create LOD1 render cell
                MyVoxelPrecalc.PrecalcImmediatelly(
                    new MyVoxelPrecalcTaskItem(
                        MyLodTypeEnum.LOD1,
                        voxelMap,
                        m_helperLodCachedDataCell,
                        new Vector3I(
                            renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS,
                            renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS,
                            renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS)));


                Profiler.BeginNextBlock("LOD1 - AddTriangles");
                m_dataCellsQueue.Clear();
                m_dataCellsQueue.Add(m_helperLodCachedDataCell);
                ret.AddTriangles(m_dataCellsQueue);
                Profiler.End();
            }
            else
            {
                throw new InvalidBranchException();
            }

            ret.End();

            return(ret);
        }
Ejemplo n.º 33
0
        public void SaveCheckPointAndSandBox()
        {
            IsBusy = true;
            ActiveWorld.SaveCheckPointAndSector(true);

            // Manages the adding of new voxel files.
            foreach (var entity in Structures)
            {
                if (entity is StructureVoxelModel)
                {
                    var voxel = (StructureVoxelModel)entity;
                    if (voxel.SourceVoxelFilepath != null && File.Exists(voxel.SourceVoxelFilepath))
                    {
                        // Any asteroid that already exists with same name, must be removed.
                        if (File.Exists(voxel.VoxelFilepath))
                        {
                            FileSystem.DeleteFile(voxel.VoxelFilepath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
                        }

                        if (Path.GetExtension(voxel.SourceVoxelFilepath).Equals(MyVoxelMap.V1FileExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            // Convert between formats.
                            var voxelmap = new MyVoxelMap();
                            voxelmap.Load(voxel.SourceVoxelFilepath, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true);
                            voxelmap.Save(voxel.VoxelFilepath);
                        }
                        else
                        {
                            File.Copy(voxel.SourceVoxelFilepath, voxel.VoxelFilepath);
                        }
                        voxel.SourceVoxelFilepath = null;
                    }
                }

                if (entity is StructurePlanetModel)
                {
                    var voxel = (StructurePlanetModel)entity;
                    if (voxel.SourceVoxelFilepath != null && File.Exists(voxel.SourceVoxelFilepath))
                    {
                        // Any asteroid that already exists with same name, must be removed.
                        if (File.Exists(voxel.VoxelFilepath))
                        {
                            FileSystem.DeleteFile(voxel.VoxelFilepath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
                        }

                        File.Copy(voxel.SourceVoxelFilepath, voxel.VoxelFilepath);
                        voxel.SourceVoxelFilepath = null;
                    }
                }
            }

            // Manages the removal old voxels files.
            foreach (var file in SpaceEngineersCore.ManageDeleteVoxelList)
            {
                var filename = Path.Combine(ActiveWorld.Savepath, file);
                if (File.Exists(filename))
                {
                    FileSystem.DeleteFile(filename, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
                }
            }
            SpaceEngineersCore.ManageDeleteVoxelList.Clear();

            IsModified = false;
            IsBusy     = false;
        }
Ejemplo n.º 34
0
        public MyObjectBuilder_EntityBase BuildEntity()
        {
            // Realign both asteroids to a common grid, so voxels can be lined up.
            Vector3I roundedPosLeft  = SelectionLeft.WorldAABB.Min.RoundToVector3I();
            Vector3D offsetPosLeft   = SelectionLeft.WorldAABB.Min - (Vector3D)roundedPosLeft;   // Use for everything.
            Vector3I roundedPosRight = (SelectionRight.WorldAABB.Min - offsetPosLeft).RoundToVector3I();
            Vector3D offsetPosRight  = SelectionRight.WorldAABB.Min - (Vector3D)roundedPosRight; // Use for everything.

            // calculate smallest allowable size for contents of both.
            const int paddCells = 3;

            // Force a calculation of the ContentBounds, as multi select in the ListView doesn't necessarily make it happen, or make it happen fast enough.
            SelectionLeft.LoadDetailsSync();
            SelectionRight.LoadDetailsSync();

            var minLeft      = SelectionLeft.WorldAABB.Min + SelectionLeft.InflatedContentBounds.Min - offsetPosLeft;
            var minRight     = SelectionRight.WorldAABB.Min + SelectionRight.InflatedContentBounds.Min - offsetPosRight;
            var min          = Vector3D.Zero;
            var posOffset    = Vector3D.Zero;
            var asteroidSize = Vector3I.Zero;

            switch (VoxelMergeType)
            {
            case VoxelMergeType.UnionVolumeLeftToRight:
            case VoxelMergeType.UnionVolumeRightToLeft:
                min = Vector3D.Min(minLeft, minRight) - paddCells;
                var max = Vector3D.Max(SelectionLeft.WorldAABB.Min + SelectionLeft.InflatedContentBounds.Max - offsetPosLeft, SelectionRight.WorldAABB.Min + SelectionRight.InflatedContentBounds.Max - offsetPosRight) + paddCells;
                posOffset = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z);
                var size = (max - min).RoundToVector3I();
                asteroidSize = MyVoxelBuilder.CalcRequiredSize(size);
                break;

            case VoxelMergeType.UnionMaterialLeftToRight:
                min          = SelectionRight.WorldAABB.Min - offsetPosRight;
                posOffset    = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z);
                asteroidSize = SelectionRight.Size;
                break;

            case VoxelMergeType.UnionMaterialRightToLeft:
                min          = SelectionLeft.WorldAABB.Min - offsetPosLeft;
                posOffset    = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z);
                asteroidSize = SelectionLeft.Size;
                break;

            case VoxelMergeType.SubtractVolumeLeftFromRight:
                min          = SelectionRight.WorldAABB.Min - offsetPosRight;
                posOffset    = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z);
                asteroidSize = SelectionRight.Size;
                break;

            case VoxelMergeType.SubtractVolumeRightFromLeft:
                min          = SelectionLeft.WorldAABB.Min - offsetPosLeft;
                posOffset    = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z);
                asteroidSize = SelectionLeft.Size;
                break;
            }

            // Prepare new asteroid.
            var newAsteroid = new MyVoxelMap();

            newAsteroid.Create(asteroidSize, SpaceEngineersCore.Resources.GetDefaultMaterialIndex());
            if (string.IsNullOrEmpty(MergeFileName))
            {
                MergeFileName = "merge";
            }
            var filename = MainViewModel.CreateUniqueVoxelStorageName(MergeFileName);

            // merge.
            switch (VoxelMergeType)
            {
            case VoxelMergeType.UnionVolumeLeftToRight:
                MergeAsteroidVolumeInto(ref newAsteroid, min, SelectionRight, SelectionLeft, minRight, minLeft);
                break;

            case VoxelMergeType.UnionVolumeRightToLeft:
                MergeAsteroidVolumeInto(ref newAsteroid, min, SelectionLeft, SelectionRight, minLeft, minRight);
                break;

            case VoxelMergeType.UnionMaterialLeftToRight:
                MergeAsteroidMaterialFrom(ref newAsteroid, min, SelectionRight, SelectionLeft, minRight, minLeft);
                break;

            case VoxelMergeType.UnionMaterialRightToLeft:
                MergeAsteroidMaterialFrom(ref newAsteroid, min, SelectionLeft, SelectionRight, minLeft, minRight);
                break;

            case VoxelMergeType.SubtractVolumeLeftFromRight:
                SubtractAsteroidVolumeFrom(ref newAsteroid, min, SelectionRight, SelectionLeft, minRight, minLeft);
                break;

            case VoxelMergeType.SubtractVolumeRightFromLeft:
                SubtractAsteroidVolumeFrom(ref newAsteroid, min, SelectionLeft, SelectionRight, minLeft, minRight);
                break;
            }

            // Generate Entity
            var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);

            newAsteroid.Save(tempfilename);
            SourceFile = tempfilename;

            var position = min + posOffset;
            var entity   = new MyObjectBuilder_VoxelMap(position, filename)
            {
                EntityId               = SpaceEngineersApi.GenerateEntityId(IDType.ASTEROID),
                PersistentFlags        = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene,
                StorageName            = Path.GetFileNameWithoutExtension(filename),
                PositionAndOrientation = new MyPositionAndOrientation
                {
                    Position = position,
                    Forward  = Vector3.Forward,
                    Up       = Vector3.Up
                }
            };

            return(entity);
        }
        public void BuildEntities(out string[] sourceVoxelFiles, out MyObjectBuilder_EntityBase[] sourceEntities)
        {
            var entities    = new List <MyObjectBuilder_EntityBase>();
            var sourceFiles = new List <string>();

            MainViewModel.ResetProgress(0, VoxelCollection.Count);

            foreach (var voxelDesign in VoxelCollection)
            {
                MainViewModel.Progress++;
                if (string.IsNullOrEmpty(voxelDesign.VoxelFile.SourceFilename) || !MyVoxelMap.IsVoxelMapFile(voxelDesign.VoxelFile.SourceFilename))
                {
                    continue;
                }


                var    asteroid           = new MyVoxelMap();
                string tempSourcefilename = null;

                switch (AsteroidFillType)
                {
                case Support.AsteroidFillType.None:
                    asteroid.Load(voxelDesign.VoxelFile.SourceFilename, voxelDesign.MainMaterial.Value, false);
                    tempSourcefilename = voxelDesign.VoxelFile.SourceFilename;
                    break;

                case AsteroidFillType.ByteFiller:
                    asteroid.Load(voxelDesign.VoxelFile.SourceFilename, voxelDesign.MainMaterial.Value, false);
                    var filler = new AsteroidByteFiller();
                    filler.FillAsteroid(asteroid, voxelDesign);
                    tempSourcefilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);
                    asteroid.Save(tempSourcefilename);
                    break;
                }


                // automatically number all files, and check for duplicate filenames.
                var filename = MainViewModel.CreateUniqueVoxelStorageName(voxelDesign.VoxelFile.Name + MyVoxelMap.V2FileExtension, entities.ToArray());

                var radius    = RandomUtil.GetDouble(MinimumRange, MaximumRange);
                var longitude = RandomUtil.GetDouble(0, 2 * Math.PI);
                var latitude  = RandomUtil.GetDouble(-Math.PI / 2, (Math.PI / 2) + double.Epsilon);

                // Test data. Place asteroids items into a circle.
                //radius = 500;
                //longitude = Math.PI * 2 * ((double)voxelDesign.Index / VoxelCollection.Count);
                //latitude = 0;

                var x = radius * Math.Cos(latitude) * Math.Cos(longitude);
                var z = radius * Math.Cos(latitude) * Math.Sin(longitude);
                var y = radius * Math.Sin(latitude);

                var center   = new Vector3D(CenterPositionX, CenterPositionY, CenterPositionZ);
                var position = center + new Vector3D(x, y, z) - asteroid.BoundingContent.Center;
                var entity   = new MyObjectBuilder_VoxelMap(position, filename)
                {
                    EntityId               = SpaceEngineersApi.GenerateEntityId(IDType.ASTEROID),
                    PersistentFlags        = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene,
                    StorageName            = Path.GetFileNameWithoutExtension(filename),
                    PositionAndOrientation = new MyPositionAndOrientation
                    {
                        Position = position,
                        Forward  = Vector3.Forward, // Asteroids currently don't have any orientation.
                        Up       = Vector3.Up
                    }
                };

                entities.Add(entity);
                sourceFiles.Add(tempSourcefilename);
            }

            sourceVoxelFiles = sourceFiles.ToArray();
            sourceEntities   = entities.ToArray();
        }
Ejemplo n.º 36
0
        private void SubtractAsteroidVolumeFrom(ref MyVoxelMap newAsteroid, Vector3D min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3D minPrimary, Vector3D minSecondary)
        {
            var      filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath;
            var      filenamePrimary   = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath;
            Vector3I block;
            Vector3I newBlock;
            Vector3I cacheSize;

            var asteroid = new MyVoxelMap();

            asteroid.Load(filenamePrimary);
            BoundingBoxI content = modelPrimary.InflatedContentBounds;

            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        newBlock = ((minPrimary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        newAsteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }

            asteroid.Load(filenameSecondary);
            content = modelSecondary.InflatedContentBounds;
            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, block, block + cacheSize - 1);

                        newBlock = ((minSecondary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        var newCache = new MyStorageData();
                        newCache.Resize(cacheSize);
                        newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1);

                        Vector3I p;
                        for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                        {
                            for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                            {
                                for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                {
                                    byte volume = cache.Content(ref p);
                                    if (volume > 0)
                                    {
                                        byte existingVolume = newCache.Content(ref p);

                                        if (existingVolume - volume < 0)
                                        {
                                            volume = 0;
                                        }
                                        else
                                        {
                                            volume = (byte)(existingVolume - volume);
                                        }
                                        newCache.Content(ref p, volume);
                                    }
                                }
                            }
                        }

                        newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }
        }
Ejemplo n.º 37
0
        /// <summary>
        /// Starts the explosion.
        /// </summary>
        /// <param name="damage"></param>
        /// <param name="type"></param>
        /// <param name="explosionSphere"></param>
        /// <param name="lifespanInMiliseconds"></param>
        /// <param name="explosionForceDirection"></param>
        /// <param name="groupMask"></param>
        /// <param name="createExplosionDebris"></param>
        /// <param name="cascadeLevel"></param>
        /// <param name="hitEntity"></param>
        /// <param name="particleScale"></param>
        /// <param name="ownerEntity"></param>
        /// <param name="affectVoxels"></param>
        /// <param name="applyForceAndDamage"></param>
        /// <param name="createDecals"></param>
        /// <param name="direction">If applicable, gives the direction of the explosion, e.g. when it was caused by a missile (with its moving direction).</param>
        public void Start(ref MyExplosionInfo explosionInfo)
        {
            //MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius <= MyExplosionsConstants.EXPLOSION_RADIUS_MAX);
            MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius > 0);

            MyRender.GetRenderProfiler().StartProfilingBlock("MyExplosion.Start");

            m_explosionSphere       = explosionInfo.ExplosionSphere;
            m_elapsedMiliseconds    = 0;
            m_lifespanInMiliseconds = explosionInfo.LifespanMiliseconds;

            if (explosionInfo.PlaySound)
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("Sound");
                //  Play explosion sound
                if (m_explosionCue != null && m_explosionCue.Value.IsPlaying)
                {
                    m_explosionCue.Value.Stop(SharpDX.XACT3.StopFlags.Immediate);
                }
                m_explosionCue = MyAudio.AddCue3D(GetCueEnumByExplosionType(explosionInfo.ExplosionType), m_explosionSphere.Center, Vector3.Zero, Vector3.Zero, Vector3.Zero);
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            MyRender.GetRenderProfiler().StartProfilingBlock("Light");
            //  Light of explosion

            /*
             * m_light = MyLights.AddLight();
             * if (m_light != null)
             * {
             *  m_light.Start(MyLight.LightTypeEnum.PointLight, m_explosionSphere.Center, MyExplosionsConstants.EXPLOSION_LIGHT_COLOR, 1, Math.Min(m_explosionSphere.Radius * 8.0f, MyLightsConstants.MAX_POINTLIGHT_RADIUS));
             *  m_light.Intensity = 2.0f;
             * } */
            MyRender.GetRenderProfiler().EndProfilingBlock();

            // close explosion check
            bool close = IsExplosionClose(explosionInfo.ExplosionSphere);

            MyParticleEffectsIDEnum newParticlesType;

            switch (explosionInfo.ExplosionType)
            {
            case MyExplosionTypeEnum.SMALL_SHIP_EXPLOSION:
                //  Create metal debris objects thrown from the explosion
                //  This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris)
                //  Throw a lot of debrises, more than only if some metalic object is hit (because this is destruction of a ship)
                //MyPhysObjectExplosionDebrises.CreateExplosionDebris(m_explosionSphere.Center, 1);
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Smallship;
                break;

            case MyExplosionTypeEnum.MISSILE_EXPLOSION:
                newParticlesType =
                    // ? MyParticleEffectsIDEnum.Explosion_Missile_Close
                    MyParticleEffectsIDEnum.Explosion_Missile;
                break;

            case MyExplosionTypeEnum.BOMB_EXPLOSION:
            case MyExplosionTypeEnum.GRAVITY_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Bomb;
                break;

            case MyExplosionTypeEnum.AMMO_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Ammo;
                break;

            case MyExplosionTypeEnum.BLASTER_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Blaster;
                break;

            case MyExplosionTypeEnum.BIOCHEM_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_BioChem;
                break;

            case MyExplosionTypeEnum.EMP_EXPLOSION:
            case MyExplosionTypeEnum.FLASH_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_EMP;
                break;

            case MyExplosionTypeEnum.METEOR_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Meteor;
                break;

            case MyExplosionTypeEnum.NUCLEAR_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Nuclear;
                break;

            case MyExplosionTypeEnum.PLASMA_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Plasma;
                break;

            case MyExplosionTypeEnum.SMALL_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_SmallPrefab;
                break;

            case MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Huge;
                break;

            case MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Large;
                break;

            case MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Medium;
                break;

            case MyExplosionTypeEnum.ASTEROID_EXPLOSION:
                newParticlesType = MyParticleEffectsIDEnum.Explosion_Asteroid;
                break;

            default:
                throw new System.NotImplementedException();
                break;
            }


            if (explosionInfo.Damage > 0)
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("Voxel or collision");

                //  If explosion sphere intersects a voxel map, we need to cut out a sphere, spawn debrises, etc
                MyVoxelMap voxelMap = explosionInfo.AffectVoxels && explosionInfo.EmpDamage == 0 ? MyVoxelMaps.GetOverlappingWithSphere(ref m_explosionSphere) : null;
                if (voxelMap != null)
                {
                    //  Dirty explosion with a lot of dust

                    MyMwcVoxelMaterialsEnum?voxelMaterial = null;
                    float voxelContentRemovedInPercent    = 0;

                    bool createDebris = true;            // We want to create debris

                    if (explosionInfo.HitEntity != null) // but not when we hit prefab
                    {
                        createDebris &= explosionInfo.HitEntity is MyVoxelMap;
                    }


                    //cut off
                    BoundingSphere voxelExpSphere = new BoundingSphere(explosionInfo.VoxelExplosionCenter, m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale);
                    if (MyVoxelGenerator.CutOutSphereFast(voxelMap, voxelExpSphere, out voxelContentRemovedInPercent, out voxelMaterial, (explosionInfo.OwnerEntity is MySmallShip && explosionInfo.OwnerEntity == Managers.Session.MySession.PlayerShip), MyFakes.VOXELS_REMOVE_RATIO))
                    {
                        if (explosionInfo.HitEntity is MyVoxelMap)
                        {
                            HUD.MyHud.ShowIndestructableAsteroidNotification();
                        }
                        createDebris = false; // and no debris when voxel is indestructible
                    }

                    //  Only if at least something was removed from voxel map
                    //  If voxelContentRemovedInPercent is more than zero than also voxelMaterial shouldn't be null, but I rather check both of them.
                    if ((voxelContentRemovedInPercent > 0) && (voxelMaterial != null))
                    {
                        //remove decals
                        MyDecals.HideTrianglesAfterExplosion(voxelMap, ref voxelExpSphere);

                        MyRender.GetRenderProfiler().StartProfilingBlock("CreateDebris");

                        if (explosionInfo.CreateDebris && (createDebris || explosionInfo.ForceDebris) && MyRenderConstants.RenderQualityProfile.ExplosionDebrisCountMultiplier > 0)
                        {
                            //  Create debris rocks thrown from the explosion
                            //  This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris)
                            MyExplosionDebrisVoxel.CreateExplosionDebris(ref voxelExpSphere, voxelContentRemovedInPercent, voxelMaterial.Value, explosionInfo.GroupMask, voxelMap);
                        }

                        MyRender.GetRenderProfiler().EndProfilingBlock();

                        MyRender.GetRenderProfiler().StartProfilingBlock("CreateParticleEffect");

                        MyParticleEffect explosionEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.MaterialExplosion_Destructible);
                        explosionEffect.WorldMatrix          = Matrix.CreateTranslation(voxelExpSphere.Center);
                        explosionEffect.UserRadiusMultiplier = voxelExpSphere.Radius;

                        MyRender.GetRenderProfiler().EndProfilingBlock();
                    }
                }
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            if (explosionInfo.Damage > 0)
            {
                //  Create dirt decals in player's cockpit glass
                MyRender.GetRenderProfiler().StartProfilingBlock("Cockpit Decals");
                CreateDirtDecalOnCockpitGlass(ref m_explosionSphere);
                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            if (DEBUG_EXPLOSIONS)
            {
                MyRender.GetRenderProfiler().EndProfilingBlock();
                return;
            }

            if (explosionInfo.Damage > 0)
            {
                BoundingSphere influenceExplosionSphere = m_explosionSphere;
                influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_RADIUS_MULTPLIER_FOR_IMPULSE;
                for (int i = 0; i < explosionInfo.CascadeLevel; i++)
                {
                    influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_CASCADE_FALLOFF;
                }

                //  Throws surrounding objects away from centre of the explosion.
                if (explosionInfo.ApplyForceAndDamage)
                {
                    if (explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION ||
                        explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION ||
                        explosionInfo.ExplosionType == MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION)
                    {
                        DisableContainedDummyParticles(ref explosionInfo);
                    }

                    explosionInfo.StrengthImpulse        = MyExplosionsConstants.EXPLOSION_STRENGTH_IMPULSE * m_explosionSphere.Radius / 20;
                    explosionInfo.StrengthAngularImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_ANGULAR_IMPULSE;
                    explosionInfo.HitEntity = explosionInfo.HitEntity != null?explosionInfo.HitEntity.GetBaseEntity() : null;

                    MyRender.GetRenderProfiler().StartProfilingBlock("ApplyExplosionForceAndDamage");
                    MyEntities.ApplyExplosionForceAndDamage(ref explosionInfo);
                    MyRender.GetRenderProfiler().EndProfilingBlock();
                }

                //  Look for objects in explosion radius
                BoundingBox boundingBox;
                BoundingBox.CreateFromSphere(ref influenceExplosionSphere, out boundingBox);

                //if (explosionInfo.CreateDecals && explosionInfo.Direction.HasValue && explosionInfo.EmpDamage == 0)
                //{
                //    CreateDecals(explosionInfo.Direction.Value);
                //}
            }

            if (explosionInfo.CreateParticleEffect)
            {
                MyRender.GetRenderProfiler().StartProfilingBlock("Particles");

                if (explosionInfo.CustomEffect != null)
                {
                    if (explosionInfo.CustomEffect.ParticleID == 0)
                    {
                        explosionInfo.CustomEffect.ParticleID = (int)newParticlesType;
                    }
                    //Reload effect
                    explosionInfo.CustomEffect.Enabled = false;
                    explosionInfo.CustomEffect.Enabled = true;
                }
                else
                {
                    //  Explosion particles
                    GenerateExplosionParticles(newParticlesType, m_explosionSphere, explosionInfo.ParticleScale);
                }

                MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            MyRender.GetRenderProfiler().EndProfilingBlock();

            /*
             *  // When MyAmmoBase entity is closed to explosion it will explode
             *  if (entity is MyAmmoBase)
             *  {
             *      (entity as MyAmmoBase).ExplodeCascade(cascadeLevel + 1);
             *  }
             */

            //  Smut decals - must be called after the explosion, after voxels are cutted out

            /*if ((intersection.PhysObject is MyVoxelMap) == false)
             * {
             *  if (intersection.PhysObject is MyCockpitGlass)
             *  {
             *      //  Change phys object so rest of the code will think we hit the parent
             *      //  Same fix is in projectile too - because cockpit glass is only helper object, we don't use it for real rendering and stuff
             *      //  And if not changed, it can make problem in "phys object decals"
             *      intersection.PhysObject = intersection.PhysObject.Parent;
             *  }
             *
             *  //  Create explosion smut decal on model we hit by this missile
             *  MyDecals.Add(
             *      MyDecalTexturesEnum.ExplosionSmut,
             *      MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.7f, m_explosionSphere.Radius * 1.3f),
             *      MyMwcUtils.GetRandomRadian(),
             *      GetSmutDecalRandomColor(),
             *      true,
             *      ref intersection);
             * }
             * else
             * {
             *  //  Creating explosion smut decal on voxel is more complicated than on voxel. We will project few lines
             *  //  from explosion epicentrum to the surounding world (random directions) and place decal where intersection detected.
             *  //if (knownMissileDirection != null)
             *  //{
             *  //    MyLine linePrologned = new MyLine(knownIntersection.Value.IntersectionPointInObjectSpace,
             *  //        knownIntersection.Value.IntersectionPointInObjectSpace + knownMissileDirection.Value * MyExplosionsConstants.EXPLOSION_RANDOM_RADIUS_MAX * 2,
             *  //        true);
             *  //    MyLineTriangleIntersectionResult intersectionForSmut = knownIntersection.Value.VoxelMap.GetIntersectionWithLine(ref linePrologned);
             *  //    if (intersectionForSmut.Found == true)
             *  //    {
             *  //        MyDecals.Add(
             *  //            MyDecalTexturesEnum.ExplosionSmut,
             *  //            MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.5f, m_explosionSphere.Radius * 1.0f),
             *  //            MyMwcUtils.GetRandomRadian(),
             *  //            GetSmutDecalRandomColor(),
             *  //            false,
             *  //            ref intersectionForSmut);
             *  //    }
             *  //}
             * }*/

            //  Generate dust particles that will stay in place of the explosion
            //doesnt look good in final
            //GenerateStatisDustParticles(m_explosionSphere);
        }
Ejemplo n.º 38
0
        //  Return reference to a voxel map that intersects with the specified box. If not intersection, null is returned.
        //  We don't look for closest intersection - so we stop on first intersection found.
        //  Params:
        //      localBoundingBox - local bounding box, we transform it to VoxelMap orientation
        //      boundingBoxWorldPosition - position of bounding box in world coordinates
        public static MyVoxelMap GetIntersectionWithBox(ref BoundingBox localBoundingBox, ref Vector3 boundingBoxWorldPosition, MyVoxelMap selected)
        {
            for (int i = 0; i < m_voxelMaps.Count; i++)
            {
                if (selected == null || m_voxelMaps[i] == selected)
                {
                    MyVoxelMap  voxelMap         = m_voxelMaps[i];
                    Matrix      world            = Matrix.CreateWorld(boundingBoxWorldPosition, voxelMap.WorldMatrix.Forward, voxelMap.WorldMatrix.Up);
                    BoundingBox worldBoundingBox = localBoundingBox.Transform(world);
                    if (voxelMap.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref worldBoundingBox))
                    {
                        return(voxelMap);
                    }
                }
            }

            //  No intersection found
            return(null);
        }
Ejemplo n.º 39
0
 public void Init(MyMwcObjectBuilder_VoxelHand_Sphere objectBuilder, MyVoxelMap parentVoxelMap)
 {
     base.Init(objectBuilder, parentVoxelMap);
     this.Radius = objectBuilder.Radius;
     UpdateLocalVolume();
 }
Ejemplo n.º 40
0
        public static MyStorageBase LoadFromFile(MyVoxelMap voxelMap, string absoluteFilePath)
        {
            if (!MyFileSystem.FileExists(absoluteFilePath))
            {
                var oldPath = Path.ChangeExtension(absoluteFilePath, "vox");
                UpdateFileFormat(oldPath);
                Debug.Assert(MyFileSystem.FileExists(absoluteFilePath));
            }
            Debug.Assert(absoluteFilePath.EndsWith(MyVoxelConstants.FILE_EXTENSION));

            byte[] compressedData = null;
            using (var file = MyFileSystem.OpenRead(absoluteFilePath))
            {
                compressedData = new byte[file.Length];
                file.Read(compressedData, 0, compressedData.Length);
            }
            return Load(voxelMap, compressedData, Path.GetFileNameWithoutExtension(absoluteFilePath));
        }
Ejemplo n.º 41
0
        private void MergeAsteroidVolumeInto(ref MyVoxelMap newAsteroid, Vector3D min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3D minPrimary, Vector3D minSecondary)
        {
            var      filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath;
            var      filenamePrimary   = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath;
            Vector3I block;
            Vector3I newBlock;
            Vector3I cacheSize;

            var asteroid = new MyVoxelMap();

            asteroid.Load(filenameSecondary);
            BoundingBoxI content = modelSecondary.InflatedContentBounds;

            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        newBlock = ((minSecondary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        newAsteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }

            asteroid.Load(filenamePrimary);
            content = modelPrimary.InflatedContentBounds;
            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        newBlock = ((minPrimary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        var newCache = new MyStorageData();
                        newCache.Resize(cacheSize);
                        newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1);

                        Vector3I p;
                        for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                        {
                            for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                            {
                                for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                {
                                    byte volume   = cache.Content(ref p);
                                    byte material = cache.Material(ref p);
                                    if (volume > 0)
                                    {
                                        byte existingVolume = newCache.Content(ref p);
                                        if (volume > existingVolume)
                                        {
                                            newCache.Content(ref p, volume);
                                        }
                                        // Overwrites secondary material with primary.
                                        newCache.Material(ref p, material);
                                    }
                                    else
                                    {
                                        // try to find cover material.
                                        Vector3I[] points = CreateTestPoints(p, cacheSize - 1);
                                        for (int i = 0; i < points.Length; i++)
                                        {
                                            byte testVolume = cache.Content(ref points[i]);
                                            if (testVolume > 0)
                                            {
                                                material = cache.Material(ref points[i]);
                                                newCache.Material(ref p, material);
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }
        }
Ejemplo n.º 42
0
        //public static event OnVoxelShapeSizeChanged OnVoxelShapeSize;
        //public static event OnVoxelShapeDistanceChanged OnVoxelShapeDistance;

        public static void HandleInput(MyGuiInput input)
        {
            // exit voxel hand using this key
            if (input.IsEditorControlNewPressed(MyEditorControlEnums.VOXEL_HAND))
            {
                SwitchEnabled();
            }

            if (m_Enabled == false || !IsAnyEditorActive())
            {
                return;
            }

            m_applyToVoxelMap = null;

            //here possible change
            if ((input.IsEditorControlNewPressed(MyEditorControlEnums.PRIMARY_ACTION_KEY) ||
                 input.IsAnyShiftKeyPressed() && input.IsEditorControlPressed(MyEditorControlEnums.PRIMARY_ACTION_KEY)) &&
                (m_timeFromLastShaping >= MyVoxelConstants.VOXEL_HAND_SHAPING_INTERVAL || MyFakes.RAPID_VOXEL_HAND_SHAPING_ENABLED || MyFakes.MWBUILDER))
            {
                m_timeFromLastShaping = 0;

                if (DetachedVoxelHand != null && !input.IsKeyPress(Keys.Space))
                {
                    return;
                }

                MyVoxelMap voxelMap = null;

                if (VoxelHandShape is MyVoxelHandSphere)
                {
                    MyVoxelHandSphere sphere = (MyVoxelHandSphere)VoxelHandShape;
                    BoundingSphere    vol    = sphere.WorldVolume;
                    voxelMap = MyVoxelMaps.GetIntersectionWithSphere(ref vol, SelectedVoxelMap);
                }
                else if (VoxelHandShape is MyVoxelHandBox)
                {
                    MyVoxelHandBox box = (MyVoxelHandBox)VoxelHandShape;
                    BoundingBox    localBoundingBox = box.GetLocalBoundingBox();
                    Vector3        boxWorldPosition = box.GetPosition();
                    voxelMap = MyVoxelMaps.GetIntersectionWithBox(ref localBoundingBox, ref boxWorldPosition, SelectedVoxelMap);
                }
                else if (VoxelHandShape is MyVoxelHandCuboid)
                {
                    MyVoxelHandCuboid cuboid           = (MyVoxelHandCuboid)VoxelHandShape;
                    BoundingBox       localBoundingBox = cuboid.GetLocalBoundingBox();
                    Vector3           boxWorldPosition = cuboid.GetPosition();
                    voxelMap = MyVoxelMaps.GetIntersectionWithBox(ref localBoundingBox, ref boxWorldPosition, SelectedVoxelMap);
                }
                else if (VoxelHandShape is MyVoxelHandCylinder)
                {
                    MyVoxelHandCylinder cylinder         = (MyVoxelHandCylinder)VoxelHandShape;
                    BoundingBox         localBoundingBox = cylinder.GetLocalBoundingBox();
                    Vector3             boxWorldPosition = cylinder.GetPosition();
                    voxelMap = MyVoxelMaps.GetIntersectionWithBox(ref localBoundingBox, ref boxWorldPosition, SelectedVoxelMap);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                if (voxelMap != null)
                {
                    m_applyToVoxelMap = voxelMap;
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Change size of asteroid tool from camera
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////

            /*
             * if (input.IsAnyShiftKeyPressed())
             * {
             * if (input.PreviousMouseScrollWheelValue() > input.MouseScrollWheelValue())
             * {
             * SetVoxelSize(MyEditorVoxelHand.VoxelHandShape.GetShapeSize() - MyVoxelConstants.VOXEL_HAND_SIZE_STEP);
             * }
             * else if (input.PreviousMouseScrollWheelValue() < input.MouseScrollWheelValue())
             * {
             * SetVoxelSize(MyEditorVoxelHand.VoxelHandShape.GetShapeSize() + MyVoxelConstants.VOXEL_HAND_SIZE_STEP);
             * }
             *
             * }
             *
             * ////////////////////////////////////////////////////////////////////////////////////////////////////////////
             * // Change distance of asteroid tool from camera
             * ////////////////////////////////////////////////////////////////////////////////////////////////////////////
             *
             * if (input.IsAnyControlPress())
             * {
             * if (input.PreviousMouseScrollWheelValue() > input.MouseScrollWheelValue())
             * {
             * SetShapeDistance(GetShapeDistance() - MyVoxelConstants.VOXEL_HAND_DISTANCE_STEP);
             *
             * }
             * else if (input.PreviousMouseScrollWheelValue() < input.MouseScrollWheelValue())
             * {
             * SetShapeDistance(GetShapeDistance() + MyVoxelConstants.VOXEL_HAND_DISTANCE_STEP);
             * }
             * } */
        }
Ejemplo n.º 43
0
        public void RotateAsteroid(Quaternion quaternion)
        {
            var sourceFile = SourceVoxelFilepath ?? VoxelFilepath;

            var asteroid = new MyVoxelMap();

            asteroid.Load(sourceFile);

            var newAsteroid = new MyVoxelMap();
            var newSize     = asteroid.Size;

            newAsteroid.Create(newSize, SpaceEngineersCore.Resources.GetDefaultMaterialIndex());

            Vector3I block;
            var      halfSize = asteroid.Storage.Size / 2;

            // Don't use anything smaller than 64 for smaller voxels, as it trashes the cache.
            var cacheSize     = new Vector3I(64);
            var halfCacheSize = new Vector3I(32); // This should only be used for the Transform, not the cache.

            // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue.
            for (block.Z = 0; block.Z < asteroid.Storage.Size.Z; block.Z += 64)
            {
                for (block.Y = 0; block.Y < asteroid.Storage.Size.Y; block.Y += 64)
                {
                    for (block.X = 0; block.X < asteroid.Storage.Size.X; block.X += 64)
                    {
                        #region source voxel

                        var cache = new MyStorageData();
                        cache.Resize(cacheSize);
                        // LOD1 is not detailed enough for content information on asteroids.
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        #endregion

                        #region target Voxel

                        // the block is a cubiod. The entire space needs to rotate, to be able to gauge where the new block position starts from.
                        var newBlockMin = Vector3I.Transform(block - halfSize, quaternion) + halfSize;
                        var newBlockMax = Vector3I.Transform(block + 64 - halfSize, quaternion) + halfSize;
                        var newBlock    = Vector3I.Min(newBlockMin, newBlockMax);

                        var newCache = new MyStorageData();
                        newCache.Resize(cacheSize);
                        newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1);

                        #endregion

                        bool     changed = false;
                        Vector3I p;
                        for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                        {
                            for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                            {
                                for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                {
                                    byte volume       = cache.Content(ref p);
                                    byte cellMaterial = cache.Material(ref p);

                                    var newP1 = Vector3I.Transform(p - halfCacheSize, quaternion) + halfCacheSize;
                                    var newP2 = Vector3I.Transform(p + 1 - halfCacheSize, quaternion) + halfCacheSize;
                                    var newP  = Vector3I.Min(newP1, newP2);

                                    newCache.Content(ref newP, volume);
                                    newCache.Material(ref newP, cellMaterial);
                                    changed = true;
                                }
                            }
                        }

                        if (changed)
                        {
                            newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                        }
                    }
                }
            }


            var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension);
            newAsteroid.Save(tempfilename);

            SourceVoxelFilepath = tempfilename;
        }
Ejemplo n.º 44
0
        public static bool UpdateVoxelMapScript(MyVoxelMap voxelMap)
        {
            if (MyHud.ContainsTextForEntity(voxelMap))
            {
                if (m_outpostReached == false)
                {
                    if (Vector3.Distance(MySession.PlayerShip.GetPosition(), voxelMap.GetPosition()) < REMOVE_FROM_HUD_POSSIBLE_OUTPOST_DISTANCE)
                    {
                        MyHud.RemoveText(voxelMap);
                    }
                }
                else
                {
                    MyHud.RemoveText(voxelMap);
                }
            }

            return true;
        }