Beispiel #1
0
            /// <summary>
            /// Checks only immediate children (any deeper would take too long).
            /// </summary>
            private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null)
                {
                    return(false);
                }

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();

                childLodCell.Lod = childLod.m_lodIndex;
                var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod);
                var start        = thisLodCell.CoordInLod << shiftToChild;
                var end          = start + ((1 << shiftToChild) >> 1);

                Vector3I.Max(ref childLod.m_lodSizeMinusOne, ref Vector3I.Zero, out childLod.m_lodSizeMinusOne);
                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);
                childLodCell.CoordInLod = start;
                for (var it = new Vector3I.RangeIterator(ref start, ref end);
                     it.IsValid(); it.GetNext(out childLodCell.CoordInLod))
                {
                    var      key = childLodCell.PackId64();
                    CellData data;
                    if (!childLod.m_storedCellData.TryGetValue(key, out data) || !data.WasLoaded)
                    {
                        return(false);
                    }
                }

                return(true);
            }
Beispiel #2
0
            private void GetNearbyLodLevels(out LodLevel parentLod, out LodLevel childLod)
            {
                var levels = m_parent.m_lodLevels;

                int parentIdx = m_lodIndex + 1;

                if (levels.IsValidIndex(parentIdx))
                {
                    parentLod = levels[parentIdx];
                }
                else
                {
                    parentLod = null;
                }

                int childIdx = m_lodIndex - 1;

                if (levels.IsValidIndex(childIdx))
                {
                    childLod = levels[childIdx];
                }
                else
                {
                    childLod = null;
                }
            }
Beispiel #3
0
            /// <summary>
            /// Checks only immediate children (any deeper would take too long).
            /// </summary>
            private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null || !childLod.Visible)
                    return false;

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();
                childLodCell.Lod = childLod.m_lodIndex;
                var start = thisLodCell.CoordInLod << 1;
                var end = start + 1;

                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);
                for (childLodCell.CoordInLod.Z = start.Z; childLodCell.CoordInLod.Z <= end.Z; ++childLodCell.CoordInLod.Z)
                for (childLodCell.CoordInLod.Y = start.Y; childLodCell.CoordInLod.Y <= end.Y; ++childLodCell.CoordInLod.Y)
                for (childLodCell.CoordInLod.X = start.X; childLodCell.CoordInLod.X <= end.X; ++childLodCell.CoordInLod.X)
                {
                    var key = childLodCell.PackId64();
                    CellData data;
                    if (!childLod.m_storedCellData.TryGetValue(key, out data))
                    {
                        return false;
                    }

                    if (!data.WasLoaded)
                    {
                        return false;
                    }
                }

                return true;
            }
