首页 > 解决方案 > 统一生成程序浮岛

问题描述

我想统一制作简单的低多边形程序生成浮岛,如下所示:

浮岛

所以我决定制作一个简单的球体,然后将顶部变平并随机生成底部噪声,但我尝试了几次都没有得到我想要的结果,比如正确的曲线并且没有锥度。

在此处输入图像描述

我怎样才能得到正确的网格结果?我的代码有问题吗?还是我可以使用另一种算法?

到目前为止我使用的代码:

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;


    // Start is called before the first frame update
    void Start()
    {
        
       StartCoroutine(createMesh());
    }

    // Update is called once per frame
    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;
    }
}

我参考了:

标签: c#unity3dprocedural-generation

解决方案


推荐阅读