summaryrefslogtreecommitdiff
path: root/terrain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'terrain.cpp')
-rw-r--r--terrain.cpp129
1 files changed, 90 insertions, 39 deletions
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);