Beispiel #4
0
            /// <summary>
            /// Checks ancestor nodes recursively.
            /// </summary>
            private static bool WasAncestorCellLoaded(LodLevel parentLod, ref MyCellCoord thisLodCell)
            {
                if (parentLod == null || !parentLod.m_fitsInFrustum || !parentLod.Visible)
                {
                    return(true);
                }

                Debug.Assert(thisLodCell.Lod == parentLod.m_lodIndex - 1);

                var      shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(thisLodCell.Lod);
                var      parentCell    = new MyCellCoord(thisLodCell.Lod + 1, thisLodCell.CoordInLod >> shiftToParent);
                CellData data;

                if (parentLod.m_storedCellData.TryGetValue(parentCell.PackId64(), out data))
                {
                    return(data.WasLoaded);
                }

                LodLevel ancestor;

                if (parentLod.m_parent.m_lodLevels.TryGetValue(parentLod.m_lodIndex + 1, out ancestor))
                {
                    return(WasAncestorCellLoaded(ancestor, ref parentCell));
                }
                else
                {
                    return(false);
                }
            }
    bool ShowLodLevel(LodLevel lod, int index)
    {
        bool removeThis = false;

        EGL.BeginVertical(GuiUtils.Skin.box);
        {
            GUILayout.Label("[" + index + "]");

            lod.Level = EGL.IntField("Lod Level", lod.Level);
            GUILayout.BeginHorizontal();
            {
                lod.FolderPath = EGL.TextField("Folder Path", lod.FolderPath);
                if (GUILayout.Button("Browse", GUILayout.Width(50f)))
                {
                    lod.FolderPath = UPath.GetProjectPath(EditorUtility.OpenFolderPanel("Browse", lod.FolderPath, Application.dataPath));
                }
            }
            GUILayout.EndHorizontal();

            lod.GridSize = EGL.IntField("Grid Size", lod.GridSize);

            lod.HeightmapResolution = EGL.IntField("Heightmap Resolution (px)", lod.HeightmapResolution);
            lod.SplatmapResolution  = EGL.IntField("Splatmap Resolution (px)", lod.SplatmapResolution);

            lod.HasDetailMap = EGL.Toggle("Use Detail Map?", lod.HasDetailMap);
            lod.HasTreeMap   = EGL.Toggle("Use Tree Map?", lod.HasTreeMap);

            if (lod.HasDetailMap)
            {
                lod.DetailmapResolution      = EGL.IntField("Detailmap Resolution (px)", lod.DetailmapResolution);
                lod.DetailResolutionPerPatch = EGL.IntField("Detailmap Patch Size (px)", lod.DetailResolutionPerPatch);
            }

            EGL.Space();

            GUILayout.Label("In-game terrain dimensions.");
            lod.TerrainWidth  = EGL.FloatField("Width & Length (m)", lod.TerrainWidth);
            lod.TerrainHeight = EGL.FloatField("Height (m)", lod.TerrainHeight);

            EGL.Space();

            GUILayout.Label("Relief Terrain Configuration");
            lod.ColormapResolution  = EGL.IntField("Colormap Resolution", lod.ColormapResolution);
            lod.NormalmapResolution = EGL.IntField("Normalmap Resolution", lod.NormalmapResolution);


            EGL.Space();

            if (GUILayout.Button("Remove", GUILayout.Width(64f), GUILayout.Height(64f)))
            {
                removeThis = true;
            }
        }
        EGL.EndVertical();

        return(removeThis);
    }
Beispiel #6
0
            public void CreateLodGroupColliders(LODGroup lodGroup, Transform parentT)
            {
                var       lodGroupGO = new GameObject("L_" + lodGroup.name);
                Transform lodGroupT  = lodGroupGO.transform;

                lodGroupT.parent = parentT;

                LOD[] lods = lodGroup.GetLODs();

                bool meshColliderCreated = false;

                for (int i = 0; i < lods.Length; i++)
                {
                    LOD      lod      = lods[i];
                    LodLevel lodLevel = new LodLevel();

                    Renderer[] rs = lod.renderers;

                    for (int j = 0; j < rs.Length; j++)
                    {
                        Renderer   r  = rs[j];
                        GameObject go = r.gameObject;

                        if (r.enabled && go.activeInHierarchy)
                        {
                            MeshFilter mf = go.GetComponent <MeshFilter>();
                            if (mf == null)
                            {
                                continue;
                            }

                            Mesh mesh = mf.sharedMesh;
                            if (mesh == null)
                            {
                                continue;
                            }

                            meshColliderCreated = true;
                            MeshCollider mc = CreateMeshCollider(mf, lodGroupT, "L" + i + "_");

                            lodLevel.colliders.Add(mc);
                            lodLevel.gos.Add(mc.gameObject);
                            lodInfoLookup.Add(mc, this);
                            lodGroupMeshes.Add(mesh);
                        }
                    }

                    lodLevels.Add(lodLevel);
                }

                if (meshColliderCreated)
                {
                    lodInfos.Add(this);
                }
            }
Beispiel #7
0
        public MeshLOD GetLOD(LodLevel level)
        {
            string lodName;

            switch (level)
            {
            case LodLevel.Physics:
                lodName = "physics_mesh";
                break;

            case LodLevel.LOD0:
                lodName = "lowest_lod";
                break;

            case LodLevel.LOD1:
                lodName = "low_lod";
                break;

            case LodLevel.LOD2:
                lodName = "medium_lod";
                break;

            case LodLevel.LOD3:
                lodName = "high_lod";
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(level));
            }

            IValue iv;

            if (!m_MeshData.TryGetValue(lodName, out iv))
            {
                throw new NoSuchMeshDataException();
            }

            var lodMap = iv as Map;

            if (lodMap == null)
            {
                throw new NoSuchMeshDataException();
            }

            int physOffset = lodMap["offset"].AsInt + m_EndOfHeader;
            int physSize   = lodMap["size"].AsInt;

            if (physOffset < m_EndOfHeader || physSize <= 0)
            {
                throw new NotAMeshFormatException();
            }

            return(new MeshLOD(m_AssetData, physOffset, physSize));
        }
