private void OnDepositQueryComplete(MyDepositQuery query, ConcurrentCachingList <MyEntityOreDeposit> deposits, List <Vector3I> emptyCells)
        {
            foreach (var deposit in deposits)
            {
                Vector3I depositCell = deposit.CellCoord;
                m_depositsByCellCoord[depositCell] = deposit;
                //RegisterMarker(deposit);
                //MyHud.OreMarkers.RegisterMarker(deposit);
            }

            foreach (var emptyCell in emptyCells)
            {
                m_emptyCellCoord.Add(emptyCell);
            }

            m_tasksRunning--;

            var bb = new BoundingBoxI(query.Min, query.Max);

            m_completed += bb.Size.Size;
            Logger.Instance.LogDebugOnGameThread($"Completed: {m_completed}");

            if (m_tasksRunning == 0)
            {
                Scanning = false;
            }
        }
        public static void Start(Vector3I min, Vector3I max, MyVoxelBase voxelMap, Action <MyDepositQuery, ConcurrentCachingList <MyEntityOreDeposit>, List <Vector3I> > completionCallback)
        {
            MyDepositQuery query = null;

            m_instancePool.AllocateOrCreate(out query);
            if (query != null)
            {
                query.Min                = min;
                query.Max                = max;
                query.VoxelMap           = voxelMap;
                query.CompletionCallback = completionCallback;
                MyAPIGateway.Parallel.Start(query, query.m_onComplete);
            }
        }
        public void UpdateDeposits(ref BoundingSphereD worldDetectionSphere)
        {
            if (m_tasksRunning != 0)
            {
                return;
            }

            var session = Sandbox.ModAPI.MyAPIGateway.Session;

            if (session == null)
            {
                return;
            }

            Vector3I min, max;
            var      worldMin = worldDetectionSphere.Center - worldDetectionSphere.Radius;
            var      worldMax = worldDetectionSphere.Center + worldDetectionSphere.Radius;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxelMap.PositionLeftBottomCorner, ref worldMin, out min);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxelMap.PositionLeftBottomCorner, ref worldMax, out max);
            // mk:TODO Get rid of this computation. Might require a mechanism to figure out whether MyVoxelMap is subpart of MyPlanet or not. (Maybe third class for subparts?)
            min += m_voxelMap.StorageMin;
            max += m_voxelMap.StorageMin;

            (m_voxelMap.Storage as IMyStorage).ClampVoxelCoord(ref min);
            (m_voxelMap.Storage as IMyStorage).ClampVoxelCoord(ref max);
            min >>= (MyOreDetectorComponent.CELL_SIZE_IN_VOXELS_BITS + MyOreDetectorComponent.QUERY_LOD);
            max >>= (MyOreDetectorComponent.CELL_SIZE_IN_VOXELS_BITS + MyOreDetectorComponent.QUERY_LOD);

            if (min == m_lastDetectionMin && max == m_lastDetectionMax)
            {
                return;
            }

            Scanning    = true;
            m_completed = 0;

            m_depositsByCellCoord.Clear();
            m_emptyCellCoord.Clear();

            m_lastDetectionMin = min;
            m_lastDetectionMax = max;

            int stepX = (max.X - min.X) / 2;
            int stepY = (max.Y - min.Y) / 2;

            Vector3I cmin;
            Vector3I cmax;

            cmin.Z = min.Z;
            cmax.Z = max.Z;

            // split to 4 parts, because this is still done on main thread and starting task eats alot of time
            for (int x = 0; x < 2; x++)
            {
                for (int y = 0; y < 2; y++)
                {
                    cmin.X = min.X + (x * stepX);
                    cmin.Y = min.Y + (y * stepY);
                    cmax.X = cmin.X + stepX;
                    cmax.Y = cmin.Y + stepY;

                    MyDepositQuery.Start(cmin, cmax, m_voxelMap, m_onDepositQueryComplete);
                    m_tasksRunning++;
                }
            }
        }