#include "terrain_generator.h" #include #include "noiseutils/noiseutils.h" #include #include using namespace noise; TerrainGenerator::TerrainGenerator(int seed, fs::path root) : TerrainLoader(root) { this->seed = seed; } float *TerrainGenerator::generate_heights(int64_t x, int64_t y, unsigned int width, unsigned int height) { const double scale_factor = 0.004; module::Perlin mod; mod.SetSeed(seed); utils::NoiseMap heightmap; utils::NoiseMapBuilderPlane heightmap_builder; heightmap_builder.SetSourceModule(mod); heightmap_builder.SetDestNoiseMap(heightmap); heightmap_builder.SetDestSize(width, height); // subtract by one due to chunk overlapping heightmap_builder.SetBounds((double)(x-1) * scale_factor, (double)(x-1+width) * scale_factor, (double)(y-1) * scale_factor, (double)(y-1+height) * scale_factor); heightmap_builder.Build(); float *heights = new float[width*height]; for(unsigned int i = 0; i < width; i++) { for(unsigned int j = 0; j < height; j++) { heights[i*height + j] = 50*(1+heightmap.GetValue(i, j)); } } save_chunk(heights, x, y, width, height); return heights; } float *TerrainGenerator::get_chunk(int64_t x, int64_t y, unsigned int width, unsigned int height) { float *h; if(has_chunk(x, y)) h = load_chunk(x, y, width, height); else h = generate_heights(x, y, width, height); return h; } // TODO: merge this into terrain height generation above somehow std::list TerrainGenerator::generate_objects(int64_t x, int64_t y, unsigned int width, unsigned int height) { std::list trees; const double scale_factor = 0.004; // "base" needs to match the terrain heightmap noise module::Perlin base; base.SetSeed(seed); module::Const low; low.SetConstValue(0); module::Select final; final.SetSourceModule(0, low); final.SetSourceModule(1, base); final.SetControlModule(base); const float lower = -.24; const float upper = .19; final.SetBounds(lower, upper); utils::NoiseMap heightmap; utils::NoiseMapBuilderPlane heightmap_builder; heightmap_builder.SetSourceModule(final); heightmap_builder.SetDestNoiseMap(heightmap); heightmap_builder.SetDestSize(width, height); heightmap_builder.SetBounds((double)x * scale_factor, (double)(x+33) * scale_factor, (double)y * scale_factor, (double)(y+33) * scale_factor); heightmap_builder.Build(); boost::mt19937 rng(seed); boost::normal_distribution nd(-2, .7); boost::variate_generator > r(rng, nd); for(unsigned int i = 0; i < 32; i++) { for(unsigned int j = 0; j < 32; j++) { if(heightmap.GetValue(i, j) > 0 && r() > 0) trees.push_back(Vector3(x + i, 0, y + j)); } } return trees; } std::list TerrainGenerator::get_objects(int64_t x, int64_t y, unsigned int width, unsigned int height) { if(has_objects(x, y)) return load_objects(x, y); else return generate_objects(x, y, width, height); }