private MyNavmeshComponents.ClosedCellInfo ConstructComponents()
        {
            ProfilerShort.Begin("ConstructComponents");

            long timeBegin = m_mesh.GetCurrentTimestamp() + 1;
            long timeEnd   = timeBegin;

            m_currentComponentRel = 0;
            m_navmeshComponents.OpenCell(m_packedCoord);

            m_tmpComponentTriangles.Clear();
            foreach (var triIndex in m_triangleList)
            {
                // The marker is used as a fake component index in triangles to mark visited triangles.
                // Negative numbers from -2 down are used to avoid collisions with existing component numbers (0, 1, 2, ...) or the special value -1
                m_currentComponentMarker = -2 - m_currentComponentRel;

                // Skip already visited triangles
                var triangle = m_mesh.GetTriangle(triIndex);
                if (m_mesh.VisitedBetween(triangle, timeBegin, timeEnd))
                {
                    continue;
                }

                m_navmeshComponents.OpenComponent();

                // Make sure we have place in m_currentCellConnections
                if (m_currentComponentRel >= m_currentCellConnections.Count)
                {
                    m_currentCellConnections.Add(new List <ConnectionInfo>());
                }

                // Find connected component from an unvisited triangle
                ProfilerShort.Begin("Graph traversal");
                m_currentHelper = this;

                m_navmeshComponents.AddComponentTriangle(triangle, triangle.Center);
                triangle.ComponentIndex = m_currentComponentMarker;
                m_tmpComponentTriangles.Add(triangle);

                m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);
                m_mesh.PerformTraversal();
                ProfilerShort.End();

                m_tmpComponentTriangles.Add(null); // Mark end of component in m_tmpComponentTriangles
                m_navmeshComponents.CloseComponent();

                timeEnd = m_mesh.GetCurrentTimestamp();
                m_currentComponentRel++;
            }

            MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo();
            m_navmeshComponents.CloseAndCacheCell(ref cellInfo);

            ProfilerShort.End();
            return(cellInfo);
        }
Beispiel #2
0
        public void ProcessCellComponents()
        {
            ProfilerShort.Begin("ProcessCellComponents");
            m_triangleLists.Add(m_packedCoord, m_triangleList.GetCopy());

            long timeBegin = m_mesh.GetCurrentTimestamp() + 1;
            long timeEnd   = timeBegin;

            m_currentComponentRel = 0;
            m_currentComponent    = m_navmeshComponents.OpenCell(m_packedCoord);

            foreach (var triIndex in m_triangleList)
            {
                // Skip already visited triangles
                var triangle = m_mesh.GetTriangle(triIndex);
                if (m_mesh.VisitedBetween(triangle, timeBegin, timeEnd))
                {
                    continue;
                }

                m_navmeshComponents.OpenComponent();

                // Make sure we have place in m_currentCellConnections
                if (m_currentComponentRel >= m_currentCellConnections.Count)
                {
                    m_currentCellConnections.Add(new List <ConnectionInfo>());
                }

                // Find connected component from an unvisited triangle
                ProfilerShort.Begin("Graph traversal");
                m_currentHelper = this;

                m_navmeshComponents.AddComponentTriangle(triangle, triangle.Center);
                triangle.ComponentIndex = m_navmeshComponents.OpenComponentIndex;
                m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);

                var primitiveEnum = m_mesh.GetEnumerator();
                while (primitiveEnum.MoveNext())
                {
                    ;
                }
                primitiveEnum.Dispose();
                ProfilerShort.End();

                m_navmeshComponents.CloseComponent();

                timeEnd = m_mesh.GetCurrentTimestamp();
                m_currentComponentRel++;
            }

            MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo();
            m_navmeshComponents.CloseAndCacheCell(ref cellInfo);

            // Add new component primitives
            if (cellInfo.NewCell)
            {
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    m_mesh.HighLevelGroup.AddPrimitive(cellInfo.StartingIndex + i, m_navmeshComponents.GetComponentCenter(i));
                }
            }

            // Connect new components with the others in the neighboring cells
            for (int i = 0; i < cellInfo.ComponentNum; ++i)
            {
                foreach (var connectionInfo in m_currentCellConnections[i])
                {
                    if (!cellInfo.ExploredDirections.HasFlag(Base6Directions.GetDirectionFlag(connectionInfo.Direction)))
                    {
                        m_mesh.HighLevelGroup.ConnectPrimitives(cellInfo.StartingIndex + i, connectionInfo.ComponentIndex);
                    }
                }
                m_currentCellConnections[i].Clear();
            }

            // Mark explored directions in the navmesh component helper
            foreach (var direction in Base6Directions.EnumDirections)
            {
                var dirFlag = Base6Directions.GetDirectionFlag(direction);
                if (cellInfo.ExploredDirections.HasFlag(dirFlag))
                {
                    continue;
                }

                Vector3I dirVec = Base6Directions.GetIntVector(direction);

                MyCellCoord otherCoord = new MyCellCoord();
                otherCoord.Lod        = MyVoxelNavigationMesh.NAVMESH_LOD;
                otherCoord.CoordInLod = m_currentCell + dirVec;
                if (otherCoord.CoordInLod.X == -1 || otherCoord.CoordInLod.Y == -1 || otherCoord.CoordInLod.Z == -1)
                {
                    continue;
                }

                ulong otherPackedCoord = otherCoord.PackId64();

                if (m_triangleLists.ContainsKey(otherPackedCoord))
                {
                    m_navmeshComponents.MarkExplored(otherPackedCoord, Base6Directions.GetFlippedDirection(direction));
                    cellInfo.ExploredDirections |= Base6Directions.GetDirectionFlag(direction);
                }
            }
            m_navmeshComponents.SetExplored(m_packedCoord, cellInfo.ExploredDirections);

            // Set all the components as expanded
            for (int i = 0; i < cellInfo.ComponentNum; ++i)
            {
                int componentIndex = cellInfo.StartingIndex + i;
                var component      = m_mesh.HighLevelGroup.GetPrimitive(componentIndex);
                if (component != null)
                {
                    component.IsExpanded = true;
                }
            }

            ProfilerShort.End();
        }