Пример #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 NavmeshTriangle(NavMeshVertex a, NavMeshVertex b, NavMeshVertex c)
 {
     v0         = a;
     v1         = b;
     v2         = c;
     normal     = Vector3.zero;
     neighbours = new List <NavmeshTriangle>();
 }
Пример #3
0
    // pre calculate path
    // find neighbour
    // profit

    void Start()
    {
        vertices = new List <NavMeshVertex>();

        NavMeshTriangulation nmt = NavMesh.CalculateTriangulation();

        foreach (Vector3 vec in nmt.vertices)
        {
            bool isAdd = true;
            foreach (var vtx in vertices)
            {
                if (vtx.point == vec)
                {
                    isAdd = false;
                    break;
                }
            }

            if (isAdd)
            {
                NavMeshVertex toAdd = new NavMeshVertex();
                toAdd.point = vec;
                vertices.Add(toAdd);
            }
        }

        Debug.Log("Vertex count: " + vertices.Count);

        foreach (NavMeshVertex vtx in vertices)
        {
            //vtx.neighbours = new List<NavMeshVertex>();
            foreach (NavMeshVertex neighbour in vertices)
            {
                if (vtx.point == neighbour.point)
                {
                    continue;
                }

                Vector3 dir  = (neighbour.point - vtx.point);
                float   dist = Vector3.Distance(vtx.point, neighbour.point);
                if (!Physics.Raycast(vtx.point, dir.normalized, dist))
                {
                    vtx.neighbours.Add(neighbour);
                    vtx.cost.Add(dist);
                }
            }
        }
    }
Пример #4
0
    public bool GetPath(NavMeshVertex origin, NavMeshVertex goal, out List <Vector3> path)
    {
        path = new List <Vector3>();

        List <NavMeshVertex> openList = new List <NavMeshVertex>();

        origin.totalCost = 0.0f;
        openList.Add(origin);

        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;
                }
            }
            var currPoint = openList[cheapestIndex];
            openList.RemoveAt(cheapestIndex);

            // Reached
            if (currPoint == goal)
            {
                while (currPoint != origin)
                {
                    path.Insert(0, currPoint.point);
                    currPoint = currPoint.parent;
                }
                path.Insert(0, origin.point);
                Debug.Log(path.Count);

                foreach (var vtx in vertices)
                {
                    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 + currPoint.cost[i];
                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]);
                }
            }

            currPoint.isVisited = true;
        }

        foreach (var vtx in vertices)
        {
            vtx.Reset();
        }

        return(false);
    }
    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 bool IsConnected(NavMeshVertex v)
 {
     return(v0.id == v.id || v1.id == v.id || v2.id == v.id);
 }
