private void FixCubeFace(ref Vector3I pos, ref Vector3I dir) { if (this.m_cubeSet.Contains(ref pos)) { MySlimBlock cubeBlock = this.m_grid.GetCubeBlock(pos); MyCompoundCubeBlock fatBlock = cubeBlock.FatBlock as MyCompoundCubeBlock; if (fatBlock != null) { ListReader <MySlimBlock> blocks = fatBlock.GetBlocks(); MySlimBlock block3 = null; foreach (MySlimBlock block4 in blocks) { if (block4.BlockDefinition.NavigationDefinition != null) { block3 = block4; break; } } if (block3 != null) { cubeBlock = block3; } } if (cubeBlock.BlockDefinition.NavigationDefinition != null) { MatrixI xi2; Vector3I vectori; Vector3I vectori2; List <int> list; MatrixI matrix = new MatrixI(cubeBlock.Position, cubeBlock.Orientation.Forward, cubeBlock.Orientation.Up); MatrixI.Invert(ref matrix, out xi2); Vector3I.Transform(ref pos, ref xi2, out vectori); Vector3I.TransformNormal(ref dir, ref xi2, out vectori2); MyGridNavigationMesh mesh = cubeBlock.BlockDefinition.NavigationDefinition.Mesh; if ((mesh != null) && mesh.m_smallTriangleRegistry.TryGetValue(vectori, out list)) { foreach (int num in list) { MyNavigationTriangle triangle = mesh.GetTriangle(num); if (this.IsFaceTriangle(triangle, vectori, vectori2)) { this.CopyTriangle(triangle, vectori, ref matrix); } } } } } }
private void MergeFromAnotherMesh(MyGridNavigationMesh otherMesh, ref MatrixI transform) { ProfilerShort.Begin("MergeFromAnotherMesh"); m_mergeHelper.Clear(); // Save the cubes from the other mesh that are touching cubes of this mesh into a helper set. // Also put the touched cubes from this mesh into the set. foreach (var position in otherMesh.m_smallTriangleRegistry.Keys) { bool add = false; foreach (var direction in Base6Directions.IntDirections) { // CH: TODO: We query the grid so far, but in the future, we should make sure that the access is thread-safe Vector3I pos = Vector3I.Transform(position + direction, transform); if (m_cubeSet.Contains(ref pos)) // Test the transformed position... { m_mergeHelper.Add(position + direction); // ... but add the original one add = true; } } if (add) { m_mergeHelper.Add(position); } } foreach (var entry in otherMesh.m_smallTriangleRegistry) { Vector3I originalCube = entry.Key; Vector3I tformedCube; Vector3I.Transform(ref originalCube, ref transform, out tformedCube); // If the cube is one of the touching cubes, we have to intersect the touching triangles if (m_mergeHelper.Contains(originalCube)) { // Take the touching pairs one by one and calculate triangulation of the disjoint union of the opposing faces // Remove the opposing faces from the old block // Add the triangulation to the mesh // Add the rest of the navmesh from this block to the mesh m_tmpTriangleList.Clear(); // CH: TODO. Just remove the triangles now foreach (var direction in Base6Directions.EnumDirections) { Vector3I directionVec = Base6Directions.GetIntVector((int)direction); Base6Directions.Direction tformedDirection = transform.GetDirection(direction); Vector3I tformedFlippedVec = Base6Directions.GetIntVector((int)Base6Directions.GetFlippedDirection(tformedDirection)); // Remove face triangles from this mesh if (m_mergeHelper.Contains(originalCube + directionVec)) { List <int> triList = null; if (m_smallTriangleRegistry.TryGetValue(tformedCube - tformedFlippedVec, out triList)) { foreach (var index in triList) { var triangle = GetTriangle(index); // CH: TODO: This will probably be expensive. Could we precalculate it? if (IsFaceTriangle(triangle, tformedCube - tformedFlippedVec, tformedFlippedVec)) { m_tmpTriangleList.Add(new KeyValuePair <MyNavigationTriangle, Vector3I>(triangle, tformedCube - tformedFlippedVec)); } } } } } foreach (var triangle in m_tmpTriangleList) { RemoveTriangle(triangle.Key, triangle.Value); } m_tmpTriangleList.Clear(); int debugCounter = 0; // CH: TODO: optimize this (actually whole this method) foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); Vector3I pos = entry.Key; bool addTriangle = true; foreach (var direction in Base6Directions.EnumDirections) { Vector3I dirvec = Base6Directions.GetIntVector((int)direction); if (m_mergeHelper.Contains(pos + dirvec) && IsFaceTriangle(triangle, pos, dirvec)) { addTriangle = false; break; } } if (addTriangle) { if (debugCounter == 5) { } CopyTriangle(triangle, pos, ref transform); debugCounter++; } } } // Otherwise, we just transform the triangles from the other mesh and add them to this mesh else { foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); CopyTriangle(triangle, entry.Key, ref transform); //if (triangleIndex > 1) break; } } } m_mergeHelper.Clear(); 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) { 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(); }
private void MergeFromAnotherMesh(MyGridNavigationMesh otherMesh, ref MatrixI transform) { int num; m_mergeHelper.Clear(); foreach (Vector3I vectori in otherMesh.m_smallTriangleRegistry.Keys) { bool flag = false; Vector3I[] intDirections = Base6Directions.IntDirections; num = 0; while (true) { if (num >= intDirections.Length) { if (flag) { m_mergeHelper.Add(vectori); } break; } Vector3I vectori2 = intDirections[num]; Vector3I position = Vector3I.Transform((Vector3I)(vectori + vectori2), (MatrixI)transform); if (this.m_cubeSet.Contains(ref position)) { m_mergeHelper.Add(vectori + vectori2); flag = true; } num++; } } using (Dictionary <Vector3I, List <int> > .Enumerator enumerator2 = otherMesh.m_smallTriangleRegistry.GetEnumerator()) { while (true) { while (true) { if (enumerator2.MoveNext()) { Vector3I vectori5; KeyValuePair <Vector3I, List <int> > current = enumerator2.Current; Vector3I key = current.Key; Vector3I.Transform(ref key, ref transform, out vectori5); if (m_mergeHelper.Contains(key)) { m_tmpTriangleList.Clear(); Base6Directions.Direction[] enumDirections = Base6Directions.EnumDirections; num = 0; while (true) { if (num < enumDirections.Length) { Base6Directions.Direction direction = enumDirections[num]; Vector3I intVector = Base6Directions.GetIntVector((int)direction); Vector3I vectori7 = Base6Directions.GetIntVector((int)Base6Directions.GetFlippedDirection(transform.GetDirection(direction))); if (m_mergeHelper.Contains(key + intVector)) { List <int> list = null; if (this.m_smallTriangleRegistry.TryGetValue(vectori5 - vectori7, out list)) { foreach (int num3 in list) { MyNavigationTriangle triangle = base.GetTriangle(num3); if (this.IsFaceTriangle(triangle, vectori5 - vectori7, vectori7)) { m_tmpTriangleList.Add(new KeyValuePair <MyNavigationTriangle, Vector3I>(triangle, vectori5 - vectori7)); } } } } num++; continue; } foreach (KeyValuePair <MyNavigationTriangle, Vector3I> pair2 in m_tmpTriangleList) { this.RemoveTriangle(pair2.Key, pair2.Value); } m_tmpTriangleList.Clear(); int num2 = 0; foreach (int num4 in current.Value) { MyNavigationTriangle triangle = otherMesh.GetTriangle(num4); Vector3I cubePosition = current.Key; bool flag2 = true; enumDirections = Base6Directions.EnumDirections; num = 0; while (true) { if (num < enumDirections.Length) { Vector3I intVector = Base6Directions.GetIntVector((int)enumDirections[num]); if (!m_mergeHelper.Contains(cubePosition + intVector) || !this.IsFaceTriangle(triangle, cubePosition, intVector)) { num++; continue; } flag2 = false; } if (flag2) { int num6 = num2; this.CopyTriangle(triangle, cubePosition, ref transform); num2++; } break; } } } } foreach (int num5 in current.Value) { MyNavigationTriangle triangle = otherMesh.GetTriangle(num5); this.CopyTriangle(triangle, current.Key, ref transform); } } else { goto TR_0000; } } } } TR_0000: m_mergeHelper.Clear(); }
private void MergeFromAnotherMesh(MyGridNavigationMesh otherMesh, ref MatrixI transform) { ProfilerShort.Begin("MergeFromAnotherMesh"); m_mergeHelper.Clear(); // Save the cubes from the other mesh that are touching cubes of this mesh into a helper set. // Also put the touched cubes from this mesh into the set. foreach (var position in otherMesh.m_smallTriangleRegistry.Keys) { bool add = false; foreach (var direction in Base6Directions.IntDirections) { // CH: TODO: We query the grid so far, but in the future, we should make sure that the access is thread-safe Vector3I pos = Vector3I.Transform(position + direction, transform); if (m_cubeSet.Contains(ref pos)) // Test the transformed position... { m_mergeHelper.Add(position + direction); // ... but add the original one add = true; } } if (add) m_mergeHelper.Add(position); } foreach (var entry in otherMesh.m_smallTriangleRegistry) { Vector3I originalCube = entry.Key; Vector3I tformedCube; Vector3I.Transform(ref originalCube, ref transform, out tformedCube); // If the cube is one of the touching cubes, we have to intersect the touching triangles if (m_mergeHelper.Contains(originalCube)) { // Take the touching pairs one by one and calculate triangulation of the disjoint union of the opposing faces // Remove the opposing faces from the old block // Add the triangulation to the mesh // Add the rest of the navmesh from this block to the mesh m_tmpTriangleList.Clear(); // CH: TODO. Just remove the triangles now foreach (var direction in Base6Directions.EnumDirections) { Vector3I directionVec = Base6Directions.GetIntVector((int)direction); Base6Directions.Direction tformedDirection = transform.GetDirection(direction); Vector3I tformedFlippedVec = Base6Directions.GetIntVector((int)Base6Directions.GetFlippedDirection(tformedDirection)); // Remove face triangles from this mesh if (m_mergeHelper.Contains(originalCube + directionVec)) { List<int> triList = null; if (m_smallTriangleRegistry.TryGetValue(tformedCube - tformedFlippedVec, out triList)) { foreach (var index in triList) { var triangle = GetTriangle(index); // CH: TODO: This will probably be expensive. Could we precalculate it? if (IsFaceTriangle(triangle, tformedCube - tformedFlippedVec, tformedFlippedVec)) m_tmpTriangleList.Add(new KeyValuePair<MyNavigationTriangle, Vector3I>(triangle, tformedCube - tformedFlippedVec)); } } } } foreach (var triangle in m_tmpTriangleList) { RemoveTriangle(triangle.Key, triangle.Value); } m_tmpTriangleList.Clear(); int debugCounter = 0; // CH: TODO: optimize this (actually whole this method) foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); Vector3I pos = entry.Key; bool addTriangle = true; foreach (var direction in Base6Directions.EnumDirections) { Vector3I dirvec = Base6Directions.GetIntVector((int)direction); if (m_mergeHelper.Contains(pos + dirvec) && IsFaceTriangle(triangle, pos, dirvec)) { addTriangle = false; break; } } if (addTriangle) { if (debugCounter == 5) { } CopyTriangle(triangle, pos, ref transform); debugCounter++; } } } // Otherwise, we just transform the triangles from the other mesh and add them to this mesh else { foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); CopyTriangle(triangle, entry.Key, ref transform); //if (triangleIndex > 1) break; } } } m_mergeHelper.Clear(); ProfilerShort.End(); }