Example #1
0
            internal void DiscardClippedCells(RequestCollector collector)
            {
                foreach (var entry in m_clippedCells)
                {
                    var data = entry.Value;

                    data.ClippedOut = true;

                    if (UseCache)
                    {
                        var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, entry.Key);

                        CellsCache.Write(clipmapCellId, data);
                        Delete(entry.Key, data, false);
                    }
                    else
                    {
                        if (data.Cell != null)
                        {
                            Delete(entry.Key, data);
                        }

                        data.ReadyInClipmap = false;
                    }
                }

                m_clippedCells.Clear();
            }
Example #2
0
        public static RequestCollector GetIncomeReader()
        {
            XmlDocument xml = new XmlDocument();

            try { xml.Load(IncomeRequestFolder + "income.xml"); } catch (Exception) { return(null); }
            XmlNode          node = xml.DocumentElement.LastChild; //TODO:New Nodes to be APPENDED!!!!
            RequestCollector rc   = new RequestCollector();

            string[] s = new string[6];
            int      i = -1;

            foreach (XmlNode n in node)
            {
                i++;
                s[i] = n.InnerText;
            }
            rc.FamilyName              = s[0];
            rc.FirstName               = s[1];
            rc.FathersName             = s[2];
            rc.Grade                   = Int32.Parse(s[3]);
            rc.Group                   = Int32.Parse(s[4]);
            rc.DesiredScheduleDateTime = DateTime.Parse(s[5]);
            rc.ReasonCode              = Int32.Parse(s[6]);
            return(rc);
        }
            internal void KeepOrDiscardClippedCells(RequestCollector collector)
            {
                LodLevel parentLod, childLod;

                GetNearbyLodLevels(out parentLod, out childLod);

                MyCellCoord thisLodCell = new MyCellCoord();

                foreach (var entry in m_clippedCells)
                {
                    var  data   = entry.Value;
                    bool needed = false;

                    // too far, but less detailed data might be missing so we still check parent
                    thisLodCell.SetUnpack(entry.Key);
                    needed = !WasAncestorCellLoaded(parentLod, ref thisLodCell);

                    if (needed)
                    {
                        if (data.State == CellState.Invalid)
                        {
                            if (!TryAddCellRequest(collector, parentLod, thisLodCell, entry.Key, data))
                            {
                                continue;
                            }
                        }

                        m_storedCellData.Add(entry.Key, data);
                    }
                    else
                    {
                        if (UseCache && data.State == CellState.Loaded)
                        {
                            var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, entry.Key);

                            CellsCache.Write(clipmapCellId, data);
                            Delete(entry.Key, data, false);
                        }
                        else
                        {
                            if (data.State == CellState.Pending)
                            {
                                collector.CancelRequest(entry.Key);
                            }
                            if (data.Cell != null)
                            {
                                Delete(entry.Key, data);
                            }
                        }

                        if (!UseCache)
                        {
                            CellsCache.Reset();
                        }
                    }
                }

                m_clippedCells.Clear();
            }
Example #4
0
 public MyClipmap(uint id, MyClipmapScaleEnum scaleGroup, MatrixD worldMatrix, Vector3I sizeLod0, IMyClipmapCellHandler cellProvider)
 {
     m_scaleGroup = scaleGroup;
     m_worldMatrix = worldMatrix;
     MatrixD.Invert(ref m_worldMatrix, out m_invWorldMatrix);
     m_sizeLod0 = sizeLod0;
     m_localAABB = new BoundingBoxD(Vector3D.Zero, new Vector3D(sizeLod0 * MyVoxelConstants.RENDER_CELL_SIZE_IN_METRES));
     for (int lod = 0; lod < m_lodLevels.Length; ++lod)
     {
         m_lodLevels[lod] = new LodLevel(this, lod, ((m_sizeLod0 - 1) >> lod) + 1);
     }
     m_updateQueueItem = new UpdateQueueItem(this);
     m_requestCollector = new RequestCollector(id);
     m_cellHandler = cellProvider;
 }
Example #5
0
 public MyClipmap(uint id, MyClipmapScaleEnum scaleGroup, MatrixD worldMatrix, Vector3I sizeLod0, IMyClipmapCellHandler cellProvider)
 {
     m_scaleGroup = scaleGroup;
     m_worldMatrix = worldMatrix;
     MatrixD.Invert(ref m_worldMatrix, out m_invWorldMatrix);
     m_sizeLod0 = sizeLod0;
     m_localAABB = new BoundingBoxD(Vector3D.Zero, new Vector3D(sizeLod0 * MyVoxelConstants.RENDER_CELL_SIZE_IN_METRES));
     for (int lod = 0; lod < m_lodLevels.Length; ++lod)
     {
         m_lodLevels[lod] = new LodLevel(this, lod, ((m_sizeLod0 - 1) >> lod) + 1);
     }
     m_updateQueueItem = new UpdateQueueItem(this);
     m_requestCollector = new RequestCollector(id);
     m_cellHandler = cellProvider;
 }
            /// <summary>
            /// New clipping routine, call on lowest desired lod with position of camera
            /// Should be later enhanced with spread if desired lod would be lower than 0
            /// Finaly it will be used as hint for structure managing cells to be calculated and rendered
            /// </summary>
            /// <param name="localPosition"></param>
            /// <param name="collector"></param>
            internal void DoClipping(Vector3D localPosition, RequestCollector collector, int spread)
            {
                Vector3I min, max;
                {
                    Vector3I center;
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref localPosition, out center);
                    min = center - spread;
                    max = center + spread;
                    Vector3I.Clamp(ref min, ref Vector3I.Zero, ref m_lodSizeMinusOne, out min);
                    Vector3I.Clamp(ref max, ref Vector3I.Zero, ref m_lodSizeMinusOne, out max);
                }
                var it0    = new Vector3I.RangeIterator(ref min, ref max);
                var ignore = BoundingBox.CreateInvalid();

                DoClipping(collector, min, max, ref ignore);
            }
