// Actually, this function marks even cubes around the block to make sure that any changes caused in their triangles
        // will be reflected in the navigation mesh.
        public void MarkBlockChanged(MySlimBlock block)
        {
            Vector3I min = block.Min - Vector3I.One;
            Vector3I max = block.Max + Vector3I.One;

            Vector3I pos = min;
            for (var it = new Vector3I.RangeIterator(ref block.Min, ref block.Max); it.IsValid(); it.GetNext(out pos))
            {
                m_changedCubes.Add(pos);
            }

            Vector3I minCell = CubeToCell(ref min);
            Vector3I maxCell = CubeToCell(ref max);

            pos = minCell;
            for (var it = new Vector3I.RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out pos))
            {
                m_changedCells.Add(pos);

                MyCellCoord cellCoord = new MyCellCoord(0, pos);
                ulong packedCell = cellCoord.PackId64();

                TryClearCell(packedCell);
            }
        }
Exemplo n.º 2
0
 public IMyClipmapCell CreateCell(MyClipmapScaleEnum scaleGroup, MyCellCoord cellCoord, ref MatrixD worldMatrix)
 {
     var cell = new MyClipmapCellProxy(cellCoord, ref worldMatrix, m_massiveCenter, m_massiveRadius, m_renderFlags);
     cell.SetVisibility(false);
     cell.ScaleGroup = scaleGroup;
     return cell;
 }
Exemplo n.º 3
0
 public MyRenderVoxelCell(MyClipmapScaleEnum scaleGroup, MyCellCoord coord, ref MatrixD worldMatrix)
     : base(0, "MyRenderVoxelCell", RenderFlags.Visible | RenderFlags.CastShadows, CullingOptions.VoxelMap)
 {
     m_scaleGroup = scaleGroup;
     m_coord = coord;
     m_worldMatrix = worldMatrix;
     m_fakeVoxelMaterial.DrawTechnique = MyMeshDrawTechnique.VOXEL_MAP;
 }
 public MyRenderVoxelCellBackground(MyCellCoord coord, ref MatrixD worldMatrix, Vector3D position, float atmoshpereRadius, float planetRadius, bool hasAtmosphere) :
     base(MyClipmapScaleEnum.Massive, coord, ref worldMatrix)
 {
     m_atmosphereRadius = atmoshpereRadius;
     m_planetRadius = planetRadius;
     m_hasAtmosphere = hasAtmosphere;
     m_position = position;
     m_leftCornerPositionOffset =  worldMatrix.Translation -position;
 }
Exemplo n.º 5
0
        IMyClipmapCell IMyClipmapCellHandler.CreateCell(MyClipmapScaleEnum scaleGroup, MyCellCoord cellCoord, ref MatrixD worldMatrix)
        {
            switch (scaleGroup)
            {
                case MyClipmapScaleEnum.Normal:
                    return new MyRenderVoxelCell(scaleGroup, cellCoord, ref worldMatrix);

                default:
                    throw new InvalidBranchException();
            }
        }
Exemplo n.º 6
0
		internal MyClipmapCellProxy(MyCellCoord cellCoord, ref VRageMath.MatrixD worldMatrix, RenderFlags additionalFlags = 0)
        {
            m_worldMatrix = worldMatrix;

            m_actor = MyActorFactory.CreateSceneObject();
            m_actor.SetMatrix(ref worldMatrix);
            m_actor.AddComponent(MyComponentFactory<MyFoliageComponent>.Create());

            m_lod = cellCoord.Lod;

            Mesh = MyMeshes.CreateVoxelCell(cellCoord.CoordInLod, cellCoord.Lod);
            m_actor.GetRenderable().SetModel(Mesh);
			m_actor.GetRenderable().m_additionalFlags = MyProxiesFactory.GetRenderableProxyFlags(additionalFlags);
        }
Exemplo n.º 7
0
        IMyClipmapCell IMyClipmapCellHandler.CreateCell(MyClipmapScaleEnum scaleGroup, MyCellCoord cellCoord, ref MatrixD worldMatrix)
        {
            switch (scaleGroup)
            {
                case MyClipmapScaleEnum.Normal:
                    return new MyRenderVoxelCell(scaleGroup, cellCoord, ref worldMatrix);

                case MyClipmapScaleEnum.Massive:
                    return new MyRenderVoxelCellBackground(cellCoord, ref worldMatrix, m_position, m_atmosphereRadius, m_planetRadius, m_hasAtmosphere);

                default:
                    throw new InvalidBranchException();
            }
        }
Exemplo n.º 8
0
        internal MyClipmapCellProxy(MyCellCoord cellCoord, ref VRageMath.Matrix worldMatrix)
        {
            m_worldMatrix = worldMatrix;

            m_actor = MyActorFactory.CreateSceneObject();
            //m_mesh = new MyVoxelMesh(cellCoord.CoordInLod, cellCoord.Lod, "");
            //m_actor.GetRenderable().SetModel(m_mesh);
            m_actor.SetMatrix(ref worldMatrix);
            m_actor.AddComponent(MyComponentFactory<MyFoliageComponent>.Create());

            m_lod = cellCoord.Lod;

            Mesh = MyMeshes.CreateVoxelCell(cellCoord.CoordInLod, cellCoord.Lod);
            m_actor.GetRenderable().SetModel(Mesh);

            m_discardingOn = false;
        }
