/// <param name="minCellLod0">Inclusive.</param>
        /// <param name="maxCellLod0">Inclusive.</param>
        public void InvalidateRange(Vector3I minCellLod0, Vector3I maxCellLod0)
        {
            //Debug.Print("InvalidateRange Clipmap: " + Id + " Min: " + minCellLod0 + " Max: " + maxCellLod0);

            if (minCellLod0 == Vector3I.Zero &&
                maxCellLod0 == m_sizeLod0 - 1)
            {
                for (int lod = 0; lod < m_lodLevels.Length; ++lod)
                {
                    m_lodLevels[lod].InvalidateAll();
                }
            }
            else
            {
                for (int lod = 0; lod < m_lodLevels.Length; ++lod)
                {
                    var shift = lod + MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShiftDelta(lod);
                    m_lodLevels[lod].InvalidateRange(
                        minCellLod0 >> shift,
                        maxCellLod0 >> shift);
                }
            }

            m_invalidated = 2;

            ResetClipping();
        }
Exemple #2
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);
            }
Exemple #3
0
            internal void UpdateCellsInScene(Vector3D localPosition)
            {
                LodLevel parentLod, childLod;

                GetNearbyLodLevels(out parentLod, out childLod);

                MyCellCoord thisLodCell = new MyCellCoord();

                foreach (var entry in m_nonEmptyCells)
                {
                    var data = entry.Value;
                    Debug.Assert(data.Cell != null);
                    thisLodCell.SetUnpack(entry.Key);

                    if (ChildrenWereLoaded(childLod, ref thisLodCell) ||
                        (MyVoxelCoordSystems.RenderCellSizeShiftToLessDetailed(thisLodCell.Lod) == 1 && !AllSiblingsWereLoaded(ref thisLodCell)))
                    {
                        RemoveFromScene(entry.Key, data);
                    }
                    else
                    {
                        AddToScene(entry.Key, data);
                    }
                }
            }
Exemple #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);
                }
            }
Exemple #5
0
 private static void TestClipSpheres(ref MyCellCoord cell, ref BoundingSphereD nearClipSphere, ref BoundingSphereD farClipSphere, out ContainmentType nearClipRes, out ContainmentType farClipRes)
 {
     BoundingBoxD localAabb;
     MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out localAabb);
     localAabb.Inflate(MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << cell.Lod));
     nearClipSphere.Contains(ref localAabb, out nearClipRes);
     farClipSphere.Contains(ref localAabb, out farClipRes);
 }
Exemple #6
0
        public static Vector3I FindBestOctreeSize(float radius)
        {
            int nodeRadius = MyVoxelCoordSystems.RenderCellSizeInLodVoxels(0);

            while (nodeRadius < radius)
            {
                nodeRadius *= 2;
            }
            return(new Vector3I(nodeRadius, nodeRadius, nodeRadius));
        }
Exemple #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;
 }
            /// <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);
            }
            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);
            }
Exemple #10
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));
            }
Exemple #11
0
 /// <param name="minCellLod0">Inclusive.</param>
 /// <param name="maxCellLod0">Inclusive.</param>
 public void InvalidateRange(Vector3I minCellLod0, Vector3I maxCellLod0)
 {
     if (minCellLod0 == Vector3I.Zero &&
         maxCellLod0 == m_sizeLod0 - 1)
     {
         for (int lod = 0; lod < m_lodLevels.Length; ++lod)
         {
             m_lodLevels[lod].InvalidateAll();
         }
     }
     else
     {
         for (int lod = 0; lod < m_lodLevels.Length; ++lod)
         {
             var shift = lod + MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShiftDelta(lod);
             m_lodLevels[lod].InvalidateRange(
                 minCellLod0 >> shift,
                 maxCellLod0 >> shift);
         }
     }
     m_updateClipping = true;
 }
Exemple #12
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);
                }
            }
