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); }
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(); }