Example #7
0
 public MyClipmap(uint id, MyClipmapScaleEnum scaleGroup, MatrixD worldMatrix, Vector3I sizeLod0, IMyClipmapCellHandler cellProvider)
 {
     m_scaleGroup  = scaleGroup;
     m_worldMatrix = worldMatrix;
     MatrixD.Invert(ref m_worldMatrix, out m_invWorldMatrix);
     m_sizeLod0  = sizeLod0;
     m_localAABB = new BoundingBoxD(Vector3D.Zero, new Vector3D(sizeLod0 * MyVoxelCoordSystems.RenderCellSizeInMeters(0)));
     for (int lod = 0; lod < m_lodLevels.Length; ++lod)
     {
         var sizeShift = lod + MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShiftDelta(lod);
         m_lodLevels[lod] = new LodLevel(this, lod, ((m_sizeLod0 - 1) >> sizeShift) + 1);
     }
     m_updateQueueItem  = new UpdateQueueItem(this);
     m_requestCollector = new RequestCollector(id);
     m_cellHandler      = cellProvider;
 }
Example #8
0
 public MyClipmap(uint id, MyClipmapScaleEnum scaleGroup, MatrixD worldMatrix, Vector3I sizeLod0, IMyClipmapCellHandler cellProvider)
 {
     m_scaleGroup = scaleGroup;
     m_worldMatrix = worldMatrix;
     MatrixD.Invert(ref m_worldMatrix, out m_invWorldMatrix);
     m_sizeLod0 = sizeLod0;
     m_localAABB = new BoundingBoxD(Vector3D.Zero, new Vector3D(sizeLod0 * MyVoxelCoordSystems.RenderCellSizeInMeters(0)));
     for (int lod = 0; lod < m_lodLevels.Length; ++lod)
     {
         var sizeShift = lod + MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShiftDelta(lod);
         m_lodLevels[lod] = new LodLevel(this, lod, ((m_sizeLod0 - 1) >> sizeShift) + 1);
     }
     m_updateQueueItem = new UpdateQueueItem(this);
     m_requestCollector = new RequestCollector(id);
     m_cellHandler = cellProvider;
 }
            private bool TryAddCellRequest(RequestCollector collector, LodLevel parentLod, MyCellCoord cell, ulong cellId, CellData data)
            {
                var          shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(cell.Lod);
                var          parentCell    = parentLod != null ? new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent) : cell;
                BoundingBoxD worldAABB;

                MyVoxelCoordSystems.RenderCellCoordToWorldAABB(m_clipmap.m_worldMatrix.Translation, ref parentCell, out worldAABB);
                worldAABB.Inflate(-1.0f * m_lodIndex * m_lodIndex);

                var parentCellId = parentCell.PackId64();

                //if (PriorityFunc(worldAABB.Center, parentLod, parentCellId) == int.MaxValue) //this cell would just slow down sorting, it will be added again if needed
                //    return false;
                collector.AddRequest(cellId, data.WasLoaded, () => PriorityFunc(worldAABB, parentLod, parentCellId, cell), (c) => DebugDrawJob(c, worldAABB));
                data.State = CellState.Pending;
                return(true);
            }
Example #10
0
            internal void KeepOrDiscardClippedCells(RequestCollector collector)
            {
                LodLevel parentLod, childLod;

                GetNearbyLodLevels(out parentLod, out childLod);

                MyCellCoord thisLodCell = new MyCellCoord();

                foreach (var entry in m_clippedCells)
                {
                    var  data   = entry.Value;
                    bool needed = false;

                    // too far, but less detailed data might be missing so we still check parent
                    thisLodCell.SetUnpack(entry.Key);
                    needed = !WasAncestorCellLoaded(parentLod, ref thisLodCell);

                    if (needed)
                    {
                        if (data.State == CellState.Invalid)
                        {
                            collector.AddRequest(entry.Key, data.WasLoaded);
                            data.State = CellState.Pending;
                        }

                        m_storedCellData.Add(entry.Key, data);
                    }
                    else
                    {
                        if (data.State == CellState.Pending)
                        {
                            collector.CancelRequest(entry.Key);
                        }
                        if (data.Cell != null)
                        {
                            Delete(entry.Key, data);
                        }
                    }
                }

                m_clippedCells.Clear();
            }
