示例#1
0
    public NavMeshVertex GetClosestVertex(int index, Vector3 pos)
    {
        NavMeshVertex retVertex    = null;
        float         shortestDist = Mathf.Infinity;

        if (index < 0)
        {
            // Check through all triangles
            foreach (var tri in nmg.allNavMeshTriangles)
            {
                float d1 = Vector3.Distance(tri.v0.point, pos);
                float d2 = Vector3.Distance(tri.v1.point, pos);
                float d3 = Vector3.Distance(tri.v2.point, pos);

                if (d1 < shortestDist)
                {
                    shortestDist = d1;
                    retVertex    = tri.v0;
                }

                if (d2 < shortestDist)
                {
                    shortestDist = d2;
                    retVertex    = tri.v1;
                }

                if (d3 < shortestDist)
                {
                    shortestDist = d3;
                    retVertex    = tri.v2;
                }
            }
        }
        else
        {
            NavmeshTriangle tri = nmg.allNavMeshTriangles[index];

            float d1 = Vector3.Distance(tri.v0.point, pos);
            float d2 = Vector3.Distance(tri.v1.point, pos);
            float d3 = Vector3.Distance(tri.v2.point, pos);

            shortestDist = d1;
            retVertex    = tri.v0;

            if (d2 < shortestDist)
            {
                shortestDist = d2;
                retVertex    = tri.v1;
            }

            if (d3 < shortestDist)
            {
                shortestDist = d3;
                retVertex    = tri.v2;
            }
        }

        return(retVertex);
    }
    public bool IsAdjacent(NavmeshTriangle triangle)
    {
        int commonEdge = 0;

        if (v0.id == triangle.v0.id || v0.id == triangle.v1.id || v0.id == triangle.v2.id)
        {
            ++commonEdge;
        }
        if (v1.id == triangle.v0.id || v1.id == triangle.v1.id || v1.id == triangle.v2.id)
        {
            ++commonEdge;
        }
        if (v2.id == triangle.v0.id || v2.id == triangle.v1.id || v2.id == triangle.v2.id)
        {
            ++commonEdge;
        }
        return(commonEdge == 2);
    }
