- Home /
How to make a voxel terrain generate all around the start point
I have a voxel terrain generator, the problem is that it only generates in the positive x + Z position. Is there a way to also make it generate in the negative X and Z directions ? Here is the code.
using UnityEngine;
using System.Collections;
public class World : MonoBehaviour
{
public GameObject chunk;
public Chunk[,,] chunks; //Changed from public GameObject[,,] chunks;
public int chunkSize = 16;
public byte[,,] data;
public int worldX = 16;
public int worldY = 16;
public int worldZ = 16;
// Use this for initialization
void Start ()
{
data = new byte[worldX, worldY, worldZ];
for (int x=0; x<worldX; x++) {
for (int z=0; z<worldZ; z++) {
int stone = PerlinNoise (x, 0, z, 10, 3, 1.2f); //PerlinNoise (int x, int y, int z, float scale, float height, float power)
stone += PerlinNoise (x, 300, z, 200, 4, 0) + 50;
int dirt = PerlinNoise (x, 1000, z, 50, 20, 0) + 1;
for (int y=0; y<worldY; y++) {
if (y <= stone) {
data [x, y, z] = 1;
} else if (y <= dirt + stone) {
data [x, y, z] = 2;
}
}
}
}
chunks = new Chunk[Mathf.FloorToInt (worldX / chunkSize), Mathf.FloorToInt (worldY / chunkSize), Mathf.FloorToInt (worldZ / chunkSize)];
}
public void GenColumn(int x, int z){
for (int y=0; y<chunks.GetLength(1); y++) {
//Create a temporary Gameobject for the new chunk instead of using chunks[x,y,z]
GameObject newChunk = Instantiate (chunk, new Vector3 (x * chunkSize - 0.5f,
y * chunkSize + 0.5f, z * chunkSize - 0.5f), new Quaternion (0, 0, 0, 0)) as GameObject;
chunks [x, y, z] = newChunk.GetComponent ("Chunk") as Chunk;
chunks [x, y, z].worldGO = gameObject;
chunks [x, y, z].chunkSize = chunkSize;
chunks [x, y, z].chunkX = x * chunkSize;
chunks [x, y, z].chunkY = y * chunkSize;
chunks [x, y, z].chunkZ = z * chunkSize;
}
}
public void UnloadColumn(int x, int z){
for (int y=0; y<chunks.GetLength(1); y++) {
Object.Destroy(chunks [x, y, z].gameObject);
}
}
int PerlinNoise (int x, int y, int z, float scale, float height, float power)
{
float rValue;
rValue = Noise.GetNoise (((double)x) / scale, ((double)y) / scale, ((double)z) / scale);
rValue *= height;
if (power != 0) {
rValue = Mathf.Pow (rValue, power);
}
return (int)rValue;
}
// Update is called once per frame
void Update ()
{
}
public byte Block (int x, int y, int z)
{
if (x >= worldX || x < 0 || y >= worldY || y < 0 || z >= worldZ || z < 0) {
return (byte)1;
}
return data [x, y, z];
}
}
Answer by Hoeloe · Feb 09, 2014 at 01:32 PM
First off, I want to say that this is a horrible way of doing a voxel engine. Yes, this is how Minecraft does it, but having extensively looked at the Minecraft source code, a lot of it is, to be frank, terrible. You may want to look up how actual voxel engines are done, specifically, sparse voxel octrees.
Secondly, this is really, REALLY simple to solve. Currently, you're calling Instantiate here:
Instantiate (chunk, new Vector3 (x * chunkSize - 0.5f,
y * chunkSize + 0.5f, z * chunkSize - 0.5f), new Quaternion (0, 0, 0, 0)) as GameObject;
Now, just this first vector is what you need to focus on.
Currently, you're spawning it at some integer x coordinate, multiplied by the chunk size, and then for some reason you're subtracting 0.5 from it.
Using some example values, say we have an x coordinate of 3, and a chunk size of 10, this would give a final x coordinate of 29.5. Not exactly what you're looking for I think.
My guess is that you were trying to use the x coordinate as the centre point of the chunk, in which case, you need some brackets:
x * (chunkSize - 0.5f)
Remember your order of operations:
Brackets
Indices
Division
Multiplication
Addition
Subtraction
Without brackets, the multiplication is done first, with the subtraction done afterwards.
Now if this wasn't what you wanted, then let me know.