示例#1
0
 public bool ContainsPoint(TriangleMeshNode node, Vector3 pos)
 {
     if (VectorMath.IsClockwiseXZ((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], pos) &&
         VectorMath.IsClockwiseXZ((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], pos) &&
         VectorMath.IsClockwiseXZ((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], pos))
     {
         return(true);
     }
     return(false);
 }
示例#2
0
        void CalculateMeshContour()
        {
            if (mesh == null)
            {
                return;
            }

            edges.Clear();
            pointers.Clear();

            Vector3[] verts = mesh.vertices;
            int[]     tris  = mesh.triangles;
            for (int i = 0; i < tris.Length; i += 3)
            {
                // Make sure it is clockwise
                if (VectorMath.IsClockwiseXZ(verts[tris[i + 0]], verts[tris[i + 1]], verts[tris[i + 2]]))
                {
                    int tmp = tris[i + 0];
                    tris[i + 0] = tris[i + 2];
                    tris[i + 2] = tmp;
                }

                edges[new Int2(tris[i + 0], tris[i + 1])] = i;
                edges[new Int2(tris[i + 1], tris[i + 2])] = i;
                edges[new Int2(tris[i + 2], tris[i + 0])] = i;
            }

            // Construct a list of pointers along all edges
            for (int i = 0; i < tris.Length; i += 3)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (!edges.ContainsKey(new Int2(tris[i + ((j + 1) % 3)], tris[i + ((j + 0) % 3)])))
                    {
                        pointers[tris[i + ((j + 0) % 3)]] = tris[i + ((j + 1) % 3)];
                    }
                }
            }

            var contourBuffer = new List <Vector3[]>();

            List <Vector3> buffer = Pathfinding.Util.ListPool <Vector3> .Claim();

            // Follow edge pointers to generate the contours
            for (int i = 0; i < verts.Length; i++)
            {
                if (pointers.ContainsKey(i))
                {
                    buffer.Clear();

                    int s = i;
                    do
                    {
                        int tmp = pointers[s];

                        //This path has been taken before
                        if (tmp == -1)
                        {
                            break;
                        }

                        pointers[s] = -1;
                        buffer.Add(verts[s]);
                        s = tmp;

                        if (s == -1)
                        {
                            Debug.LogError("Invalid Mesh '" + mesh.name + " in " + gameObject.name);
                            break;
                        }
                    } while (s != i);

                    if (buffer.Count > 0)
                    {
                        contourBuffer.Add(buffer.ToArray());
                    }
                }
            }

            // Return lists to the pool
            Pathfinding.Util.ListPool <Vector3> .Release(buffer);

            contours = contourBuffer.ToArray();
        }
示例#3
0
 public static bool IsClockwise(Vector3 a, Vector3 b, Vector3 c)
 {
     return(VectorMath.IsClockwiseXZ(a, b, c));
 }
示例#4
0
 public static bool IsClockwise(Int3 a, Int3 b, Int3 c)
 {
     return(VectorMath.IsClockwiseXZ(a, b, c));
 }