Exemple #13
0
        private void Update(ref Vector3D cameraPos, float farPlaneDistance)
        {
            ProfilerShort.Begin("MyRenderClipmap.Update");

            var mostDetailedLod = (uint)DebugClipmapMostDetailedLod;

            if (m_lastMostDetailedLod != mostDetailedLod)
            {
                m_updateClipping = true;
            }
            m_lastMostDetailedLod = mostDetailedLod;
            for (uint lod = 0; lod < m_lodLevels.Length; ++lod)
            {
                m_lodLevels[lod].Visible = lod >= mostDetailedLod;
            }

            Vector3D localPosition;

            Vector3D.Transform(ref cameraPos, ref m_invWorldMatrix, out localPosition);

            double cellSizeHalf = MyVoxelCoordSystems.RenderCellSizeInMetersHalf(0);
            double threshold    = cellSizeHalf * cellSizeHalf;

            if (!m_updateClipping && Vector3D.DistanceSquared(localPosition, m_lastClippingPosition) > threshold)
            {
                m_updateClipping = true;
            }

            if (m_updateClipping)
            {
                ProfilerShort.Begin("DoClipping");
                Debug.Assert(m_scaleGroup == MyClipmapScaleEnum.Normal || m_scaleGroup == MyClipmapScaleEnum.Massive);
                for (int lod = m_lodLevels.Length - 1; lod >= mostDetailedLod; --lod)
                {
                    ProfilerShort.Begin("Lod " + lod);
                    m_lodLevels[lod].DoClipping(localPosition, farPlaneDistance, m_requestCollector);
                    ProfilerShort.End();
                }
                ProfilerShort.End();

                ProfilerShort.Begin("KeepOrDiscardClippedCells");
                for (int lod = m_lodLevels.Length - 1; lod >= mostDetailedLod; --lod)
                {
                    m_lodLevels[lod].KeepOrDiscardClippedCells(m_requestCollector);
                }
                ProfilerShort.End();

                m_lastClippingPosition = localPosition;
                m_updateClipping       = false;
            }

            ProfilerShort.Begin("UpdateCellsInScene");
            for (int lod = m_lodLevels.Length - 1; lod >= mostDetailedLod; --lod)
            {
                m_lodLevels[lod].UpdateCellsInScene(localPosition);
            }
            ProfilerShort.End();

            m_requestCollector.Submit();
            if (m_requestCollector.SentRequestsEmpty)
            {
                m_notReady.Remove(this);
            }

            ProfilerShort.End();
        }
        private void Update(ref Vector3D cameraPos, ref Vector3 cameraForward, float farPlaneDistance)
        {
            ProfilerShort.Begin("MyRenderClipmap.Update");

            LastCameraPosition = cameraPos;

            if (!Environment.Is64BitProcess)
            {
                UseCache = false;
            }

            if (NeedsResetCache)
            {
                MyClipmap.CellsCache.Reset();
                NeedsResetCache = false;
            }

            for (uint lod = 0; lod < m_lodLevels.Length; lod++)
            {
                if (m_lodLevels[lod].IsDitheringInProgress())
                {
                    m_lodLevels[lod].UpdateDithering();
                }
            }

            Vector3D localPosition;

            Vector3D.Transform(ref cameraPos, ref m_invWorldMatrix, out localPosition);

            Vector3 localForward;

            Vector3.TransformNormal(ref cameraForward, ref m_invWorldMatrix, out localForward);

            double cellSizeHalf      = MyVoxelCoordSystems.RenderCellSizeInMetersHalf(0);
            double threshold         = cellSizeHalf / 4.0f;
            float  thresholdRotation = 0.03f;

            if (!m_updateClippingFrustum && (Vector3D.DistanceSquared(localPosition, m_lastClippingPosition) > threshold) || (Vector3.DistanceSquared(localForward, m_lastClippingForward) > thresholdRotation) || m_invalidated > 0)
            {
                ResetClipping();

                m_lastClippingPosition = localPosition;
                m_lastClippingForward  = localForward;
            }

            float camDistanceFromCenter = Vector3.Distance(m_massiveCenter, cameraPos);

            if (m_requestCollector.SentRequestsEmpty && m_updateClippingFrustum)
            {
                ProfilerShort.Begin("DoClipping");
                //Top priority for 0 lod when invalidated (drill)
                if (m_invalidated == 2)
                {
                    m_lodLevels[0].DoClipping(camDistanceFromCenter, localPosition, farPlaneDistance, m_requestCollector, true, 1);
                    m_lodLevels[0].DiscardClippedCells(m_requestCollector);
                    m_lodLevels[0].UpdateCellsInScene(camDistanceFromCenter, localPosition);

                    if (!m_requestCollector.SentRequestsEmpty)
                    {
                        m_requestCollector.Submit();
                        ProfilerShort.End();    // DoClipping
                        ProfilerShort.End();    // Update
                        return;
                    }

                    m_updateClippingFrustum = false;
                    m_invalidated           = 1;
                }
                else
                {
                    //Most important frustum culling
                    for (int lod = m_lodLevels.Length - 1; lod >= 0; --lod)
                    {
                        ProfilerShort.Begin("Lod " + lod);
                        m_lodLevels[lod].DoClipping(camDistanceFromCenter, localPosition, farPlaneDistance, m_requestCollector, true, 1);
                        ProfilerShort.End();
                    }
                    //ProfilerShort.End();

                    ProfilerShort.Begin("KeepOrDiscardClippedCells");
                    for (int lod = m_lodLevels.Length - 1; lod >= 0; --lod)
                    {
                        m_lodLevels[lod].DiscardClippedCells(m_requestCollector);
                    }
                    ProfilerShort.End();

                    ProfilerShort.Begin("UpdateCellsInScene");
                    for (int lod = m_lodLevels.Length - 1; lod >= 0; --lod)
                    {
                        m_lodLevels[lod].UpdateCellsInScene(camDistanceFromCenter, localPosition);
                    }
                    ProfilerShort.End();

                    if (!m_requestCollector.SentRequestsEmpty)
                    {
                        m_requestCollector.Submit();
                        ProfilerShort.End();    // DoClipping
                        ProfilerShort.End();    // Update
                        return;
                    }

                    m_invalidated = 0;
                    m_notReady.Remove(this);
                    m_updateClippingFrustum = false;
                }
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
            /// <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);
                    }
                }
            }