Example #11
0
        public static bool VerifyAndGetID(RequestCollector req, ResponseCollector resp)
        {
            int ID = DatabaseController.Class1.StudentList.GetIDByName(req.FamilyName, req.FirstName, req.FathersName, req.Grade, req.Group);

            switch (ID)
            {
            case 0:
                resp.nameIsWrong = true;
                return(false);

            case -1:
                resp.groupOrGradeIsWrong = true;
                return(false);

            default:
                resp.ID          = ID;
                resp.nameIsWrong = false;
                return(true);
            }
        }
Example #12
0
            private void UnclipCell(RequestCollector collector, MyCellCoord cell, bool isVisible)
            {
                var      cellId        = cell.PackId64();
                var      clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);
                CellData data;

                if (isVisible)
                {
                    bool highPriority = true;

                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        highPriority = false;

                        CellBlendData blendData;
                        if (!m_blendedCells.TryGetValue(cellId, out blendData))
                        {
                            data = CellsCache.Read(clipmapCellId);

                            if (data == null) //cache miss
                            {
                                data = new CellData();
                                ClippingCacheMisses++;
                            }
                            else
                            {
                                //cache hit
                                ClippingCacheHits++;

                                //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state");
                                data.InScene = false;
                                if (data.Cell != null)
                                {
                                    m_nonEmptyCells[cellId] = data;
                                }
                            }
                        }
                        else
                        {
                            data = blendData.CellData;
                            if (blendData.State == BlendState.Removing)
                            {
                                blendData.UndoAfterFinish = true;
                            }
                            if (data.Cell != null)
                            {
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }

                    if (data.State == CellState.Invalid)
                    {
                        if (MyClipmap.UseQueries)
                        {
                            BoundingBoxD bbd;
                            MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd);
                            BoundingBox bb = new BoundingBox(bbd);
                            if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects)
                            {
                                collector.AddRequest(cellId, data, highPriority);
                            }
                            else
                            {
                                data.State     = CellState.Loaded;
                                data.WasLoaded = true;
                            }
                        }
                        else
                        {
                            collector.AddRequest(cellId, data, highPriority);
                        }
                    }

                    m_storedCellData.Add(cellId, data);
                    data.ReadyInClipmap = true;
                    data.ClippedOut     = false;
                }
                else
                {
                    if (!m_storedCellData.ContainsKey(cellId) && (!PendingCacheCellData.ContainsKey(clipmapCellId) || PendingCacheCellData[clipmapCellId].State == CellState.Invalid) && CellsCache.Read(clipmapCellId) == null)
                    {
                        if (!PendingCacheCellData.TryGetValue(clipmapCellId, out data))
                        {
                            data = new CellData();
                            PendingCacheCellData.Add(clipmapCellId, data);
                        }

                        if (MyClipmap.UseQueries)
                        {
                            BoundingBoxD bbd;
                            MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd);
                            BoundingBox bb = new BoundingBox(bbd);
                            if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects)
                            {
                                data.State = CellState.Invalid;

                                collector.AddRequest(cellId, data, false);
                            }
                            else
                            {
                                data.State     = CellState.Loaded;
                                data.WasLoaded = true;
                            }
                        }
                        else
                        {
                            data.State = CellState.Invalid;
                            collector.AddRequest(cellId, data, false);
                        }
                    }
                }
            }
            /// <summary>
            /// Recursive clipping function requests cells in provided range and
            /// cells needed from parent to wrap the lod safely
            /// </summary>
            /// <param name="collector"></param>
            /// <param name="it0">requested range</param>
            /// <param name="ignore">inner range filled by children</param>
            private void DoClipping(RequestCollector collector, Vector3I min, Vector3I max, ref BoundingBox ignore)
            {
                LodLevel parentLod, clevel;

                GetNearbyLodLevels(out parentLod, out clevel);
                MyCellCoord cell = new MyCellCoord(m_lodIndex, Vector3I.Zero);

                //if (collector.SentRequestsEmpty)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                var it0 = new Vector3I.RangeIterator(ref min, ref max);

                cell.CoordInLod = it0.Current;

                var shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(cell.Lod);
                var parentCell    = parentLod != null ? new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent) : cell;
                var parentIgnore  = new BoundingBox(parentCell.CoordInLod, parentCell.CoordInLod);

                BoundingBox bb = new BoundingBox(cell.CoordInLod, cell.CoordInLod);

                for (; it0.IsValid(); it0.GetNext(out cell.CoordInLod)) //cells to be loaded
                {
                    if (ignore.Contains((Vector3)cell.CoordInLod) == ContainmentType.Contains)
                    {
                        continue; //lower lod requested
                    }

                    if (parentLod != null) //get also their lodcell mates
                    {
                        parentCell = new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent);
                        var it = GetChildrenCoords(this, ref parentCell);
                        bb.Include(it);
                        parentIgnore.Max = parentCell.CoordInLod;
                    }
                }
                if (parentLod != null)
                {
                    Vector3I parentMinI = Vector3I.Round(parentIgnore.Min - Vector3.One);
                    Vector3I parentMaxI = Vector3I.Round(parentIgnore.Max + Vector3.One);
                    //Vector3I.Clamp(ref parentMinI, ref Vector3I.Zero, ref m_lodSizeMinusOne, out parentMinI);
                    //Vector3I.Clamp(ref parentMaxI, ref Vector3I.Zero, ref m_lodSizeMinusOne, out parentMaxI);
                    var parentIterator = new Vector3I.RangeIterator(ref parentMinI, ref parentMaxI);
                    parentLod.DoClipping(collector, parentMinI, parentMaxI, ref parentIgnore);
                }

                Vector3I start, end;

                start = Vector3I.Round(bb.Min); end = Vector3I.Round(bb.Max);
                Vector3I.Clamp(ref start, ref Vector3I.Zero, ref m_lodSizeMinusOne, out start);
                Vector3I.Clamp(ref end, ref Vector3I.Zero, ref m_lodSizeMinusOne, out end);
                it0             = new Vector3I.RangeIterator(ref start, ref end);
                cell.CoordInLod = it0.Current;
                for (; it0.IsValid(); it0.GetNext(out cell.CoordInLod)) //cells to be loaded
                {
                    if (ignore.Contains((Vector3)cell.CoordInLod) == ContainmentType.Contains)
                    {
                        continue; //lower lod requested
                    }

                    var cellId = cell.PackId64();

                    CellData data;
                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);

                        data = CellsCache.Read(clipmapCellId);

                        if (data == null) //cache miss
                        {
                            data = new CellData();
                            ClippingCacheMisses++;
                        }
                        else
                        {
                            //cache hit
                            ClippingCacheHits++;

                            data.InScene = false;
                            if (data.Cell != null)
                            {
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }

                    if (data.State == CellState.Invalid)
                    {
                        if (!TryAddCellRequest(collector, parentLod, cell, cellId, data))
                        {
                            continue;
                        }
                    }
                    if (!m_storedCellData.ContainsKey(cellId))
                    {
                        m_storedCellData.Add(cellId, data);
                    }
                }
            }