示例#3
0
    public int GetClosestTriangleIndex(Vector3 point)
    {
        int   index            = -1;
        float shortestDistance = Mathf.Infinity;

        for (int i = 0; i < nmg.allNavMeshTriangles.Count; ++i)
        {
            NavmeshTriangle tri      = nmg.allNavMeshTriangles[i];
            Vector3         midPoint = (tri.v0.point + tri.v1.point + tri.v2.point) / 3;
            float           dist     = Vector3.Distance(midPoint, point);
            if (dist < shortestDistance)
            {
                shortestDistance = dist;
                index            = i;
            }
        }

        return(index);
    }
    void Triangulate(List <Vertex> vertices, ref GameObject[] obstacles)
    {
        vertices.Sort((a, b) => a.position.x.CompareTo(b.position.x));

        for (int i = 0; i < vertices.Count; ++i)
        {
            for (int j = i + 1; j < vertices.Count; ++j)
            {
                for (int k = j + 1; (k % vertices.Count) != i; ++k)
                {
                    Vertex v0      = vertices[i];
                    Vertex v1      = vertices[j % vertices.Count];
                    Vertex v2      = vertices[k % vertices.Count];
                    int    idxTri0 = v0.id;
                    int    idxTri1 = v1.id;
                    int    idxTri2 = v2.id;

                    Ray        ray0  = new Ray(v0.position, (v1.position - v0.position).normalized);
                    Ray        ray1  = new Ray(v1.position, (v2.position - v1.position).normalized);
                    Ray        ray2  = new Ray(v2.position, (v0.position - v2.position).normalized);
                    float      dist0 = (v1.position - v0.position).magnitude;
                    float      dist1 = (v2.position - v1.position).magnitude;
                    float      dist2 = (v0.position - v2.position).magnitude;
                    RaycastHit hitInfo;

                    bool skip = false;
                    foreach (GameObject obstacle in obstacles)
                    {
                        Collider collider = obstacle.GetComponent <Collider>();
                        if (!collider)
                        {
                            continue;
                        }

                        if (collider.Raycast(ray0, out hitInfo, dist0) ||
                            collider.Raycast(ray1, out hitInfo, dist1) ||
                            collider.Raycast(ray2, out hitInfo, dist2))
                        {
                            skip = true;
                            break;
                        }
                        else
                        {
                            Vector3 p0 = collider.ClosestPoint(v0.position);
                            Vector3 p1 = collider.ClosestPoint(v1.position);
                            Vector3 p2 = collider.ClosestPoint(v2.position);

                            if (IsPointInTriangle(v0.position, v1.position, v2.position, p0) ||
                                IsPointInTriangle(v0.position, v1.position, v2.position, p1) ||
                                IsPointInTriangle(v0.position, v1.position, v2.position, p2))
                            {
                                skip = true;
                                break;
                            }
                        }
                    }
                    if (skip)
                    {
                        continue;
                    }

                    if (!uniqueVertices[idxTri0].neighbours.ContainsKey(idxTri1))
                    {
                        uniqueVertices[idxTri0].neighbours.Add(idxTri1, v1);
                    }
                    if (!uniqueVertices[idxTri0].neighbours.ContainsKey(idxTri2))
                    {
                        uniqueVertices[idxTri0].neighbours.Add(idxTri2, v2);
                    }
                    if (!uniqueVertices[idxTri1].neighbours.ContainsKey(idxTri0))
                    {
                        uniqueVertices[idxTri1].neighbours.Add(idxTri0, v0);
                    }
                    if (!uniqueVertices[idxTri1].neighbours.ContainsKey(idxTri2))
                    {
                        uniqueVertices[idxTri1].neighbours.Add(idxTri2, v2);
                    }
                    if (!uniqueVertices[idxTri2].neighbours.ContainsKey(idxTri1))
                    {
                        uniqueVertices[idxTri2].neighbours.Add(idxTri1, v1);
                    }
                    if (!uniqueVertices[idxTri2].neighbours.ContainsKey(idxTri0))
                    {
                        uniqueVertices[idxTri2].neighbours.Add(idxTri0, v0);
                    }

                    NavMeshVertex nv0, nv1, nv2;
                    if (!uniqueNavmeshVertices.ContainsKey(idxTri0))
                    {
                        nv0        = new NavMeshVertex();
                        nv0.id     = v0.id;
                        nv0.point  = v0.position;
                        nv0.normal = v0.normal;
                        uniqueNavmeshVertices.Add(idxTri0, nv0);
                    }
                    else
                    {
                        nv0 = uniqueNavmeshVertices[idxTri0];
                    }
                    if (!uniqueNavmeshVertices.ContainsKey(idxTri1))
                    {
                        nv1        = new NavMeshVertex();
                        nv1.id     = v1.id;
                        nv1.point  = v1.position;
                        nv1.normal = v1.normal;
                        uniqueNavmeshVertices.Add(idxTri1, nv1);
                    }
                    else
                    {
                        nv1 = uniqueNavmeshVertices[idxTri1];
                    }
                    if (!uniqueNavmeshVertices.ContainsKey(idxTri2))
                    {
                        nv2        = new NavMeshVertex();
                        nv2.id     = v2.id;
                        nv2.point  = v2.position;
                        nv2.normal = v2.normal;
                        uniqueNavmeshVertices.Add(idxTri2, nv2);
                    }
                    else
                    {
                        nv2 = uniqueNavmeshVertices[idxTri2];
                    }

                    NavmeshTriangle triangle = new NavmeshTriangle(nv0, nv1, nv2);
                    allNavMeshTriangles.Add(triangle);
                }
            }
        }
    }
    public void AddNeighbour(NavmeshTriangle triangle)
    {
        neighbours.Add(triangle);

        if (triangle.IsConnected(v0))
        {
            if (v0.id != triangle.v0.id)
            {
                if (!v0.neighbours.Contains(triangle.v0))
                {
                    v0.neighbours.Add(triangle.v0);
                }
            }
            if (v0.id != triangle.v1.id)
            {
                if (!v0.neighbours.Contains(triangle.v1))
                {
                    v0.neighbours.Add(triangle.v1);
                }
            }
            if (v0.id != triangle.v2.id)
            {
                if (!v0.neighbours.Contains(triangle.v2))
                {
                    v0.neighbours.Add(triangle.v2);
                }
            }
        }
        if (triangle.IsConnected(v1))
        {
            if (v1.id != triangle.v0.id)
            {
                if (!v1.neighbours.Contains(triangle.v0))
                {
                    v1.neighbours.Add(triangle.v0);
                }
            }
            if (v1.id != triangle.v1.id)
            {
                if (!v1.neighbours.Contains(triangle.v1))
                {
                    v1.neighbours.Add(triangle.v1);
                }
            }
            if (v1.id != triangle.v2.id)
            {
                if (!v1.neighbours.Contains(triangle.v2))
                {
                    v1.neighbours.Add(triangle.v2);
                }
            }
        }
        if (triangle.IsConnected(v2))
        {
            if (v2.id != triangle.v0.id)
            {
                if (!v2.neighbours.Contains(triangle.v0))
                {
                    v2.neighbours.Add(triangle.v0);
                }
            }
            if (v2.id != triangle.v1.id)
            {
                if (!v2.neighbours.Contains(triangle.v1))
                {
                    v2.neighbours.Add(triangle.v1);
                }
            }
            if (v2.id != triangle.v2.id)
            {
                if (!v2.neighbours.Contains(triangle.v2))
                {
                    v2.neighbours.Add(triangle.v2);
                }
            }
        }
    }