Exemple #16
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();
                }
            }
            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);
                    }
                }
            }
Exemple #18
0
            public void DebugDraw()
            {
                //if (m_lodIndex > 5)
                //    return;


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

                //                //var start = localFarCameraBox.Min;
                //                //var end = localFarCameraBox.Max;
                //                var start = m_localNearCameraBox.Min;
                //                var end = m_localNearCameraBox.Max;
                //                Vector3I coord = start;

                //                Color nearColor = Color.Yellow;
                //                Color farColor = Color.White;

                //                var startF = m_localFarCameraBox.Min;
                //                var endF = m_localFarCameraBox.Max;
                //                Vector3I coordF = startF;

                ////                for (var it = new Vector3I.RangeIterator(ref startF, ref endF);
                ////it.IsValid(); it.GetNext(out coordF))
                ////                {
                ////                    Vector3D min = Vector3D.Transform((Vector3D)(sizeInMetres * coordF), m_parent.m_worldMatrix);
                ////                    Vector3D max = Vector3D.Transform((Vector3D)(sizeInMetres * coordF + new Vector3(sizeInMetres)), m_parent.m_worldMatrix);

                ////                    BoundingBoxD aabb = new BoundingBoxD(min, max);
                ////                    MyRenderProxy.DebugDrawAABB(aabb, farColor, 1, 1, false);

                ////                    if (Vector3D.Distance(CameraFrustumGetter().Matrix.Translation, aabb.Center) < 200)
                ////                        MyRenderProxy.DebugDrawText3D(aabb.Center, coordF.ToString(), farColor, 0.5f, false);
                ////                }


                //                for (var it = new Vector3I.RangeIterator(ref start, ref end);
                //it.IsValid(); it.GetNext(out coord))
                //                {
                //                    Vector3D min = Vector3D.Transform((Vector3D)(sizeInMetres * coord), m_clipmap.m_worldMatrix);
                //                    Vector3D max = Vector3D.Transform((Vector3D)(sizeInMetres * coord + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                //                    BoundingBoxD aabb = new BoundingBoxD(min, max);
                //                    MyRenderProxy.DebugDrawAABB(aabb, nearColor, 1, 1, false);
                //                }


                //                Vector3D center = Vector3D.Transform(m_localPosition, m_clipmap.m_worldMatrix);

                //                MyRenderProxy.DebugDrawSphere(center, m_nearDistance, nearColor, 1, false);
                //                MyRenderProxy.DebugDrawSphere(center, m_farDistance, farColor, 1, false);

                //            }

                var camera = m_clipmap.LastCameraPosition;

                //if (m_lodIndex < 6)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex);
                    Color color        = LOD_COLORS[m_lodIndex] + new Vector4(0.2f);


                    foreach (var cell in m_storedCellData)
                    {
                        if (!cell.Value.InScene)
                        {
                            continue;
                        }

                        MyCellCoord cellStr = new MyCellCoord();
                        cellStr.SetUnpack(cell.Key);
                        var coordF = cellStr.CoordInLod;

                        Vector3D min = Vector3D.Transform((Vector3D)(sizeInMetres * coordF), m_clipmap.m_worldMatrix);
                        Vector3D max = Vector3D.Transform((Vector3D)(sizeInMetres * coordF + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        BoundingBoxD aabb     = new BoundingBoxD(min, max);
                        double       distance = Vector3D.Distance(camera, aabb.Center);
                        //if (distance < sizeInMetres * 4)
                        MyRenderProxy.DebugDrawAABB(aabb, color, 1, 1, true);
                        if (distance < sizeInMetres * 2)
                        {
                            MyRenderProxy.DebugDrawText3D(aabb.Center, String.Format("{0}:{1}", m_lodIndex, coordF.ToString()), color, 0.7f, false);
                        }
                    }

                    if (m_storedCellData.Count > 0)
                    {
                        Vector3D center = Vector3D.Transform(m_localPosition, m_clipmap.m_worldMatrix);
                        //MyRenderProxy.DebugDrawSphere(center, m_farDistance, color, 1, false);
                    }
                }
            }
Exemple #19
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);
                        }
                    }
                }
            }
