The new mapgen, noise functions, et al.

This commit is contained in:
kwolekr 2012-11-25 21:16:48 -05:00 committed by Perttu Ahola
parent 736b386554
commit 11afcbff69
23 changed files with 1892 additions and 1037 deletions

@ -218,6 +218,7 @@ set(common_SRCS
sha1.cpp sha1.cpp
base64.cpp base64.cpp
ban.cpp ban.cpp
biome.cpp
clientserver.cpp clientserver.cpp
staticobject.cpp staticobject.cpp
util/serialize.cpp util/serialize.cpp

229
src/biome.cpp Normal file

@ -0,0 +1,229 @@
/*
Minetest-c55
Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "biome.h"
#include "nodedef.h"
#include "map.h" //for ManualMapVoxelManipulator
#include "main.h"
#define BT_NONE 0
#define BT_OCEAN 1
#define BT_LAKE 2
#define BT_SBEACH 3
#define BT_GBEACH 4
#define BT_PLAINS 5
#define BT_HILLS 6
#define BT_EXTREMEHILLS 7
#define BT_MOUNTAINS 8
#define BT_DESERT 9
#define BT_DESERTHILLS 10
#define BT_HELL 11
#define BT_AETHER 12
#define BT_BTMASK 0x3F
#define BTF_SNOW 0x40
#define BTF_FOREST 0x80
#define BGFREQ_1 ( 0.40)
#define BGFREQ_2 (BGFREQ_1 + 0.05)
#define BGFREQ_3 (BGFREQ_2 + 0.08)
#define BGFREQ_4 (BGFREQ_3 + 0.35)
#define BGFREQ_5 (BGFREQ_4 + 0.18)
//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.
/*float bg1_temps[] = {0.0};
int bg1_biomes[] = {BT_OCEAN};
float bg2_temps[] = {10.0};
int bg2_biomes[] = {BT_GBEACH, BT_SBEACH};
float bg3_temps[] = {30.0, 40.0};
int bg3_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS};
float bg4_temps[] = {25.0, 30.0, 35.0, 40.0};
int bg4_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESERTHILLS};
float bg5_temps[] = {5.0, 40.0};
int bg5_biomes[] = {BT_LAKE, BT_PLAINS, BT_DESERT};*/
BiomeDefManager::BiomeDefManager(IGameDef *gamedef) {
this->m_gamedef = gamedef;
this->ndef = gamedef->ndef();
//addDefaultBiomes(); //can't do this in the ctor, too early
}
BiomeDefManager::~BiomeDefManager() {
for (int i = 0; i != bgroups.size(); i++)
delete bgroups[i];
}
void BiomeDefManager::addBiome() {
}
NoiseParams npmtdef = {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6};
void BiomeDefManager::addDefaultBiomes() {
std::vector<Biome *> *bgroup;
Biome *b;
//bgroup = new std::vector<Biome *>;
b = new Biome;
b->name = "Default";
b->n_top = MapNode(ndef->getId("mapgen_stone"));
b->n_filler = b->n_top;
b->ntopnodes = 0;
b->height_min = -MAP_GENERATION_LIMIT;
b->height_max = MAP_GENERATION_LIMIT;
b->heat_min = FLT_MIN;
b->heat_max = FLT_MAX;
b->humidity_min = FLT_MIN;
b->humidity_max = FLT_MAX;
b->np = &npmtdef;
biome_default = b;
//bgroup->push_back(b);
//bgroups.push_back(bgroup);
}
Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) {
std::vector<Biome *> bgroup;
Biome *b;
int i;
int ngroups = bgroup_freqs.size();
if (!ngroups)
return biome_default;
for (i = 0; (i != ngroups - 1) && (bgfreq > bgroup_freqs[i]); i++);
bgroup = *(bgroups[i]);
int nbiomes = bgroup.size();
if (!nbiomes)
return biome_default;
for (i = 0; i != nbiomes - 1; i++) {
b = bgroup[i];
if (heat >= b->heat_min && heat <= b->heat_max &&
humidity >= b->humidity_min && humidity <= b->humidity_max)
return b;
}
return biome_default;
}
//////////////////////////// [ Generic biome ] ////////////////////////////////
int Biome::getSurfaceHeight(float noise_terrain) {
return np->offset + np->scale * noise_terrain;
}
void Biome::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
//printf("(%d, %d): %f\n", x, z, mg->map_terrain[z * mg->ystride + x]);
//int surfaceh = 4;
int surfaceh = np->offset + np->scale * mg->map_terrain[(z - mg->node_min.Z) * 80 /*THIS IS TEMPORARY mg->ystride*/ + (x - mg->node_min.X)];
//printf("gen column %f\n", );
int y = y1;
int i = mg->vmanip->m_area.index(x, y, z); //z * mg->zstride + x + (y - mg->vmanip->m_area.MinEdge.Y) * mg->ystride;
for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_filler;
for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_top;
for (; y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = mg->n_air;
}
///////////////////////////// [ Ocean biome ] /////////////////////////////////
void BiomeOcean::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
int y, i = 0;
int surfaceh = np->offset + np->scale * mg->map_terrain[z * mg->ystride + x];
i = z * mg->zstride + x;
for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_filler;
for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_top;
for (; y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = mg->n_air;
}
///////////////////////////// [ Nether biome ] /////////////////////////////////
int BiomeHell::getSurfaceHeight(float noise_terrain) {
return np->offset + np->scale * noise_terrain;
}
void BiomeHell::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
int y, i = 0;
int surfaceh = np->offset + np->scale * mg->map_terrain[z * mg->ystride + x];
i = z * mg->zstride + x;
for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_filler;
for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_top;
for (; y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = mg->n_air;
}
///////////////////////////// [ Aether biome ] ////////////////////////////////
/////////////////////////// [ Superflat biome ] ///////////////////////////////
int BiomeSuperflat::getSurfaceHeight(float noise_terrain) {
return ntopnodes;
}
void BiomeSuperflat::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
int y, i = 0;
int surfaceh = ntopnodes;
i = z * mg->zstride + x;
for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_filler;
for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = n_top;
for (; y <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = mg->n_air;
}

79
src/biome.h Normal file

@ -0,0 +1,79 @@
/*
Minetest-c55
Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef BIOME_HEADER
#define BIOME_HEADER
#include "nodedef.h"
#include "gamedef.h"
#include "mapnode.h"
#include "noise.h"
#include "mapgen.h"
class Biome {
public:
MapNode n_top;
MapNode n_filler;
s16 ntopnodes;
s16 flags;
s16 height_min;
s16 height_max;
float heat_min;
float heat_max;
float humidity_min;
float humidity_max;
const char *name;
NoiseParams *np;
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
virtual int getSurfaceHeight(float noise_terrain);
};
class BiomeOcean : public Biome {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
};
class BiomeHell : public Biome {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
virtual int getSurfaceHeight(float noise_terrain);
};
class BiomeSuperflat : public Biome {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
virtual int getSurfaceHeight(float noise_terrain);
};
class BiomeDefManager {
public:
std::vector<float> bgroup_freqs;
std::vector<std::vector<Biome *> *> bgroups;
Biome *biome_default;
IGameDef *m_gamedef;
INodeDefManager *ndef;
BiomeDefManager(IGameDef *gamedef);
~BiomeDefManager();
Biome *getBiome(float bgfreq, float heat, float humidity);
void addBiome();
void addDefaultBiomes();
};
#endif

@ -163,7 +163,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("max_block_generate_distance", "7"); settings->setDefault("max_block_generate_distance", "7");
settings->setDefault("time_send_interval", "5"); settings->setDefault("time_send_interval", "5");
settings->setDefault("time_speed", "72"); settings->setDefault("time_speed", "72");
settings->setDefault("water_level", "1"); settings->setDefault("default_water_level", "1");
settings->setDefault("server_unload_unused_data_timeout", "29"); settings->setDefault("server_unload_unused_data_timeout", "29");
settings->setDefault("server_map_save_interval", "5.3"); settings->setDefault("server_map_save_interval", "5.3");
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");

@ -1301,6 +1301,7 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
return id; return id;
} }
#if 0
bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj) bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
{ {
assert(obj); assert(obj);
@ -1343,6 +1344,7 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
return succeeded; return succeeded;
} }
#endif
/* /*
Finds out what new objects have been added to Finds out what new objects have been added to
@ -1563,13 +1565,15 @@ void ServerEnvironment::removeRemovedObjects()
*/ */
if(obj->m_static_exists && obj->m_removed) if(obj->m_static_exists && obj->m_removed)
{ {
MapBlock *block = m_map->emergeBlock(obj->m_static_block); MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
if(block) if (block) {
{
block->m_static_objects.remove(id); block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"removeRemovedObjects"); "removeRemovedObjects");
obj->m_static_exists = false; obj->m_static_exists = false;
} else {
infostream << "failed to emerge block from which "
"an object to be removed was loaded from. id="<<id<<std::endl;
} }
} }
@ -1717,6 +1721,8 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
If force_delete is set, active object is deleted nevertheless. It If force_delete is set, active object is deleted nevertheless. It
shall only be set so in the destructor of the environment. shall only be set so in the destructor of the environment.
If block wasn't generated (not in memory or on disk),
*/ */
void ServerEnvironment::deactivateFarObjects(bool force_delete) void ServerEnvironment::deactivateFarObjects(bool force_delete)
{ {

@ -241,8 +241,9 @@ public:
MapBlock. MapBlock.
Caller allocates memory, ServerEnvironment frees memory. Caller allocates memory, ServerEnvironment frees memory.
Return value: true if succeeded, false if failed. Return value: true if succeeded, false if failed.
(note: not used, pending removal from engine)
*/ */
bool addActiveObjectAsStatic(ServerActiveObject *object); //bool addActiveObjectAsStatic(ServerActiveObject *object);
/* /*
Find out what new objects have been added to Find out what new objects have been added to

@ -120,14 +120,14 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
if(n) if(n)
return n->getValue(); return n->getValue();
HeightPoint hp; HeightPoint hp;
s16 level = mapgen::find_ground_level_from_noise(seed, p2d, 3); s16 level = Mapgen::find_ground_level_from_noise(seed, p2d, 3);
hp.gh = (level-4)*BS; hp.gh = (level-4)*BS;
hp.ma = (4)*BS; hp.ma = (4)*BS;
/*hp.gh = BS*base_rock_level_2d(seed, p2d); /*hp.gh = BS*base_rock_level_2d(seed, p2d);
hp.ma = BS*get_mud_add_amount(seed, p2d);*/ hp.ma = BS*get_mud_add_amount(seed, p2d);*/
hp.have_sand = mapgen::get_have_beach(seed, p2d); hp.have_sand = Mapgen::get_have_beach(seed, p2d);
if(hp.gh > BS*WATER_LEVEL) if(hp.gh > BS*WATER_LEVEL)
hp.tree_amount = mapgen::tree_amount_2d(seed, p2d); hp.tree_amount = Mapgen::tree_amount_2d(seed, p2d);
else else
hp.tree_amount = 0; hp.tree_amount = 0;
// No mud has been added if mud amount is less than 1 // No mud has been added if mud amount is less than 1

@ -1,253 +1,253 @@
/* /*
Minetest-c55 Minetest-c55
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com> Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "guiPauseMenu.h" #include "guiPauseMenu.h"
#include "debug.h" #include "debug.h"
#include "serialization.h" #include "serialization.h"
#include "porting.h" #include "porting.h"
#include "config.h" #include "config.h"
#include "main.h" #include "main.h"
#include <IGUICheckBox.h> #include <IGUICheckBox.h>
#include <IGUIEditBox.h> #include <IGUIEditBox.h>
#include <IGUIButton.h> #include <IGUIButton.h>
#include <IGUIStaticText.h> #include <IGUIStaticText.h>
#include <IGUIFont.h> #include <IGUIFont.h>
#include "gettext.h" #include "gettext.h"
#include "util/string.h" #include "util/string.h"
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env, GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
IGameCallback *gamecallback, IGameCallback *gamecallback,
IMenuManager *menumgr, IMenuManager *menumgr,
bool simple_singleplayer_mode): bool simple_singleplayer_mode):
GUIModalMenu(env, parent, id, menumgr), GUIModalMenu(env, parent, id, menumgr),
m_gamecallback(gamecallback), m_gamecallback(gamecallback),
m_simple_singleplayer_mode(simple_singleplayer_mode) m_simple_singleplayer_mode(simple_singleplayer_mode)
{ {
} }
GUIPauseMenu::~GUIPauseMenu() GUIPauseMenu::~GUIPauseMenu()
{ {
removeChildren(); removeChildren();
} }
void GUIPauseMenu::removeChildren() void GUIPauseMenu::removeChildren()
{ {
{ {
gui::IGUIElement *e = getElementFromId(256); gui::IGUIElement *e = getElementFromId(256);
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }
{ {
gui::IGUIElement *e = getElementFromId(257); gui::IGUIElement *e = getElementFromId(257);
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }
{ {
gui::IGUIElement *e = getElementFromId(258); gui::IGUIElement *e = getElementFromId(258);
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }
{ {
gui::IGUIElement *e = getElementFromId(259); gui::IGUIElement *e = getElementFromId(259);
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }
{ {
gui::IGUIElement *e = getElementFromId(260); gui::IGUIElement *e = getElementFromId(260);
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }
{ {
gui::IGUIElement *e = getElementFromId(261); gui::IGUIElement *e = getElementFromId(261);
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }
} }
void GUIPauseMenu::regenerateGui(v2u32 screensize) void GUIPauseMenu::regenerateGui(v2u32 screensize)
{ {
/* /*
Remove stuff Remove stuff
*/ */
removeChildren(); removeChildren();
/* /*
Calculate new sizes and positions Calculate new sizes and positions
*/ */
core::rect<s32> rect( core::rect<s32> rect(
screensize.X/2 - 580/2, screensize.X/2 - 580/2,
screensize.Y/2 - 300/2, screensize.Y/2 - 300/2,
screensize.X/2 + 580/2, screensize.X/2 + 580/2,
screensize.Y/2 + 300/2 screensize.Y/2 + 300/2
); );
DesiredRect = rect; DesiredRect = rect;
recalculateAbsolutePosition(false); recalculateAbsolutePosition(false);
v2s32 size = rect.getSize(); v2s32 size = rect.getSize();
/* /*
Add stuff Add stuff
*/ */
const s32 btn_height = 30; const s32 btn_height = 30;
const s32 btn_gap = 20; const s32 btn_gap = 20;
const s32 btn_num = m_simple_singleplayer_mode ? 3 : 4; const s32 btn_num = m_simple_singleplayer_mode ? 3 : 4;
s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2; s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
changeCtype(""); changeCtype("");
{ {
core::rect<s32> rect(0, 0, 140, btn_height); core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y); rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 256, Environment->addButton(rect, this, 256,
wgettext("Continue")); wgettext("Continue"));
} }
btn_y += btn_height + btn_gap; btn_y += btn_height + btn_gap;
if(!m_simple_singleplayer_mode) if(!m_simple_singleplayer_mode)
{ {
{ {
core::rect<s32> rect(0, 0, 140, btn_height); core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y); rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 261, Environment->addButton(rect, this, 261,
wgettext("Change Password")); wgettext("Change Password"));
} }
btn_y += btn_height + btn_gap; btn_y += btn_height + btn_gap;
} }
{ {
core::rect<s32> rect(0, 0, 140, btn_height); core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y); rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 260, Environment->addButton(rect, this, 260,
wgettext("Exit to Menu")); wgettext("Exit to Menu"));
} }
btn_y += btn_height + btn_gap; btn_y += btn_height + btn_gap;
{ {
core::rect<s32> rect(0, 0, 140, btn_height); core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y); rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 257, Environment->addButton(rect, this, 257,
wgettext("Exit to OS")); wgettext("Exit to OS"));
} }
{ {
core::rect<s32> rect(0, 0, 180, 240); core::rect<s32> rect(0, 0, 180, 240);
rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2); rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
Environment->addStaticText(chartowchar_t(gettext( Environment->addStaticText(chartowchar_t(gettext(
"Default Controls:\n" "Default Controls:\n"
"- WASD: Walk\n" "- WASD: Walk\n"
"- Mouse left: dig/hit\n" "- Mouse left: dig/hit\n"
"- Mouse right: place/use\n" "- Mouse right: place/use\n"
"- Mouse wheel: select item\n" "- Mouse wheel: select item\n"
"- 0...9: select item\n" "- 0...9: select item\n"
"- Shift: sneak\n" "- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n" "- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n" "- I: Inventory menu\n"
"- ESC: This menu\n" "- ESC: This menu\n"
"- T: Chat\n" "- T: Chat\n"
)), rect, false, true, this, 258); )), rect, false, true, this, 258);
} }
{ {
core::rect<s32> rect(0, 0, 180, 220); core::rect<s32> rect(0, 0, 180, 220);
rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2); rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);
v2u32 max_texture_size; v2u32 max_texture_size;
{ {
video::IVideoDriver* driver = Environment->getVideoDriver(); video::IVideoDriver* driver = Environment->getVideoDriver();
max_texture_size = driver->getMaxTextureSize(); max_texture_size = driver->getMaxTextureSize();
} }
std::ostringstream os; std::ostringstream os;
os<<"Minetest\n"; os<<"Minetest\n";
os<<BUILD_INFO<<"\n"; os<<BUILD_INFO<<"\n";
os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n"; os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n";
Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259); Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
} }
changeCtype("C"); changeCtype("C");
} }
void GUIPauseMenu::drawMenu() void GUIPauseMenu::drawMenu()
{ {
gui::IGUISkin* skin = Environment->getSkin(); gui::IGUISkin* skin = Environment->getSkin();
if (!skin) if (!skin)
return; return;
video::IVideoDriver* driver = Environment->getVideoDriver(); video::IVideoDriver* driver = Environment->getVideoDriver();
video::SColor bgcolor(140,0,0,0); video::SColor bgcolor(140,0,0,0);
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect); driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
gui::IGUIElement::draw(); gui::IGUIElement::draw();
} }
bool GUIPauseMenu::OnEvent(const SEvent& event) bool GUIPauseMenu::OnEvent(const SEvent& event)
{ {
if(event.EventType==EET_KEY_INPUT_EVENT) if(event.EventType==EET_KEY_INPUT_EVENT)
{ {
if(event.KeyInput.PressedDown) if(event.KeyInput.PressedDown)
{ {
if(event.KeyInput.Key==KEY_ESCAPE) if(event.KeyInput.Key==KEY_ESCAPE)
{ {
quitMenu(); quitMenu();
return true; return true;
} }
else if(event.KeyInput.Key==KEY_RETURN) else if(event.KeyInput.Key==KEY_RETURN)
{ {
quitMenu(); quitMenu();
return true; return true;
} }
} }
} }
if(event.EventType==EET_GUI_EVENT) if(event.EventType==EET_GUI_EVENT)
{ {
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
&& isVisible()) && isVisible())
{ {
if(!canTakeFocus(event.GUIEvent.Element)) if(!canTakeFocus(event.GUIEvent.Element))
{ {
dstream<<"GUIPauseMenu: Not allowing focus change." dstream<<"GUIPauseMenu: Not allowing focus change."
<<std::endl; <<std::endl;
// Returning true disables focus change // Returning true disables focus change
return true; return true;
} }
} }
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED) if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
{ {
switch(event.GUIEvent.Caller->getID()) switch(event.GUIEvent.Caller->getID())
{ {
case 256: // continue case 256: // continue
quitMenu(); quitMenu();
// ALWAYS return immediately after quitMenu() // ALWAYS return immediately after quitMenu()
return true; return true;
case 261: case 261:
quitMenu(); quitMenu();
m_gamecallback->changePassword(); m_gamecallback->changePassword();
return true; return true;
case 260: // disconnect case 260: // disconnect
m_gamecallback->disconnect(); m_gamecallback->disconnect();
quitMenu(); quitMenu();
return true; return true;
case 257: // exit case 257: // exit
m_gamecallback->exitToOS(); m_gamecallback->exitToOS();
quitMenu(); quitMenu();
return true; return true;
} }
} }
} }
return Parent ? Parent->OnEvent(event) : false; return Parent ? Parent->OnEvent(event) : false;
} }

