Пример #1
0
        public MyGridHighLevelHelper(MyGridNavigationMesh mesh, Dictionary <Vector3I, List <int> > triangleRegistry, Vector3I cellSize)
        {
            m_mesh                   = mesh;
            m_cellSize               = cellSize;
            m_packedCoord            = 0;
            m_currentCellConnections = new List <List <int> >();

            m_changedCells = new MyVector3ISet();
            m_changedCubes = new MyVector3ISet();

            m_triangleRegistry = triangleRegistry;
            m_components       = new MyNavmeshComponents();
        }
        public MyGridHighLevelHelper(MyGridNavigationMesh mesh, Dictionary<Vector3I, List<int>> triangleRegistry, Vector3I cellSize)
        {
            m_mesh = mesh;
            m_cellSize = cellSize;
            m_packedCoord = 0;
            m_currentCellConnections = new List<List<int>>();

            m_changedCells = new MyVector3ISet();
            m_changedCubes = new MyVector3ISet();

            m_triangleRegistry = triangleRegistry;
            m_components = new MyNavmeshComponents();
        }
Пример #3
0
 public void Update()
 {
     if (this.m_highLevelNavigationDirty)
     {
         foreach (KeyValuePair <MyCubeGrid, MyGridNavigationMesh> pair in this.m_navigationMeshes)
         {
             MyGridNavigationMesh mesh = pair.Value;
             if (mesh.HighLevelDirty)
             {
                 mesh.UpdateHighLevel();
             }
         }
         this.m_highLevelNavigationDirty = false;
     }
 }
Пример #4
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);
                     }
                 }
             }
         }
     }
 }
Пример #5
0
        public List <Vector4D> FindPathGlobal(MyCubeGrid startGrid, MyCubeGrid endGrid, ref Vector3D start, ref Vector3D end)
        {
            Debug.Assert(startGrid == endGrid, "Pathfinding between different grids not implemented yet!");
            if (startGrid != endGrid)
            {
                return(null);
            }

            Vector3D tformedStart = Vector3D.Transform(start, startGrid.PositionComp.WorldMatrixInvScaled);
            Vector3D tformedEnd   = Vector3D.Transform(end, endGrid.PositionComp.WorldMatrixInvScaled);

            MyGridNavigationMesh mesh = null;

            if (m_navigationMeshes.TryGetValue(startGrid, out mesh))
            {
                return(mesh.FindPath(tformedStart, tformedEnd));
            }

            return(null);
        }
Пример #6
0
        public void RemoveGridNavmeshLinks(MyCubeGrid grid)
        {
            MyGridNavigationMesh navmesh = this.m_gridPathfinding.GetNavmesh(grid);

            if (navmesh != null)
            {
                m_tmpNavPrims.Clear();
                MyVector3ISet.Enumerator cubes = navmesh.GetCubes();
                while (cubes.MoveNext())
                {
                    int num;
                    MyGridPathfinding.CubeId key = new MyGridPathfinding.CubeId {
                        Grid   = grid,
                        Coords = cubes.Current
                    };
                    if (this.m_gridLinkCounter.TryGetValue(key, out num))
                    {
                        m_tmpNavTris.Clear();
                        navmesh.GetCubeTriangles(cubes.Current, m_tmpNavTris);
                        foreach (MyNavigationTriangle triangle in m_tmpNavTris)
                        {
                            this.m_links.RemoveAllLinks(triangle);
                            MyHighLevelPrimitive highLevelPrimitive = triangle.GetHighLevelPrimitive();
                            if (!m_tmpNavPrims.Contains(highLevelPrimitive))
                            {
                                m_tmpNavPrims.Add(highLevelPrimitive);
                            }
                        }
                        m_tmpNavTris.Clear();
                        this.m_gridLinkCounter.Remove(key);
                    }
                }
                cubes.Dispose();
                foreach (MyNavigationPrimitive primitive2 in m_tmpNavPrims)
                {
                    this.m_highLevelLinks.RemoveAllLinks(primitive2);
                }
                m_tmpNavPrims.Clear();
            }
        }
Пример #7
0
        public void Update()
        {
            if (m_highLevelNavigationDirty)
            {
                ProfilerShort.Begin("MyGridPathfinding.Update");

                foreach (var entry in m_navigationMeshes)
                {
                    MyGridNavigationMesh navMesh = entry.Value;
                    if (!navMesh.HighLevelDirty)
                    {
                        continue;
                    }

                    navMesh.UpdateHighLevel();
                }

                m_highLevelNavigationDirty = false;

                ProfilerShort.End();
            }
        }