示例#5
0
        /** Calculate a funnel path from the \a left and \a right portal lists.
         * The result will be appended to \a funnelPath
         */
        public static bool RunFunnel(List <Vector3> left, List <Vector3> right, List <Vector3> funnelPath)
        {
            if (left == null)
            {
                throw new System.ArgumentNullException("left");
            }
            if (right == null)
            {
                throw new System.ArgumentNullException("right");
            }
            if (funnelPath == null)
            {
                throw new System.ArgumentNullException("funnelPath");
            }

            if (left.Count != right.Count)
            {
                throw new System.ArgumentException("left and right lists must have equal length");
            }

            if (left.Count < 3)
            {
                return(false);
            }

            //Remove identical vertices
            while (left[1] == left[2] && right[1] == right[2])
            {
                //System.Console.WriteLine ("Removing identical left and right");
                left.RemoveAt(1);
                right.RemoveAt(1);

                if (left.Count <= 3)
                {
                    return(false);
                }
            }

            Vector3 swPoint = left[2];

            if (swPoint == left[1])
            {
                swPoint = right[2];
            }

            //Test
            while (VectorMath.IsColinearXZ(left[0], left[1], right[1]) || VectorMath.RightOrColinearXZ(left[1], right[1], swPoint) == VectorMath.RightOrColinearXZ(left[1], right[1], left[0]))
            {
        #if ASTARDEBUG
                Debug.DrawLine(left[1], right[1], new Color(0, 0, 0, 0.5F));
                Debug.DrawLine(left[0], swPoint, new Color(0, 0, 0, 0.5F));
        #endif
                left.RemoveAt(1);
                right.RemoveAt(1);

                if (left.Count <= 3)
                {
                    return(false);
                }

                swPoint = left[2];
                if (swPoint == left[1])
                {
                    swPoint = right[2];
                }
            }

            //Switch left and right to really be on the "left" and "right" sides
            /** \todo The colinear check should not be needed */
            if (!VectorMath.IsClockwiseXZ(left[0], left[1], right[1]) && !VectorMath.IsColinearXZ(left[0], left[1], right[1]))
            {
                //System.Console.WriteLine ("Wrong Side 2");
                List <Vector3> tmp = left;
                left  = right;
                right = tmp;
            }

                        #if ASTARDEBUG
            for (int i = 0; i < left.Count - 1; i++)
            {
                Debug.DrawLine(left[i], left[i + 1], Color.red);
                Debug.DrawLine(right[i], right[i + 1], Color.magenta);
                Debug.DrawRay(right[i], Vector3.up, Color.magenta);
            }
            for (int i = 0; i < left.Count; i++)
            {
                //Debug.DrawLine (right[i],left[i], Color.cyan);
            }
                        #endif

            funnelPath.Add(left[0]);

            Vector3 portalApex  = left[0];
            Vector3 portalLeft  = left[1];
            Vector3 portalRight = right[1];

            int apexIndex  = 0;
            int rightIndex = 1;
            int leftIndex  = 1;

            for (int i = 2; i < left.Count; i++)
            {
                if (funnelPath.Count > 2000)
                {
                    Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths.");
                    break;
                }

                Vector3 pLeft  = left[i];
                Vector3 pRight = right[i];

                /*Debug.DrawLine (portalApex,portalLeft,Color.red);
                 * Debug.DrawLine (portalApex,portalRight,Color.yellow);
                 * Debug.DrawLine (portalApex,left,Color.cyan);
                 * Debug.DrawLine (portalApex,right,Color.cyan);*/

                if (VectorMath.SignedTriangleAreaTimes2XZ(portalApex, portalRight, pRight) >= 0)
                {
                    if (portalApex == portalRight || VectorMath.SignedTriangleAreaTimes2XZ(portalApex, portalLeft, pRight) <= 0)
                    {
                        portalRight = pRight;
                        rightIndex  = i;
                    }
                    else
                    {
                        funnelPath.Add(portalLeft);
                        portalApex = portalLeft;
                        apexIndex  = leftIndex;

                        portalLeft  = portalApex;
                        portalRight = portalApex;

                        leftIndex  = apexIndex;
                        rightIndex = apexIndex;

                        i = apexIndex;

                        continue;
                    }
                }

                if (VectorMath.SignedTriangleAreaTimes2XZ(portalApex, portalLeft, pLeft) <= 0)
                {
                    if (portalApex == portalLeft || VectorMath.SignedTriangleAreaTimes2XZ(portalApex, portalRight, pLeft) >= 0)
                    {
                        portalLeft = pLeft;
                        leftIndex  = i;
                    }
                    else
                    {
                        funnelPath.Add(portalRight);
                        portalApex = portalRight;
                        apexIndex  = rightIndex;

                        portalLeft  = portalApex;
                        portalRight = portalApex;

                        leftIndex  = apexIndex;
                        rightIndex = apexIndex;

                        i = apexIndex;

                        continue;
                    }
                }
            }

            funnelPath.Add(left[left.Count - 1]);
            return(true);
        }
