summaryrefslogtreecommitdiffstats
path: root/src/Generating/ShapeGen.cpp
blob: 43601ee20a8ac0351b193b48c48db0c1f8aa3a34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

// ShapeGen.cpp

// Implements the function to create a cTerrainShapeGen descendant based on INI file settings

#include "Globals.h"
#include "HeiGen.h"
#include "../IniFile.h"
#include "DistortedHeightmap.h"
#include "EndGen.h"
#include "Noise3DGenerator.h"
#include "TwoHeights.h"





////////////////////////////////////////////////////////////////////////////////
// cTerrainHeightToShapeGen:

/** Converts old-style height-generators into new-style shape-generators. */
class cTerrainHeightToShapeGen:
	public cTerrainShapeGen
{
public:
	cTerrainHeightToShapeGen(cTerrainHeightGenPtr a_HeightGen):
		m_HeightGen(a_HeightGen)
	{
	}


	// cTerrainShapeGen overrides:
	virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override
	{
		// Generate the heightmap:
		cChunkDef::HeightMap heightMap;
		m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, heightMap);

		// Convert from heightmap to shape:
		for (int z = 0; z < cChunkDef::Width; z++)
		{
			for (int x = 0; x < cChunkDef::Width; x++)
			{
				int height = cChunkDef::GetHeight(heightMap, x, z) + 1;
				Byte * shapeColumn = &(a_Shape[(x + 16 * z) * 256]);
				for (int y = 0; y < height; y++)
				{
					shapeColumn[y] = 1;
				}
				for (int y = height; y < cChunkDef::Height; y++)
				{
					shapeColumn[y] = 0;
				}
			}  // for x
		}  // for z
	}


	virtual void InitializeShapeGen(cIniFile & a_IniFile) override
	{
		m_HeightGen->InitializeHeightGen(a_IniFile);
	}

protected:
	/** The height generator being converted. */
	cTerrainHeightGenPtr m_HeightGen;
};

typedef SharedPtr<cTerrainHeightToShapeGen> cTerrainHeightToShapeGenPtr;





////////////////////////////////////////////////////////////////////////////////
// cTerrainShapeGen:

cTerrainShapeGenPtr cTerrainShapeGen::CreateShapeGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault)
{
	AString shapeGenName = a_IniFile.GetValueSet("Generator", "ShapeGen", "");
	if (shapeGenName.empty())
	{
		LOGWARN("[Generator] ShapeGen value not set in world.ini, using \"BiomalNoise3D\".");
		shapeGenName = "BiomalNoise3D";
	}
	
	// If the shapegen is HeightMap, redirect to older HeightMap-based generators:
	if (NoCaseCompare(shapeGenName, "HeightMap") == 0)
	{
		cTerrainHeightGenPtr heightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
		if (heightGen != nullptr)
		{
			return std::make_shared<cTerrainHeightToShapeGen>(heightGen);
		}

		// The height gen was not recognized; several heightgens were promoted to shape gens, so let's try them instead:
		shapeGenName = a_IniFile.GetValue("Generator", "HeightGen", "");
		if (shapeGenName.empty())
		{
			LOGWARNING("[Generator] ShapeGen set to HeightMap, but HeightGen not set. Reverting to \"BiomalNoise3D\".");
			shapeGenName = "BiomalNoise3D";
			a_IniFile.SetValue("Generator", "ShapeGen", shapeGenName);
		}
	}

	// Choose the shape generator based on the name:
	a_CacheOffByDefault = false;
	cTerrainShapeGenPtr res;
	if (NoCaseCompare(shapeGenName, "DistortedHeightmap") == 0)
	{
		res = std::make_shared<cDistortedHeightmap>(a_Seed, a_BiomeGen);
	}
	else if (NoCaseCompare(shapeGenName, "End") == 0)
	{
		res = std::make_shared<cEndGen>(a_Seed);
	}
	else if (NoCaseCompare(shapeGenName, "BiomalNoise3D") == 0)
	{
		res = std::make_shared<cBiomalNoise3DComposable>(a_Seed, a_BiomeGen);
	}
	else if (NoCaseCompare(shapeGenName, "Noise3D") == 0)
	{
		res = std::make_shared<cNoise3DComposable>(a_Seed);
	}
	else if (NoCaseCompare(shapeGenName, "TwoHeights") == 0)
	{
		res = CreateShapeGenTwoHeights(a_Seed, a_BiomeGen);
	}
	else
	{
		// No match found, force-set the default and retry
		LOGWARN("Unknown ShapeGen \"%s\", using \"BiomalNoise3D\" instead.", shapeGenName.c_str());
		a_IniFile.SetValue("Generator", "ShapeGen", "BiomalNoise3D");
		return CreateShapeGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
	}
	
	// Read the settings:
	res->InitializeShapeGen(a_IniFile);
	
	return res;
}