Generating Y values for dynamically generated terrain LOD
I'm having a problem generating Y values from perlin noise function. Current way I do it every patch looks the same. I'm generating meshes recursively so I don't know which patch I am.
LOD 0: http://i.imgur.com/1BpZ2Dg.png Rest: http://i.imgur.com/aelH8PV.png
Generation part:
Vector3[] vertices;
vertices = new Vector3[(int)((patchSize + 1) * (patchSize + 1))];
Vector2[] uv = new Vector2[vertices.Length];
for (int i = 0, x = 0; x <= patchSize; x += 1) {
for (int z = 0; z <= patchSize; z += 1, i++) {
vertices[i] = new Vector3(z * size/patchSize,
Mathf.PerlinNoise(meshObject.transform.TransformPoint(x+currentDepth*size, 0, 0).x / noiseXZScale,
meshObject.transform.TransformPoint(z+currentDepth*size, 0, 0).x / noiseXZScale) * noiseYScale,
x* size/patchSize);
/*// map to sphere
vertices[i].Normalize();
vertices[i] *= 100;*/
uv[i] = new Vector2((float)x / patchSize, (float)z / patchSize);
}
}
Whole code: (attach script to empty gameobject centered in 0 0 0)
using UnityEngine;
using System.Collections;
public class Neomex_QuadTreeTerrain : MonoBehaviour {
public GameObject parent;
//Neomex_QuadTreeTerrain [] children;
public GameObject [] children = null;
public Vector3 center;
public float size;
public int maxDepth = 2;
int currentDepth = 0;
public int patchSize = 33;
public GameObject target;
public float noiseYScale = 10.0f;
public float noiseXZScale = 30.0f;
GameObject meshObject;
Mesh mesh;
[HideInInspector]
public bool wasMeshGenerated = false;
[HideInInspector]
public bool childrenExist = false;
public Texture2D texture;
public void init(GameObject parent, Vector3 center, float size, int maxDepth, int currentDepth, int patchSize, GameObject target, float noiseYScale, float noiseXZScale, Texture2D texture) {
this.parent = parent;
this.center = center;
this.size = size;
this.maxDepth = maxDepth;
this.currentDepth = currentDepth;
this.patchSize = patchSize;
this.target = target;
this.texture = texture;
}
void Awake() {
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (IsTargetInside () == false) {
if (wasMeshGenerated == false)
GenerateMesh ();
if(childrenExist)
DeleteChildren ();
}
if (IsTargetInside () == true) {
if (wasMeshGenerated == true)
DeleteMesh ();
if (childrenExist == false && currentDepth < maxDepth)
GenerateChildren ();
if (childrenExist == false && currentDepth >= maxDepth) {
GenerateMesh ();
}
}
}
bool IsTargetInside() {
Vector3 targetPosition = target.transform.position;
if (targetPosition.x > center.x - size && targetPosition.x < center.x + size &&
targetPosition.z > center.z - size && targetPosition.z < center.z + size )
return true; else return false;
}
void GenerateChildren() {
childrenExist = true;
children = new GameObject[4];
for (int i = 0; i < 4; i++)
children [i] = new GameObject ();
// TOP LEFT
children [0].name = "TL at level: " + currentDepth;
children [0].transform.parent = this.gameObject.transform;
children [0].AddComponent<Neomex_QuadTreeTerrain> ();
children [0].GetComponent<Neomex_QuadTreeTerrain> ().init(this.gameObject,
new Vector3 (center.x - size / 4, 0, center.z - size / 4),
size / 2,
maxDepth,
currentDepth+1,
patchSize,
target,
noiseYScale,
noiseXZScale,
texture);
// TOP RIGHT
children [1].name = "TR at level: " + currentDepth;
children [1].transform.parent = this.gameObject.transform;
children [1].AddComponent<Neomex_QuadTreeTerrain> ();
children [1].GetComponent<Neomex_QuadTreeTerrain> ().init(this.gameObject,
new Vector3 (center.x + size / 4, 0, center.z - size / 4),
size / 2,
maxDepth,
currentDepth+1,
patchSize,
target,
noiseYScale,
noiseXZScale,
texture);
// BOTTOM RIGHT
children [2].name = "BR at level: " + currentDepth;
children [2].transform.parent = this.gameObject.transform;
children [2].AddComponent<Neomex_QuadTreeTerrain> ();
children [2].GetComponent<Neomex_QuadTreeTerrain> ().init(this.gameObject,
new Vector3 (center.x + size / 4, 0, center.z + size / 4),
size / 2,
maxDepth,
currentDepth+1,
patchSize,
target,
noiseYScale,
noiseXZScale,
texture);
// BOTTOM LEFT
children [3].name = "BL at level: " + currentDepth;
children [3].transform.parent = this.gameObject.transform;
children [3].AddComponent<Neomex_QuadTreeTerrain> ();
children [3].GetComponent<Neomex_QuadTreeTerrain> ().init(this.gameObject,
new Vector3 (center.x - size / 4, 0, center.z + size / 4),
size / 2,
maxDepth,
currentDepth+1,
patchSize,
target,
noiseYScale,
noiseXZScale,
texture);
}
void DeleteMesh() {
Destroy (meshObject);
mesh = null;
meshObject = null;
wasMeshGenerated = false;
}
void DeleteChildren() {
childrenExist = false;
//Debug.Log (children.Length);
//if(children != null)
//if(children.Length == 4)
for (int i = 0; i < 4; i++) {
Destroy (children [i]);
children[i] = null;
}
children = null;
}
void GenerateMesh() {
wasMeshGenerated = true;
meshObject = new GameObject ();
meshObject.name = "Mesh at level: " + currentDepth;
meshObject.AddComponent<MeshFilter> ();
meshObject.AddComponent<MeshRenderer> ();
meshObject.transform.position = center - new Vector3(size/2, 0, size/2);
Vector3[] vertices;
vertices = new Vector3[(int)((patchSize + 1) * (patchSize + 1))];
Vector2[] uv = new Vector2[vertices.Length];
for (int i = 0, x = 0; x <= patchSize; x += 1) {
for (int z = 0; z <= patchSize; z += 1, i++) {
vertices[i] = new Vector3(z * size/patchSize,
Mathf.PerlinNoise(meshObject.transform.TransformPoint(x+currentDepth*size, 0, 0).x / noiseXZScale,
meshObject.transform.TransformPoint(z+currentDepth*size, 0, 0).x / noiseXZScale) * noiseYScale,
x* size/patchSize);
/*// map to sphere
vertices[i].Normalize();
vertices[i] *= 100;*/
uv[i] = new Vector2((float)x / patchSize, (float)z / patchSize);
}
}
int[] triangles = new int[(int)(patchSize * patchSize * 6)];
for (int ti = 0, vi = 0, z = 0; z < patchSize; z++, vi++) {
for (int x = 0; x < patchSize; x++, ti += 6, vi++) {
triangles[ti] = vi;
triangles[ti + 3] = triangles[ti + 2] = vi + 1;
triangles[ti + 4] = triangles[ti + 1] = vi + (int)patchSize + 1;
triangles[ti + 5] = vi + (int)patchSize + 2;
}
}
mesh = new Mesh ();
mesh.name = "TerrainQuad - Level: " + currentDepth;
mesh.vertices = vertices;
mesh.uv = uv;
mesh.triangles = triangles;
mesh.RecalculateNormals();
Neomex_TangentSolver.calculateMeshTangents (mesh);
mesh.RecalculateBounds ();
//GetComponent<Renderer> ().bounds.center.Set(size.x / 2, 0, size.y / 2);
meshObject.GetComponent<MeshFilter> ().mesh = mesh;
meshObject.GetComponent<MeshRenderer>().material.mainTexture = texture;
//if (parent == null)
meshObject.transform.parent = this.gameObject.transform;
//else
// meshObject.transform.parent = parent.gameObject.transform;
}
}
Ive read this on the docs:
Any point in the plane can be sampled by passing the appropriate X and Y coordinates. The same coordinates will always return the same sample value but the plane is essentially infinite so it is easy to avoid repetition by choosing a random area to sample from.
Could that be the problem?
Your answer
Follow this Question
Related Questions
Terrain generation with overhangs and caves 0 Answers
Creating a grid on top of a terrain 0 Answers
Creating discrete-leveled terrain. 1 Answer
Problems with the way my sprites look 2 Answers
Terrain generation with things like generation and overhangs 0 Answers