Exemplo n.º 1
0
        private YnvPolySplit TryGetSplit(Dictionary <YnvPoly, YnvPolySplit> polysplits, YnvPoly poly)
        {
            if (poly == null)
            {
                return(null);
            }
            YnvPolySplit r = null;

            polysplits.TryGetValue(poly, out r);
            return(r);
        }
Exemplo n.º 2
0
        private List <YnvPoly> SplitPolys(List <YnvPoly> polys, bool xaxis)
        {
            var newpolys = new List <YnvPoly>();

            var verts1 = new List <Vector3>();
            var verts2 = new List <Vector3>();
            var edges1 = new List <YnvEdge>();
            var edges2 = new List <YnvEdge>();

            var polysplits = new Dictionary <YnvPoly, YnvPolySplit>();

            foreach (var poly in polys)  //split along borders
            {
                var verts = poly.Vertices;
                if (verts == null)
                {
                    continue;
                }            //ignore empty polys..
                if (verts.Length < 3)
                {
                    continue;
                }            //not enough verts for a triangle!

                Vector2I gprev  = NavGrid.GetCellPos(verts[0]);
                int      split1 = 0;
                int      split2 = 0;
                for (int i = 1; i < verts.Length; i++)
                {
                    Vector2I g  = NavGrid.GetCellPos(verts[i]);
                    int      g1 = xaxis ? g.X : g.Y;
                    int      g2 = xaxis ? gprev.X : gprev.Y;
                    if (g1 != g2) //this poly is crossing a border
                    {
                        if (split1 == 0)
                        {
                            split1 = i;
                        }
                        else
                        {
                            split2 = i; break;
                        }
                    }
                    gprev = g;
                }
                if (split1 > 0)
                {
                    var split2beg = (split2 > 0) ? split2 - 1 : verts.Length - 1;
                    var split2end = split2beg + 1;
                    var sv11      = verts[split1 - 1];
                    var sv12      = verts[split1];
                    var sv21      = verts[split2beg];
                    var sv22      = verts[split2];
                    var sp1       = GetSplitPos(sv11, sv12, xaxis);
                    var sp2       = GetSplitPos(sv21, sv22, xaxis);

                    //if ((sp1 == sp2) || (sp1 == sv11) || (sp1 == sv12) || (sp2 == sv21) || (sp2 == sv22))
                    if (!IsValidSplit(sp1, sp2, sv11, sv12, sv21, sv22))
                    {
                        //split did nothing, just leave this poly alone
                        newpolys.Add(poly);
                    }
                    else
                    {
                        //split it!
                        var poly1 = new YnvPoly();
                        var poly2 = new YnvPoly();
                        poly1.RawData = poly.RawData;
                        poly2.RawData = poly.RawData;
                        verts1.Clear();
                        verts2.Clear();

                        for (int i = 0; i < split1; i++)
                        {
                            verts1.Add(verts[i]);
                        }
                        verts1.Add(sp1);
                        verts1.Add(sp2);
                        for (int i = split2end; i < verts.Length; i++)
                        {
                            verts1.Add(verts[i]);
                        }

                        verts2.Add(sp1);
                        for (int i = split1; i < split2end; i++)
                        {
                            verts2.Add(verts[i]);
                        }
                        verts2.Add(sp2);

                        poly1.Vertices = verts1.ToArray();
                        poly2.Vertices = verts2.ToArray();


                        //save this information for the edge splitting pass
                        var polysplit = new YnvPolySplit();
                        polysplit.Orig   = poly;
                        polysplit.New1   = poly1;
                        polysplit.New2   = poly2;
                        polysplit.Split1 = split1;
                        polysplit.Split2 = split2end;
                        polysplits[poly] = polysplit;


                        newpolys.Add(poly1);
                        newpolys.Add(poly2);
                    }
                }
                else
                {
                    //no need to split
                    newpolys.Add(poly);
                }
            }


            foreach (var polysplit in polysplits.Values) //build new edges for split polys
            {
                //the two edges that were split each need to be turned into two new edges (1 for each poly).
                //also, the split itself needs to be added as a new edge to the original poly.

                var poly  = polysplit.Orig;
                var poly1 = polysplit.New1;
                var poly2 = polysplit.New2;
                var edges = poly.Edges;
                var verts = poly.Vertices;
                var ec    = edges?.Length ?? 0;
                if (ec <= 0)
                {
                    continue;
                }            //shouldn't happen - no edges?
                if (ec != poly.Vertices?.Length)
                {
                    continue;
                }            //shouldn't happen

                var split1beg = polysplit.Split1 - 1;
                var split1end = polysplit.Split1;
                var split2beg = polysplit.Split2 - 1;
                var split2end = polysplit.Split2;

                edges1.Clear();
                edges2.Clear();

                var se1    = edges[split1beg];                   //the two original edges that got split
                var se2    = edges[split2beg];
                var sp1    = TryGetSplit(polysplits, se1.Poly1); //could use Poly2, but they should be the same..
                var sp2    = TryGetSplit(polysplits, se2.Poly1);
                var sv1a   = verts[split1beg];
                var sv2a   = verts[split2beg];
                var sp1a   = sp1?.GetNearest(sv1a);
                var sp1b   = sp1?.GetOther(sp1a);
                var sp2b   = sp2?.GetNearest(sv2a);
                var sp2a   = sp2?.GetOther(sp2b);
                var edge1a = new YnvEdge(se1, sp1a);
                var edge1b = new YnvEdge(se1, sp1b);
                var edge2a = new YnvEdge(se2, sp2a);
                var edge2b = new YnvEdge(se2, sp2b);
                var splita = new YnvEdge(se1, poly2);
                var splitb = new YnvEdge(se1, poly1);

                for (int i = 0; i < split1beg; i++)
                {
                    edges1.Add(edges[i]);                                //untouched edges
                }
                edges1.Add(edge1a);
                edges1.Add(splita);
                edges1.Add(edge2a);
                for (int i = split2end; i < ec; i++)
                {
                    edges1.Add(edges[i]);                                 //untouched edges
                }
                edges2.Add(edge1b);
                for (int i = split1end; i < split2beg; i++)
                {
                    edges2.Add(edges[i]);                                        //untouched edges
                }
                edges2.Add(edge2b);
                edges2.Add(splitb);


                poly1.Edges = edges1.ToArray();
                poly2.Edges = edges2.ToArray();

                if (poly1.Edges.Length != poly1.Vertices.Length)
                {
                }  //debug
                if (poly2.Edges.Length != poly2.Vertices.Length)
                {
                }  //debug
            }

            foreach (var poly in newpolys) //fix any untouched edges that joined to split polys
            {
                if (poly.Edges?.Length != poly.Vertices?.Length)
                {
                    continue;
                }            //shouldn't happen (no edges?)
                for (int i = 0; i < poly.Edges.Length; i++)
                {
                    var edge = poly.Edges[i];
                    var vert = poly.Vertices[i];
                    if (edge == null)
                    {
                        continue;
                    }            //shouldn't happen
                    if (edge.Poly1 != edge.Poly2)
                    {
                        continue;
                    }            //shouldn't happen?
                    if (edge.Poly1 == null)
                    {
                        continue;
                    }            //probably this edge joins to nothing


                    YnvPolySplit polysplit;
                    if (polysplits.TryGetValue(edge.Poly1, out polysplit))
                    {
                        var newpoly = polysplit.GetNearest(vert);
                        if (newpoly == null)
                        {
                        }  //debug
                        edge.Poly1 = newpoly;
                        edge.Poly2 = newpoly;
                    }
                }
            }


            return(newpolys);
        }