Exemple #1
0
 public override void DebugDraw(ref Matrix drawMatrix)
 {
     if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW)
     {
         if (((MyDebugDrawSettings.DEBUG_DRAW_NAVMESHES & MyWEMDebugDrawMode.EDGES) != MyWEMDebugDrawMode.NONE) && (this.m_connectionHelper != null))
         {
             foreach (KeyValuePair <EdgeIndex, int> pair in this.m_connectionHelper)
             {
                 Vector3 pointTo = Vector3.Transform(pair.Key.B / 256f, (Matrix)drawMatrix);
                 MyRenderProxy.DebugDrawLine3D(Vector3.Transform(pair.Key.A / 256f, (Matrix)drawMatrix), pointTo, Color.Red, Color.Yellow, false, false);
             }
         }
         if ((MyDebugDrawSettings.DEBUG_DRAW_NAVMESHES & MyWEMDebugDrawMode.NORMALS) != MyWEMDebugDrawMode.NONE)
         {
             foreach (KeyValuePair <Vector3I, List <int> > pair2 in this.m_smallTriangleRegistry)
             {
                 foreach (int num in pair2.Value)
                 {
                     MyNavigationTriangle triangle = base.GetTriangle(num);
                     Vector3 pointTo = Vector3.Transform(triangle.Center + (triangle.Normal * 0.2f), (Matrix)drawMatrix);
                     MyRenderProxy.DebugDrawLine3D(Vector3.Transform(triangle.Center, (Matrix)drawMatrix), pointTo, Color.Blue, Color.Blue, true, false);
                 }
             }
         }
         if (MyFakes.DEBUG_DRAW_NAVMESH_HIERARCHY && (this.m_higherLevel != null))
         {
             this.m_higherLevel.DebugDraw(MyFakes.DEBUG_DRAW_NAVMESH_HIERARCHY_LITE);
         }
     }
 }
Exemple #2
0
        private bool ProcessTriangleForHierarchy(MyNavigationTriangle triangle)
        {
            // The triangle parent can be wrong when we have multiple navmeshes connected via external edges
            if (triangle.Parent != m_mesh)
            {
                return(false);
            }

            if (m_tmpCellTriangles.Contains(triangle.Index))
            {
                m_components.AddComponentTriangle(triangle, triangle.Center);
                m_tmpComponentTriangles.Add(triangle);
                return(true);
            }
            else
            {
                ulong cellIndex;
                // This test succeeds only if the triangle belongs to an unchanged component or to a component that was changed,
                // but processed in a different cell already
                if (m_components.TryGetComponentCell(triangle.ComponentIndex, out cellIndex))
                {
                    // Save connections to other components. There won't be so many, so we can keep them in a list instead of a HashSet
                    if (!m_currentCellConnections[m_currentComponentRel].Contains(triangle.ComponentIndex))
                    {
                        m_currentCellConnections[m_currentComponentRel].Add(triangle.ComponentIndex);
                    }
                }
            }
            return(false);
        }
        /// <summary>
        /// All coords should be in the voxel local coordinates
        /// </summary>
        public List <Vector4D> FindPath(Vector3 start, Vector3 end)
        {
            float closestDistance         = float.PositiveInfinity;
            MyNavigationTriangle startTri = GetClosestNavigationTriangle(ref start, ref closestDistance);

            if (startTri == null)
            {
                return(null);
            }
            closestDistance = float.PositiveInfinity;
            MyNavigationTriangle endTri = GetClosestNavigationTriangle(ref end, ref closestDistance);

            if (endTri == null)
            {
                return(null);
            }

            m_debugPos1 = Vector3.Transform(startTri.Position, m_voxelMap.PositionComp.WorldMatrix);
            m_debugPos2 = Vector3.Transform(endTri.Position, m_voxelMap.PositionComp.WorldMatrix);
            m_debugPos3 = Vector3.Transform(start, m_voxelMap.PositionComp.WorldMatrix);
            m_debugPos4 = Vector3.Transform(end, m_voxelMap.PositionComp.WorldMatrix);

            var path = FindRefinedPath(startTri, endTri, ref start, ref end);

            return(path);
        }
        /// <summary>
        /// All coords should be in the grid local coordinates
        /// </summary>
        public List <Vector4D> FindPath(Vector3 start, Vector3 end)
        {
            start /= m_grid.GridSize;
            end   /= m_grid.GridSize;

            float closestDistSq           = float.PositiveInfinity;
            MyNavigationTriangle startTri = GetClosestNavigationTriangle(ref start, ref closestDistSq);

            if (startTri == null)
            {
                return(null);
            }

            closestDistSq = float.PositiveInfinity;
            MyNavigationTriangle endTri = GetClosestNavigationTriangle(ref end, ref closestDistSq);

            if (endTri == null)
            {
                return(null);
            }

            var path = FindRefinedPath(startTri, endTri, ref start, ref end);

            if (path != null)
            {
                for (int i = 0; i < path.Count; ++i)
                {
                    var point = path[i];
                    point  *= m_grid.GridSize;
                    path[i] = point;
                }
            }

            return(path);
        }
Exemple #5
0
        private MyNavigationTriangle GetClosestNavigationTriangle(ref Vector3 point, ref float closestDistanceSq)
        {
            MyNavigationTriangle triangle = null;
            Vector3I             vectori  = Vector3I.Round((point + (this.m_voxelMap.PositionComp.GetPosition() - this.m_voxelMap.PositionLeftBottomCorner)) / this.m_cellSize);

            for (int i = 0; i < 8; i++)
            {
                Vector3I position = (Vector3I)(vectori + m_cornerOffsets[i]);
                if (this.m_processedCells.Contains(position))
                {
                    ulong          packedCellCoord = new MyCellCoord(0, position).PackId64();
                    MyIntervalList list            = this.m_higherLevelHelper.TryGetTriangleList(packedCellCoord);
                    if (list != null)
                    {
                        MyIntervalList.Enumerator enumerator = list.GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            int current = enumerator.Current;
                            MyNavigationTriangle triangle2 = base.GetTriangle(current);
                            float num4 = Vector3.DistanceSquared(triangle2.Center, point);
                            if (num4 < closestDistanceSq)
                            {
                                closestDistanceSq = num4;
                                triangle          = triangle2;
                            }
                        }
                    }
                }
            }
            return(triangle);
        }
Exemple #6
0
        private void RemoveTerrainTriangle(MyNavigationTriangle tri)
        {
            MyWingedEdgeMesh.FaceVertexEnumerator vertexEnumerator = tri.GetVertexEnumerator();
            vertexEnumerator.MoveNext();
            Vector3 current = vertexEnumerator.Current;

            vertexEnumerator.MoveNext();
            Vector3 vector2 = vertexEnumerator.Current;

            vertexEnumerator.MoveNext();
            Vector3 vector3   = vertexEnumerator.Current;
            int     edgeIndex = tri.GetEdgeIndex(0);
            int     num2      = tri.GetEdgeIndex(1);
            int     num3      = tri.GetEdgeIndex(2);
            int     num4      = edgeIndex;

            if (!this.m_connectionHelper.TryRemoveOuterEdge(ref current, ref vector2, ref num4) && (base.Mesh.GetEdge(edgeIndex).OtherFace(tri.Index) != -1))
            {
                this.m_connectionHelper.AddOuterEdgeIndex(ref vector2, ref current, edgeIndex);
            }
            num4 = num2;
            if (!this.m_connectionHelper.TryRemoveOuterEdge(ref vector2, ref vector3, ref num4) && (base.Mesh.GetEdge(num2).OtherFace(tri.Index) != -1))
            {
                this.m_connectionHelper.AddOuterEdgeIndex(ref vector3, ref vector2, num2);
            }
            num4 = num3;
            if (!this.m_connectionHelper.TryRemoveOuterEdge(ref vector3, ref current, ref num4) && (base.Mesh.GetEdge(num3).OtherFace(tri.Index) != -1))
            {
                this.m_connectionHelper.AddOuterEdgeIndex(ref current, ref vector3, num3);
            }
            base.RemoveTriangle(tri);
        }
            private void GetEdgeVerticesSafe(MyNavigationTriangle triangle, int edgeIndex, out Vector3 left, out Vector3 right)
            {
                triangle.GetEdgeVertices(edgeIndex, out left, out right);

                float d = (left - right).LengthSquared();

                bool leftDangerous  = triangle.IsEdgeVertexDangerous(edgeIndex, predVertex: true);
                bool rightDangerous = triangle.IsEdgeVertexDangerous(edgeIndex, predVertex: false);

                m_segmentDangerous |= leftDangerous | rightDangerous;

                if (leftDangerous)
                {
                    if (rightDangerous)
                    {
                        if (SAFE_DISTANCE2_SQ > d)
                        {
                            left  = (left + right) * 0.5f;
                            right = left;
                        }
                        else
                        {
                            float   t       = SAFE_DISTANCE / (float)Math.Sqrt(d);
                            Vector3 newLeft = right * t + left * (1.0f - t);
                            right = left * t + right * (1.0f - t);
                            left  = newLeft;
                        }
                    }
                    else
                    {
                        if (SAFE_DISTANCE_SQ > d)
                        {
                            left = right;
                        }
                        else
                        {
                            float t = SAFE_DISTANCE / (float)Math.Sqrt(d);
                            left = right * t + left * (1.0f - t);
                        }
                    }
                }
                else
                {
                    if (rightDangerous)
                    {
                        if (SAFE_DISTANCE_SQ > d)
                        {
                            right = left;
                        }
                        else
                        {
                            float t = SAFE_DISTANCE / (float)Math.Sqrt(d);
                            right = left * t + right * (1.0f - t);
                        }
                    }
                }

                m_debugPointsLeft.Add(left);
                m_debugPointsRight.Add(right);
            }
Exemple #8
0
        public List <Vector4D> FindPath(Vector3 start, Vector3 end)
        {
            start /= this.m_grid.GridSize;
            end   /= this.m_grid.GridSize;
            float positiveInfinity = float.PositiveInfinity;
            MyNavigationTriangle closestNavigationTriangle = this.GetClosestNavigationTriangle(ref start, ref positiveInfinity);

            if (closestNavigationTriangle == null)
            {
                return(null);
            }
            positiveInfinity = float.PositiveInfinity;
            MyNavigationTriangle triangle2 = this.GetClosestNavigationTriangle(ref end, ref positiveInfinity);

            if (triangle2 == null)
            {
                return(null);
            }
            List <Vector4D> list = base.FindRefinedPath(closestNavigationTriangle, triangle2, ref start, ref end);

            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    Vector4D vectord = list[i] * this.m_grid.GridSize;
                    list[i] = vectord;
                }
            }
            return(list);
        }
Exemple #9
0
 public void RegisterTriangle(MyNavigationTriangle tri, ref Vector3I gridPos)
 {
     if (this.m_grid == null)
     {
         this.RegisterTriangleInternal(tri, ref gridPos);
     }
 }
        public void TryAddVoxelNavmeshLinks2(MyVoxelPathfinding.CellId cellId, Dictionary <MyGridPathfinding.CubeId, List <MyNavigationPrimitive> > linkCandidates)
        {
            ProfilerShort.Begin("TryAddVoxelNavmeshLinks");
            foreach (var entry in linkCandidates)
            {
                double closestDistSq = double.MaxValue;
                MyNavigationTriangle  closestGridTri    = null;
                MyNavigationPrimitive closestLinkedPrim = null;

                m_tmpNavTris.Clear();
                m_gridPathfinding.GetCubeTriangles(entry.Key, m_tmpNavTris);
                foreach (var tri in m_tmpNavTris)
                {
                    Vector3 a, b, c;
                    tri.GetVertices(out a, out b, out c);

                    a = tri.Parent.LocalToGlobal(a);
                    b = tri.Parent.LocalToGlobal(b);
                    c = tri.Parent.LocalToGlobal(c);

                    Vector3D normal = (c - a).Cross(b - a);
                    Vector3D center = (a + b + c) / 3.0f;
                    double   lowerY = Math.Min(a.Y, Math.Min(b.Y, c.Y));
                    double   upperY = Math.Max(a.Y, Math.Max(b.Y, c.Y));
                    lowerY -= 0.25f;
                    upperY += 0.25f;

                    foreach (var primitive in entry.Value)
                    {
                        Vector3D primPos   = primitive.WorldPosition;
                        Vector3D offset    = primPos - center;
                        double   offsetLen = offset.Length();
                        offset = offset / offsetLen;
                        double dot; Vector3D.Dot(ref offset, ref normal, out dot);
                        if (dot > -0.2f && primPos.Y < upperY && primPos.Y > lowerY)
                        {
                            double dist = offsetLen / (dot + 0.3f);
                            if (dist < closestDistSq)
                            {
                                closestDistSq     = dist;
                                closestGridTri    = tri;
                                closestLinkedPrim = primitive;
                            }
                        }
                    }
                }
                m_tmpNavTris.Clear();

                if (closestGridTri != null)
                {
                    Debug.Assert(closestLinkedPrim.GetHighLevelPrimitive() != null);
                    Debug.Assert(closestGridTri.GetHighLevelPrimitive() != null);
                    m_links.AddLink(closestLinkedPrim, closestGridTri);
                    SaveVoxelLinkToDictionary(cellId, closestLinkedPrim);
                    IncreaseGridLinkCounter(entry.Key);
                }
            }
            ProfilerShort.End();
        }
