using System.Collections.Generic; using UnityEngine; public class PlaneGenerator : MonoBehaviour { public Material material; public float noiseLevel = 0.1f; private const int pqsResolution = 16; private const int sphereRadius = 10; private List quads; // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { BuildRootQuads(); UpdateMeshes(); } // Update is called once per frame void Update() { } private void BuildRootQuads() { quads = new List { BuildQuad("quadY", new Vector3(0, 0, 0)), BuildQuad("quadY1", new Vector3(180, 0, 0)), BuildQuad("quadZ", new Vector3(90, 0, 0)), BuildQuad("quadZ1", new Vector3(-90, 0, 0)), BuildQuad("quadX", new Vector3(0, 0, 90)), BuildQuad("quadX1", new Vector3(0, 0, -90)) }; } private Quad BuildQuad(string name, Vector3 eulerAngles) { var (vertices, uv) = CreateVertices(); Rotate(vertices, eulerAngles); var triangles = CreateTriangles(); return new Quad { Name = name, Vertices = vertices, Triangles = triangles, Uv = uv }; } private void UpdateMeshes() { foreach (var quad in quads) { CreateMesh(quad.Name, quad.Vertices, quad.Uv, quad.Triangles); } } private (Vector3[] vertices, Vector2[] uv) CreateVertices() { var half = sphereRadius / 2f; var vertices = new Vector3[(pqsResolution + 1) * (pqsResolution + 1)]; Vector2[] uv = new Vector2[(pqsResolution + 1) * (pqsResolution + 1)]; for (int x = 0, vertex = 0; x < pqsResolution + 1; x++) { for (int z = 0; z < pqsResolution + 1; z++, vertex++) { vertices[vertex] = new Vector3(half - (float)x / pqsResolution * sphereRadius, half, half - (float)z / pqsResolution * sphereRadius); uv[vertex] = new Vector2((float)x / pqsResolution, (float)z / pqsResolution); } } return (vertices, uv); } private int[] CreateTriangles() { var triangles = new int[(pqsResolution) * (pqsResolution) * 6]; int triangle = 0; for (int x = 1, vertex = 0; x(); meshFilter.mesh.vertices = vertices; meshFilter.mesh.triangles = triangles; meshFilter.mesh.uv = uv; mesh.GetComponent().sharedMesh = meshFilter.mesh; meshFilter.mesh.RecalculateBounds(); meshFilter.mesh.RecalculateNormals(); mesh.GetComponent().material = material; } private void Rotate(Vector3[] vertices, Vector3 eulerAngles) { for (int x = 0, vertex = 0; x < pqsResolution + 1; x++) { for (int z = 0; z < pqsResolution + 1; z++, vertex++) { vertices[vertex] = Rotate(vertices[vertex], eulerAngles); vertices[vertex] = Vector3.Normalize(vertices[vertex]); } } } private Vector3 Rotate(Vector3 vertex, Vector3 eulerAngles) { var result = vertex; if (eulerAngles.x != 0) result = RotateX(result, eulerAngles.x); if (eulerAngles.y != 0) result = RotateY(result, eulerAngles.y); if (eulerAngles.z != 0) result = RotateZ(result, eulerAngles.z); return result; } private Vector3 RotateX(Vector3 vertex, float angle) { var angleDeg = Mathf.Deg2Rad * angle; return new Vector3( x: vertex.x, y: vertex.y * Mathf.Cos(angleDeg) - vertex.z * Mathf.Sin(angleDeg), z: vertex.y * Mathf.Sin(angleDeg) + vertex.z * Mathf.Cos(angleDeg)); } private Vector3 RotateY(Vector3 vertex, float angle) { var angleDeg = Mathf.Deg2Rad * angle; return new Vector3( x: vertex.x * Mathf.Cos(angleDeg) + vertex.z * Mathf.Sin(angleDeg), y: vertex.y, z: -vertex.x * Mathf.Sin(angleDeg) + vertex.z * Mathf.Cos(angleDeg)); } private Vector3 RotateZ(Vector3 vertex, float angle) { var angleDeg = Mathf.Deg2Rad * angle; return new Vector3( x: vertex.x * Mathf.Cos(angleDeg) - vertex.y * Mathf.Sin(angleDeg), y: vertex.x * Mathf.Sin(angleDeg) + vertex.y * Mathf.Cos(angleDeg), z: vertex.z); } private float GetNoise(float x, float y) { return 1 + Mathf.PerlinNoise(x, y) * noiseLevel; } private void AddHeights(Vector3[] vertices) { for (int x = 0, vertex = 0; x < pqsResolution + 1; x++) { for (int z = 0; z < pqsResolution + 1; z++, vertex++) { var noise = 1; // GetNoise(vertices[vertex].x, vertices[vertex].y); vertices[vertex] = noise * sphereRadius * vertices[vertex]; } } vertices[pqsResolution + 3] *= 2f; } }