I want make simple lowpoly procedural generation floating island in Unity, like this:
I decided to make a simple sphere then I flattened the top and randomly generated the bottom noise but several times I tried I did not get the results I wanted, like a right curve and no taper
How can I get results the right mesh? Is there something wrong with my code? or is there another algorithm that I can use?
The code I’ve used so far…
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphereGenerator : MonoBehaviour
{
public float minRadius = 1f;
Vector3[] vertices;
Vector3[] normales;
Vector2[] uvs;
int[] triangles;
MeshFilter filter;
void Start()
{
StartCoroutine(createMesh());
}
void Update()
{
updateMesh();
}
IEnumerator createMesh(){
float radius = minRadius;
// Longitude |||
int nbLong = 24;
// Latitude ---
int nbLat = 16;
#region Vertices
vertices = new Vector3[(nbLong+1) * nbLat + 2];
float _pi = Mathf.PI;
float _2pi = _pi * 2f;
vertices[0] = Vector3.zero;
float y = 0f;
for( int lat = 0; lat < 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);
y = cos1 - Mathf.PerlinNoise(Time.time*1f,0f) * 2f;
float x = Time.time*(sin1 * cos2) * Random.Range(0f,1f);
float z = Time.time*(sin1 * sin2) * Random.Range(0f,1f);
//check top half
if(lat <= nbLat/2){
// float height = Random.Range(0f,0.1f);
// Debug.Log(height);
// y = height;
y = 0f;
} else {
z = (sin1 * sin2) * Random.Range(0f,1f);
}
float newRad = radius;
newRad = radius + Mathf.PerlinNoise(x,z) * 2f;
vertices[ lon + lat * (nbLong + 1) + 1] = new Vector3( sin1 * cos2, y, sin1 * sin2 ) * newRad;
}
}
vertices[vertices.Length-1] = Vector3.up * (-radius + y - Random.Range(0f,1f));
#endregion
#region Normales
normales = new Vector3[vertices.Length];
for( int n = 0; n < vertices.Length; n++ )
normales[n] = vertices[n].normalized;
#endregion
#region UVs
uvs = new Vector2[vertices.Length];
uvs[0] = Vector2.up;
uvs[uvs.Length-1] = Vector2.zero;
for( int lat = 0; lat < 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) );
#endregion
#region Triangles
int nbFaces = vertices.Length;
int nbTriangles = nbFaces * 2;
int nbIndexes = nbTriangles * 3;
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 < 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;
yield return new WaitForSeconds(.05f);
}
}
//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
}
void updateMesh(){
filter = gameObject.GetComponent< MeshFilter >();
Mesh mesh = new Mesh();
mesh.Clear();
mesh.vertices = vertices;
mesh.normals = normales;
mesh.uv = uvs;
mesh.triangles = triangles;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.Optimize();
filter.mesh = mesh;
}
}
I have taken references from:
Have you figured it out?,Did you figure it out?
– Northumbrian