Exemple #11
0
        public void AddComponentTriangle(MyNavigationTriangle triangle, Vector3 center)
        {
            MyIntervalList list = this.m_components[this.m_componentNum];

            list.Add(triangle.Index);
            float num2 = 1f / ((float)list.Count);

            this.m_lastCellComponentCenters[this.m_componentNum] = (center * num2) + (this.m_lastCellComponentCenters[this.m_componentNum] * (1f - num2));
        }
Exemple #12
0
            public bool Contains(MyNavigationPrimitive primitive)
            {
                if (!ReferenceEquals(primitive.Group, this.m_parent))
                {
                    return(false);
                }
                MyNavigationTriangle triangle = primitive as MyNavigationTriangle;

                return((triangle != null) ? (triangle.ComponentIndex == this.m_componentIndex) : false);
            }
        public void RegisterTriangle(MyNavigationTriangle tri, ref Vector3I gridPos)
        {
            Debug.Assert(m_grid == null, "Triangles can be registered in the grid navigation mesh from the outside only if it's a mesh for block navigation definition!");
            if (m_grid != null)
            {
                return;
            }

            RegisterTriangleInternal(tri, ref gridPos);
        }
Exemple #14
0
        private MyNavigationTriangle AddTriangleInternal(Vector3 a, Vector3 b, Vector3 c)
        {
            int      num;
            int      num2;
            int      num3;
            Vector3I pointB   = Vector3I.Round(a * 256f);
            Vector3I pointA   = Vector3I.Round(b * 256f);
            Vector3I vectori3 = Vector3I.Round(c * 256f);
            Vector3  vector   = pointB / 256f;
            Vector3  vector2  = pointA / 256f;
            Vector3  vector3  = vectori3 / 256f;

            if (!this.m_connectionHelper.TryGetValue(new EdgeIndex(ref pointA, ref pointB), out num))
            {
                num = -1;
            }
            if (!this.m_connectionHelper.TryGetValue(new EdgeIndex(ref vectori3, ref pointA), out num2))
            {
                num2 = -1;
            }
            if (!this.m_connectionHelper.TryGetValue(new EdgeIndex(ref pointB, ref vectori3), out num3))
            {
                num3 = -1;
            }
            int num4 = num2;
            int num5 = num3;
            MyNavigationTriangle triangle = base.AddTriangle(ref vector, ref vector3, ref vector2, ref num3, ref num2, ref num);

            if (num == -1)
            {
                this.m_connectionHelper.Add(new EdgeIndex(ref pointB, ref pointA), num);
            }
            else
            {
                this.m_connectionHelper.Remove(new EdgeIndex(ref pointA, ref pointB));
            }
            if (num4 == -1)
            {
                this.m_connectionHelper.Add(new EdgeIndex(ref pointA, ref vectori3), num2);
            }
            else
            {
                this.m_connectionHelper.Remove(new EdgeIndex(ref vectori3, ref pointA));
            }
            if (num5 == -1)
            {
                this.m_connectionHelper.Add(new EdgeIndex(ref vectori3, ref pointB), num3);
            }
            else
            {
                this.m_connectionHelper.Remove(new EdgeIndex(ref pointB, ref vectori3));
            }
            return(triangle);
        }
            bool IMyHighLevelComponent.Contains(MyNavigationPrimitive primitive)
            {
                MyNavigationTriangle tri = primitive as MyNavigationTriangle;

                if (tri == null)
                {
                    return(false);
                }

                return(tri.ComponentIndex == m_componentIndex);
            }
Exemple #16
0
        private void RegisterTriangleInternal(MyNavigationTriangle tri, ref Vector3I gridPos)
        {
            List <int> list = null;

            if (!this.m_smallTriangleRegistry.TryGetValue(gridPos, out list))
            {
                list = new List <int>();
                this.m_smallTriangleRegistry.Add(gridPos, list);
            }
            list.Add(tri.Index);
            tri.Registered = true;
        }
        private void RemoveTerrainTriangle(MyNavigationTriangle tri)
        {
            var vertices = tri.GetVertexEnumerator();

            vertices.MoveNext();
            Vector3 aPos = vertices.Current;

            vertices.MoveNext();
            Vector3 bPos = vertices.Current;

            vertices.MoveNext();
            Vector3 cPos = vertices.Current;

            int edgeAB = tri.GetEdgeIndex(0);
            int edgeBC = tri.GetEdgeIndex(1);
            int edgeCA = tri.GetEdgeIndex(2);

            int tmp;

            ProfilerShort.Begin("Handling outer edges");
            tmp = edgeAB;
            if (!m_connectionHelper.TryRemoveOuterEdge(ref aPos, ref bPos, ref tmp))
            {
                var edge = Mesh.GetEdge(edgeAB);
                if (edge.OtherFace(tri.Index) != -1)
                {
                    m_connectionHelper.AddOuterEdgeIndex(ref bPos, ref aPos, edgeAB);
                }
            }
            tmp = edgeBC;
            if (!m_connectionHelper.TryRemoveOuterEdge(ref bPos, ref cPos, ref tmp))
            {
                var edge = Mesh.GetEdge(edgeBC);
                if (edge.OtherFace(tri.Index) != -1)
                {
                    m_connectionHelper.AddOuterEdgeIndex(ref cPos, ref bPos, edgeBC);
                }
            }
            tmp = edgeCA;
            if (!m_connectionHelper.TryRemoveOuterEdge(ref cPos, ref aPos, ref tmp))
            {
                var edge = Mesh.GetEdge(edgeCA);
                if (edge.OtherFace(tri.Index) != -1)
                {
                    m_connectionHelper.AddOuterEdgeIndex(ref aPos, ref cPos, edgeCA);
                }
            }
            ProfilerShort.End();

            ProfilerShort.Begin("Removing the tri");
            RemoveTriangle(tri);
            ProfilerShort.End();
        }