Example #14
0
            internal void KeepOrDiscardClippedCells(RequestCollector collector)
            {
                LodLevel parentLod, childLod;
                GetNearbyLodLevels(out parentLod, out childLod);

                MyCellCoord thisLodCell = new MyCellCoord();
                foreach (var entry in m_clippedCells)
                {
                    var data = entry.Value;
                    bool needed = false;

                    // too far, but less detailed data might be missing so we still check parent
                    thisLodCell.SetUnpack(entry.Key);
                    needed = !WasAncestorCellLoaded(parentLod, ref thisLodCell);

                    if (needed)
                    {
                        if (data.State == CellState.Invalid)
                        {
                            collector.AddRequest(entry.Key, data.WasLoaded);
                            data.State = CellState.Pending;
                        }

                        m_storedCellData.Add(entry.Key, data);
                    }
                    else
                    {
                        if (data.State == CellState.Pending)
                            collector.CancelRequest(entry.Key);
                        if (data.Cell != null)
                            Delete(entry.Key, data);
                    }
                }

                m_clippedCells.Clear();
            }
Example #15
0
            internal void DoClipping(Vector3D localPosition, float farPlaneDistance, RequestCollector collector)
            {
                MyClipmap.ComputeLodViewBounds(m_parent.m_scaleGroup, m_lodIndex, out m_nearDistance, out m_farDistance);

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum)
                    return;

                Vector3I min, max;
                {
                    var minD = localPosition - m_farDistance;
                    var maxD = localPosition + m_farDistance;
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(ref minD, out min);
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(ref maxD, out max);
                    Vector3I.Max(ref min, ref Vector3I.Zero, out min);
                    Vector3I.Max(ref max, ref Vector3I.Zero, out max);
                    min >>= m_lodIndex;
                    max >>= m_lodIndex;

                    Vector3I.Min(ref min, ref m_lodSizeMinusOne, out min);
                    Vector3I.Min(ref max, ref m_lodSizeMinusOne, out max);
                }

                if (m_lastMin == min && m_lastMax == max && !m_parent.m_updateClipping)
                    return;

                m_lastMin = min;
                m_lastMax = max;

                LodLevel parentLod, childLod;
                GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.
                MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                m_storedCellData.Clear();
                MyCellCoord cell = new MyCellCoord(m_lodIndex, ref min);
                for (var it = new Vector3I.RangeIterator(ref min, ref max);
                    it.IsValid(); it.GetNext(out cell.CoordInLod))
                {
                    if (!WasAncestorCellLoaded(parentLod, ref cell))
                        continue;

                    var cellId = cell.PackId64();
                    CellData data;
                    if (m_clippedCells.TryGetValue(cellId, out data))
                        m_clippedCells.Remove(cellId);
                    else
                        data = new CellData();

                    if (data.State == CellState.Invalid)
                    {
                        collector.AddRequest(cellId, data.WasLoaded);
                        data.State = CellState.Pending;
                    }
                    m_storedCellData.Add(cellId, data);
                }
            }
            internal void KeepOrDiscardClippedCells(RequestCollector collector)
            {
                LodLevel parentLod, childLod;
                GetNearbyLodLevels(out parentLod, out childLod);

                MyCellCoord thisLodCell = new MyCellCoord();
                foreach (var entry in m_clippedCells)
                {
                    var data = entry.Value;
                    bool needed = false;

                    // too far, but less detailed data might be missing so we still check parent
                    thisLodCell.SetUnpack(entry.Key);
                    needed = !WasAncestorCellLoaded(parentLod, ref thisLodCell);

                    if (needed)
                    {
                        if (data.State == CellState.Invalid)
                        {
                            if (!TryAddCellRequest(collector, parentLod, thisLodCell, entry.Key, data))
                                continue;
                        }

                        m_storedCellData.Add(entry.Key, data);
                    }
                    else
                    {
                        if (UseCache && data.State == CellState.Loaded)
                        {
                            var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, entry.Key);

                            CellsCache.Write(clipmapCellId, data);
                            Delete(entry.Key, data, false);
                        }
                        else
                        {
                            if (data.State == CellState.Pending)
                                collector.CancelRequest(entry.Key);
                            if (data.Cell != null)
                                Delete(entry.Key, data);
                        }

                        if (!UseCache)
                        {
                            CellsCache.Reset();
                        }
                    }
                }

                m_clippedCells.Clear();
            }
            internal void DiscardClippedCells(RequestCollector collector)
            {
                foreach (var entry in m_clippedCells)
                {
                    var data = entry.Value;

                    data.ClippedOut = true;

                    if (UseCache)
                    {
                        var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, entry.Key);

                        CellsCache.Write(clipmapCellId, data);
                        Delete(entry.Key, data, false);
                    }
                    else
                    {
                        if (data.Cell != null)
                            Delete(entry.Key, data);

                        data.ReadyInClipmap = false;
                    }
                }

                m_clippedCells.Clear();
            }
            internal void DoClipping_Old(Vector3D localPosition, float farPlaneDistance, RequestCollector collector)
            {
                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex, out m_nearDistance, out m_farDistance);

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum)
                {
                    return;
                }


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - m_farDistance;
                var maxD = m_localPosition + m_farDistance;

                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxD, out max);

                BoundingBoxI lodBox         = new BoundingBoxI(Vector3I.Zero, m_lodSizeMinusOne);
                bool         intersects     = false;
                bool         intersectsNear = false;

                m_localFarCameraBox  = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox.Intersect(m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    if (m_lodIndex > 1)
                    {
                        float lowerFar, lowerNear;
                        MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                        var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                        m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                        if (lodBox.Intersects(m_localNearCameraBox))
                        {
                            intersectsNear = false;
                        }
                    }
                }

                if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                {
                    return;
                }

                m_lastMin = min;
                m_lastMax = max;

                LodLevel parentLod, childLod;

                GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.
                MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                m_storedCellData.Clear();

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex);

                    MyCellCoord cell = new MyCellCoord(m_lodIndex, ref min);
                    for (var it = new Vector3I.RangeIterator(ref min, ref max);
                         it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        if (intersectsNear &&
                            m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                        {
                            continue;
                        }

                        //if (!WasAncestorCellLoaded(parentLod, ref cell))
                        //    continue;


                        Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                        {
                            continue;
                        }

                        var      cellId = cell.PackId64();
                        CellData data;
                        if (m_clippedCells.TryGetValue(cellId, out data))
                        {
                            m_clippedCells.Remove(cellId);
                        }
                        else
                        {
                            var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);
                            data = CellsCache.Read(clipmapCellId);

                            if (data == null) //cache miss
                            {
                                data = new CellData();
                                ClippingCacheMisses++;
                            }
                            else
                            {
                                //cache hit
                                ClippingCacheHits++;

                                //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state");
                                data.InScene = false;
                                if (data.Cell != null)
                                {
                                    m_nonEmptyCells[cellId] = data;
                                }
                            }
                        }

                        if (data.State == CellState.Invalid)
                        {
                            if (!TryAddCellRequest(collector, parentLod, cell, cellId, data))
                            {
                                continue;
                            }
                        }
                        m_storedCellData.Add(cellId, data);
                    }
                }
            }
            internal void DoClipping_Old(Vector3D localPosition, float farPlaneDistance, RequestCollector collector)
            {
                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex, out m_nearDistance, out m_farDistance);

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum)
                    return;


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - m_farDistance;
                var maxD = m_localPosition + m_farDistance;
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxD, out max);

                BoundingBoxI lodBox = new BoundingBoxI(Vector3I.Zero, m_lodSizeMinusOne);
                bool intersects = false;
                bool intersectsNear = false;

                m_localFarCameraBox = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox.Intersect(m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    if (m_lodIndex > 1)
                    {
                        float lowerFar, lowerNear;
                        MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                        var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                        m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                        if (lodBox.Intersects(m_localNearCameraBox))
                            intersectsNear = false;
                    }
                }
            
                if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                    return;

                m_lastMin = min;
                m_lastMax = max;

                LodLevel parentLod, childLod;
                GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.
                MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                m_storedCellData.Clear();

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex);

                    MyCellCoord cell = new MyCellCoord(m_lodIndex, ref min);
                    for (var it = new Vector3I.RangeIterator(ref min, ref max);
                        it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        if (intersectsNear &&
                            m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                            continue;

                        //if (!WasAncestorCellLoaded(parentLod, ref cell))
                        //    continue;

                        
                        Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                         if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                            continue;

                        var cellId = cell.PackId64();
                        CellData data;
                        if (m_clippedCells.TryGetValue(cellId, out data))
                        {
                            m_clippedCells.Remove(cellId);
                        }
                        else
                        {
                            var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);
                            data = CellsCache.Read(clipmapCellId);

                            if (data == null) //cache miss
                            {
                                data = new CellData();
                                ClippingCacheMisses++;
                            }
                            else
                            {
                                //cache hit
                                ClippingCacheHits++;

                                //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state");
                                data.InScene = false;
                                if (data.Cell != null)
                                {
                                    m_nonEmptyCells[cellId] = data;
                                }
                            }
                        }

                        if (data.State == CellState.Invalid)
                        {
                            if (!TryAddCellRequest(collector, parentLod, cell, cellId, data))
                                continue;
                        }
                        m_storedCellData.Add(cellId, data);
                    }
                }
            }
            /// <summary>
            /// Recursive clipping function requests cells in provided range and
            /// cells needed from parent to wrap the lod safely
            /// </summary>
            /// <param name="collector"></param>
            /// <param name="it0">requested range</param>
            /// <param name="ignore">inner range filled by children</param>
            private void DoClipping(RequestCollector collector, Vector3I min, Vector3I max, ref BoundingBox ignore)
            {
                LodLevel parentLod, clevel;
                GetNearbyLodLevels(out parentLod, out clevel);
                MyCellCoord cell = new MyCellCoord(m_lodIndex, Vector3I.Zero);

                //if (collector.SentRequestsEmpty)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                var it0 = new Vector3I.RangeIterator(ref min, ref max);
                cell.CoordInLod = it0.Current;

                var shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(cell.Lod);
                var parentCell = parentLod != null ? new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent) : cell;
                var parentIgnore = new BoundingBox(parentCell.CoordInLod, parentCell.CoordInLod);

                BoundingBox bb = new BoundingBox(cell.CoordInLod, cell.CoordInLod);
                for (; it0.IsValid(); it0.GetNext(out cell.CoordInLod)) //cells to be loaded
                {
                    if (ignore.Contains((Vector3)cell.CoordInLod) == ContainmentType.Contains)
                    {
                        continue; //lower lod requested
                    }

                    if (parentLod != null) //get also their lodcell mates
                    {
                        parentCell = new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent);
                        var it = GetChildrenCoords(this, ref parentCell);
                        bb.Include(it);
                        parentIgnore.Max = parentCell.CoordInLod;
                    }

                }
                if (parentLod != null)
                {
                    Vector3I parentMinI = Vector3I.Round(parentIgnore.Min - Vector3.One);
                    Vector3I parentMaxI = Vector3I.Round(parentIgnore.Max + Vector3.One);
                    //Vector3I.Clamp(ref parentMinI, ref Vector3I.Zero, ref m_lodSizeMinusOne, out parentMinI);
                    //Vector3I.Clamp(ref parentMaxI, ref Vector3I.Zero, ref m_lodSizeMinusOne, out parentMaxI);
                    var parentIterator = new Vector3I.RangeIterator(ref parentMinI, ref parentMaxI);
                    parentLod.DoClipping(collector, parentMinI, parentMaxI, ref parentIgnore);
                }

                Vector3I start, end;
                start = Vector3I.Round(bb.Min); end = Vector3I.Round(bb.Max);
                Vector3I.Clamp(ref start, ref Vector3I.Zero, ref m_lodSizeMinusOne, out start);
                Vector3I.Clamp(ref end, ref Vector3I.Zero, ref m_lodSizeMinusOne, out end);
                it0 = new Vector3I.RangeIterator(ref start, ref end);
                cell.CoordInLod = it0.Current;
                for (; it0.IsValid(); it0.GetNext(out cell.CoordInLod)) //cells to be loaded
                {
                    if (ignore.Contains((Vector3)cell.CoordInLod) == ContainmentType.Contains)
                    {
                        continue; //lower lod requested
                    }

                    var cellId = cell.PackId64();
                    
                    CellData data;
                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);

                        data = CellsCache.Read(clipmapCellId);

                        if (data == null) //cache miss
                        {
                            data = new CellData();
                            ClippingCacheMisses++;
                        }
                        else
                        {
                            //cache hit
                            ClippingCacheHits++;

                            data.InScene = false;
                            if (data.Cell != null)
                            {
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }

                    if (data.State == CellState.Invalid)
                    {
                        if (!TryAddCellRequest(collector, parentLod, cell, cellId, data))
                        {
                            continue;
                        }
                    }
                    if (!m_storedCellData.ContainsKey(cellId))
                        m_storedCellData.Add(cellId, data);
                }

            }
            /// <summary>
            /// New clipping routine, call on lowest desired lod with position of camera
            /// Should be later enhanced with spread if desired lod would be lower than 0
            /// Finaly it will be used as hint for structure managing cells to be calculated and rendered
            /// </summary>
            /// <param name="localPosition"></param>
            /// <param name="collector"></param>
            internal void DoClipping(Vector3D localPosition, RequestCollector collector, int spread)
            {
                Vector3I min, max;
                {
                    Vector3I center;
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref localPosition, out center);
                    min = center - spread;
                    max = center + spread;
                    Vector3I.Clamp(ref min, ref Vector3I.Zero, ref m_lodSizeMinusOne, out min);
                    Vector3I.Clamp(ref max, ref Vector3I.Zero, ref m_lodSizeMinusOne, out max);
                }
                var it0 = new Vector3I.RangeIterator(ref min, ref max);
                var ignore = BoundingBox.CreateInvalid();

                DoClipping(collector, min, max, ref ignore);
            }
