summaryrefslogtreecommitdiff
path: root/quadtree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'quadtree.cpp')
-rw-r--r--quadtree.cpp110
1 files changed, 81 insertions, 29 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);