Exemplo n.º 9
0
 internal void InvalidateRange(Vector3I lodMin, Vector3I lodMax)
 {
     var cell = new MyCellCoord(m_lodIndex, lodMin);
     for (var it = new Vector3I.RangeIterator(ref lodMin, ref lodMax);
         it.IsValid(); it.GetNext(out cell.CoordInLod))
     {
         CellData data;
         var id = cell.PackId64();
         using (m_storedCellDataLock.AcquireSharedUsing())
         {
             if (m_storedCellData.TryGetValue(id, out data))
             {
                 data.State = CellState.Invalid;
             }
         }
     }
 }
Exemplo n.º 10
0
 public static void RenderCellCoordToLocalAABB(ref MyCellCoord renderCell, out BoundingBoxD localAABB)
 {
     Vector3D localMinCorner;
     RenderCellCoordToLocalPosition(ref renderCell, out localMinCorner);
     localAABB = new BoundingBoxD(localMinCorner, localMinCorner + RenderCellSizeInMeters(renderCell.Lod));
 }
Exemplo n.º 11
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);
                }
            }
Exemplo n.º 12
0
            public void Submit()
            {
                ProfilerShort.Begin("RequestCollector.Submit");

                MyCellCoord cell = default(MyCellCoord);

                foreach (var cellId in m_cancelRequests)
                {
                    cell.SetUnpack(cellId);
                    MyRenderProxy.CancelClipmapCell(m_clipmapId, cell);
                    bool removed = m_sentRequests.Remove(cellId);
                    Debug.Assert(removed);
                }

                foreach (var request in m_unsentRequests)
                {
                    m_sentRequests.Add(request.Key);
                    cell.SetUnpack(request.Key);
                    MyRenderProxy.RequireClipmapCell(m_clipmapId, cell, true, request.Value.PriorityFunc, request.Value.DebugDraw);
                }

                m_unsentRequests.Clear();

                //foreach (var highPriorityRequest in m_unsentRequestsHigh)
                //{
                //    cell.SetUnpack(highPriorityRequest);
                //    MyRenderProxy.RequireClipmapCell(m_clipmapId, cell, highPriority: true);
                //}
                //m_unsentRequestsHigh.Clear();

                int addedCount = 0;

                for (int i = m_unsentRequestsLow.Length - 1; i >= 0; i--)
                {
                    var unsent = m_unsentRequestsLow[i];
                    while (0 < unsent.Count)// && m_sentRequests.Count < m_maxRequests*1000)
                    {
                        var pair   = unsent.FirstPair();
                        var cellId = pair.Key;
                        var hs     = new HashSet <object>();
                        cell.SetUnpack(cellId);
                        // Do Z-order style iteration of siblings that also need to
                        // be requested. This ensures faster processing of cells and
                        // shorter time when both lods are rendered.
                        var baseCoord = (cell.CoordInLod >> 1) << 1;
                        var offset    = Vector3I.Zero;
                        for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref Vector3I.One);
                             it.IsValid(); it.GetNext(out offset))
                        {
                            cell.CoordInLod = baseCoord + offset;
                            cellId          = cell.PackId64();
                            if (!unsent.Remove(cellId))
                            {
                                continue;
                            }

                            Debug.Assert(!m_cancelRequests.Contains(cellId));
                            MyRenderProxy.RequireClipmapCell(m_clipmapId, cell, false, pair.Value.PriorityFunc, pair.Value.DebugDraw);
                            bool added = m_sentRequests.Add(cellId);
                            Debug.Assert(added);
                            addedCount++;
                        }
                    }

                    // When set reaches reasonably small size, stop freeing memory
                    //if (unsent.Count > 100) no trim for dictionary :(
                    //    unsent.TrimExcess();
                }

                m_cancelRequests.Clear();

                ProfilerShort.End();
            }
Exemplo n.º 13
0
        private MyNavigationTriangle GetClosestNavigationTriangle(ref Vector3 point, ref float closestDistanceSq)
        {
            // TODO: When point is completely away (according to BB), return null

            MyNavigationTriangle closestTriangle = null;

            // Convert from world matrix local coords to LeftBottomCorner-based coords
            Vector3 lbcPoint = point + (m_voxelMap.PositionComp.GetPosition() - m_voxelMap.PositionLeftBottomCorner);

            Vector3I closestCellCorner = Vector3I.Round(lbcPoint / m_cellSize);
            for (int i = 0; i < 8; ++i)
            {
                Vector3I cell = closestCellCorner + m_cornerOffsets[i];
                if (!m_processedCells.Contains(cell)) continue;

                MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cell);
                ulong packedCoord = coord.PackId64();
                MyIntervalList triList = m_higherLevelHelper.TryGetTriangleList(packedCoord);
                if (triList == null) continue;

                foreach (var triIndex in triList)
                {
                    MyNavigationTriangle tri = GetTriangle(triIndex);

                    // TODO: Use triangle centers so far
                    float distSq = Vector3.DistanceSquared(tri.Center, point);
                    if (distSq < closestDistanceSq)
                    {
                        closestDistanceSq = distSq;
                        closestTriangle = tri;
                    }
                }
            }

            return closestTriangle;
        }