示例#6
0
        /** Generates a navmesh. Based on the supplied vertices and triangles */
        void GenerateNodes(Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices)
        {
            Profiler.BeginSample("Init");

            if (vectorVertices.Length == 0 || triangles.Length == 0)
            {
                originalVertices = vectorVertices;
                vertices         = new Int3[0];
                nodes            = new TriangleMeshNode[0];
                return;
            }

            vertices = new Int3[vectorVertices.Length];

            int c = 0;

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = (Int3)matrix.MultiplyPoint3x4(vectorVertices[i]);
            }

            var hashedVerts = new Dictionary <Int3, int>();

            var newVertices = new int[vertices.Length];

            Profiler.EndSample();
            Profiler.BeginSample("Hashing");

            for (int i = 0; i < vertices.Length; i++)
            {
                if (!hashedVerts.ContainsKey(vertices[i]))
                {
                    newVertices[c] = i;
                    hashedVerts.Add(vertices[i], c);
                    c++;
                }
            }

            for (int x = 0; x < triangles.Length; x++)
            {
                Int3 vertex = vertices[triangles[x]];

                triangles[x] = hashedVerts[vertex];
            }

            Int3[] totalIntVertices = vertices;
            vertices         = new Int3[c];
            originalVertices = new Vector3[c];
            for (int i = 0; i < c; i++)
            {
                vertices[i]         = totalIntVertices[newVertices[i]];
                originalVertices[i] = vectorVertices[newVertices[i]];
            }

            Profiler.EndSample();
            Profiler.BeginSample("Constructing Nodes");

            nodes = new TriangleMeshNode[triangles.Length / 3];

            int graphIndex = active.astarData.GetGraphIndex(this);

            // Does not have to set this, it is set in ScanInternal
            //TriangleMeshNode.SetNavmeshHolder ((int)graphIndex,this);

            for (int i = 0; i < nodes.Length; i++)
            {
                nodes[i] = new TriangleMeshNode(active);
                TriangleMeshNode node = nodes[i];                //new MeshNode ();

                node.GraphIndex = (uint)graphIndex;
                node.Penalty    = initialPenalty;
                node.Walkable   = true;


                node.v0 = triangles[i * 3];
                node.v1 = triangles[i * 3 + 1];
                node.v2 = triangles[i * 3 + 2];

                if (!VectorMath.IsClockwiseXZ(vertices[node.v0], vertices[node.v1], vertices[node.v2]))
                {
                    //Debug.DrawLine (vertices[node.v0],vertices[node.v1],Color.red);
                    //Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.red);
                    //Debug.DrawLine (vertices[node.v2],vertices[node.v0],Color.red);

                    int tmp = node.v0;
                    node.v0 = node.v2;
                    node.v2 = tmp;
                }

                if (VectorMath.IsColinearXZ(vertices[node.v0], vertices[node.v1], vertices[node.v2]))
                {
                    Debug.DrawLine((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], Color.red);
                    Debug.DrawLine((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], Color.red);
                    Debug.DrawLine((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], Color.red);
                }

                // Make sure position is correctly set
                node.UpdatePositionFromVertices();
            }

            Profiler.EndSample();

            var sides = new Dictionary <Int2, TriangleMeshNode>();

            for (int i = 0, j = 0; i < triangles.Length; j += 1, i += 3)
            {
                sides[new Int2(triangles[i + 0], triangles[i + 1])] = nodes[j];
                sides[new Int2(triangles[i + 1], triangles[i + 2])] = nodes[j];
                sides[new Int2(triangles[i + 2], triangles[i + 0])] = nodes[j];
            }

            Profiler.BeginSample("Connecting Nodes");

            var connections     = new List <MeshNode>();
            var connectionCosts = new List <uint>();

            for (int i = 0, j = 0; i < triangles.Length; j += 1, i += 3)
            {
                connections.Clear();
                connectionCosts.Clear();

                TriangleMeshNode node = nodes[j];

                for (int q = 0; q < 3; q++)
                {
                    TriangleMeshNode other;
                    if (sides.TryGetValue(new Int2(triangles[i + ((q + 1) % 3)], triangles[i + q]), out other))
                    {
                        connections.Add(other);
                        connectionCosts.Add((uint)(node.position - other.position).costMagnitude);
                    }
                }

                node.connections     = connections.ToArray();
                node.connectionCosts = connectionCosts.ToArray();
            }

            Profiler.EndSample();
            Profiler.BeginSample("Rebuilding BBTree");

            RebuildBBTree(this);

            Profiler.EndSample();

#if ASTARDEBUG
            for (int i = 0; i < nodes.Length; i++)
            {
                TriangleMeshNode node = nodes[i] as TriangleMeshNode;

                float a1 = VectorMath.SignedTriangleAreaTimes2XZ((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], (Vector3)vertices[node.v2]);

                long a2 = VectorMath.SignedTriangleAreaTimes2XZ(vertices[node.v0], vertices[node.v1], vertices[node.v2]);
                if (a1 * a2 < 0)
                {
                    Debug.LogError(a1 + " " + a2);
                }


                if (VectorMath.IsClockwiseXZ(vertices[node.v0], vertices[node.v1], vertices[node.v2]))
                {
                    Debug.DrawLine((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], Color.green);
                    Debug.DrawLine((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], Color.green);
                    Debug.DrawLine((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], Color.green);
                }
                else
                {
                    Debug.DrawLine((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], Color.red);
                    Debug.DrawLine((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], Color.red);
                    Debug.DrawLine((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], Color.red);
                }
            }
#endif
        }