Пример #8
0
 public MyBlockNavigationDefinition()
 {
     m_mesh  = null;
     NoEntry = false;
 }
 public Component(MyGridNavigationMesh parent, int componentIndex)
 {
     m_parent         = parent;
     m_componentIndex = componentIndex;
 }
        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 MyBlockNavigationDefinition()
 {
     m_mesh = null;
     NoEntry = false;
 }
        protected override void Init(MyObjectBuilder_DefinitionBase ob)
        {
            base.Init(ob);

            var objectBuilder = ob as MyObjectBuilder_BlockNavigationDefinition;
            Debug.Assert(ob != null);
            if (ob == null) return;

            if (objectBuilder.NoEntry || objectBuilder.Triangles == null)
            {
                NoEntry = true;
            }
            else
            {
                NoEntry = false;
                var newMesh = new MyGridNavigationMesh(null, null, objectBuilder.Triangles.Length);

                Vector3I maxPos = objectBuilder.Size - Vector3I.One - objectBuilder.Center;
                Vector3I minPos = - (Vector3I)(objectBuilder.Center);

                foreach (var triOb in objectBuilder.Triangles)
                {
                    Vector3 pa = (Vector3)triOb.Points[0];
                    Vector3 pb = (Vector3)triOb.Points[1];
                    Vector3 pc = (Vector3)triOb.Points[2];

                    var tri = newMesh.AddTriangle(ref pa, ref pb, ref pc);

                    var center = (pa + pb + pc) / 3.0f;

                    // We want to move the triangle vertices more towards the triangle center to ensure correct calculation of containing cube
                    Vector3 cvA = (center - pa) * 0.0001f;
                    Vector3 cvB = (center - pb) * 0.0001f;
                    Vector3 cvC = (center - pc) * 0.0001f;
                    Vector3I gridPosA = Vector3I.Round(pa + cvA);
                    Vector3I gridPosB = Vector3I.Round(pb + cvB);
                    Vector3I gridPosC = Vector3I.Round(pc + cvC);
                    Vector3I.Clamp(ref gridPosA, ref minPos, ref maxPos, out gridPosA);
                    Vector3I.Clamp(ref gridPosB, ref minPos, ref maxPos, out gridPosB);
                    Vector3I.Clamp(ref gridPosC, ref minPos, ref maxPos, out gridPosC);
                    Vector3I min, max;
                    Vector3I.Min(ref gridPosA, ref gridPosB, out min);
                    Vector3I.Min(ref min, ref gridPosC, out min);
                    Vector3I.Max(ref gridPosA, ref gridPosB, out max);
                    Vector3I.Max(ref max, ref gridPosC, out max);

                    Vector3I pos = min;
                    for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                    {
                        newMesh.RegisterTriangle(tri, ref pos);
                    }
                }

                m_mesh = newMesh;
            }
        }
Пример #13
0
        protected override unsafe void Init(MyObjectBuilder_DefinitionBase ob)
        {
            base.Init(ob);
            MyObjectBuilder_BlockNavigationDefinition definition = ob as MyObjectBuilder_BlockNavigationDefinition;

            if (ob != null)
            {
                if (definition.NoEntry || (definition.Triangles == null))
                {
                    this.NoEntry = true;
                }
                else
                {
                    this.NoEntry = false;
                    MyGridNavigationMesh mesh = new MyGridNavigationMesh(null, null, definition.Triangles.Length, null);
                    Vector3I             max  = (Vector3I)((definition.Size - Vector3I.One) - definition.Center);
                    Vector3I             min  = (Vector3I) - definition.Center;
                    MyObjectBuilder_BlockNavigationDefinition.Triangle[] triangles = definition.Triangles;
                    int index = 0;
                    while (index < triangles.Length)
                    {
                        Vector3I vectori6;
                        Vector3I vectori7;
                        MyObjectBuilder_BlockNavigationDefinition.Triangle triangle1 = triangles[index];
                        Vector3 a = (Vector3)triangle1.Points[0];
                        Vector3 b = (Vector3)triangle1.Points[1];
                        Vector3 c = (Vector3)triangle1.Points[2];
                        MyNavigationTriangle tri = mesh.AddTriangle(ref a, ref b, ref c);
                        Vector3   vector4        = ((((a + b) + c) / 3f) - a) * 0.0001f;
                        Vector3   vector5        = ((((a + b) + c) / 3f) - b) * 0.0001f;
                        Vector3   vector6        = ((((a + b) + c) / 3f) - c) * 0.0001f;
                        Vector3I  result         = Vector3I.Round(a + vector4);
                        Vector3I  vectori4       = Vector3I.Round(b + vector5);
                        Vector3I  vectori5       = Vector3I.Round(c + vector6);
                        Vector3I *vectoriPtr1    = (Vector3I *)ref result;
                        Vector3I.Clamp(ref (Vector3I) ref vectoriPtr1, ref min, ref max, out result);
                        Vector3I *vectoriPtr2 = (Vector3I *)ref vectori4;
                        Vector3I.Clamp(ref (Vector3I) ref vectoriPtr2, ref min, ref max, out vectori4);
                        Vector3I *vectoriPtr3 = (Vector3I *)ref vectori5;
                        Vector3I.Clamp(ref (Vector3I) ref vectoriPtr3, ref min, ref max, out vectori5);
                        Vector3I.Min(ref result, ref vectori4, out vectori6);
                        Vector3I *vectoriPtr4 = (Vector3I *)ref vectori6;
                        Vector3I.Min(ref (Vector3I) ref vectoriPtr4, ref vectori5, out vectori6);
                        Vector3I.Max(ref result, ref vectori4, out vectori7);
                        Vector3I *vectoriPtr5 = (Vector3I *)ref vectori7;
                        Vector3I.Max(ref (Vector3I) ref vectoriPtr5, ref vectori5, out vectori7);
                        Vector3I gridPos = vectori6;
                        Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori6, ref vectori7);
                        while (true)
                        {
                            if (!iterator.IsValid())
                            {
                                index++;
                                break;
                            }
                            mesh.RegisterTriangle(tri, ref gridPos);
                            iterator.GetNext(out gridPos);
                        }
                    }
                    this.m_mesh = mesh;
                }
            }
        }
Пример #14
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();
        }
Пример #15
0
 public Component(MyGridNavigationMesh parent, int componentIndex)
 {
     m_parent = parent;
     m_componentIndex = componentIndex;
 }
Пример #16
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();
        }