Exemplo n.º 14
0
        private bool AddCell(Vector3I cellPos)
        {
            MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cellPos);

            var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(new MyIsoMesherArgs()
            {
                Storage = m_voxelMap.Storage,
                GeometryCell = coord,
            });

            if (generatedMesh == null)
            {
                m_processedCells.Add(ref cellPos);
                m_higherLevelHelper.AddExplored(ref cellPos);
                return false;
            }

            ulong packedCoord = coord.PackId64();

            List<DebugDrawEdge> debugEdgesList = new List<DebugDrawEdge>();
            m_debugCellEdges[packedCoord] = debugEdgesList;

            MyVoxelPathfinding.CellId cellId = new MyVoxelPathfinding.CellId() { VoxelMap = m_voxelMap, Pos = cellPos };

            MyTrace.Send(TraceWindow.Ai, "Adding cell " + cellPos);

            m_connectionHelper.ClearCell();
            m_vertexMapping.Init(generatedMesh.VerticesCount);

            // Prepare list of possibly intersecting cube grids for voxel-grid navmesh intersection testing
            Vector3D bbMin = m_voxelMap.PositionLeftBottomCorner + (m_cellSize * (new Vector3D(-0.125) + cellPos));
            Vector3D bbMax = m_voxelMap.PositionLeftBottomCorner + (m_cellSize * (Vector3D.One + cellPos));
            BoundingBoxD cellBB = new BoundingBoxD(bbMin, bbMax);
            m_tmpGridList.Clear();
            m_navmeshCoordinator.PrepareVoxelTriangleTests(cellBB, m_tmpGridList);

            Vector3D voxelMapCenter = m_voxelMap.PositionComp.GetPosition();
            Vector3 centerDisplacement = voxelMapCenter - m_voxelMap.PositionLeftBottomCorner;

            // This is needed for correct edge classification - to tell, whether the edges are inner or outer edges of the cell
            ProfilerShort.Begin("Triangle preprocessing");
            for (int i = 0; i < generatedMesh.TrianglesCount; i++)
            {
                ushort a = generatedMesh.Triangles[i].VertexIndex0;
                ushort b = generatedMesh.Triangles[i].VertexIndex1;
                ushort c = generatedMesh.Triangles[i].VertexIndex2;

                Vector3 aPos, bPos, cPos;
                Vector3 vert;

                generatedMesh.GetUnpackedPosition(a, out vert);
                aPos = vert - centerDisplacement;
                generatedMesh.GetUnpackedPosition(b, out vert);
                bPos = vert - centerDisplacement;
                generatedMesh.GetUnpackedPosition(c, out vert);
                cPos = vert - centerDisplacement;

                bool invalidTriangle = false;
                if ((bPos - aPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ)
                {
                    m_vertexMapping.Union(a, b);
                    invalidTriangle = true;
                }
                if ((cPos - aPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ)
                {
                    m_vertexMapping.Union(a, c);
                    invalidTriangle = true;
                }
                if ((cPos - bPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ)
                {
                    m_vertexMapping.Union(b, c);
                    invalidTriangle = true;
                }

                if (invalidTriangle) continue;

                m_connectionHelper.PreprocessInnerEdge(a, b);
                m_connectionHelper.PreprocessInnerEdge(b, c);
                m_connectionHelper.PreprocessInnerEdge(c, a);
            }
            ProfilerShort.End();

            ProfilerShort.Begin("Free face sorting");
            // Ensure that the faces have increasing index numbers
            Mesh.SortFreeFaces();
            ProfilerShort.End();

            m_higherLevelHelper.OpenNewCell(coord);

            ProfilerShort.Begin("Adding triangles");
            for (int i = 0; i < generatedMesh.TrianglesCount; i++)
            {
                ushort a = generatedMesh.Triangles[i].VertexIndex0;
                ushort b = generatedMesh.Triangles[i].VertexIndex1;
                ushort c = generatedMesh.Triangles[i].VertexIndex2;
                ushort setA = (ushort)m_vertexMapping.Find(a);
                ushort setB = (ushort)m_vertexMapping.Find(b);
                ushort setC = (ushort)m_vertexMapping.Find(c);

                if (setA == setB || setB == setC || setA == setC) continue;

                Vector3 aPos, bPos, cPos;
                Vector3 vert;
                generatedMesh.GetUnpackedPosition(a, out vert);
                aPos = vert - centerDisplacement;
                generatedMesh.GetUnpackedPosition(b, out vert);
                bPos = vert - centerDisplacement;
                generatedMesh.GetUnpackedPosition(c, out vert);
                cPos = vert - centerDisplacement;

                if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
                {
                    Vector3 normal = (cPos - aPos).Cross(bPos - aPos);
                    normal.Normalize();
                    if (normal.Dot(ref Vector3.Up) <= Math.Cos(MathHelper.ToRadians(54.0f))) continue;
                }

                Vector3D aTformed = aPos + voxelMapCenter;
                Vector3D bTformed = bPos + voxelMapCenter;
                Vector3D cTformed = cPos + voxelMapCenter;

                bool intersecting = false;
                m_tmpLinkCandidates.Clear();
                m_navmeshCoordinator.TestVoxelNavmeshTriangle(ref aTformed, ref bTformed, ref cTformed, m_tmpGridList, m_tmpLinkCandidates, out intersecting);
                if (intersecting)
                {
                    m_tmpLinkCandidates.Clear();
                    continue;
                }

                if (!m_connectionHelper.IsInnerEdge(a, b)) debugEdgesList.Add(new DebugDrawEdge(aTformed, bTformed));
                if (!m_connectionHelper.IsInnerEdge(b, c)) debugEdgesList.Add(new DebugDrawEdge(bTformed, cTformed));
                if (!m_connectionHelper.IsInnerEdge(c, a)) debugEdgesList.Add(new DebugDrawEdge(cTformed, aTformed));

                int edgeAB = m_connectionHelper.TryGetAndRemoveEdgeIndex(b, a, ref bPos, ref aPos);
                int edgeBC = m_connectionHelper.TryGetAndRemoveEdgeIndex(c, b, ref cPos, ref bPos);
                int edgeCA = m_connectionHelper.TryGetAndRemoveEdgeIndex(a, c, ref aPos, ref cPos);
                int formerAB = edgeAB;
                int formerBC = edgeBC;
                int formerCA = edgeCA;

                ProfilerShort.Begin("AddTriangle");
                var tri = AddTriangle(ref aPos, ref bPos, ref cPos, ref edgeAB, ref edgeBC, ref edgeCA);
                ProfilerShort.End();

                CheckMeshConsistency();

                m_higherLevelHelper.AddTriangle(tri.Index);

                if (formerAB == -1) m_connectionHelper.AddEdgeIndex(a, b, ref aPos, ref bPos, edgeAB);
                if (formerBC == -1) m_connectionHelper.AddEdgeIndex(b, c, ref bPos, ref cPos, edgeBC);
                if (formerCA == -1) m_connectionHelper.AddEdgeIndex(c, a, ref cPos, ref aPos, edgeCA);

                // TODO: Instead of this, just add the tri into a list of tris that want to connect with the link candidates
                //m_navmeshCoordinator.TryAddVoxelNavmeshLinks(tri, cellId, m_tmpLinkCandidates);
                foreach (var candidate in m_tmpLinkCandidates)
                {
                    List<MyNavigationPrimitive> primitives = null;
                    if (!m_tmpCubeLinkCandidates.TryGetValue(candidate, out primitives))
                    {
                        primitives = m_primitiveListPool.Allocate();
                        m_tmpCubeLinkCandidates.Add(candidate, primitives);
                    }
                    
                    primitives.Add(tri);
                }
                m_tmpLinkCandidates.Clear();
            }
            ProfilerShort.End();

            m_tmpGridList.Clear();
            m_connectionHelper.ClearCell();
            m_vertexMapping.Clear();

            Debug.Assert(!m_processedCells.Contains(ref cellPos));
            m_processedCells.Add(ref cellPos);
            m_higherLevelHelper.AddExplored(ref cellPos);

            // Find connected components in the current cell's subgraph of the navigation mesh
            m_higherLevelHelper.ProcessCellComponents();
            m_higherLevelHelper.CloseCell();

            // Create navmesh links using the navmesh coordinator, taking into consideration the high level components
            m_navmeshCoordinator.TryAddVoxelNavmeshLinks2(cellId, m_tmpCubeLinkCandidates);
            m_navmeshCoordinator.UpdateVoxelNavmeshCellHighLevelLinks(cellId);

            foreach (var candidate in m_tmpCubeLinkCandidates)
            {
                candidate.Value.Clear();
                m_primitiveListPool.Deallocate(candidate.Value);
            }
            m_tmpCubeLinkCandidates.Clear();

            return true;
        }
        public bool Intersects(ref BoundingSphereD localSphere)
        {
            MyPrecalcComponent.AssertUpdateThread();

            //  Get min and max cell coordinate where boundingBox can fit
            BoundingBoxD sphereBoundingBox = BoundingBoxD.CreateInvalid();
            sphereBoundingBox.Include(ref localSphere);
            Vector3I cellCoordMin, cellCoordMax;
            {
                Vector3D minD = sphereBoundingBox.Min;
                Vector3D maxD = sphereBoundingBox.Max;
                MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref minD, out cellCoordMin);
                MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref maxD, out cellCoordMax);
            }

            //  Fix min and max cell coordinates so they don't overlap the voxelmap
            ClampCellCoord(ref cellCoordMin);
            ClampCellCoord(ref cellCoordMax);

            MyCellCoord cell = new MyCellCoord();
            for (cell.CoordInLod.X = cellCoordMin.X; cell.CoordInLod.X <= cellCoordMax.X; cell.CoordInLod.X++)
            {
                for (cell.CoordInLod.Y = cellCoordMin.Y; cell.CoordInLod.Y <= cellCoordMax.Y; cell.CoordInLod.Y++)
                {
                    for (cell.CoordInLod.Z = cellCoordMin.Z; cell.CoordInLod.Z <= cellCoordMax.Z; cell.CoordInLod.Z++)
                    {
                        //  If no overlap between bounding box of data cell and the sphere
                        BoundingBox cellBoundingBox;
                        MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref cell.CoordInLod, out cellBoundingBox);
                        if (cellBoundingBox.Intersects(ref localSphere) == false)
                            continue;

                        //  Get cell from cache. If not there, precalc it and store in the cache.
                        //  If null is returned, we know that cell doesn't contain any triangleVertexes so we don't need to do intersections.
                        CellData cachedData = GetCell(ref cell);

                        if (cachedData == null) continue;

                        for (int i = 0; i < cachedData.VoxelTrianglesCount; i++)
                        {
                            MyVoxelTriangle voxelTriangle = cachedData.VoxelTriangles[i];

                            MyTriangle_Vertexes triangle;
                            cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangle.Vertex0);
                            cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangle.Vertex1);
                            cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangle.Vertex2);

                            BoundingBox localTriangleAABB = BoundingBox.CreateInvalid();
                            localTriangleAABB.Include(ref triangle.Vertex0);
                            localTriangleAABB.Include(ref triangle.Vertex1);
                            localTriangleAABB.Include(ref triangle.Vertex2);

                            //  First test intersection of triangle's bounding box with line's bounding box. And only if they overlap or intersect, do further intersection tests.
                            if (localTriangleAABB.Intersects(ref localSphere))
                            {
                                PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2);

                                if (MyUtils.GetSphereTriangleIntersection(ref localSphere, ref trianglePlane, ref triangle) != null)
                                {
                                    //  If intersection found - we are finished. We don't need to look for more.
                                    return true;
                                }
                            }
                        }

                    }
                }
            }

            return false;
        }
