static void SaveVoxel(MyVoxelMap voxelMap)
        {
            Debug.Assert(voxelMap.EntityId != null);

            using (var voxelStream = new FileStream(GetVoxelPath(voxelMap), FileMode.Create))
            using (var voxelWriter = new BinaryWriter(voxelStream))
            {
                voxelWriter.Write(MyMwcFinalBuildConstants.VOXEL_CACHE_FILE_VERSION);

                MyMwcVector3Int cellCoord;
                for (cellCoord.X = 0; cellCoord.X < voxelMap.DataCellsCount.X; cellCoord.X++)
                {
                    for (cellCoord.Y = 0; cellCoord.Y < voxelMap.DataCellsCount.Y; cellCoord.Y++)
                    {
                        for (cellCoord.Z = 0; cellCoord.Z < voxelMap.DataCellsCount.Z; cellCoord.Z++)
                        {
                            var dataCell = MyVoxelCacheData.GetCell(voxelMap, ref cellCoord, false);
                            if (dataCell != null/* && dataCell.VoxelTrianglesCount > 0*/)
                            {
                                voxelWriter.Write(cellCoord.X);
                                voxelWriter.Write(cellCoord.Y);
                                voxelWriter.Write(cellCoord.Z);

                                dataCell.Write(voxelWriter);

                                //Log("update", sectorIdentifier, checkpointName, sector.Version);
                            }
                        }
                    }
                }
            }
        }
 public MyVoxelPrecalcTaskItem(MyLodTypeEnum type, MyVoxelMap voxelMap, MyVoxelCacheCellData cache, MyMwcVector3Int voxelStart)
 {
     Type = type;
     VoxelMap = voxelMap;
     Cache = cache;
     VoxelStart = voxelStart;
 }
 public static Dictionary<MyMwcVoxelMaterialsEnum, int> CutOutSphereFastWithMaterials(MyVoxelMap voxelMap, BoundingSphere sphere, float removeRatio = 1)
 {
     var exactCutOutMaterials = new Dictionary<MyMwcVoxelMaterialsEnum, int>();
     MyMwcVoxelMaterialsEnum? voxelMaterial_unused;
     float voxelContentRemovedInPercent_unused;
     MyVoxelGenerator.CutOutSphereFast(voxelMap, sphere, out voxelContentRemovedInPercent_unused, out voxelMaterial_unused, false, removeRatio, exactCutOutMaterials);
     return exactCutOutMaterials;
 }
 public MyEditorActionVoxelHand(MyVoxelMap voxelMap, MyVoxelHandShape voxelHandShape)
     : base(voxelMap)
 {
     MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MyEditorActionVoxelHand::ctor");
     m_voxelHandShape = voxelHandShape;
     m_voxelShapes = voxelMap.GetVoxelHandShapes();
     MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
 }
        static string GetVoxelPath(MyVoxelMap voxelMap)
        {
            var sectorIdentifier = MyGuiScreenGamePlay.Static.GetSectorIdentifier();
            int sectorVersion = MyGuiScreenGamePlay.Static.SectorVersion;

            string path = MyLocalCache.CachePath;
            if (sectorIdentifier.UserId != null) // TODO change?
            {
                path = MyLocalCache.CurrentSavePath;
            }

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            return Path.Combine(path, GetVoxelName(voxelMap, sectorIdentifier, sectorVersion) + ".mwv");
        }
        public MyVoxelMapOreDepositCell(MyVoxelMap voxelMap, MyMwcVector3Int coord)
        {
            m_voxelMap = voxelMap;
            m_coord = coord;
            m_positionIsDirty = true;
            m_totalSumOfOreContent = 0;
            
            m_oreWithContent = new List<MyMwcVoxelMaterialsEnum>(MyVoxelMapOreMaterials.RareOreCount());

            /*
            int allMaterialsCount = MyMwcUtils.GetMaxValueFromEnum<MyMwcVoxelMaterialsEnum>() + 1;
            m_allMaterialsContent = new int[allMaterialsCount];
            m_allMaterialsPositions = new Vector3?[allMaterialsCount];
            m_helpersMaxContentForMaterial = new byte[allMaterialsCount];
              */

            m_allMaterialsContent = new Dictionary<int, int>();
            m_allMaterialsPositions = new Dictionary<int, Vector3?>();
            m_helpersMaxContentForMaterial = new Dictionary<int, byte>();
        }
        static string GetVoxelName(MyVoxelMap voxelMap, MyMwcSectorIdentifier sectorIdentifier, int sectorVersion)
        {
            string name;
            switch (sectorIdentifier.SectorType)
            {
                case MyMwcSectorTypeEnum.STORY:
                    name = "STORY";
                    break;

                case MyMwcSectorTypeEnum.SANDBOX:
                    name = "SANDBOX";
                    break;

                default:
                    throw new MyMwcExceptionApplicationShouldNotGetHere();
            }

            string userId = sectorIdentifier.UserId.HasValue ? sectorIdentifier.UserId.Value.ToString(CultureInfo.InvariantCulture) : "NULL";

            Debug.Assert(voxelMap.EntityId != null, "voxelMap.EntityId != null");
            return String.Format("{0}_{1}_{2}_{3}_{4}_{5}_{6}_{7}", name, userId, sectorIdentifier.Position.X, sectorIdentifier.Position.Y, sectorIdentifier.Position.Z, sectorVersion, voxelMap.VoxelMapId, voxelMap.EntityId.Value.NumericValue);
        }
 //  Because this class is reused in buffers, it isn't really initialized by constructor. We make real initialization here.
 public void Start(MyVoxelMap voxelMap, ref MyMwcVector3Int renderCellCoord, MyDecalTexturesEnum decalTexture, ref BoundingBox renderCellBoundingBox)
 {
     VoxelMap = voxelMap;
     RenderCellCoord = renderCellCoord;
     DecalTexture = decalTexture;
     m_status = MyDecalsBufferState.READY;
     m_fadingOutStartTime = 0;
     RenderCellBoundingBox = renderCellBoundingBox;
     
     if (MyDecals.IsLargeTexture(decalTexture) == true)
     {
         m_capacityAfterStart = MyDecalsConstants.MAX_DECAL_TRIANGLES_IN_BUFFER_LARGE;
         m_fadingOutStartLimit = (int)(m_capacityAfterStart * MyDecalsConstants.TEXTURE_LARGE_FADING_OUT_START_LIMIT_PERCENT);
         m_fadingOutMinimalTriangleCount = (int)(m_capacityAfterStart * MyDecalsConstants.TEXTURE_LARGE_FADING_OUT_MINIMAL_TRIANGLE_COUNT_PERCENT);
         MaxNeighbourTriangles = MyDecalsConstants.TEXTURE_LARGE_MAX_NEIGHBOUR_TRIANGLES;
     }
     else
     {
         m_capacityAfterStart = MyDecalsConstants.MAX_DECAL_TRIANGLES_IN_BUFFER_SMALL;
         m_fadingOutStartLimit = (int)(m_capacityAfterStart * MyDecalsConstants.TEXTURE_SMALL_FADING_OUT_START_LIMIT_PERCENT);
         m_fadingOutMinimalTriangleCount = (int)(m_capacityAfterStart * MyDecalsConstants.TEXTURE_SMALL_FADING_OUT_MINIMAL_TRIANGLE_COUNT_PERCENT);
         MaxNeighbourTriangles = MyDecalsConstants.TEXTURE_SMALL_MAX_NEIGHBOUR_TRIANGLES;
     }
 }
 Vector3 GetGridCoord(MyVoxelMap voxelMap, int gridPointX, int gridPointY, int gridPointZ)
 {
     return voxelMap.PositionLeftBottomCorner + new Vector3(
         gridPointX * m_gridPointsSize + m_gridPointsSizeHalf,
         gridPointY * m_gridPointsSize + m_gridPointsSizeHalf,
         gridPointZ * m_gridPointsSize + m_gridPointsSizeHalf);
 }
 bool PerformSoftenVoxels(MyVoxelMap voxelMap, MyMwcVector3Int voxelCoord, ref bool changed)
 {
     bool contentChanged = false;
     byte originalContent = voxelMap.GetVoxelContent(ref voxelCoord);
     if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
     {
         changed = true;
         voxelMap.SoftenVoxelContent(voxelCoord, MyVoxelConstants.DEFAULT_SOFTEN_WEIGHT);
         contentChanged = true;
     }
     return contentChanged;
 }
 bool PerformRemoveVoxels(MyVoxelMap voxelMap, MyMwcVector3Int voxelCoord, byte content, ref bool changed)
 {
     bool contentChanged = false;
     byte originalContent = voxelMap.GetVoxelContent(ref voxelCoord);
     if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && content > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
     {
         int newVal = originalContent - content;
         if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY)
         {
             newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
         }
         changed = true;
         voxelMap.SetVoxelContent((byte)newVal, ref voxelCoord);
         contentChanged = true;
     }
     return contentChanged;
 }
        bool PerformGridAction(MyVoxelMap voxelMap, MyvoxelImportAction action, int gridX, int gridZ, ref MyMwcVector3Int minChanged, ref MyMwcVector3Int maxChanged, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed)
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PerformGridAction");

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("get content sum");
            int[, ,] voxelContentSum = GetVoxelContentSum(voxelMap, gridX, gridZ);
            if (voxelContentSum == null)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

                return false;
            }

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("loop");
            bool anyContentChanged = false;

            //  Transform grid values to voxels
            int voxelStartX = gridX * VOXELS_IN_GRID_IN_ONE_DIRECTION;
            int voxelStartZ = gridZ * VOXELS_IN_GRID_IN_ONE_DIRECTION;


            switch (action)
            {
                case MyvoxelImportAction.AddVoxels:
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MyvoxelImportAction.AddVoxels");
                    for (int x = 0; x < VOXELS_IN_GRID_IN_ONE_DIRECTION; x++) for (int y = 0; y < voxelMap.Size.Y; y++) for (int z = 0; z < VOXELS_IN_GRID_IN_ONE_DIRECTION; z++)
                    {
                        MyMwcVector3Int voxelCoord = new MyMwcVector3Int(voxelStartX + x, y, voxelStartZ + z);

                        byte newContent =  (byte)(voxelContentSum[x, y, z] * MyVoxelConstants.VOXEL_CONTENT_FULL / GRID_POINTS_IN_ONE_VOXEL_TOTAL);
                        if (newContent == 0) continue;

                        bool c = PerformAddVoxels(voxelMap, voxelCoord, newContent, ref changed);
                        c |= PerformChangeMaterialVoxels(voxelMap, voxelCoord, voxelMaterial, ref changed);
                        if (c)
                        {
                            anyContentChanged = true;
                            if (voxelCoord.X < minChanged.X) minChanged.X = voxelCoord.X;
                            if (voxelCoord.Y < minChanged.Y) minChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z < minChanged.Z) minChanged.Z = voxelCoord.Z;
                            if (voxelCoord.X > maxChanged.X) maxChanged.X = voxelCoord.X;
                            if (voxelCoord.Y > maxChanged.Y) maxChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z > maxChanged.Z) maxChanged.Z = voxelCoord.Z;
                        }
                    }
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                    break;

                case MyvoxelImportAction.RemoveVoxels:
                    for (int x = 0; x < VOXELS_IN_GRID_IN_ONE_DIRECTION; x++) for (int y = 0; y < voxelMap.Size.Y; y++) for (int z = 0; z < VOXELS_IN_GRID_IN_ONE_DIRECTION; z++)
                    {
                        MyMwcVector3Int voxelCoord = new MyMwcVector3Int(voxelStartX + x, y, voxelStartZ + z);

                        byte newContent = (byte)(voxelContentSum[x, y, z] * MyVoxelConstants.VOXEL_CONTENT_FULL / GRID_POINTS_IN_ONE_VOXEL_TOTAL);
                        if (newContent == 0) continue;

                        if (PerformRemoveVoxels(voxelMap, voxelCoord, newContent, ref changed))
                        {
                            anyContentChanged = true;
                            if (voxelCoord.X < minChanged.X) minChanged.X = voxelCoord.X;
                            if (voxelCoord.Y < minChanged.Y) minChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z < minChanged.Z) minChanged.Z = voxelCoord.Z;
                            if (voxelCoord.X > maxChanged.X) maxChanged.X = voxelCoord.X;
                            if (voxelCoord.Y > maxChanged.Y) maxChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z > maxChanged.Z) maxChanged.Z = voxelCoord.Z;
                        }
                    }
                    break;

                case MyvoxelImportAction.ChangeMaterial:
                    for (int x = 0; x < VOXELS_IN_GRID_IN_ONE_DIRECTION; x++) for (int y = 0; y < voxelMap.Size.Y; y++) for (int z = 0; z < VOXELS_IN_GRID_IN_ONE_DIRECTION; z++)
                    {
                        MyMwcVector3Int voxelCoord = new MyMwcVector3Int(voxelStartX + x, y, voxelStartZ + z);

                        byte newContent = (byte)(voxelContentSum[x, y, z] * MyVoxelConstants.VOXEL_CONTENT_FULL / GRID_POINTS_IN_ONE_VOXEL_TOTAL);
                        if (newContent == 0) continue;

                        if (PerformChangeMaterialVoxels(voxelMap, voxelCoord, voxelMaterial, ref changed))
                        {
                            anyContentChanged = true;
                            if (voxelCoord.X < minChanged.X) minChanged.X = voxelCoord.X;
                            if (voxelCoord.Y < minChanged.Y) minChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z < minChanged.Z) minChanged.Z = voxelCoord.Z;
                            if (voxelCoord.X > maxChanged.X) maxChanged.X = voxelCoord.X;
                            if (voxelCoord.Y > maxChanged.Y) maxChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z > maxChanged.Z) maxChanged.Z = voxelCoord.Z;
                        }
                    }
                    break;

                case MyvoxelImportAction.SoftenVoxels:
                    for (int x = 0; x < VOXELS_IN_GRID_IN_ONE_DIRECTION; x++) for (int y = 0; y < voxelMap.Size.Y; y++) for (int z = 0; z < VOXELS_IN_GRID_IN_ONE_DIRECTION; z++)
                    {
                        MyMwcVector3Int voxelCoord = new MyMwcVector3Int(voxelStartX + x, y, voxelStartZ + z);

                        byte newContent = (byte)(voxelContentSum[x, y, z] * MyVoxelConstants.VOXEL_CONTENT_FULL / GRID_POINTS_IN_ONE_VOXEL_TOTAL);
                        if (newContent == 0) continue;

                        if (PerformSoftenVoxels(voxelMap, voxelCoord, ref changed))
                        {
                            anyContentChanged = true;
                            if (voxelCoord.X < minChanged.X) minChanged.X = voxelCoord.X;
                            if (voxelCoord.Y < minChanged.Y) minChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z < minChanged.Z) minChanged.Z = voxelCoord.Z;
                            if (voxelCoord.X > maxChanged.X) maxChanged.X = voxelCoord.X;
                            if (voxelCoord.Y > maxChanged.Y) maxChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z > maxChanged.Z) maxChanged.Z = voxelCoord.Z;
                        }
                    }
                    break;

                case MyvoxelImportAction.WrinkleVoxels:
                    for (int x = 0; x < VOXELS_IN_GRID_IN_ONE_DIRECTION; x++) for (int y = 0; y < voxelMap.Size.Y; y++) for (int z = 0; z < VOXELS_IN_GRID_IN_ONE_DIRECTION; z++)
                    {
                        MyMwcVector3Int voxelCoord = new MyMwcVector3Int(voxelStartX + x, y, voxelStartZ + z);

                        byte newContent = (byte)(voxelContentSum[x, y, z] * MyVoxelConstants.VOXEL_CONTENT_FULL / GRID_POINTS_IN_ONE_VOXEL_TOTAL);

                        if (newContent == 0) continue;

                        if (PerformWrinkleVoxels(voxelMap, voxelCoord, ref changed))
                        {
                            anyContentChanged = true;
                            if (voxelCoord.X < minChanged.X) minChanged.X = voxelCoord.X;
                            if (voxelCoord.Y < minChanged.Y) minChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z < minChanged.Z) minChanged.Z = voxelCoord.Z;
                            if (voxelCoord.X > maxChanged.X) maxChanged.X = voxelCoord.X;
                            if (voxelCoord.Y > maxChanged.Y) maxChanged.Y = voxelCoord.Y;
                            if (voxelCoord.Z > maxChanged.Z) maxChanged.Z = voxelCoord.Z;
                        }
                    }
                    break;
            }

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            return anyContentChanged;
        }
        //  Import one individual grid
        void ImportGrid(MyVoxelMap voxelMap, int gridX, int gridZ)
        {
            int[, ,] voxelContentSum = GetVoxelContentSum(voxelMap, gridX, gridZ);

            //  Transform grid values to voxels
            int voxelStartX = gridX * VOXELS_IN_GRID_IN_ONE_DIRECTION;
            int voxelStartZ = gridZ * VOXELS_IN_GRID_IN_ONE_DIRECTION;
            for (int x = 0; x < VOXELS_IN_GRID_IN_ONE_DIRECTION; x++)
            {
                for (int y = 0; y < voxelMap.Size.Y; y++)
                {
                    for (int z = 0; z < VOXELS_IN_GRID_IN_ONE_DIRECTION; z++)
                    {
                        MyMwcVector3Int voxelCoord = new MyMwcVector3Int(voxelStartX + x, y, voxelStartZ + z);

                        float content = 0;

                        if (voxelContentSum != null)
                            content = (float)voxelContentSum[x, y, z] / (float)GRID_POINTS_IN_ONE_VOXEL_TOTAL;

                        //  Content value must be in interval <0..1>
                        MyCommonDebugUtils.AssertRelease((content >= 0.0f) && (content <= 1.0f));

                        voxelMap.SetVoxelContent((byte)(content * MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT), ref voxelCoord);
                    }
                }
            }
        }
        //  We splited voxel map to more grids because if voxel map is large, it can't fit in one grid.
        //  So here we iterate over this grid. Everytime clear the grid, fill with triangleVertexes intersections and then set voxels.
        void Import(MyVoxelMap voxelMap)
        {
            //  Voxel map size must be multiple of grid size. Or, whole grid must fit exactly into X times into voxel map, without crossing border!
            MyCommonDebugUtils.AssertRelease((voxelMap.Size.X % VOXELS_IN_GRID_IN_ONE_DIRECTION) == 0);

            //  Voxel map size must be multiple of grid size. Or, whole grid must fit exactly into X times into voxel map, without crossing border!
            MyCommonDebugUtils.AssertRelease((voxelMap.Size.Z % VOXELS_IN_GRID_IN_ONE_DIRECTION) == 0);

            int gridsCountX = voxelMap.Size.X / VOXELS_IN_GRID_IN_ONE_DIRECTION;
            int gridsCountZ = voxelMap.Size.Z / VOXELS_IN_GRID_IN_ONE_DIRECTION;

            //  Space between two grid points in metres
            m_gridPointsSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES / (float)GRID_POINTS_IN_ONE_VOXEL_IN_ONE_DIRECTION;
            m_gridPointsSizeHalf = m_gridPointsSize / 2.0f;


            for (int gridX = 0; gridX < gridsCountX; gridX++)
            {
                for (int gridZ = 0; gridZ < gridsCountZ; gridZ++)
                {
                    ImportGrid(voxelMap, gridX, gridZ);
                }
            }
        }
 //  Use this static method do one-time import of a voxel map
 public static void Run(MyVoxelMap voxelMap, string modelName, MyVoxelImportOptions importOptions)
 {
     MyVoxelImport voxelMapImport = new MyVoxelImport(voxelMap, modelName, importOptions);
 }
        //  Rescales the model to size specified by 'sizeInMetres'
        void RescaleModel(MyVoxelMap voxelMap, MyVoxelImportOptions importOptions)
        {
            Vector3 originalSize = m_maxCoord - m_minCoord;
            Vector3 originalCenter = (m_maxCoord + m_minCoord) / 2.0f;

            m_minCoord = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            m_maxCoord = new Vector3(float.MinValue, float.MinValue, float.MinValue);


            //  We don't want to touch borders of a voxel map so we need to subtract size of data cell from each side.
            //  I have choosen data cell (not one or two voxels) because LOD - average content of some data cells that were too close to voxel map border 
            //  were almost full data cell so when converted as LOD, hole appear there (originaly I was just multiplying by 0.9, but that is wasting in case of large voxel maps).
            //Vector3 rescaleFactor = voxelMap.SizeInMetres / originalSize * 0.9f;
            Vector3 rescaleFactor;
            rescaleFactor.X = (voxelMap.SizeInMetres.X - 2 * MyVoxelConstants.VOXEL_DATA_CELL_SIZE_IN_METRES) / originalSize.X;
            rescaleFactor.Y = (voxelMap.SizeInMetres.Y - 2 * MyVoxelConstants.VOXEL_DATA_CELL_SIZE_IN_METRES) / originalSize.Y;
            rescaleFactor.Z = (voxelMap.SizeInMetres.Z - 2 * MyVoxelConstants.VOXEL_DATA_CELL_SIZE_IN_METRES) / originalSize.Z;

            switch (importOptions)
            {
                case MyVoxelImportOptions.KeepAspectRatio:
                    rescaleFactor.X = rescaleFactor.Y = rescaleFactor.Z = Math.Min(Math.Min(rescaleFactor.X, rescaleFactor.Y), rescaleFactor.Z);
                    break;
                case MyVoxelImportOptions.KeepScale:
                    //Cannot keep scale if the voxel map isn't big enough to contain it, will keep aspect ratio instead
                    if (rescaleFactor.X >= 1 && rescaleFactor.Y >= 1 && rescaleFactor.Z >= 1)
                    {
                        rescaleFactor = Vector3.One;
                    }
                    else
                    {
                        rescaleFactor.X = rescaleFactor.Y = rescaleFactor.Z = Math.Min(Math.Min(rescaleFactor.X, rescaleFactor.Y), rescaleFactor.Z);
                    }
                    break;
            }

            for (int i = 0; i < m_triangles.Count; i++)
            {
                //  Translate vertexes to the origin
                m_triangles[i].Vertex0 -= originalCenter;
                m_triangles[i].Vertex1 -= originalCenter;
                m_triangles[i].Vertex2 -= originalCenter;

                //  Rescale vertexes
                m_triangles[i].Vertex0 *= rescaleFactor;
                m_triangles[i].Vertex1 *= rescaleFactor;
                m_triangles[i].Vertex2 *= rescaleFactor;

                //  Translate vertexes to voxel map position
                m_triangles[i].Vertex0 += voxelMap.PositionLeftBottomCorner + voxelMap.SizeInMetresHalf;
                m_triangles[i].Vertex1 += voxelMap.PositionLeftBottomCorner + voxelMap.SizeInMetresHalf;
                m_triangles[i].Vertex2 += voxelMap.PositionLeftBottomCorner + voxelMap.SizeInMetresHalf;

                CheckMinMaxCoords(m_triangles[i].Vertex0);
                CheckMinMaxCoords(m_triangles[i].Vertex1);
                CheckMinMaxCoords(m_triangles[i].Vertex2);
            }
        }
        //  Fill lookup array with triangles located at specified voxel positions. Array is 2D.
        void FillTrianglesLookup(MyVoxelMap voxelMap)
        {
            m_trianglesLookupSizeX = voxelMap.Size.X;
            m_trianglesLookupSizeZ = voxelMap.Size.Z;
            m_trianglesLookupElementSizeX = voxelMap.SizeInMetres.X / voxelMap.Size.X;
            m_trianglesLookupElementSizeZ = voxelMap.SizeInMetres.Z / voxelMap.Size.Z;
            m_trianglesLookup = new List<MyImportTriangle>[m_trianglesLookupSizeX, m_trianglesLookupSizeZ];

            //  Initialize array
            for (int x = 0; x < m_trianglesLookupSizeX; x++)
            {
                for (int z = 0; z < m_trianglesLookupSizeZ; z++)
                {
                    m_trianglesLookup[x, z] = new List<MyImportTriangle>(INITIAL_COUNT_OF_TRIANGLES_IN_GRID_POSITION);
                }
            }

            //  Iterate over all triangles and put them into correct array positions based on their coordinates
            for (int i = 0; i < m_triangles.Count; i++)
            {
                //  Get bounding rectangle for this triangleVertexes (in fact we need only 2D coordinates, but it's clearer to use 3D and ignore Y value)
                Vector3 minCoord = new Vector3(float.MaxValue, 0, float.MaxValue);
                Vector3 maxCoord = new Vector3(float.MinValue, 0, float.MinValue);
                CheckMinMaxCoords2d(ref minCoord, ref maxCoord, m_triangles[i].Vertex0);
                CheckMinMaxCoords2d(ref minCoord, ref maxCoord, m_triangles[i].Vertex1);
                CheckMinMaxCoords2d(ref minCoord, ref maxCoord, m_triangles[i].Vertex2);

                MyMwcVector2Int minCoordInt = GetTriangleLookupCoord(voxelMap, minCoord);
                MyMwcVector2Int maxCoordInt = GetTriangleLookupCoord(voxelMap, maxCoord);

                if (minCoordInt.X < 0) minCoordInt.X = 0;
                if (minCoordInt.Y < 0) minCoordInt.Y = 0;
                if (minCoordInt.X > m_trianglesLookupSizeX - 1) minCoordInt.X = m_trianglesLookupSizeX - 1;
                if (minCoordInt.Y > m_trianglesLookupSizeZ - 1) minCoordInt.Y = m_trianglesLookupSizeZ - 1;
                if (maxCoordInt.X < 0) maxCoordInt.X = 0;
                if (maxCoordInt.Y < 0) maxCoordInt.Y = 0;
                if (maxCoordInt.X > m_trianglesLookupSizeX - 1) maxCoordInt.X = m_trianglesLookupSizeX - 1;
                if (maxCoordInt.Y > m_trianglesLookupSizeZ - 1) maxCoordInt.Y = m_trianglesLookupSizeZ - 1;

                //  Iterate over all elements that may contain this triangleVertexes.
                //  Notice that we swap Y and Z. It's because MyMwcVector2Int has X and Y, but we are working on XZ plane. So it's still Z value, even if its name is Y.
                for (int x = minCoordInt.X; x <= maxCoordInt.X; x++)
                {
                    for (int z = minCoordInt.Y; z <= maxCoordInt.Y; z++)
                    {
                        m_trianglesLookup[x, z].Add(m_triangles[i]);
                    }
                }
            }
        }
 //  Use this static method do one-time import of a voxel map
 public static void Run(MyVoxelMap voxelMap, MyModel model)
 {
     MyVoxelImport voxelMapImport = new MyVoxelImport(voxelMap, model, MyVoxelImportOptions.None);
 }
        // Returns temporary in/out values for voxels
        int[, ,] GetVoxelContentSum(MyVoxelMap voxelMap, int gridX, int gridZ)
        {
            int gridStartPointX = gridX * MAX_GRID_SIZE_IN_ONE_DIRECTION;
            int gridStartPointZ = gridZ * MAX_GRID_SIZE_IN_ONE_DIRECTION;

            //  Here we store intersections with line and triangles and specified grid point
            List<MyImportIntersection> intersections = new List<MyImportIntersection>(INITIAL_COUNT_OF_INTERSECTIONS);

            //  Here we store temporary in/out values for voxels. After that, we convert it to common voxel content values (0..255)
            int[, ,] voxelContentSum = null; 

            for (int gridPointX = 0; gridPointX < MAX_GRID_SIZE_IN_ONE_DIRECTION; gridPointX++)
            {
                for (int gridPointZ = 0; gridPointZ < MAX_GRID_SIZE_IN_ONE_DIRECTION; gridPointZ++)
                {
                    Vector3 gridCoord = GetGridCoord(voxelMap, gridStartPointX + gridPointX, 0, gridStartPointZ + gridPointZ);
                    if (gridCoord.X < m_minCoord.X || gridCoord.Z < m_minCoord.Z || gridCoord.X > m_maxCoord.X || gridCoord.Z > m_maxCoord.Z)
                    {
                        continue;
                    }

                    if (voxelContentSum == null)
                        voxelContentSum = new int[VOXELS_IN_GRID_IN_ONE_DIRECTION, voxelMap.Size.Y, VOXELS_IN_GRID_IN_ONE_DIRECTION];

                    MyMwcVector2Int triangleLookupCoord = GetTriangleLookupCoord(voxelMap, gridCoord);

                    //  We need to clear list of intersections
                    intersections.Clear();

                    //  Get triangles that lie on this grid point/line
                    List<MyImportTriangle> triangles = m_trianglesLookup[triangleLookupCoord.X, triangleLookupCoord.Y];
                    for (int i = 0; i < triangles.Count; i++)
                    {
                        //  Ray is always in Y-axis direction
                        //MyLine line = new MyLine(gridCoord, gridCoord + Vector3.Up * 100000, false);
                        MyLine line = new MyLine(new Vector3(gridCoord.X, m_minCoord.Y, gridCoord.Z) + Vector3.Down * 10, new Vector3(gridCoord.X, m_maxCoord.Y, gridCoord.Z) + Vector3.Up * 10, false);

                        MyTriangle_Vertexes triangle;
                        triangle.Vertex0 = triangles[i].Vertex0;
                        triangle.Vertex1 = triangles[i].Vertex1;
                        triangle.Vertex2 = triangles[i].Vertex2;

                        float? distance = MyUtils.GetLineTriangleIntersection(ref line, ref triangle);
                        if (distance.HasValue == true)
                        {
                            intersections.Add(new MyImportIntersection(line.From + line.Direction * distance.Value, triangles[i].Normal, distance.Value));
                        }
                    }

                    //  SortForSAP intersections by their distance from the origin (from the grid point)
                    intersections.Sort(delegate(MyImportIntersection p1, MyImportIntersection p2) { return p1.Distance.CompareTo(p2.Distance); });

                    int lastY = 0;
                    bool contentSwitch = false;     //  This tells us if we will add empty or full voxels. False = until now it's empty. True = it full.                    
                    for (int i = 0; i < intersections.Count; i++)
                    {
                        Vector3 tempGridCoord = GetGridCoord(voxelMap, gridStartPointX + gridPointX, lastY, gridStartPointZ + gridPointZ);
                        int length = (int)((intersections[i].Intersection.Y - tempGridCoord.Y) / m_gridPointsSize);
                        // this is here, because we must find intersection with triangle out of borders of voxel map, because we can use voxel hand at the borders
                        if (length < 0)
                        {
                            contentSwitch = !contentSwitch;
                            continue;
                        }

                        for (int y = lastY; y < (lastY + length); y++)
                        {
                            MyMwcVector3Int voxelCoord = voxelMap.GetVoxelCoordinateFromMeters(GetGridCoord(voxelMap, gridPointX, y, gridPointZ));
                            if (voxelCoord.Y < voxelContentSum.GetLength(1) &&
                               voxelCoord.Y >= 0)
                            {
                                voxelContentSum[voxelCoord.X, voxelCoord.Y, voxelCoord.Z] += (contentSwitch == false) ? 0 : 1;
                            }
                        }

                        contentSwitch = !contentSwitch;
                        lastY = lastY + length;
                    }
                }
            }

            return voxelContentSum;
        }
 //  Use this static method do one-time import of a voxel map
 public static void Run(MyVoxelMap voxelMap, MyModelObj model, MyVoxelImportOptions importOptions)
 {
     MyVoxelImport voxelMapImport = new MyVoxelImport(voxelMap, model, importOptions);
 }
        void PerformAction(MyVoxelMap voxelMap, MyvoxelImportAction action, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed)
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PerformAction");

            //  Voxel map size must be multiple of grid size. Or, whole grid must fit exactly into X times into voxel map, without crossing border!
            MyCommonDebugUtils.AssertRelease((voxelMap.Size.X % VOXELS_IN_GRID_IN_ONE_DIRECTION) == 0);

            //  Voxel map size must be multiple of grid size. Or, whole grid must fit exactly into X times into voxel map, without crossing border!
            MyCommonDebugUtils.AssertRelease((voxelMap.Size.Z % VOXELS_IN_GRID_IN_ONE_DIRECTION) == 0);

            int gridsCountX = voxelMap.Size.X / VOXELS_IN_GRID_IN_ONE_DIRECTION;
            int gridsCountZ = voxelMap.Size.Z / VOXELS_IN_GRID_IN_ONE_DIRECTION;

            //  Space between two grid points in metres
            m_gridPointsSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES / (float)GRID_POINTS_IN_ONE_VOXEL_IN_ONE_DIRECTION;
            m_gridPointsSizeHalf = m_gridPointsSize / 2.0f;

            //  Get min corner of the box
            MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(m_minCoord);

            //  Get max corner of the box
            MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(m_maxCoord);

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

            //  We are tracking which voxels were changed, so we can invalidate only needed cells in the cache
            MyMwcVector3Int minChanged = maxCorner;
            MyMwcVector3Int maxChanged = minCorner;

            bool contentChanged = false;

            for (int gridX = 0; gridX < gridsCountX; gridX++)
            {
                for (int gridZ = 0; gridZ < gridsCountZ; gridZ++)
                {
                    if (PerformGridAction(voxelMap, action, gridX, gridZ, ref minChanged, ref maxChanged, voxelMaterial, ref changed))
                    {
                        contentChanged = true;
                    }
                }
            }

            if (contentChanged)
            {
                //  Extend borders for cleaning, so it's one pixel on both sides
                minChanged.X -= 1;
                minChanged.Y -= 1;
                minChanged.Z -= 1;
                maxChanged.X += 1;
                maxChanged.Y += 1;
                maxChanged.Z += 1;
                voxelMap.FixVoxelCoord(ref minChanged);
                voxelMap.FixVoxelCoord(ref maxChanged);

                voxelMap.InvalidateCache(minChanged, maxChanged);
            }

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
        }
 public static void Run(MyVoxelMap voxelMap, MyModel model, MyvoxelImportAction importAction, Matrix modelWorld, float modelScale, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed)
 {
     MyVoxelImport voxelImport = new MyVoxelImport(voxelMap, model, importAction, modelWorld, modelScale, voxelMaterial, ref changed);
 }
        bool PerformAddVoxels(MyVoxelMap voxelMap, MyMwcVector3Int voxelCoord, byte content, ref bool changed)
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PerformAddVoxels");

            bool contentChanged = false;
            byte originalContent = voxelMap.GetVoxelContent(ref voxelCoord);
            if (content > originalContent)
            {
                changed = true;
                voxelMap.SetVoxelContent(content, ref voxelCoord);
                contentChanged = true;
            }

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            return contentChanged;
        }
 public static void Run(MyVoxelMap voxelMap, Vector3[] vertexes, MyTriangleVertexIndices[] triangles, MyvoxelImportAction importAction, Matrix modelWorld, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed)
 {
     MyVoxelImport voxelImport = new MyVoxelImport(voxelMap, vertexes, triangles, importAction, modelWorld, voxelMaterial, ref changed);
 }
        bool PerformChangeMaterialVoxels(MyVoxelMap voxelMap, MyMwcVector3Int voxelCoord, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed)
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PerformChangeMaterialVoxels");
            if (voxelMaterial != null)
            {
                byte originalContent = voxelMap.GetVoxelContent(ref voxelCoord);
                if (originalContent == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                {
                    // if there are no voxel content then do nothing
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                    return false;
                }

                MyMwcVoxelMaterialsEnum originalMaterial;
                byte originalIndestructibleContent;
                voxelMap.GetMaterialAndIndestructibleContent(ref voxelCoord, out originalMaterial,
                                                             out originalIndestructibleContent);
                if (originalMaterial == voxelMaterial.Value)
                {
                    // if original material is same as new material then do nothing
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                    return false;
                }

                byte indestructibleContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY;

                voxelMap.SetVoxelMaterialAndIndestructibleContent(voxelMaterial.Value, indestructibleContent, ref voxelCoord);
                changed = true;
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                return true;
            }
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            return false;
        }
        //  Model will be scaled/translated to fit voxel map size (X, Y and Z)
        MyVoxelImport(MyVoxelMap voxelMap, MyModelObj model, MyVoxelImportOptions importOptions)
        {
            //  Load model, get triangles
            LoadModel(model);

            //  Rescale the model so it fits voxelMap (three directions!!!)
            RescaleModel(voxelMap, importOptions);

            //  Fill lookup array with triangles located at specified voxel positions. Array is 2D.
            FillTrianglesLookup(voxelMap);

            //  Create XZ map where every voxel center gets list of triangles that lie on its Y line
            //      Do this by iterating over all triangles and making references to them from XZ map
            Import(voxelMap);
        }
        bool PerformWrinkleVoxels(MyVoxelMap voxelMap, MyMwcVector3Int voxelCoord, ref bool changed)
        {
            bool contentChanged = false;
            byte originalContent = voxelMap.GetVoxelContent(ref voxelCoord);

            voxelMap.WrinkleVoxelContent(voxelCoord, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE);
            byte newContent = voxelMap.GetVoxelContent(ref voxelCoord);
            if (originalContent != newContent)
            {
                contentChanged = true;
                changed = true;
            }

            return contentChanged;
        }
        MyVoxelImport(MyVoxelMap voxelMap, Vector3[] vertexes, MyTriangleVertexIndices[] triangles, MyvoxelImportAction importAction, Matrix modelWorld, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed)
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("voxel import");

            // Load model, get triangles transformed to model's world matrix
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("load model");
            LoadModel(vertexes, triangles, modelWorld);

            //  Fill lookup array with triangles located at specified voxel positions. Array is 2D.
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("fill lookup");
            FillTrianglesLookup(voxelMap);

            // Performs action
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("perform action");
            PerformAction(voxelMap, importAction, voxelMaterial, ref changed);

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
        }
 //  Converts vertex from 'world coordinates' to 'triangleVertexes lookup array coordinates'. 
 MyMwcVector2Int GetTriangleLookupCoord(MyVoxelMap voxelMap, Vector3 vertex)
 {
     return new MyMwcVector2Int(
         (int)((vertex.X - voxelMap.PositionLeftBottomCorner.X) / m_trianglesLookupElementSizeX),
         (int)((vertex.Z - voxelMap.PositionLeftBottomCorner.Z) / m_trianglesLookupElementSizeZ));
 }
        MyVoxelImport(MyVoxelMap voxelMap, MyModel model, MyvoxelImportAction importAction, Matrix modelWorld, float modelScale, MyMwcVoxelMaterialsEnum? voxelMaterial, ref bool changed)
        {
            // Load model, get triangles transformed to model's world matrix
            LoadModel(model, modelWorld, modelScale);

            RescaleModel(voxelMap, MyVoxelImportOptions.KeepScale);

            //  Fill lookup array with triangles located at specified voxel positions. Array is 2D.
            FillTrianglesLookup(voxelMap);

            // Performs action
           //PerformAction(voxelMap, importAction, voxelMaterial, ref changed);
            Import(voxelMap);
        }