示例#7
0
 private void GenerateNodes(Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices)
 {
     if ((vectorVertices.Length == 0) || (triangles.Length == 0))
     {
         originalVertices = vectorVertices;
         vertices         = new Int3[0];
         this.nodes       = new TriangleMeshNode[0];
     }
     else
     {
         vertices = new Int3[vectorVertices.Length];
         int index = 0;
         for (int i = 0; i < vertices.Length; i++)
         {
             vertices[i] = (Int3)this.matrix.MultiplyPoint3x4(vectorVertices[i]);
         }
         Dictionary <Int3, int> dictionary = new Dictionary <Int3, int>();
         int[] numArray = new int[vertices.Length];
         for (int j = 0; j < vertices.Length; j++)
         {
             if (!dictionary.ContainsKey(vertices[j]))
             {
                 numArray[index] = j;
                 dictionary.Add(vertices[j], index);
                 index++;
             }
         }
         for (int k = 0; k < triangles.Length; k++)
         {
             Int3 num5 = vertices[triangles[k]];
             triangles[k] = dictionary[num5];
         }
         Int3[] numArray2 = vertices;
         vertices         = new Int3[index];
         originalVertices = new Vector3[index];
         for (int m = 0; m < index; m++)
         {
             vertices[m]         = numArray2[numArray[m]];
             originalVertices[m] = vectorVertices[numArray[m]];
         }
         this.nodes = new TriangleMeshNode[triangles.Length / 3];
         int graphIndex = base.active.astarData.GetGraphIndex(this);
         for (int n = 0; n < this.nodes.Length; n++)
         {
             this.nodes[n] = new TriangleMeshNode(base.active);
             TriangleMeshNode node = this.nodes[n];
             node.GraphIndex = (uint)graphIndex;
             node.Penalty    = base.initialPenalty;
             node.Walkable   = true;
             node.v0         = triangles[n * 3];
             node.v1         = triangles[(n * 3) + 1];
             node.v2         = triangles[(n * 3) + 2];
             if (!VectorMath.IsClockwiseXZ(vertices[node.v0], vertices[node.v1], vertices[node.v2]))
             {
                 int num9 = node.v0;
                 node.v0 = node.v2;
                 node.v2 = num9;
             }
             if (VectorMath.IsColinearXZ(vertices[node.v0], vertices[node.v1], vertices[node.v2]))
             {
                 UnityEngine.Debug.DrawLine((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], Color.red);
                 UnityEngine.Debug.DrawLine((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], Color.red);
                 UnityEngine.Debug.DrawLine((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], Color.red);
             }
             node.UpdatePositionFromVertices();
         }
         Dictionary <Int2, TriangleMeshNode> dictionary2 = new Dictionary <Int2, TriangleMeshNode>();
         int num10 = 0;
         int num11 = 0;
         while (num10 < triangles.Length)
         {
             dictionary2[new Int2(triangles[num10], triangles[num10 + 1])]     = this.nodes[num11];
             dictionary2[new Int2(triangles[num10 + 1], triangles[num10 + 2])] = this.nodes[num11];
             dictionary2[new Int2(triangles[num10 + 2], triangles[num10])]     = this.nodes[num11];
             num11++;
             num10 += 3;
         }
         List <MeshNode> list  = new List <MeshNode>();
         List <uint>     list2 = new List <uint>();
         int             num12 = 0;
         int             num13 = 0;
         while (num12 < triangles.Length)
         {
             list.Clear();
             list2.Clear();
             TriangleMeshNode node2 = this.nodes[num13];
             for (int num14 = 0; num14 < 3; num14++)
             {
                 TriangleMeshNode node3;
                 if (dictionary2.TryGetValue(new Int2(triangles[num12 + ((num14 + 1) % 3)], triangles[num12 + num14]), out node3))
                 {
                     list.Add(node3);
                     Int3 num15 = node2.position - node3.position;
                     list2.Add((uint)num15.costMagnitude);
                 }
             }
             node2.connections     = list.ToArray();
             node2.connectionCosts = list2.ToArray();
             num13++;
             num12 += 3;
         }
         RebuildBBTree(this);
     }
 }
示例#8
0
        private void CalculateMeshContour()
        {
            if (this.mesh == null)
            {
                return;
            }
            NavmeshCut.edges.Clear();
            NavmeshCut.pointers.Clear();
            Vector3[] vertices  = this.mesh.vertices;
            int[]     triangles = this.mesh.triangles;
            for (int i = 0; i < triangles.Length; i += 3)
            {
                if (VectorMath.IsClockwiseXZ(vertices[triangles[i]], vertices[triangles[i + 1]], vertices[triangles[i + 2]]))
                {
                    int num = triangles[i];
                    triangles[i]     = triangles[i + 2];
                    triangles[i + 2] = num;
                }
                NavmeshCut.edges[new Int2(triangles[i], triangles[i + 1])]     = i;
                NavmeshCut.edges[new Int2(triangles[i + 1], triangles[i + 2])] = i;
                NavmeshCut.edges[new Int2(triangles[i + 2], triangles[i])]     = i;
            }
            for (int j = 0; j < triangles.Length; j += 3)
            {
                for (int k = 0; k < 3; k++)
                {
                    if (!NavmeshCut.edges.ContainsKey(new Int2(triangles[j + (k + 1) % 3], triangles[j + k % 3])))
                    {
                        NavmeshCut.pointers[triangles[j + k % 3]] = triangles[j + (k + 1) % 3];
                    }
                }
            }
            List <Vector3[]> list  = new List <Vector3[]>();
            List <Vector3>   list2 = ListPool <Vector3> .Claim();

            for (int l = 0; l < vertices.Length; l++)
            {
                if (NavmeshCut.pointers.ContainsKey(l))
                {
                    list2.Clear();
                    int num2 = l;
                    do
                    {
                        int num3 = NavmeshCut.pointers[num2];
                        if (num3 == -1)
                        {
                            break;
                        }
                        NavmeshCut.pointers[num2] = -1;
                        list2.Add(vertices[num2]);
                        num2 = num3;
                        if (num2 == -1)
                        {
                            goto Block_9;
                        }
                    }while (num2 != l);
IL_20C:
                    if (list2.Count > 0)
                    {
                        list.Add(list2.ToArray());
                        goto IL_227;
                    }
                    goto IL_227;
Block_9:
                    Debug.LogError("Invalid Mesh '" + this.mesh.name + " in " + base.gameObject.name);
                    goto IL_20C;
                }
                IL_227 :;
            }
            ListPool <Vector3> .Release(list2);

            this.contours = list.ToArray();
        }
