using System.Collections.Generic; using UnityEngine; public class PlaneGenerator : MonoBehaviour { public Material material; public float noiseLevel = 0.1f; public float noiseScale = 0.1f; private const int pqsResolution = 8; private const int sphereRadius = 2; 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() { var quadY = new Quad(); var quadY1 = new Quad(); var quadZ = new Quad(); var quadZ1 = new Quad(); var quadX = new Quad(); var quadX1 = new Quad(); quadY = BuildRootQuad( id: 1, eulerAngles: new Vector3(0, 0, 0), upperQuad: null, // quadX1, rightQuad: null, // quadZ, lowerQuad: null, // quadX, leftQuad: null); // quadZ1); quadZ = BuildRootQuad( id: 3, eulerAngles: new Vector3(-90, 0, 0), upperQuad: null, // quadX, rightQuad: null, lowerQuad: null, leftQuad: quadY); quadZ1 = BuildRootQuad( id: 4, eulerAngles: new Vector3(90, 0, 0), upperQuad: null, // quadX, rightQuad: quadY, lowerQuad: null, leftQuad: null); quadX = BuildRootQuad( id: 5, eulerAngles: new Vector3(0, 0, 90), upperQuad: quadY, rightQuad: null, // quadZ lowerQuad: null, leftQuad: null); //quadZ1 quadX1 = BuildRootQuad( id: 6, eulerAngles: new Vector3(0, 0, -90), upperQuad: null, rightQuad: null, lowerQuad: quadY, leftQuad: null); ////quadY1 = BuildRootQuad(2, new Vector3(180, 0, 0)); ////quadZ = BuildRootQuad(3, new Vector3(-90, 0, 0)); ////quadZ1 = BuildRootQuad(4, new Vector3(90, 0, 0)); ////quadX = BuildRootQuad(5, new Vector3(0, 0, -90)); ////quadX1 = BuildRootQuad(6, new Vector3(0, 0, 90)); quads = new List { quadY, quadY1, quadZ, quadZ1, quadX, quadX1 }; } private Quad BuildRootQuad( int id, Vector3 eulerAngles, Quad? upperQuad, Quad? rightQuad, Quad? lowerQuad, Quad? leftQuad) { var (vertices, uv) = CreateVertices(); Rotate(vertices, eulerAngles); AddHeights( vertices, upperQuad, rightQuad, lowerQuad, leftQuad); var triangles = CreateTriangles(); return new Quad { Id = id, Vertices = vertices, Triangles = triangles, Uv = uv }; } private void UpdateMeshes() { foreach (var quad in quads) { CreateMesh($"quad_{quad.Id}", 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; x++) { for (int z = 0; z <= pqsResolution; z++, vertex++) { vertices[vertex] = new Vector3((float)x / pqsResolution * sphereRadius - half, half, (float)z / pqsResolution * sphereRadius - half); 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; x++) { for (int z = 0; z <= pqsResolution; 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 Mathf.PerlinNoise(x * noiseScale, y * noiseScale) * noiseLevel; } private void AddHeights( Vector3[] vertices, Quad? upperQuad, Quad? rightQuad, Quad? lowerQuad, Quad? leftQuad) { for (int x = 0, vertex = 0; x <= pqsResolution; x++) { for (int z = 0; z <= pqsResolution; z++, vertex++) { if (x == 0 && lowerQuad?.Vertices != null) { vertices[vertex] = lowerQuad.Value.Vertices[(pqsResolution + 1) * pqsResolution + z]; //+ } else if (x == pqsResolution && upperQuad?.Vertices != null) { vertices[vertex] = upperQuad.Value.Vertices[z]; } else if (z == 0 && rightQuad?.Vertices != null) { vertices[vertex] = rightQuad.Value.Vertices[(pqsResolution + 1) * (x + 1) - 1]; //+ } else if (z == pqsResolution && leftQuad?.Vertices != null) { vertices[vertex] = leftQuad.Value.Vertices[x * (pqsResolution + 1)]; //+ } else { var noise = 1 + GetNoise(Random.value, Random.value); vertices[vertex] = noise * sphereRadius * vertices[vertex]; } } } } private void OnDrawGizmos() { var gizmoSize = 0.05f; if (quads != null) { foreach (var quad in quads) { if (quad.Vertices == null) continue; for (int x = 0, vertex = 0; x <= pqsResolution; x++) { for (int z = 0; z <= pqsResolution; z++, vertex++) { if (x == 0) { Gizmos.DrawSphere(quad.Vertices[vertex], gizmoSize); } else if (x == pqsResolution) { Gizmos.DrawWireSphere(quad.Vertices[vertex], gizmoSize); } else if (z == 0) { Gizmos.DrawCube(quad.Vertices[vertex], new Vector3(gizmoSize, gizmoSize, gizmoSize)); } else if (z == pqsResolution) { Gizmos.DrawWireCube(quad.Vertices[vertex], new Vector3(gizmoSize, gizmoSize, gizmoSize)); } else { var noise = 1; // 1 + GetNoise(Random.value, Random.value); //vertices[vertex] = noise * sphereRadius * vertices[vertex]; } } } } } } }