3 Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "map.h" //for ManualMapVoxelManipulator
33 #define BT_EXTREMEHILLS 7
34 #define BT_MOUNTAINS 8
36 #define BT_DESERTHILLS 10
40 #define BT_BTMASK 0x3F
43 #define BTF_FOREST 0x80
45 #define BGFREQ_1 ( 0.40)
46 #define BGFREQ_2 (BGFREQ_1 + 0.05)
47 #define BGFREQ_3 (BGFREQ_2 + 0.08)
48 #define BGFREQ_4 (BGFREQ_3 + 0.35)
49 #define BGFREQ_5 (BGFREQ_4 + 0.18)
50 //BGFREQ_5 is not checked as an upper bound; it ought to sum up to 1.00, but it's okay if it doesn't.
53 /*float bg1_temps[] = {0.0};
54 int bg1_biomes[] = {BT_OCEAN};
56 float bg2_temps[] = {10.0};
57 int bg2_biomes[] = {BT_GBEACH, BT_SBEACH};
59 float bg3_temps[] = {30.0, 40.0};
60 int bg3_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS};
62 float bg4_temps[] = {25.0, 30.0, 35.0, 40.0};
63 int bg4_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESERTHILLS};
65 float bg5_temps[] = {5.0, 40.0};
66 int bg5_biomes[] = {BT_LAKE, BT_PLAINS, BT_DESERT};*/
68 NoiseParams np_default = {20.0, 15.0, v3f(250., 250., 250.), 82341, 5, 0.6};
71 BiomeDefManager::BiomeDefManager(IGameDef *gamedef) {
72 this->m_gamedef = gamedef;
73 this->ndef = gamedef->ndef();
75 //the initial biome group
76 bgroups.push_back(new std::vector<Biome *>);
80 BiomeDefManager::~BiomeDefManager() {
81 for (unsigned int i = 0; i != bgroups.size(); i++)
86 Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) {
88 case BIOME_TERRAIN_NORMAL:
90 case BIOME_TERRAIN_LIQUID:
91 return new BiomeLiquid;
92 case BIOME_TERRAIN_NETHER:
94 case BIOME_TERRAIN_AETHER:
95 return new BiomeAether;
96 case BIOME_TERRAIN_FLAT:
97 return new BiomeSuperflat;
103 void BiomeDefManager::addBiomeGroup(float freq) {
104 int size = bgroup_freqs.size();
105 float newfreq = freq;
108 newfreq += bgroup_freqs[size - 1];
109 bgroup_freqs.push_back(newfreq);
110 bgroups.push_back(new std::vector<Biome *>);
112 verbosestream << "BiomeDefManager: added biome group with frequency " <<
113 newfreq << std::endl;
117 void BiomeDefManager::addBiome(Biome *b) {
118 std::vector<Biome *> *bgroup;
120 if ((unsigned int)b->groupid >= bgroups.size()) {
121 errorstream << "BiomeDefManager: attempted to add biome '" << b->name
122 << "' to nonexistent biome group " << b->groupid << std::endl;
126 bgroup = bgroups[b->groupid];
127 bgroup->push_back(b);
129 verbosestream << "BiomeDefManager: added biome '" << b->name <<
130 "' to biome group " << b->groupid << std::endl;
134 void BiomeDefManager::addDefaultBiomes() {
139 b->n_top = MapNode(ndef->getId("mapgen_stone"));
140 b->n_filler = b->n_top;
142 b->height_min = -MAP_GENERATION_LIMIT;
143 b->height_max = MAP_GENERATION_LIMIT;
144 b->heat_min = FLT_MIN;
145 b->heat_max = FLT_MAX;
146 b->humidity_min = FLT_MIN;
147 b->humidity_max = FLT_MAX;
153 Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) {
154 std::vector<Biome *> *bgroup;
158 int ngroups = bgroup_freqs.size();
160 return biome_default;
161 for (i = 0; (i != ngroups) && (bgfreq > bgroup_freqs[i]); i++);
164 int nbiomes = bgroup->size();
165 for (i = 0; i != nbiomes; i++) {
166 b = bgroup->operator[](i);
167 if (heat >= b->heat_min && heat <= b->heat_max &&
168 humidity >= b->humidity_min && humidity <= b->humidity_max)
172 return biome_default;
176 //////////////////////////// [ Generic biome ] ////////////////////////////////
179 int Biome::getSurfaceHeight(float noise_terrain) {
180 return np->offset + np->scale * noise_terrain;
184 void Biome::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
185 MapgenV7 *mg = (MapgenV7 *)mapgen;
186 int i = (z - mg->node_min.Z) * mg->csize.Z + (x - mg->node_min.X);
187 int surfaceh = np->offset + np->scale * mg->map_terrain[i];
191 float prevfreq = mg->biomedef->bgroup_freqs[groupid - 1];
192 float range = mg->biomedef->bgroup_freqs[groupid] - prevfreq;
193 float factor = (mg->map_bgroup[i] - prevfreq) / range;
195 std::vector<Biome *> *bg = mg->biomedef->bgroups[groupid - 1];
197 int h1 = b->np->offset + b->np->scale * mg->map_terrain[i];
198 surfaceh += (int)round((surfaceh - h1) * factor);
199 //printf("h1: %d, surfaceh: %d, factor %f\n", h1, surfaceh, factor);
205 i = mg->vmanip->m_area.index(x, y, z);
206 for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
207 mg->vmanip->m_data[i] = n_filler;
208 for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
209 mg->vmanip->m_data[i] = n_top;
210 for (; y <= y2; y++, i += mg->ystride)
211 mg->vmanip->m_data[i] = mg->n_air;
215 ///////////////////////////// [ Ocean biome ] /////////////////////////////////
218 void BiomeLiquid::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
219 MapgenV7 *mg = (MapgenV7 *)mapgen;
220 int i = (z - mg->node_min.Z) * mg->csize.Z + (x - mg->node_min.X);
221 int surfaceh = np->offset + np->scale * mg->map_terrain[i];
224 i = mg->vmanip->m_area.index(x, y, z);
225 for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
226 mg->vmanip->m_data[i] = n_filler;
227 for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
228 mg->vmanip->m_data[i] = n_top;
229 for (; y <= mg->water_level && y <= y2; y++, i += mg->ystride)
230 mg->vmanip->m_data[i] = mg->n_water;
231 for (; y <= y2; y++, i += mg->ystride)
232 mg->vmanip->m_data[i] = mg->n_air;
236 ///////////////////////////// [ Nether biome ] /////////////////////////////////
239 int BiomeHell::getSurfaceHeight(float noise_terrain) {
240 return np->offset + np->scale * noise_terrain;
244 void BiomeHell::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
245 MapgenV7 *mg = (MapgenV7 *)mapgen;
250 ///////////////////////////// [ Aether biome ] ////////////////////////////////
253 int BiomeAether::getSurfaceHeight(float noise_terrain) {
254 return np->offset + np->scale * noise_terrain;
258 void BiomeAether::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
259 MapgenV7 *mg = (MapgenV7 *)mapgen;
264 /////////////////////////// [ Superflat biome ] ///////////////////////////////
267 int BiomeSuperflat::getSurfaceHeight(float noise_terrain) {
272 void BiomeSuperflat::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
273 MapgenV7 *mg = (MapgenV7 *)mapgen;
274 int surfaceh = ntopnodes;
277 int i = mg->vmanip->m_area.index(x, y, z);
278 for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
279 mg->vmanip->m_data[i] = n_filler;
280 for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
281 mg->vmanip->m_data[i] = n_top;
282 for (; y <= y2; y++, i += mg->ystride)
283 mg->vmanip->m_data[i] = mg->n_air;