Exemple #18
0
        protected MyNavigationTriangle AddTriangle(ref Vector3 A, ref Vector3 B, ref Vector3 C, ref int edgeAB, ref int edgeBC, ref int edgeCA)
        {
            MyNavigationTriangle userData = this.m_triPool.Allocate();
            int num           = ((0 + ((edgeAB == -1) ? 1 : 0)) + ((edgeBC == -1) ? 1 : 0)) + ((edgeCA == -1) ? 1 : 0);
            int triangleIndex = -1;

            if (num == 3)
            {
                triangleIndex = this.m_mesh.MakeNewTriangle(userData, ref A, ref B, ref C, out edgeAB, out edgeBC, out edgeCA);
            }
            else if (num == 2)
            {
                triangleIndex = (edgeAB == -1) ? ((edgeBC == -1) ? this.m_mesh.ExtrudeTriangleFromEdge(ref B, edgeCA, userData, out edgeAB, out edgeBC) : this.m_mesh.ExtrudeTriangleFromEdge(ref A, edgeBC, userData, out edgeCA, out edgeAB)) : this.m_mesh.ExtrudeTriangleFromEdge(ref C, edgeAB, userData, out edgeBC, out edgeCA);
            }
            else if (num == 1)
            {
                triangleIndex = (edgeAB != -1) ? ((edgeBC != -1) ? this.GetTriangleOneNewEdge(ref edgeCA, ref edgeAB, ref edgeBC, userData) : this.GetTriangleOneNewEdge(ref edgeBC, ref edgeCA, ref edgeAB, userData)) : this.GetTriangleOneNewEdge(ref edgeAB, ref edgeBC, ref edgeCA, userData);
            }
            else
            {
                MyWingedEdgeMesh.Edge other = this.m_mesh.GetEdge(edgeAB);
                MyWingedEdgeMesh.Edge edge  = this.m_mesh.GetEdge(edgeBC);
                MyWingedEdgeMesh.Edge edge3 = this.m_mesh.GetEdge(edgeCA);
                int sharedB = edge3.TryGetSharedVertex(ref other);
                int sharedC = other.TryGetSharedVertex(ref edge);
                int num5    = edge.TryGetSharedVertex(ref edge3);
                int num6    = ((0 + ((sharedB == -1) ? 0 : 1)) + ((sharedC == -1) ? 0 : 1)) + ((num5 == -1) ? 0 : 1);
                if (num6 == 3)
                {
                    triangleIndex = this.m_mesh.MakeFace(userData, edgeAB);
                }
                else if (num6 == 2)
                {
                    triangleIndex = (sharedB != -1) ? ((sharedC != -1) ? this.GetTriangleTwoSharedVertices(edgeCA, edgeAB, ref edgeBC, sharedB, sharedC, userData) : this.GetTriangleTwoSharedVertices(edgeBC, edgeCA, ref edgeAB, num5, sharedB, userData)) : this.GetTriangleTwoSharedVertices(edgeAB, edgeBC, ref edgeCA, sharedC, num5, userData);
                }
                else if (num6 == 1)
                {
                    triangleIndex = (sharedB == -1) ? ((sharedC == -1) ? this.GetTriangleOneSharedVertex(edgeBC, edgeCA, ref edgeAB, num5, userData) : this.GetTriangleOneSharedVertex(edgeAB, edgeBC, ref edgeCA, sharedC, userData)) : this.GetTriangleOneSharedVertex(edgeCA, edgeAB, ref edgeBC, sharedB, userData);
                }
                else
                {
                    int num7;
                    int num8;
                    triangleIndex = this.m_mesh.ExtrudeTriangleFromEdge(ref C, edgeAB, userData, out num7, out num8);
                    this.m_mesh.MergeEdges(num8, edgeCA);
                    this.m_mesh.MergeEdges(num7, edgeBC);
                }
            }
            userData.Init(this, triangleIndex);
            return(userData);
        }
Exemple #19
0
            private void GetEdgeVerticesSafe(MyNavigationTriangle triangle, int edgeIndex, out Vector3 left, out Vector3 right)
            {
                triangle.GetEdgeVertices(edgeIndex, out left, out right);
                float num   = (left - right).LengthSquared();
                bool  flag  = triangle.IsEdgeVertexDangerous(edgeIndex, true);
                bool  flag2 = triangle.IsEdgeVertexDangerous(edgeIndex, false);

                this.m_segmentDangerous |= flag | flag2;
                if (!flag)
                {
                    if (flag2)
                    {
                        if (SAFE_DISTANCE_SQ > num)
                        {
                            right = left;
                        }
                        else
                        {
                            float num4 = SAFE_DISTANCE / ((float)Math.Sqrt((double)num));
                            right = (left * num4) + (right * (1f - num4));
                        }
                    }
                }
                else if (!flag2)
                {
                    if (SAFE_DISTANCE_SQ > num)
                    {
                        left = right;
                    }
                    else
                    {
                        float num3 = SAFE_DISTANCE / ((float)Math.Sqrt((double)num));
                        left = (right * num3) + (left * (1f - num3));
                    }
                }
                else if (SAFE_DISTANCE2_SQ > num)
                {
                    left  = (left + right) * 0.5f;
                    right = left;
                }
                else
                {
                    float   num2    = SAFE_DISTANCE / ((float)Math.Sqrt((double)num));
                    Vector3 vector2 = (right * num2) + (left * (1f - num2));
                    right = (left * num2) + (right * (1f - num2));
                    left  = vector2;
                }
                MyNavigationMesh.m_debugPointsLeft.Add(left);
                MyNavigationMesh.m_debugPointsRight.Add(right);
            }