Exemplo n.º 16
0
        public static void RenderCellCoordToLocalPosition(ref MyCellCoord renderCell, out Vector3D localPosition)
        {
            var scale = 1 << renderCell.Lod;

            localPosition = renderCell.CoordInLod * scale * MyVoxelConstants.RENDER_CELL_SIZE_IN_METRES;
        }
Exemplo n.º 17
0
        public static void RenderCellCoordToWorldPosition(Vector3D referenceVoxelMapPosition, ref MyCellCoord renderCell, out Vector3D worldPosition)
        {
            Vector3D localPosition;

            RenderCellCoordToLocalPosition(ref renderCell, out localPosition);
            LocalPositionToWorldPosition(referenceVoxelMapPosition, ref localPosition, out worldPosition);
        }
Exemplo n.º 18
0
 public static void GeometryCellCoordToLocalPosition(ref MyCellCoord geometryCellCoord, out Vector3D localPosition)
 {
     localPosition = geometryCellCoord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES * (1 << geometryCellCoord.Lod);
 }
Exemplo n.º 19
0
 public static void RenderCellCoordToWorldAABB(Vector3D referenceVoxelMapPosition, ref MyCellCoord renderCell, out BoundingBoxD worldAABB)
 {
     RenderCellCoordToLocalAABB(ref renderCell, out worldAABB);
     worldAABB = worldAABB.Translate(referenceVoxelMapPosition);
 }
