예제 #1
0
 public static bool TryMerge(ref Poly toPoly, Triangle mergeTri, ref GeoEdge sharedEdge)
 {
     if (CouldMerge(ref toPoly, mergeTri, sharedEdge))
     {
         return(Merge(ref toPoly, mergeTri, ref sharedEdge));
     }
     else
     {
         return(false);
     }
 }
예제 #2
0
        public static bool IsIntersect(Poly poly, int x, int z)
        {
            Vector2 pA = new Vector2(left + tileSize * x, bottom + tileSize * z);
            Vector2 pB = new Vector2(left + tileSize * (x + 1), bottom + tileSize * z);
            Vector2 pC = new Vector2(left + tileSize * (x + 1), bottom + tileSize * (z + 1));
            Vector2 pD = new Vector2(left + tileSize * x, bottom + tileSize * (z + 1));

            Geo2D poly2d = poly.GetGeo2D();
            Geo2D rect2d = new Geo2D(pA, pB, pC, pD);

            return(GraphTester2D.IsIntersect(poly2d, rect2d));
        }
예제 #3
0
        protected int GetPoly(Vector2 pos, List <int> plys)
        {
            foreach (int i in plys)
            {
                Poly p = polys[i];
                if (GraphTester2D.IsInside(pos, p.GetGeo2D()))
                {
                    return(i);
                }
            }

            return(-1);
        }
예제 #4
0
        public static GeoEdge SharedEdge(Poly polyA, Poly polyB)
        {
            for (int i = 0; i < polyA.EdgeCount; i++)
            {
                for (int j = 0; j < polyB.EdgeCount; j++)
                {
                    if (AreEqual(polyA.Edges[i], polyB.Edges[j]))
                    {
                        return(polyA.Edges[i]);
                    }
                }
            }

            return(null);
        }
