| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- 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<Quad> 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<Quad> { 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<pqsResolution + 1; x++, vertex++)
- {
- for (int z = 1; z<pqsResolution + 1; z++, vertex++)
- {
- triangles[triangle] = vertex;
- triangles[triangle + 1] = vertex + pqsResolution + 2;
- triangles[triangle + 2] = vertex + pqsResolution + 1;
- triangles[triangle + 3] = vertex;
- triangles[triangle + 4] = vertex + 1;
- triangles[triangle + 5] = vertex + pqsResolution + 2;
- triangle += 6;
- }
- }
- return triangles;
- }
- private void CreateMesh(string name, Vector3[] vertices, Vector2[] uv, int[] triangles)
- {
- var mesh = new GameObject(name, typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider));
- mesh.transform.localScale = new Vector3(1, 1, 1);
- var meshFilter = mesh.GetComponent<MeshFilter>();
- meshFilter.mesh.vertices = vertices;
- meshFilter.mesh.triangles = triangles;
- meshFilter.mesh.uv = uv;
- mesh.GetComponent<MeshCollider>().sharedMesh = meshFilter.mesh;
- meshFilter.mesh.RecalculateBounds();
- meshFilter.mesh.RecalculateNormals();
- mesh.GetComponent<MeshRenderer>().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];
- }
- }
- }
- }
- }
- }
- }
|