Exemplo n.º 20
0
        public static void GeometryCellCoordToWorldAABB(Vector3D referenceVoxelMapPosition, ref MyCellCoord geometryCellCoord, out BoundingBoxD worldAABB)
        {
            Vector3D center;

            GeometryCellCoordToLocalPosition(ref geometryCellCoord, out center);
            LocalPositionToWorldPosition(referenceVoxelMapPosition, ref center, out center);
            worldAABB = new BoundingBoxD(center, center + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES * (1 << geometryCellCoord.Lod));
        }
Exemplo n.º 21
0
 public static void RenderCellCoordToLocalPosition(ref MyCellCoord renderCell, out Vector3D localPosition)
 {
     localPosition = renderCell.CoordInLod * RenderCellSizeInMeters(renderCell.Lod);
 }
Exemplo n.º 22
0
            /// <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);
                    }
                }
            }
Exemplo n.º 23
0
 public static void RenderCellCoordToWorldAABB(Vector3D referenceVoxelMapPosition, ref MyCellCoord renderCell, out BoundingBoxD worldAABB)
 {
     RenderCellCoordToLocalAABB(ref renderCell, out worldAABB);
     worldAABB = worldAABB.Translate(referenceVoxelMapPosition);
 }
Exemplo n.º 24
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);
                        }
                    }
                }
            }
Exemplo n.º 25
0
 public static void RenderCellCoordToLocalPosition(ref MyCellCoord renderCell, out Vector3D localPosition)
 {
     localPosition = renderCell.CoordInLod * RenderCellSizeInMeters(renderCell.Lod);
 }
Exemplo n.º 26
0
            internal void SetCellMesh(MyRenderMessageUpdateClipmapCell msg)
            {
                var      cellId = msg.Metadata.Cell.PackId64();
                CellData data;
                var      clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);

                //  MyCellCoord cellc = new MyCellCoord();
                //  cellc.SetUnpack(cellId);

                //MyLog.Default.WriteLine("SetCellMesh Lod: " + cellc.Lod + " Coord: " + cellc.CoordInLod);

                if (m_storedCellData.TryGetValue(cellId, out data))
                {
                    PendingCacheCellData.Remove(clipmapCellId);

                    if (data.State == CellState.Invalid)
                    {
//                        MyLog.Default.WriteLine("Invalid");
                        //Cell was invalidated while calculating from old data
                        return;
                    }

                    if (data.Cell == null && msg.Batches.Count != 0)
                    {
                        //MyLog.Default.WriteLine("added to nonempty");
                        data.Cell = m_clipmap.m_cellHandler.CreateCell(m_clipmap.m_scaleGroup, msg.Metadata.Cell, ref m_clipmap.m_worldMatrix);
                        System.Diagnostics.Debug.Assert(data.Cell != null, "Cell not created");
                        if (data.Cell != null)
                        {
                            if (data.Cell.IsValid())
                            {
                                data.CellHandler        = m_clipmap.m_cellHandler;
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }
                    else if (data.Cell != null && msg.Batches.Count == 0)
                    {
                        //MyLog.Default.WriteLine("removed");
                        RemoveFromScene(cellId, data);
                        m_nonEmptyCells.Remove(cellId);
                        m_clipmap.m_cellHandler.DeleteCell(data.Cell);
                        m_blendedCells.Remove(cellId);
                        data.Cell        = null;
                        data.CellHandler = null;
                        if (UseCache)
                        {
                            CellsCache.Remove(cellId);
                        }
                    }

                    if (data.Cell != null)
                    {
                        //MyLog.Default.WriteLine("mesh updated");
                        if (data.Cell.IsValid())
                        {
                            m_clipmap.m_cellHandler.UpdateMesh(data.Cell, msg);
                        }
                    }
                    data.State     = CellState.Loaded;
                    data.WasLoaded = true;
                }
                else
                if (PendingCacheCellData.TryGetValue(clipmapCellId, out data))
                {
                    if (msg.Batches.Count != 0)
                    {
                        data.Cell = m_clipmap.m_cellHandler.CreateCell(m_clipmap.m_scaleGroup, msg.Metadata.Cell, ref m_clipmap.m_worldMatrix);
                        m_clipmap.m_cellHandler.UpdateMesh(data.Cell, msg);
                        data.CellHandler = m_clipmap.m_cellHandler;
                    }

                    CellsCache.Write(clipmapCellId, data);
                    PendingCacheCellData.Remove(clipmapCellId);

                    data.State     = CellState.Loaded;
                    data.WasLoaded = true;
                }
            }
        private void SetEmpty(ref MyCellCoord cell, bool value)
        {
            UInt64 cacheKey;
            int bitIdx;
            ComputeIsEmptyLookup(cell, out cacheKey, out bitIdx);
            var cacheLine = m_isEmptyCache.Read(cacheKey);
            if (value)
                cacheLine |= ((ulong)1) << bitIdx;
            else
                cacheLine &= ~(((ulong)1) << bitIdx);
            m_isEmptyCache.Write(cacheKey, cacheLine);

            Debug.Assert(IsEmpty(ref cell) == value);
        }
Exemplo n.º 28
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);
                    }
                }
            }
