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 ProcessChangedCellComponents()
        {
            ProfilerShort.Begin("ProcessChangedCellComponents");

            m_currentHelper = this;

            Vector3I   min, max, pos;
            List <int> triangles = null;

            foreach (var cell in m_changedCells)
            {
                min = CellToLowestCube(cell);
                max = min + m_cellSize - Vector3I.One;

                // Save a hashset of all the triangles in the current cell
                pos = min;
                for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                {
                    if (!m_triangleRegistry.TryGetValue(pos, out triangles))
                    {
                        continue;
                    }

                    foreach (var triIndex in triangles)
                    {
                        m_tmpCellTriangles.Add(triIndex);
                    }
                }

                if (m_tmpCellTriangles.Count == 0)
                {
                    continue;
                }

                MyCellCoord cellCoord  = new MyCellCoord(0, cell);
                ulong       packedCell = cellCoord.PackId64();
                m_components.OpenCell(packedCell);

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

                m_tmpComponentTriangles.Clear();
                foreach (var triIndex in m_tmpCellTriangles)
                {
                    // Skip already visited triangles
                    var triangle = m_mesh.GetTriangle(triIndex);
                    if (m_currentComponentRel != 0 && m_mesh.VisitedBetween(triangle, timeBegin, timeEnd))
                    {
                        continue;
                    }

                    m_components.OpenComponent();

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

                    // Find connected component from an unvisited triangle and mark its connections
                    m_components.AddComponentTriangle(triangle, triangle.Center);
                    triangle.ComponentIndex = m_currentComponentRel;
                    m_tmpComponentTriangles.Add(triangle);
                    m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);
                    m_mesh.PerformTraversal();
                    m_tmpComponentTriangles.Add(null);

                    m_components.CloseComponent();

                    timeEnd = m_mesh.GetCurrentTimestamp();
                    if (m_currentComponentRel == 0)
                    {
                        timeBegin = timeEnd;
                    }
                    m_currentComponentRel++;
                }

                m_tmpCellTriangles.Clear();

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

                // Renumber triangles from the old indices to the newly assigned index from m_components
                int componentIndex = cellInfo.StartingIndex;
                foreach (var triangle in m_tmpComponentTriangles)
                {
                    if (triangle == null)
                    {
                        componentIndex++;
                        continue;
                    }
                    triangle.ComponentIndex = componentIndex;
                }
                m_tmpComponentTriangles.Clear();

                // Remove old component primitives
                if (!cellInfo.NewCell && cellInfo.ComponentNum != cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.OldComponentNum; ++i)
                    {
                        m_mesh.HighLevelGroup.RemovePrimitive(cellInfo.OldStartingIndex + i);
                    }
                }

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

                // Update existing component primitives
                if (!cellInfo.NewCell && cellInfo.ComponentNum == cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.ComponentNum; ++i)
                    {
                        var primitive = m_mesh.HighLevelGroup.GetPrimitive(cellInfo.StartingIndex + i);
                        primitive.UpdatePosition(m_components.GetComponentCenter(i));
                    }
                }

                // Connect new components with the others in the neighboring cells
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    int compIndex = cellInfo.StartingIndex + i;

                    var primitive = m_mesh.HighLevelGroup.GetPrimitive(compIndex);
                    primitive.GetNeighbours(m_tmpNeighbors);

                    // Connect to disconnected components
                    foreach (var connection in m_currentCellConnections[i])
                    {
                        if (!m_tmpNeighbors.Remove(connection))
                        {
                            m_mesh.HighLevelGroup.ConnectPrimitives(compIndex, connection);
                        }
                    }

                    // Disconnect neighbors that should be no longer connected
                    foreach (var neighbor in m_tmpNeighbors)
                    {
                        // Only disconnect from the other cell if it is expanded and there was no connection found
                        var neighborPrimitive = m_mesh.HighLevelGroup.TryGetPrimitive(neighbor);
                        if (neighborPrimitive != null && neighborPrimitive.IsExpanded)
                        {
                            m_mesh.HighLevelGroup.DisconnectPrimitives(compIndex, neighbor);
                        }
                    }

                    m_tmpNeighbors.Clear();
                    m_currentCellConnections[i].Clear();
                }

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

            m_changedCells.Clear();

            m_currentHelper = null;

            ProfilerShort.End();
        }
        public void ProcessChangedCellComponents()
        {
            ProfilerShort.Begin("ProcessChangedCellComponents");

            m_currentHelper = this;

            Vector3I   min, max, pos;
            List <int> triangles = null;

            foreach (var cell in m_changedCells)
            {
                MyCellCoord cellCoord  = new MyCellCoord(0, cell);
                ulong       packedCell = cellCoord.PackId64();

                m_components.OpenCell(packedCell);

                min = CellToLowestCube(cell);
                max = min + m_cellSize - Vector3I.One;

                // Save a hashset of all the triangles in the current cell
                pos = min;
                for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                {
                    if (!m_triangleRegistry.TryGetValue(pos, out triangles))
                    {
                        continue;
                    }

                    foreach (var triIndex in triangles)
                    {
                        m_tmpCellTriangles.Add(triIndex);
                    }
                }

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

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

                    m_components.OpenComponent();

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

                    // Find connected component from an unvisited triangle and mark its connections
                    m_components.AddComponentTriangle(triangle, triangle.Center);
                    triangle.ComponentIndex = m_components.OpenComponentIndex;
                    m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);

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

                    m_components.CloseComponent();

                    timeEnd = m_mesh.GetCurrentTimestamp();
                    if (m_currentComponentRel == 0)
                    {
                        timeBegin = timeEnd;
                    }
                    m_currentComponentRel++;
                }

                m_tmpCellTriangles.Clear();

                MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo();
                m_components.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_components.GetComponentCenter(i));
                    }
                }

                // Connect new components with the others in the neighboring cells
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    foreach (var otherComponent in m_currentCellConnections[i])
                    {
                        m_mesh.HighLevelGroup.ConnectPrimitives(cellInfo.StartingIndex + i, otherComponent);
                    }
                    m_currentCellConnections[i].Clear();
                }

                // 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;
                    }
                }
            }

            m_changedCells.Clear();

            m_currentHelper = null;

            ProfilerShort.End();
        }
Beispiel #4
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();
        }