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

View File

@ -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
View 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
View 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

View File

@ -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");

View File

@ -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)
{ {

View File

@ -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

View File

@ -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

View File

@ -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);
@ -3102,6 +3118,9 @@ void ServerMap::loadMapMeta()
} }
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;
} }

View File

@ -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;

View File

@ -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,
@ -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

View File

@ -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
@ -42,9 +151,8 @@ 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

View File

@ -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){ //noise poly: p(n) = 60493n^3 + 19990303n + 137612589
double tx = easeCurve(x); float noise2d(int x, int y, int seed) {
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)
{
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; u = orig_u;
m_start_y = first_y - samplelength_y; noisex = 0;
m_start_z = first_z - samplelength_z; for (i = 0; i != sx; i++) {
m_samplelength_x = samplelength_x; buf[j * sx + i] = biLinearInterpolation(v00, v10, v01, v11, u, v);
m_samplelength_y = samplelength_y; u += step_x;
m_samplelength_z = samplelength_z; 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_size_x = (last_x - m_start_x)/samplelength_x + 2; v += step_y;
m_size_y = (last_y - m_start_y)/samplelength_y + 2; if (v >= 1.0) {
m_size_z = (last_z - m_start_z)/samplelength_z + 2; v -= 1.0;
noisey++;
m_data = new double[m_size_x*m_size_y*m_size_z]; }
for(int x=0; x<m_size_x; x++)
for(int y=0; y<m_size_y; y++)
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)
}*/

View File

@ -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;
int sy;
int sz;
float *noisebuf;
float *buf;
float *result;
void clear(); Noise(NoiseParams *np, int seed, int sx, int sy);
void create(const NoiseParams &param, Noise(NoiseParams *np, int seed, int sx, int sy, int sz);
double first_x, double first_y, double first_z, ~Noise();
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z);
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); void gradientMap2D(
void intMultiply(int x, int y, int z, double d); float x, float y,
double intGet(int x, int y, int z); float step_x, float step_y,
double get(double x, double y, double z); int seed);
//bool contains(double x, double y, double z); void gradientMap3D(
float x, float y, float z,
private: float step_x, float step_y, float step_z,
double *m_data; int seed);
double m_start_x, m_start_y, m_start_z; float *perlinMap2D(float x, float y);
double m_samplelength_x, m_samplelength_y, m_samplelength_z; float *perlinMap3D(float x, float y, float z);
int m_size_x, m_size_y, m_size_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

View File

@ -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;

View File

@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "itemdef.h" #include "itemdef.h"
#include "craftdef.h" #include "craftdef.h"
#include "mapgen.h" #include "mapgen.h"
#include "biome.h"
#include "content_mapnode.h" #include "content_mapnode.h"
#include "content_nodemeta.h" #include "content_nodemeta.h"
#include "content_abm.h" #include "content_abm.h"
@ -169,6 +170,10 @@ void * EmergeThread::Thread()
v3s16 last_tried_pos(-32768,-32768,-32768); // For error output v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
EmergeManager *emerge = m_server->m_emerge;
Mapgen *mapgen = new Mapgen( m_server->m_emerge->biomedef,/*mapgenid*/ 0, map.getSeed()); ////////fix this...!
/* /*
Get block info from queue, emerge them and send them Get block info from queue, emerge them and send them
to clients. to clients.
@ -233,7 +238,7 @@ void * EmergeThread::Thread()
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") " <<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
<<"only_from_disk="<<only_from_disk<<std::endl; <<"only_from_disk="<<only_from_disk<<std::endl;
ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
MapBlock *block = NULL; MapBlock *block = NULL;
bool got_block = true; bool got_block = true;
@ -245,7 +250,7 @@ void * EmergeThread::Thread()
*/ */
bool started_generate = false; bool started_generate = false;
mapgen::BlockMakeData data; BlockMakeData data;
{ {
JMutexAutoLock envlock(m_server->m_env_mutex); JMutexAutoLock envlock(m_server->m_env_mutex);
@ -287,7 +292,8 @@ void * EmergeThread::Thread()
SPT_AVG); SPT_AVG);
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
@ -332,7 +338,7 @@ void * EmergeThread::Thread()
{ {
TimeTaker timer("on_generated"); TimeTaker timer("on_generated");
scriptapi_environment_on_generated(m_server->m_lua, scriptapi_environment_on_generated(m_server->m_lua,
minp, maxp, mapgen::get_blockseed(data.seed, minp)); minp, maxp, emerge->getBlockSeed(minp));
/*int t = timer.stop(true); /*int t = timer.stop(true);
dstream<<"on_generated took "<<t<<"ms"<<std::endl;*/ dstream<<"on_generated took "<<t<<"ms"<<std::endl;*/
} }
@ -937,6 +943,7 @@ Server::Server(
m_rollback(NULL), m_rollback(NULL),
m_rollback_sink_enabled(true), m_rollback_sink_enabled(true),
m_enable_rollback_recording(false), m_enable_rollback_recording(false),
m_emerge(NULL),
m_lua(NULL), m_lua(NULL),
m_itemdef(createItemDefManager()), m_itemdef(createItemDefManager()),
m_nodedef(createNodeDefManager()), m_nodedef(createNodeDefManager()),
@ -976,6 +983,9 @@ Server::Server(
infostream<<"- config: "<<m_path_config<<std::endl; infostream<<"- config: "<<m_path_config<<std::endl;
infostream<<"- game: "<<m_gamespec.path<<std::endl; infostream<<"- game: "<<m_gamespec.path<<std::endl;
// Create emerge manager
m_emerge = new EmergeManager(this);
// Create rollback manager // Create rollback manager
std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt"; std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
m_rollback = createRollbackManager(rollback_path, this); m_rollback = createRollbackManager(rollback_path, this);
@ -1082,9 +1092,12 @@ Server::Server(
// Apply item aliases in the node definition manager // Apply item aliases in the node definition manager
m_nodedef->updateAliases(m_itemdef); m_nodedef->updateAliases(m_itemdef);
// Add default biomes after nodedef had its aliases added
m_emerge->biomedef->addDefaultBiomes();
// Initialize Environment // Initialize Environment
m_env = new ServerEnvironment(new ServerMap(path_world, this), m_lua, m_env = new ServerEnvironment(new ServerMap(path_world, this, m_emerge), m_lua,
this, this); this, this);
// Give environment reference to scripting api // Give environment reference to scripting api
@ -1184,6 +1197,7 @@ Server::~Server()
i = m_clients.getIterator(); i = m_clients.getIterator();
i.atEnd() == false; i++) i.atEnd() == false; i++)
{ {
// Delete client // Delete client
delete i.getNode()->getValue(); delete i.getNode()->getValue();
} }
@ -1192,6 +1206,7 @@ Server::~Server()
// Delete things in the reverse order of creation // Delete things in the reverse order of creation
delete m_env; delete m_env;
delete m_rollback; delete m_rollback;
delete m_emerge;
delete m_event; delete m_event;
delete m_itemdef; delete m_itemdef;
delete m_nodedef; delete m_nodedef;
@ -4832,7 +4847,7 @@ v3f findSpawnPos(ServerMap &map)
#endif #endif
#if 1 #if 1
s16 water_level = g_settings->getS16("water_level"); s16 water_level = map.m_emerge->water_level; //g_settings->getS16("default_water_level");
// Try to find a good place a few times // Try to find a good place a few times
for(s32 i=0; i<1000; i++) for(s32 i=0; i<1000; i++)

View File

@ -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;

View File

@ -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;

View File

@ -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)
{ {