For my chunk generator for my game, it currently uses a triple nested loop, which seems very inefficient. It also seems like I could cut down a lot of code in the function somehow. Does anyone have any ideas?
void Chunk::Generate() {
const int octaves = 6;
const float heightMod = 4.0f;
const float densityMod = 8.0f;
const float horizontalFrequency = 1.0f / 256.0f;
const float frontalFrequency = 1.0f / 256.0f;
const float heightMapSize = 1.0f / 512.0f;
for (int z = m_chunkZ; z < m_chunkZ + m_chunkDepth; z++) {
for (int x = m_chunkX; x < m_chunkX + m_chunkWidth; x++) {
// the last type generated
VoxelType lastType = VoxelType::SAND;
// the height used for this part of the chunk
int height = static_cast<int>(noise_fractal_brownian_motion(m_noise, octaves, x * horizontalFrequency, heightMapSize, z * frontalFrequency) * (m_chunkHeight * heightMod));
int minY = m_chunkY;
int maxY = m_chunkY + height;
for (int y = minY; y < maxY; y++) {
const float colorMinCap = -0.45f;
const float colorMaxCap = 0.45f;
const float densityXFrequency = 1.0f / 64.0f;
const float densityZFrequency = 1.0f / 256.0f;
const float verticalFrequency = 1.0f / (static_cast<float>(abs(height)) * heightMod);
float density = noise_fractal_brownian_motion(m_noise, octaves, x * densityXFrequency, abs(y) * verticalFrequency, z * densityZFrequency) * (abs(height) * densityMod);
// todo: new noise map for color
float colorR = noise_fractal_brownian_motion(m_noise, octaves, x * densityXFrequency, 0.0f, z * densityZFrequency - 0.15f);
float colorG = noise_fractal_brownian_motion(m_noise, octaves, x * densityXFrequency - 0.08f, 0.0f, z * densityZFrequency);
float colorB = noise_fractal_brownian_motion(m_noise, octaves, x * densityXFrequency - 0.32f, 0.0f, z * densityZFrequency - 0.64f);
if (colorR >= colorMaxCap)
colorR = colorMaxCap;
if (colorG >= colorMaxCap)
colorG = colorMaxCap;
if (colorB >= colorMaxCap)
colorB = colorMaxCap;
if (colorR <= colorMinCap)
colorR = colorMinCap;
if (colorG <= colorMinCap)
colorG = colorMinCap;
if (colorB <= colorMinCap)
colorB = colorMinCap;
if (density >= 0.0f) {
VoxelType type = ((y == maxY - 1 && lastType == VoxelType::DIRT) ? VoxelType::GRASS : _GetTypeFromY(y));
// check if we should replace a dirt type with grass
if (y == maxY - 1 && type == VoxelType::DIRT) type = VoxelType::GRASS;
if (type == VoxelType::WATER) {
m_transparentRenderer.AddVoxel(Position(x, y, z), Voxel(VoxelType::WATER, 0));
}
else {
if (y <= m_seaLevel)
m_underwaterRenderer.AddVoxel(Position(x, y, z), Voxel(type, colorR, colorG, colorB));
else
m_opaqueRenderer.AddVoxel(Position(x, y, z), Voxel(type, colorR, colorG, colorB));
}
lastType = _GetTypeFromY(y);
}
}
// no matter what, add one water voxel at sea level
m_transparentRenderer.AddVoxel(Position(x, m_seaLevel, z), Voxel(VoxelType::WATER, 0));
// no matter what, add one sand voxel at 0 (bottom of the water)
m_underwaterRenderer.AddVoxel(Position(x, 0, z), Voxel(VoxelType::SAND, 0));
lastType = VoxelType::SAND;
}
}
}