Пример #7
0
        public void Load(string onvfile)
        {
            Name = Path.GetFileNameWithoutExtension(onvfile).ToLowerInvariant();

            var       lines            = File.ReadAllLines(onvfile);
            bool      inverts          = false;
            bool      ininds           = false;
            bool      inedges          = false;
            bool      inpolys          = false;
            bool      insectors        = false;
            bool      insectordata     = false;
            bool      insectorpolyinds = false;
            bool      insectorbounds   = false;
            bool      inportals        = false;
            int       depth            = 0;
            int       cdepth           = 0;
            OnvSector csector          = SectorTree;

            var spacedelim = new[] { ' ' };
            var cult       = CultureInfo.InvariantCulture;

            foreach (var line in lines)
            {
                string tline = line.Trim();
                if (string.IsNullOrEmpty(tline))
                {
                    continue;                              //blank line
                }
                //if (tline.StartsWith("#")) continue; //commented out

                string[] parts = tline.Split(spacedelim, StringSplitOptions.RemoveEmptyEntries);

                if (tline.StartsWith("{"))
                {
                    depth++; continue;
                }
                if (tline.StartsWith("}"))
                {
                    depth--;
                }                                       //need to handle the closing cases

                if (inverts)
                {
                    if (depth <= 0)
                    {
                        inverts = false;
                    }
                    else if (parts.Length == 3)
                    {
                        NavMeshVertex v = new NavMeshVertex();
                        v.X = ushort.Parse(parts[0].Trim(), cult);
                        v.Y = ushort.Parse(parts[1].Trim(), cult);
                        v.Z = ushort.Parse(parts[2].Trim(), cult);
                        Vertices.Add(v);
                    }
                }
                else if (ininds)
                {
                    if (depth <= 0)
                    {
                        ininds = false;
                    }
                    else
                    {
                        for (int i = 0; i < parts.Length; i++)
                        {
                            int ind = int.Parse(parts[i]);
                            Indices.Add(ind);
                        }
                    }
                }
                else if (inedges)
                {
                    if (depth <= 0)
                    {
                        inedges = false;
                    }
                    else
                    {
                        OnvEdge edge = new OnvEdge(parts);
                        Edges.Add(edge);
                    }
                }
                else if (inpolys)
                {
                    if (depth <= 0)
                    {
                        inpolys = false;
                    }
                    else
                    {
                        OnvPoly poly = new OnvPoly(parts);
                        Polys.Add(poly);
                    }
                }
                else if (insectors)
                {
                    if (depth <= 0)
                    {
                        insectors        = false;
                        insectordata     = false;
                        insectorpolyinds = false;
                        insectorbounds   = false;
                    }
                    else if (insectordata)
                    {
                        if (depth <= cdepth)
                        {
                            insectordata     = false;
                            insectorpolyinds = false;
                            insectorbounds   = false;
                        }
                        else if (insectorpolyinds)
                        {
                            if (depth <= (cdepth + 1))
                            {
                                insectorpolyinds = false;
                            }
                            else
                            {
                                for (int i = 0; i < parts.Length; i++)
                                {
                                    int ind = int.Parse(parts[i]);
                                    csector.SectorData.PolyIndices.Add(ind);
                                }
                            }
                        }
                        else if (insectorbounds)
                        {
                            if (depth <= (cdepth + 1))
                            {
                                insectorbounds = false;
                            }
                            else
                            {
                                OnvBounds bounds = new OnvBounds(parts);
                                csector.SectorData.Bounds.Add(bounds);
                            }
                        }
                        else
                        {
                            string idstr = parts[0].Trim();
                            if (idstr == "PolyIndices")
                            {
                                csector.SectorData.PolyIndicesCount = int.Parse(parts[1].Trim(), cult);
                                insectorpolyinds = csector.SectorData.PolyIndicesCount > 0;
                                if (insectorpolyinds)
                                {
                                    csector.SectorData.PolyIndices = new List <int>();
                                }
                            }
                            else if (idstr == "Bounds")
                            {
                                csector.SectorData.BoundsCount = int.Parse(parts[1].Trim(), cult);
                                insectorbounds = csector.SectorData.BoundsCount > 0;
                                if (insectorbounds)
                                {
                                    csector.SectorData.Bounds = new List <OnvBounds>();
                                }
                            }
                        }
                    }
                    else
                    {
                        if (depth < cdepth)
                        {
                            csector = csector.Parent;
                        }
                        cdepth = depth;
                        string idstr = parts[0].Trim();
                        if (idstr == "AABBMin")
                        {
                            csector.AABBMin = Util.GetVector3(parts, 1);
                        }
                        else if (idstr == "AABBMax")
                        {
                            csector.AABBMax = Util.GetVector3(parts, 1);
                        }
                        else if ((parts.Length < 2) || (parts[1].Trim() != "null"))
                        {
                            if (idstr == "SectorData")
                            {
                                csector.SectorData = new OnvSectorData();
                                insectordata       = true;
                            }
                            else if (idstr == "SubTree0")
                            {
                                csector.SubTree0        = new OnvSector();
                                csector.SubTree0.Parent = csector;
                                csector = csector.SubTree0;
                            }
                            else if (idstr == "SubTree1")
                            {
                                csector.SubTree1        = new OnvSector();
                                csector.SubTree1.Parent = csector;
                                csector = csector.SubTree1;
                            }
                            else if (idstr == "SubTree2")
                            {
                                csector.SubTree2        = new OnvSector();
                                csector.SubTree2.Parent = csector;
                                csector = csector.SubTree2;
                            }
                            else if (idstr == "SubTree3")
                            {
                                csector.SubTree3        = new OnvSector();
                                csector.SubTree3.Parent = csector;
                                csector = csector.SubTree3;
                            }
                        }
                    }
                }
                else if (inportals)
                {
                    if (depth <= 0)
                    {
                        inportals = false;
                    }
                    else
                    {
                        OnvPortal portal = new OnvPortal(parts);
                        Portals.Add(portal);
                    }
                }
                else
                {
                    //at root level, look for identifier
                    depth = 0; //reset just in case
                    string idstr = parts[0].Trim();
                    if (idstr == "Version")
                    {
                        VersionMaj = int.Parse(parts[1].Trim(), cult);
                        VersionMin = int.Parse(parts[2].Trim(), cult);
                    }
                    else if (idstr == "Sizes")
                    {
                        Sizes = Util.GetVector3(parts, 1);
                    }
                    else if (idstr == "Flags")
                    {
                        Flags = int.Parse(parts[1].Trim(), cult);
                    }
                    else if (idstr == "Vertices")
                    {
                        VerticesCount = int.Parse(parts[1].Trim(), cult);
                        inverts       = VerticesCount > 0;
                    }
                    else if (idstr == "Indices")
                    {
                        IndicesCount = int.Parse(parts[1].Trim(), cult);
                        ininds       = IndicesCount > 0;
                    }
                    else if (idstr == "Edges")
                    {
                        EdgesCount = int.Parse(parts[1].Trim(), cult);
                        inedges    = EdgesCount > 0;
                    }
                    else if (idstr == "Polys")
                    {
                        PolysCount = int.Parse(parts[1].Trim(), cult);
                        inpolys    = PolysCount > 0;
                    }
                    else if (idstr == "SectorTree")
                    {
                        insectors = true;
                    }
                    else if (idstr == "Portals")
                    {
                        PortalsCount = int.Parse(parts[1].Trim(), cult);
                        inportals    = PortalsCount > 0;
                    }
                    else if (idstr == "SectorID")
                    {
                        SectorID = int.Parse(parts[1].Trim(), cult);
                    }
                }
            }
        }
Пример #8
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);
    }