summaryrefslogtreecommitdiff
path: root/terrain.cpp
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2011-05-14 23:22:05 +0200
committerJon Bergli Heier <snakebite@jvnv.net>2011-05-14 23:22:05 +0200
commite7e6a79f8bf2855b5d1d432613151e48d2d685da (patch)
tree147fbe4a4af633427958d1bf1dcbaaaf0c0a1e00 /terrain.cpp
parent07ec7829e75a71fa7b70b513f0a2c7daeaea11d5 (diff)
Implemented terrain chunk caching.
Diffstat (limited to 'terrain.cpp')
-rw-r--r--terrain.cpp122
1 files changed, 15 insertions, 107 deletions
diff --git a/terrain.cpp b/terrain.cpp
index 1fd75db..f3f573d 100644
--- a/terrain.cpp
+++ b/terrain.cpp
@@ -3,20 +3,10 @@
#include "gl.h"
-#include <noise/noise.h>
-#include "noiseutils/noiseutils.h"
-#include <boost/format.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/filesystem/fstream.hpp>
-
#include <cmath>
#include <queue>
#include <set>
-using namespace noise;
-
-namespace fs = boost::filesystem;
-
using std::min;
using std::max;
@@ -129,7 +119,7 @@ float Terrain::Node::get_height(float px, float py) {
/* Chunk */
-Terrain::Chunk::Chunk(Terrain *terrain, float x, float y, float width, float height) {
+Terrain::Chunk::Chunk(Terrain *terrain, float x, float y, float width, float height) : cache_obj(terrain->tc->get_chunk(x, y, width+1, height+1)) {
this->terrain = terrain;
this->x = x;
this->y = y;
@@ -139,7 +129,7 @@ Terrain::Chunk::Chunk(Terrain *terrain, float x, float y, float width, float hei
this->h_height = height+1;
this->vbo_object = this->node_count = this->vertices = 0;
this->nodes = NULL;
- heights = terrain->get_chunk(x, y, h_width, h_height);
+ heights = cache_obj->heights;
normals = new Vector3[(int)((h_width)*(h_height))];
calc_normals();
@@ -158,7 +148,6 @@ Terrain::Chunk::~Chunk() {
for(unsigned int i = 0; i < node_count; i++)
delete nodes[i];
delete[] nodes;
- delete[] heights;
delete[] normals;
}
@@ -281,11 +270,16 @@ Terrain::Node* Terrain::Chunk::find(float x, float y) {
void Terrain::Chunk::calc_normals() {
float *right, *left, *up, *down;
- right = left = up = down = NULL;
- right = terrain->get_chunk(this->x - chunk_size, this->y, h_width, h_height);
- left = terrain->get_chunk(this->x + chunk_size, this->y, h_width, h_height);
- up = terrain->get_chunk(this->x, this->y + chunk_size, h_width, h_height);
- down = terrain->get_chunk(this->x, this->y - chunk_size, h_width, h_height);
+
+ TerrainCacheObject::p right_ob = terrain->tc->get_chunk(this->x - chunk_size, this->y, h_width, h_height),
+ left_ob = terrain->tc->get_chunk(this->x + chunk_size, this->y, h_width, h_height),
+ up_ob = terrain->tc->get_chunk(this->x, this->y + chunk_size, h_width, h_height),
+ down_ob = terrain->tc->get_chunk(this->x, this->y - chunk_size, h_width, h_height);
+
+ right = right_ob->heights;
+ left = left_ob->heights;
+ up = up_ob->heights;
+ down = down_ob->heights;
for(int x = 0; x < h_width; x++) {
for(int y = 0; y < h_height; y++) {
@@ -343,98 +337,17 @@ void Terrain::Chunk::calc_normals() {
normals[x*h_height + y] = N;
}
}
-
- if(right)
- delete[] right;
- if(left)
- delete[] left;
- if(up)
- delete[] up;
- if(down)
- delete[] down;
}
Terrain::Terrain() {
+ tc = new TerrainCache(0, "map", 120);
}
Terrain::~Terrain() {
for(std::list<Chunk*>::iterator it = chunks.begin(); it != chunks.end(); it++) {
delete *it;
}
-}
-
-float *Terrain::generate_heights(int x, int y, int width, int height) {
- module::Perlin mod;
- mod.SetSeed(0);
-
- utils::NoiseMap heightmap;
- utils::NoiseMapBuilderPlane heightmap_builder;
-
- heightmap_builder.SetSourceModule(mod);
- heightmap_builder.SetDestNoiseMap(heightmap);
-
- heightmap_builder.SetDestSize(width, height);
- heightmap_builder.SetBounds((double)x / 100, (double)(x+width) / 100, (double)y / 100, (double)(y+height) / 100);
- heightmap_builder.Build();
-
- float *heights = new float[width*height];
- for(int i = 0; i < width; i++) {
- for(int j = 0; j < height; j++) {
- heights[i*height + j] = 10*(1+heightmap.GetValue(i, j));
- }
- }
-
- 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) {
- 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 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;
+ delete tc;
}
void Terrain::raise(float x, float z, float radius, float focus, float strength, bool up) {
@@ -498,12 +411,6 @@ void Terrain::raise(float x, float z, float radius, float focus, float strength,
}
}
- // 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(std::set<Chunk*>::iterator it = changed_chunks.begin(); it != changed_chunks.end(); it++) {
(*it)->calc_normals();
@@ -540,6 +447,7 @@ void Terrain::update(float x, float z) {
chunk_indices.erase(ind_it);
}
if((*it)->distance(x, z) > chunk_dist_threshold) {
+ delete *it;
it = chunks.erase(it);
}
}