示例#9
0
        public bool RunFunnel(List <VInt3> left, List <VInt3> right, List <VInt3> funnelPath)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }
            if (funnelPath == null)
            {
                throw new ArgumentNullException("funnelPath");
            }
            if (left.Count != right.Count)
            {
                throw new ArgumentException("left and right lists must have equal length");
            }
            if (left.Count <= 3)
            {
                return(false);
            }
            while ((left[1] == left[2]) && (right[1] == right[2]))
            {
                left.RemoveAt(1);
                right.RemoveAt(1);
                if (left.Count <= 3)
                {
                    return(false);
                }
            }
            VInt3 c = left[2];

            if (c == left[1])
            {
                c = right[2];
            }
            while (VectorMath.IsColinearXZ(left[0], left[1], right[1]) || (VectorMath.RightOrColinearXZ(left[1], right[1], c) == VectorMath.RightOrColinearXZ(left[1], right[1], left[0])))
            {
                left.RemoveAt(1);
                right.RemoveAt(1);
                if (left.Count <= 3)
                {
                    return(false);
                }
                c = left[2];
                if (c == left[1])
                {
                    c = right[2];
                }
            }
            if (!VectorMath.IsClockwiseXZ(left[0], left[1], right[1]) && !VectorMath.IsColinearXZ(left[0], left[1], right[1]))
            {
                List <VInt3> list = left;
                left  = right;
                right = list;
            }
            funnelPath.Add(left[0]);
            VInt3 a    = left[0];
            VInt3 b    = left[1];
            VInt3 num4 = right[1];
            int   num5 = 0;
            int   num6 = 1;
            int   num7 = 1;

            for (int i = 2; i < left.Count; i++)
            {
                if (funnelPath.Count > 0x7d0)
                {
                    Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths.");
                    break;
                }
                VInt3 num9  = left[i];
                VInt3 num10 = right[i];
                if (VectorMath.SignedTriangleAreaTimes2XZ(a, num4, num10) >= 0L)
                {
                    if ((a == num4) || (VectorMath.SignedTriangleAreaTimes2XZ(a, b, num10) <= 0L))
                    {
                        num4 = num10;
                        num6 = i;
                    }
                    else
                    {
                        funnelPath.Add(b);
                        a    = b;
                        num5 = num7;
                        b    = a;
                        num4 = a;
                        num7 = num5;
                        num6 = num5;
                        i    = num5;
                        continue;
                    }
                }
                if (VectorMath.SignedTriangleAreaTimes2XZ(a, b, num9) <= 0L)
                {
                    if ((a == b) || (VectorMath.SignedTriangleAreaTimes2XZ(a, num4, num9) >= 0L))
                    {
                        b    = num9;
                        num7 = i;
                    }
                    else
                    {
                        funnelPath.Add(num4);
                        a    = num4;
                        num5 = num6;
                        b    = a;
                        num4 = a;
                        num7 = num5;
                        num6 = num5;
                        i    = num5;
                    }
                }
            }
            funnelPath.Add(left[left.Count - 1]);
            return(true);
        }
示例#10
0
 public bool ContainsPoint(TriangleMeshNode node, Vector3 pos)
 {
     return((VectorMath.IsClockwiseXZ((Vector3)this.vertices[node.v0], (Vector3)this.vertices[node.v1], pos) && VectorMath.IsClockwiseXZ((Vector3)this.vertices[node.v1], (Vector3)this.vertices[node.v2], pos)) && VectorMath.IsClockwiseXZ((Vector3)this.vertices[node.v2], (Vector3)this.vertices[node.v0], pos));
 }
示例#11
0
		public static bool RunFunnel(List<Vector3> left, List<Vector3> right, List<Vector3> funnelPath)
		{
			if (left == null)
			{
				throw new ArgumentNullException("left");
			}
			if (right == null)
			{
				throw new ArgumentNullException("right");
			}
			if (funnelPath == null)
			{
				throw new ArgumentNullException("funnelPath");
			}
			if (left.Count != right.Count)
			{
				throw new ArgumentException("left and right lists must have equal length");
			}
			if (left.Count < 3)
			{
				return false;
			}
			while (left[1] == left[2] && right[1] == right[2])
			{
				left.RemoveAt(1);
				right.RemoveAt(1);
				if (left.Count <= 3)
				{
					return false;
				}
			}
			Vector3 vector = left[2];
			if (vector == left[1])
			{
				vector = right[2];
			}
			while (VectorMath.IsColinearXZ(left[0], left[1], right[1]) || VectorMath.RightOrColinearXZ(left[1], right[1], vector) == VectorMath.RightOrColinearXZ(left[1], right[1], left[0]))
			{
				left.RemoveAt(1);
				right.RemoveAt(1);
				if (left.Count <= 3)
				{
					return false;
				}
				vector = left[2];
				if (vector == left[1])
				{
					vector = right[2];
				}
			}
			if (!VectorMath.IsClockwiseXZ(left[0], left[1], right[1]) && !VectorMath.IsColinearXZ(left[0], left[1], right[1]))
			{
				List<Vector3> list = left;
				left = right;
				right = list;
			}
			funnelPath.Add(left[0]);
			Vector3 vector2 = left[0];
			Vector3 vector3 = left[1];
			Vector3 vector4 = right[1];
			int num = 1;
			int num2 = 1;
			int i = 2;
			while (i < left.Count)
			{
				if (funnelPath.Count > 2000)
				{
					Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths.");
					break;
				}
				Vector3 vector5 = left[i];
				Vector3 vector6 = right[i];
				if (VectorMath.SignedTriangleAreaTimes2XZ(vector2, vector4, vector6) < 0f)
				{
					goto IL_279;
				}
				if (vector2 == vector4 || VectorMath.SignedTriangleAreaTimes2XZ(vector2, vector3, vector6) <= 0f)
				{
					vector4 = vector6;
					num = i;
					goto IL_279;
				}
				funnelPath.Add(vector3);
				vector2 = vector3;
				int num3 = num2;
				vector3 = vector2;
				vector4 = vector2;
				num2 = num3;
				num = num3;
				i = num3;
				IL_2DD:
				i++;
				continue;
				IL_279:
				if (VectorMath.SignedTriangleAreaTimes2XZ(vector2, vector3, vector5) > 0f)
				{
					goto IL_2DD;
				}
				if (vector2 == vector3 || VectorMath.SignedTriangleAreaTimes2XZ(vector2, vector4, vector5) >= 0f)
				{
					vector3 = vector5;
					num2 = i;
					goto IL_2DD;
				}
				funnelPath.Add(vector4);
				vector2 = vector4;
				num3 = num;
				vector3 = vector2;
				vector4 = vector2;
				num2 = num3;
				num = num3;
				i = num3;
				goto IL_2DD;
			}
			funnelPath.Add(left[left.Count - 1]);
			return true;
		}