Exemple #20
0
        private bool IsFaceTriangle(MyNavigationTriangle triangle, Vector3I cubePosition, Vector3I direction)
        {
            MyWingedEdgeMesh.FaceVertexEnumerator vertexEnumerator = triangle.GetVertexEnumerator();
            vertexEnumerator.MoveNext();
            vertexEnumerator.MoveNext();
            vertexEnumerator.MoveNext();
            cubePosition *= 0x100;
            Vector3I vectori4 = (Vector3I)(cubePosition + (direction * 0x80));
            Vector3I vectori  = Vector3I.Round(vertexEnumerator.Current * 256f) - vectori4;
            Vector3I vectori2 = Vector3I.Round(vertexEnumerator.Current * 256f) - vectori4;
            Vector3I vectori3 = Vector3I.Round(vertexEnumerator.Current * 256f) - vectori4;

            return(!((vectori * direction) != Vector3I.Zero) ? (!((vectori2 * direction) != Vector3I.Zero) ? (!((vectori3 * direction) != Vector3I.Zero) ? ((vectori.AbsMax() <= 0x80) && ((vectori2.AbsMax() <= 0x80) && (vectori3.AbsMax() <= 0x80))) : false) : false) : false);
        }
Exemple #21
0
 public void TryAddVoxelNavmeshLinks2(MyVoxelPathfinding.CellId cellId, Dictionary <MyGridPathfinding.CubeId, List <MyNavigationPrimitive> > linkCandidates)
 {
     foreach (KeyValuePair <MyGridPathfinding.CubeId, List <MyNavigationPrimitive> > pair in linkCandidates)
     {
         double maxValue = double.MaxValue;
         MyNavigationTriangle  triangle  = null;
         MyNavigationPrimitive primitive = null;
         m_tmpNavTris.Clear();
         this.m_gridPathfinding.GetCubeTriangles(pair.Key, m_tmpNavTris);
         foreach (MyNavigationTriangle triangle2 in m_tmpNavTris)
         {
             Vector3 vector;
             Vector3 vector2;
             Vector3 vector3;
             triangle2.GetVertices(out vector, out vector2, out vector3);
             vector  = (Vector3)triangle2.Parent.LocalToGlobal(vector);
             vector2 = (Vector3)triangle2.Parent.LocalToGlobal(vector2);
             vector3 = (Vector3)triangle2.Parent.LocalToGlobal(vector3);
             Vector3D vectord  = (vector3 - vector).Cross(vector2 - vector);
             Vector3D vectord2 = ((vector + vector2) + vector3) / 3f;
             double   num2     = Math.Min(vector.Y, Math.Min(vector2.Y, vector3.Y)) - 0.25;
             double   num3     = Math.Max(vector.Y, Math.Max(vector2.Y, vector3.Y)) + 0.25;
             foreach (MyNavigationPrimitive primitive2 in pair.Value)
             {
                 double   num5;
                 Vector3D worldPosition = primitive2.WorldPosition;
                 Vector3D vectord4      = worldPosition - vectord2;
                 double   num4          = vectord4.Length();
                 Vector3D.Dot(ref vectord4 / num4, ref vectord, out num5);
                 if ((num5 > -0.20000000298023224) && ((worldPosition.Y < num3) && (worldPosition.Y > num2)))
                 {
                     double num6 = num4 / (num5 + 0.30000001192092896);
                     if (num6 < maxValue)
                     {
                         maxValue  = num6;
                         triangle  = triangle2;
                         primitive = primitive2;
                     }
                 }
             }
         }
         m_tmpNavTris.Clear();
         if (triangle != null)
         {
             this.m_links.AddLink(primitive, triangle, false);
             this.SaveVoxelLinkToDictionary(cellId, primitive);
             this.IncreaseGridLinkCounter(pair.Key);
         }
     }
 }
        public void AddComponentTriangle(MyNavigationTriangle triangle, Vector3 center)
        {
            Debug.Assert(m_componentOpen, "Adding a triangle to a component in TriangleComponentMapping, when no component is open!");

            int triIndex = triangle.Index;

            MyIntervalList triList = m_components[m_componentNum];

            triList.Add(triIndex);

            float t = 1.0f / triList.Count;

            m_lastCellComponentCenters[m_componentNum] = center * t + m_lastCellComponentCenters[m_componentNum] * (1.0f - t);
        }
Exemple #23
0
 private int AddTriangle(int index)
 {
     if (!this.m_funnelConstructed)
     {
         this.ConstructFunnel(index);
     }
     else
     {
         Vector3 vector;
         Vector3 vector2;
         MyPath <MyNavigationPrimitive> .PathNode node = this.m_input[index];
         MyNavigationTriangle vertex = node.Vertex as MyNavigationTriangle;
         vertex.GetNavigationEdge(node.nextVertex);
         this.GetEdgeVerticesSafe(vertex, node.nextVertex, out vector, out vector2);
         PointTestResult result  = this.TestPoint(vector);
         PointTestResult result2 = this.TestPoint(vector2);
         if (result == PointTestResult.INSIDE)
         {
             this.NarrowFunnel(vector, index, true);
         }
         if (result2 == PointTestResult.INSIDE)
         {
             this.NarrowFunnel(vector2, index, false);
         }
         if (result == PointTestResult.RIGHT)
         {
             this.m_apex = this.m_rightPoint;
             this.m_funnelConstructed = false;
             this.ConstructFunnel(this.m_rightIndex + 1);
             return(this.m_rightIndex + 1);
         }
         if (result2 == PointTestResult.LEFT)
         {
             this.m_apex = this.m_leftPoint;
             this.m_funnelConstructed = false;
             this.ConstructFunnel(this.m_leftIndex + 1);
             return(this.m_leftIndex + 1);
         }
         if ((result == PointTestResult.INSIDE) || (result2 == PointTestResult.INSIDE))
         {
             MyNavigationMesh.FunnelState item = new MyNavigationMesh.FunnelState {
                 Apex  = this.m_apex,
                 Left  = this.m_leftPoint,
                 Right = this.m_rightPoint
             };
             MyNavigationMesh.m_debugFunnel.Add(item);
         }
     }
     return(index + 1);
 }
        private bool ProcessTriangleForHierarchy(MyNavigationTriangle triangle)
        {
            // The triangle parent can be wrong when we have multiple navmeshes connected via external edges
            if (triangle.Parent != m_mesh)
            {
                return(false);
            }

            // Previously unvisited triangle will be assigned the current relative component index
            if (triangle.ComponentIndex == -1)
            {
                m_navmeshComponents.AddComponentTriangle(triangle, triangle.Center);
                m_tmpComponentTriangles.Add(triangle);
                triangle.ComponentIndex = m_currentComponentMarker;
                return(true);
            }
            else if (triangle.ComponentIndex == m_currentComponentMarker)
            {
                // We can safely ignore this triangle (it has already been processed);
                return(true);
            }
            else
            {
                ulong cellIndex;
                if (m_navmeshComponents.GetComponentCell(triangle.ComponentIndex, out cellIndex))
                {
                    MyCellCoord cellCoord = new MyCellCoord();
                    cellCoord.SetUnpack(cellIndex);
                    Vector3I diff = cellCoord.CoordInLod - m_currentCell;
                    if (diff.RectangularLength() != 1)
                    {
                        // CH: TODO: Connection of components over cell edges or vertices. I currently silently ignore that...
                        return(false);
                    }

                    ConnectionInfo connection = new ConnectionInfo();
                    connection.Direction      = Base6Directions.GetDirection(diff);
                    connection.ComponentIndex = triangle.ComponentIndex;

                    // Save connections to other components. There won't be so many, so we can keep them in a list instead of a HashSet
                    if (!m_currentCellConnections[m_currentComponentRel].Contains(connection))
                    {
                        m_currentCellConnections[m_currentComponentRel].Add(connection);
                    }
                }
            }
            return(false);
        }
