diff options
-rw-r--r-- | SConstruct | 2 | ||||
-rw-r--r-- | terrain.cpp | 129 | ||||
-rw-r--r-- | terrain.h | 3 |
3 files changed, 94 insertions, 40 deletions
@@ -8,7 +8,7 @@ AddOption('--release', action = 'store_true') AddOption('--profiling', action = 'store_true') env.Append(CPPPATH = ['.']) -env.Append(LIBS = ['GL', 'GLU', 'noise']) +env.Append(LIBS = ['GL', 'GLU', 'noise', 'boost_filesystem']) env.ParseConfig('sdl-config --cflags --libs') env.ParseConfig('pkg-config --cflags --libs SDL_image') env.ParseConfig('pkg-config --cflags --libs ftgl') diff --git a/terrain.cpp b/terrain.cpp index e0f635a..359cb84 100644 --- a/terrain.cpp +++ b/terrain.cpp @@ -6,14 +6,17 @@ #include <noise/noise.h> #include "noiseutils/noiseutils.h" #include <boost/format.hpp> +#include <boost/filesystem.hpp> +#include <boost/filesystem/fstream.hpp> -#include <iostream> #include <cmath> #include <queue> #include <set> using namespace noise; +namespace fs = boost::filesystem; + using std::min; using std::max; @@ -338,8 +341,6 @@ void Terrain::Chunk::calc_normals() { delete[] down; } -/* Terrain */ - Terrain::Terrain() { } @@ -371,20 +372,62 @@ float *Terrain::generate_heights(int x, int y, int width, int height) { } chunk_indices.insert(std::pair<int, int>(x, y)); + save_chunk(heights, x, y, width, height); return heights; } float *Terrain::get_chunk(int x, int y, int width, int height) { - return generate_heights(x, y, width, height); + if(has_chunk(x, y)) + return load_chunk(x, y, width, height); + else + return generate_heights(x, y, width, height); } bool Terrain::has_chunk(int x, int y) { - return chunk_indices.find(std::pair<int, int>(x, y)) != chunk_indices.end(); + return fs::exists((boost::format("map/%d.%d.chunk") % x % y).str()); + //return chunk_indices.find(std::pair<int, int>(x, y)) != chunk_indices.end(); +} + +void Terrain::save_chunk(float *chunk, int x, int y, int width, int height) { + fs::path p = (boost::format("map/%d.%d.chunk") % x % y).str(); + fs::ofstream os(p); + + os << width << std::endl; + os << height << std::endl; + + for(int x = 0; x < width; x++) + for(int y = 0; y < height; y++) + os << chunk[x*height + y] << std::endl; + os.close(); +} + +// NOTE: assumes width <= chunk_size+, likewise for height +float *Terrain::load_chunk(int x, int y, int width, int height) { + fs::path p = (boost::format("map/%d.%d.chunk") % x % y).str(); + fs::ifstream is(p); + + int w, h; + is >> w; + is >> h; + + float *chunk = new float[width*height]; + for(int x = 0; x < w; x++) + for(int y = 0; y < h; y++) { + float v; + is >> v; + if(x < width && y < height) + chunk[x*height + y] = v; + } + is.close(); + + return chunk; } void Terrain::raise(float x, float z, float radius, float focus, float strength, bool up) { - // TODO: check nodes + // TODO: fix setting heights on unloaded chunks + + std::set<Chunk*> changed_chunks; /* adjust heights */ for(int i = x-radius; i < x+radius; i++) { @@ -397,66 +440,69 @@ void Terrain::raise(float x, float z, float radius, float focus, float strength, */ v /= radius * (focus/2); - Node *node = find(i, j); - int index = (i-node->chunk->x)*(node->chunk->h_height) + j-node->chunk->y; + Chunk *chunk = find_chunk(i, j); + changed_chunks.insert(chunk); + int index = (i-chunk->x)*(chunk->h_height) + j-chunk->y; if(up) - node->chunk->heights[index] += v; + chunk->heights[index] += v; else - node->chunk->heights[index] -= v; + chunk->heights[index] -= v; /* fill the "outer border" */ if(i % chunk_size == 0) { - node = find(i-chunk_size, j); - if(node) { - index = (chunk_size)*(node->chunk->h_height) + j-node->chunk->y; + Chunk *chunk = find_chunk(i-chunk_size, j); + if(chunk) { + changed_chunks.insert(chunk); + index = (chunk_size)*(chunk->h_height) + j-chunk->y; if(up) - node->chunk->heights[index] += v; + chunk->heights[index] += v; else - node->chunk->heights[index] -= v; + chunk->heights[index] -= v; } } if(j % chunk_size == 0) { - node = find(i, j-chunk_size); - if(node) { - index = (i-node->chunk->x)*(node->chunk->h_height) + chunk_size; + Chunk *chunk = find_chunk(i, j-chunk_size); + if(chunk) { + changed_chunks.insert(chunk); + index = (i-chunk->x)*(chunk->h_height) + chunk_size; if(up) - node->chunk->heights[index] += v; + chunk->heights[index] += v; else - node->chunk->heights[index] -= v; + chunk->heights[index] -= v; } } if(i % chunk_size == 0 && j % chunk_size == 0) { - node = find(i-chunk_size, j-chunk_size); - if(node) { - index = (chunk_size)*(node->chunk->h_height) + chunk_size; + Chunk *chunk = find_chunk(i-chunk_size, j-chunk_size); + if(chunk) { + changed_chunks.insert(chunk); + index = (chunk_size)*(chunk->h_height) + chunk_size; if(up) - node->chunk->heights[index] += v; + chunk->heights[index] += v; else - node->chunk->heights[index] -= v; + chunk->heights[index] -= v; } } } } + // save chunks + for(std::set<Chunk*>::iterator it = changed_chunks.begin(); it != changed_chunks.end(); it++) { + Chunk *chunk = *it; + save_chunk(chunk->heights, chunk->x, chunk->y, chunk->h_width, chunk->h_height); + } + /* recalculate normals */ - for(int i = x-radius-1; i < x+radius; i+=chunk_size) { - for(int j = z-radius-1; j < z+radius; j+=chunk_size) { - find(i, j)->chunk->calc_normals(); - } + for(std::set<Chunk*>::iterator it = changed_chunks.begin(); it != changed_chunks.end(); it++) { + (*it)->calc_normals(); } /* refill nodes and remake VBOs */ - for(int nx = x-radius-1; nx < x+radius+chunk_size; nx+=chunk_size) { - for(int nz = z-radius-1; nz < z+radius+chunk_size; nz+=chunk_size) { - Node *node = find(nx, nz); - if(!node) { - continue; - } - for(unsigned int i = 0; i < node->chunk->node_count; i++) { - node->chunk->nodes[i]->fill(); - } - node->chunk->make_vbo(); + for(std::set<Chunk*>::iterator it = changed_chunks.begin(); it != changed_chunks.end(); it++) { + Chunk *chunk = *it; + for(unsigned int i = 0; i < chunk->node_count; i++) { + chunk->nodes[i]->fill(); } + chunk->make_vbo(); } } @@ -489,6 +535,11 @@ void Terrain::update(float x, float z) { } } +Terrain::Chunk *Terrain::find_chunk(float x, float y) { + Node *node = find(x, y); + return node ? node->chunk : NULL; +} + Terrain::Node *Terrain::find(float x, float y) { for(std::list<Chunk*>::iterator it = chunks.begin(); it != chunks.end(); it++) { Node *node = (*it)->find(x, y); @@ -60,10 +60,13 @@ class Terrain { float *generate_heights(int x, int y, int width, int height); float *get_chunk(int x, int y, int width, int height); bool has_chunk(int x, int y); + void save_chunk(float *chunk, int x, int y, int width, int height); + float *load_chunk(int x, int y, int width, int height); void raise(float x, float z, float radius, float focus, float strength, bool up = true); void update(float x, float z); + Chunk *find_chunk(float x, float y); Node *find(float x, float y); }; |