예제 #1
0
 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();
        }
예제 #3
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();
        }
예제 #5
0
        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();
        }
예제 #6
0
        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();
        }