From e0c0a9f3816facd0fc4066a50479f823447e03f6 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Sun, 10 Apr 2011 14:51:47 +0200 Subject: Simple raise/lower implementation. --- quadtree.cpp | 110 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 29 deletions(-) (limited to 'quadtree.cpp') diff --git a/quadtree.cpp b/quadtree.cpp index c60fd27..65c60ae 100644 --- a/quadtree.cpp +++ b/quadtree.cpp @@ -220,6 +220,8 @@ float Quadtree::QuadChunk::distance(float px, float pz) { void Quadtree::QuadChunk::make_vbo() { node_count = width*height; vertices = node_count*12; + if(vbo_object) + glDeleteBuffers(1, &vbo_object); glGenBuffers(1, &vbo_object); glBindBuffer(GL_ARRAY_BUFFER, vbo_object); @@ -325,15 +327,16 @@ Quadtree::QuadNode* Quadtree::QuadChunk::find(float x, float y) { if(!nodes) { float mx = this->x + width / 2; float my = this->y + height / 2; - int i = 2*(y > my); - if(i < 2 && x > mx) + int i = 2*(y >= my); + if(i < 2 && x >= mx) i = 1; else if(i == 2 && x < mx) i = 3; return children[i]->find(x, y); } - if(!(x >= this->x && x < this->x+width && y >= this->y && y < this->y+height)) + if(!(x >= this->x && x < this->x+width && y >= this->y && y < this->y+height)) { return NULL; + } return nodes[(int)(x-this->x)*(int)height + (int)(y - this->y)]; } @@ -349,32 +352,7 @@ Quadtree::Quadtree(int width, int height, float *heightmap) { normals = new Vector3[width*height]; for(int x = 0; x < width; x++) { for(int y = 0; y < height; y++) { - Vector3 p(x, heights[x*height + y], y); - Vector3 N; - - if(x > 0) { - Vector3 U = Vector3(x-1, heights[(x-1)*height + y], y) - p; - if(y > 0) { - Vector3 V = Vector3(x, heights[x*height + y - 1], y-1) - p; - N += V.cross(U); - } - if(y < height-1) { - Vector3 V = Vector3(x, heights[x*height + y + 1], y+1) - p; - N += U.cross(V); - } - } - if(x < width-1) { - Vector3 U = Vector3(x+1, heights[(x+1)*height + y], y) - p; - if(y > 0) { - Vector3 V = Vector3(x, heights[x*height + y - 1], y-1) - p; - N += U.cross(V); - } - if(y < height-1) { - Vector3 V = Vector3(x, heights[x*height + y + 1], y+1) - p; - N += V.cross(U); - } - } - normals[x*height + y] = N / N.length(); + calc_normal(x, y); } } } @@ -385,6 +363,80 @@ Quadtree::~Quadtree() { delete[] normals; } +void Quadtree::raise(float x, float z, float radius, float focus, float strength) { + if(x < 0 || x >= width-1 || z < 0 || z >= height-1) + return; + + /* adjust heights */ + QuadNode *node = find(x, z); + for(int i = x-radius; i < x+radius; i++) { + if(i < 0 || i >= width-1) + continue; + for(int j = z-radius; j < z+radius; j++) { + if(j < 0 || j >= height-1) + continue; + heights[i*height + j] += strength / max(powf((Vector2(x, z) - Vector2(i, j)).length(), focus), 1.0f); + } + } + + /* recalculate normals */ + for(int i = x-radius-1; i < x+radius; i++) { + if(i < 0 || i >= width-1) + continue; + for(int j = z-radius-1; j < z+radius; j++) { + if(j < 0 || j >= height-1) + continue; + calc_normal(i, j); + } + } + + /* refill nodes and remake VBOs */ + for(int nx = x-radius-1; nx < x+chunk_size; nx+=chunk_size) { + if(nx < 0 || nx >= width-1) + continue; + for(int nz = z-radius-1; nz < z+chunk_size; nz+=chunk_size) { + if(nz < 0 || nz >= height-1) + continue; + QuadNode *node = find(nx, nz); + for(int i = 0; i < node->chunk->node_count; i++) { + node->chunk->nodes[i]->fill(); + } + node->chunk->make_vbo(); + } + } +} + +Vector3 Quadtree::calc_normal(int x, int y) { + Vector3 p(x, heights[x*height + y], y); + Vector3 N; + + if(x > 0) { + Vector3 U = Vector3(x-1, heights[(x-1)*height + y], y) - p; + if(y > 0) { + Vector3 V = Vector3(x, heights[x*height + y - 1], y-1) - p; + N += V.cross(U); + } + if(y < height-1) { + Vector3 V = Vector3(x, heights[x*height + y + 1], y+1) - p; + N += U.cross(V); + } + } + if(x < width-1) { + Vector3 U = Vector3(x+1, heights[(x+1)*height + y], y) - p; + if(y > 0) { + Vector3 V = Vector3(x, heights[x*height + y - 1], y-1) - p; + N += U.cross(V); + } + if(y < height-1) { + Vector3 V = Vector3(x, heights[x*height + y + 1], y+1) - p; + N += V.cross(U); + } + } + N /= N.length(); + normals[x*height + y] = N; + return N; +} + void Quadtree::update(float x, float z) { std::queue q; q.push(root); -- cgit v1.2.3