private void MergeAsteroidMaterialFrom(ref MyVoxelMap newAsteroid, Vector3 min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3 minPrimary, Vector3 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.ContentAndMaterial, 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);
                                    byte material = cache.Material(ref p);
                                    if (volume > 0)
                                    {
                                        newCache.Material(ref p, material);
                                    }
                                }
                            }
                        }

                        newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }
        }
        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);
                    }
                }
            }
        }
        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);

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

            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);
                            }
                        }
                    }
                }
            }
        }
        private void MergeAsteroidMaterialFrom(ref MyVoxelMap newAsteroid, Vector3 min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3 minPrimary, Vector3 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)
                            {
                                newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord);
                            }
                        }
                    }
                }
            }
        }
        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 coords;

            var asteroid = new MyVoxelMap();

            asteroid.Load(filenameSecondary);

            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++)
                    {
                        byte   volume;
                        string cellMaterial;
                        asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume);

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

            asteroid.Load(filenamePrimary);

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

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

                            var newCoord = ((minPrimary - min) + ((Vector3D)coords - modelPrimary.ContentBounds.Min)).RoundToVector3I();
                            newAsteroid.GetVoxelMaterialContent(ref newCoord, out existingCellMaterial, out existingVolume);

                            if (volume > existingVolume)
                            {
                                newAsteroid.SetVoxelContent(volume, ref newCoord);
                            }
                            // Overwrites secondary material with primary.
                            newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord);
                        }
                    }
                }
            }
        }