Generate procedural floating island
Asked Answered
S

2

0

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

163642-screen-shot-2020-07-19-at-092325.png

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:

Smarmy answered 27/3, 2024 at 13:49 Comment(1)

Have you figured it out?,Did you figure it out?

Northumbrian
E
0

This may not be what you’re looking for, but couldn’t you just model different islands and then choose a random one from the list? If you had about 20 different models, no one would ever be able to tell the difference anyway, but you could get exactly the kind of island you wanted.

Egotist answered 22/10, 2021 at 14:6 Comment(0)
S
0

you are pretty close, i used your code to get the required result.
on line 55 or something
y = cos1 - Mathf.PerlinNoise(Time.time*1f,0f) * 2f; this should probably not end in a hardcoded 2 but a height value since it will determin how low the bottom will be from the top.

   //check top half
  if (lat <= nbLat / 2)
  {
      z = (sin1 * sin2) * Random.Range(0f, 0.1f);
             
      var height = (cos1 * sin2) * Random.Range(0f, 0.1f);

      y = height;
  }

the last part i found through some trail and error. i added a slight height offset based on the sign wave thingy (i’m bad at math but can implement it.) to not make the top surface flat. hope this helps someone else out there.

String answered 27/3, 2024 at 13:49 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.