Beispiel #8
0
        public bool TryGetLODByteSize(LodLevel level, out int bytesize)
        {
            bytesize = 0;
            string lodName;

            switch (level)
            {
            case LodLevel.Physics:
                lodName = "physics_mesh";
                break;

            case LodLevel.LOD0:
                lodName = "lowest_lod";
                break;

            case LodLevel.LOD1:
                lodName = "low_lod";
                break;

            case LodLevel.LOD2:
                lodName = "medium_lod";
                break;

            case LodLevel.LOD3:
                lodName = "high_lod";
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(level));
            }

            IValue iv;

            if (!m_MeshData.TryGetValue(lodName, out iv))
            {
                return(false);
            }

            var lodMap = iv as Map;

            if (lodMap == null)
            {
                return(false);
            }

            bytesize = lodMap["size"].AsInt;

            if (bytesize < m_EndOfHeader || bytesize <= 0)
            {
                bytesize = 0;
                return(false);
            }
            return(true);
        }
Beispiel #9
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;
 }
Beispiel #10
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;
 }
Beispiel #11
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;
 }
Beispiel #12
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);
            }
Beispiel #14
0
            private static BoundingBox GetChildrenCoords(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null)
                {
                    return(BoundingBox.CreateInvalid());
                }

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();

                childLodCell.Lod = childLod.m_lodIndex;
                var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod);
                var start        = thisLodCell.CoordInLod << shiftToChild;
                var end          = start + ((1 << shiftToChild) >> 1);

                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);

                return(new BoundingBox(start, end));
            }
Beispiel #15
0
            /// <summary>
            /// Checks ancestor nodes recursively. Typically, this checks at most 9 nodes or so (depending on settings).
            /// </summary>
            private static bool WasAncestorCellLoaded(LodLevel parentLod, ref MyCellCoord thisLodCell)
            {            
                if (parentLod == null || !parentLod.m_fitsInFrustum || !parentLod.Visible)
                {
                    return true;
                }

                Debug.Assert(thisLodCell.Lod == parentLod.m_lodIndex - 1);

                var parentCell = new MyCellCoord(thisLodCell.Lod + 1, thisLodCell.CoordInLod >> 1);
                CellData data;
                if (parentLod.m_storedCellData.TryGetValue(parentCell.PackId64(), out data))
                {
                    return data.WasLoaded;
                }

                LodLevel ancestor;
                if (parentLod.m_parent.m_lodLevels.TryGetValue(parentLod.m_lodIndex+1, out ancestor))
                    return WasAncestorCellLoaded(ancestor, ref parentCell);
                else
                    return false;
            }