Exemple #25
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 RegisterTriangleInternal(MyNavigationTriangle tri, ref Vector3I gridPos)
        {
            Debug.Assert(!tri.Registered); // So far, triangles can only be registered in one cube. This can change in the future with optimizations

            List <int> list = null;

            if (!m_smallTriangleRegistry.TryGetValue(gridPos, out list))
            {
                list = new List <int>();
                m_smallTriangleRegistry.Add(gridPos, list);
            }

            list.Add(tri.Index);

            tri.Registered = true;
        }
Exemple #27
0
        public override MyNavigationPrimitive FindClosestPrimitive(Vector3D point, bool highLevel, ref double closestDistanceSq)
        {
            if (highLevel)
            {
                return(null);
            }
            Vector3 vector        = (Vector3)(Vector3D.Transform(point, this.m_grid.PositionComp.WorldMatrixNormalizedInv) / this.m_grid.GridSize);
            float   closestDistSq = ((float)closestDistanceSq) / this.m_grid.GridSize;
            MyNavigationTriangle closestNavigationTriangle = this.GetClosestNavigationTriangle(ref vector, ref closestDistSq);

            if (closestNavigationTriangle != null)
            {
                closestDistanceSq = closestDistSq * this.m_grid.GridSize;
            }
            return(closestNavigationTriangle);
        }
        public MyHighLevelPrimitive GetHighLevelNavigationPrimitive(MyNavigationTriangle triangle)
        {
            Debug.Assert(triangle.Parent == this.m_mesh, "Finding cell of a navigation triangle in a wrong mesh!");
            if (triangle.Parent != this.m_mesh)
            {
                return(null);
            }

            if (triangle.ComponentIndex != -1)
            {
                return(m_mesh.HighLevelGroup.GetPrimitive(triangle.ComponentIndex));
            }
            else
            {
                return(null);
            }
        }
Exemple #29
0
        private void RemoveAndAddTriangle(ref Vector3I positionA, ref Vector3I positionB, int registeredEdgeIndex)
        {
            MyNavigationTriangle edgeTriangle = base.GetEdgeTriangle(registeredEdgeIndex);

            MyWingedEdgeMesh.FaceVertexEnumerator vertexEnumerator = edgeTriangle.GetVertexEnumerator();
            vertexEnumerator.MoveNext();
            Vector3 current = vertexEnumerator.Current;

            vertexEnumerator.MoveNext();
            vertexEnumerator.MoveNext();
            Vector3I cube = this.FindTriangleCube(edgeTriangle.Index, ref positionA, ref positionB);

            this.RemoveTriangle(edgeTriangle, cube);
            MyNavigationTriangle tri = this.AddTriangleInternal(current, vertexEnumerator.Current, vertexEnumerator.Current);

            this.RegisterTriangleInternal(tri, ref cube);
        }