Exemple #20
0
        private void Update(ref Vector3D cameraPos, float farPlaneDistance)
        {
            ProfilerShort.Begin("MyRenderClipmap.Update");


            Vector3D localPosition;

            Vector3D.Transform(ref cameraPos, ref m_invWorldMatrix, out localPosition);

            double cellSizeHalf = MyVoxelCoordSystems.RenderCellSizeInMetersHalf(0);
            double threshold    = cellSizeHalf * cellSizeHalf;

            if (!m_updateClipping && Vector3D.DistanceSquared(localPosition, m_lastClippingPosition) > threshold)
            {
                m_updateClipping = true;
            }

            //modified clipping routine
            //we clip only when there are no old requests since we are not able to combine
            //multiple clippings reasonably
            //(need the structure to hold and merge result otherwise holes are inevitable)
            if (!m_updateClipping && m_requestCollector.SentRequestsEmpty && m_clipingAdjustment < 5)
            {
                m_clipingAdjustment += 2;
                m_updateClipping     = true;
            }

            if (m_updateClipping)
            {
                m_requestCollector.Submit();
                if (m_requestCollector.SentRequestsEmpty)
                {
                    ProfilerShort.Begin("KeepOrDiscardClippedCells");
                    for (int lod = m_lodLevels.Length - 1; lod >= 0; --lod)
                    {
                        m_lodLevels[lod].KeepOrDiscardClippedCells(m_requestCollector);
                    }
                    ProfilerShort.End();
                    if (!ENABLE_CLIPPING_ADJUSTMENT)
                    {
                        m_clipingAdjustment = 1;
                    }
                    var startLod = MathHelper.Clamp(-1 * m_clipingAdjustment, 0, m_lodLevels.Length - 1);
                    ProfilerShort.Begin("DoClipping");

                    if (NEW_VOXEL_CLIPPING)
                    {
                        m_lodLevels[startLod].DoClipping(localPosition, m_requestCollector, MathHelper.Clamp(m_clipingAdjustment, 0, 5));
                    }
                    else
                    {
                        Debug.Assert(m_scaleGroup == MyClipmapScaleEnum.Normal);
                        for (int lod = m_lodLevels.Length - 1; lod >= 0; --lod)
                        {
                            ProfilerShort.Begin("Lod " + lod);
                            m_lodLevels[lod].DoClipping_Old(localPosition, farPlaneDistance, m_requestCollector);
                            ProfilerShort.End();
                        }
                    }


                    ProfilerShort.End();
                    if (m_requestCollector.SentRequestsEmpty)
                    {
                        m_clipingAdjustment += 2;
                    }
                }
                //else
                //    m_clipingAdjustment -= 2;

                m_lastClippingPosition = localPosition;
                m_updateClipping       = false;
            }

            ProfilerShort.Begin("UpdateCellsInScene");
            for (int lod = m_lodLevels.Length - 1; lod >= 0; --lod)
            {
                m_lodLevels[lod].UpdateCellsInScene(localPosition);
            }
            ProfilerShort.End();

            m_clipingAdjustment = MathHelper.Clamp(m_clipingAdjustment, -m_lodLevels.Length + 3, 5);
            m_requestCollector.Submit();
            if (m_requestCollector.SentRequestsEmpty)
            {
                m_notReady.Remove(this);
            }

            ProfilerShort.End();
        }