示例#6
0
    public int GetTriangleIndex(Vector3 point)
    {
        for (int i = 0; i < nmg.allNavMeshTriangles.Count; ++i)
        {
            NavmeshTriangle tri  = nmg.allNavMeshTriangles[i];
            Vector3[]       vecs = new Vector3[] { tri.v0.point, tri.v1.point, tri.v2.point };

            /*if (CheckPointInTriangle(point, vecs, 1.0f))
             * {
             *  return i;
             * }*/
            // find barycenter
            Vector3 midPoint = (tri.v0.point + tri.v1.point + tri.v2.point) / 3;
            if (CheckPointInTriangle(midPoint, vecs, 1.0f)) // clockwise
            {
                if (CheckPointInTriangle(point, vecs, 1.0f))
                {
                    return(i);
                }
            }
            else // anti clockwise
            {
                if (CheckPointInTriangle(point, vecs, -1.0f))
                {
                    return(i);
                }
            }

            /*
             * bool clockWise = false;
             *
             * // find barycenter
             * Vector3 midPoint = (tri.v0.point + tri.v1.point + tri.v2.point) / 3;
             *
             * // check for outward normal
             * Vector3 inward = midPoint - tri.v0.point;
             * Vector3 edge = tri.v1.point - tri.v0.point;
             * Vector2 edgeNormal = new Vector2(edge.z, -edge.x);
             * Vector2 inward2D = new Vector2(inward.x, inward.z);
             *
             * if (Vector2.Dot(inward2D.normalized, edgeNormal.normalized) > 0.0f)
             * {
             *  clockWise = true;
             * }
             *
             *
             * Vector3 diff = tri.v0.point - point;
             * Vector3 line = tri.v1.point - tri.v0.point;
             *
             * Vector2 dir = new Vector2(diff.x, diff.z);
             * Vector2 norm = new Vector2(line.z, -line.x);
             *
             * if (Vector2.Dot(dir.normalized, norm.normalized) < 0.0f)
             *  continue;
             *
             * diff = tri.v1.point - point;
             * line = tri.v2.point - tri.v1.point;
             *
             * dir = new Vector2(diff.x, diff.z);
             * norm = new Vector2(line.z, -line.x);
             *
             * if (Vector2.Dot(dir.normalized, norm.normalized) < 0.0f)
             *  continue;
             *
             * diff = tri.v2.point - point;
             * line = tri.v0.point - tri.v2.point;
             *
             * dir = new Vector2(diff.x, diff.z);
             * norm = new Vector2(line.z, -line.x);
             *
             * if (Vector2.Dot(dir.normalized, norm.normalized) < 0.0f)
             *  continue;
             *
             * return i;
             */
        }

        return(-1); // Out of bound for all triangles
    }
