- Home /
Perlin Noise Spherical Terrain
So, I'm trying to figure out my own way of doing Procedural Planetary terrain a bit of a time. I can spherify a cube just fine, but when I try to implement some Perlin Noise, it usually ends up as a spike ball and shrinks. Here is my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PerlinHeightSingle: MonoBehaviour {
public float radius = 20;
public int size = 10;
public GameObject cube;
public float scale = 6.5f;
public float power = 3;
private Vector2 v2SampleStart = new Vector2(0, 0);
void Start(){
Mesh mesh = transform.GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
for(int i = 0; i < vertices.Length; i++){
vertices[i] = vertices[i].normalized * radius;
}
mesh.vertices = vertices;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
SetHeights();
}
void Update(){
if(Input.GetKeyUp(KeyCode.Space)){
v2SampleStart = new Vector2(Random.Range(0, 100), Random.Range(0, 100));
SetHeights();
}
}
void SetHeights(){
Mesh mesh = transform.GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
for (int i = 0; i < vertices.Length; i++) {
float xCoord = v2SampleStart.x + vertices[i].x * scale;
float yCoord = v2SampleStart.y + vertices[i].z * scale;
vertices[i] = vertices[i] * Mathf.PerlinNoise (xCoord, yCoord);
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
}
Answer by cclaypool1 · Dec 22, 2014 at 04:11 AM
I created something like this a while back. Take a look, the source is available. link text
here is some relevant code too
using UnityEngine;
using System.Collections;
using LibNoise.Unity;
using LibNoise.Unity.Generator;
using LibNoise.Unity.Operator;
public class Normalize : MonoBehaviour {
private Mesh gameMesh;
Vector3[] vertices;
Vector3[] verticesN;
public float radius = 1f;
public RidgedMultifractal noise = new RidgedMultifractal();
public float frequency = 10f;
public float noisemod = 1f;
private MeshCollider meshCollider;
void Start () {
gameMesh = GetComponent<MeshFilter>().mesh;
meshCollider = GetComponent<MeshCollider>();
Vector3[] vertices = gameMesh.vertices;
Vector3[] verticesN = gameMesh.vertices;
noise.Frequency = frequency;
for (int i = 0; i < vertices.Length; i++)
{
verticesN[i] = (vertices[i].normalized * (radius + (float)noise.GetValue(verticesN[i].normalized)*noisemod));
}
gameMesh.vertices = verticesN;
gameMesh.RecalculateNormals();
gameMesh.RecalculateBounds();
meshCollider.sharedMesh = gameMesh;
}
Awesome, thanks for sharing your source. It would be great if you could take the relevant part and edit it into your answer.
Awesome! Thank you. I'll have to $$anonymous$$r your code apart and see what I can learn.
I'm testing out your scripts and it seems everytime I enter the planet's atmosphere, the ground turns to that horrible pink texture. The atmosphere works just fine, but can't see the terrain while in the planet.
Answer by justin35f · Dec 21, 2014 at 08:37 AM
First of all, Unity's Mathf.PerlinNoise function is honestly not that useful, as you have no access to any of the parameters, setting the seed, etc...
In regards to your issue, my first check would be on the xCoord and yCoord values. Generally speaking, noise functions don't play well with whole numbers, and do much better with decimals. As a test add something random like 0.0654f to each of those, and see if it does the trick, or at least improves it a bit. If so, then the next step would be to create your own noise functions so that you have finer grain control on what's going on.
Yeah, that didn't work. Any idea where I can get examples of writing my own Perlin Generator?
ahh, I didn't notice it before, but you are multiplying your Vector3 position for the vertices by your perlin noise value. The issue is that it is adjusting all three (x, y, z) positions. What you actually want is to adjust just the height component. Also, in Unity 3D, height is generally represented by the y axis, so you should be putting the xCoord and the zCoord into your perlin noise function, then setting your yCoord to whatever is returned.
You may need to massage that a little bit to fit whatever you are doing with the spherical terrain, but that should fix the issue.
So, if it's a cube sphere, would it still be along the y, or along the normals? How would that line look like in code?
Honestly, I've never done a cube sphere, but I do know that you want to use the noise value for your height. You use the other coordinates as parameters in the noise function.