示例#12
0
        protected NavmeshTile CreateTile(int[] tris, Int3[] verts, int x, int z)
        {
#if BNICKSON_UPDATED
            if (tris == null)
            {
                throw new System.ArgumentNullException("The mesh must be valid. tris is null.");
            }
            if (verts == null)
            {
                throw new System.ArgumentNullException("The mesh must be valid. verts is null.");
            }

            //Create a new navmesh tile and assign its settings
            var tile = new NavmeshTile();

            tile.x      = x;
            tile.z      = z;
            tile.w      = 1;
            tile.d      = 1;
            tile.tris   = tris;
            tile.verts  = verts;
            tile.bbTree = new BBTree();
#endif

            if (tile.tris.Length % 3 != 0)
            {
                throw new System.ArgumentException("Indices array's length must be a multiple of 3 (mesh.tris)");
            }

            if (tile.verts.Length >= VertexIndexMask)
            {
                throw new System.ArgumentException("Too many vertices per tile (more than " + VertexIndexMask + ")." +
                                                   "\nTry enabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* Inspector");
            }

            //Dictionary<Int3, int> firstVerts = new Dictionary<Int3, int> ();
            Dictionary <Int3, int> firstVerts = cachedInt3_int_dict;
            firstVerts.Clear();

            var compressedPointers = new int[tile.verts.Length];

            int count = 0;
            for (int i = 0; i < tile.verts.Length; i++)
            {
                try
                {
                    firstVerts.Add(tile.verts[i], count);
                    compressedPointers[i] = count;
                    tile.verts[count]     = tile.verts[i];
                    count++;
                }
                catch
                {
                    //There are some cases, rare but still there, that vertices are identical
                    compressedPointers[i] = firstVerts[tile.verts[i]];
                }
            }

            for (int i = 0; i < tile.tris.Length; i++)
            {
                tile.tris[i] = compressedPointers[tile.tris[i]];
            }

            var compressed = new Int3[count];
            for (int i = 0; i < count; i++)
            {
                compressed[i] = tile.verts[i];
            }

            tile.verts = compressed;

            var nodes = new TriangleMeshNode[tile.tris.Length / 3];
            tile.nodes = nodes;

            //Here we are faking a new graph
            //The tile is not added to any graphs yet, but to get the position querys from the nodes
            //to work correctly (not throw exceptions because the tile is not calculated) we fake a new graph
            //and direct the position queries directly to the tile
            int graphIndex = AstarPath.active.astarData.graphs.Length;

            TriangleMeshNode.SetNavmeshHolder(graphIndex, tile);

            //This index will be ORed to the triangle indices
            int tileIndex = x + z * tileXCount;
            tileIndex <<= TileIndexOffset;

            //Create nodes and assign triangle indices
            for (int i = 0; i < nodes.Length; i++)
            {
                var node = new TriangleMeshNode(active);
                nodes[i]        = node;
                node.GraphIndex = (uint)graphIndex;
                node.v0         = tile.tris[i * 3 + 0] | tileIndex;
                node.v1         = tile.tris[i * 3 + 1] | tileIndex;
                node.v2         = tile.tris[i * 3 + 2] | tileIndex;

                //Degenerate triangles might occur, but they will not cause any large troubles anymore
                //if (Polygon.IsColinear (node.GetVertex(0), node.GetVertex(1), node.GetVertex(2))) {
                //	Debug.Log ("COLINEAR!!!!!!");
                //}

                //Make sure the triangle is clockwise
                if (!VectorMath.IsClockwiseXZ(node.GetVertex(0), node.GetVertex(1), node.GetVertex(2)))
                {
                    int tmp = node.v0;
                    node.v0 = node.v2;
                    node.v2 = tmp;
                }

                node.Walkable = true;
                node.Penalty  = initialPenalty;
                node.UpdatePositionFromVertices();
                tile.bbTree.Insert(node);
            }

            CreateNodeConnections(tile.nodes);

            //Remove the fake graph
            TriangleMeshNode.SetNavmeshHolder(graphIndex, null);

            return(tile);
        }