Beispiel #16
0
        public bool HasLOD(LodLevel level)
        {
            switch (level)
            {
            case LodLevel.Physics:
                return(m_MeshData.ContainsKey("physics_mesh"));

            case LodLevel.LOD0:
                return(m_MeshData.ContainsKey("lowest_lod"));

            case LodLevel.LOD1:
                return(m_MeshData.ContainsKey("low_lod"));

            case LodLevel.LOD2:
                return(m_MeshData.ContainsKey("medium_lod"));

            case LodLevel.LOD3:
                return(m_MeshData.ContainsKey("high_lod"));

            default:
                throw new ArgumentOutOfRangeException(nameof(level));
            }
        }
            /// <summary>
            /// Priority function for sorting render cell precalc jobs
            /// </summary>
            /// <param name="cellWorldPos"></param>
            /// <param name="parent"></param>
            /// <param name="parentCellId"></param>
            /// <param name="cell"></param>
            /// <returns></returns>
            int PriorityFunc(BoundingBoxD cellWorldPos, LodLevel parent, ulong parentCellId, MyCellCoord cell)
            {
                //not using priority now, only physics prefetch is prioritized before graphics
                return(int.MaxValue);
                //commented out since now we are not dependent on parent
                //if (parent != null)//topmost lod does not have parent
                //{
                //    //var coordCell = new MyCellCoord();
                //    //coordCell.SetUnpack(parentCellId);
                //    //if (!AllSiblingsWereLoaded(ref coordCell))//doesnt improve holes and slows progression awfully
                //    //    return int.MaxValue;

                //    CellData data;
                //    if (!parent.m_storedCellData.TryGetValue(parentCellId, out data) || !data.WasLoaded) //we need loaded parent for blending lods
                //        return int.MaxValue;
                //}

                //var cam = CameraMatrixGetter();//get current cam position

                ////float mult = m_lodIndex;
                //var dir = (cellWorldPos.Center - cam.Translation); //direction to camera
                //var length = dir.Length();
                //var dot = (dir/length).Dot(cam.Forward); //dot with look direction

                //if (cellWorldPos.Contains(cam.Translation) != ContainmentType.Disjoint)
                //{//we are inside the cell so top priority
                //    length = 1;
                //}
                ////commented out since now we are not dependent on parent
                ////else if (AnySiblingChildrenLoaded(ref cell))
                ////    mult = 0.1f; //we should speed up since sibling child cannot be rendered without us
                //length *= 1.5f - dot; //prioritize by view direction

                //const double intMax = (double)int.MaxValue;
                //return length > intMax ? (int)intMax : (int)length;
            }
Beispiel #18
0
            /// <summary>
            /// Checks only immediate children (any deeper would take too long).
            /// </summary>
            private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null || !childLod.Visible)
                    return false;

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();
                childLodCell.Lod = childLod.m_lodIndex;
                var start = thisLodCell.CoordInLod << 1;
                var end = start + 1;

                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);
                for (childLodCell.CoordInLod.Z = start.Z; childLodCell.CoordInLod.Z <= end.Z; ++childLodCell.CoordInLod.Z)
                for (childLodCell.CoordInLod.Y = start.Y; childLodCell.CoordInLod.Y <= end.Y; ++childLodCell.CoordInLod.Y)
                for (childLodCell.CoordInLod.X = start.X; childLodCell.CoordInLod.X <= end.X; ++childLodCell.CoordInLod.X)
                {
                    var key = childLodCell.PackId64();
                    CellData data;
                    if (!childLod.m_storedCellData.TryGetValue(key, out data))
                    {
                        return false;
                    }

                    if (!data.WasLoaded)
                    {
                        return false;
                    }
                }

                return true;
            }
Beispiel #19
0
            /// <summary>
            /// Checks ancestor nodes recursively. Typically, this checks at most 9 nodes or so (depending on settings).
            /// </summary>
            private static bool WasAncestorCellLoaded(LodLevel parentLod, ref MyCellCoord thisLodCell)
            {            
                if (parentLod == null || !parentLod.m_fitsInFrustum || !parentLod.Visible)
                {
                    return true;
                }

                Debug.Assert(thisLodCell.Lod == parentLod.m_lodIndex - 1);

                var parentCell = new MyCellCoord(thisLodCell.Lod + 1, thisLodCell.CoordInLod >> 1);
                CellData data;
                if (parentLod.m_storedCellData.TryGetValue(parentCell.PackId64(), out data))
                {
                    return data.WasLoaded;
                }

                LodLevel ancestor;
                if (parentLod.m_parent.m_lodLevels.TryGetValue(parentLod.m_lodIndex+1, out ancestor))
                    return WasAncestorCellLoaded(ancestor, ref parentCell);
                else
                    return false;
            }
