summaryrefslogtreecommitdiffstats
path: root/src/Generating/HeiGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Generating/HeiGen.cpp')
-rw-r--r--src/Generating/HeiGen.cpp422
1 files changed, 319 insertions, 103 deletions
diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp
index 79d529a6a..1d9f1e3aa 100644
--- a/src/Generating/HeiGen.cpp
+++ b/src/Generating/HeiGen.cpp
@@ -6,7 +6,7 @@
#include "Globals.h"
#include "HeiGen.h"
#include "../LinearUpscale.h"
-#include "inifile/iniFile.h"
+#include "../IniFile.h"
#include "DistortedHeightmap.h"
#include "EndGen.h"
#include "Noise3DGenerator.h"
@@ -17,81 +17,6 @@
////////////////////////////////////////////////////////////////////////////////
-// cTerrainHeightGen:
-
-cTerrainHeightGen * cTerrainHeightGen::CreateHeightGen(cIniFile &a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault)
-{
- AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", "");
- if (HeightGenName.empty())
- {
- LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\".");
- HeightGenName = "Biomal";
- }
-
- a_CacheOffByDefault = false;
- cTerrainHeightGen * res = NULL;
- if (NoCaseCompare(HeightGenName, "flat") == 0)
- {
- res = new cHeiGenFlat;
- a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data
- }
- else if (NoCaseCompare(HeightGenName, "classic") == 0)
- {
- res = new cHeiGenClassic(a_Seed);
- }
- else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0)
- {
- res = new cDistortedHeightmap(a_Seed, a_BiomeGen);
- }
- else if (NoCaseCompare(HeightGenName, "End") == 0)
- {
- res = new cEndGen(a_Seed);
- }
- else if (NoCaseCompare(HeightGenName, "Mountains") == 0)
- {
- res = new cHeiGenMountains(a_Seed);
- }
- else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
- {
- res = new cNoise3DComposable(a_Seed);
- }
- else if (NoCaseCompare(HeightGenName, "biomal") == 0)
- {
- res = new cHeiGenBiomal(a_Seed, a_BiomeGen);
-
- /*
- // Performance-testing:
- LOGINFO("Measuring performance of cHeiGenBiomal...");
- clock_t BeginTick = clock();
- for (int x = 0; x < 500; x++)
- {
- cChunkDef::HeightMap Heights;
- res->GenHeightMap(x * 5, x * 5, Heights);
- }
- clock_t Duration = clock() - BeginTick;
- LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
- //*/
- }
- else
- {
- // No match found, force-set the default and retry
- LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str());
- a_IniFile.DeleteValue("Generator", "HeightGen");
- a_IniFile.SetValue("Generator", "HeightGen", "Biomal");
- return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
- }
-
- // Read the settings:
- res->InitializeHeightGen(a_IniFile);
-
- return res;
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
// cHeiGenFlat:
void cHeiGenFlat::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
@@ -118,7 +43,7 @@ void cHeiGenFlat::InitializeHeightGen(cIniFile & a_IniFile)
////////////////////////////////////////////////////////////////////////////////
// cHeiGenCache:
-cHeiGenCache::cHeiGenCache(cTerrainHeightGen & a_HeiGenToCache, int a_CacheSize) :
+cHeiGenCache::cHeiGenCache(cTerrainHeightGenPtr a_HeiGenToCache, int a_CacheSize) :
m_HeiGenToCache(a_HeiGenToCache),
m_CacheSize(a_CacheSize),
m_CacheOrder(new int[a_CacheSize]),
@@ -142,9 +67,9 @@ cHeiGenCache::cHeiGenCache(cTerrainHeightGen & a_HeiGenToCache, int a_CacheSize)
cHeiGenCache::~cHeiGenCache()
{
delete[] m_CacheData;
- m_CacheData = NULL;
+ m_CacheData = nullptr;
delete[] m_CacheOrder;
- m_CacheOrder = NULL;
+ m_CacheOrder = nullptr;
}
@@ -190,7 +115,7 @@ void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap
// Not in the cache:
m_NumMisses++;
- m_HeiGenToCache.GenHeightMap(a_ChunkX, a_ChunkZ, a_HeightMap);
+ m_HeiGenToCache->GenHeightMap(a_ChunkX, a_ChunkZ, a_HeightMap);
// Insert it as the first item in the MRU order:
int Idx = m_CacheOrder[m_CacheSize - 1];
@@ -210,7 +135,7 @@ void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap
void cHeiGenCache::InitializeHeightGen(cIniFile & a_IniFile)
{
- m_HeiGenToCache.InitializeHeightGen(a_IniFile);
+ m_HeiGenToCache->InitializeHeightGen(a_IniFile);
}
@@ -317,7 +242,9 @@ void cHeiGenClassic::InitializeHeightGen(cIniFile & a_IniFile)
cHeiGenMountains::cHeiGenMountains(int a_Seed) :
m_Seed(a_Seed),
- m_Noise(a_Seed)
+ m_MountainNoise(a_Seed + 100),
+ m_DitchNoise(a_Seed + 200),
+ m_Perlin(a_Seed + 300)
{
}
@@ -332,9 +259,11 @@ void cHeiGenMountains::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::Heigh
NOISE_DATATYPE StartZ = (NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width);
NOISE_DATATYPE EndZ = (NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width + cChunkDef::Width - 1);
NOISE_DATATYPE Workspace[16 * 16];
- NOISE_DATATYPE Noise[16 * 16];
+ NOISE_DATATYPE MountainNoise[16 * 16];
+ NOISE_DATATYPE DitchNoise[16 * 16];
NOISE_DATATYPE PerlinNoise[16 * 16];
- m_Noise.Generate2D(Noise, 16, 16, StartX, EndX, StartZ, EndZ, Workspace);
+ m_MountainNoise.Generate2D(MountainNoise, 16, 16, StartX, EndX, StartZ, EndZ, Workspace);
+ m_DitchNoise.Generate2D(DitchNoise, 16, 16, StartX, EndX, StartZ, EndZ, Workspace);
m_Perlin.Generate2D(PerlinNoise, 16, 16, StartX, EndX, StartZ, EndZ, Workspace);
for (int z = 0; z < cChunkDef::Width; z++)
{
@@ -342,7 +271,7 @@ void cHeiGenMountains::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::Heigh
for (int x = 0; x < cChunkDef::Width; x++)
{
int idx = IdxZ + x;
- int hei = 100 - (int)((Noise[idx] + PerlinNoise[idx]) * 15);
+ int hei = 100 - (int)((MountainNoise[idx] - DitchNoise[idx] + PerlinNoise[idx]) * 15);
if (hei < 10)
{
hei = 10;
@@ -363,9 +292,12 @@ void cHeiGenMountains::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::Heigh
void cHeiGenMountains::InitializeHeightGen(cIniFile & a_IniFile)
{
// TODO: Read the params from an INI file
- m_Noise.AddOctave(0.1f, 0.1f);
- m_Noise.AddOctave(0.05f, 0.5f);
- m_Noise.AddOctave(0.02f, 1.5f);
+ m_MountainNoise.AddOctave(0.1f, 0.2f);
+ m_MountainNoise.AddOctave(0.05f, 0.4f);
+ m_MountainNoise.AddOctave(0.02f, 1.0f);
+ m_DitchNoise.AddOctave(0.1f, 0.2f);
+ m_DitchNoise.AddOctave(0.05f, 0.4f);
+ m_DitchNoise.AddOctave(0.02f, 1.0f);
m_Perlin.AddOctave(0.01f, 1.5f);
}
@@ -423,15 +355,15 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
/* biMesaPlateau */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80},
// biomes 40 .. 128 are unused, 89 empty placeholders here:
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 40 .. 49
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 50 .. 59
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 60 .. 69
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 70 .. 79
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 80 .. 89
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 90 .. 99
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 100 .. 109
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 110 .. 119
- {}, {}, {}, {}, {}, {}, {}, {}, {}, // 120 .. 128
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 40 .. 49
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 50 .. 59
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 60 .. 69
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 70 .. 79
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 80 .. 89
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 90 .. 99
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 100 .. 109
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 110 .. 119
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 120 .. 128
/* biSunflowerPlains */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 129
/* biDesertM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 130
@@ -441,22 +373,22 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
/* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134
// Biomes 135 .. 139 unused, 5 empty placeholders here:
- {}, {}, {}, {}, {}, // 135 .. 139
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 135 .. 139
/* biIcePlainsSpikes */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 140
// Biomes 141 .. 148 unused, 8 empty placeholders here:
- {}, {}, {}, {}, {}, {}, {}, {}, // 141 .. 148
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 141 .. 148
/* biJungleM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 149
- {}, // 150
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 150
/* biJungleEdgeM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 151
- {}, {}, {}, // 152 .. 154
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 152 .. 154
/* biBirchForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 155
/* biBirchForestHillsM */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 156
/* biRoofedForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 157
/* biColdTaigaM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 158
- {}, // 159
+ {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 159
/* biMegaSpruceTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 160
/* biMegaSpruceTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 161
/* biExtremeHillsPlusM */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 120}, // 162
@@ -479,7 +411,7 @@ void cHeiGenBiomal::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMa
{
for (int x = -1; x <= 1; x++)
{
- m_BiomeGen.GenBiomes(a_ChunkX + x, a_ChunkZ + z, Biomes[x + 1][z + 1]);
+ m_BiomeGen->GenBiomes(a_ChunkX + x, a_ChunkZ + z, Biomes[x + 1][z + 1]);
} // for x
} // for z
@@ -604,3 +536,287 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX,
+////////////////////////////////////////////////////////////////////////////////
+// cHeiGenMinMax:
+
+class cHeiGenMinMax:
+ public cTerrainHeightGen
+{
+ typedef cTerrainHeightGen super;
+
+ /** Size of the averaging process, in columns (for each direction). Must be less than 16. */
+ static const int AVERAGING_SIZE = 4;
+
+public:
+ cHeiGenMinMax(int a_Seed, cBiomeGenPtr a_BiomeGen):
+ m_Noise(a_Seed),
+ m_BiomeGen(a_BiomeGen),
+ m_TotalWeight(0)
+ {
+ // Initialize the weights:
+ for (int z = 0; z <= AVERAGING_SIZE * 2; z++)
+ {
+ for (int x = 0; x <= AVERAGING_SIZE * 2; x++)
+ {
+ m_Weights[z][x] = 1 + 2 * AVERAGING_SIZE - std::abs(x - AVERAGING_SIZE) - std::abs(z - AVERAGING_SIZE);
+ m_TotalWeight += m_Weights[z][x];
+ }
+ }
+
+ // Initialize the Perlin generator:
+ m_Perlin.AddOctave(0.04f, 0.2f);
+ m_Perlin.AddOctave(0.02f, 0.1f);
+ m_Perlin.AddOctave(0.01f, 0.05f);
+ }
+
+
+ virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
+ {
+ // Generate the biomes for the 3*3 neighbors:
+ cChunkDef::BiomeMap neighborBiomes[3][3];
+ for (int z = 0; z < 3; z++) for (int x = 0; x < 3; x++)
+ {
+ m_BiomeGen->GenBiomes(a_ChunkX + x - 1, a_ChunkZ + z - 1, neighborBiomes[z][x]);
+ }
+
+ // Get the min and max heights based on the biomes:
+ double minHeight[cChunkDef::Width * cChunkDef::Width];
+ double maxHeight[cChunkDef::Width * cChunkDef::Width];
+ for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ for (int x = 0; x < cChunkDef::Width; x++)
+ {
+ // For each column, sum the min and max values of the neighborhood around it:
+ double min = 0, max = 0;
+ for (int relz = 0; relz <= AVERAGING_SIZE * 2; relz++)
+ {
+ int bz = z + 16 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start
+ int cz = bz / 16; // Chunk Z coord relative to the neighborBiomes start
+ bz = bz % 16; // Biome Z coord relative to cz in neighborBiomes
+ for (int relx = 0; relx <= AVERAGING_SIZE * 2; relx++)
+ {
+ int bx = x + 16 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start
+ int cx = bx / 16; // Chunk X coord relative to the neighborBiomes start
+ bx = bx % 16; // Biome X coord relative to cz in neighborBiomes
+
+ // Get the biome's min and max heights:
+ double bmin, bmax;
+ getBiomeMinMax(cChunkDef::GetBiome(neighborBiomes[cz][cx], bx, bz), bmin, bmax);
+
+ // Add them to the total, with the weight depending on their relative position to the column:
+ min += bmin * m_Weights[relz][relx];
+ max += bmax * m_Weights[relz][relx];
+ } // for relx
+ } // for relz
+ minHeight[x + z * cChunkDef::Width] = min / m_TotalWeight;
+ maxHeight[x + z * cChunkDef::Width] = max / m_TotalWeight;
+ } // for x
+ } // for z
+
+ // Generate the base noise:
+ NOISE_DATATYPE noise[cChunkDef::Width * cChunkDef::Width];
+ NOISE_DATATYPE workspace[cChunkDef::Width * cChunkDef::Width];
+ NOISE_DATATYPE startX = static_cast<float>(a_ChunkX * cChunkDef::Width);
+ NOISE_DATATYPE endX = startX + cChunkDef::Width - 1;
+ NOISE_DATATYPE startZ = static_cast<float>(a_ChunkZ * cChunkDef::Width);
+ NOISE_DATATYPE endZ = startZ + cChunkDef::Width - 1;
+ m_Perlin.Generate2D(noise, 16, 16, startX, endX, startZ, endZ, workspace);
+
+ // Make the height by ranging the noise between min and max:
+ for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ for (int x = 0; x < cChunkDef::Width; x++)
+ {
+ double min = minHeight[x + z * cChunkDef::Width];
+ double max = maxHeight[x + z * cChunkDef::Width];
+ double h = (max + min) / 2 + noise[x + z * cChunkDef::Width] * (max - min);
+ cChunkDef::SetHeight(a_HeightMap, x, z, static_cast<HEIGHTTYPE>(h));
+ }
+ }
+ }
+
+
+ virtual void InitializeHeightGen(cIniFile & a_IniFile)
+ {
+ // No settings available
+ }
+
+protected:
+ cNoise m_Noise;
+
+ cPerlinNoise m_Perlin;
+
+ /** The biome generator to query for the underlying biomes. */
+ cBiomeGenPtr m_BiomeGen;
+
+ /** Weights applied to each of the min / max values in the neighborhood of the currently evaluated column. */
+ double m_Weights[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1];
+
+ /** Sum of all the m_Weights items. */
+ double m_TotalWeight;
+
+
+ /** Returns the minimum and maximum heights for the given biome. */
+ void getBiomeMinMax(EMCSBiome a_Biome, double & a_Min, double & a_Max)
+ {
+ switch (a_Biome)
+ {
+ case biBeach: a_Min = 61; a_Max = 64; break;
+ case biBirchForest: a_Min = 63; a_Max = 75; break;
+ case biBirchForestHills: a_Min = 63; a_Max = 90; break;
+ case biBirchForestHillsM: a_Min = 63; a_Max = 90; break;
+ case biBirchForestM: a_Min = 63; a_Max = 75; break;
+ case biColdBeach: a_Min = 61; a_Max = 64; break;
+ case biColdTaiga: a_Min = 63; a_Max = 75; break;
+ case biColdTaigaHills: a_Min = 63; a_Max = 90; break;
+ case biColdTaigaM: a_Min = 63; a_Max = 75; break;
+ case biDeepOcean: a_Min = 30; a_Max = 60; break;
+ case biDesert: a_Min = 63; a_Max = 70; break;
+ case biDesertHills: a_Min = 63; a_Max = 85; break;
+ case biDesertM: a_Min = 63; a_Max = 70; break;
+ case biEnd: a_Min = 10; a_Max = 100; break;
+ case biExtremeHills: a_Min = 60; a_Max = 120; break;
+ case biExtremeHillsEdge: a_Min = 63; a_Max = 100; break;
+ case biExtremeHillsM: a_Min = 60; a_Max = 120; break;
+ case biExtremeHillsPlus: a_Min = 60; a_Max = 140; break;
+ case biExtremeHillsPlusM: a_Min = 60; a_Max = 140; break;
+ case biFlowerForest: a_Min = 63; a_Max = 75; break;
+ case biForest: a_Min = 63; a_Max = 75; break;
+ case biForestHills: a_Min = 63; a_Max = 90; break;
+ case biFrozenOcean: a_Min = 45; a_Max = 64; break;
+ case biFrozenRiver: a_Min = 60; a_Max = 62; break;
+ case biIceMountains: a_Min = 63; a_Max = 90; break;
+ case biIcePlains: a_Min = 63; a_Max = 70; break;
+ case biIcePlainsSpikes: a_Min = 60; a_Max = 70; break;
+ case biJungle: a_Min = 60; a_Max = 80; break;
+ case biJungleEdge: a_Min = 62; a_Max = 75; break;
+ case biJungleEdgeM: a_Min = 62; a_Max = 75; break;
+ case biJungleHills: a_Min = 60; a_Max = 90; break;
+ case biJungleM: a_Min = 60; a_Max = 75; break;
+ case biMegaSpruceTaiga: a_Min = 63; a_Max = 75; break;
+ case biMegaSpruceTaigaHills: a_Min = 63; a_Max = 90; break;
+ case biMegaTaiga: a_Min = 63; a_Max = 75; break;
+ case biMegaTaigaHills: a_Min = 63; a_Max = 90; break;
+ case biMesa: a_Min = 63; a_Max = 90; break;
+ case biMesaBryce: a_Min = 60; a_Max = 67; break;
+ case biMesaPlateau: a_Min = 75; a_Max = 85; break;
+ case biMesaPlateauF: a_Min = 80; a_Max = 90; break;
+ case biMesaPlateauFM: a_Min = 80; a_Max = 90; break;
+ case biMesaPlateauM: a_Min = 75; a_Max = 85; break;
+ case biMushroomIsland: a_Min = 63; a_Max = 90; break;
+ case biMushroomShore: a_Min = 60; a_Max = 75; break;
+ case biNether: a_Min = 10; a_Max = 100; break;
+ case biOcean: a_Min = 45; a_Max = 64; break;
+ case biPlains: a_Min = 63; a_Max = 70; break;
+ case biRiver: a_Min = 60; a_Max = 62; break;
+ case biRoofedForest: a_Min = 63; a_Max = 75; break;
+ case biRoofedForestM: a_Min = 63; a_Max = 75; break;
+ case biSavanna: a_Min = 63; a_Max = 75; break;
+ case biSavannaM: a_Min = 63; a_Max = 80; break;
+ case biSavannaPlateau: a_Min = 75; a_Max = 100; break;
+ case biSavannaPlateauM: a_Min = 80; a_Max = 160; break;
+ case biStoneBeach: a_Min = 60; a_Max = 64; break;
+ case biSunflowerPlains: a_Min = 63; a_Max = 70; break;
+ case biSwampland: a_Min = 60; a_Max = 67; break;
+ case biSwamplandM: a_Min = 61; a_Max = 67; break;
+ case biTaiga: a_Min = 63; a_Max = 75; break;
+ case biTaigaHills: a_Min = 63; a_Max = 90; break;
+ case biTaigaM: a_Min = 63; a_Max = 80; break;
+ default:
+ {
+ ASSERT(!"Unknown biome");
+ a_Min = 10;
+ a_Max = 10;
+ break;
+ }
+ }
+ }
+};
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cTerrainHeightGen:
+
+cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault)
+{
+ AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", "");
+ if (HeightGenName.empty())
+ {
+ LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\".");
+ HeightGenName = "Biomal";
+ }
+
+ a_CacheOffByDefault = false;
+ cTerrainHeightGen * res = nullptr;
+ if (NoCaseCompare(HeightGenName, "flat") == 0)
+ {
+ res = new cHeiGenFlat;
+ a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data
+ }
+ else if (NoCaseCompare(HeightGenName, "classic") == 0)
+ {
+ res = new cHeiGenClassic(a_Seed);
+ }
+ else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0)
+ {
+ res = new cDistortedHeightmap(a_Seed, a_BiomeGen);
+ }
+ else if (NoCaseCompare(HeightGenName, "End") == 0)
+ {
+ res = new cEndGen(a_Seed);
+ }
+ else if (NoCaseCompare(HeightGenName, "MinMax") == 0)
+ {
+ res = new cHeiGenMinMax(a_Seed, a_BiomeGen);
+ }
+ else if (NoCaseCompare(HeightGenName, "Mountains") == 0)
+ {
+ res = new cHeiGenMountains(a_Seed);
+ }
+ else if (NoCaseCompare(HeightGenName, "BiomalNoise3D") == 0)
+ {
+ res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen);
+ }
+ else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
+ {
+ res = new cNoise3DComposable(a_Seed);
+ }
+ else if (NoCaseCompare(HeightGenName, "biomal") == 0)
+ {
+ res = new cHeiGenBiomal(a_Seed, a_BiomeGen);
+
+ /*
+ // Performance-testing:
+ LOGINFO("Measuring performance of cHeiGenBiomal...");
+ clock_t BeginTick = clock();
+ for (int x = 0; x < 500; x++)
+ {
+ cChunkDef::HeightMap Heights;
+ res->GenHeightMap(x * 5, x * 5, Heights);
+ }
+ clock_t Duration = clock() - BeginTick;
+ LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
+ //*/
+ }
+ else
+ {
+ // No match found, force-set the default and retry
+ LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str());
+ a_IniFile.DeleteValue("Generator", "HeightGen");
+ a_IniFile.SetValue("Generator", "HeightGen", "Biomal");
+ return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
+ }
+
+ // Read the settings:
+ res->InitializeHeightGen(a_IniFile);
+
+ return cTerrainHeightGenPtr(res);
+}
+
+
+
+
+