Exemplo n.º 29
0
        public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged)
        {
            minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate;
            maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate;

            m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged);
            m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged);

            Vector3I minCell, maxCell;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCell);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCell);

            Vector3I currentCell = minCell;
            for (var it = new Vector3I.RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out currentCell))
            {
                if (m_processedCells.Contains(ref currentCell))
                {
                    RemoveCell(currentCell);
                }

                MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, currentCell);
                m_higherLevelHelper.TryClearCell(coord.PackId64());
            }
        }
Exemplo n.º 30
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();
                }
            }
Exemplo n.º 31
0
        private bool RemoveCell(Vector3I cell)
        {
            if (!MyFakes.REMOVE_VOXEL_NAVMESH_CELLS) return true;

            Debug.Assert(m_processedCells.Contains(cell), "Removing a non-existent cell from the navmesh!");
            if (!m_processedCells.Contains(cell)) return false;

            MyTrace.Send(TraceWindow.Ai, "Removing cell " + cell);

            ProfilerShort.Begin("Removing navmesh links");
            MyVoxelPathfinding.CellId cellId = new MyVoxelPathfinding.CellId() { VoxelMap = m_voxelMap, Pos = cell };
            m_navmeshCoordinator.RemoveVoxelNavmeshLinks(cellId);
            ProfilerShort.End();

            ProfilerShort.Begin("Removing triangles");
            MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cell);
            ulong packedCoord = coord.PackId64();
            MyIntervalList triangleList = m_higherLevelHelper.TryGetTriangleList(packedCoord);
            if (triangleList != null)
            {
                foreach (var triangleIndex in triangleList)
                {
                    RemoveTerrainTriangle(GetTriangle(triangleIndex));
                }
                m_higherLevelHelper.ClearCachedCell(packedCoord);
            }
            ProfilerShort.End();

            Debug.Assert(m_processedCells.Contains(ref cell));
            m_processedCells.Remove(ref cell);

            return triangleList != null;
        }
Exemplo n.º 32
0
            /// <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;
            }
Exemplo n.º 33
0
        private MyHighLevelPrimitive GetClosestHighLevelPrimitive(ref Vector3 point, ref float closestDistanceSq)
        {
            MyHighLevelPrimitive retval = null;

            // Convert from world matrix local coords to LeftBottomCorner-based coords
            Vector3 lbcPoint = point + (m_voxelMap.PositionComp.GetPosition() - m_voxelMap.PositionLeftBottomCorner);

            m_tmpIntList.Clear();

            // Collect components from the eight closest cells
            Vector3I closestCellCorner = Vector3I.Round(lbcPoint / m_cellSize);
            for (int i = 0; i < 8; ++i)
            {
                Vector3I cell = closestCellCorner + m_cornerOffsets[i];

                MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cell);
                ulong packedCoord = coord.PackId64();

                m_higherLevelHelper.CollectComponents(packedCoord, m_tmpIntList);
            }

            foreach (int componentIndex in m_tmpIntList)
            {
                var hlPrimitive = m_higherLevel.GetPrimitive(componentIndex);
                Debug.Assert(hlPrimitive != null, "Couldnt' find a high-level primitive for the index given by higher level helper!");
                if (hlPrimitive == null) continue;

                float distSq = Vector3.DistanceSquared(hlPrimitive.Position, point);
                if (distSq < closestDistanceSq)
                {
                    closestDistanceSq = distSq;
                    retval = hlPrimitive;
                }
            }

            m_tmpIntList.Clear();

            return retval;
        }
Exemplo n.º 34
0
 internal void OnTaskComplete(MyCellCoord coord, HkBvCompressedMeshShape childShape)
 {
     Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen.");
     if (RigidBody != null)
     {
         HkUniformGridShape shape = GetShape(coord.Lod);
         Debug.Assert(shape.Base.IsValid);
         shape.SetChild(coord.CoordInLod.X, coord.CoordInLod.Y, coord.CoordInLod.Z, childShape, HkReferencePolicy.None);
         //BoundingBoxD worldAabb;
         //MyVoxelCoordSystems.GeometryCellCoordToWorldAABB(m_voxelMap.PositionLeftBottomCorner, ref coord, out worldAabb);
         //VRageRender.MyRenderProxy.DebugDrawAABB(worldAabb, Color.Green, 1f, 1f, true);
         m_needsShapeUpdate = true;
     }
 }
