////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public override void LoadData()
        {
            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("MyVoxelCacheRender.LoadData");

            MySandboxGame.Log.WriteLine("MyVoxelCacheRender.LoadData() - START");
            MySandboxGame.Log.IncreaseIndent();

            m_capacity                = MyVoxelConstants.RENDER_CELL_CACHE_SIZE;
            m_cellsByCoordinate       = new Dictionary <Int64, LinkedListNode <MyVoxelCacheCellRender> >(m_capacity);
            m_priority                = new LinkedList <MyVoxelCacheCellRender>();
            m_priorityArray           = new LinkedListNode <MyVoxelCacheCellRender> [m_capacity];
            m_cellsPreallocated       = new MyVoxelCacheCellRender[m_capacity];
            m_helperLodCachedDataCell = new MyVoxelGeometry.CellData();
            m_dataCellsQueue          = new List <MyVoxelGeometry.CellData>(MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS_TOTAL);
            for (int i = 0; i < m_capacity; i++)
            {
                m_cellsPreallocated[i] = new MyVoxelCacheCellRender();
                m_priorityArray[i]     = new LinkedListNode <MyVoxelCacheCellRender>(m_cellsPreallocated[i]);
                m_priority.AddLast(m_priorityArray[i]);
            }
            MySandboxGame.Log.DecreaseIndent();
            MySandboxGame.Log.WriteLine("MyVoxelCacheRender.LoadData() - END");
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

            LoadCache();
        }
Example #2
0
 public MyVoxelPrecalcTaskItem(MyLodTypeEnum type, MyVoxelMap voxelMap, MyVoxelGeometry.CellData cache, Vector3I voxelStart)
 {
     Type       = type;
     VoxelMap   = voxelMap;
     Cache      = cache;
     VoxelStart = voxelStart;
 }
Example #3
0
        public static void AddToQueue(
            MyLodTypeEnum type,
            MyVoxelMap voxelMap,
            MyVoxelGeometry.CellData cache,
            int voxelStartX, int voxelStartY, int voxelStartZ)
        {
            Debug.Assert(Thread.CurrentThread == MySandboxGame.Static.UpdateThread, "Only update thread should queue voxel precalc.");
            MyVoxelPrecalcTaskItem a = new MyVoxelPrecalcTaskItem(type, voxelMap, cache, new Vector3I(voxelStartX, voxelStartY, voxelStartZ));

            Tasks.Enqueue(a);
        }
        protected override void UnloadData()
        {
            UnloadCache();

            m_cellsPreallocated = null;
            m_priority          = null;
            m_priorityArray     = null;
            if (m_dataCellsQueue != null)
            {
                m_dataCellsQueue.Clear();
            }
            m_helperLodCachedDataCell = null;
        }
        private bool AddCell(Vector3I cellPos)
        {
            MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cellPos);

            var geometry = m_voxelMap.Storage.Geometry;

            MyVoxelGeometry.CellData data = geometry.GetCell(ref coord);
            if (data == 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(data.VoxelVerticesCount);

            // 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 < data.VoxelTrianglesCount; i++)
            {
                short a = data.VoxelTriangles[i].VertexIndex0;
                short b = data.VoxelTriangles[i].VertexIndex1;
                short c = data.VoxelTriangles[i].VertexIndex2;

                Vector3 aPos, bPos, cPos;
                Vector3 vert;
                data.GetUnpackedPosition(a, out vert);
                aPos = vert - centerDisplacement;
                data.GetUnpackedPosition(b, out vert);
                bPos = vert - centerDisplacement;
                data.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 < data.VoxelTrianglesCount; i++)
            {
                short a    = data.VoxelTriangles[i].VertexIndex0;
                short b    = data.VoxelTriangles[i].VertexIndex1;
                short c    = data.VoxelTriangles[i].VertexIndex2;
                short setA = (short)m_vertexMapping.Find(a);
                short setB = (short)m_vertexMapping.Find(b);
                short setC = (short)m_vertexMapping.Find(c);

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

                Vector3 aPos, bPos, cPos;
                Vector3 vert;
                data.GetUnpackedPosition(setA, out vert);
                aPos = vert - centerDisplacement;
                data.GetUnpackedPosition(setB, out vert);
                bPos = vert - centerDisplacement;
                data.GetUnpackedPosition(setC, out vert);
                cPos = vert - centerDisplacement;

                if (MyFakes.NAVMESH_PRESUMES_DOWNWARD_GRAVITY)
                {
                    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);
        }
        private static MyVoxelCacheCellRender LoadCell(MyVoxelMap voxelMap, ref Vector3I renderCellCoord, MyLodTypeEnum cellHashType)
        {
            Profiler.Begin("AddCell");

            MyVoxelCacheCellRender ret = AddCell(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType);

            ret.Begin(voxelMap, ref renderCellCoord);
            ret.CellHashType = cellHashType;

            Profiler.End();

            if (cellHashType == MyLodTypeEnum.LOD0)
            {
                Profiler.Begin("LOD0 - queue cells");
                m_dataCellsQueue.Clear();

                //  Create normal (LOD0) version
                for (int dataX = 0; dataX < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataX++)
                {
                    for (int dataY = 0; dataY < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataY++)
                    {
                        for (int dataZ = 0; dataZ < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataZ++)
                        {
                            //  Don't precalculate this cells now. Store it in queue and calculate all cells at once by MyVoxelPrecalc.PrecalcQueue()
                            Vector3I dataCellCoord =
                                new Vector3I(
                                    renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataX,
                                    renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataY,
                                    renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataZ);
                            MyVoxelGeometry.CellData cachedDataCell = voxelMap.Geometry.GetCellLater(MyLodTypeEnum.LOD0, ref dataCellCoord);
                            if (cachedDataCell != null)
                            {
                                m_dataCellsQueue.Add(cachedDataCell);
                            }
                        }
                    }
                }

                Profiler.BeginNextBlock("LOD0 - PrecalcQueue");

                //  Precalculate all queued data cells in parallel threads - using multiple cores if possible.
                MyVoxelPrecalc.PrecalcQueue();

                Profiler.BeginNextBlock("LOD0 - AddTriangles");
                ret.AddTriangles(m_dataCellsQueue);
                Profiler.End();
            }
            else if (cellHashType == MyLodTypeEnum.LOD1)
            {
                Profiler.Begin("LOD1 - PrecalcImmediatelly");

                m_helperLodCachedDataCell.Reset();

                //  Create LOD1 render cell
                MyVoxelPrecalc.PrecalcImmediatelly(
                    new MyVoxelPrecalcTaskItem(
                        MyLodTypeEnum.LOD1,
                        voxelMap,
                        m_helperLodCachedDataCell,
                        new Vector3I(
                            renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS,
                            renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS,
                            renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS)));


                Profiler.BeginNextBlock("LOD1 - AddTriangles");
                m_dataCellsQueue.Clear();
                m_dataCellsQueue.Add(m_helperLodCachedDataCell);
                ret.AddTriangles(m_dataCellsQueue);
                Profiler.End();
            }
            else
            {
                throw new InvalidBranchException();
            }

            ret.End();

            return(ret);
        }