public static GameObject DrawArrow(Vector2 from, Vector2 to, Color color, float width = 0.1f, float arrowHeadWidth = 0.2f, float arrowHeadLength = 0.1f, float yPos = 0.01f) { GameObject arrow = new GameObject("Arrow"); // Create mesh vertices and triangles Vector2[] vertices2D = new Vector2[7]; Vector2 v = to - from; Vector2 v90 = GeometryFunctions.RotateVector(v, 90).normalized; vertices2D[0] = from + (v90 * width); vertices2D[6] = from - (v90 * width); float arrowHeadLengthRatio = arrowHeadLength / Vector2.Distance(from, to); Vector2 headStart = Vector2.Lerp(from, to, 1f - arrowHeadLengthRatio); vertices2D[1] = headStart + (v90 * width); vertices2D[5] = headStart - (v90 * width); vertices2D[2] = headStart + (v90 * arrowHeadWidth); vertices2D[4] = headStart - (v90 * arrowHeadWidth); vertices2D[3] = to; Vector3[] vertices = new Vector3[vertices2D.Length]; for (int i = 0; i < vertices2D.Length; i++) { vertices[i] = new Vector3(vertices2D[i].x, yPos, vertices2D[i].y); } int[] triangles = { 0, 5, 6, 1, 5, 0, 2, 3, 4 }; // Add mesh renderer MeshRenderer renderer = arrow.AddComponent <MeshRenderer>(); renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; renderer.receiveShadows = false; renderer.material = MapDisplayResources.Singleton.DefaultMaterial; renderer.material.color = color; // Create the mesh MeshFilter meshFilter = arrow.AddComponent <MeshFilter>(); Mesh msh = new Mesh(); msh.vertices = vertices; msh.triangles = triangles; msh.RecalculateNormals(); msh.RecalculateBounds(); meshFilter.mesh = msh; return(arrow); }
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); }