@ -1,60 +1,60 @@
/* /*
Minetest-c55 Minetest-c55
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com> Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef GUIPAUSEMENU_HEADER #ifndef GUIPAUSEMENU_HEADER
#define GUIPAUSEMENU_HEADER #define GUIPAUSEMENU_HEADER
#include "irrlichttypes_extrabloated.h" #include "irrlichttypes_extrabloated.h"
#include "modalMenu.h" #include "modalMenu.h"
class IGameCallback class IGameCallback
{ {
public: public:
virtual void exitToOS() = 0; virtual void exitToOS() = 0;
virtual void disconnect() = 0; virtual void disconnect() = 0;
virtual void changePassword() = 0; virtual void changePassword() = 0;
}; };
class GUIPauseMenu : public GUIModalMenu class GUIPauseMenu : public GUIModalMenu
{ {
public: public:
GUIPauseMenu(gui::IGUIEnvironment* env, GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
IGameCallback *gamecallback, IGameCallback *gamecallback,
IMenuManager *menumgr, IMenuManager *menumgr,
bool simple_singleplayer_mode); bool simple_singleplayer_mode);
~GUIPauseMenu(); ~GUIPauseMenu();
void removeChildren(); void removeChildren();
/* /*
Remove and re-add (or reposition) stuff Remove and re-add (or reposition) stuff
*/ */
void regenerateGui(v2u32 screensize); void regenerateGui(v2u32 screensize);
void drawMenu(); void drawMenu();
bool OnEvent(const SEvent& event); bool OnEvent(const SEvent& event);
private: private:
IGameCallback *m_gamecallback; IGameCallback *m_gamecallback;
bool m_simple_singleplayer_mode; bool m_simple_singleplayer_mode;
}; };
#endif #endif

