summaryrefslogtreecommitdiff
path: root/terrain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'terrain.cpp')
-rw-r--r--terrain.cpp107
1 files changed, 67 insertions, 40 deletions
diff --git a/terrain.cpp b/terrain.cpp
index f3f573d..4035a89 100644
--- a/terrain.cpp
+++ b/terrain.cpp
@@ -47,19 +47,19 @@ float Terrain::Node::distance(float px, float pz) {
void Terrain::Node::fill() {
vertex_array[0] = x;
- vertex_array[1] = chunk->heights[(int)floorf((x)*(chunk->h_height)+y)];
+ vertex_array[1] = chunk->heights[(int)floorf((x + 1)*(chunk->h_height) + (y + 1))];
vertex_array[2] = y;
vertex_array[3] = x;
- vertex_array[4] = chunk->heights[(int)floorf((x)*(chunk->h_height) + (y + 1))];
+ vertex_array[4] = chunk->heights[(int)floorf((x + 1)*(chunk->h_height) + (y + 2))];
vertex_array[5] = y + 1;
vertex_array[6] = x + 1;
- vertex_array[7] = chunk->heights[(int)floorf((x + 1)*(chunk->h_height) + (y + 1))];
+ vertex_array[7] = chunk->heights[(int)floorf((x + 2)*(chunk->h_height) + (y + 2))];
vertex_array[8] = y + 1;
vertex_array[9] = x + 1;
- vertex_array[10] = chunk->heights[(int)floorf((x + 1)*(chunk->h_height) + y)];
+ vertex_array[10] = chunk->heights[(int)floorf((x + 2)*(chunk->h_height) + (y + 1))];
vertex_array[11] = y;
}
@@ -92,11 +92,12 @@ void Terrain::Node::draw_grid() {
void Terrain::Node::draw_normal() {
glNormal3f(0, 1, 0);
glColor3f(1, 0, 0);
- int i = (int)(x*(chunk->h_height) + y);
+ int i = (int)(x*(chunk->n_height) + y);
+ int i2 = (int)((x + 1) * (chunk->h_height) + (y + 1));
glBegin(GL_LINES);
Vector3 N = chunk->normals[i];
- glVertex3f(chunk->x + x, chunk->heights[i], chunk->y + y);
- glVertex3f(chunk->x + x + N.x, chunk->heights[i] + N.y, chunk->y + y + N.z);
+ glVertex3f(chunk->x + x, chunk->heights[i2], chunk->y + y);
+ glVertex3f(chunk->x + x + N.x, chunk->heights[i2] + N.y, chunk->y + y + N.z);
glEnd();
}
@@ -119,18 +120,21 @@ float Terrain::Node::get_height(float px, float py) {
/* Chunk */
-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)) {
+Terrain::Chunk::Chunk(Terrain *terrain, float x, float y) : cache_obj(terrain->tc->get_chunk(x, y, Terrain::chunk_size_total, Terrain::chunk_size_total)) {
this->terrain = terrain;
this->x = x;
this->y = y;
- this->width = width;
- this->height = height;
- this->h_width = width+1;
- this->h_height = height+1;
+ this->width = Terrain::chunk_size;
+ this->height = Terrain::chunk_size;
+ this->h_width = Terrain::chunk_size_total;
+ this->h_height = Terrain::chunk_size_total;
+ this->n_width = width+1;
+ this->n_height = height+1;
this->vbo_object = this->node_count = this->vertices = 0;
this->nodes = NULL;
+ this->need_normals = true;
heights = cache_obj->heights;
- normals = new Vector3[(int)((h_width)*(h_height))];
+ normals = new Vector3[(int)((n_width)*(n_height))];
calc_normals();
@@ -141,7 +145,9 @@ Terrain::Chunk::Chunk(Terrain *terrain, float x, float y, float width, float hei
nodes[j*(int)height + i] = new Node(this, j, i);
}
}
- make_vbo();
+
+ if(!need_normals)
+ make_vbo();
}
Terrain::Chunk::~Chunk() {
@@ -236,10 +242,10 @@ void Terrain::Chunk::make_vbo() {
float *n = buffer + vertices_size + normal_chunk_size*index;
- Vector3 bl = normals[(int)((node->x+1)*(h_height) + node->y)];
- Vector3 br = normals[(int)((node->x)*(h_height) + node->y)];
- Vector3 tr = normals[(int)((node->x)*(h_height) + node->y+1)];
- Vector3 tl = normals[(int)((node->x+1)*(h_height) + node->y+1)];
+ Vector3 bl = normals[(int)((node->x+1)*(n_height) + node->y)];
+ Vector3 br = normals[(int)((node->x)*(n_height) + node->y)];
+ Vector3 tr = normals[(int)((node->x)*(n_height) + node->y+1)];
+ Vector3 tl = normals[(int)((node->x+1)*(n_height) + node->y+1)];
n[0] = n[9] = br.x;
n[1] = n[10] = br.y;
@@ -271,7 +277,7 @@ Terrain::Node* Terrain::Chunk::find(float x, float y) {
void Terrain::Chunk::calc_normals() {
float *right, *left, *up, *down;
- TerrainCacheObject::p right_ob = terrain->tc->get_chunk(this->x - chunk_size, this->y, 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);
@@ -279,68 +285,75 @@ void Terrain::Chunk::calc_normals() {
right = right_ob->heights;
left = left_ob->heights;
up = up_ob->heights;
- down = down_ob->heights;
+ down = down_ob->heights;*/
+
+ if(!right || !left || !up || !down) {
+ need_normals = true;
+ return;
+ }
- for(int x = 0; x < h_width; x++) {
- for(int y = 0; y < h_height; y++) {
+ for(int x = 1; x < h_width-1; x++) {
+ for(int y = 1; y < h_height-1; y++) {
Vector3 p(x, heights[x*h_height + y], y);
Vector3 N, U, V;
float h;
// right
- if(x == 0)
+ /*if(x == 0)
h = right[(chunk_size-1)*(int)(h_height) + y];
- else
+ else*/
h = heights[(x-1)*h_height + y];
U = Vector3(x-1, h, y) - p;
// down
- if(y == 0)
+ /*if(y == 0)
h = down[x*(int)(h_height) + chunk_size - 1];
- else
+ else*/
h = heights[x*h_height + y - 1];
V = Vector3(x, h, y-1) - p;
N += V.cross(U);
// up
- if(y == h_height-1)
+ /*if(y == h_height-1)
h = up[x*(int)(h_height) + 1]; // y == 1
- else
+ else*/
h = heights[x*h_height + y + 1];
V = Vector3(x, h, y+1) - p;
N += U.cross(V);
// left
- if(x == h_width-1)
+ /*if(x == h_width-1)
h = left[h_height + y]; // x == 1
- else
+ else*/
h = heights[(x+1)*h_height + y];
U = Vector3(x+1, h, y) - p;
//down
- if(y == 0)
+ /*if(y == 0)
h = down[x*(int)(h_height) + chunk_size - 1];
- else
+ else*/
h = heights[x*h_height + y - 1];
V = Vector3(x, h, y-1) - p;
N += U.cross(V);
// up
- if(y == h_height-1)
+ /*if(y == h_height-1)
h = up[x*(int)(h_height) + 1]; // y == 1
- else
+ else*/
h = heights[x*h_height + y + 1];
V = Vector3(x, h, y+1) - p;
N += V.cross(U);
N /= N.length();
- normals[x*h_height + y] = N;
+ normals[(x-1)*n_height + y - 1] = N;
}
}
+
+ need_normals = false;
}
Terrain::Terrain() {
- tc = new TerrainCache(0, "map", 120);
+ tc = new TerrainCache("map", 120);
}
Terrain::~Terrain() {
@@ -351,6 +364,7 @@ Terrain::~Terrain() {
}
void Terrain::raise(float x, float z, float radius, float focus, float strength, bool up) {
+ // TODO: fix
// TODO: fix setting heights on unloaded chunks
std::set<Chunk*> changed_chunks;
@@ -441,19 +455,32 @@ void Terrain::update(float x, float z) {
chunk_indices.insert(std::pair<int, int>(i, j));
}
}
+
for(std::list<Chunk*>::iterator it = chunks.begin(); it != chunks.end(); it++) {
- std::set<std::pair<int, int> >::iterator ind_it = chunk_indices.find(std::pair<int, int>((*it)->x, (*it)->y));
+ Chunk *chunk = *it;
+ std::set<std::pair<int, int> >::iterator ind_it = chunk_indices.find(std::pair<int, int>(chunk->x, chunk->y));
if(ind_it != chunk_indices.end()) {
chunk_indices.erase(ind_it);
}
- if((*it)->distance(x, z) > chunk_dist_threshold) {
+ if(chunk->distance(x, z) > chunk_dist_threshold) {
delete *it;
it = chunks.erase(it);
+ } else if((*it)->need_normals) {
+ chunk->calc_normals();
+ chunk->make_vbo();
}
}
+
for(std::set<std::pair<int, int> >::iterator it = chunk_indices.begin(); it != chunk_indices.end(); it++) {
- Chunk *chunk = new Chunk(this, it->first, it->second, chunk_size, chunk_size);
- chunks.push_back(chunk);
+ if(tc->tl->has_chunk(it->first, it->second)) {
+ Chunk *chunk = NULL;
+ try {
+ chunk = new Chunk(this, it->first, it->second);
+ } catch(...) {
+ }
+ if(chunk)
+ chunks.push_back(chunk);
+ }
}
}