Exemplo n.º 35
0
        private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary<Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList)
        {
            bool useCache = cache != null;
            if (useCache)
                CheckCacheValidity();

            obb.HalfExtent += new Vector3D(border, 0, border);
            BoundingBoxD bb = obb.GetAABB();            
            int aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2);
            bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide);
            bb.Translate(obb.Center - bb.Center);

            // For debug
            bbList.Add(new BoundingBoxD(bb.Min, bb.Max));

            bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            bb.Translate(voxelBase.SizeInMetresHalf);

            Vector3I min = Vector3I.Round(bb.Min);
            Vector3I max = min + aabbSideSide;
            Vector3I geomMin, geomMax;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax);

            var cullBox = obb;
            cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            cullBox.Center += voxelBase.SizeInMetresHalf;
            ProfilerShort.Begin("WOOOORK");

            Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref geomMin, ref geomMax);
            MyCellCoord coord = new MyCellCoord();
            BoundingBox localAabb;
            coord.Lod = NAVMESH_LOD;
            int hits = 0;
            MyIsoMesh gMesh;
            Vector3 offset = originPosition - voxelBase.PositionLeftBottomCorner;

            // Calculate rotation
            Vector3 gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Vector3 forwardVector = Vector3.CalculatePerpendicularVector(gravityVector);
            Quaternion quaternion = Quaternion.CreateFromForwardUp(forwardVector, gravityVector);
            Matrix rotation = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion));

            Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (it.IsValid())
            {
                ProfilerShort.Begin("ITERATOR");

                if (useCache && cache.TryGetValue(it.Current, out gMesh))
                {
                    if (gMesh != null)
                    {
                        AddMeshTriangles(gMesh, offset, rotation, ownRotation);
                    }
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                    
                coord.CoordInLod = it.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb);
                
                if (!cullBox.Intersects(ref localAabb))
                {
                    hits++;
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                ProfilerShort.End();

                var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf);
                bbList.Add(debugBB);

                ProfilerShort.Begin("Mesh Calc");
                var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1;
                var voxelEnd = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1
                    + 1 // overlap to neighbor so geometry is stitched together within same LOD
                    + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels)

                var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true);
                ProfilerShort.End();

                if (useCache)
                    cache[it.Current] = generatedMesh;

                if (generatedMesh != null)
                {
                    ProfilerShort.Begin("Mesh NOT NULL");
                    AddMeshTriangles(generatedMesh, offset, rotation, ownRotation);
                    ProfilerShort.End();
                }
                it.MoveNext();
            }
            ProfilerShort.End();
        }
Exemplo n.º 36
0
            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);
            }
Exemplo n.º 37
0
 public static void RenderCellCoordToWorldPosition(Vector3D referenceVoxelMapPosition, ref MyCellCoord renderCell, out Vector3D worldPosition)
 {
     Vector3D localPosition;
     RenderCellCoordToLocalPosition(ref renderCell, out localPosition);
     LocalPositionToWorldPosition(referenceVoxelMapPosition, ref localPosition, out worldPosition);
 }
        internal CellData GetCell(ref MyCellCoord cell)
        {
            MyPrecalcComponent.AssertUpdateThread();

            bool isEmpty;
            CellData data;
            if (TryGetCell(cell, out isEmpty, out data))
            {
                return data;
            }

            MyIsoMesh mesh;
            if (!TryGetMesh(cell, out isEmpty, out mesh))
            {
                ProfilerShort.Begin("Cell precalc");
                if (true)
                {
                    var min = cell.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
                    var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS;
                    // overlap to neighbor; introduces extra data but it makes logic for raycasts simpler (no need to check neighbor cells)
                    min -= 1;
                    max += 2;
                    mesh = MyPrecalcComponent.IsoMesher.Precalc(m_storage, 0, min, max, false, MyFakes.ENABLE_VOXEL_COMPUTED_OCCLUSION, true);
                }
                else
                {
                    mesh = MyPrecalcComponent.IsoMesher.Precalc(new MyIsoMesherArgs()
                    {
                        Storage = m_storage,
                        GeometryCell = cell,
                    });
                }
                ProfilerShort.End();
            }

            if (mesh != null)
            {
                data = new CellData();
                data.Init(
                    mesh.PositionOffset, mesh.PositionScale,
                    mesh.Positions.GetInternalArray(), mesh.VerticesCount,
                    mesh.Triangles.GetInternalArray(), mesh.TrianglesCount);
            }

            if (cell.Lod == 0)
            {
                using (m_lock.AcquireExclusiveUsing())
                {
                    if (data != null)
                    {
                        var key = cell.PackId64();
                        m_cellsByCoordinate[key] = data;
                    }
                    else
                    {
                        SetEmpty(ref cell, true);
                    }
                }
            }

            return data;
        }
