您的位置:首页 > 其它

Minetest源码分析十三:Mapgen

2017-08-31 22:50 155 查看
Minetest源码分析十三:Mapgen

minetest->margen.h   minetest->mapgen_v6.h

Mapgen:真实生成具体的地图。要生成什么样的地图,具体参数都是是这里设置。通过MapgenParams结构来存储传递参数的。

类的实例初始化:

在类EmergeManager中的initMapgens()中创建实例的,在实例的create函数中传入MapgenParams参数。initMapgens()方法只在server对象的构造函数中调用。程序运行过程中,只在开始时调用一次EmergeManager中的initMapgens,也就是开始给emergeThread创建了这个Mapgen对象。

具体方法如下:

void EmergeManager::initMapgens()
{
if (!params.sparams) {
params.sparams = createMapgenParams(params.mg_name);
params.sparams->readParams(g_settings);
}

// Create the mapgens
for (u32 i = 0; i != emergethread.size(); i++) {
Mapgen *mg = createMapgen(params.mg_name, i, ¶ms);
mapgen.push_back(mg);
}
}


MapgenParams:Mapgen类中使用到的参数,这里是定义的一个结构。地图参数存储在map_meta.txt文件中。

struct MapgenParams {
std::string mg_name;
s16 chunksize;
u64 seed;
s16 water_level;
u32 flags;

NoiseParams np_biome_heat;
NoiseParams np_biome_humidity;

MapgenSpecificParams *sparams;

MapgenParams() :
mg_name(DEFAULT_MAPGEN),
chunksize(5),
seed(0),
water_level(1),
flags(MG_TREES | MG_CAVES | MG_LIGHT),
np_biome_heat(NoiseParams(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.5, 2.0)),
np_biome_humidity(NoiseParams(50, 50, v3f(500.0, 500.0, 500.0), 842, 3, 0.5, 2.0)),
sparams(NULL)
{}

void load(const Settings &settings);
void save(Settings &settings) const;
};


MapgenParams中使用到的相关宏定义

#define MG_TREES         0x01

#define MG_CAVES         0x02

#define MG_DUNGEONS      0x04

#define MG_FLAT          0x08

#define MG_LIGHT         0x10

Mapgen类:

主要方法:

void MapgenV6::makeChunk(BlockMakeData *data)

功能:给Block创建的数据结构设置值、填充值。主要是BlockMakeData结构中MMVManip变量设置值,MMVManip实例变量中主要是设置MapNode
*m_data这个成员变量值。也就是说makeChunk主要是设置一系列MapNode的data值。

参数:BlockMakeData,init Block 时创建的数据结构。

调用:一般与initBlockMake、finishBlockMake一起使用,在这两个方法中间调用。主要是EmergeThread的Thread()线程函数的循环体中使用,不断获取需要生成的block
位置,然后根据位置进行生成block的数据结构,之后就需要使用makeChunk来设置好block数据结构中该有的数据。

initBlockMake(&data, p);

mapgen->makeChunk(&data);

finishBlockMake(&data, modified_blocks);

函数主要流程:

1.Generate general ground level to full area

2.Make caves (this code is relatively horrible)

3.Add mud to the central chunk

4.Flow mud away from steep edges

5.Add dungeons

6.Add top and bottom side of water to transforming_liquid queue

7.Add surface nodes:growGrass();

8.Generate some trees, and add grass, if a jungle

9.Generate the registered decorations

10.Generate the registered ores

11.Calculate lighting

void MapgenV6::makeChunk(BlockMakeData *data)
{
this->generating = true;
this->vm   = data->vmanip;
this->ndef = data->nodedef;

// Hack: use minimum block coords for old code that assumes a single block
v3s16 blockpos = data->blockpos_requested;
v3s16 blockpos_min = data->blockpos_min;
v3s16 blockpos_max = data->blockpos_max;

// Area of central chunk
node_min = blockpos_min * MAP_BLOCKSIZE;
node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);

// Full allocated area
full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);

central_area_size = node_max - node_min + v3s16(1, 1, 1);
assert(central_area_size.X == central_area_size.Z);

int volume_blocks = (blockpos_max.X - blockpos_min.X + 1)
* (blockpos_max.Y - blockpos_min.Y + 1)
* (blockpos_max.Z - blockpos_max.Z + 1);

volume_nodes = volume_blocks *
MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;

// Create a block-specific seed
blockseed = get_blockseed(data->seed, full_node_min);

// Make some noise
calculateNoise();

// Maximum height of the stone surface and obstacles.
// This is used to guide the cave generation
s16 stone_surface_max_y;

// Generate general ground level to full area
stone_surface_max_y = generateGround();

//	// Create initial heightmap to limit caves
//	updateHeightmap(node_min, node_max);

const s16 max_spread_amount = MAP_BLOCKSIZE;
// Limit dirt flow area by 1 because mud is flown into neighbors.
s16 mudflow_minpos = -max_spread_amount + 1;
s16 mudflow_maxpos = central_area_size.X + max_spread_amount - 2;

// Loop this part, it will make stuff look older and newer nicely
const u32 age_loops = 2;
for (u32 i_age = 0; i_age < age_loops; i_age++) { // Aging loop
// Make caves (this code is relatively horrible)
//		if (flags & MG_CAVES)
//			generateCaves(stone_surface_max_y);

// Add mud to the central chunk
addMud();

// Flow mud away from steep edges
if (spflags & MGV6_MUDFLOW)
flowMud(mudflow_minpos, mudflow_maxpos);

}
//
//	// Update heightmap after mudflow
//	updateHeightmap(node_min, node_max);

// Add dungeons
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
DungeonParams dp;

dp.np_rarity  = nparams_dungeon_rarity;
dp.np_density = nparams_dungeon_density;
dp.np_wetness = nparams_dungeon_wetness;
dp.c_water = c_water_source;
if (getBiome(0, v2s16(node_min.X, node_min.Z)) == BT_DESERT) {
dp.c_cobble  = c_sandbrick;
dp.c_moss    = c_sandbrick; // should make this 'cracked sandstone' later
dp.c_stair   = c_stair_sandstone;

dp.diagonal_dirs = true;
dp.mossratio  = 0.0;
dp.holesize   = v3s16(2, 3, 2);
dp.roomsize   = v3s16(2, 5, 2);
dp.notifytype = GENNOTIFY_TEMPLE;
} else {
dp.c_cobble  = c_cobble;
dp.c_moss    = c_mossycobble;
dp.c_stair   = c_stair_cobble;

dp.diagonal_dirs = false;
dp.mossratio  = 3.0;
dp.holesize   = v3s16(1, 2, 1);
dp.roomsize   = v3s16(0, 0, 0);
dp.notifytype = GENNOTIFY_DUNGEON;
}

//		DungeonGen dgen(this, &dp);
//		dgen.generate(blockseed, full_node_min, full_node_max);
}

// Add top and bottom side of water to transforming_liquid queue
updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);

//	// Add surface nodes
//	growGrass();

//	// Generate some trees, and add grass, if a jungle
//	if (flags & MG_TREES)
//		placeTreesAndJungleGrass();

// Generate the registered decorations
m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);

// Generate the registered ores
m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);

// Calculate lighting
if (flags & MG_LIGHT)
calcLighting(node_min, node_max);

this->generating = false;
}


参考资料
http://dev.minetest.net/Mapgen
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息