Beispiel #20
0
            private void GetNearbyLodLevels(out LodLevel parentLod, out LodLevel childLod)
            {
                var levels = m_parent.m_lodLevels;

                int parentIdx = m_lodIndex + 1;
                if (levels.IsValidIndex(parentIdx))
                    parentLod = levels[parentIdx];
                else
                    parentLod = null;

                int childIdx = m_lodIndex - 1;
                if (levels.IsValidIndex(childIdx))
                    childLod = levels[childIdx];
                else
                    childLod = null;
            }
            private static BoundingBox GetChildrenCoords(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null)
                    return BoundingBox.CreateInvalid();

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();
                childLodCell.Lod = childLod.m_lodIndex;
                var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod);
                var start = thisLodCell.CoordInLod << shiftToChild;
                var end = start + ((1 << shiftToChild) >> 1);

                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);

                return new VRageMath.BoundingBox(start, end);
            }
            /// <summary>
            /// Checks only immediate children (any deeper would take too long).
            /// </summary>
            private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null)
                    return false;

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();
                childLodCell.Lod = childLod.m_lodIndex;
                var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod);
                var start = thisLodCell.CoordInLod << shiftToChild;
                var end = start + ((1 << shiftToChild) >> 1);

                Vector3I.Max(ref childLod.m_lodSizeMinusOne, ref Vector3I.Zero, out childLod.m_lodSizeMinusOne);
                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);
                childLodCell.CoordInLod = start;
                for (var it = new Vector3I_RangeIterator(ref start, ref end);
                    it.IsValid(); it.GetNext(out childLodCell.CoordInLod))
                {
                    var key = childLodCell.PackId64();
                    MyClipmap_CellData data;
                    if (!childLod.m_storedCellData.TryGetValue(key, out data) || !data.WasLoaded)
                    {
                        return false;
                    }
                }

                return true;
            }
            /// <summary>
            /// Checks ancestor nodes recursively.
            /// </summary>
            private static bool WasAncestorCellLoaded(LodLevel parentLod, ref MyCellCoord thisLodCell)
            {
                if (parentLod == null || !parentLod.m_fitsInFrustum)
                {
                    return true;
                }

                Debug.Assert(thisLodCell.Lod == parentLod.m_lodIndex - 1);

                var shiftToParent = MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(thisLodCell.Lod);
                var parentCell = new MyCellCoord(thisLodCell.Lod + 1, thisLodCell.CoordInLod >> shiftToParent);
                MyClipmap_CellData data;
                if (parentLod.m_storedCellData.TryGetValue(parentCell.PackId64(), out data))
                {
                    return data.WasLoaded;
                }

                LodLevel ancestor;
                if (parentLod.m_clipmap.m_lodLevels.TryGetValue(parentLod.m_lodIndex + 1, out ancestor))
                    return WasAncestorCellLoaded(ancestor, ref parentCell);
                else
                    return 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;
            }
            /// <summary>
            /// Priority function for sorting render cell precalc jobs
            /// </summary>
            /// <param name="cellWorldPos"></param>
            /// <param name="parent"></param>
            /// <param name="parentCellId"></param>
            /// <param name="cell"></param>
            /// <returns></returns>
            int PriorityFunc(BoundingBoxD cellWorldPos, LodLevel parent, ulong parentCellId, MyCellCoord cell)
            {
                //not using priority now, only physics prefetch is prioritized before graphics
                return int.MaxValue;
                //commented out since now we are not dependent on parent
                //if (parent != null)//topmost lod does not have parent
                //{
                //    //var coordCell = new MyCellCoord(); 
                //    //coordCell.SetUnpack(parentCellId);
                //    //if (!AllSiblingsWereLoaded(ref coordCell))//doesnt improve holes and slows progression awfully
                //    //    return int.MaxValue;

                //    CellData data;
                //    if (!parent.m_storedCellData.TryGetValue(parentCellId, out data) || !data.WasLoaded) //we need loaded parent for blending lods
                //        return int.MaxValue;
                //}

                //var cam = CameraMatrixGetter();//get current cam position

                ////float mult = m_lodIndex; 
                //var dir = (cellWorldPos.Center - cam.Translation); //direction to camera
                //var length = dir.Length(); 
                //var dot = (dir/length).Dot(cam.Forward); //dot with look direction

                //if (cellWorldPos.Contains(cam.Translation) != ContainmentType.Disjoint)
                //{//we are inside the cell so top priority
                //    length = 1;
                //}
                ////commented out since now we are not dependent on parent
                ////else if (AnySiblingChildrenLoaded(ref cell))
                ////    mult = 0.1f; //we should speed up since sibling child cannot be rendered without us
                //length *= 1.5f - dot; //prioritize by view direction

                //const double intMax = (double)int.MaxValue;
                //return length > intMax ? (int)intMax : (int)length;
            }