예제 #5
0
        public static bool HasSharedEdge(Poly polyA, Poly polyB)
        {
            for (int i = 0; i < polyA.EdgeCount; i++)
            {
                for (int j = 0; j < polyB.EdgeCount; j++)
                {
                    if (AreEqual(polyA.Edges[i], polyB.Edges[j]))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #6
0
        public static bool Merge(ref Poly toPoly, Poly mergeTri, ref GeoEdge sharedEdge)
        {
            List <GeoEdge> restEdge = mergeTri.RestEdge(sharedEdge);

            if (!toPoly.ContainsSomeEdge(restEdge))
            {
                toPoly.RemoveEdge(sharedEdge);
                toPoly.AddEdges(restEdge);
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #7
0
        public static bool CouldMerge(ref Poly toPoly, Poly mergeTri, GeoEdge sharedEdge)
        {
            bool    couldmerge = true;
            Vector3 a          = toPoly.RelatedEdgeExtrude(sharedEdge.A, sharedEdge).OtherPoint(sharedEdge.A);
            Vector3 b          = sharedEdge.PointA;
            Vector3 c          = mergeTri.RelatedEdgeExtrude(sharedEdge.A, sharedEdge).OtherPoint(sharedEdge.A);
            Vector3 d          = sharedEdge.OtherPoint(sharedEdge.A);

            couldmerge &= GraphTester2D.TotalAngleForThreeSeg(a, b, c, d) - 180f < 1e-06;

            a           = toPoly.RelatedEdgeExtrude(sharedEdge.B, sharedEdge).OtherPoint(sharedEdge.B);
            b           = sharedEdge.PointB;
            c           = mergeTri.RelatedEdgeExtrude(sharedEdge.B, sharedEdge).OtherPoint(sharedEdge.B);
            d           = sharedEdge.OtherPoint(sharedEdge.B);
            couldmerge &= GraphTester2D.TotalAngleForThreeSeg(a, b, c, d) - 180f < 1e-06;

            return(couldmerge);
        }
예제 #8
0
        /// <summary>
        /// 得到处理过后的导航文件,包含信息(顶点、多边形、多边形连接、预计算路径信息、多边形的AOI信息)
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="ifPreCalculatePath"></param>
        public static void WriteProcessedNavFile(NavMesh navMesh, string fileName, bool ifPreCalculatePath)
        {
            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }

            StreamWriter  sw = new StreamWriter(fileName);
            StringBuilder lBuilder;

            for (int i = 0; i < navMesh.Points.Count; i++)//顶点信息
            {
                lBuilder = new StringBuilder("v").Append(navMesh.Points[i].x.ToString()).Append(" ").Append(navMesh.Points[i].y.ToString()).Append(" ").Append(navMesh.Points[i].z);
                sw.WriteLine(lBuilder.ToString());
            }

            SortedDictionary <int, Poly> .Enumerator polyIter = navMesh.Polys.GetEnumerator();
            while (polyIter.MoveNext())  //Poly 信息
            {
                lBuilder = new StringBuilder("p").Append(polyIter.Current.Key.ToString()).Append(" ");
                Poly p = polyIter.Current.Value;
                foreach (GeoEdge e in p.Edges)
                {
                    lBuilder.Append("|").Append(e.A.ToString()).Append(" ").Append(e.B);
                }
                sw.WriteLine(lBuilder.ToString());
            }
            polyIter.Dispose();

            SortedDictionary <int, HashSet <PolyConnection> > .Enumerator iter = navMesh.NearPolys.GetEnumerator();
            while (iter.MoveNext())//Poly connection信息
            {
                //有连接的poly的序号
                lBuilder = new StringBuilder("c ").Append(iter.Current.Key.ToString());
                HashSet <PolyConnection> cons = iter.Current.Value;

                foreach (PolyConnection con in cons)
                {
                    lBuilder.Append(" ").Append(con.Other(iter.Current.Key).ToString()).Append(" ").Append(con.Weight.ToString()).Append(" ").Append(con.ConnectionEdge.A.ToString()).Append(" ").Append(con.ConnectionEdge.B.ToString());
                    //每个连接有4个数据,分别是:连向的Poly的序号、此连接的权重、对应此连接的边的两个顶点
                }
                sw.WriteLine(lBuilder.ToString());
            }
            iter.Dispose();

            if (ifPreCalculatePath)
            {//预存储的路径信息, 存在文件的后部
                List <int>[,] paths = navMesh.Paths;
                for (int m = 0; m < navMesh.Polys.Count; m++)
                {
                    for (int n = 0; n < navMesh.Polys.Count; n++)
                    {
                        List <int> pth = paths[m, n];
                        if (pth != null && pth.Count > 0)
                        {
                            lBuilder = new StringBuilder("from ").Append(m.ToString()).Append(" to ").Append(n.ToString());
                            for (int x = 0; x < pth.Count; x++)
                            {
                                lBuilder.Append(" ").Append(pth[x].ToString());
                            }
                            sw.WriteLine(lBuilder.ToString());
                        }
                    }
                }
            }

            sw.WriteLine("componentCount " + navMesh.ComponentCount);

            //这里把AOI信息也写进来
            NavAOI navAOI = NavAOIProcesser.ProcessPolyAOI(navMesh.Polys, navMesh);

            sw.WriteLine("navAOI:");
            lBuilder = new StringBuilder("AOIInfo ").Append(navAOI.Left.ToString()).Append(" ").Append(navAOI.Bottom).Append(" ").Append(navAOI.TileSize).Append(" ").Append(navAOI.Width).Append(" ").Append(navAOI.Height);
            sw.WriteLine(lBuilder.ToString());
            for (int i = 0; i < navAOI.Width; i++)
            {
                for (int j = 0; j < navAOI.Height; j++)
                {
                    List <int> aoiList = navAOI.NavPolyAOI[i, j];
                    if (aoiList != null)
                    {
                        lBuilder = new StringBuilder(i.ToString()).Append(",").Append(j.ToString()).Append(":");
                        for (int k = 0; k < aoiList.Count; k++)
                        {
                            lBuilder.Append(" ").Append(aoiList[k]);
                        }

                        sw.WriteLine(lBuilder.ToString());
                    }
                }
            }

            sw.Close();
            sw.Dispose();
        }
예제 #9
0
        public void ProcessMeshToGraph()
        {
            Dictionary <Triangle, bool> visited = new Dictionary <Triangle, bool>();

            foreach (Triangle tri in triangles)
            {
                visited.Add(tri, false);
            }
            Queue <Poly> processEdgeQueue = new Queue <Poly>();

            int i = 0;

            componentCount = 0;

            int mergedCout = 0;

            while (triangles.Count > 0)
            {
                componentCount++;                 //整张图的联通分量计数++
                Triangle tri = triangles.First(); //拿出一个三角形
                tri.Index    = i++;               //为这个poly分配索引
                visited[tri] = true;
                processEdgeQueue.Enqueue(tri);
                triangles.Remove(tri);
                foreach (GeoEdge e in tri.Edges)
                {
                    if (edgeTriangleMap.ContainsKey(e.Index) && edgeTriangleMap[e.Index].Contains(tri))
                    {
                        edgeTriangleMap[e.Index].Remove(tri);//移除这个三角形和它的边的映射
                    }
                }

                while (processEdgeQueue.Count > 0)
                {
                    Poly poly = processEdgeQueue.Dequeue();

                    bool hasConnection = false;
                    for (int j = 0; j < poly.Edges.Count; j++)
                    {//对于这个多边形的每一条边
                        GeoEdge e = poly.Edges[j];

                        for (int k = 0; k < edgeTriangleMap[e.Index].Count; k++)
                        {//如果有与之相连的其他三角形
                            Triangle t = edgeTriangleMap[e.Index][k];
                            if (triangles.Contains(t) && t != poly && PolyProcesser.HasSharedEdge(poly, t))
                            {
                                GeoEdge sharedEdge = PolyProcesser.SharedEdge(poly, t);
                                if (PolyProcesser.TryMerge(ref poly, t, ref sharedEdge)) //如果可以成功合并
                                {                                                        //这里ref Poly处理过后,里面就有t的边了
                                    hasConnection = true;
                                    mergedCout++;
                                }
                                else
                                {//相连但不可成功合并,说明是相连的多边形
                                    if (!visited[t])
                                    {
                                        processEdgeQueue.Enqueue(t);
                                        t.Index    = i++;
                                        visited[t] = true;
                                        //设置polyConnection,这里polyConnection还不用计算Weight,因为可能poly和t的顶点都没有全部得到
                                        PolyConnection con = new PolyConnection(poly.Index, t.Index, sharedEdge);
                                        if (!polyConnections.Contains(con))
                                        {
                                            polyConnections.Add(con);
                                            InsertNearPoly(con.A, con);
                                            InsertNearPoly(con.B, con);
                                        }
                                    }
                                }

                                edgeTriangleMap[e.Index].Remove(t);
                                triangles.Remove(t);
                            }
                        }
                    }

                    if (hasConnection)
                    {
                        processEdgeQueue.Enqueue(poly);//说明还有连接,可能这个poly还没有处理完
                    }
                    else
                    {//Poly没有连接了,说明处理完了,对poly做最后的处理
                        if (!polys.ContainsKey(poly.Index))
                        {
                            polys.Add(poly.Index, poly);
                        }
                    }
                }
            }
            //对polyConnection计算权值
            foreach (PolyConnection polyCon in polyConnections)
            {
                Vector3 pointA = CenterPoint(polys[polyCon.A].GetPoints());
                Vector3 pointB = CenterPoint(polys[polyCon.B].GetPoints());
                polyCon.Weight = Vector3.Distance(pointA, pointB);
            }

            Debug.Log("merged count :" + mergedCout);
            Debug.Log("component count :" + componentCount);
        }
예제 #10
0
        public static PathFinder Read(string fileName)
        {
            StreamReader sr = new StreamReader(fileName);
            string       l;

            float                              left           = 0f;
            float                              bottom         = 0f;
            float                              tileSize       = 0f;
            int                                width          = 0;
            int                                height         = 0;
            int                                componentCount = 0;
            List <Vector3>                     points         = new List <Vector3>();
            Dictionary <int, Poly>             polys          = new Dictionary <int, Poly>();
            Dictionary <int, List <NodeEdge> > edges          = new Dictionary <int, List <NodeEdge> >();

            List <int>[,] pths    = null;
            List <int>[,] polyAOI = null;
            while ((l = sr.ReadLine()) != null)
            {
                string[] info = l.Split(' ');
                if (info[0] == "v")
                {
                    Vector3 p = new Vector3(Convert.ToSingle(info[1]), Convert.ToSingle(info[2]), Convert.ToSingle(info[3]));
                    points.Add(p);
                }
                else if (info[0] == "p")
                {
                    string[] infos = l.Split('|');
                    Poly     poly  = new Poly();
                    int      index = Convert.ToInt32(info[1]);
                    poly.Index = Convert.ToInt32(info[1]);
                    for (int i = 1; i < infos.Length; i++)
                    {
                        string[] edge = infos[i].Split(' ');
                        poly.AddEdge(new GeoEdge(Convert.ToInt32(edge[0]), Convert.ToInt32(edge[1]), points));
                    }
                    polys.Add(index, poly);
                }
                else if (info[0] == "c")
                {
                    int             index  = Convert.ToInt32(info[1]);
                    List <NodeEdge> eEdges = new List <NodeEdge>();
                    for (int i = 2; i < info.Length - 3; i += 4)
                    {
                        NodeEdge nEdge = new NodeEdge();
                        nEdge.A      = index;
                        nEdge.B      = Convert.ToInt32(info[i]);
                        nEdge.Weight = Convert.ToSingle(info[i + 1]);
                        nEdge.PointA = Convert.ToInt32(info[i + 2]);
                        nEdge.PointB = Convert.ToInt32(info[i + 3]);
                    }
                    edges.Add(index, eEdges);
                }
                else if (info[0] == "from")
                {
                    if (pths == null)
                    {
                        pths = new List <int> [polys.Count, polys.Count];
                    }

                    List <int> path = new List <int>();
                    int        from = Convert.ToInt32(info[1]);
                    int        to   = Convert.ToInt32(info[3]);
                    for (int i = 4; i < info.Length; i++)
                    {
                        path.Add(Convert.ToInt32(info[i]));
                    }
                    pths[from, to] = path;
                }
                else if (info[0] == "componentCount")
                {
                    componentCount = Convert.ToInt32(info[1]);
                }
                else if (info[0] == "AOIInfo")
                {
                    left     = Convert.ToSingle(info[1]);
                    bottom   = Convert.ToSingle(info[2]);
                    tileSize = Convert.ToSingle(info[3]);
                    width    = Convert.ToInt32(info[4]);
                    height   = Convert.ToInt32(info[5]);
                }
                else if (info[0] == "aoiOf")
                {
                    if (polyAOI == null)
                    {
                        polyAOI = new List <int> [width, height];
                    }

                    List <int> aoi = new List <int>();
                    int        i   = Convert.ToInt32(info[1]);
                    int        j   = Convert.ToInt32(info[2]);

                    for (int k = 3; k < info.Length; k++)
                    {
                        aoi.Add(Convert.ToInt32(info[k]));
                    }

                    polyAOI[i, j] = aoi;
                }
            }

            sr.Close();
            sr.Dispose();

            if (pths == null)
            {
                return(new PathFinderRealtime(points, polys, edges, left, bottom, tileSize, width, height, componentCount, polyAOI));
            }
            else
            {
                return(new PathFinderPre(points, polys, edges, left, bottom, tileSize, width, height, componentCount, polyAOI));
            }
        }
예제 #11
0
        public static NavAOI ProcessPolyAOI(SortedDictionary <int, Poly> polys, NavMesh mesh)
        {
            float l    = Mathf.Infinity;
            float r    = Mathf.NegativeInfinity;
            float b    = Mathf.Infinity;
            float t    = Mathf.NegativeInfinity;
            float area = 0f;

            SortedDictionary <int, Poly> .Enumerator polyIter = polys.GetEnumerator();
            while (polyIter.MoveNext())
            {//Poly 信息
                Poly poly = polyIter.Current.Value;

                foreach (int pIndex in poly.GetPoints())
                {
                    Vector3 point = mesh.Point(pIndex);
                    if (point.x < l)
                    {
                        l = point.x;
                    }
                    if (point.z < b)
                    {
                        b = point.z;
                    }
                    if (point.x > r)
                    {
                        r = point.x;
                    }
                    if (point.z > t)
                    {
                        t = point.z;
                    }
                }
                area += poly.GetGeo2D().GetArea();
            }
            polyIter.Dispose();
            area /= polys.Count;

            left     = l;
            bottom   = b;
            width    = r - l;
            height   = t - b;
            tileSize = Mathf.Sqrt(area);
            int w = Mathf.CeilToInt(width / tileSize);
            int h = Mathf.CeilToInt(height / tileSize);

            NavAOI navAOI = new NavAOI(left, bottom, width, height, tileSize);

            polyIter = polys.GetEnumerator();
            while (polyIter.MoveNext())
            {
                Poly poly = polyIter.Current.Value;

                Geo2D geo2D  = poly.GetGeo2D();
                int   xStart = Mathf.FloorToInt(geo2D.MinX / tileSize);
                int   xEnd   = Mathf.CeilToInt(geo2D.MaxX / tileSize);
                int   yStart = Mathf.FloorToInt(geo2D.MinY / tileSize);
                int   yEnd   = Mathf.CeilToInt(geo2D.MaxY / tileSize);

                for (int i = xStart; i < xEnd; i++)
                {
                    for (int j = yStart; j < yEnd; j++)
                    {
                        if (IsIntersect(poly, i, j))
                        {
                            navAOI.AddPolyToAOI(i, j, polyIter.Current.Key);
                        }
                    }
                }
            }
            polyIter.Dispose();

            return(navAOI);
        }