示例#7
0
    public bool FindPath(Vector3 goal, out List <NavMeshVertex> outPath)
    {
        outPath = new List <NavMeshVertex>();
        foreach (NavmeshTriangle tri in nmg.allNavMeshTriangles)
        {
            tri.v0.Reset();
            tri.v1.Reset();
            tri.v2.Reset();
        }

        // Get origin and goal triangle
        int startIndex = GetClosestTriangleIndex(transform.position);//GetTriangleIndex(transform.position);
        int goalIndex  = GetTriangleIndex(goal);

        if (startIndex == -1)
        {
            Debug.Log("start out of bound");
            return(false);
        }
        else if (goalIndex == -1)
        {
            Debug.Log("goal out of bound");
            return(false);
        }

        NavmeshTriangle originTri = nmg.allNavMeshTriangles[startIndex];
        NavmeshTriangle goalTri   = nmg.allNavMeshTriangles[goalIndex];

        // If origin and goal share the same triangle
        NavMeshVertex v1 = new NavMeshVertex();
        NavMeshVertex v2 = new NavMeshVertex();

        v1.point = transform.position;
        v2.point = goal;
        outPath.Add(v1);
        outPath.Add(v2);

        //if (originTri.v0 == goalTri.v0 && originTri.v1 == goalTri.v1 && originTri.v2 == goalTri.v2)
        if (startIndex == goalIndex)
        {
            Debug.Log("same tri");
            return(true);
        }

        // Calculate origin triangle
        NavMeshVertex originTempVertex = new NavMeshVertex();

        originTempVertex.point  = transform.position;
        originTempVertex.parent = null;

        originTri.v0.totalCost = Vector3.SqrMagnitude(originTri.v0.point - transform.position);
        originTri.v1.totalCost = Vector3.SqrMagnitude(originTri.v1.point - transform.position);
        originTri.v2.totalCost = Vector3.SqrMagnitude(originTri.v2.point - transform.position);

        originTri.v0.parent = originTempVertex;
        originTri.v1.parent = originTempVertex;
        originTri.v2.parent = originTempVertex;

        // Open list
        List <NavMeshVertex> openList = new List <NavMeshVertex>();

        openList.Add(originTri.v0);
        openList.Add(originTri.v1);
        openList.Add(originTri.v2);

        // Master list for reset
        //List<NavMeshVertex> dumpster = new List<NavMeshVertex>();
        //dumpster.AddRange(openList);

        while (openList.Count > 0)
        {
            // Find cheapest node
            int cheapestIndex = 0;
            for (int i = 1; i < openList.Count; ++i)
            {
                if (openList[i].totalCost < openList[cheapestIndex].totalCost)
                {
                    cheapestIndex = i;
                }
            }
            NavMeshVertex currPoint = openList[cheapestIndex];
            openList.RemoveAt(cheapestIndex);

            // Check vertex against goal triangle
            if (goalTri.v0 == currPoint || goalTri.v1 == currPoint || goalTri.v2 == currPoint)
            {
                while (currPoint.parent != null)
                {
                    outPath.Insert(1, currPoint);
                    currPoint = currPoint.parent;
                }

                //foreach (NavMeshVertex vtx in dumpster)
                //    vtx.Reset();

                return(true);
            }

            // Loop neighbours
            for (int i = 0; i < currPoint.neighbours.Count; ++i)
            {
                // Skip visited vertex
                if (currPoint.neighbours[i].isVisited)
                {
                    continue;
                }

                float newCost = currPoint.totalCost + Vector3.SqrMagnitude(currPoint.neighbours[i].point - currPoint.point);
                if (newCost < currPoint.neighbours[i].totalCost)
                {
                    currPoint.neighbours[i].totalCost = newCost;
                    currPoint.neighbours[i].parent    = currPoint;
                }

                if (!openList.Contains(currPoint.neighbours[i]))
                {
                    openList.Add(currPoint.neighbours[i]);
                    //dumpster.Add(currPoint);
                }
            }

            currPoint.isVisited = true;
        }

        //foreach (NavMeshVertex vtx in dumpster)
        //    vtx.Reset();

        return(false);
    }