-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMeshGenerator.cs
More file actions
194 lines (144 loc) · 9.3 KB
/
Copy pathMeshGenerator.cs
File metadata and controls
194 lines (144 loc) · 9.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/* ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//
-------------------------------------- MESH GENERATOR (MAIN SCRIPT) ------------------------------------------
- SUMMARY: This script allows generates and stores the mesh properties such as vertices, triangles, normals, uvs, colours, etc. It shades the mesh according to a
gradient using a vertex shader. It allows for mesh generation using a 3 octave Perlin Noise algorithm.
- USED IN: (MeshInteractor.cs) Most of the functionality references the mesh created in this script
- FOUND ON: 'Mesh Renderer' Game Object in Unity.
// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
// Namespaces -------------------------------------------
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))] // This makes it require a mesh filter just so a mesh is not added to nothing. Unity will crash if this happens, most likely.
public class MeshGenerator : MonoBehaviour
{
// VARIABLES -----------------------------------------------------------------------------------------------------------------------------------------------------------------
Mesh mesh; // Unity native 'mesh' object - picked up by Mesh Filter and , consequently, Mesh Renderer scripts that are also on the mesh Game Object in Unity
// Arrays to hold vertices, triangles and colours ---------------------
public Vector3[] vertices; // Vector3 = (x,y,z) for vertices in the scene
public int[] triangles; // int = (n) for triangles. Used as indices basically with three vertices indicating the position of the triangle.
public Color[] colours; // Unity native colour object defined in RGB. Used with Colour Gradient on Unity object by reference.
// For grid of quads (made up of triangles made up of vertices) -------
public int xSize = 20; // Indicates total number of vertices in a row. Number of Quads in the row = (xSize - 1)
public int zSize = 20; // No. of vertices in a column
public float verticeScale = 1.0f;
public float verticeRadius = 2.0f;
public GameObject[] selectors;
// Perlin Noise variables ---------------------------------------------
[Header("Noise")]
[SerializeField]private bool isPerlinNoise = true;
[SerializeField]private List<NoiseLayer> noiseLayers = new();
/*#if UNITY_EDITOR
// This method updates / generates new plane.
// Called from editor script on change.
public void UpdatePlane()
{
CreateShape();
UpdateMesh();
}
#endif*/
// Colour Variables ---------------------------------------------------
public Gradient gradient; // Unity object has reference to editable gradient
[HideInInspector] public float minHeight; // To set the gradient according to min and max as it takes minimum and maximum value arguments
[HideInInspector] public float maxHeight;
// FUNCTIONS ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Start() ---------------------------------------------------------------------
void Start()
{
mesh = new Mesh(); // Create new mesh object
GetComponent<MeshFilter>().mesh = mesh; // Indicate to the MeshFilter that its mesh component is the mesh we create here
GetComponent<MeshCollider>().sharedMesh = mesh;
//mesh.GetComponent<Collider>().enabled = true;
CreateShape(); // Creates the shape
UpdateMesh(); // Updates it on the beginning frame
}
// CreateShape() ---------------------------------------------------------------
/// <summary>
/// For creating the vertices, triangles, uvs, and colours of the mesh plane for the first time.
/// </summary>
void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)]; // Create a new Vector3 array the size of the indicated grid. (xSize + 1) because it takes (n + 1) vertices to create a grid with n quads per row/column
selectors = new GameObject[(xSize + 1) * (zSize + 1)]; // Selectors array same size as vertices array
// Creating vertices ------------------------------
for (int z = 0, i = 0; z <= zSize; z++) // Nested for-loops to go through all rows and columns
{
for (int x = 0; x <= xSize; x++)
{
float y = 0;
vertices[i] = (new Vector3(x, y, z) - new Vector3(xSize / 2f, 0, zSize / 2f)) * verticeScale;
// Calculating elevation from noise layers.
if (isPerlinNoise)
{
float elevation = 0;
for (int l = 0; l < noiseLayers.Count; l++)
{
elevation += noiseLayers[l].Elevate(x / (float)xSize, z / (float)zSize); // Adding layers of Perlin Noise according to number of layers added in Inspector
}
vertices[i].y = elevation * verticeScale; // Adding elevation from perlin noise.
}
// Recording minHeight and maxHeight for Gradient
if (vertices[i].y > maxHeight) maxHeight = vertices[i].y; // Update minHeight and maxHeight according to y generated using Perlin Noise
if (vertices[i].y < minHeight) minHeight = vertices[i].y; // At the end, we should have a variable measure of the max height and the min height in the generation.
// Creating Selector spheres at each vertice
selectors[i] = GameObject.CreatePrimitive(PrimitiveType.Cube);
selectors[i].transform.localScale = new Vector3(0.05f, 0.05f, 0.05f) * verticeRadius;
selectors[i].transform.position = (new Vector3(x, vertices[i].y / verticeScale, z) - new Vector3(xSize / 2f, 0, zSize / 2f)) * verticeScale; // Applying same transform as vertices[i] before nested for loops
selectors[i].GetComponent<Collider>().enabled = false; // Disable the colliders of the collision spheres
i++; // Increment i inside the row loop, after every run
}
}
// Creating Triangles --------------------------
triangles = new int[xSize * zSize * 6]; // New array for storing all triangles. Total number of triangles = no. of quads desired * 6 (no. of vertices for each quad). Two triangles per quad.
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++) // Nested for-loops to go through all rows and columns
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0; // Six vertices need to be defined for every triangle. Every six subsequent int values in the triangles array indicate one full quad with both triangles drawn clockwise
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++; // Skip generating a triangle from one row to another
}
// Colouring triangles ---------------------------
colours = new Color[vertices.Length];
for (int z = 0, i = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
//float height = vertices[i].y / 0.5f;
float height = Mathf.Abs( 1 - Mathf.InverseLerp(minHeight, maxHeight, vertices[i].y)); // Lerp between maximum and minimum height and give value between 0 and 1
//Debug.Log("height: " + height + " " + minHeight + " " + maxHeight);
colours[i] = gradient.Evaluate(height);
i++;
}
}
}
// UpdateMesh() --------------------------------------------------------------------
/// <summary>
/// For updating the mesh objects vertices on every frame
/// </summary>
void UpdateMesh()
{
mesh.Clear(); // Clear after previous frame
mesh.vertices = vertices; // Mesh creation in Unity takes these elements to be defined
mesh.triangles = triangles;
mesh.colors = colours;
mesh.RecalculateNormals(); // Unity calculates normals for all surfaces for lighting
}
// Update is called once per frame
void Update()
{
UpdateMesh(); // Updates it every frame
//Debug.Log(selectors[45].transform.position); // Way to reference the selctor sphere's position
//Debug.Log(Time.deltaTime);
}
}