Created
May 21, 2024 19:13
-
-
Save unitycoder/77311665cd1a6336e2fb593951be7feb to your computer and use it in GitHub Desktop.
Script to create a hemisphere mesh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://forum.unity.com/threads/script-to-create-a-hemisphere-mesh.496720/ | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class MakeSphereHemisphere : MonoBehaviour | |
{ | |
[Header("Sphere Options")] | |
public float radius = 1f; | |
[Range(1, 3)] | |
public int meshSmoothness = 1; | |
[Space] | |
[Header("Hemisphere Options")] | |
[Tooltip("Create north hemisphere only")] | |
public bool hemisphere = false; | |
[Tooltip("UV covers full sphere")] | |
public bool fullUvRange = true; | |
// Use this for initialization | |
void Start() | |
{ | |
MeshFilter mf = GetComponent<MeshFilter>(); | |
Make(mf); | |
FlipNormals(mf); | |
} | |
void Make(MeshFilter mf) | |
{ | |
Mesh mesh = mf.mesh; | |
mesh.Clear(); | |
// Longitude ||| | |
int nbLong = 24 * meshSmoothness; | |
// Latitude --- | |
int nbLat = 16 * meshSmoothness; | |
#region Vertices | |
Vector3[] vertices = new Vector3[(nbLong + 1) * ((hemisphere) ? nbLat / 2 : nbLat) + 2]; | |
float _pi = Mathf.PI; | |
float _2pi = _pi * 2f; | |
vertices[0] = Vector3.up * radius; | |
//for (int lat = 0; lat < nbLat; lat++) | |
for (int lat = 0; lat < ((hemisphere) ? nbLat / 2 : nbLat); lat++) | |
{ | |
float a1 = _pi * (float)(lat + 1) / (nbLat + 1); | |
float sin1 = Mathf.Sin(a1); | |
float cos1 = Mathf.Cos(a1); | |
for (int lon = 0; lon <= nbLong; lon++) | |
{ | |
float a2 = _2pi * (float)(lon == nbLong ? 0 : lon) / nbLong; | |
float sin2 = Mathf.Sin(a2); | |
float cos2 = Mathf.Cos(a2); | |
vertices[lon + lat * (nbLong + 1) + 1] = new Vector3(sin1 * cos2, cos1, sin1 * sin2) * radius; | |
} | |
} | |
vertices[vertices.Length - 1] = Vector3.up * -radius; | |
#endregion | |
#region Normals | |
Vector3[] normals = new Vector3[vertices.Length]; | |
for (int n = 0; n < vertices.Length; n++) | |
normals[n] = vertices[n].normalized; | |
#endregion | |
#region UVs | |
Vector2[] uvs = new Vector2[vertices.Length]; | |
uvs[0] = Vector2.up; | |
uvs[uvs.Length - 1] = Vector2.zero; | |
//for (int lat = 0; lat < nbLat; lat++) | |
for (int lat = 0; lat < ((hemisphere) ? nbLat / 2 : nbLat); lat++) | |
for (int lon = 0; lon <= nbLong; lon++) | |
{ | |
//uvs[lon + lat * (nbLong + 1) + 1] = new Vector2((float)lon / nbLong, 1f - (float)(lat + 1) / (nbLat + 1)); | |
if (!hemisphere || fullUvRange) uvs[lon + lat * (nbLong + 1) + 1] = new Vector2((float)lon / nbLong, 1f - (float)(lat + 1) / (nbLat + 1)); | |
else uvs[lon + lat * (nbLong + 1) + 1] = new Vector2((float)lon / nbLong, 1f - (float)(lat + 1) / (nbLat / 2)); | |
} | |
#endregion | |
#region Triangles | |
int nbFaces = vertices.Length; | |
int nbTriangles = nbFaces * 2; | |
int nbIndexes = nbTriangles * 3; | |
int[] triangles = new int[nbIndexes]; | |
//Top Cap | |
int i = 0; | |
for (int lon = 0; lon < nbLong; lon++) | |
{ | |
triangles[i++] = lon + 2; | |
triangles[i++] = lon + 1; | |
triangles[i++] = 0; | |
} | |
//Middle | |
for (int lat = 0; lat < ((hemisphere) ? nbLat / 2 : nbLat) - 1; lat++) | |
{ | |
for (int lon = 0; lon < nbLong; lon++) | |
{ | |
int current = lon + lat * (nbLong + 1) + 1; | |
int next = current + nbLong + 1; | |
triangles[i++] = current; | |
triangles[i++] = current + 1; | |
triangles[i++] = next + 1; | |
triangles[i++] = current; | |
triangles[i++] = next + 1; | |
triangles[i++] = next; | |
} | |
} | |
if (!hemisphere) | |
{ | |
//Bottom Cap | |
for (int lon = 0; lon < nbLong; lon++) | |
{ | |
triangles[i++] = vertices.Length - 1; | |
triangles[i++] = vertices.Length - (lon + 2) - 1; | |
triangles[i++] = vertices.Length - (lon + 1) - 1; | |
} | |
} | |
#endregion | |
mesh.vertices = vertices; | |
mesh.normals = normals; | |
mesh.uv = uvs; | |
mesh.triangles = triangles; | |
mesh.RecalculateBounds(); | |
} | |
void FlipNormals (MeshFilter filter) | |
{ | |
if (filter != null) | |
{ | |
Mesh mesh = filter.mesh; | |
Vector3[] normals = mesh.normals; | |
for (int i = 0; i < normals.Length; i++) | |
normals[i] = -normals[i]; | |
mesh.normals = normals; | |
for (int m = 0; m < mesh.subMeshCount; m++) | |
{ | |
int[] triangles = mesh.GetTriangles(m); | |
for (int i = 0; i < triangles.Length; i += 3) | |
{ | |
int temp = triangles[i + 0]; | |
triangles[i + 0] = triangles[i + 1]; | |
triangles[i + 1] = temp; | |
} | |
mesh.SetTriangles(triangles, m); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment