0

I have been trying to figure out how to create wave effect on a 3d sphere using Perlin Noise

I have found some tutorials on how to do it on a plane, however, none on a 3d object, This code works just fine on a plane, does anyone know how to adapt it on a 3d sphere ? Thank you in advance for your help

using UnityEngine;
using System.Collections;
public class PerlinTerrain : MonoBehaviour {

    public float perlinScale;
    public float waveSpeed;
    public float waveHeight;
    public float offset;

    void Update () {
        CalcNoise();
    }

    void CalcNoise() {
        MeshFilter mF = GetComponent<MeshFilter>();
        MeshCollider mC = GetComponent<MeshCollider>();

        mC.sharedMesh = mF.mesh;

        Vector3[] verts = mF.mesh.vertices;

        for (int i=0; i< verts.Length; i++) {
            float pX = (verts[i].x * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            float pZ = (verts[i].z * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            verts[i].y = Mathf.PerlinNoise(pX, pZ) * waveHeight;
        }

        mF.mesh.vertices = verts;
        mF.mesh.RecalculateNormals();
        mF.mesh.RecalculateBounds();
    }

}

  • It might help if you linked to the tutorial you are following. There's at least 2 very different ways that you could have a Perlin noise based sphere: you could either carve a sphere out of 3d noise, or you could cover the outside of the sphere with 2d noise. – Pikalek Aug 27 '19 at 13:49

2 Answers2

0

The easiest way would be to apply the 2D noise to the surface. You could do this by using the vertex normal to know which way you should move the position to.

In your code you are only moving the Y position. For a plane this means you moved the vertex in its normal direction by the amount that the noise function gives you. For a spheere you could do something like this:

verts[i] = verts[i] + (Mathf.PerlinNoise(pX, pZ) * waveHeight * mF.mesh.normals[i].normalized);

This will work for any mesh because it takes in account its original position and just moves the vertex in the direction of its normal.

This will move the vertex up which means it will always be higher than original position, you can apply a simple offset to the noise function to make it go lower as well

verts[i] = verts[i] + ((Mathf.PerlinNoise(pX, pZ) - 0.5f) * waveHeight * mF.mesh.normals[i].normalized);

I noticed you are animating this noise, its important to take the original mesh each update and not the new one that had noise applied to it. So in the end it would look something like this

using UnityEngine;
using System.Collections;

public class PerlinTerrain : MonoBehaviour
{

    public float perlinScale;
    public float waveSpeed;
    public float waveHeight;
    public float offset;

    Vector3[] baseVertices;

    private void OnEnable()
    {
        MeshFilter mF = GetComponent<MeshFilter>();

        baseVertices = mF.mesh.vertices;
    }

    void Update()
    {
        CalcNoise();
    }

    void CalcNoise()
    {
        MeshFilter mF = GetComponent<MeshFilter>();

        mF.sharedMesh.vertices = baseVertices;
        mF.sharedMesh.RecalculateNormals();

        Vector3[] verts = mF.sharedMesh.vertices;

        for (int i = 0; i < verts.Length; i++)
        {
            float pX = (verts[i].x * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            float pZ = (verts[i].z * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            verts[i] = verts[i] + ((Mathf.PerlinNoise(pX, pZ)) * waveHeight * mF.sharedMesh.normals[i].normalized);
        }

        mF.sharedMesh.vertices = verts;
    }
}

But you still have 1 problem. There are multiple vertices that have the same position but have different normal. You will have to figure out which vertices are shared and calculate its normal.

Group the vertices by its position and take the average normal and only iterate over each unique vertex once.

-3

Because it would be called simplex noise

https://en.wikipedia.org/wiki/Simplex_noise

Perlin is the specific name of 2D version

Thaina Yu
  • 1,372
  • 2
  • 16
  • 27
  • 2
    Sorry, but where is it stated Perlin Noise is only 2D and Simplex is the 3D representation? – Ryanas Aug 27 '19 at 11:07
  • Is it not ? So what is Simplex Noise ? – Gauthier Barbosa Aug 27 '19 at 11:30
  • This answer is incorrect. "Perlin noise is most commonly implemented as a two-, three- or four-dimensional function, but can be defined for any number of dimensions." [source](https://en.wikipedia.org/wiki/Perlin_noise#Algorithm_detail). Simplex noise is a method for constructing an n-dimensional noise function comparable to Perlin noise ... but with fewer directional artifacts and, in higher dimensions, a lower computational overhead. They are similar, but different n-dimensional gradient noise functions. – Pikalek Aug 27 '19 at 13:45
  • This is the tutorial that I have followed : https://pastebin.com/enKSz6Mm, would you help me by proposing me a method to implement the code to a 3 dimension object – Gauthier Barbosa Aug 27 '19 at 15:33