@ -1994,7 +1994,7 @@ void Map::removeNodeTimer(v3s16 p)
ServerMap ServerMap
*/ */
ServerMap::ServerMap(std::string savedir, IGameDef *gamedef): ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge):
Map(dout_server, gamedef), Map(dout_server, gamedef),
m_seed(0), m_seed(0),
m_map_metadata_changed(true), m_map_metadata_changed(true),
@ -2004,6 +2004,8 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
{ {
verbosestream<<__FUNCTION_NAME<<std::endl; verbosestream<<__FUNCTION_NAME<<std::endl;
m_emerge = emerge;
//m_chunksize = 8; // Takes a few seconds //m_chunksize = 8; // Takes a few seconds
if (g_settings->get("fixed_map_seed").empty()) if (g_settings->get("fixed_map_seed").empty())
@ -2011,12 +2013,15 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
m_seed = (((u64)(myrand()%0xffff)<<0) m_seed = (((u64)(myrand()%0xffff)<<0)
+ ((u64)(myrand()%0xffff)<<16) + ((u64)(myrand()%0xffff)<<16)
+ ((u64)(myrand()%0xffff)<<32) + ((u64)(myrand()%0xffff)<<32)
+ ((u64)(myrand()%0xffff)<<48)); + ((u64)(myrand()&0xffff)<<48));
} }
else else
{ {
m_seed = g_settings->getU64("fixed_map_seed"); m_seed = g_settings->getU64("fixed_map_seed");
} }
emerge->seed = m_seed;
emerge->water_level = g_settings->getS16("default_water_level");
//<set noiseparams here>
/* /*
Experimental and debug stuff Experimental and debug stuff
@ -2136,7 +2141,7 @@ ServerMap::~ServerMap()
#endif #endif
} }
void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos) void ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos)
{ {
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
if(enable_mapgen_debug_info) if(enable_mapgen_debug_info)
@ -2208,7 +2213,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
Refer to the map generator heuristics. Refer to the map generator heuristics.
*/ */
bool ug = mapgen::block_is_underground(data->seed, p); bool ug = m_emerge->isBlockUnderground(p);
block->setIsUnderground(ug); block->setIsUnderground(ug);
} }
@ -2243,7 +2248,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
// Data is ready now. // Data is ready now.
} }
MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data, MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
core::map<v3s16, MapBlock*> &changed_blocks) core::map<v3s16, MapBlock*> &changed_blocks)
{ {
v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_min = data->blockpos_min;
@ -2483,6 +2488,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
return sector; return sector;
} }
#if 0
/* /*
This is a quick-hand function for calling makeBlock(). This is a quick-hand function for calling makeBlock().
*/ */
@ -2518,7 +2524,7 @@ MapBlock * ServerMap::generateBlock(
/* /*
Create block make data Create block make data
*/ */
mapgen::BlockMakeData data; BlockMakeData data;
initBlockMake(&data, p); initBlockMake(&data, p);
/* /*
@ -2526,7 +2532,8 @@ MapBlock * ServerMap::generateBlock(
*/ */
{ {
TimeTaker t("mapgen::make_block()"); TimeTaker t("mapgen::make_block()");
mapgen::make_block(&data); mapgen->makeChunk(&data);
//mapgen::make_block(&data);
if(enable_mapgen_debug_info == false) if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output t.stop(true); // Hide output
@ -2595,6 +2602,7 @@ MapBlock * ServerMap::generateBlock(
return block; return block;
} }
#endif
MapBlock * ServerMap::createBlock(v3s16 p) MapBlock * ServerMap::createBlock(v3s16 p)
{ {
@ -2656,14 +2664,15 @@ MapBlock * ServerMap::createBlock(v3s16 p)
} }
// Create blank // Create blank
block = sector->createBlankBlock(block_y); block = sector->createBlankBlock(block_y);
return block; return block;
} }
MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate) MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
{ {
DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d", DSTACKF("%s: p=(%d,%d,%d), create_blank=%d",
__FUNCTION_NAME, __FUNCTION_NAME,
p.X, p.Y, p.Z, allow_generate); p.X, p.Y, p.Z, create_blank);
{ {
MapBlock *block = getBlockNoCreateNoEx(p); MapBlock *block = getBlockNoCreateNoEx(p);
@ -2677,7 +2686,13 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
return block; return block;
} }
if(allow_generate) if (create_blank) {
ServerMapSector *sector = createSector(v2s16(p.X, p.Z));
MapBlock *block = sector->createBlankBlock(p.Y);
return block;
}
/*if(allow_generate)
{ {
core::map<v3s16, MapBlock*> modified_blocks; core::map<v3s16, MapBlock*> modified_blocks;
MapBlock *block = generateBlock(p, modified_blocks); MapBlock *block = generateBlock(p, modified_blocks);
@ -2700,7 +2715,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
return block; return block;
} }
} }*/
return NULL; return NULL;
} }
@ -2742,7 +2757,7 @@ plan_b:
Determine from map generator noise functions Determine from map generator noise functions
*/ */
s16 level = mapgen::find_ground_level_from_noise(m_seed, p2d, 1); s16 level = m_emerge->getGroundLevelAtPoint(p2d);
return level; return level;
//double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT; //double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
@ -3062,6 +3077,7 @@ void ServerMap::saveMapMeta()
Settings params; Settings params;
params.setU64("seed", m_seed); params.setU64("seed", m_seed);
params.setS16("water_level", m_emerge->water_level);
params.writeLines(os); params.writeLines(os);
@ -3100,8 +3116,11 @@ void ServerMap::loadMapMeta()
break; break;
params.parseConfigLine(line); params.parseConfigLine(line);
} }
m_seed = params.getU64("seed"); m_seed = params.getU64("seed");
m_emerge->seed = m_seed;
m_emerge->water_level = params.getS16("water_level");
//m_emerge->np = ;
verbosestream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl; verbosestream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl;
} }

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapnode.h" #include "mapnode.h"
#include "constants.h" #include "constants.h"
#include "voxel.h" #include "voxel.h"
#include "mapgen.h" //for BlockMakeData and EmergeManager
#include "modifiedstate.h" #include "modifiedstate.h"
#include "util/container.h" #include "util/container.h"
#include "nodetimer.h" #include "nodetimer.h"
@ -46,9 +47,6 @@ class NodeMetadata;
class IGameDef; class IGameDef;
class IRollbackReportSink; class IRollbackReportSink;
namespace mapgen{
struct BlockMakeData;
};
/* /*
MapEditEvent MapEditEvent
@ -360,7 +358,7 @@ public:
/* /*
savedir: directory to which map data should be saved savedir: directory to which map data should be saved
*/ */
ServerMap(std::string savedir, IGameDef *gamedef); ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge);
~ServerMap(); ~ServerMap();
s32 mapType() const s32 mapType() const
@ -379,15 +377,15 @@ public:
/* /*
Blocks are generated by using these and makeBlock(). Blocks are generated by using these and makeBlock().
*/ */
void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos); void initBlockMake(BlockMakeData *data, v3s16 blockpos);
MapBlock* finishBlockMake(mapgen::BlockMakeData *data, MapBlock* finishBlockMake(BlockMakeData *data,
core::map<v3s16, MapBlock*> &changed_blocks); core::map<v3s16, MapBlock*> &changed_blocks);
// A non-threaded wrapper to the above // A non-threaded wrapper to the above - DEFUNCT
MapBlock * generateBlock( /* MapBlock * generateBlock(
v3s16 p, v3s16 p,
core::map<v3s16, MapBlock*> &modified_blocks core::map<v3s16, MapBlock*> &modified_blocks
); );*/
/* /*
Get a block from somewhere. Get a block from somewhere.
@ -400,9 +398,10 @@ public:
Forcefully get a block from somewhere. Forcefully get a block from somewhere.
- Memory - Memory
- Load from disk - Load from disk
- Generate - Create blank filled with CONTENT_IGNORE
*/ */
MapBlock * emergeBlock(v3s16 p, bool allow_generate=true); MapBlock * emergeBlock(v3s16 p, bool create_blank=true);
// Helper for placing objects on ground level // Helper for placing objects on ground level
s16 findGroundLevel(v2s16 p2d); s16 findGroundLevel(v2s16 p2d);
@ -479,6 +478,7 @@ public:
u64 getSeed(){ return m_seed; } u64 getSeed(){ return m_seed; }
EmergeManager *m_emerge;
private: private:
// Seed used for all kinds of randomness in generation // Seed used for all kinds of randomness in generation
u64 m_seed; u64 m_seed;

@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h" #include "mapgen.h"
#include "voxel.h" #include "voxel.h"
#include "noise.h" #include "noise.h"
#include "biome.h"
#include "mapblock.h" #include "mapblock.h"
#include "mapnode.h"
#include "map.h" #include "map.h"
//#include "serverobject.h" //#include "serverobject.h"
#include "content_sao.h" #include "content_sao.h"
@ -28,9 +30,296 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_mapnode.h" // For content_mapnode_get_new_name #include "content_mapnode.h" // For content_mapnode_get_new_name
#include "voxelalgorithms.h" #include "voxelalgorithms.h"
#include "profiler.h" #include "profiler.h"
#include "settings.h" // For g_settings
#include "main.h" // For g_profiler #include "main.h" // For g_profiler
#include "treegen.h" #include "treegen.h"
NoiseParams nparams_mtdefault =
{0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6}; //terrain
NoiseParams nparams_def_bgroup =
{0.5, 1/(2*1.6), v3f(250., 250., 250.), 5923, 2, 0.60}; //0 to 1
NoiseParams nparams_def_heat =
{25.0, 50.0, v3f(500., 500., 500.), 35293, 1, 0.00}; //-25 to 75
NoiseParams nparams_def_humidity =
{50, 100/(2*1.6), v3f(750., 750., 750.), 12094, 2, 0.60}; //0 to 100
///////////////////////////////////////////////////////////////////////////////
/*
Mapgen::Mapgen(BiomeDefManager *biomedef) {
Mapgen(0, 0, biomedef);
}*/
Mapgen::Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed) {
initMapgen(biomedef, mapgenid, seed,
&nparams_mtdefault, &nparams_def_bgroup,
&nparams_def_heat, &nparams_def_humidity);
}
Mapgen::Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity) {
initMapgen(biomedef, mapgenid, seed,
np_terrain, np_bgroup, np_heat, np_humidity);
}
void Mapgen::initMapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity) {
this->generating = false;
this->id = mapgenid;
this->seed = (int)seed;
this->biomedef = biomedef;
this->csize = v3s16(5, 5, 5) * MAP_BLOCKSIZE; /////////////////get this from config!
this->water_level = g_settings->getS16("default_water_level"); ////fix this!
this->np_terrain = np_terrain;
this->np_bgroup = np_bgroup;
this->np_heat = np_heat;
this->np_humidity = np_humidity;
noise_terrain = new Noise(np_terrain, seed, csize.X, csize.Y);
noise_bgroup = new Noise(np_bgroup, seed, csize.X, csize.Y);
noise_heat = new Noise(np_heat, seed, csize.X, csize.Y);
noise_humidity = new Noise(np_humidity, seed, csize.X, csize.Y);
this->ndef = biomedef->ndef;
n_air = MapNode(ndef->getId("mapgen_air"));
n_water = MapNode(ndef->getId("mapgen_water_source"));
n_lava = MapNode(ndef->getId("mapgen_lava_source"));
}
Mapgen::~Mapgen() {
delete noise_terrain;
delete noise_bgroup;
delete noise_heat;
delete noise_humidity;
}
void Mapgen::makeChunk(BlockMakeData *data) {
if (data->no_op)
return;
//printf("generating...\n");//////////////
assert(data->vmanip);
assert(data->nodedef);
assert(data->blockpos_requested.X >= data->blockpos_min.X &&
data->blockpos_requested.Y >= data->blockpos_min.Y &&
data->blockpos_requested.Z >= data->blockpos_min.Z);
assert(data->blockpos_requested.X <= data->blockpos_max.X &&
data->blockpos_requested.Y <= data->blockpos_max.Y &&
data->blockpos_requested.Z <= data->blockpos_max.Z);
this->generating = true;
this->data = data;
this->vmanip = data->vmanip;
v3s16 em = vmanip->m_area.getExtent();
this->ystride = em.X;
this->zstride = em.Y * em.X;
node_min = (data->blockpos_min) * MAP_BLOCKSIZE;
node_max = (data->blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
v3s16 full_node_min = (data->blockpos_min - 1) * MAP_BLOCKSIZE;
v3s16 full_node_max = (data->blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1,1,1);
int y1 = node_min.Y;
int y2 = node_max.Y;
int x = node_min.X;
int z = node_min.Z;
//printf("full_node_min.X: %d | full_node_min.Z: %d | MinEdge: %d | MaxEdge: %d\n", node_min.X, node_min.Z, vmanip->m_area.MinEdge.X, vmanip->m_area.MinEdge.Z);
TimeTaker timer("Generating terrain");
map_terrain = noise_terrain->perlinMap2D(x, z);
map_bgroup = noise_bgroup->perlinMap2D(x, z);
map_heat = noise_heat->perlinMap2D(x, z);
map_humidity = noise_humidity->perlinMap2D(x, z);
int i = 0;
for (x = node_min.X; x <= node_max.X; x++) {
for (z = node_min.Z; z <= node_max.Z; z++) {
Biome *biome = biomedef->getBiome(map_bgroup[i], map_heat[i], map_humidity[i]);
biome->genColumn(this, x, z, y1, y2);
i++;
}
}
timer.stop();
//genCave();
//genDungeon();
//add blobs of dirt and gravel underground
//decorateChunk();
//updateLiquid(full_node_min, full_node_max);
updateLighting(node_min, node_max);
this->generating = false;
//printf("generated block (%d, %d) to (%d, %d)\n", node_min.X, node_min.Y, node_max.X, node_max.Y);//////////
}
void Mapgen::updateLiquid(v3s16 node_min, v3s16 node_max) {
bool isliquid, wasliquid;
u32 i;
content_t c;
for (s16 z = node_min.Z; z <= node_max.Z; z++) {
for (s16 x = node_min.X; x <= node_max.X; x++) {
v2s16 p2d(x, z);
wasliquid = true;
v3s16 em = vmanip->m_area.getExtent();
i = vmanip->m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
isliquid = ndef->get(vmanip->m_data[i]).isLiquid();
//there was a change between liquid and nonliquid, add to queue
if (isliquid != wasliquid)
data->transforming_liquid.push_back(v3s16(p2d.X, y, p2d.Y));
wasliquid = isliquid;
vmanip->m_area.add_y(em, i, -1);
}
}
}
}
void Mapgen::updateLighting(v3s16 node_min, v3s16 node_max) {
enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT};
VoxelArea a(node_min - v3s16(1,0,1) * MAP_BLOCKSIZE,
node_max + v3s16(1,0,1) * MAP_BLOCKSIZE);
bool block_is_underground = (water_level > node_max.Y);
bool sunlight = !block_is_underground;
ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
for (int i = 0; i < 2; i++) {
enum LightBank bank = banks[i];
core::map<v3s16, bool> light_sources;
core::map<v3s16, u8> unlight_from;
voxalgo::clearLightAndCollectSources(*vmanip, a, bank, ndef,
light_sources, unlight_from);
voxalgo::propagateSunlight(*vmanip, a, sunlight, light_sources, ndef);
printf("light_sources: %d\t\tunlight_from: %d\n", light_sources.size(), unlight_from.size());
vmanip->unspreadLight(bank, unlight_from, light_sources, ndef);
vmanip->spreadLight(bank, light_sources, ndef);
}
}
/*class EmergeManager {
public:
int seed;
int water_level;
BiomeDefManager *biomedef;
//mapgen objects here
void addBlockToQueue();
//mapgen helper methods
int getGroundLevelAtPoint(u64 mseed, v2s16 p);
bool isBlockUnderground(u64 mseed, v3s16 blockpos);
u32 getBlockSeed(u64 mseed, v3s16 p);
};*/
EmergeManager::EmergeManager(IGameDef *gamedef) {
this->seed = 0;
this->water_level = 0;
this->np_terrain = &nparams_mtdefault;
this->np_bgroup = &nparams_def_bgroup;
this->np_heat = &nparams_def_heat;
this->np_humidity = &nparams_def_humidity;
this->biomedef = new BiomeDefManager(gamedef);
}
EmergeManager::~EmergeManager() {
delete biomedef;
}
void EmergeManager::addBlockToQueue() {
}
Biome *EmergeManager::getBiomeAtPoint(v3s16 p) {
float bgroup = NoisePerlin2D(np_bgroup, p.X, p.Y, seed);
float heat = NoisePerlin2D(np_heat, p.X, p.Y, seed);
float humidity = NoisePerlin2D(np_humidity, p.X, p.Y, seed);
return biomedef->getBiome(bgroup, heat, humidity);
}
//FIXME: This assumes y == 0, that is, always in a non-hell/non-sky biome
int EmergeManager::getGroundLevelAtPoint(v2s16 p) {
float terrain = NoisePerlin2D(np_terrain, p.X, p.Y, seed);
Biome *biome = getBiomeAtPoint(v3s16(p.X, p.Y, 0));
return biome->getSurfaceHeight(terrain);
}
bool EmergeManager::isBlockUnderground(v3s16 blockpos) {
/*
v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2,
(blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2);
int ground_level = getGroundLevelAtPoint(p);
return blockpos.Y * (MAP_BLOCKSIZE + 1) <= min(water_level, ground_level);
*/
//yuck, but then again, should i bother being accurate?
//the height of the nodes in a single block is quite variable
return false; //blockpos.Y * (MAP_BLOCKSIZE + 1) <= water_level;
}
u32 EmergeManager::getBlockSeed(v3s16 p) {
return (u32)(seed & 0xFFFFFFFF) +
p.Z * 38134234 +
p.Y * 42123 +
p.Y * 23;
}
/////////////////////////////////// legacy static functions for farmesh
s16 Mapgen::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) {
//just need to return something
s16 level = 5;
return level;
}
bool Mapgen::get_have_beach(u64 seed, v2s16 p2d) {
double sandnoise = noise2d_perlin(
0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250,
seed+59420, 3, 0.50);
return (sandnoise > 0.15);
}
double Mapgen::tree_amount_2d(u64 seed, v2s16 p) {
double noise = noise2d_perlin(
0.5+(float)p.X/125, 0.5+(float)p.Y/125,
seed+2, 4, 0.66);
double zeroval = -0.39;
if(noise < zeroval)
return 0;
else
return 0.04 * (noise-zeroval) / (1.0-zeroval);
}
#if 0 /// BIG COMMENT
namespace mapgen namespace mapgen
{ {
@ -121,6 +410,7 @@ static s16 find_stone_level(VoxelManipulator &vmanip, v2s16 p2d,
} }
#endif #endif
#if 0 #if 0
static void make_papyrus(VoxelManipulator &vmanip, v3s16 p0, static void make_papyrus(VoxelManipulator &vmanip, v3s16 p0,
@ -190,7 +480,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble")); vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
} }
} }
// Make +-Z walls // Make +-Z walls
for(s16 x=0; x<roomsize.X; x++) for(s16 x=0; x<roomsize.X; x++)
for(s16 y=0; y<roomsize.Y; y++) for(s16 y=0; y<roomsize.Y; y++)
@ -214,7 +504,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble")); vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
} }
} }
// Make +-Y walls (floor and ceiling) // Make +-Y walls (floor and ceiling)
for(s16 z=0; z<roomsize.Z; z++) for(s16 z=0; z<roomsize.Z; z++)
for(s16 x=0; x<roomsize.X; x++) for(s16 x=0; x<roomsize.X; x++)
@ -238,7 +528,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble")); vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
} }
} }
// Fill with air // Fill with air
for(s16 z=1; z<roomsize.Z-1; z++) for(s16 z=1; z<roomsize.Z-1; z++)
for(s16 y=1; y<roomsize.Y-1; y++) for(s16 y=1; y<roomsize.Y-1; y++)
@ -401,9 +691,9 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace,
if(partcount >= partlength) if(partcount >= partlength)
{ {
partcount = 0; partcount = 0;
dir = random_turn(random, dir); dir = random_turn(random, dir);
partlength = random.range(1,length); partlength = random.range(1,length);
make_stairs = 0; make_stairs = 0;
@ -443,7 +733,7 @@ public:
{ {
m_dir = dir; m_dir = dir;
} }
bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir) bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
{ {
for(u32 i=0; i<100; i++) for(u32 i=0; i<100; i++)
@ -540,7 +830,7 @@ public:
if(doordir == v3s16(0,0,-1)) // Z- if(doordir == v3s16(0,0,-1)) // Z-
roomplace = doorplace + v3s16(-roomsize.X/2,-1,-roomsize.Z+1); roomplace = doorplace + v3s16(-roomsize.X/2,-1,-roomsize.Z+1);
#endif #endif
// Check fit // Check fit
bool fits = true; bool fits = true;
for(s16 z=1; z<roomsize.Z-1; z++) for(s16 z=1; z<roomsize.Z-1; z++)
@ -587,7 +877,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
v3s16 areasize = vmanip.m_area.getExtent(); v3s16 areasize = vmanip.m_area.getExtent();
v3s16 roomsize; v3s16 roomsize;
v3s16 roomplace; v3s16 roomplace;
/* /*
Find place for first room Find place for first room
*/ */
@ -627,20 +917,20 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
// No place found // No place found
if(fits == false) if(fits == false)
return; return;
/* /*
Stores the center position of the last room made, so that Stores the center position of the last room made, so that
a new corridor can be started from the last room instead of a new corridor can be started from the last room instead of
the new room, if chosen so. the new room, if chosen so.
*/ */
v3s16 last_room_center = roomplace+v3s16(roomsize.X/2,1,roomsize.Z/2); v3s16 last_room_center = roomplace+v3s16(roomsize.X/2,1,roomsize.Z/2);
u32 room_count = random.range(2,7); u32 room_count = random.range(2,7);
for(u32 i=0; i<room_count; i++) for(u32 i=0; i<room_count; i++)
{ {
// Make a room to the determined place // Make a room to the determined place
make_room1(vmanip, roomsize, roomplace, ndef); make_room1(vmanip, roomsize, roomplace, ndef);
v3s16 room_center = roomplace + v3s16(roomsize.X/2,1,roomsize.Z/2); v3s16 room_center = roomplace + v3s16(roomsize.X/2,1,roomsize.Z/2);
// Place torch at room center (for testing) // Place torch at room center (for testing)
@ -649,7 +939,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
// Quit if last room // Quit if last room
if(i == room_count-1) if(i == room_count-1)
break; break;
// Determine walker start position // Determine walker start position
bool start_in_last_room = (random.range(0,2)!=0); bool start_in_last_room = (random.range(0,2)!=0);
@ -667,7 +957,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
// Store center of current room as the last one // Store center of current room as the last one
last_room_center = room_center; last_room_center = room_center;
} }
// Create walker and find a place for a door // Create walker and find a place for a door
RoomWalker walker(vmanip, walker_start_place, random, ndef); RoomWalker walker(vmanip, walker_start_place, random, ndef);
v3s16 doorplace; v3s16 doorplace;
@ -675,20 +965,20 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
bool r = walker.findPlaceForDoor(doorplace, doordir); bool r = walker.findPlaceForDoor(doorplace, doordir);
if(r == false) if(r == false)
return; return;
if(random.range(0,1)==0) if(random.range(0,1)==0)
// Make the door // Make the door
make_door1(vmanip, doorplace, doordir, ndef); make_door1(vmanip, doorplace, doordir, ndef);
else else
// Don't actually make a door // Don't actually make a door
doorplace -= doordir; doorplace -= doordir;
// Make a random corridor starting from the door // Make a random corridor starting from the door
v3s16 corridor_end; v3s16 corridor_end;
v3s16 corridor_end_dir; v3s16 corridor_end_dir;
make_corridor(vmanip, doorplace, doordir, corridor_end, make_corridor(vmanip, doorplace, doordir, corridor_end,
corridor_end_dir, random, ndef); corridor_end_dir, random, ndef);
// Find a place for a random sized room // Find a place for a random sized room
roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8)); roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8));
walker.setPos(corridor_end); walker.setPos(corridor_end);
@ -703,7 +993,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
else else
// Don't actually make a door // Don't actually make a door
roomplace -= doordir; roomplace -= doordir;
} }
} }
#endif #endif
@ -926,7 +1216,7 @@ s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision)
} }
} }
} }
// This is more like the actual ground level // This is more like the actual ground level
level += dec[i-1]/2; level += dec[i-1]/2;
@ -1024,7 +1314,7 @@ bool block_is_underground(u64 seed, v3s16 blockpos)
seed, v2s16(blockpos.X, blockpos.Z));*/ seed, v2s16(blockpos.X, blockpos.Z));*/
// Nah, this is just a heuristic, just return something // Nah, this is just a heuristic, just return something
s16 minimum_groundlevel = WATER_LEVEL; s16 minimum_groundlevel = WATER_LEVEL;
if(blockpos.Y*MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel) if(blockpos.Y*MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel)
return true; return true;
else else
@ -1132,9 +1422,9 @@ BiomeType get_biome(u64 seed, v2s16 p2d)
double d = noise2d_perlin( double d = noise2d_perlin(
0.6+(float)p2d.X/250, 0.2+(float)p2d.Y/250, 0.6+(float)p2d.X/250, 0.2+(float)p2d.Y/250,
seed+9130, 3, 0.50); seed+9130, 3, 0.50);
if(d > 0.45) if(d > 0.45)
return BT_DESERT; return BT_DESERT;
if(d > 0.35 && (noise2d( p2d.X, p2d.Y, int(seed) ) + 1.0) > ( 0.45 - d ) * 20.0 ) if(d > 0.35 && (noise2d( p2d.X, p2d.Y, int(seed) ) + 1.0) > ( 0.45 - d ) * 20.0 )
return BT_DESERT; return BT_DESERT;
return BT_NORMAL; return BT_NORMAL;
}; };
@ -1169,7 +1459,7 @@ void make_block(BlockMakeData *data)
// Hack: use minimum block coordinates for old code that assumes // Hack: use minimum block coordinates for old code that assumes
// a single block // a single block
v3s16 blockpos = data->blockpos_requested; v3s16 blockpos = data->blockpos_requested;
/*dstream<<"makeBlock(): ("<<blockpos.X<<","<<blockpos.Y<<"," /*dstream<<"makeBlock(): ("<<blockpos.X<<","<<blockpos.Y<<","
<<blockpos.Z<<")"<<std::endl;*/ <<blockpos.Z<<")"<<std::endl;*/
@ -1177,7 +1467,7 @@ void make_block(BlockMakeData *data)
v3s16 blockpos_max = data->blockpos_max; v3s16 blockpos_max = data->blockpos_max;
v3s16 blockpos_full_min = blockpos_min - v3s16(1,1,1); v3s16 blockpos_full_min = blockpos_min - v3s16(1,1,1);
v3s16 blockpos_full_max = blockpos_max + v3s16(1,1,1); v3s16 blockpos_full_max = blockpos_max + v3s16(1,1,1);
ManualMapVoxelManipulator &vmanip = *(data->vmanip); ManualMapVoxelManipulator &vmanip = *(data->vmanip);
// Area of central chunk // Area of central chunk
v3s16 node_min = blockpos_min*MAP_BLOCKSIZE; v3s16 node_min = blockpos_min*MAP_BLOCKSIZE;
@ -1193,10 +1483,10 @@ void make_block(BlockMakeData *data)
int volume_blocks = (blockpos_max.X - blockpos_min.X + 1) int volume_blocks = (blockpos_max.X - blockpos_min.X + 1)
* (blockpos_max.Y - blockpos_min.Y + 1) * (blockpos_max.Y - blockpos_min.Y + 1)
* (blockpos_max.Z - blockpos_max.Z + 1); * (blockpos_max.Z - blockpos_max.Z + 1);
int volume_nodes = volume_blocks * int volume_nodes = volume_blocks *
MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
// Generated surface area // Generated surface area
//double gen_area_nodes = MAP_BLOCKSIZE*MAP_BLOCKSIZE * rel_volume; //double gen_area_nodes = MAP_BLOCKSIZE*MAP_BLOCKSIZE * rel_volume;
@ -1207,7 +1497,7 @@ void make_block(BlockMakeData *data)
Create a block-specific seed Create a block-specific seed
*/ */
u32 blockseed = get_blockseed(data->seed, full_node_min); u32 blockseed = get_blockseed(data->seed, full_node_min);
/* /*
Cache some ground type values for speed Cache some ground type values for speed
*/ */
@ -1253,13 +1543,13 @@ void make_block(BlockMakeData *data)
{ {
#if 1 #if 1
TimeTaker timer1("Generating ground level"); TimeTaker timer1("Generating ground level");
for(s16 x=node_min.X; x<=node_max.X; x++) for(s16 x=node_min.X; x<=node_max.X; x++)
for(s16 z=node_min.Z; z<=node_max.Z; z++) for(s16 z=node_min.Z; z<=node_max.Z; z++)
{ {
// Node position // Node position
v2s16 p2d = v2s16(x,z); v2s16 p2d = v2s16(x,z);
/* /*
Skip of already generated Skip of already generated
*/ */
@ -1274,7 +1564,7 @@ void make_block(BlockMakeData *data)
// Use perlin noise for ground height // Use perlin noise for ground height
surface_y_f = base_rock_level_2d(data->seed, p2d); surface_y_f = base_rock_level_2d(data->seed, p2d);
/*// Experimental stuff /*// Experimental stuff
{ {
float a = highlands_level_2d(data->seed, p2d); float a = highlands_level_2d(data->seed, p2d);
@ -1284,7 +1574,7 @@ void make_block(BlockMakeData *data)
// Convert to integer // Convert to integer
s16 surface_y = (s16)surface_y_f; s16 surface_y = (s16)surface_y_f;
// Log it // Log it
if(surface_y > stone_surface_max_y) if(surface_y > stone_surface_max_y)
stone_surface_max_y = surface_y; stone_surface_max_y = surface_y;
@ -1316,9 +1606,9 @@ void make_block(BlockMakeData *data)
} }
} }
#endif #endif
}//timer1 }//timer1
// Limit dirt flow area by 1 because mud is flown into neighbors. // Limit dirt flow area by 1 because mud is flown into neighbors.
assert(central_area_size.X == central_area_size.Z); assert(central_area_size.X == central_area_size.Z);
s16 mudflow_minpos = 0-max_spread_amount+1; s16 mudflow_minpos = 0-max_spread_amount+1;
@ -1375,7 +1665,7 @@ void make_block(BlockMakeData *data)
tunnel_routepoints = ps.range(10, ps.range(15,30)); tunnel_routepoints = ps.range(10, ps.range(15,30));
} }
bool large_cave_is_flat = (ps.range(0,1) == 0); bool large_cave_is_flat = (ps.range(0,1) == 0);
v3f main_direction(0,0,0); v3f main_direction(0,0,0);
// Allowed route area size in nodes // Allowed route area size in nodes
@ -1391,7 +1681,7 @@ void make_block(BlockMakeData *data)
s16 more = max_spread_amount - max_tunnel_diameter/2 - insure; s16 more = max_spread_amount - max_tunnel_diameter/2 - insure;
ar += v3s16(1,0,1) * more * 2; ar += v3s16(1,0,1) * more * 2;
of -= v3s16(1,0,1) * more; of -= v3s16(1,0,1) * more;
s16 route_y_min = 0; s16 route_y_min = 0;
// Allow half a diameter + 7 over stone surface // Allow half a diameter + 7 over stone surface
s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2 + 7; s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2 + 7;
@ -1434,7 +1724,7 @@ void make_block(BlockMakeData *data)
if(coming_from_surface) if(coming_from_surface)
route_start_y_min = -of.Y + stone_surface_max_y + 10; route_start_y_min = -of.Y + stone_surface_max_y + 10;
}*/ }*/
route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1); route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1);
route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1); route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1);
@ -1451,11 +1741,11 @@ void make_block(BlockMakeData *data)
MapNode airnode(CONTENT_AIR); MapNode airnode(CONTENT_AIR);
MapNode waternode(c_water_source); MapNode waternode(c_water_source);
MapNode lavanode(c_lava_source); MapNode lavanode(c_lava_source);
/* /*
Generate some tunnel starting from orp Generate some tunnel starting from orp
*/ */
for(u16 j=0; j<tunnel_routepoints; j++) for(u16 j=0; j<tunnel_routepoints; j++)
{ {
if(j%dswitchint==0 && large_cave == false) if(j%dswitchint==0 && large_cave == false)
@ -1467,12 +1757,12 @@ void make_block(BlockMakeData *data)
); );
main_direction *= (float)ps.range(0, 10)/10; main_direction *= (float)ps.range(0, 10)/10;
} }
// Randomize size // Randomize size
s16 min_d = min_tunnel_diameter; s16 min_d = min_tunnel_diameter;
s16 max_d = max_tunnel_diameter; s16 max_d = max_tunnel_diameter;
s16 rs = ps.range(min_d, max_d); s16 rs = ps.range(min_d, max_d);
// Every second section is rough // Every second section is rough
bool randomize_xz = (ps2.range(1,2) == 1); bool randomize_xz = (ps2.range(1,2) == 1);
@ -1495,13 +1785,13 @@ void make_block(BlockMakeData *data)
} }
v3f vec; v3f vec;
vec = v3f( vec = v3f(
(float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2, (float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
(float)(ps.next()%(maxlen.Y*1))-(float)maxlen.Y/2, (float)(ps.next()%(maxlen.Y*1))-(float)maxlen.Y/2,
(float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2 (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
); );
// Jump downward sometimes // Jump downward sometimes
if(!large_cave && ps.range(0,12) == 0) if(!large_cave && ps.range(0,12) == 0)
{ {
@ -1511,7 +1801,7 @@ void make_block(BlockMakeData *data)
(float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2 (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
); );
} }
/*if(large_cave){ /*if(large_cave){
v3f p = orp + vec; v3f p = orp + vec;
s16 h = find_ground_level_clever(vmanip, s16 h = find_ground_level_clever(vmanip,
@ -1573,12 +1863,12 @@ void make_block(BlockMakeData *data)
s16 x = cp.X + x0; s16 x = cp.X + x0;
v3s16 p(x,y,z); v3s16 p(x,y,z);
p += of; p += of;
if(vmanip.m_area.contains(p) == false) if(vmanip.m_area.contains(p) == false)
continue; continue;
u32 i = vmanip.m_area.index(p); u32 i = vmanip.m_area.index(p);
if(large_cave) if(large_cave)
{ {
if(full_node_min.Y < WATER_LEVEL && if(full_node_min.Y < WATER_LEVEL &&
@ -1602,7 +1892,7 @@ void make_block(BlockMakeData *data)
vmanip.m_data[i].getContent() == c_water_source || vmanip.m_data[i].getContent() == c_water_source ||
vmanip.m_data[i].getContent() == c_lava_source) vmanip.m_data[i].getContent() == c_lava_source)
continue; continue;
vmanip.m_data[i] = airnode; vmanip.m_data[i] = airnode;
// Set tunnel flag // Set tunnel flag
@ -1615,12 +1905,12 @@ void make_block(BlockMakeData *data)
orp = rp; orp = rp;
} }
} }
}//timer1 }//timer1
#endif #endif
#if 1 #if 1
{ {
// 15ms @cs=8 // 15ms @cs=8
@ -1629,13 +1919,13 @@ void make_block(BlockMakeData *data)
/* /*
Add mud to the central chunk Add mud to the central chunk
*/ */
for(s16 x=node_min.X; x<=node_max.X; x++) for(s16 x=node_min.X; x<=node_max.X; x++)
for(s16 z=node_min.Z; z<=node_max.Z; z++) for(s16 z=node_min.Z; z<=node_max.Z; z++)
{ {
// Node position in 2d // Node position in 2d
v2s16 p2d = v2s16(x,z); v2s16 p2d = v2s16(x,z);
// Randomize mud amount // Randomize mud amount
s16 mud_add_amount = get_mud_add_amount(data->seed, p2d) / 2.0 + 0.5; s16 mud_add_amount = get_mud_add_amount(data->seed, p2d) / 2.0 + 0.5;
@ -1660,7 +1950,7 @@ void make_block(BlockMakeData *data)
surface_y + mud_add_amount <= WATER_LEVEL+2){ surface_y + mud_add_amount <= WATER_LEVEL+2){
addnode = MapNode(c_sand); addnode = MapNode(c_sand);
} }
if(bt == BT_DESERT){ if(bt == BT_DESERT){
if(surface_y > 20){ if(surface_y > 20){
mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20)/5); mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20)/5);
@ -1691,7 +1981,7 @@ void make_block(BlockMakeData *data)
{ {
if(mudcount >= mud_add_amount) if(mudcount >= mud_add_amount)
break; break;
MapNode &n = vmanip.m_data[i]; MapNode &n = vmanip.m_data[i];
n = addnode; n = addnode;
mudcount++; mudcount++;
@ -1756,7 +2046,7 @@ void make_block(BlockMakeData *data)
/* /*
Flow mud away from steep edges Flow mud away from steep edges
*/ */
// Iterate a few times // Iterate a few times
for(s16 k=0; k<3; k++) for(s16 k=0; k<3; k++)
{ {
@ -1773,7 +2063,7 @@ void make_block(BlockMakeData *data)
// Node position in 2d // Node position in 2d
v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x,z); v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x,z);
v3s16 em = vmanip.m_area.getExtent(); v3s16 em = vmanip.m_area.getExtent();
u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y)); u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
s16 y=node_max.Y; s16 y=node_max.Y;
@ -1794,7 +2084,7 @@ void make_block(BlockMakeData *data)
n->getContent() == c_dirt_with_grass || n->getContent() == c_dirt_with_grass ||
n->getContent() == c_gravel) n->getContent() == c_gravel)
break; break;
vmanip.m_area.add_y(em, i, -1); vmanip.m_area.add_y(em, i, -1);
} }
@ -1813,7 +2103,7 @@ void make_block(BlockMakeData *data)
{ {
// Make it exactly mud // Make it exactly mud
n->setContent(c_dirt); n->setContent(c_dirt);
/* /*
Don't flow it if the stuff under it is not mud Don't flow it if the stuff under it is not mud
*/ */
@ -1851,7 +2141,7 @@ void make_block(BlockMakeData *data)
} }
// Drop mud on side // Drop mud on side
for(u32 di=0; di<4; di++) for(u32 di=0; di<4; di++)
{ {
v3s16 dirp = dirs4[di]; v3s16 dirp = dirs4[di];
@ -1894,7 +2184,7 @@ void make_block(BlockMakeData *data)
// Loop one up so that we're in air // Loop one up so that we're in air
vmanip.m_area.add_y(em, i2, 1); vmanip.m_area.add_y(em, i2, 1);
n2 = &vmanip.m_data[i2]; n2 = &vmanip.m_data[i2];
bool old_is_water = (n->getContent() == c_water_source); bool old_is_water = (n->getContent() == c_water_source);
// Move mud to new place // Move mud to new place
if(!dropped_to_unknown) { if(!dropped_to_unknown) {
@ -1912,7 +2202,7 @@ void make_block(BlockMakeData *data)
} }
} }
} }
} }
}//timer1 }//timer1
@ -1940,7 +2230,7 @@ void make_block(BlockMakeData *data)
for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--) for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
{ {
if(y == full_node_max.Y){ if(y == full_node_max.Y){
water_found = water_found =
(vmanip.m_data[i].getContent() == c_water_source || (vmanip.m_data[i].getContent() == c_water_source ||
vmanip.m_data[i].getContent() == c_lava_source); vmanip.m_data[i].getContent() == c_lava_source);
} }
@ -1982,7 +2272,7 @@ void make_block(BlockMakeData *data)
{ {
// Node position in 2d // Node position in 2d
v2s16 p2d = v2s16(x,z); v2s16 p2d = v2s16(x,z);
/* /*
Find the lowest surface to which enough light ends up Find the lowest surface to which enough light ends up
to make grass grow. to make grass grow.
@ -2008,7 +2298,7 @@ void make_block(BlockMakeData *data)
else else
surface_y = full_node_min.Y; surface_y = full_node_min.Y;
} }
u32 i = vmanip.m_area.index(p2d.X, surface_y, p2d.Y); u32 i = vmanip.m_area.index(p2d.X, surface_y, p2d.Y);
MapNode *n = &vmanip.m_data[i]; MapNode *n = &vmanip.m_data[i];
if(n->getContent() == c_dirt){ if(n->getContent() == c_dirt){
@ -2113,7 +2403,7 @@ void make_block(BlockMakeData *data)
else else
vmanip.m_data[i] = n_stone; vmanip.m_data[i] = n_stone;
} }
vmanip->m_area.add_y(em, i, 1); vmanip->m_area.add_y(em, i, 1);
} }
} }
@ -2168,7 +2458,7 @@ void make_block(BlockMakeData *data)
/* /*
Add dungeons Add dungeons
*/ */
//if(node_min.Y < approx_groundlevel) //if(node_min.Y < approx_groundlevel)
//if(myrand() % 3 == 0) //if(myrand() % 3 == 0)
//if(myrand() % 3 == 0 && node_min.Y < approx_groundlevel) //if(myrand() % 3 == 0 && node_min.Y < approx_groundlevel)
@ -2182,7 +2472,7 @@ void make_block(BlockMakeData *data)
// Dungeon generator doesn't modify places which have this set // Dungeon generator doesn't modify places which have this set
vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE
| VMANIP_FLAG_DUNGEON_PRESERVE); | VMANIP_FLAG_DUNGEON_PRESERVE);
// Set all air and water to be untouchable to make dungeons open // Set all air and water to be untouchable to make dungeons open
// to caves and open air // to caves and open air
for(s16 x=full_node_min.X; x<=full_node_max.X; x++) for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
@ -2204,12 +2494,12 @@ void make_block(BlockMakeData *data)
} }
} }
} }
PseudoRandom random(blockseed+2); PseudoRandom random(blockseed+2);
// Add it // Add it
make_dungeon1(vmanip, random, ndef); make_dungeon1(vmanip, random, ndef);
// Convert some cobble to mossy cobble // Convert some cobble to mossy cobble
for(s16 x=full_node_min.X; x<=full_node_max.X; x++) for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++) for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
@ -2257,7 +2547,7 @@ void make_block(BlockMakeData *data)
make_nc(vmanip, ncrandom, ndef); make_nc(vmanip, ncrandom, ndef);
} }
} }
/* /*
Add top and bottom side of water to transforming_liquid queue Add top and bottom side of water to transforming_liquid queue
*/ */
@ -2346,7 +2636,7 @@ void make_block(BlockMakeData *data)
if(current_depth == 0 && y <= WATER_LEVEL+2 if(current_depth == 0 && y <= WATER_LEVEL+2
&& possibly_have_sand) && possibly_have_sand)
have_sand = true; have_sand = true;
if(current_depth < 4) if(current_depth < 4)
{ {
if(have_sand) if(have_sand)
@ -2384,7 +2674,7 @@ void make_block(BlockMakeData *data)
/* /*
Calculate some stuff Calculate some stuff
*/ */
float surface_humidity = surface_humidity_2d(data->seed, p2d_center); float surface_humidity = surface_humidity_2d(data->seed, p2d_center);
bool is_jungle = surface_humidity > 0.75; bool is_jungle = surface_humidity > 0.75;
// Amount of trees // Amount of trees
@ -2521,7 +2811,7 @@ void make_block(BlockMakeData *data)
/* /*
Add some kind of random stones Add some kind of random stones
*/ */
u32 random_stone_count = gen_area_nodes * u32 random_stone_count = gen_area_nodes *
randomstone_amount_2d(data->seed, p2d_center); randomstone_amount_2d(data->seed, p2d_center);
// Put in random places on part of division // Put in random places on part of division
@ -2555,7 +2845,7 @@ void make_block(BlockMakeData *data)
/* /*
Add larger stones Add larger stones
*/ */
u32 large_stone_count = gen_area_nodes * u32 large_stone_count = gen_area_nodes *
largestone_amount_2d(data->seed, p2d_center); largestone_amount_2d(data->seed, p2d_center);
//u32 large_stone_count = 1; //u32 large_stone_count = 1;
@ -2612,7 +2902,7 @@ void make_block(BlockMakeData *data)
if(mineralrandom.next()%8 == 0) if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(c_mese); vmanip.m_data[vi] = MapNode(c_mese);
} }
} }
} }
/* /*
@ -2742,7 +3032,7 @@ void make_block(BlockMakeData *data)
voxalgo::clearLightAndCollectSources(vmanip, a, bank, ndef, voxalgo::clearLightAndCollectSources(vmanip, a, bank, ndef,
light_sources, unlight_from); light_sources, unlight_from);
bool inexistent_top_provides_sunlight = !block_is_underground; bool inexistent_top_provides_sunlight = !block_is_underground;
voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
vmanip, a, inexistent_top_provides_sunlight, vmanip, a, inexistent_top_provides_sunlight,
@ -2756,6 +3046,8 @@ void make_block(BlockMakeData *data)
} }
} }
#endif ///BIG COMMENT
BlockMakeData::BlockMakeData(): BlockMakeData::BlockMakeData():
no_op(false), no_op(false),
vmanip(NULL), vmanip(NULL),
@ -2768,6 +3060,6 @@ BlockMakeData::~BlockMakeData()
delete vmanip; delete vmanip;
} }
}; // namespace mapgen //}; // namespace mapgen

@ -22,12 +22,121 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h" #include "irrlichttypes_extrabloated.h"
#include "util/container.h" // UniqueQueue #include "util/container.h" // UniqueQueue
#include "gamedef.h"
#include "mapnode.h"
#include "noise.h"
struct BlockMakeData; class BiomeDefManager;
class Biome;
//struct BlockMakeData;
class MapBlock; class MapBlock;
class ManualMapVoxelManipulator; class ManualMapVoxelManipulator;
class INodeDefManager; class INodeDefManager;
struct BlockMakeData {
bool no_op;
ManualMapVoxelManipulator *vmanip;
u64 seed;
v3s16 blockpos_min;
v3s16 blockpos_max;
v3s16 blockpos_requested;
UniqueQueue<v3s16> transforming_liquid;
INodeDefManager *nodedef;
BlockMakeData();
~BlockMakeData();
};
class Mapgen {
public:
BlockMakeData *data;
ManualMapVoxelManipulator *vmanip;
INodeDefManager *ndef;
BiomeDefManager *biomedef;
int ystride;
int zstride;
v3s16 csize;
int seed;
int water_level;
Noise *noise_terrain;
Noise *noise_bgroup;
Noise *noise_heat;
Noise *noise_humidity;
v3s16 node_min;
v3s16 node_max;
float *map_terrain;
float *map_bgroup;
float *map_heat;
float *map_humidity;
bool generating;
int id;
NoiseParams *np_terrain;
NoiseParams *np_bgroup;
NoiseParams *np_heat;
NoiseParams *np_humidity;
//should these be broken off into a "commonly used nodes" class?
MapNode n_air;
MapNode n_water;
MapNode n_lava;
Mapgen(BiomeDefManager *biomedef, int mapgenid=0, u64 seed=0);
Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity);
void initMapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity);
~Mapgen();
void makeChunk(BlockMakeData *data);
void updateLiquid(v3s16 node_min, v3s16 node_max);
void updateLighting(v3s16 node_min, v3s16 node_max);
//Legacy functions for Farmesh (pending removal)
static bool get_have_beach(u64 seed, v2s16 p2d);
static double tree_amount_2d(u64 seed, v2s16 p);
static s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
};
class EmergeManager {
public:
//settings
u64 seed;
int water_level;
NoiseParams *np_terrain;
NoiseParams *np_bgroup;
NoiseParams *np_heat;
NoiseParams *np_humidity;
//biome manager
BiomeDefManager *biomedef;
//mapgen objects here
EmergeManager(IGameDef *gamedef);
~EmergeManager();
void addBlockToQueue();
//mapgen helper methods
Biome *getBiomeAtPoint(v3s16 p);
int getGroundLevelAtPoint(v2s16 p);
bool isBlockUnderground(v3s16 blockpos);
u32 getBlockSeed(v3s16 p);
};
/*
namespace mapgen namespace mapgen
{ {
// Finds precise ground level at any position // Finds precise ground level at any position
@ -41,10 +150,9 @@ namespace mapgen
// Main map generation routine // Main map generation routine
void make_block(BlockMakeData *data); void make_block(BlockMakeData *data);
/*
These are used by FarMesh //These are used by FarMesh
*/
bool get_have_beach(u64 seed, v2s16 p2d); bool get_have_beach(u64 seed, v2s16 p2d);
double tree_amount_2d(u64 seed, v2s16 p); double tree_amount_2d(u64 seed, v2s16 p);
@ -64,6 +172,6 @@ namespace mapgen
}; };
}; // namespace mapgen }; // namespace mapgen
*/
#endif #endif

