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 +++++++++++++++++++++++++++++++----------- quadtree.h | 3 ++ scene.cpp | 14 ++++-- shaders/terrain_fragment.glsl | 2 +- 4 files changed, 95 insertions(+), 34 deletions(-) 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); diff --git a/quadtree.h b/quadtree.h index 36e92ad..45ee09b 100644 --- a/quadtree.h +++ b/quadtree.h @@ -52,6 +52,9 @@ class Quadtree { Quadtree(int width, int height, float *heightmap); virtual ~Quadtree(); + void raise(float x, float z, float radius, float focus, float strength); + + Vector3 calc_normal(int x, int y); void update(float x, float z); QuadNode *find(float x, float y); QuadNode *get_left(QuadNode *node); diff --git a/scene.cpp b/scene.cpp index cbeedd3..4f872d2 100644 --- a/scene.cpp +++ b/scene.cpp @@ -177,8 +177,10 @@ void Scene::events() { show_selection = false; break; case SDL_BUTTON_WHEELUP: + qt->raise(selected.x, selected.z, 10, 1, 1); + break; case SDL_BUTTON_WHEELDOWN: - // TODO: reimplement? + qt->raise(selected.x, selected.z, 10, 1, -1); break; } case SDL_MOUSEMOTION: @@ -252,7 +254,9 @@ void Scene::render() { yvel = 0; } } - move_str = (boost::format("%s %.2f,%.2f %.2fx%.2f") % pos.str() % node->x % node->y % node->width % node->height).str(); + move_str = (boost::format("%s n: %.2f,%.2f %.2fx%.2f c: %d,%d %dx%d") + % pos.str() % node->x % node->y % node->width % node->height + % node->chunk->x % node->chunk->y % node->chunk->width % node->chunk->height).str(); if(last_node != node) { last_node = node; @@ -355,14 +359,16 @@ void Scene::render() { float height = font->LineHeight(); glColor3f(1, 1, 1); glTranslatef(0, video::height-height, 0); - font->Render((boost::format("%dx%d chunks: %d steps: %d") - % qt->width % qt->height % chunks_rendered % steps).str().c_str()); + font->Render((boost::format("%dx%d chunks: %d gravity: %d steps: %d") + % qt->width % qt->height % chunks_rendered % gravity % steps).str().c_str()); //font->Render((boost::format("%dx%d %d levels %d nodes tree creation time: %f steps: %d update: %d") // % scene.qt->width % scene.qt->height % scene.qt->levels % scene.qt->nodes % scene.qt->init_time % steps % scene.qt->thread_running).str().c_str()); //glTranslatef(0, height, 0); //font->Render((boost::format("selected: %x") % selected).str().c_str()); glTranslatef(0, -height, 0); font->Render(move_str.c_str()); + glTranslatef(0, -height, 0); + font->Render(selected.str().c_str()); /*if(selected) { glTranslatef(0, height, 0); //font->Render((boost::format("(%s %s %s %s)") % selected->a->str() % selected->b->str() % selected->c->str() % selected->d->str()).str().c_str()); diff --git a/shaders/terrain_fragment.glsl b/shaders/terrain_fragment.glsl index 78417af..2d02dc8 100644 --- a/shaders/terrain_fragment.glsl +++ b/shaders/terrain_fragment.glsl @@ -7,7 +7,7 @@ uniform sampler2D tex[3]; void main() { vec3 n = normalize(normal); - float diffuse = max(dot(n, light_pos), 0.0); + float diffuse = max(dot(n, light_pos), 0.5); float f1 = clamp((y-15.0) / 3.0, 0.0, 1.0); float f2 = clamp((y-2) / 3.0, 0.0, 1.0); -- cgit v1.2.3