summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--quadtree.cpp110
-rw-r--r--quadtree.h3
-rw-r--r--scene.cpp14
-rw-r--r--shaders/terrain_fragment.glsl2
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<QuadChunk*> 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);