@ -106,7 +106,7 @@ void NodeBox::deSerialize(std::istream &is)
/* /*
TileDef TileDef
*/ */
void TileDef::serialize(std::ostream &os) const void TileDef::serialize(std::ostream &os) const
{ {
writeU8(os, 0); // version writeU8(os, 0); // version
@ -173,7 +173,7 @@ void ContentFeatures::reset()
has_after_destruct = false; has_after_destruct = false;
/* /*
Actual data Actual data
NOTE: Most of this is always overridden by the default values given NOTE: Most of this is always overridden by the default values given
in builtin.lua in builtin.lua
*/ */
@ -354,7 +354,7 @@ public:
ContentFeatures &f = m_content_features[i]; ContentFeatures &f = m_content_features[i];
f.reset(); // Reset to defaults f.reset(); // Reset to defaults
} }
// Set CONTENT_AIR // Set CONTENT_AIR
{ {
ContentFeatures f; ContentFeatures f;
@ -541,11 +541,11 @@ public:
bool new_style_water = g_settings->getBool("new_style_water"); bool new_style_water = g_settings->getBool("new_style_water");
bool new_style_leaves = g_settings->getBool("new_style_leaves"); bool new_style_leaves = g_settings->getBool("new_style_leaves");
bool opaque_water = g_settings->getBool("opaque_water"); bool opaque_water = g_settings->getBool("opaque_water");
for(u16 i=0; i<=MAX_CONTENT; i++) for(u16 i=0; i<=MAX_CONTENT; i++)
{ {
ContentFeatures *f = &m_content_features[i]; ContentFeatures *f = &m_content_features[i];
// Figure out the actual tiles to use // Figure out the actual tiles to use
TileDef tiledef[6]; TileDef tiledef[6];
for(u32 j=0; j<6; j++) for(u32 j=0; j<6; j++)

@ -21,89 +21,116 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "noise.h" #include "noise.h"
#include <iostream> #include <iostream>
#include "debug.h" #include "debug.h"
#include "util/numeric.h"
#define NOISE_MAGIC_X 1619 #define NOISE_MAGIC_X 1619
#define NOISE_MAGIC_Y 31337 #define NOISE_MAGIC_Y 31337
#define NOISE_MAGIC_Z 52591 #define NOISE_MAGIC_Z 52591
#define NOISE_MAGIC_SEED 1013 #define NOISE_MAGIC_SEED 1013
double cos_lookup[16] = { float cos_lookup[16] = {
1.0,0.9238,0.7071,0.3826,0,-0.3826,-0.7071,-0.9238, 1.0, 0.9238, 0.7071, 0.3826, 0, -0.3826, -0.7071, -0.9238,
1.0,-0.9238,-0.7071,-0.3826,0,0.3826,0.7071,0.9238 1.0, -0.9238, -0.7071, -0.3826, 0, 0.3826, 0.7071, 0.9238
}; };
double dotProduct(double vx, double vy, double wx, double wy){
return vx*wx+vy*wy;
}
double easeCurve(double t){
return t * t * t * (6. * t * t - 15. * t + 10.);
}
double linearInterpolation(double x0, double x1, double t){
return x0+(x1-x0)*t;
}
double biLinearInterpolation(double x0y0, double x1y0, double x0y1, double x1y1, double x, double y){
double tx = easeCurve(x);
double ty = easeCurve(y);
/*double tx = x;
double ty = y;*/
double u = linearInterpolation(x0y0,x1y0,tx);
double v = linearInterpolation(x0y1,x1y1,tx);
return linearInterpolation(u,v,ty);
}
double triLinearInterpolation( ///////////////////////////////////////////////////////////////////////////////
double v000, double v100, double v010, double v110,
double v001, double v101, double v011, double v111,
double x, double y, double z)
{
/*double tx = easeCurve(x);
double ty = easeCurve(y);
double tz = easeCurve(z);*/
double tx = x;
double ty = y;
double tz = z;
return(
v000*(1-tx)*(1-ty)*(1-tz) +
v100*tx*(1-ty)*(1-tz) +
v010*(1-tx)*ty*(1-tz) +
v110*tx*ty*(1-tz) +
v001*(1-tx)*(1-ty)*tz +
v101*tx*(1-ty)*tz +
v011*(1-tx)*ty*tz +
v111*tx*ty*tz
);
}
double noise2d(int x, int y, int seed)
{ //noise poly: p(n) = 60493n^3 + 19990303n + 137612589
float noise2d(int x, int y, int seed) {
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff; + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
n = (n>>13)^n; n = (n >> 13) ^ n;
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff; n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.0 - (double)n/1073741824; return 1.f - (float)n / 0x40000000;
} }
double noise3d(int x, int y, int z, int seed)
{ float noise3d(int x, int y, int z, int seed) {
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff; + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
n = (n>>13)^n; n = (n >> 13) ^ n;
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff; n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.0 - (double)n/1073741824; return 1.f - (float)n / 0x40000000;
} }
float dotProduct(float vx, float vy, float wx, float wy) {
return vx * wx + vy * wy;
}
inline float linearInterpolation(float v0, float v1, float t) {
return v0 + (v1 - v0) * t;
}
float biLinearInterpolation(float v00, float v10,
float v01, float v11,
float x, float y) {
float tx = easeCurve(x);
float ty = easeCurve(y);
float u = linearInterpolation(v00, v10, tx);
float v = linearInterpolation(v01, v11, tx);
return linearInterpolation(u, v, ty);
}
float biLinearInterpolationNoEase(float x0y0, float x1y0,
float x0y1, float x1y1,
float x, float y) {
float u = linearInterpolation(x0y0, x1y0, x);
float v = linearInterpolation(x0y1, x1y1, x);
return linearInterpolation(u, v, y);
}
float triLinearInterpolation(
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111,
float x, float y, float z) {
float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y);
float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y);
return linearInterpolation(u, v, z);
}
#if 0 #if 0
double noise2d_gradient(double x, double y, int seed) float triLinearInterpolation(
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111,
float x, float y, float z)
{
/*float tx = easeCurve(x);
float ty = easeCurve(y);
float tz = easeCurve(z);*/
float tx = x;
float ty = y;
float tz = z;
return(
v000 * (1 - tx) * (1 - ty) * (1 - tz) +
v100 * tx * (1 - ty) * (1 - tz) +
v010 * (1 - tx) * ty * (1 - tz) +
v110 * tx * ty * (1 - tz) +
v001 * (1 - tx) * (1 - ty) * tz +
v101 * tx * (1 - ty) * tz +
v011 * (1 - tx) * ty * tz +
v111 * tx * ty * tz
);
}
#endif
#if 0
float noise2d_gradient(float x, float y, int seed)
{ {
// Calculate the integer coordinates // Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1); int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1); int y0 = (y > 0.0 ? (int)y : (int)y - 1);
// Calculate the remaining part of the coordinates // Calculate the remaining part of the coordinates
double xl = x - (double)x0; float xl = x - (float)x0;
double yl = y - (double)y0; float yl = y - (float)y0;
// Calculate random cosine lookup table indices for the integer corners. // Calculate random cosine lookup table indices for the integer corners.
// They are looked up as unit vector gradients from the lookup table. // They are looked up as unit vector gradients from the lookup table.
int n00 = (int)((noise2d(x0, y0, seed)+1)*8); int n00 = (int)((noise2d(x0, y0, seed)+1)*8);
@ -111,119 +138,126 @@ double noise2d_gradient(double x, double y, int seed)
int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8); int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8);
int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8); int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8);
// Make a dot product for the gradients and the positions, to get the values // Make a dot product for the gradients and the positions, to get the values
double s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl); float s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
double u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl); float u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
double v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl); float v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
double w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl); float w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
// Interpolate between the values // Interpolate between the values
return biLinearInterpolation(s,u,v,w,xl,yl); return biLinearInterpolation(s,u,v,w,xl,yl);
} }
#endif #endif
#if 1
double noise2d_gradient(double x, double y, int seed) float noise2d_gradient(float x, float y, int seed)
{ {
// Calculate the integer coordinates // Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1); int x0 = myfloor(x);
int y0 = (y > 0.0 ? (int)y : (int)y - 1); int y0 = myfloor(y);
// Calculate the remaining part of the coordinates // Calculate the remaining part of the coordinates
double xl = x - (double)x0; float xl = x - (float)x0;
double yl = y - (double)y0; float yl = y - (float)y0;
// Get values for corners of cube // Get values for corners of square
double v00 = noise2d(x0, y0, seed); float v00 = noise2d(x0, y0, seed);
double v10 = noise2d(x0+1, y0, seed); float v10 = noise2d(x0+1, y0, seed);
double v01 = noise2d(x0, y0+1, seed); float v01 = noise2d(x0, y0+1, seed);
double v11 = noise2d(x0+1, y0+1, seed); float v11 = noise2d(x0+1, y0+1, seed);
// Interpolate // Interpolate
return biLinearInterpolation(v00,v10,v01,v11,xl,yl); return biLinearInterpolation(v00,v10,v01,v11,xl,yl);
} }
#endif
double noise3d_gradient(double x, double y, double z, int seed)
float noise3d_gradient(float x, float y, float z, int seed)
{ {
// Calculate the integer coordinates // Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1); int x0 = myfloor(x);
int y0 = (y > 0.0 ? (int)y : (int)y - 1); int y0 = myfloor(y);
int z0 = (z > 0.0 ? (int)z : (int)z - 1); int z0 = myfloor(z);
// Calculate the remaining part of the coordinates // Calculate the remaining part of the coordinates
double xl = x - (double)x0; float xl = x - (float)x0;
double yl = y - (double)y0; float yl = y - (float)y0;
double zl = z - (double)z0; float zl = z - (float)z0;
// Get values for corners of cube // Get values for corners of cube
double v000 = noise3d(x0, y0, z0, seed); float v000 = noise3d(x0, y0, z0, seed);
double v100 = noise3d(x0+1, y0, z0, seed); float v100 = noise3d(x0 + 1, y0, z0, seed);
double v010 = noise3d(x0, y0+1, z0, seed); float v010 = noise3d(x0, y0 + 1, z0, seed);
double v110 = noise3d(x0+1, y0+1, z0, seed); float v110 = noise3d(x0 + 1, y0 + 1, z0, seed);
double v001 = noise3d(x0, y0, z0+1, seed); float v001 = noise3d(x0, y0, z0 + 1, seed);
double v101 = noise3d(x0+1, y0, z0+1, seed); float v101 = noise3d(x0 + 1, y0, z0 + 1, seed);
double v011 = noise3d(x0, y0+1, z0+1, seed); float v011 = noise3d(x0, y0 + 1, z0 + 1, seed);
double v111 = noise3d(x0+1, y0+1, z0+1, seed); float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
// Interpolate // Interpolate
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl); return triLinearInterpolation(v000, v100, v010, v110,
v001, v101, v011, v111,
xl, yl, zl);
} }
double noise2d_perlin(double x, double y, int seed,
int octaves, double persistence) float noise2d_perlin(float x, float y, int seed,
int octaves, float persistence)
{ {
double a = 0; float a = 0;
double f = 1.0; float f = 1.0;
double g = 1.0; float g = 1.0;
for(int i=0; i<octaves; i++) for (int i = 0; i < octaves; i++)
{ {
a += g * noise2d_gradient(x*f, y*f, seed+i); a += g * noise2d_gradient(x * f, y * f, seed + i);
f *= 2.0; f *= 2.0;
g *= persistence; g *= persistence;
} }
return a; return a;
} }
double noise2d_perlin_abs(double x, double y, int seed,
int octaves, double persistence) float noise2d_perlin_abs(float x, float y, int seed,
int octaves, float persistence)
{ {
double a = 0; float a = 0;
double f = 1.0; float f = 1.0;
double g = 1.0; float g = 1.0;
for(int i=0; i<octaves; i++) for (int i = 0; i < octaves; i++)
{ {
a += g * fabs(noise2d_gradient(x*f, y*f, seed+i)); a += g * fabs(noise2d_gradient(x * f, y * f, seed + i));
f *= 2.0; f *= 2.0;
g *= persistence; g *= persistence;
} }
return a; return a;
} }
double noise3d_perlin(double x, double y, double z, int seed,
int octaves, double persistence) float noise3d_perlin(float x, float y, float z, int seed,
int octaves, float persistence)
{ {
double a = 0; float a = 0;
double f = 1.0; float f = 1.0;
double g = 1.0; float g = 1.0;
for(int i=0; i<octaves; i++) for (int i = 0; i < octaves; i++)
{ {
a += g * noise3d_gradient(x*f, y*f, z*f, seed+i); a += g * noise3d_gradient(x * f, y * f, z * f, seed + i);
f *= 2.0; f *= 2.0;
g *= persistence; g *= persistence;
} }
return a; return a;
} }
double noise3d_perlin_abs(double x, double y, double z, int seed,
int octaves, double persistence) float noise3d_perlin_abs(float x, float y, float z, int seed,
int octaves, float persistence)
{ {
double a = 0; float a = 0;
double f = 1.0; float f = 1.0;
double g = 1.0; float g = 1.0;
for(int i=0; i<octaves; i++) for (int i = 0; i < octaves; i++)
{ {
a += g * fabs(noise3d_gradient(x*f, y*f, z*f, seed+i)); a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i));
f *= 2.0; f *= 2.0;
g *= persistence; g *= persistence;
} }
return a; return a;
} }
// -1->0, 0->1, 1->0 // -1->0, 0->1, 1->0
double contour(double v) float contour(float v)
{ {
v = fabs(v); v = fabs(v);
if(v >= 1.0) if(v >= 1.0)
@ -231,195 +265,276 @@ double contour(double v)
return (1.0-v); return (1.0-v);
} }
double noise3d_param(const NoiseParams &param, double x, double y, double z)
{
double s = param.pos_scale;
x /= s;
y /= s;
z /= s;
if(param.type == NOISE_CONSTANT_ONE) ///////////////////////// [ New perlin stuff ] ////////////////////////////
{
return 1.0;
} Noise::Noise(NoiseParams *np, int seed, int sx, int sy) {
else if(param.type == NOISE_PERLIN) int nlx, nly;
{ float ofactor;
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
param.octaves, //maximum possible spread value factor
param.persistence); ofactor = (float)(1 << (np->octaves - 1));
}
else if(param.type == NOISE_PERLIN_ABS) //noise lattice point count
{ //(int)(sz * spread * ofactor) is # of lattice points crossed due to length
return param.noise_scale*noise3d_perlin_abs(x,y,z, param.seed, // + 2 for the two initial endpoints
param.octaves, // + 1 for potentially crossing a boundary due to offset
param.persistence); nlx = (int)(sx * ofactor / np->spread.X) + 3;
} nly = (int)(sy * ofactor / np->spread.Y) + 3;
else if(param.type == NOISE_PERLIN_CONTOUR)
{ this->np = np;
return contour(param.noise_scale*noise3d_perlin(x,y,z, this->seed = seed;
param.seed, param.octaves, this->sx = sx;
param.persistence)); this->sy = sy;
} this->sz = 0;
else if(param.type == NOISE_PERLIN_CONTOUR_FLIP_YZ) this->noisebuf = new float[nlx * nly];
{ this->buf = new float[sx * sy];
return contour(param.noise_scale*noise3d_perlin(x,z,y, this->result = new float[sx * sy];
param.seed, param.octaves,
param.persistence));
}
else assert(0);
} }
Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) {
int nlx, nly, nlz;
float ofactor;
ofactor = (float)(1 << (np->octaves - 1));
nlx = (int)(sx * ofactor / np->spread.X) + 3;
nly = (int)(sy * ofactor / np->spread.Y) + 3;
nlz = (int)(sz * ofactor / np->spread.Z) + 3;
this->np = np;
this->seed = seed;
this->sx = sx;
this->sy = sy;
this->sz = sz;
this->noisebuf = new float[nlx * nly * nlz];
this->buf = new float[sx * sy * sz];
this->result = new float[sx * sy * sz];
}
Noise::~Noise() {
delete[] buf;
delete[] result;
delete[] noisebuf;
}
/* /*
NoiseBuffer * NB: This algorithm is not optimal in terms of space complexity. The entire
*/ * integer lattice of noise points could be done as 2 lines instead, and for 3D,
* 2 lines + 2 planes.
* However, this would require the noise calls to be interposed with the
* interpolation loops, which may trash the icache, leading to lower overall
* performance.
* Another optimization that could save half as many noise calls is to carry over
* values from the previous noise lattice as midpoints in the new lattice for the
* next octave.
*/
void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) {
float v00, v01, v10, v11, u, v, orig_u;
int index, i, j, x0, y0, noisex, noisey;
int nlx, nly;
NoiseBuffer::NoiseBuffer(): x0 = floor(x);
m_data(NULL) y0 = floor(y);
{ u = x - (float)x0;
} v = y - (float)y0;
orig_u = u;
NoiseBuffer::~NoiseBuffer() //calculate noise point lattice
{
clear();
}
void NoiseBuffer::clear() nlx = (int)(u + sx * step_x) + 2;
{ nly = (int)(v + sy * step_y) + 2;
if(m_data) index = 0;
delete[] m_data; for (j = 0; j != nly; j++)
m_data = NULL; for (i = 0; i != nlx; i++)
m_size_x = 0; noisebuf[index++] = noise2d(x0 + i, y0 + j, seed);
m_size_y = 0;
m_size_z = 0;
}
void NoiseBuffer::create(const NoiseParams &param, //calculate interpolations
double first_x, double first_y, double first_z, noisey = 0;
double last_x, double last_y, double last_z, for (j = 0; j != sy; j++) {
double samplelength_x, double samplelength_y, double samplelength_z) v00 = noisebuf[noisey * nlx];
{ v10 = noisebuf[noisey * nlx + 1];
clear(); v01 = noisebuf[(noisey + 1) * nlx];
v11 = noisebuf[(noisey + 1) * nlx + 1];
m_start_x = first_x - samplelength_x;
m_start_y = first_y - samplelength_y;
m_start_z = first_z - samplelength_z;
m_samplelength_x = samplelength_x;
m_samplelength_y = samplelength_y;
m_samplelength_z = samplelength_z;
m_size_x = (last_x - m_start_x)/samplelength_x + 2; u = orig_u;
m_size_y = (last_y - m_start_y)/samplelength_y + 2; noisex = 0;
m_size_z = (last_z - m_start_z)/samplelength_z + 2; for (i = 0; i != sx; i++) {
buf[j * sx + i] = biLinearInterpolation(v00, v10, v01, v11, u, v);
u += step_x;
if (u >= 1.0) {
u -= 1.0;
noisex++;
v00 = v10;
v01 = v11;
v10 = noisebuf[noisey * nlx + noisex + 1];
v11 = noisebuf[(noisey + 1) * nlx + noisex + 1];
}
}
m_data = new double[m_size_x*m_size_y*m_size_z]; v += step_y;
if (v >= 1.0) {
for(int x=0; x<m_size_x; x++) v -= 1.0;
for(int y=0; y<m_size_y; y++) noisey++;
for(int z=0; z<m_size_z; z++) }
{
double xd = (m_start_x + (double)x*m_samplelength_x);
double yd = (m_start_y + (double)y*m_samplelength_y);
double zd = (m_start_z + (double)z*m_samplelength_z);
double a = noise3d_param(param, xd,yd,zd);
intSet(x,y,z, a);
} }
} }
void NoiseBuffer::multiply(const NoiseParams &param)
{
assert(m_data != NULL);
for(int x=0; x<m_size_x; x++) void Noise::gradientMap3D(float x, float y, float z,
for(int y=0; y<m_size_y; y++) float step_x, float step_y, float step_z,
for(int z=0; z<m_size_z; z++) int seed) {
{ float v000, v010, v100, v110;
double xd = (m_start_x + (double)x*m_samplelength_x); float v001, v011, v101, v111;
double yd = (m_start_y + (double)y*m_samplelength_y); float u, v, w, orig_u, orig_w;
double zd = (m_start_z + (double)z*m_samplelength_z); int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
double a = noise3d_param(param, xd,yd,zd); int nlx, nly, nlz;
intMultiply(x,y,z, a);
x0 = floor(x);
y0 = floor(y);
z0 = floor(z);
u = x - (float)x0;
v = y - (float)y0;
w = z - (float)z0;
orig_u = u;
orig_w = w;
//calculate noise point lattice
nlx = (int)(u + sx * step_x) + 2;
nly = (int)(v + sy * step_y) + 2;
nlz = (int)(v + sy * step_z) + 2;
index = 0;
for (k = 0; k != nlz; k++)
for (j = 0; j != nly; j++)
for (i = 0; i != nlx; i++)
noisebuf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);
#define index(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
//calculate interpolations
noisey = 0;
noisez = 0;
for (k = 0; k != sz; k++) {
v000 = noisebuf[index(0, noisey, noisez)];
v100 = noisebuf[index(1, noisey, noisez)];
v010 = noisebuf[index(0, noisey + 1, noisez)];
v110 = noisebuf[index(1, noisey + 1, noisez)];
v001 = noisebuf[index(0, noisey, noisez + 1)];
v101 = noisebuf[index(1, noisey, noisez + 1)];
v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
w = orig_w;
noisey = 0;
for (j = 0; j != sy; j++) {
v000 = noisebuf[index(0, noisey, noisez)];
v100 = noisebuf[index(1, noisey, noisez)];
v010 = noisebuf[index(0, noisey + 1, noisez)];
v110 = noisebuf[index(1, noisey + 1, noisez)];
v001 = noisebuf[index(0, noisey, noisez + 1)];
v101 = noisebuf[index(1, noisey, noisez + 1)];
v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
u = orig_u;
noisex = 0;
for (i = 0; i != sx; i++) {
buf[j * sx + i] = triLinearInterpolation(
v000, v100, v010, v110,
v001, v101, v011, v111,
u, v, w);
u += step_x;
if (u >= 1.0) {
u -= 1.0;
noisex++;
v000 = v100;
v010 = v110;
v100 = noisebuf[index(noisex + 1, noisey, noisez)];
v110 = noisebuf[index(noisex + 1, noisey + 1, noisez)];
v001 = v101;
v011 = v111;
v101 = noisebuf[index(noisex + 1, noisey, noisez + 1)];
v111 = noisebuf[index(noisex + 1, noisey + 1, noisez + 1)];
}
}
v += step_y;
if (v >= 1.0) {
v -= 1.0;
noisey++;
}
}
w += step_z;
if (w >= 1.0) {
w -= 1.0;
noisez++;
}
} }
} }
// Deprecated
void NoiseBuffer::create(int seed, int octaves, double persistence,
bool abs,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z)
{
NoiseParams param;
param.type = abs ? NOISE_PERLIN_ABS : NOISE_PERLIN;
param.seed = seed;
param.octaves = octaves;
param.persistence = persistence;
create(param, first_x, first_y, first_z, float *Noise::perlinMap2D(float x, float y) {
last_x, last_y, last_z, float a = 0.0, f = 1.0, g = 1.0;
samplelength_x, samplelength_y, samplelength_z); int i, j, index, oct;
x /= np->spread.X;
y /= np->spread.Y;
memset(result, 0, sizeof(float) * sx * sy);
for (oct = 0; oct < np->octaves; oct++) {
gradientMap2D(x * f, y * f,
f / np->spread.X, f / np->spread.Y,
seed + np->seed + oct);
index = 0;
for (j = 0; j != sy; j++) {
for (i = 0; i != sx; i++) {
result[index] += g * buf[index];
index++;
}
}
f *= 2.0;
g *= np->persist;
}
return result;
} }
void NoiseBuffer::intSet(int x, int y, int z, double d)
{ float *Noise::perlinMap3D(float x, float y, float z) {
int i = m_size_x*m_size_y*z + m_size_x*y + x; float a = 0.0, f = 1.0, g = 1.0;
assert(i >= 0); int i, j, k, index, oct;
assert(i < m_size_x*m_size_y*m_size_z);
m_data[i] = d; x /= np->spread.X;
y /= np->spread.Y;
z /= np->spread.Z;
memset(result, 0, sizeof(float) * sx * sy * sz);
for (oct = 0; oct < np->octaves; oct++) {
gradientMap3D(x * f, y * f, z * f,
f / np->spread.X, f / np->spread.Y, f / np->spread.Z,
seed + np->seed + oct);
index = 0;
for (k = 0; k != sz; k++) {
for (j = 0; j != sy; j++) {
for (i = 0; i != sx; i++) {
result[index] += g * buf[index];
index++;
}
}
}
f *= 2.0;
g *= np->persist;
}
return result;
} }
void NoiseBuffer::intMultiply(int x, int y, int z, double d)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
m_data[i] = m_data[i] * d;
}
double NoiseBuffer::intGet(int x, int y, int z)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
return m_data[i];
}
double NoiseBuffer::get(double x, double y, double z)
{
x -= m_start_x;
y -= m_start_y;
z -= m_start_z;
x /= m_samplelength_x;
y /= m_samplelength_y;
z /= m_samplelength_z;
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int z0 = (z > 0.0 ? (int)z : (int)z - 1);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
double zl = z - (double)z0;
// Get values for corners of cube
double v000 = intGet(x0, y0, z0);
double v100 = intGet(x0+1, y0, z0);
double v010 = intGet(x0, y0+1, z0);
double v110 = intGet(x0+1, y0+1, z0);
double v001 = intGet(x0, y0, z0+1);
double v101 = intGet(x0+1, y0, z0+1);
double v011 = intGet(x0, y0+1, z0+1);
double v111 = intGet(x0+1, y0+1, z0+1);
// Interpolate
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
}
/*bool NoiseBuffer::contains(double x, double y, double z)
{
x -= m_start_x;
y -= m_start_y;
z -= m_start_z;
x /= m_samplelength_x;
y /= m_samplelength_y;
z /= m_samplelength_z;
if(x <= 0.0 || x >= m_size_x)
}*/

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define NOISE_HEADER #define NOISE_HEADER
#include "debug.h" #include "debug.h"
#include "irr_v3d.h"
class PseudoRandom class PseudoRandom
{ {
@ -59,91 +60,69 @@ private:
int m_next; int m_next;
}; };
double easeCurve(double t); struct NoiseParams {
float offset;
// Return value: -1 ... 1 float scale;
double noise2d(int x, int y, int seed); v3f spread;
double noise3d(int x, int y, int z, int seed);
double noise2d_gradient(double x, double y, int seed);
double noise3d_gradient(double x, double y, double z, int seed);
double noise2d_perlin(double x, double y, int seed,
int octaves, double persistence);
double noise2d_perlin_abs(double x, double y, int seed,
int octaves, double persistence);
double noise3d_perlin(double x, double y, double z, int seed,
int octaves, double persistence);
double noise3d_perlin_abs(double x, double y, double z, int seed,
int octaves, double persistence);
enum NoiseType
{
NOISE_CONSTANT_ONE,
NOISE_PERLIN,
NOISE_PERLIN_ABS,
NOISE_PERLIN_CONTOUR,
NOISE_PERLIN_CONTOUR_FLIP_YZ,
};
struct NoiseParams
{
NoiseType type;
int seed; int seed;
int octaves; int octaves;
double persistence; float persist;
double pos_scale;
double noise_scale; // Useful for contour noises
NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0,
int octaves_=3, double persistence_=0.5,
double pos_scale_=100.0, double noise_scale_=1.0):
type(type_),
seed(seed_),
octaves(octaves_),
persistence(persistence_),
pos_scale(pos_scale_),
noise_scale(noise_scale_)
{
}
}; };
double noise3d_param(const NoiseParams &param, double x, double y, double z);
class NoiseBuffer class Noise {
{
public: public:
NoiseBuffer(); NoiseParams *np;
~NoiseBuffer(); int seed;
int sx;
void clear(); int sy;
void create(const NoiseParams &param, int sz;
double first_x, double first_y, double first_z, float *noisebuf;
double last_x, double last_y, double last_z, float *buf;
double samplelength_x, double samplelength_y, double samplelength_z); float *result;
void multiply(const NoiseParams &param);
// Deprecated
void create(int seed, int octaves, double persistence,
bool abs,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z);
void intSet(int x, int y, int z, double d); Noise(NoiseParams *np, int seed, int sx, int sy);
void intMultiply(int x, int y, int z, double d); Noise(NoiseParams *np, int seed, int sx, int sy, int sz);
double intGet(int x, int y, int z); ~Noise();
double get(double x, double y, double z);
//bool contains(double x, double y, double z);
private: void gradientMap2D(
double *m_data; float x, float y,
double m_start_x, m_start_y, m_start_z; float step_x, float step_y,
double m_samplelength_x, m_samplelength_y, m_samplelength_z; int seed);
int m_size_x, m_size_y, m_size_z; void gradientMap3D(
float x, float y, float z,
float step_x, float step_y, float step_z,
int seed);
float *perlinMap2D(float x, float y);
float *perlinMap3D(float x, float y, float z);
}; };
// Return value: -1 ... 1
float noise2d(int x, int y, int seed);
float noise3d(int x, int y, int z, int seed);
float noise2d_gradient(float x, float y, int seed);
float noise3d_gradient(float x, float y, float z, int seed);
float noise2d_perlin(float x, float y, int seed,
int octaves, float persistence);
float noise2d_perlin_abs(float x, float y, int seed,
int octaves, float persistence);
float noise3d_perlin(float x, float y, float z, int seed,
int octaves, float persistence);
float noise3d_perlin_abs(float x, float y, float z, int seed,
int octaves, float persistence);
inline float easeCurve(float t) {
return t * t * t * (t * (6.f * t - 15.f) + 10.f);
}
#define NoisePerlin2D(np, x, y, s) ((np)->offset + (np)->scale * \
noise2d_perlin((float)(x) * (np)->spread.X, (float)(y) * (np)->spread.Y, \
(s) + (np)->seed, (np)->octaves, (np)->persist))
#endif #endif

