public static GameObject GeneratePolygon(List <Vector2> vertices2D, PolygonMapGenerator PMG, float layer) { // Use the triangulator to get indices for creating triangles Triangulator tr = new Triangulator(vertices2D.ToArray()); int[] indices = tr.Triangulate(); // Create the Vector3 vertices Vector3[] vertices = new Vector3[vertices2D.Count]; Vector4[] tangents = new Vector4[vertices2D.Count]; Vector2[] uvs = new Vector2[vertices2D.Count]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = new Vector3(vertices2D[i].x, layer, vertices2D[i].y); if (PMG != null) { uvs[i] = new Vector2(vertices2D[i].x / PMG.GenerationSettings.Width, vertices2D[i].y / PMG.GenerationSettings.Height); } // tangent calc Vector2 beforeVertex = vertices2D[i == 0 ? vertices2D.Count - 1 : i - 1]; Vector2 thisVertex = vertices2D[i]; Vector2 afterVertex = vertices2D[i == vertices2D.Count - 1 ? 0 : i + 1]; Vector2 targetPoint = GeometryFunctions.GetOffsetIntersection(beforeVertex, thisVertex, afterVertex, 1f, 1f, false); Vector2 tangent = targetPoint - thisVertex; /* * float angle = Mathf.Abs(Vector2.Angle((beforeVertex - thisVertex).normalized, (afterVertex - thisVertex).normalized)); * float factor = (180 - angle) * 0.005f; * tangent *= (1 + factor); */ tangents[i] = new Vector4(tangent.x, 0, tangent.y, 0); } // Create the mesh Mesh msh = new Mesh(); msh.vertices = vertices; msh.tangents = tangents; msh.uv = uvs; msh.triangles = indices; msh.RecalculateNormals(); msh.RecalculateBounds(); // Set up game object with mesh; GameObject polygon = new GameObject("Polygon (" + vertices2D.Count + ")"); MeshRenderer renderer = polygon.AddComponent <MeshRenderer>(); Color ranCol = Color.red; // new Color(Random.Range(0f, 0.3f), Random.Range(0.4f, 1f), Random.Range(0.1f, 0.6f)); renderer.material.color = ranCol; MeshFilter filter = polygon.AddComponent(typeof(MeshFilter)) as MeshFilter; filter.mesh = msh; return(polygon); }
public static GameObject CreateSinglePolygonBorder(List <GraphNode> nodes, float width, Color c, float layer, bool clockwise = false) { List <Vector2> outerVertices = nodes.Select(x => x.Vertex).ToList(); List <Vector2> innerVertices = new List <Vector2>(); for (int i = 0; i < outerVertices.Count; i++) { Vector2 beforeVertex = outerVertices[i == 0 ? outerVertices.Count - 1 : i - 1]; Vector2 thisVertex = outerVertices[i]; Vector2 afterVertex = outerVertices[i == outerVertices.Count - 1 ? 0 : i + 1]; Vector2 targetPoint = GeometryFunctions.GetOffsetIntersection(beforeVertex, thisVertex, afterVertex, width, width, clockwise); innerVertices.Add(targetPoint); } // Create full vertex list (outer0, inner0, outer1, inner1, outer2, inner2, ...) Vector3[] vertices = new Vector3[outerVertices.Count + innerVertices.Count]; for (int i = 0; i < outerVertices.Count; i++) { vertices[2 * i] = new Vector3(outerVertices[i].x, layer, outerVertices[i].y); vertices[2 * i + 1] = new Vector3(innerVertices[i].x, layer, innerVertices[i].y); } // Create triangles ( 0/2/1, 1/2/3, 2/4/3, 3/4/5, 4/6/5, 5/6/7, ...) int[] triangles = new int[vertices.Length * 3]; for (int i = 0; i < vertices.Length; i++) { if (clockwise) { triangles[3 * i] = i; triangles[3 * i + 1] = ((((i + 1) / 2) * 2) + 1) % vertices.Length; triangles[3 * i + 2] = (((i / 2) * 2) + 2) % vertices.Length; } else { // One column represents one triangle triangles[3 * i] = i; // 0, 1, 2, 3, 4, 5, ... triangles[3 * i + 1] = (((i / 2) * 2) + 2) % vertices.Length; // 2, 2, 4, 4, 6, 6, ... triangles[3 * i + 2] = ((((i + 1) / 2) * 2) + 1) % vertices.Length; // 1, 3, 3, 5, 5, 7, ... } } // Create the mesh Mesh msh = new Mesh(); msh.vertices = vertices; msh.triangles = triangles; msh.RecalculateNormals(); msh.RecalculateBounds(); GameObject border = new GameObject("Border (" + vertices.Length + ")"); MeshRenderer renderer = border.AddComponent <MeshRenderer>(); renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; renderer.receiveShadows = false; renderer.material = MapDisplayResources.Singleton.DefaultMaterial; renderer.material.color = c; MeshFilter filter = border.AddComponent <MeshFilter>(); filter.mesh = msh; return(border); }
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); }