Example #22
0
            internal void DoClipping(float camDistanceFromCenter, Vector3D localPosition, float farPlaneDistance, RequestCollector collector, bool frustumCulling, float rangeScale)
            {
                int lodIndex = m_lodIndex;

                if (!ShouldBeThisLodVisible(camDistanceFromCenter))
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                    return;
                }


                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, lodIndex, out m_nearDistance, out m_farDistance);


                farPlaneDistance *= rangeScale;
                m_farDistance    *= rangeScale;
                m_nearDistance   *= rangeScale;

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum && m_lodIndex == lodIndex)
                {
                    return;
                }


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                // Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - m_farDistance;
                var maxD = m_localPosition + m_farDistance;

                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref maxD, out max);

                BoundingBoxI lodBox     = new BoundingBoxI(Vector3I.Zero, Vector3I.Max(m_lodSizeMinusOne, Vector3I.Zero));
                bool         intersects = false;

                //bool intersectsNear = false;

                m_localFarCameraBox  = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox;
                    intersection.IntersectWith(ref m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    //if (m_lodIndex > 1)
                    //{
                    //    float lowerFar, lowerNear;
                    //    MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                    //    var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                    //    m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                    //    if (lodBox.Intersects(m_localNearCameraBox))
                    //        intersectsNear = false;
                    //}
                }

                //if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                //    return;

                //m_lastMin = min;
                //m_lastMax = max;

                //LodLevel parentLod, childLod;
                //GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.

                if (frustumCulling)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(lodIndex);


                    MyCellCoord cell = new MyCellCoord(lodIndex, ref min);

                    for (var it = new Vector3I.RangeIterator(ref min, ref max);
                         it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        //if (intersectsNear &&
                        //    m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                        //    continue;

                        //if (frustumCulling)
                        //{
                        //    Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        //    Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        //    if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                        //    {
                        //        m_outsideCells.Add(cell.CoordInLod);
                        //        continue;
                        //    }
                        //}

                        UnclipCell(collector, cell, true);
                    }

                    //cache cells around frustum
                    if (collector.SentRequestsEmpty)
                    {
                        foreach (var outsideCell in m_outsideCells)
                        {
                            cell.CoordInLod = outsideCell;
                            UnclipCell(collector, cell, frustumCulling);
                        }
                    }

                    m_outsideCells.Clear();
                }
            }