@ -3240,8 +3240,8 @@ class LuaPerlinNoise
private: private:
int seed; int seed;
int octaves; int octaves;
double persistence; float persistence;
double scale; float scale;
static const char className[]; static const char className[];
static const luaL_reg methods[]; static const luaL_reg methods[];
@ -3273,8 +3273,8 @@ private:
} }
public: public:
LuaPerlinNoise(int a_seed, int a_octaves, double a_persistence, LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
double a_scale): float a_scale):
seed(a_seed), seed(a_seed),
octaves(a_octaves), octaves(a_octaves),
persistence(a_persistence), persistence(a_persistence),
@ -3292,8 +3292,8 @@ public:
{ {
int seed = luaL_checkint(L, 1); int seed = luaL_checkint(L, 1);
int octaves = luaL_checkint(L, 2); int octaves = luaL_checkint(L, 2);
double persistence = luaL_checknumber(L, 3); float persistence = luaL_checknumber(L, 3);
double scale = luaL_checknumber(L, 4); float scale = luaL_checknumber(L, 4);
LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale); LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o; *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className); luaL_getmetatable(L, className);
@ -3999,8 +3999,8 @@ private:
int seeddiff = luaL_checkint(L, 2); int seeddiff = luaL_checkint(L, 2);
int octaves = luaL_checkint(L, 3); int octaves = luaL_checkint(L, 3);
double persistence = luaL_checknumber(L, 4); float persistence = luaL_checknumber(L, 4);
double scale = luaL_checknumber(L, 5); float scale = luaL_checknumber(L, 5);
LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale); LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = n; *(void **)(lua_newuserdata(L, sizeof(void *))) = n;

