Search Unity

Procedural Sphere Generation

Discussion in 'Getting Started' started by fhilprec, Jan 6, 2019.

  1. fhilprec

    fhilprec

    Joined:
    Dec 21, 2018
    Posts:
    11
    I want to create a Sphere for generating planets. I started out with an Octaeder due to its easy shape and i didnt want to use a cube because i already saw that in the internet. This code here works it does create a sphere with a resolution that can varry. My problem is that due to my algorithm multiple vertices with the same coordinates are created which leads to performance issues at 4 to the power of 8 or so triangles. Moreover i cannot deform the mesh using perlin noise or something because i would have to extend multiple vectors. Also its not good in general to have multiple vertices with the same coordinates.

    Is there a way to change the algorith or to merge vertices or something like that?













    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Octaeder : MonoBehaviour
    {
    public GameObject prefab;
    Vector3[] newmid;
    public GameObject Planet;
    public int radius;
    private int x;
    [Range(0, 1)]
    public float ra;
    int[] oldtri;
    Mesh body;
    [Range(0, 7)]
    public int resolution;





    void OnValidate()
    {
    // GameObject Planet = new GameObject("Planet", typeof(MeshFilter), typeof(MeshRenderer));

    if (Planet.GetComponent<MeshFilter>() == null) { Planet.AddComponent<MeshFilter>(); }
    if (Planet.AddComponent<MeshRenderer>() == null) { Planet.AddComponent<MeshFilter>(); }


    body = new Mesh();
    int[] oldtri = new int[1325];
    List<Vector3> vertices = new List<Vector3>();
    List<int> triangles = new List<int>();
    Vector3[] verticesarray = vertices.ToArray();
    body.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;


    Planet.GetComponent<MeshFilter>().mesh = body; //creating an octaeder
    vertices.Add(new Vector3(1, 0, 1).normalized);
    vertices.Add(new Vector3(1, 0, -1).normalized);
    vertices.Add(new Vector3(-1, 0, -1).normalized);
    vertices.Add(new Vector3(-1, 0, 1).normalized);
    vertices.Add(new Vector3(0, 1, 0).normalized);
    vertices.Add(new Vector3(0, -1, 0).normalized);



    triangles.Add(0);
    triangles.Add(1);
    triangles.Add(4);
    triangles.Add(0);
    triangles.Add(5);
    triangles.Add(1);
    triangles.Add(3);
    triangles.Add(0);
    triangles.Add(4);
    triangles.Add(3);
    triangles.Add(5);
    triangles.Add(0);
    triangles.Add(3);
    triangles.Add(4);
    triangles.Add(2);
    triangles.Add(2);
    triangles.Add(5);
    triangles.Add(3);
    triangles.Add(1);
    triangles.Add(2);
    triangles.Add(4);
    triangles.Add(1);
    triangles.Add(5);
    triangles.Add(2);

    Debug.Log(triangles.Count / 3);;

    for (int go = 0; go < resolution; go++) //resolution loop (essentially just repeats the process)
    {


    int trianglepointscount = triangles.Count;

    for (x = 0; x < trianglepointscount / 3 ; x++) //looping through each surface
    {

    for (int y = 0; y < 3; y++) //looping through each vertices of that surface
    {
    oldtri[y] = triangles[x * 3 + y];

    }
    Vector3[] newmid = new Vector3[3]; //initiating the Vector3 for new Midpoints


    newmid[0] = (vertices[oldtri[0]] + vertices[oldtri[1]]) / 2;
    newmid[1] = (vertices[oldtri[1]] + vertices[oldtri[2]]) / 2;
    newmid[2] = (vertices[oldtri[2]] + vertices[oldtri[0]]) / 2;



    for (int c = 0; c < 3; c++)

    {
    newmid[c] = newmid[c].normalized;
    // newmid[c] = newmid[c].normalized * Random.Range(1.00f+ra,1.00f-ra);
    //newmid[c] = newmid[c].normalized * Mathf.PerlinNoise(1.00f+ra,1.00f-ra); //getting the vertices to have the same distance to the origin (which is equal to the radius)
    vertices.Add(newmid[c]);

    }
    int a = new int();
    a = vertices.Count - 1;


    for (int e = 0; e < 3; e++)
    {
    triangles.Add(a - 2 + e);

    }

    triangles.Add(oldtri[1]);
    triangles.Add(a - 1);
    triangles.Add(a - 2);

    triangles.Add(oldtri[0]);
    triangles.Add(a - 2);
    triangles.Add(a - 0);

    triangles.Add(oldtri[2]);
    triangles.Add(a - 0);
    triangles.Add(a - 1);







    /* for (int i = 0; i < vertices.Count; i++) //Test whether all vertices are added correctly (lowers performance drastically)
    {
    GameObject cube = Object.Instantiate(prefab) as GameObject;
    cube.transform.position = vertices;
    }*/

    }


    for (int delete = triangles.Count/3; delete>-1; delete--)
    {
    if (delete < 8 * Mathf.Pow(4, go)*3)
    {
    triangles.RemoveAt(delete);
    }

    }


    Debug.Log(triangles.Count/3 + " Dreiecke");

    Debug.Log(vertices.Count + " vertices");


    verticesarray = vertices.ToArray();
    body.RecalculateNormals();
    }
    Vector3[] zero = new Vector3[0];
    verticesarray = zero;
    verticesarray = vertices.ToArray();
    body.vertices = verticesarray;
    int[] trianglearray = triangles.ToArray();
    body.triangles = trianglearray;
    Planet.GetComponent<MeshRenderer>().material = new Material(Shader.Find("Standard"));
    body.RecalculateNormals();
    Planet.transform.localScale = new Vector3(radius, radius, radius);


    }
    }
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    1. Please use code tags to make your code readable.
    2. Don't believe everything you hear on the internet. I've done dynamic planets, and in my opinion, the cube sphere is by far the best way to manage this. The only tricky thing about it are the 8 points where 3 "faces" come together, but that's no worse than the many more tricky things about other geometries.
    3. Yes, of course vertices can be shared among multiple triangles. I can't easily read your code, so I don't know why/whether it's not already doing this.
     
  3. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,192
    That said it isn't very tricky when you can just follow a tutorial. Below is a series of tutorials covering procedural generation with the third part being the one in question.

    https://catlikecoding.com/unity/tutorials/procedural-grid/
    https://catlikecoding.com/unity/tutorials/rounded-cube/
    https://catlikecoding.com/unity/tutorials/cube-sphere/
    https://catlikecoding.com/unity/tutorials/mesh-deformation/
     
    Last edited: Jan 6, 2019
    JoeStrout likes this.
  4. fhilprec

    fhilprec

    Joined:
    Dec 21, 2018
    Posts:
    11
    I am sorry i dont know what code tags are. Its not that i think its wrong to use cubes but i didnt just want to copy things from the internet. Sorry but my problem is that they dont share points.
     
  5. fhilprec

    fhilprec

    Joined:
    Dec 21, 2018
    Posts:
    11