From fb58acf27c5d30642c85dfbaf9f10e90f8b23e71 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sat, 27 Apr 2013 13:38:40 +0000 Subject: [PATCH] New terrain generator - Noise3D. A testbed for a generator based on 3D noise. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1414 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- VC2008/MCServer.vcproj | 8 ++ source/Generating/ChunkGenerator.cpp | 5 +- source/Generating/Noise3DGenerator.cpp | 186 +++++++++++++++++++++++++ source/Generating/Noise3DGenerator.h | 39 ++++++ 4 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 source/Generating/Noise3DGenerator.cpp create mode 100644 source/Generating/Noise3DGenerator.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index e019c848e..40a97946f 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1768,6 +1768,14 @@ RelativePath="..\source\Generating\MineShafts.h" > + + + + diff --git a/source/Generating/ChunkGenerator.cpp b/source/Generating/ChunkGenerator.cpp index 7da7af69d..a4717380d 100644 --- a/source/Generating/ChunkGenerator.cpp +++ b/source/Generating/ChunkGenerator.cpp @@ -8,6 +8,7 @@ #include "../PluginManager.h" #include "ChunkDesc.h" #include "ComposableGenerator.h" +#include "Noise3DGenerator.h" @@ -53,9 +54,9 @@ bool cChunkGenerator::Start(cWorld * a_World, cIniFile & a_IniFile) m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", rnd.randInt()); AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable"); - if (NoCaseCompare(GeneratorName, "RoughHills") == 0) + if (NoCaseCompare(GeneratorName, "Noise3D") == 0) { - // TODO + m_Generator = new cNoise3DGenerator(*this); } else { diff --git a/source/Generating/Noise3DGenerator.cpp b/source/Generating/Noise3DGenerator.cpp new file mode 100644 index 000000000..c4614ffc2 --- /dev/null +++ b/source/Generating/Noise3DGenerator.cpp @@ -0,0 +1,186 @@ + +// Nosie3DGenerator.cpp + +// Generates terrain using 3D noise, rather than composing. Is a test. + +#include "Globals.h" +#include "Noise3DGenerator.h" +#include "../OSSupport/File.h" + + + + + +cNoise3DGenerator::cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator) : + super(a_ChunkGenerator), + m_Noise1(0), + m_Noise2(0) +{ +} + + + + + +cNoise3DGenerator::~cNoise3DGenerator() +{ + // Nothing needed yet +} + + + + + +void cNoise3DGenerator::Initialize(cWorld * a_World, cIniFile & a_IniFile) +{ + m_World = a_World; + // TODO: params +} + + + + + +void cNoise3DGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) +{ + for (int i = 0; i < ARRAYCOUNT(a_BiomeMap); i++) + { + a_BiomeMap[i] = biExtremeHills; + } +} + + + + + +void cNoise3DGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) +{ + const int INTERPOL_X = 8; + const int INTERPOL_Y = 4; + const int INTERPOL_Z = 8; + const NOISE_DATATYPE FrequencyX = 20; + const NOISE_DATATYPE FrequencyY = 20; + const NOISE_DATATYPE FrequencyZ = 20; + NOISE_DATATYPE Noise[257 * 17 * 17]; // x + 17 * z + 17 * 17 * y + int idx = 0; + for (int y = 0; y < 257; y += INTERPOL_Y) + { + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)y) / FrequencyY; + NOISE_DATATYPE AddHeight = NoiseY - ((NOISE_DATATYPE)128 / FrequencyY); + AddHeight *= AddHeight * AddHeight * AddHeight * AddHeight; + NOISE_DATATYPE * CurFloor = &(Noise[y * 17 * 17]); + for (int z = 0; z < 17; z += INTERPOL_Z) + { + NOISE_DATATYPE NoiseZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width + z)) / FrequencyZ; + for (int x = 0; x < 17; x += INTERPOL_X) + { + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / FrequencyX; + CurFloor[x + 17 * z] = + m_Noise1.CubicNoise3D(NoiseX, NoiseY, NoiseZ) + + m_Noise2.CubicNoise3D(NoiseX / 2, NoiseY / 2, NoiseZ / 2) + + AddHeight; + } + } + // Linear-interpolate this XZ floor: + ArrayLinearInterpolate2D(CurFloor, 17, 17, INTERPOL_X, INTERPOL_Z); + } + + // Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis + for (int y = 1; y < cChunkDef::Height; y++) + { + if ((y % INTERPOL_Y) == 0) + { + // This is the interpolation source floor, already calculated + continue; + } + int LoFloorY = (y / INTERPOL_Y) * INTERPOL_Y; + int HiFloorY = LoFloorY + INTERPOL_Y; + NOISE_DATATYPE * LoFloor = &(Noise[LoFloorY * 17 * 17]); + NOISE_DATATYPE * HiFloor = &(Noise[HiFloorY * 17 * 17]); + NOISE_DATATYPE * CurFloor = &(Noise[y * 17 * 17]); + NOISE_DATATYPE Ratio = ((NOISE_DATATYPE)(y % INTERPOL_Y)) / INTERPOL_Y; + int idx = 0; + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + CurFloor[idx] = LoFloor[idx] + (HiFloor[idx] - LoFloor[idx]) * Ratio; + idx += 1; + } + idx += 1; // Skipping one X column + } + } + + // The noise array is now fully interpolated + /* + // DEBUG: Output two images of the array, sliced by XY and XZ: + cFile f1; + if (f1.Open(Printf("Chunk_%d_%d_XY.raw", a_ChunkX, a_ChunkZ), cFile::fmWrite)) + { + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int y = 0; y < cChunkDef::Height; y++) + { + int idx = y * 17 * 17 + z * 17; + unsigned char buf[16]; + for (int x = 0; x < cChunkDef::Width; x++) + { + buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 128 * Noise[idx++])))); + } + f1.Write(buf, 16); + } // for y + } // for z + } // if (XY file open) + + cFile f2; + if (f2.Open(Printf("Chunk_%d_%d_XZ.raw", a_ChunkX, a_ChunkZ), cFile::fmWrite)) + { + for (int y = 0; y < cChunkDef::Height; y++) + { + for (int z = 0; z < cChunkDef::Width; z++) + { + int idx = y * 17 * 17 + z * 17; + unsigned char buf[16]; + for (int x = 0; x < cChunkDef::Width; x++) + { + buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 128 * Noise[idx++])))); + } + f2.Write(buf, 16); + } // for z + } // for y + } // if (XZ file open) + */ + + // Output into chunk: + for (int y = 0; y < cChunkDef::Height; y++) + { + for (int z = 0; z < cChunkDef::Width; z++) + { + int idx = y * 17 * 17 + z * 17; + for (int x = 0; x < cChunkDef::Width; x++) + { + a_ChunkDesc.SetBlockType(x, y, z, (Noise[idx++] > 0.5) ? E_BLOCK_AIR : E_BLOCK_STONE); + } + } + } + + // Update the heightmap: + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + for (int y = cChunkDef::Height - 1; y > 0; y--) + { + if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) + { + a_ChunkDesc.SetHeight(x, z, y); + break; + } + } // for y + } // for x + } // for z +} + + + + diff --git a/source/Generating/Noise3DGenerator.h b/source/Generating/Noise3DGenerator.h new file mode 100644 index 000000000..3a6b6dff4 --- /dev/null +++ b/source/Generating/Noise3DGenerator.h @@ -0,0 +1,39 @@ + +// Noise3DGenerator.h + +// Generates terrain using 3D noise, rather than composing. Is a test. + + + + +#pragma once + +#include "ChunkGenerator.h" +#include "ChunkDesc.h" +#include "../Noise.h" + + + + + +class cNoise3DGenerator : + public cChunkGenerator::cGenerator +{ + typedef cChunkGenerator::cGenerator super; + +public: + cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator); + virtual ~cNoise3DGenerator(); + + virtual void Initialize(cWorld * a_World, cIniFile & a_IniFile) override; + virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override; + virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override; + +protected: + cNoise m_Noise1; + cNoise m_Noise2; +} ; + + + +