File diff suppressed because it is too large Load Diff

@ -739,6 +739,9 @@ private:
bool m_rollback_sink_enabled; bool m_rollback_sink_enabled;
bool m_enable_rollback_recording; // Updated once in a while bool m_enable_rollback_recording; // Updated once in a while
// Emerge manager
EmergeManager *m_emerge;
// Scripting // Scripting
// Envlock and conlock should be locked when using Lua // Envlock and conlock should be locked when using Lua
lua_State *m_lua; lua_State *m_lua;

@ -574,10 +574,7 @@ public:
set(name, "false"); set(name, "false");
} }
void setS32(std::string name, s32 value)
{
set(name, itos(value));
}
void setFloat(std::string name, float value) void setFloat(std::string name, float value)
{ {
@ -598,6 +595,16 @@ public:
set(name, os.str()); set(name, os.str());
} }
void setS16(std::string name, s16 value)
{
set(name, itos(value));
}
void setS32(std::string name, s32 value)
{
set(name, itos(value));
}
void setU64(std::string name, u64 value) void setU64(std::string name, u64 value)
{ {
std::ostringstream os; std::ostringstream os;

@ -120,6 +120,7 @@ inline s16 rangelim(s16 i, s16 max)
} }
#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d))) #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
#define myfloor(x) ((x) > 0.0 ? (int)(x) : (int)(x) - 1)
inline v3s16 arealim(v3s16 p, s16 d) inline v3s16 arealim(v3s16 p, s16 d)
{ {

@ -72,7 +72,7 @@ public:
MaxEdge(p) MaxEdge(p)
{ {
} }
/* /*
Modifying methods Modifying methods
*/ */
@ -106,14 +106,14 @@ public:
if(p.Y > MaxEdge.Y) MaxEdge.Y = p.Y; if(p.Y > MaxEdge.Y) MaxEdge.Y = p.Y;
if(p.Z > MaxEdge.Z) MaxEdge.Z = p.Z; if(p.Z > MaxEdge.Z) MaxEdge.Z = p.Z;
} }
// Pad with d nodes // Pad with d nodes
void pad(v3s16 d) void pad(v3s16 d)
{ {
MinEdge -= d; MinEdge -= d;
MaxEdge += d; MaxEdge += d;
} }
/*void operator+=(v3s16 off) /*void operator+=(v3s16 off)
{ {
MinEdge += off; MinEdge += off;
@ -202,7 +202,7 @@ public:
} }
assert(contains(a)); assert(contains(a));
// Take back area, XY inclusive // Take back area, XY inclusive
{ {
v3s16 min(MinEdge.X, MinEdge.Y, a.MaxEdge.Z+1); v3s16 min(MinEdge.X, MinEdge.Y, a.MaxEdge.Z+1);
@ -258,7 +258,7 @@ public:
} }
} }
/* /*
Translates position from virtual coordinates to array index Translates position from virtual coordinates to array index
*/ */
@ -274,7 +274,7 @@ public:
{ {
return index(p.X, p.Y, p.Z); return index(p.X, p.Y, p.Z);
} }
// Translate index in the X coordinate // Translate index in the X coordinate
void add_x(const v3s16 &extent, u32 &i, s16 a) void add_x(const v3s16 &extent, u32 &i, s16 a)
{ {
@ -343,7 +343,7 @@ class VoxelManipulator /*: public NodeContainer*/
public: public:
VoxelManipulator(); VoxelManipulator();
virtual ~VoxelManipulator(); virtual ~VoxelManipulator();
/* /*
Virtuals from NodeContainer Virtuals from NodeContainer
*/ */
@ -430,7 +430,7 @@ public:
void setNode(v3s16 p, const MapNode &n) void setNode(v3s16 p, const MapNode &n)
{ {
emerge(p); emerge(p);
m_data[m_area.index(p)] = n; m_data[m_area.index(p)] = n;
m_flags[m_area.index(p)] &= ~VOXELFLAG_INEXISTENT; m_flags[m_area.index(p)] &= ~VOXELFLAG_INEXISTENT;
m_flags[m_area.index(p)] &= ~VOXELFLAG_NOT_LOADED; m_flags[m_area.index(p)] &= ~VOXELFLAG_NOT_LOADED;
@ -457,10 +457,10 @@ public:
//dstream<<"operator[] p=("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl; //dstream<<"operator[] p=("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;
if(isValidPosition(p) == false) if(isValidPosition(p) == false)
emerge(VoxelArea(p)); emerge(VoxelArea(p));
return m_data[m_area.index(p)]; return m_data[m_area.index(p)];
}*/ }*/
/* /*
Set stuff if available without an emerge. Set stuff if available without an emerge.
Return false if failed. Return false if failed.
@ -496,7 +496,7 @@ public:
void print(std::ostream &o, INodeDefManager *nodemgr, void print(std::ostream &o, INodeDefManager *nodemgr,
VoxelPrintMode mode=VOXELPRINT_MATERIAL); VoxelPrintMode mode=VOXELPRINT_MATERIAL);
void addArea(VoxelArea area); void addArea(VoxelArea area);
/* /*
@ -505,7 +505,7 @@ public:
*/ */
void copyFrom(MapNode *src, VoxelArea src_area, void copyFrom(MapNode *src, VoxelArea src_area,
v3s16 from_pos, v3s16 to_pos, v3s16 size); v3s16 from_pos, v3s16 to_pos, v3s16 size);
// Copy data // Copy data
void copyTo(MapNode *dst, VoxelArea dst_area, void copyTo(MapNode *dst, VoxelArea dst_area,
v3s16 dst_pos, v3s16 from_pos, v3s16 size); v3s16 dst_pos, v3s16 from_pos, v3s16 size);
@ -523,15 +523,15 @@ public:
void unspreadLight(enum LightBank bank, void unspreadLight(enum LightBank bank,
core::map<v3s16, u8> & from_nodes, core::map<v3s16, u8> & from_nodes,
core::map<v3s16, bool> & light_sources, INodeDefManager *nodemgr); core::map<v3s16, bool> & light_sources, INodeDefManager *nodemgr);
void spreadLight(enum LightBank bank, v3s16 p, INodeDefManager *nodemgr); void spreadLight(enum LightBank bank, v3s16 p, INodeDefManager *nodemgr);
void spreadLight(enum LightBank bank, void spreadLight(enum LightBank bank,
core::map<v3s16, bool> & from_nodes, INodeDefManager *nodemgr); core::map<v3s16, bool> & from_nodes, INodeDefManager *nodemgr);
/* /*
Virtual functions Virtual functions
*/ */
/* /*
Get the contents of the requested area from somewhere. Get the contents of the requested area from somewhere.
Shall touch only nodes that have VOXELFLAG_NOT_LOADED Shall touch only nodes that have VOXELFLAG_NOT_LOADED
@ -565,7 +565,7 @@ public:
MaxEdge is 1 higher than maximum allowed position MaxEdge is 1 higher than maximum allowed position
*/ */
VoxelArea m_area; VoxelArea m_area;
/* /*
NULL if data size is 0 (extent (0,0,0)) NULL if data size is 0 (extent (0,0,0))
Data is stored as [z*h*w + y*h + x] Data is stored as [z*h*w + y*h + x]
@ -576,7 +576,7 @@ public:
Flags of all nodes Flags of all nodes
*/ */
u8 *m_flags; u8 *m_flags;
//TODO: Use these or remove them //TODO: Use these or remove them
//TODO: Would these make any speed improvement? //TODO: Would these make any speed improvement?
//bool m_pressure_route_valid; //bool m_pressure_route_valid;

@ -86,10 +86,10 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
required_a.pad(v3s16(0,1,0)); required_a.pad(v3s16(0,1,0));
// Make sure we have access to it // Make sure we have access to it
v.emerge(a); v.emerge(a);
s16 max_y = a.MaxEdge.Y; s16 max_y = a.MaxEdge.Y;
s16 min_y = a.MinEdge.Y; s16 min_y = a.MinEdge.Y;
for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++) for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++)
for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++) for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
{ {
@ -125,11 +125,11 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
if(incoming_light > old_light) if(incoming_light > old_light)
n.setLight(LIGHTBANK_DAY, incoming_light, ndef); n.setLight(LIGHTBANK_DAY, incoming_light, ndef);
if(diminish_light(incoming_light) != 0) if(diminish_light(incoming_light) != 0)
light_sources.insert(p, true); light_sources.insert(p, true);
} }
// Check validity of sunlight at top of block below if it // Check validity of sunlight at top of block below if it
// hasn't already been proven invalid // hasn't already been proven invalid
if(bottom_sunlight_valid) if(bottom_sunlight_valid)