예제 #1
0
        public static River CreateRiverObject(GraphPath riverPath, PolygonMapGenerator PMG)
        {
            //Debug.Log("Creating mesh for river with " + riverPath.Nodes.Count + " points");

            // Calculate vertices of river polygon
            List <Vector2> polygonVerticesHalf1 = new List <Vector2>();
            List <Vector2> polygonVerticesHalf2 = new List <Vector2>();

            for (int i = 1; i < riverPath.Nodes.Count - 1; i++)
            {
                Vector2 startPoint = riverPath.Nodes[i - 1].Vertex;
                Vector2 thisPoint  = riverPath.Nodes[i].Vertex;
                Vector2 nextPoint  = riverPath.Nodes[i + 1].Vertex;

                float startWidth = riverPath.Nodes[i - 1].RiverWidth;
                float endWidth   = riverPath.Nodes[i].RiverWidth;

                //Debug.Log("River point " + i + ": startWidth = " + startWidth + ", endWidth = " + endWidth);

                if (i == 1) // Add two starting points
                {
                    Vector2 rotatedVector = GeometryFunctions.RotateVector((thisPoint - startPoint).normalized * startWidth, 90);
                    polygonVerticesHalf1.Add(startPoint + rotatedVector);
                    polygonVerticesHalf2.Add(startPoint - rotatedVector);
                }

                polygonVerticesHalf1.Add(GeometryFunctions.GetOffsetIntersection(startPoint, thisPoint, nextPoint, startWidth, endWidth, true));
                polygonVerticesHalf2.Add(GeometryFunctions.GetOffsetIntersection(startPoint, thisPoint, nextPoint, startWidth, endWidth, false));

                if (i == riverPath.Nodes.Count - 2) // Add two ending points (calculate river delta by taking intersecion between river and shoreline
                {
                    GraphNode lastNode = riverPath.Nodes.Last();
                    List <GraphConnection> shoreDelta       = lastNode.Connections.Where(x => x.Type == BorderType.Shore).ToList();
                    List <GraphNode>       riverDeltaPoints = new List <GraphNode>();
                    foreach (GraphConnection delta in shoreDelta)
                    {
                        if (delta.StartNode == lastNode)
                        {
                            riverDeltaPoints.Add(delta.EndNode);
                        }
                        else
                        {
                            riverDeltaPoints.Add(delta.StartNode);
                        }
                    }

                    Vector2 endPoint1, endPoint2;

                    // BUG: this method doesn't work 100%
                    GraphPolygon firstPolygon = riverPath.Nodes[i].Polygons.FirstOrDefault(x => GeometryFunctions.IsPointInPolygon4(x.Nodes.Select(x => x.Vertex).ToList(), polygonVerticesHalf1.Last()));
                    if (firstPolygon == null)
                    {
                        throw new Exception("Couldn't find direction of river delta. is river too short? length = " + riverPath.Nodes.Count);
                    }

                    bool addDeltaMidPoint = true;
                    if (riverDeltaPoints[0].Polygons.Contains(firstPolygon))
                    {
                        endPoint1 = GeometryFunctions.GetOffsetIntersection(thisPoint, nextPoint, riverDeltaPoints[0].Vertex, endWidth, 0f, true);
                        endPoint2 = GeometryFunctions.GetOffsetIntersection(thisPoint, nextPoint, riverDeltaPoints[1].Vertex, endWidth, 0f, false);

                        if (!GeometryFunctions.IsPointOnLineSegment(endPoint1, riverDeltaPoints[0].Vertex, lastNode.Vertex))
                        {
                            endPoint1        = lastNode.Vertex;
                            addDeltaMidPoint = false;
                        }
                        if (!GeometryFunctions.IsPointOnLineSegment(endPoint2, riverDeltaPoints[1].Vertex, lastNode.Vertex))
                        {
                            endPoint2        = lastNode.Vertex;
                            addDeltaMidPoint = false;
                        }
                    }
                    else
                    {
                        endPoint1 = GeometryFunctions.GetOffsetIntersection(thisPoint, nextPoint, riverDeltaPoints[1].Vertex, endWidth, 0f, true);
                        endPoint2 = GeometryFunctions.GetOffsetIntersection(thisPoint, nextPoint, riverDeltaPoints[0].Vertex, endWidth, 0f, false);

                        if (!GeometryFunctions.IsPointOnLineSegment(endPoint1, riverDeltaPoints[1].Vertex, lastNode.Vertex))
                        {
                            endPoint1        = lastNode.Vertex;
                            addDeltaMidPoint = false;
                        }
                        if (!GeometryFunctions.IsPointOnLineSegment(endPoint2, riverDeltaPoints[0].Vertex, lastNode.Vertex))
                        {
                            endPoint2        = lastNode.Vertex;
                            addDeltaMidPoint = false;
                        }
                    }

                    polygonVerticesHalf1.Add(endPoint1);
                    if (addDeltaMidPoint)
                    {
                        polygonVerticesHalf1.Add(lastNode.Vertex);
                    }
                    polygonVerticesHalf2.Add(endPoint2);
                }
            }

            polygonVerticesHalf2.Reverse();
            List <Vector2> polygonVertices = polygonVerticesHalf1;

            polygonVertices.AddRange(polygonVerticesHalf2);

            List <Vector2> polygonVerticesList = polygonVertices.ToList();

            if (GeometryFunctions.IsClockwise(polygonVerticesList))
            {
                polygonVerticesList.Reverse();
            }

            // Create object
            GameObject riverObject = MeshGenerator.GeneratePolygon(polygonVerticesList, PMG, layer: PolygonMapGenerator.LAYER_RIVER);

            River river = riverObject.AddComponent <River>();

            river.Init(riverPath.Nodes.Select(x => x.BorderPoint).ToList(), riverPath.Connections.Select(x => x.Border).ToList(), riverPath.Polygons.Select(x => x.Region).ToList());

            riverObject.GetComponent <MeshRenderer>().material.color = Color.red;

            riverObject.name = "River";

            return(river);
        }