Example #23
0
            internal void DoClipping(Vector3D localPosition, float farPlaneDistance, RequestCollector collector)
            {
                MyClipmap.ComputeLodViewBounds(m_parent.m_scaleGroup, m_lodIndex, out m_nearDistance, out m_farDistance);

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum)
                {
                    return;
                }

                Vector3I min, max;

                {
                    var minD = localPosition - m_farDistance;
                    var maxD = localPosition + m_farDistance;
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minD, out min);
                    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxD, out max);
                    Vector3I.Clamp(ref min, ref Vector3I.Zero, ref m_lodSizeMinusOne, out min);
                    Vector3I.Clamp(ref max, ref Vector3I.Zero, ref m_lodSizeMinusOne, out max);
                }

                if (m_lastMin == min && m_lastMax == max && !m_parent.m_updateClipping)
                {
                    return;
                }

                m_lastMin = min;
                m_lastMax = max;

                LodLevel parentLod, childLod;

                GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.
                MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                m_storedCellData.Clear();
                MyCellCoord cell = new MyCellCoord(m_lodIndex, ref min);

                for (var it = new Vector3I.RangeIterator(ref min, ref max);
                     it.IsValid(); it.GetNext(out cell.CoordInLod))
                {
                    if (!WasAncestorCellLoaded(parentLod, ref cell))
                    {
                        continue;
                    }

                    var      cellId = cell.PackId64();
                    CellData data;
                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        data = new CellData();
                    }

                    if (data.State == CellState.Invalid)
                    {
                        collector.AddRequest(cellId, data.WasLoaded);
                        data.State = CellState.Pending;
                    }
                    m_storedCellData.Add(cellId, data);
                }
            }
            internal void DoClipping(float camDistanceFromCenter, Vector3D localPosition, float farPlaneDistance, RequestCollector collector, bool frustumCulling, float rangeScale)
            {
                int lodIndex = m_lodIndex;

                if (!ShouldBeThisLodVisible(camDistanceFromCenter))
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                    return;
                }


                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, lodIndex, out m_nearDistance, out m_farDistance);


                farPlaneDistance *= rangeScale;
                m_farDistance *= rangeScale;
                m_nearDistance *= rangeScale;

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum && m_lodIndex == lodIndex)
                    return;


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                // Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - (double)m_farDistance;
                var maxD = m_localPosition + (double)m_farDistance;
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref maxD, out max);

                BoundingBoxI lodBox = new BoundingBoxI(Vector3I.Zero, Vector3I.Max(m_lodSizeMinusOne, Vector3I.Zero));
                bool intersects = false;
                //bool intersectsNear = false;

                m_localFarCameraBox = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox;
                    intersection.IntersectWith(ref m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    //if (m_lodIndex > 1)
                    //{
                    //    float lowerFar, lowerNear;
                    //    MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                    //    var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                    //    m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                    //    if (lodBox.Intersects(m_localNearCameraBox))
                    //        intersectsNear = false;
                    //}
                }
            
                //if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                //    return;

                //m_lastMin = min;
                //m_lastMax = max;

                //LodLevel parentLod, childLod;
                //GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.

                if (frustumCulling)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(lodIndex);


                    MyCellCoord cell = new MyCellCoord(lodIndex, ref min);

                    for (var it = new Vector3I_RangeIterator(ref min, ref max);
                        it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        //if (intersectsNear &&
                        //    m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                        //    continue;

                        //if (frustumCulling)
                        //{
                        //    Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        //    Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        //    if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                        //    {
                        //        m_outsideCells.Add(cell.CoordInLod);
                        //        continue;
                        //    }
                        //}

                        UnclipCell(collector, cell, true);
                    }

                    //cache cells around frustum
                    if (collector.SentRequestsEmpty)
                    {
                          foreach (var outsideCell in m_outsideCells)
                          {
                              cell.CoordInLod = outsideCell;
                              UnclipCell(collector, cell, frustumCulling);
                          }
                    }

                    m_outsideCells.Clear();
                }
            }
            private void UnclipCell(RequestCollector collector, MyCellCoord cell, bool isVisible)
            {
                var cellId = cell.PackId64();
                var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);
                MyClipmap_CellData data;

                if (isVisible)
                {
                    bool highPriority = true;

                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        highPriority = false;

                        CellBlendData blendData;
                        if (!m_blendedCells.TryGetValue(cellId, out blendData))
                        {
                            data = CellsCache.Read(clipmapCellId);

                            if (data == null) //cache miss
                            {
                                data = new MyClipmap_CellData();
                                ClippingCacheMisses++;
                            }
                            else
                            {
                                //cache hit
                                ClippingCacheHits++;

                                //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state");
                                data.InScene = false;
                                if (data.Cell != null)
                                {
                                    m_nonEmptyCells[cellId] = data;
                                }
                            }
                        }
                        else
                        {
                            data = blendData.CellData;
                            if (blendData.State == BlendState.Removing)
                                blendData.UndoAfterFinish = true;
                            if (data.Cell != null)
                            {
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }

                    if (data.State == CellState.Invalid)
                    {
                        if (MyClipmap.UseQueries)
                        {
                            BoundingBoxD bbd;
                            MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd);
                            BoundingBox bb = new BoundingBox(bbd);
                            if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects)
                            {
                                collector.AddRequest(cellId, data, highPriority);
                            }
                            else
                            {
                                data.State = CellState.Loaded;
                                data.WasLoaded = true;
                            }
                        }
                        else
                          collector.AddRequest(cellId, data, highPriority);
                    }
             
                    m_storedCellData.Add(cellId, data);
                    data.ReadyInClipmap = true;
                    data.ClippedOut = false;
                }
                else
                {
                    if (!m_storedCellData.ContainsKey(cellId) && (!PendingCacheCellData.ContainsKey(clipmapCellId) || PendingCacheCellData[clipmapCellId].State == CellState.Invalid) && CellsCache.Read(clipmapCellId) == null)
                    {
                        if (!PendingCacheCellData.TryGetValue(clipmapCellId, out data))
                        {
                            data = new MyClipmap_CellData();
                            PendingCacheCellData.Add(clipmapCellId, data);
                        }

                        if (MyClipmap.UseQueries)
                        {
                            BoundingBoxD bbd;
                            MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd);
                            BoundingBox bb = new BoundingBox(bbd);
                            if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects)
                            {
                                data.State = CellState.Invalid;

                                collector.AddRequest(cellId, data, false);
                            }
                            else
                            {
                                data.State = CellState.Loaded;
                                data.WasLoaded = true;
                            }
                        }
                        else
                        {
                            data.State = CellState.Invalid;
                            collector.AddRequest(cellId, data, false);
                        }
                    }
                }
            }
            private bool TryAddCellRequest(RequestCollector collector, LodLevel parentLod, MyCellCoord cell, ulong cellId, CellData data)
            {
                var shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(cell.Lod);
                var parentCell = parentLod != null ? new MyCellCoord(parentLod.m_lodIndex, cell.CoordInLod >> shiftToParent) : cell;
                BoundingBoxD worldAABB;
                MyVoxelCoordSystems.RenderCellCoordToWorldAABB(m_clipmap.m_worldMatrix.Translation, ref parentCell, out worldAABB);
                worldAABB.Inflate(-1.0f * m_lodIndex * m_lodIndex);

                var parentCellId = parentCell.PackId64();
                //if (PriorityFunc(worldAABB.Center, parentLod, parentCellId) == int.MaxValue) //this cell would just slow down sorting, it will be added again if needed
                //    return false;
                collector.AddRequest(cellId, data.WasLoaded, () => PriorityFunc(worldAABB, parentLod, parentCellId, cell), (c) => DebugDrawJob(c, worldAABB));
                data.State = CellState.Pending;
                return true;
            }