//  This method does same thing as GetCell(), but doesn't do it now or immediately.
        //  Instead it adds data cells that are needed to be precalculated to the queue so later they can be calculated on multiple cores.
        public static MyVoxelCacheCellData GetCellLater(MyVoxelMap voxelMap, ref MyMwcVector3Int cellCoord)
        {
            lock (Locker)
            {
                MyVoxelCacheCellData cachedDataCell = GetCellFromCache(voxelMap.VoxelMapId, ref cellCoord);

                //  If cell isn't in the cache yet
                if (cachedDataCell == null)
                {
                    //  If cell and its neighborhood is completely full or completely empty, result of precalc will be zero-triangles, so we can skip precalc.
                    //  It can speedup precalc because then we don't have to check every voxel
                    if (voxelMap.IsDataCellCompletelyFullOrCompletelyEmpty(ref cellCoord) == false)
                    {
                        //  Cell may have triangles, so add it to cache and run precalc
                        cachedDataCell = AddCell(voxelMap.VoxelMapId, ref cellCoord);

                        MyVoxelPrecalc.AddToQueue(MyLodTypeEnum.LOD0, voxelMap, cachedDataCell, cellCoord.X * MyVoxelConstants.VOXEL_DATA_CELL_SIZE_IN_VOXELS, cellCoord.Y * MyVoxelConstants.VOXEL_DATA_CELL_SIZE_IN_VOXELS, cellCoord.Z * MyVoxelConstants.VOXEL_DATA_CELL_SIZE_IN_VOXELS);
                    }
                }

                //  I commented out this condition "(cachedDataCell != null)" because now I think we want to move-up in priority list
                //  all data cells, independently of whether they contain or don't contain triangles
                if (cachedDataCell != null)
                {
                    UpdateCell(voxelMap.VoxelMapId, ref cellCoord);
                }

                return(cachedDataCell);
            }
        }
        private static MyVoxelCacheCellRender LoadCell(
            MyVoxelMap voxelMap, ref MyMwcVector3Int renderCellCoord, MyLodTypeEnum cellHashType)
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("AddCell");

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

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

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

            if (cellHashType == MyLodTypeEnum.LOD0)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("cellHashType LOD0");
                m_dataCellsQueue.Clear();

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

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("PrecalcQueue LOD0");

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

                if (MyFakes.SIMPLIFY_VOXEL_MESH)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Stitch Data Cells LOD0");
                    MyDataCellStitcher.StitchDataCells(m_dataCellsQueue);

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Decimate mesh LOD0");
                    MyMeshSimplifier.Instance.SimplifyMesh(MyDataCellStitcher.Vertices, MyDataCellStitcher.Triangles);

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("AddTriangles LOD0");
                    ret.AddTriangles(MyDataCellStitcher.Vertices, MyDataCellStitcher.Triangles);
                }
                else
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("AddTriangles LOD0");
                    ret.AddTriangles(m_dataCellsQueue);
                }

                //  Iterate all data cells and copy their triangles to this render cell
                //for (int i = 0; i < m_dataCellsQueue.Count; i++)
                //{
                //    ret.AddTriangles(m_dataCellsQueue[i]);
                //}
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }
            else if (cellHashType == MyLodTypeEnum.LOD1)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("cellHashType LOD1");

                m_helperLodCachedDataCell.Reset();

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


                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("m_dataCellsQueue LOD1");
                m_dataCellsQueue.Clear();
                m_dataCellsQueue.Add(m_helperLodCachedDataCell);


                if (MyFakes.SIMPLIFY_VOXEL_MESH)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Stitch data cells LOD1");
                    MyDataCellStitcher.StitchDataCells(m_dataCellsQueue);

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("Decimate mesh LOD1");
                    MyMeshSimplifier.Instance.SimplifyMesh(MyDataCellStitcher.Vertices, MyDataCellStitcher.Triangles);

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("AddTriangles LOD1");
                    ret.AddTriangles(MyDataCellStitcher.Vertices, MyDataCellStitcher.Triangles);
                }
                else
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("AddTriangles LOD1");
                    ret.AddTriangles(m_dataCellsQueue);
                }

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }
            else
            {
                throw new MyMwcExceptionApplicationShouldNotGetHere();
            }

            ret.End();
            return(ret);
        }