Exemple #30
0
 private bool ProcessTriangleForHierarchy(MyNavigationTriangle triangle)
 {
     if (ReferenceEquals(triangle.Parent, this.m_mesh))
     {
         ulong num;
         if (m_tmpCellTriangles.Contains(triangle.Index))
         {
             this.m_components.AddComponentTriangle(triangle, triangle.Center);
             this.m_tmpComponentTriangles.Add(triangle);
             return(true);
         }
         if (this.m_components.TryGetComponentCell(triangle.ComponentIndex, out num) && !this.m_currentCellConnections[this.m_currentComponentRel].Contains(triangle.ComponentIndex))
         {
             this.m_currentCellConnections[this.m_currentComponentRel].Add(triangle.ComponentIndex);
         }
     }
     return(false);
 }
        private bool ProcessTriangleForHierarchy(MyNavigationTriangle triangle)
        {
            // The triangle parent can be wrong when we have multiple navmeshes connected via external edges
            if (triangle.Parent != m_mesh)
            {
                return false;
            }

            if (m_tmpCellTriangles.Contains(triangle.Index))
            {
                m_components.AddComponentTriangle(triangle, triangle.Center);
                m_tmpComponentTriangles.Add(triangle);
                return true;
            }
            else
            {
                ulong cellIndex;
                // This test succeeds only if the triangle belongs to an unchanged component or to a component that was changed,
                // but processed in a different cell already
                if (m_components.TryGetComponentCell(triangle.ComponentIndex, out cellIndex))
                {
                    // Save connections to other components. There won't be so many, so we can keep them in a list instead of a HashSet
                    if (!m_currentCellConnections[m_currentComponentRel].Contains(triangle.ComponentIndex))
                    {
                        m_currentCellConnections[m_currentComponentRel].Add(triangle.ComponentIndex);
                    }
                }
            }
            return false;
        }
        public MyHighLevelPrimitive GetHighLevelNavigationPrimitive(MyNavigationTriangle triangle)
        {
            Debug.Assert(triangle != null, "Navigation triangle was null!");
            if (triangle == null) return null;

            Debug.Assert(triangle.Parent == this.m_mesh, "Finding cell of a navigation triangle in a wrong mesh!");
            if (triangle.Parent != this.m_mesh)
            {
                return null;
            }

            if (triangle.ComponentIndex != -1)
            {
                return m_mesh.HighLevelGroup.GetPrimitive(triangle.ComponentIndex);
            }
            else
            {
                return null;
            }
        }
        private void RemoveTriangle(MyNavigationTriangle triangle, Vector3I cube)
        {
            var e = triangle.GetVertexEnumerator();
            e.MoveNext();
            Vector3I positionA = Vector3I.Round(e.Current * 256);
            e.MoveNext();
            Vector3I positionC = Vector3I.Round(e.Current * 256); // This is not a mistake! C is swapped with B (see also: AddTriangle...)
            e.MoveNext();
            Vector3I positionB = Vector3I.Round(e.Current * 256);

            // This should be AB, BC and CA, but after swapping it's AC, CB and BA
            int triCA = triangle.GetEdgeIndex(0);
            int triBC = triangle.GetEdgeIndex(1);
            int triAB = triangle.GetEdgeIndex(2);

            int edgeAB, edgeBC, edgeCA;
            if (!m_connectionHelper.TryGetValue(new EdgeIndex(ref positionA, ref positionB), out edgeAB)) edgeAB = -1;
            if (!m_connectionHelper.TryGetValue(new EdgeIndex(ref positionB, ref positionC), out edgeBC)) edgeBC = -1;
            if (!m_connectionHelper.TryGetValue(new EdgeIndex(ref positionC, ref positionA), out edgeCA)) edgeCA = -1;

            // Register those edges that were not registered in the connection helper.
            // They are registered counter-clockwise, because we are in fact registering the other triangle across the edges
            if (edgeAB != -1 && triAB == edgeAB)
                m_connectionHelper.Remove(new EdgeIndex(ref positionA, ref positionB));
            else
                m_connectionHelper.Add(new EdgeIndex(positionB, positionA), triAB);

            if (edgeBC != -1 && triBC == edgeBC)
                m_connectionHelper.Remove(new EdgeIndex(ref positionB, ref positionC));
            else
                m_connectionHelper.Add(new EdgeIndex(positionC, positionB), triBC);

            if (edgeCA != -1 && triCA == edgeCA)
                m_connectionHelper.Remove(new EdgeIndex(ref positionC, ref positionA));
            else
                m_connectionHelper.Add(new EdgeIndex(positionA, positionC), triCA);

            List<int> list = null;
            m_smallTriangleRegistry.TryGetValue(cube, out list);
            Debug.Assert(list != null, "Removed triangle was not registered in the registry!");
            for (int i = 0; i < list.Count; ++i)
            {
                if (list[i] == triangle.Index)
                {
                    list.RemoveAtFast(i);
                    break;
                }
            }
            if (list.Count == 0)
                m_smallTriangleRegistry.Remove(cube);

            RemoveTriangle(triangle);

            if (edgeAB != -1 && triAB != edgeAB)
                RemoveAndAddTriangle(ref positionA, ref positionB, edgeAB);
            if (edgeBC != -1 && triBC != edgeBC)
                RemoveAndAddTriangle(ref positionB, ref positionC, edgeBC);
            if (edgeCA != -1 && triCA != edgeCA)
                RemoveAndAddTriangle(ref positionC, ref positionA, edgeCA);
        }
        private bool IsFaceTriangle(MyNavigationTriangle triangle, Vector3I cubePosition, Vector3I direction)
        {
            var e = triangle.GetVertexEnumerator();

            // Quantize the point positions to 1/256ths inside each cube (but multiplied by 256 :-) )
            e.MoveNext();
            Vector3I positionA = Vector3I.Round(e.Current * 256);
            e.MoveNext();
            Vector3I positionB = Vector3I.Round(e.Current * 256);
            e.MoveNext();
            Vector3I positionC = Vector3I.Round(e.Current * 256);
            cubePosition = cubePosition * 256;

            // Change the point coordinates to be relative to the face center
            Vector3I faceCenter = cubePosition + direction * 128;
            positionA -= faceCenter;
            positionB -= faceCenter;
            positionC -= faceCenter;

            // Discard all triangles whose points are not on the plane of the face
            if (positionA * direction != Vector3I.Zero) return false;
            if (positionB * direction != Vector3I.Zero) return false;
            if (positionC * direction != Vector3I.Zero) return false;

            // Discard all triangles that are not contained inside the face's square
            return (positionA.AbsMax() <= 128 && positionB.AbsMax() <= 128 && positionC.AbsMax() <= 128);
        }
        private void CopyTriangle(MyNavigationTriangle otherTri, Vector3I triPosition, ref MatrixI transform)
        {
            Vector3 newA, newB, newC;
            otherTri.GetTransformed(ref transform, out newA, out newB, out newC);

            if (MyFakes.NAVMESH_PRESUMES_DOWNWARD_GRAVITY)
            {
                Vector3 n = Vector3.Cross(newC - newA, newB - newA);
                n.Normalize();
                if (Vector3.Dot(n, Base6Directions.GetVector(Base6Directions.Direction.Up)) < 0.7f) return; // Slightly lower than sqrt(2)/2 = 45 deg
            }

            Vector3I.Transform(ref triPosition, ref transform, out triPosition);

            // This is not an error - we need to swap C and B from the navmesh,
            // because they will be swapped again when the triangle is added
            var tri = AddTriangleInternal(newA, newC, newB);
            RegisterTriangleInternal(tri, ref triPosition);
        }
        private void RemoveTerrainTriangle(MyNavigationTriangle tri)
        {
            var vertices = tri.GetVertexEnumerator();

            vertices.MoveNext();
            Vector3 aPos = vertices.Current;
            vertices.MoveNext();
            Vector3 bPos = vertices.Current;
            vertices.MoveNext();
            Vector3 cPos = vertices.Current;

            int edgeAB = tri.GetEdgeIndex(0);
            int edgeBC = tri.GetEdgeIndex(1);
            int edgeCA = tri.GetEdgeIndex(2);

            int tmp;

            ProfilerShort.Begin("Handling outer edges");
            tmp = edgeAB;
            if (!m_connectionHelper.TryRemoveOuterEdge(ref aPos, ref bPos, ref tmp))
            {
                var edge = Mesh.GetEdge(edgeAB);
                if (edge.OtherFace(tri.Index) != -1)
                    m_connectionHelper.AddOuterEdgeIndex(ref bPos, ref aPos, edgeAB);
            }
            tmp = edgeBC;
            if (!m_connectionHelper.TryRemoveOuterEdge(ref bPos, ref cPos, ref tmp))
            {
                var edge = Mesh.GetEdge(edgeBC);
                if (edge.OtherFace(tri.Index) != -1)
                    m_connectionHelper.AddOuterEdgeIndex(ref cPos, ref bPos, edgeBC);
            }
            tmp = edgeCA;
            if (!m_connectionHelper.TryRemoveOuterEdge(ref cPos, ref aPos, ref tmp))
            {
                var edge = Mesh.GetEdge(edgeCA);
                if (edge.OtherFace(tri.Index) != -1)
                    m_connectionHelper.AddOuterEdgeIndex(ref aPos, ref cPos, edgeCA);
            }
            ProfilerShort.End();

            ProfilerShort.Begin("Removing the tri");
            RemoveTriangle(tri);
            ProfilerShort.End();
        }
        private void RegisterTriangleInternal(MyNavigationTriangle tri, ref Vector3I gridPos)
        {
            Debug.Assert(!tri.Registered); // So far, triangles can only be registered in one cube. This can change in the future with optimizations

            List<int> list = null;
            if (!m_smallTriangleRegistry.TryGetValue(gridPos, out list))
            {
                list = new List<int>();
                m_smallTriangleRegistry.Add(gridPos, list);
            }

            list.Add(tri.Index);

            tri.Registered = true;
        }
        private bool ProcessTriangleForHierarchy(MyNavigationTriangle triangle)
        {
            // The triangle parent can be wrong when we have multiple navmeshes connected via external edges
            if (triangle.Parent != m_mesh)
            {
                return false;
            }

            if (triangle.ComponentIndex == -1)
            {
                m_navmeshComponents.AddComponentTriangle(triangle, triangle.Center);
                triangle.ComponentIndex = m_navmeshComponents.OpenComponentIndex;
                return true;
            }
            else if (triangle.ComponentIndex == m_navmeshComponents.OpenComponentIndex)
            {
                return true;
            }
            else
            {
                ulong cellIndex;
                if (m_navmeshComponents.GetComponentCell(triangle.ComponentIndex, out cellIndex))
                {
                    MyCellCoord cellCoord = new MyCellCoord();
                    cellCoord.SetUnpack(cellIndex);
                    Vector3I diff = cellCoord.CoordInLod - m_currentCell;
                    if (diff.RectangularLength() != 1)
                    {
                        // CH: TODO: Connection of components over cell edges or vertices. I currently silently ignore that...
                        return false;
                    }

                    ConnectionInfo connection = new ConnectionInfo();
                    connection.Direction = Base6Directions.GetDirection(diff);
                    connection.ComponentIndex = triangle.ComponentIndex;

                    // Save connections to other components. There won't be so many, so we can keep them in a list instead of a HashSet
                    if (!m_currentCellConnections[m_currentComponentRel].Contains(connection))
                    {
                        m_currentCellConnections[m_currentComponentRel].Add(connection);
                    }
                }
            }
            return false;
        }
        // This is an old version of the function
        public void TryAddVoxelNavmeshLinks(MyNavigationTriangle addedPrimitive, MyVoxelPathfinding.CellId cellId, List<MyGridPathfinding.CubeId> linkCandidates)
        {
            ProfilerShort.Begin("TryAddVoxelNavmeshLinks");

            m_tmpNavTris.Clear();
            foreach (var candidate in linkCandidates)
            {
                // First, find closest navigation triangle from the given candidate cube
                ProfilerShort.Begin("Find closest grid nav tri");
                m_gridPathfinding.GetCubeTriangles(candidate, m_tmpNavTris);

                double closestDistSq = double.MaxValue;
                MyNavigationTriangle closestGridTri = null;

                foreach (var tri in m_tmpNavTris)
                {
                    Vector3D posDiff = addedPrimitive.WorldPosition - tri.WorldPosition;
                    if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
                    {
                        if (Math.Abs(posDiff.Y) < 0.3)
                        {
                            if (posDiff.LengthSquared() < closestDistSq)
                            {
                                closestDistSq = posDiff.LengthSquared();
                                closestGridTri = tri;
                            }
                        }
                    }
                }
                ProfilerShort.End();

                if (closestGridTri != null)
                {
                    bool createLink = true;
                    var existingLinks = m_links.GetLinks(closestGridTri);
                    List<MyNavigationPrimitive> existingCellLinks = null;
                    m_voxelLinkDictionary.TryGetValue(cellId, out existingCellLinks);

                    if (existingLinks != null)
                    {
                        m_tmpNavPrims.Clear();
                        CollectClosePrimitives(addedPrimitive, m_tmpNavPrims, 2);
                        for (int i = 0; i < m_tmpNavPrims.Count; ++i)
                        {
                            if (existingLinks.Contains(m_tmpNavPrims[i]) && existingCellLinks != null && existingCellLinks.Contains(m_tmpNavPrims[i]))
                            {
                                double existingDistSq = (m_tmpNavPrims[i].WorldPosition - closestGridTri.WorldPosition).LengthSquared();
                                if (existingDistSq < closestDistSq)
                                {
                                    createLink = false;
                                    break;
                                }
                                else
                                {
                                    m_links.RemoveLink(closestGridTri, m_tmpNavPrims[i]);
                                    if (m_links.GetLinkCount(m_tmpNavPrims[i]) == 0)
                                    {
                                        RemoveVoxelLinkFromDictionary(cellId, m_tmpNavPrims[i]);
                                    }
                                    DecreaseGridLinkCounter(candidate);
                                    continue;
                                }
                            }
                        }
                        m_tmpNavPrims.Clear();
                    }

                    if (createLink)
                    {
                        m_links.AddLink(addedPrimitive, closestGridTri);
                        SaveVoxelLinkToDictionary(cellId, addedPrimitive);
                        IncreaseGridLinkCounter(candidate);
                    }
                }

                m_tmpNavTris.Clear();
            }

            ProfilerShort.End();
        }
        public void AddComponentTriangle(MyNavigationTriangle triangle, Vector3 center)
        {
            Debug.Assert(m_componentOpen, "Adding a triangle to a component in TriangleComponentMapping, when no component is open!");

            int triIndex = triangle.Index;

            MyIntervalList triList = m_components[m_componentNum];
            triList.Add(triIndex);

            float t = 1.0f / triList.Count;
            m_lastCellComponentCenters[m_componentNum] = center * t + m_lastCellComponentCenters[m_componentNum] * (1.0f - t);
        }
        public void RegisterTriangle(MyNavigationTriangle tri, ref Vector3I gridPos)
        {
            Debug.Assert(m_grid == null, "Triangles can be registered in the grid navigation mesh from the outside only if it's a mesh for block navigation definition!");
            if (m_grid != null)
            {
                return;
            }

            RegisterTriangleInternal(tri, ref gridPos);
        }