Exemplo n.º 39
0
 public static void GeometryCellCoordToWorldAABB(Vector3D referenceVoxelMapPosition, ref MyCellCoord geometryCellCoord, out BoundingBoxD worldAABB)
 {
     Vector3D center;
     GeometryCellCoordToLocalPosition(ref geometryCellCoord, out center);
     LocalPositionToWorldPosition(referenceVoxelMapPosition, ref center, out center);
     worldAABB = new BoundingBoxD(center, center + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES * (1 << geometryCellCoord.Lod));
 }
 private void ComputeIsEmptyLookup(MyCellCoord cell, out ulong outCacheKey, out int outBit)
 {
     var offset = cell.CoordInLod % 4;
     cell.CoordInLod >>= 2;
     Debug.Assert(offset.IsInsideInclusive(Vector3I.Zero, new Vector3I(3)));
     outCacheKey = cell.PackId64();
     outBit = offset.X + 4 * (offset.Y + 4 * offset.Z);
     Debug.Assert((uint)outBit < 64u);
 }
Exemplo n.º 41
0
 public static void GeometryCellCoordToLocalPosition(ref MyCellCoord geometryCellCoord, out Vector3D localPosition)
 {
     localPosition = geometryCellCoord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES * (1 << geometryCellCoord.Lod);
 }
 private bool IsEmpty(ref MyCellCoord cell)
 {
     ulong cacheKey;
     int bitIdx;
     ComputeIsEmptyLookup(cell, out cacheKey, out bitIdx);
     var cacheLine = m_isEmptyCache.Read(cacheKey);
     return (cacheLine & ((ulong)1 << bitIdx)) != 0;
 }
Exemplo n.º 43
0
        private void RequestShapeBlockingInternal(int x, int y, int z, out HkBvCompressedMeshShape shape, out HkReferencePolicy refPolicy, bool lod1physics)
        {
            ProfilerShort.Begin("MyVoxelPhysicsBody.RequestShapeBlocking");

            if (!m_bodiesInitialized) CreateRigidBodies();

            int lod = lod1physics ? 1 : 0;
            var cellCoord = new MyCellCoord(lod, new Vector3I(x, y, z));
            shape = (HkBvCompressedMeshShape)HkShape.Empty;
            // shape must take ownership, otherwise shapes created here will leak, since I can't remove reference
            refPolicy = HkReferencePolicy.TakeOwnership;
            MyPrecalcComponent.QueueJobCancel(m_workTracker, cellCoord);

            if (m_voxelMap.MarkedForClose)
            {
                ProfilerShort.End();
                return;
            }
            if (MyDebugDrawSettings.DEBUG_DRAW_REQUEST_SHAPE_BLOCKING)
            {
                BoundingBoxD aabb;
                MyVoxelCoordSystems.GeometryCellCoordToWorldAABB(m_voxelMap.PositionLeftBottomCorner, ref cellCoord, out aabb);
                MyRenderProxy.DebugDrawAABB(aabb, lod1physics ? Color.Yellow : Color.Red, 1, 1, true);
            }
            ProfilerShort.Begin("Generating geometry");
            MyIsoMesh geometryData = CreateMesh(m_voxelMap.Storage, cellCoord);
            ProfilerShort.End();

            if (!MyIsoMesh.IsEmpty(geometryData))
            {
                ProfilerShort.Begin("Shape from geometry");
                shape = CreateShape(geometryData);
                m_needsShapeUpdate = true;
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
Exemplo n.º 44
0
            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);
                    }
                }
            }
Exemplo n.º 45
0
        internal MyIsoMesh CreateMesh(IMyStorage storage, MyCellCoord coord)
        {
            // mk:NOTE This method must be thread safe. Called from worker threads.

            coord.CoordInLod += m_cellsOffset >> coord.Lod;

            if (m_voxelMap is MyVoxelPhysics)
            {
                var clipmapId = ((MyVoxelPhysics)m_voxelMap).Parent.Render.RenderObjectIDs[0];
                var clipmapCellId = MyCellCoord.GetClipmapCellHash(clipmapId, coord.PackId64());
                var isoMesh = MyPrecalcJobRender.IsoMeshCache.Read(clipmapCellId);
                if (isoMesh != null)
                {
                    return isoMesh;
                }
            }

            var min = coord.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS;
            // overlap to neighbor; introduces extra data but it makes logic for raycasts and collisions simpler (no need to check neighbor cells)
            min -= 1;
            max += 2;
            return MyPrecalcComponent.IsoMesher.Precalc(storage, coord.Lod, min, max, false, false);
        }
        /// <param name="minVoxelChanged">Inclusive min.</param>
        /// <param name="maxVoxelChanged">Inclusive max.</param>
        private void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags changedData)
        {
            MyPrecalcComponent.AssertUpdateThread();

            ProfilerShort.Begin("MyVoxelGeometry.storage_RangeChanged");

            minChanged -= MyPrecalcComponent.InvalidatedRangeInflate;
            maxChanged += MyPrecalcComponent.InvalidatedRangeInflate;
            m_storage.ClampVoxelCoord(ref minChanged);
            m_storage.ClampVoxelCoord(ref maxChanged);
            var minCellChanged = minChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            var maxCellChanged = maxChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            using (m_lock.AcquireExclusiveUsing())
            {
                if (minCellChanged == Vector3I.Zero && maxCellChanged == m_cellsCount - 1)
                {
                    m_cellsByCoordinate.Clear();
                    m_coordinateToMesh.Clear();
                    m_isEmptyCache.Reset();
                }
                else
                {
                    MyCellCoord cell = new MyCellCoord();
                    cell.CoordInLod = minCellChanged;
                    for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        var key = cell.PackId64();
                        m_cellsByCoordinate.Remove(key);
                        m_coordinateToMesh.Remove(key);
                        SetEmpty(ref cell, false);
                    }
                }
            }

            ProfilerShort.End();
        }