示例#13
0
        private void CalculateMeshContour()
        {
            if (this.mesh != null)
            {
                edges.Clear();
                pointers.Clear();
                Vector3[] vertices  = this.mesh.vertices;
                int[]     triangles = this.mesh.triangles;
                for (int i = 0; i < triangles.Length; i += 3)
                {
                    if (VectorMath.IsClockwiseXZ(vertices[triangles[i]], vertices[triangles[i + 1]], vertices[triangles[i + 2]]))
                    {
                        int num2 = triangles[i];
                        triangles[i]     = triangles[i + 2];
                        triangles[i + 2] = num2;
                    }
                    edges[new Int2(triangles[i], triangles[i + 1])]     = i;
                    edges[new Int2(triangles[i + 1], triangles[i + 2])] = i;
                    edges[new Int2(triangles[i + 2], triangles[i])]     = i;
                }
                for (int j = 0; j < triangles.Length; j += 3)
                {
                    for (int m = 0; m < 3; m++)
                    {
                        if (!edges.ContainsKey(new Int2(triangles[j + ((m + 1) % 3)], triangles[j + (m % 3)])))
                        {
                            pointers[triangles[j + (m % 3)]] = triangles[j + ((m + 1) % 3)];
                        }
                    }
                }
                List <Vector3[]> list  = new List <Vector3[]>();
                List <Vector3>   list2 = ListPool <Vector3> .Claim();

                for (int k = 0; k < vertices.Length; k++)
                {
                    if (!pointers.ContainsKey(k))
                    {
                        continue;
                    }
                    list2.Clear();
                    int index = k;
                    do
                    {
                        int num7 = pointers[index];
                        if (num7 == -1)
                        {
                            break;
                        }
                        pointers[index] = -1;
                        list2.Add(vertices[index]);
                        switch (num7)
                        {
                        case -1:
                            Debug.LogError("Invalid Mesh '" + this.mesh.name + " in " + base.gameObject.name);
                            break;
                        }
                    }while (index != k);
                    if (list2.Count > 0)
                    {
                        list.Add(list2.ToArray());
                    }
                }
                ListPool <Vector3> .Release(list2);

                this.contours = list.ToArray();
            }
        }
示例#14
0
        private void GenerateNodes(Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices)
        {
            if (vectorVertices.Length == 0 || triangles.Length == 0)
            {
                originalVertices = vectorVertices;
                vertices         = new Int3[0];
                this.nodes       = new TriangleMeshNode[0];
                return;
            }
            vertices = new Int3[vectorVertices.Length];
            int num = 0;

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = (Int3)this.matrix.MultiplyPoint3x4(vectorVertices[i]);
            }
            Dictionary <Int3, int> dictionary = new Dictionary <Int3, int>();

            int[] array = new int[vertices.Length];
            for (int j = 0; j < vertices.Length; j++)
            {
                if (!dictionary.ContainsKey(vertices[j]))
                {
                    array[num] = j;
                    dictionary.Add(vertices[j], num);
                    num++;
                }
            }
            for (int k = 0; k < triangles.Length; k++)
            {
                Int3 key = vertices[triangles[k]];
                triangles[k] = dictionary[key];
            }
            Int3[] array2 = vertices;
            vertices         = new Int3[num];
            originalVertices = new Vector3[num];
            for (int l = 0; l < num; l++)
            {
                vertices[l]         = array2[array[l]];
                originalVertices[l] = vectorVertices[array[l]];
            }
            this.nodes = new TriangleMeshNode[triangles.Length / 3];
            int graphIndex = this.active.astarData.GetGraphIndex(this);

            for (int m = 0; m < this.nodes.Length; m++)
            {
                this.nodes[m] = new TriangleMeshNode(this.active);
                TriangleMeshNode triangleMeshNode = this.nodes[m];
                triangleMeshNode.GraphIndex = (uint)graphIndex;
                triangleMeshNode.Penalty    = this.initialPenalty;
                triangleMeshNode.Walkable   = true;
                triangleMeshNode.v0         = triangles[m * 3];
                triangleMeshNode.v1         = triangles[m * 3 + 1];
                triangleMeshNode.v2         = triangles[m * 3 + 2];
                if (!VectorMath.IsClockwiseXZ(vertices[triangleMeshNode.v0], vertices[triangleMeshNode.v1], vertices[triangleMeshNode.v2]))
                {
                    int v = triangleMeshNode.v0;
                    triangleMeshNode.v0 = triangleMeshNode.v2;
                    triangleMeshNode.v2 = v;
                }
                if (VectorMath.IsColinearXZ(vertices[triangleMeshNode.v0], vertices[triangleMeshNode.v1], vertices[triangleMeshNode.v2]))
                {
                    Debug.DrawLine((Vector3)vertices[triangleMeshNode.v0], (Vector3)vertices[triangleMeshNode.v1], Color.red);
                    Debug.DrawLine((Vector3)vertices[triangleMeshNode.v1], (Vector3)vertices[triangleMeshNode.v2], Color.red);
                    Debug.DrawLine((Vector3)vertices[triangleMeshNode.v2], (Vector3)vertices[triangleMeshNode.v0], Color.red);
                }
                triangleMeshNode.UpdatePositionFromVertices();
            }
            Dictionary <Int2, TriangleMeshNode> dictionary2 = new Dictionary <Int2, TriangleMeshNode>();
            int n    = 0;
            int num2 = 0;

            while (n < triangles.Length)
            {
                dictionary2[new Int2(triangles[n], triangles[n + 1])]     = this.nodes[num2];
                dictionary2[new Int2(triangles[n + 1], triangles[n + 2])] = this.nodes[num2];
                dictionary2[new Int2(triangles[n + 2], triangles[n])]     = this.nodes[num2];
                num2++;
                n += 3;
            }
            List <MeshNode> list  = new List <MeshNode>();
            List <uint>     list2 = new List <uint>();
            int             num3  = 0;
            int             num4  = 0;

            while (num3 < triangles.Length)
            {
                list.Clear();
                list2.Clear();
                TriangleMeshNode triangleMeshNode2 = this.nodes[num4];
                for (int num5 = 0; num5 < 3; num5++)
                {
                    TriangleMeshNode triangleMeshNode3;
                    if (dictionary2.TryGetValue(new Int2(triangles[num3 + (num5 + 1) % 3], triangles[num3 + num5]), out triangleMeshNode3))
                    {
                        list.Add(triangleMeshNode3);
                        list2.Add((uint)(triangleMeshNode2.position - triangleMeshNode3.position).costMagnitude);
                    }
                }
                triangleMeshNode2.connections     = list.ToArray();
                triangleMeshNode2.connectionCosts = list2.ToArray();
                num4++;
                num3 += 3;
            }
            NavMeshGraph.RebuildBBTree(this);
        }
