/* Define the vertex array that specifies the terrain (x, y) specifies the pixel dimensions of the heightfield (x * y) vertices (xs, ys) specifies the size of the heightfield region */ void terrain_object::createTerrain(GLuint xp, GLuint zp, GLfloat xs, GLfloat zs, GLfloat freq, GLfloat scale) { xsize = xp; zsize = zp; width = xs; height = zs; /* Scale heights in relation to the terrain size */ height_scale = xs; /* Create array of vertices */ GLuint numvertices = xsize * zsize; vertices = new glm::vec3[numvertices]; normals = new glm::vec3[numvertices]; /* First calculate the noise array which we'll use for our vertex height values */ calculateNoise(freq, scale); /* Debug code to check that noise values are sensible */ // for (int i = 0; i < (xsize*zsize*perlin_octaves); i++) // { // printf("\n noise[%d] = %f", i, noise[i]); // } /* Define starting (x,z) positions and the step changes */ GLfloat xpos = -width / 2.f; GLfloat xpos_step = width / GLfloat(xp); GLfloat zpos_step = height / GLfloat(zp); GLfloat zpos_start = -height / 2.f; /* Define the vertex positions and the initial normals for a flat surface */ for (GLuint x = 0; x < xsize; x++) { GLfloat zpos = zpos_start; for (GLuint z = 0; z < zsize; z++) { GLfloat height = noise[(x*zsize + z) * 4+3]; vertices[x*xsize + z] = glm::vec3(xpos, (height-0.5f)*height_scale, zpos); normals[x*xsize + z] = glm::vec3(0, 1.0f, 0); // Normals for a flat surface zpos += zpos_step; } xpos += xpos_step; } /* Define vertices for triangle strips */ for (GLuint x = 0; x < xsize - 1; x++) { GLuint top = x * zsize; GLuint bottom = top + zsize; for (GLuint z = 0; z < zsize; z++) { elements.push_back(top++); elements.push_back(bottom++); } } calculateNormals(); }
void MapgenV7::makeChunk(BlockMakeData *data) { // Pre-conditions 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->vm = data->vmanip; this->ndef = data->nodedef; //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; node_min = blockpos_min * MAP_BLOCKSIZE; node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1); full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE; full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); blockseed = getBlockSeed2(full_node_min, seed); // Make some noise calculateNoise(); // Generate base terrain, mountains, and ridges with initial heightmaps s16 stone_surface_max_y = generateTerrain(); // Create heightmap updateHeightmap(node_min, node_max); // Create biomemap at heightmap surface bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); // Actually place the biome-specific nodes MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result); if (flags & MG_CAVES) generateCaves(stone_surface_max_y); 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 (stone_type == STONE) { 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; } else if (stone_type == DESERT_STONE) { dp.c_cobble = c_desert_stone; dp.c_moss = c_desert_stone; dp.c_stair = c_desert_stone; 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 if (stone_type == SANDSTONE) { dp.c_cobble = c_sandstonebrick; dp.c_moss = c_sandstonebrick; dp.c_stair = c_sandstonebrick; dp.diagonal_dirs = false; dp.mossratio = 0.0; dp.holesize = v3s16(2, 2, 2); dp.roomsize = v3s16(2, 0, 2); dp.notifytype = GENNOTIFY_DUNGEON; } DungeonGen dgen(this, &dp); dgen.generate(blockseed, full_node_min, full_node_max); } // 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); // Sprinkle some dust on top after everything else was generated dustTopNodes(); //printf("makeChunk: %dms\n", t.stop()); updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); if (flags & MG_LIGHT) calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0), full_node_min, full_node_max); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); this->generating = false; }
void MapgenV6::makeChunk(BlockMakeData *data) { // Pre-conditions 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->vm = data->vmanip; this->ndef = data->nodedef; // Hack: use minimum block coords for old code that assumes a single block 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(); generateExperimental(); // 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, node_min) == BT_DESERT) { dp.c_cobble = c_desert_stone; dp.c_moss = c_desert_stone; dp.c_stair = c_desert_stone; 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(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; }
void MapgenV7::makeChunk(BlockMakeData *data) { 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->vm = data->vmanip; this->ndef = data->nodedef; //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; node_min = blockpos_min * MAP_BLOCKSIZE; node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1); full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE; full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); blockseed = getBlockSeed2(full_node_min, seed); // Make some noise calculateNoise(); // Generate base terrain, mountains, and ridges with initial heightmaps s16 stone_surface_max_y = generateTerrain(); updateHeightmap(node_min, node_max); // Calculate biomes bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, noise_humidity->result, heightmap, biomemap); // Actually place the biome-specific nodes and what not generateBiomes(); if (flags & MG_CAVES) generateCaves(stone_surface_max_y); if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) { DungeonGen dgen(this, NULL); dgen.generate(blockseed, full_node_min, full_node_max); } // 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); // Sprinkle some dust on top after everything else was generated dustTopNodes(); //printf("makeChunk: %dms\n", t.stop()); updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); if (flags & MG_LIGHT) calcLighting(node_min, node_max); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); this->generating = false; }
void MapgenV7::makeChunk(BlockMakeData *data) { 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->vm = data->vmanip; this->ndef = data->nodedef; //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; node_min = blockpos_min * MAP_BLOCKSIZE; node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1); full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE; full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); blockseed = emerge->getBlockSeed(full_node_min); //////use getBlockSeed2()! // Make some noise calculateNoise(); // Generate base terrain, mountains, and ridges with initial heightmaps s16 stone_surface_max_y = generateTerrain(); updateHeightmap(node_min, node_max); // Calculate biomes BiomeNoiseInput binput; binput.mapsize = v2s16(csize.X, csize.Z); binput.heat_map = noise_heat->result; binput.humidity_map = noise_humidity->result; binput.height_map = heightmap; bmgr->calcBiomes(&binput, biomemap); // Actually place the biome-specific nodes and what not generateBiomes(); if (flags & MG_CAVES) generateCaves(stone_surface_max_y); if (flags & MG_DUNGEONS) { DungeonGen dgen(this, NULL); dgen.generate(blockseed, full_node_min, full_node_max); } for (size_t i = 0; i != emerge->decorations.size(); i++) { Decoration *deco = emerge->decorations[i]; deco->placeDeco(this, blockseed + i, node_min, node_max); } for (size_t i = 0; i != emerge->ores.size(); i++) { Ore *ore = emerge->ores[i]; ore->placeOre(this, blockseed + i, node_min, node_max); } // Sprinkle some dust on top after everything else was generated dustTopNodes(); //printf("makeChunk: %dms\n", t.stop()); updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); if (flags & MG_LIGHT) calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); this->generating = false; }
void MapgenV6::makeChunk(BlockMakeData *data) { 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->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(); c_stone = ndef->getId("mapgen_stone"); c_dirt = ndef->getId("mapgen_dirt"); c_dirt_with_grass = ndef->getId("mapgen_dirt_with_grass"); c_dirt_with_snow = ndef->getId("mapgen_dirt_with_snow"); c_sand = ndef->getId("mapgen_sand"); c_water_source = ndef->getId("mapgen_water_source"); c_lava_source = ndef->getId("mapgen_lava_source"); c_gravel = ndef->getId("mapgen_gravel"); c_cobble = ndef->getId("mapgen_cobble"); c_desert_sand = ndef->getId("mapgen_desert_sand"); c_desert_stone = ndef->getId("mapgen_desert_stone"); c_ice = ndef->getId("mapgen_ice"); if (c_desert_sand == CONTENT_IGNORE) c_desert_sand = c_sand; if (c_desert_stone == CONTENT_IGNORE) c_desert_stone = c_stone; // 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(); generateExperimental(); 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(); // Add blobs of dirt and gravel underground addDirtGravelBlobs(); // Flow mud away from steep edges flowMud(mudflow_minpos, mudflow_maxpos); } // Add dungeons if (flags & MG_DUNGEONS) { DungeonGen dgen(ndef, data->seed, water_level); dgen.generate(vm, 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); // Grow grass growGrass(); // Generate some trees, and add grass, if a jungle if (flags & MG_TREES) placeTreesAndJungleGrass(); // Generate the registered decorations for (unsigned int i = 0; i != emerge->decorations.size(); i++) { Decoration *deco = emerge->decorations[i]; deco->placeDeco(this, blockseed + i, node_min, node_max); } // Generate the registered ores for (unsigned int i = 0; i != emerge->ores.size(); i++) { Ore *ore = emerge->ores[i]; ore->placeOre(this, blockseed + i, node_min, node_max); } // Calculate lighting if (!(flags & MG_NOLIGHT)) calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); this->generating = false; }
void MapgenV7::makeChunk(BlockMakeData *data) { 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->vm = data->vmanip; this->ndef = data->nodedef; //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; v3s16 blockpos_full_min = blockpos_min - v3s16(1, 1, 1); v3s16 blockpos_full_max = blockpos_max + v3s16(1, 1, 1); node_min = blockpos_min * MAP_BLOCKSIZE; node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1); full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE; full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); blockseed = emerge->getBlockSeed(full_node_min); //////use getBlockSeed2()! // Make some noise calculateNoise(); // Calculate height map s16 stone_surface_max_y = calcHeightMap(); // Calculate biomes BiomeNoiseInput binput; binput.mapsize = v2s16(csize.X, csize.Z); binput.heat_map = noise_heat->result; binput.humidity_map = noise_humidity->result; binput.height_map = heightmap; bmgr->calcBiomes(&binput, biomemap); c_stone = ndef->getId("mapgen_stone"); c_dirt = ndef->getId("mapgen_dirt"); c_dirt_with_grass = ndef->getId("mapgen_dirt_with_grass"); c_sand = ndef->getId("mapgen_sand"); c_water_source = ndef->getId("mapgen_water_source"); c_lava_source = ndef->getId("mapgen_lava_source"); generateTerrain(); carveRidges(); generateCaves(stone_surface_max_y); addTopNodes(); //v3s16 central_area_size = node_max - node_min + v3s16(1,1,1); if (flags & MG_DUNGEONS) { DungeonGen dgen(ndef, data->seed, water_level); dgen.generate(vm, blockseed, full_node_min, full_node_max); } for (size_t i = 0; i != emerge->ores.size(); i++) { Ore *ore = emerge->ores[i]; ore->placeOre(this, blockseed + i, node_min, node_max); } //printf("makeChunk: %dms\n", t.stop()); updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); this->generating = false; }
void MapgenValleys::makeChunk(BlockMakeData *data) { // Pre-conditions 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->vm = data->vmanip; this->ndef = data->nodedef; //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; node_min = blockpos_min * MAP_BLOCKSIZE; node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1); full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE; full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); blockseed = getBlockSeed2(full_node_min, seed); // Generate noise maps and base terrain height. calculateNoise(); // Generate biome noises. Note this must be executed strictly before // generateTerrain, because generateTerrain depends on intermediate // biome-related noises. m_bgen->calcBiomeNoise(node_min); // Generate base terrain with initial heightmaps s16 stone_surface_max_y = generateTerrain(); // Build biomemap m_bgen->getBiomes(heightmap); // Place biome-specific nodes MgStoneType stone_type = generateBiomes(); // Cave creation. if (flags & MG_CAVES) generateCaves(stone_surface_max_y, large_cave_depth); // Dungeon creation if ((flags & MG_DUNGEONS) && node_max.Y < 50) generateDungeons(stone_surface_max_y, stone_type); // Generate the registered decorations if (flags & MG_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); // Sprinkle some dust on top after everything else was generated dustTopNodes(); //TimeTaker tll("liquid_lighting"); updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); if (flags & MG_LIGHT) calcLighting( node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0), full_node_min, full_node_max); //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f); //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f); this->generating = false; }
/* Define the vertex array that specifies the terrain (x, y) specifies the pixel dimensions of the heightfield (x * y) vertices (xs, ys) specifies the size of the heightfield region in world coords */ void Terrain::createTerrain(GLuint xp, GLuint zp, GLfloat xs, GLfloat zs, GLfloat sl) { xsize = xp; zsize = zp; width = xs; height = zs; /* Scale heights in relation to the terrain size */ height_scale = xs; /* Create array of vertices */ GLuint numvertices = xsize * zsize; vertices = new glm::vec3[numvertices]; normals = new glm::vec3[numvertices]; colours = new glm::vec3[numvertices]; /* First calculate the noise array which we'll use for our vertex height values */ calculateNoise(); /* Define starting (x,z) positions and the step changes */ GLfloat xpos = -width / 2.f; GLfloat xpos_step = width / GLfloat(xp); GLfloat zpos_step = height / GLfloat(zp); GLfloat zpos_start = -height / 2.f; /* Define the vertex positions and the initial normals for a flat surface */ for (GLuint x = 0; x < xsize; x++) { GLfloat zpos = zpos_start; for (GLuint z = 0; z < zsize; z++) { GLfloat height = noise[(x*zsize + z) * perlin_octaves + perlin_octaves - 1]; vertices[x*xsize + z] = glm::vec3(xpos, (height - 0.5f)*height_scale, zpos); // Normals for a flat surface if (height > 0.48) { colours[x * xsize + z] = glm::vec3( (1.0 * (1.0 - height) * 2.0), (1.0 * (1.0 - height) * 2.0), (1.0 * (1.0 - height) * 2.0) ); normals[x*xsize + z] = glm::vec3(0, 1.0f, 0); } else if (height < 0.2) { colours[x * xsize + z] = glm::vec3( (1.0 * (1.0 * height) / 1.0), (1.0 * (1.0 - height) / 1.0), 0 ); normals[x * xsize + z] = glm::vec3(1.0f, 0, 0); } else { colours[x * xsize + z] = glm::vec3( (1.0 * (1.0 * height) / 1.0), (1.0 * (1.0 - height) / 1.0), 0 ); normals[x*xsize + z] = glm::vec3(0, 1.0f, 0); } zpos += zpos_step; } xpos += xpos_step; } /* Define vertices for triangle strips */ for (GLuint x = 0; x < xsize - 1; x++) { GLuint top = x * zsize; GLuint bottom = top + zsize; for (GLuint z = 0; z < zsize; z++) { elements.push_back(top++); elements.push_back(bottom++); } } // Stretch the height values to a defined height range stretchToRange(-(xs / 8.f), (xs / 8.f)); // Define a sea level by flattening low regions defineSea(sl); //defineTexture(); // Calculate the normals by averaging cross products for all triangles calculateNormals(); }