示例#15
0
        public static bool RunFunnel(List <Vector3> left, List <Vector3> right, List <Vector3> funnelPath)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }
            if (funnelPath == null)
            {
                throw new ArgumentNullException("funnelPath");
            }
            if (left.Count != right.Count)
            {
                throw new ArgumentException("left and right lists must have equal length");
            }
            if (left.Count <= 3)
            {
                return(false);
            }
            while ((left[1] == left[2]) && (right[1] == right[2]))
            {
                left.RemoveAt(1);
                right.RemoveAt(1);
                if (left.Count <= 3)
                {
                    return(false);
                }
            }
            Vector3 p = left[2];

            if (p == left[1])
            {
                p = right[2];
            }
            while (VectorMath.IsColinearXZ(left[0], left[1], right[1]) || (VectorMath.RightOrColinearXZ(left[1], right[1], p) == VectorMath.RightOrColinearXZ(left[1], right[1], left[0])))
            {
                left.RemoveAt(1);
                right.RemoveAt(1);
                if (left.Count <= 3)
                {
                    return(false);
                }
                p = left[2];
                if (p == left[1])
                {
                    p = right[2];
                }
            }
            if (!VectorMath.IsClockwiseXZ(left[0], left[1], right[1]) && !VectorMath.IsColinearXZ(left[0], left[1], right[1]))
            {
                List <Vector3> list = left;
                left  = right;
                right = list;
            }
            funnelPath.Add(left[0]);
            Vector3 a       = left[0];
            Vector3 b       = left[1];
            Vector3 vector4 = right[1];
            int     num     = 0;
            int     num2    = 1;
            int     num3    = 1;

            for (int i = 2; i < left.Count; i++)
            {
                if (funnelPath.Count > 0x7d0)
                {
                    Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths.");
                    break;
                }
                Vector3 c       = left[i];
                Vector3 vector6 = right[i];
                if (VectorMath.SignedTriangleAreaTimes2XZ(a, vector4, vector6) >= 0f)
                {
                    if ((a == vector4) || (VectorMath.SignedTriangleAreaTimes2XZ(a, b, vector6) <= 0f))
                    {
                        vector4 = vector6;
                        num2    = i;
                    }
                    else
                    {
                        funnelPath.Add(b);
                        a       = b;
                        num     = num3;
                        b       = a;
                        vector4 = a;
                        num3    = num;
                        num2    = num;
                        i       = num;
                        continue;
                    }
                }
                if (VectorMath.SignedTriangleAreaTimes2XZ(a, b, c) <= 0f)
                {
                    if ((a == b) || (VectorMath.SignedTriangleAreaTimes2XZ(a, vector4, c) >= 0f))
                    {
                        b    = c;
                        num3 = i;
                    }
                    else
                    {
                        funnelPath.Add(vector4);
                        a       = vector4;
                        num     = num2;
                        b       = a;
                        vector4 = a;
                        num3    = num;
                        num2    = num;
                        i       = num;
                    }
                }
            }
            funnelPath.Add(left[left.Count - 1]);
            return(true);
        }