aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--samples/OpenGL/qt_terr/Makefile7
-rw-r--r--samples/OpenGL/qt_terr/main.cpp582
-rw-r--r--samples/OpenGL/qt_terr/mountains.pngbin0 -> 9265856 bytes
-rw-r--r--samples/OpenGL/qt_terr/mountains.terbin0 -> 526424 bytes
-rw-r--r--samples/OpenGL/qt_terr/mountains.tgwbin0 -> 3128 bytes
-rw-r--r--samples/OpenGL/qt_terr/quad.cpp140
-rw-r--r--samples/OpenGL/qt_terr/quad.h49
-rw-r--r--samples/OpenGL/qt_terr/readme.txt14
-rw-r--r--samples/OpenGL/qt_terr/terragen.cpp138
-rw-r--r--samples/OpenGL/qt_terr/terragen.h6
-rw-r--r--samples/OpenGL/qt_terr/terrain.cpp43
-rw-r--r--samples/OpenGL/qt_terr/terrain.h26
-rw-r--r--samples/OpenGL/qt_terr/vecmath.cpp39
-rw-r--r--samples/OpenGL/qt_terr/vecmath.h16
-rw-r--r--samples/OpenGL/x11argb_opengl_glsl/Makefile2
15 files changed, 1060 insertions, 2 deletions
diff --git a/samples/OpenGL/qt_terr/Makefile b/samples/OpenGL/qt_terr/Makefile
new file mode 100644
index 0000000..1f9c52b
--- /dev/null
+++ b/samples/OpenGL/qt_terr/Makefile
@@ -0,0 +1,7 @@
+CC = gcc
+CPP = g++
+OBJS += main.o quad.o terragen.o terrain.o vecmath.o
+
+qt_terr: $(OBJS)
+ $(CPP) -o qt_terr $(OBJS) -lm -lGL -lGLU -lGLEW -lglut -lIL -lILU -lILUT
+
diff --git a/samples/OpenGL/qt_terr/main.cpp b/samples/OpenGL/qt_terr/main.cpp
new file mode 100644
index 0000000..64c4327
--- /dev/null
+++ b/samples/OpenGL/qt_terr/main.cpp
@@ -0,0 +1,582 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <algorithm>
+#include <math.h>
+
+#include <string>
+
+#define ILUT_USE_OPENGL 1
+
+#include <GL/glew.h>
+#include <GL/glut.h>
+#include <IL/il.h>
+#include <IL/ilu.h>
+#include <IL/ilut.h>
+
+using namespace std;
+
+#include "vecmath.h"
+#include "terragen.h"
+#include "terrain.h"
+
+Terrain Q;
+
+double const water_level=-1.0;
+
+void reshape(int width, int height);
+void display();
+void keyboard(unsigned char key, int x, int y);
+
+double frand()
+{
+ return (double)rand()/(double)RAND_MAX;
+}
+
+struct RGB
+{
+ GLubyte r, g, b;
+};
+
+int width, height, levels;
+int iMaxLOD;
+int iMaxCull=7;
+double t, k, l;
+double scale[3];
+double scale_dim;
+double fov=1.414/2;
+//double fov=0.1;
+double near_clip=1;
+double far_clip=100000;
+
+void assign_elevations(Terrain *pT, double *buffer, int width, int height, double t, double k,
+ int left=-1, int bottom=-1, int right=-1, int top=-1);
+
+GLuint texID;
+
+void idle()
+{
+ glutPostRedisplay();
+}
+
+int main(int argc, char **argv)
+{
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
+ glutCreateWindow("Terrain");
+ glutDisplayFunc(display);
+ glutReshapeFunc(reshape);
+ glutKeyboardFunc(keyboard);
+ glutIdleFunc(idle);
+
+ glewInit();
+
+ if(argc<2)
+ return -1;
+
+ std::string terrain_filename(argv[1]);
+
+ double *buffer=NULL;
+ read_terrain(terrain_filename.c_str(), &buffer, &width, &height, scale);
+ levels = max(width, height);
+ levels = log(levels)/log(2);
+ scale_dim=sqrt(pow(scale[0]*width, 2)+pow(scale[1]*height, 2)+scale[2]*scale[2]);
+
+ iMaxLOD=levels;
+
+ ilInit();
+ iluInit();
+ ilutInit();
+ ilutRenderer(ILUT_OPENGL);
+
+ std::string img_filename( terrain_filename );
+ img_filename.replace(img_filename.length()-5, 4, ".png");
+
+ texID=ilutGLLoadImage(img_filename.c_str());
+ glBindTexture(GL_TEXTURE_2D, texID);
+
+ int x, y;
+ double min_v = 0, max_v = 0;
+ for(y = 0; y < height; y++)
+ {
+ for( x = 0; x < width; x++)
+ {
+ min_v = min( buffer[ y*width + x ], min_v );
+ max_v = max( buffer[ y*width + x ], max_v );
+ }
+ }
+
+#if 0
+ RGB *img_buffer = new RGB[width*height];
+ t=min_v;
+ k=255.0/(double)(max_v-min_v);
+ l=1.0/(double)(max_v-min_v);
+ for(y=0; y<height; y++)
+ {
+ for(x=0; x<width; x++)
+ {
+ RGB *rgb=(img_buffer+(y*width+x));
+ double const *value=(buffer+(y*width+x));
+
+ Q.track_down((double)x/(double)width, (double)y/(double)height, (*value), levels);
+
+ if(*value>=water_level)
+ {
+ rgb->r=rgb->g=rgb->b=(*value-t)*k;
+ }
+ else
+ {
+ rgb->r=rgb->g=0.5*(*value-t)*k+75;
+ rgb->b=(*value-t)*k+128;
+ }
+
+ }
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, 1);
+ glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_buffer);
+
+ delete[] img_buffer;
+#endif
+
+ assign_elevations(&Q, buffer, width, height, 0, 1);
+
+ delete[] buffer;
+
+ glEnable(GL_CULL_FACE);
+ glClearColor(0.7, 0.8, 1.0, 1.0);
+
+ glutMainLoop();
+
+ return 0;
+};
+
+void assign_elevations(Terrain *pT, double *buffer, int width, int height, double t, double k,
+ int left, int bottom, int right, int top)
+{
+ if(left == -1)
+ left=0;
+ if(bottom == -1)
+ bottom=0;
+ if(right == -1)
+ right=width-1;
+ if(top == -1)
+ top=height-1;
+
+// WTF, a no-op macro, why?!
+// BTW, I wrote that, whatever I was planning, I didn't finish it
+// -- Wolfgang
+#define PEL(d) (d)
+
+ pT->z[0][0]=( buffer[ PEL(left+bottom*width) ] -t )*k;
+ pT->z[0][1]=( buffer[ PEL(right+bottom*width) ] -t )*k;
+ pT->z[1][1]=( buffer[ PEL(right+top*width) ] -t )*k;
+ pT->z[1][0]=( buffer[ PEL(left+top*width) ] -t )*k;
+
+ pT->z_mean=(
+ pT->z[0][0]+
+ pT->z[0][1]+
+ pT->z[1][1]+
+ pT->z[1][0])*0.25;
+
+ if(pT->is_split())
+ {
+ assign_elevations((Terrain*)pT->quads[0][0], buffer, width, height, t, k,
+ left, bottom, left+(right-left)/2, bottom+(top-bottom)/2);
+
+ assign_elevations((Terrain*)pT->quads[0][1], buffer, width, height, t, k,
+ left+(right-left)/2, bottom, right, bottom+(top-bottom)/2);
+
+ assign_elevations((Terrain*)pT->quads[1][1], buffer, width, height, t, k,
+ left+(right-left)/2, bottom+(top-bottom)/2, right, top);
+
+ assign_elevations((Terrain*)pT->quads[1][0], buffer, width, height, t, k,
+ left, bottom+(top-bottom)/2, left+(right-left)/2, top);
+ }
+}
+
+double view_dot;
+
+void reshape(int width, int height)
+{
+ glViewport(0,0,width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ double aspect=(double)width/(double)height;
+
+ double x=near_clip*fov;
+ double y=x/aspect;
+
+ double RIGHT_UPPER[3]={x, y, near_clip};
+ double cam_view[3]={0,0,1};
+ normalize(RIGHT_UPPER, RIGHT_UPPER);
+ view_dot=DOT(cam_view, RIGHT_UPPER);
+
+ glFrustum(-x, x, -y, y, near_clip, far_clip);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+bool bDrawQuads=true;
+bool bFill=true;
+bool bLOD=true;
+bool bFrustumCulling=true;
+bool bContinuous=true;
+bool bAnimation=true;
+bool bPaused=false;
+
+enum Camera{follow, bird_view};
+int eCam;
+
+void keyboard(unsigned char key, int x, int y)
+{
+ switch(key)
+ {
+ case ' ':
+ bAnimation=!bAnimation;
+ break;
+
+ case 'Q':
+ case 'q':
+ exit(0);
+ break;
+
+ case 'F':
+ case 'f':
+ bFill=!bFill;
+ break;
+
+ case 'H':
+ case 'h':
+ bFrustumCulling=!bFrustumCulling;
+ break;
+
+ case 'L':
+ case 'l':
+ bLOD=!bLOD;
+ break;
+
+ case 'V':
+ case 'v':
+ eCam++;
+ if(eCam>bird_view)
+ eCam = 0;
+ break;
+
+ case 'C':
+ case 'c':
+ bContinuous=!bContinuous;
+ break;
+
+ case 'p':
+ case 'P':
+ bPaused=!bPaused;
+ break;
+
+ case 's':
+ case 'S':
+ ilutGLScreenie();
+
+ case '+':
+ if(iMaxLOD<levels)
+ iMaxLOD++;
+ break;
+
+ case '-':
+ if(iMaxLOD>0)
+ iMaxLOD--;
+ break;
+ }
+ glutPostRedisplay();
+}
+
+void draw_quad(Terrain *pQ, int LOD=0, double z1=0, double z2=0, double z3=0, double z4=0);
+
+GLdouble cam_pos[3];//={68.0f*scale[0], 44.0f*scale[1], 47.7*scale[2]*0.5};
+double cam_la[3];
+double cam_vec[3];
+double cam_vec_n0[3];
+
+#define PI 3.141512
+
+double modelview_matrix[16];
+double projection_matrix[16];
+GLint viewport[4]={0,0,1,1};
+
+void display()
+{
+ static double alpha=0;
+ static double beta=0;
+
+ if(bAnimation)
+ {
+ alpha+=0.0025*PI;
+ beta+=0.001*PI;
+
+ if(alpha>2*PI)
+ alpha=0;
+
+ if(beta>2*PI)
+ beta=0;
+ }
+
+ double dx=(1+cos(alpha))*0.5;
+ double dy=(1+sin(alpha))*0.5;
+
+ double dz=(1+sin(beta))*0.5;
+
+ cam_pos[0]=dx*width*scale[0];
+ cam_pos[1]=dy*height*scale[1];
+ cam_pos[2]=max(dz*scale[2]*width*3, (20.0f+((Terrain*)Q.get_at(dx, dy))->z_mean)*scale[2]);
+ //cam_pos[2]=(20.0f+((Terrain*)Q.get_at(dx, dy))->z_mean)*scale[2];
+
+ cam_la[0]=width*scale[0]*0.5;
+ cam_la[1]=height*scale[1]*0.5;
+ cam_la[2]=9.6*scale[2]*0.5;
+
+ cam_vec[0]=cam_la[0]-cam_pos[0];
+ cam_vec[1]=cam_la[1]-cam_pos[1];
+ cam_vec[2]=cam_la[2]-cam_pos[2];
+
+ normalize(cam_vec_n0, cam_vec);
+
+ normalize(cam_vec, cam_vec);
+
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+ gluLookAt( cam_pos[0], cam_pos[1], cam_pos[2],
+ cam_la[0], cam_la[1], cam_la[2],
+ 0,0,1);
+ glScalef(1,1,0.5);
+ glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
+ glGetIntegerv(GL_VIEWPORT, viewport);
+
+ switch(eCam)
+ {
+ case follow:
+ break;
+
+ case bird_view:
+ glLoadIdentity();
+ gluLookAt( width*scale[0]*0.5, height*scale[1]*0.5, scale[2]*500,
+ cam_la[0], cam_la[1], cam_la[2],
+ 0,1,0);
+ //glScalef(1,1,0.5);
+ break;
+ }
+ //glTranslatef(-0.5, -0.5, -5);
+
+ glEnable(GL_DEPTH_TEST);
+ /*
+ if(bDrawTerrain)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_TEXTURE_RECTANGLE_NV);
+ glBegin(GL_QUADS);
+ glColor3f(1,1,1);
+ glTexCoord2i(0,0);
+ glVertex2f(0,0);
+ glTexCoord2i(width,0);
+ glVertex2f(1,0);
+ glTexCoord2i(width, height);
+ glVertex2f(1,1);
+ glTexCoord2i(0,height);
+ glVertex2f(0,1);
+ glEnd();
+ }*/
+
+ glColor3f(1,0,0);
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3dv(cam_pos);
+ glEnd();
+
+ if(bDrawQuads)
+ {
+ glColor3f(1,1,1);
+ glDisable(GL_TEXTURE_RECTANGLE_NV);
+ glEnable(GL_TEXTURE_2D);
+ glPolygonMode(GL_FRONT_AND_BACK, bFill?GL_FILL:GL_LINE);
+ glBegin(GL_QUADS);
+ draw_quad(&Q);
+ glEnd();
+ }
+
+ glutSwapBuffers();
+}
+
+bool in_view(double a[3])
+{
+ GLdouble winx, winy, winz;
+
+ gluProject(a[0], a[1], a[2], modelview_matrix, projection_matrix, viewport, &winx, &winy, &winz);
+ if( winx>=viewport[0] && winx<=viewport[2] &&
+ winy>=viewport[1] && winy<=viewport[3] )
+ return true;
+
+ return false;
+}
+
+void draw_quad(Terrain *pT, int LOD, double z1, double z2, double z3, double z4)
+{
+ bool bRefine=true;
+ bool bInFront=true;
+
+ double Q[3]={pT->x_mid*width*scale[0], pT->y_mid*height*scale[1], pT->z_mean*scale[2]};
+ double Q1[3]={pT->x1*width*scale[0], pT->y1*height*scale[1], pT->z[0][0]*scale[2]};
+ double Q2[3]={pT->x2*width*scale[0], pT->y1*height*scale[1], pT->z[0][1]*scale[2]};
+ double Q3[3]={pT->x2*width*scale[0], pT->y2*height*scale[1], pT->z[1][1]*scale[2]};
+ double Q4[3]={pT->x1*width*scale[0], pT->y2*height*scale[1], pT->z[1][0]*scale[2]};
+ double Qt[3];
+
+ double dir[3];
+ SUB(dir, Q, cam_pos);
+ double dot=DOT(dir, cam_vec);
+
+ double l_n[4];
+ double dir_n[3];
+
+ /*
+ SUB(dir_n, Q1, cam_pos);
+ l_n[0]=length(dir_n);
+
+ SUB(dir_n, Q2, cam_pos);
+ l_n[1]=length(dir_n);
+
+ SUB(dir_n, Q3, cam_pos);
+ l_n[2]=length(dir_n);
+
+ SUB(dir_n, Q4, cam_pos);
+ l_n[3]=length(dir_n);
+ */
+
+ //if(l_n[0]<l_n[2])
+ {
+ memcpy(Qt, Q1, sizeof(double)*3);
+ Qt[2]=z1;
+ SUB(dir_n, Qt, cam_pos);
+ l_n[0]=length(dir_n);
+ }
+
+ //if(l_n[1]<l_n[3])
+ {
+ memcpy(Qt, Q2, sizeof(double)*3);
+ Qt[2]=z2;
+ SUB(dir_n, Qt, cam_pos);
+ l_n[1]=length(dir_n);
+ }
+
+ //if(l_n[2]<l_n[0])
+ {
+ memcpy(Qt, Q3, sizeof(double)*3);
+ Qt[2]=z3;
+ SUB(dir_n, Qt, cam_pos);
+ l_n[2]=length(dir_n);
+ }
+
+ //if(l_n[3]<l_n[1])
+ {
+ memcpy(Qt, Q4, sizeof(double)*3);
+ Qt[2]=z4;
+ SUB(dir_n, Qt, cam_pos);
+ l_n[3]=length(dir_n);
+ }
+
+ double l=length(dir);
+ double sz=scale_dim/((double)(1<<LOD)*l*fov);
+
+ double diameter=scale_dim/((double)(1<<LOD));
+
+ double const k=0.05;
+
+ double d_lod_plus_1=scale_dim/((double)(1<<(LOD))*k*fov);
+ double d_lod=scale_dim/((double)(1<<(LOD-1))*k*fov);
+
+ double lod_scale[4]={1.0, 1.0, 1.0, 1.0};
+ double one_minus_lod_scale[4]={0.0, 0.0, 0.0, 0.0};
+
+ bool bClipped = false;
+ if(bContinuous && LOD>0)
+ {
+ for(int i=0; i<4; i++)
+ {
+ lod_scale[i]=(d_lod-l_n[i])/(d_lod-d_lod_plus_1);
+
+ lod_scale[i]=min(lod_scale[i], 1.0);
+ lod_scale[i]=max(lod_scale[i], 0.0);
+
+ one_minus_lod_scale[i]=1.0-lod_scale[i];
+ }
+ }
+
+ if(bLOD)
+ {
+ bRefine = sz > k;
+ }
+
+ if(bFrustumCulling&&LOD<iMaxCull)
+ {
+ bInFront=( in_view(Q) ||
+ in_view(Q1) ||
+ in_view(Q2) ||
+ in_view(Q3) ||
+ in_view(Q4) );
+ }
+
+ if(bInFront)
+ {
+ if(pT->is_split() && LOD<iMaxLOD && bRefine)
+ {
+ double Z1=(Q1[2]+Q2[2])*0.5;
+ double Z2=(Q2[2]+Q3[2])*0.5;
+ double Z3=(Q3[2]+Q4[2])*0.5;
+ double Z4=(Q4[2]+Q1[2])*0.5;
+
+ Q[2]=(Q1[2]+Q2[2]+Q3[2]+Q4[2])*0.25;
+
+ draw_quad( pT->quads[0][0], LOD+1,
+ Q1[2], Z1, Q[2], Z4);
+
+ draw_quad( pT->quads[0][1], LOD+1,
+ Z1, Q2[2], Z2, Q[2]);
+
+ draw_quad( pT->quads[1][1], LOD+1,
+ Q[2], Z2, Q3[2], Z3);
+
+ draw_quad( pT->quads[1][0], LOD+1,
+ Z4, Q[2], Z3, Q4[2]);
+ }
+ else// if(bInFront)
+ {
+ Q1[2]=Q1[2]*lod_scale[0] + z1*one_minus_lod_scale[0];
+ Q2[2]=Q2[2]*lod_scale[1] + z2*one_minus_lod_scale[1];
+ Q3[2]=Q3[2]*lod_scale[2] + z3*one_minus_lod_scale[2];
+ Q4[2]=Q4[2]*lod_scale[3] + z4*one_minus_lod_scale[3];
+
+#define LUM(v) glColor3f(v,v,v)
+
+ if(bClipped)
+ glColor3f(1,0,0);
+ else
+ glColor3f(1,1,1);
+ //LUM(one_minus_lod_scale[0]);
+ glTexCoord2f(pT->x1, pT->y1);
+ glVertex3dv(Q1);
+
+ //LUM(one_minus_lod_scale[1]);
+ glTexCoord2f(pT->x2, pT->y1);
+ glVertex3dv(Q2);
+
+ //LUM(one_minus_lod_scale[2]);
+ glTexCoord2f(pT->x2, pT->y2);
+ glVertex3dv(Q3);
+
+ //LUM(one_minus_lod_scale[3]);
+ glTexCoord2f(pT->x1, pT->y2);
+ glVertex3dv(Q4);
+ }
+ }
+}
diff --git a/samples/OpenGL/qt_terr/mountains.png b/samples/OpenGL/qt_terr/mountains.png
new file mode 100644
index 0000000..77e87c5
--- /dev/null
+++ b/samples/OpenGL/qt_terr/mountains.png
Binary files differ
diff --git a/samples/OpenGL/qt_terr/mountains.ter b/samples/OpenGL/qt_terr/mountains.ter
new file mode 100644
index 0000000..5f48ff0
--- /dev/null
+++ b/samples/OpenGL/qt_terr/mountains.ter
Binary files differ
diff --git a/samples/OpenGL/qt_terr/mountains.tgw b/samples/OpenGL/qt_terr/mountains.tgw
new file mode 100644
index 0000000..5162265
--- /dev/null
+++ b/samples/OpenGL/qt_terr/mountains.tgw
Binary files differ
diff --git a/samples/OpenGL/qt_terr/quad.cpp b/samples/OpenGL/qt_terr/quad.cpp
new file mode 100644
index 0000000..e57bcfa
--- /dev/null
+++ b/samples/OpenGL/qt_terr/quad.cpp
@@ -0,0 +1,140 @@
+#include <stdlib.h>
+#include "quad.h"
+
+Quad::Quad() :
+ V(new std::vector<double>)
+{
+ quads[0][0] =
+ quads[0][1] =
+ quads[1][0] =
+ quads[1][1] = 0;
+
+ unsigned int V_old_size = V->size();
+ unsigned int V_new_size = V_old_size + 9;
+ V->resize(V_new_size, 0.);
+
+ v1_offset = V_new_size - 3*3;
+ v2_offset = V_new_size - 2*3;
+ v_mid_offset = V_new_size - 1*3;
+
+ set_range(0., 1., 0., 1.);
+}
+
+Quad::Quad( std::vector<double> * const V_) :
+ V(V_)
+{
+ quads[0][0] =
+ quads[0][1] =
+ quads[1][0] =
+ quads[1][1] = 0;
+
+ unsigned int V_old_size = V->size();
+ unsigned int V_new_size = V_old_size + 9;
+ V->resize(V_new_size, 0.);
+
+ v1_offset = V_new_size - 3*3;
+ v2_offset = V_new_size - 2*3;
+ v_mid_offset = V_new_size - 1*3;
+
+ set_range(0., 1., 0., 1.);
+}
+
+Quad::Quad(Quad &q) :
+ V(new std::vector<double>)
+{
+ operator= (q);
+}
+
+Quad::~Quad()
+{
+ if(is_split())
+ {
+ delete quads[0][0];
+ delete quads[0][1];
+ delete quads[1][0];
+ delete quads[1][1];
+ }
+}
+
+Quad& Quad::operator=(Quad &q)
+{
+ *x1() = *q.x1();
+ *x2() = *q.x2();
+ *y1() = *q.y1();
+ *y2() = *q.y2();
+
+ if( q.is_split() )
+ {
+ split();
+ quads[0][0] = q.quads[0][0];
+ quads[0][1] = q.quads[0][1];
+ quads[1][0] = q.quads[1][0];
+ quads[1][1] = q.quads[1][1];
+ }
+
+ return *this;
+}
+
+void Quad::split()
+{
+ if(is_split())
+ return;
+
+ quads[0][0] = new Quad(V);
+ quads[0][1] = new Quad(V);
+ quads[1][0] = new Quad(V);
+ quads[1][1] = new Quad(V);
+
+ quads[0][0]->set_range( *x1(), *x_mid(), *y1(), *y_mid() );
+ quads[0][1]->set_range( *x_mid(), *x2(), *y1(), *y_mid() );
+ quads[1][0]->set_range( *x1(), *x_mid(), *y_mid(), *y2() );
+ quads[1][1]->set_range( *x_mid(), *x2(), *y_mid(), *y2() );
+}
+
+bool Quad::is_split()
+{
+ return quads[0][0] &&
+ quads[0][1] &&
+ quads[1][0] &&
+ quads[1][1];
+}
+
+void Quad::set_range(double nx1, double nx2, double ny1, double ny2)
+{
+ *x1() = nx1;
+ *x2() = nx2;
+ *y1() = ny1;
+ *y2() = ny2;
+ *x_mid() = ( *x1() + *x2() )*0.5f;
+ *y_mid() = ( *y1() + *y2() )*0.5f;
+
+}
+
+void Quad::track_down(double x, double y, int levels)
+{
+ if(levels>0)
+ {
+ int a = ( x < *x_mid() ) ? 0 : 1;
+ int b = ( y < *y_mid() ) ? 0 : 1;
+
+ if( !is_split() )
+ split();
+
+ quads[b][a]->track_down(x, y, levels-1);
+ }
+}
+
+Quad *Quad::get_at(double x, double y, int max_level, int level)
+{
+ if(!is_split())
+ return this;
+
+ /*if(max_level>-1 && level>=max_level)
+ return this;*/
+
+ int a = ( x < *x_mid() ) ? 0 : 1;
+ int b = ( y < *y_mid() ) ? 0 : 1;
+
+ return quads[b][a]->get_at(x, y, max_level, level+1);
+}
+
diff --git a/samples/OpenGL/qt_terr/quad.h b/samples/OpenGL/qt_terr/quad.h
new file mode 100644
index 0000000..1c6549a
--- /dev/null
+++ b/samples/OpenGL/qt_terr/quad.h
@@ -0,0 +1,49 @@
+#ifndef QUAD_H
+#define QUAD_H
+
+#include <vector>
+
+class Quad
+{
+public:
+// double x1,x2, x_mid;
+// double y1,y2, y_mid;
+
+ unsigned int v1_offset;
+ unsigned int v2_offset;
+ unsigned int v_mid_offset;
+
+ double *x1() { return &(*V)[v1_offset + 0]; }
+ double *y1() { return &(*V)[v1_offset + 1]; }
+ double *z1() { return &(*V)[v1_offset + 2]; }
+
+ double *x2() { return &(*V)[v2_offset + 0]; }
+ double *y2() { return &(*V)[v2_offset + 1]; }
+ double *z2() { return &(*V)[v2_offset + 2]; }
+
+ double *x_mid() { return &(*V)[v_mid_offset + 0]; }
+ double *y_mid() { return &(*V)[v_mid_offset + 1]; }
+ double *z_mid() { return &(*V)[v_mid_offset + 2]; }
+
+ Quad *quads[2][2];
+
+public:
+ Quad();
+ Quad(Quad &q);
+ ~Quad();
+ Quad& operator=(Quad &q);
+
+ virtual void split();
+ virtual bool is_split();
+
+ virtual void track_down(double x, double y, int levels);
+ virtual Quad *get_at(double x, double y, int max_level=0, int level=0);
+
+protected:
+ virtual void set_range(double nx1, double nx2, double ny1, double ny2);
+
+ Quad(std::vector<double>*);
+ std::vector<double> * const V;
+};
+
+#endif//QUAD_H
diff --git a/samples/OpenGL/qt_terr/readme.txt b/samples/OpenGL/qt_terr/readme.txt
new file mode 100644
index 0000000..cb2b065
--- /dev/null
+++ b/samples/OpenGL/qt_terr/readme.txt
@@ -0,0 +1,14 @@
+Extract all into a single directory
+
+Execute with
+# terrain <terrain>.ter
+
+Key mapping:
+[V] Change camera mode
+[H] Frustum Culling on/off
+[L] Level of Detail triangle reduction on/off
+[F] Polygonfilling/Wireframe on/off
+[+] increase max. Level of Detail
+[-] decrease max. Level of Detail
+[S] Screenshot
+<SPACE> pause/restart animation \ No newline at end of file
diff --git a/samples/OpenGL/qt_terr/terragen.cpp b/samples/OpenGL/qt_terr/terragen.cpp
new file mode 100644
index 0000000..3b922a4
--- /dev/null
+++ b/samples/OpenGL/qt_terr/terragen.cpp
@@ -0,0 +1,138 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "terragen.h"
+
+// Some custom types and helper macros that
+// allow for a portable file to number variable
+// read procedure
+
+typedef uint8_t DUET[2];
+typedef uint8_t QUARTET[4];
+typedef uint8_t OCTET[8];
+
+#define DUET_TO_NUMBER(duet) ((duet[0]|duet[1]<<8))
+#define QUARTET_TO_NUMBER(quartet) ((quartet[0])|(quartet[1]<<8)|(quartet[2]<<16)|(quartet[3]<<24))
+
+int read_terrain(char *filename, double **pbuffer, int *width, int *height, double *scale)
+// [in] filename: path to the file to be read in
+// [out] pbuffer: address of new allocated data buffer
+// [out] width: width of the terrain
+// [out] heigt: height of the terrain
+// [out] return value: 0 if read in successfully 1 otherwise
+{
+ FILE *file=fopen(filename, "rb");
+ if(!file)
+ return -1;
+
+ OCTET octet;
+ QUARTET quartet;
+ QUARTET quartet_marker;
+ DUET duet;
+
+ fread(octet, 8, 1, file);
+ if(memcmp(octet, "TERRAGEN", 8))
+ return -1;
+
+ fread(octet, 8, 1, file);
+ if(memcmp(octet, "TERRAIN ", 8))
+ return -1;
+
+ fread(quartet, 4, 1, file);
+ if(memcmp(quartet, "SIZE", 4))
+ return -1;
+ fread(duet, 2, 1, file);
+ fseek(file, 2, SEEK_CUR);
+ int size=DUET_TO_NUMBER(duet);
+
+ int xpts=0, ypts=0;
+ do
+ {
+ fread(quartet_marker, 4, 1, file);
+
+ if(memcmp(quartet_marker, "XPTS", 4)==0)
+ {
+ fread(duet, 2, 1, file);
+ fseek(file, 2, SEEK_CUR);
+ xpts=DUET_TO_NUMBER(duet);
+ continue;
+ }
+
+ if(memcmp(quartet_marker, "YPTS", 4)==0)
+ {
+ fread(duet, 2, 1, file);
+ fseek(file, 2, SEEK_CUR);
+ ypts=DUET_TO_NUMBER(duet);
+ continue;
+ }
+
+ // I'm going to ignore the other segments so long
+ // so we can leave the quartet marker test to the
+ // while condition
+ //if(strcmp(quartet_marker, "SIZE")) // Ignore SIZE
+ // fseek(file, 4, SEEK_CUR);
+
+ if(memcmp(quartet_marker, "SCAL", 4)==0&&scale) // Ignore SCAL
+ {
+ float fscale[3];
+ fread(&(fscale[0]), 4, 1, file);
+ fread(&(fscale[1]), 4, 1, file);
+ fread(&(fscale[2]), 4, 1, file);
+ scale[0]=fscale[0];
+ scale[1]=fscale[1];
+ scale[2]=fscale[2];
+ }
+
+ //if(strcmp(quartet_marker, "CRAD")) // Ignore CRAD
+ // fseek(file, 4, SEEK_CUR);
+
+ //if(strcmp(quartet_marker, "CRVM")) // Ignore CRVM
+ // fseek(file, 4, SEEK_CUR);
+
+ }while(memcmp(quartet_marker, "ALTW", 4));
+
+ int16_t height_scale, base_height;
+ fread(duet, 2, 1, file);
+ height_scale = DUET_TO_NUMBER(duet);
+ fread(duet, 2, 1, file);
+ base_height = DUET_TO_NUMBER(duet);
+
+ if(xpts==0&&ypts==0)
+ {
+ xpts=size+1;
+ ypts=size+1;
+ }
+
+ *width=xpts;
+ *height=ypts;
+
+ // The caller of this function is responsible
+ // to free the memory consumed by buffer
+ DUET *buffer=new DUET[xpts*ypts];
+ fread(buffer, 2, xpts*ypts, file);
+
+ *pbuffer=new double[xpts*ypts];
+ for(int y=0; y<ypts; y++)
+ {
+ for(int x=0; x<xpts; x++)
+ {
+ int16_t elev = (int16_t)DUET_TO_NUMBER( buffer[y*xpts+x] );
+ //memcpy(&elev, (buffer+(y*xpts+x)), 2);
+ (*pbuffer)[y*xpts+x]=
+ static_cast<double>(base_height+elev*height_scale/65536);
+ }
+ }
+ delete[] buffer;
+
+ // a last test, the next we read should be "EOF ", since currently the Terragen
+ // file format says, that "ALTW" must be the last segment of a file
+ // however it's no problem for _us_ if we've no "EOF " here, because it doesn't matter
+ fread(quartet, 4, 1, file);
+ if(memcmp(quartet, "EOF ", 4))
+ printf("read terrain file with \"EOF \" at the end\n");
+
+ fclose(file);
+ return 0;
+}
diff --git a/samples/OpenGL/qt_terr/terragen.h b/samples/OpenGL/qt_terr/terragen.h
new file mode 100644
index 0000000..5037a08
--- /dev/null
+++ b/samples/OpenGL/qt_terr/terragen.h
@@ -0,0 +1,6 @@
+#ifndef TERRAGEN_H
+#define TERRAGEN_H
+
+int read_terrain(char *filename, double **pbuffer, int *width, int *height, double *scale);
+
+#endif/*TERRAGEN*/ \ No newline at end of file
diff --git a/samples/OpenGL/qt_terr/terrain.cpp b/samples/OpenGL/qt_terr/terrain.cpp
new file mode 100644
index 0000000..d08d345
--- /dev/null
+++ b/samples/OpenGL/qt_terr/terrain.cpp
@@ -0,0 +1,43 @@
+#include "terrain.h"
+
+Terrain::Terrain()
+{
+ z_mean=0.0;
+}
+
+void Terrain::split()
+{
+ if(is_split())
+ return;
+
+ quads[0][0] = new Terrain(V);
+ quads[0][1] = new Terrain(V);
+ quads[1][0] = new Terrain(V);
+ quads[1][1] = new Terrain(V);
+
+ quads[0][0]->set_range(x1, x_mid, y1, y_mid);
+ quads[0][1]->set_range(x_mid, x2, y1, y_mid);
+ quads[1][0]->set_range(x1, x_mid, y_mid, y2);
+ quads[1][1]->set_range(x_mid, x2, y_mid, y2);
+}
+
+void Terrain::track_down(double x, double y, double nz, int levels)
+{
+ if(levels>0)
+ {
+ int a=(x<x_mid)?0:1;
+ int b=(y<y_mid)?0:1;
+
+ if(!is_split())
+ split();
+
+ quads[b][a]->track_down(x, y, nz, levels-1);
+ }
+ else
+ {
+ z[0][0]=
+ z[0][1]=
+ z[1][1]=
+ z[1][0]=z_mean=nz;
+ }
+}
diff --git a/samples/OpenGL/qt_terr/terrain.h b/samples/OpenGL/qt_terr/terrain.h
new file mode 100644
index 0000000..0197380
--- /dev/null
+++ b/samples/OpenGL/qt_terr/terrain.h
@@ -0,0 +1,26 @@
+#ifndef TERRAIN_H
+#define TERRAIN_H
+
+#include "quad.h"
+
+#include <vector>
+
+class Terrain : public Quad
+{
+public:
+ double * const z_mean() {
+
+ };
+ double z[2][2];
+
+public:
+ Terrain();
+
+ virtual void split();
+ virtual void track_down(double x, double y, double nz, int levels);
+
+/*protected:
+ virtual void set_range(double nx1, double nx2, double ny1, double ny2);*/
+};
+
+#endif/*TERRAIN_H*/
diff --git a/samples/OpenGL/qt_terr/vecmath.cpp b/samples/OpenGL/qt_terr/vecmath.cpp
new file mode 100644
index 0000000..ff4230c
--- /dev/null
+++ b/samples/OpenGL/qt_terr/vecmath.cpp
@@ -0,0 +1,39 @@
+#include <math.h>
+#include "vecmath.h"
+
+double DOT(double a[3], double b[3])
+{
+ return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
+}
+
+void ADD(double out[3], double a[3], double b[3])
+{
+ out[0]=a[0]+b[0];
+ out[1]=a[1]+b[1];
+ out[2]=a[2]+b[2];
+}
+
+void SUB(double out[3], double a[3], double b[3])
+{
+ out[0]=a[0]-b[0];
+ out[1]=a[1]-b[1];
+ out[2]=a[2]-b[2];
+}
+
+void SCALE(double out[3], double v[3], double scalar)
+{
+ out[0]=v[0]*scalar;
+ out[1]=v[1]*scalar;
+ out[2]=v[2]*scalar;
+}
+
+double length(double v[3])
+{
+ return (double)sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
+}
+
+void normalize(double out[3], double in[3])
+{
+ double k=1.0f/length(in);
+ SCALE(out, in, k);
+} \ No newline at end of file
diff --git a/samples/OpenGL/qt_terr/vecmath.h b/samples/OpenGL/qt_terr/vecmath.h
new file mode 100644
index 0000000..0c27eff
--- /dev/null
+++ b/samples/OpenGL/qt_terr/vecmath.h
@@ -0,0 +1,16 @@
+#ifndef VECMATH_H
+#define VECMATH_H
+
+double DOT(double a[3], double b[3]);
+
+void ADD(double out[3], double a[3], double b[3]);
+
+void SUB(double out[3], double a[3], double b[3]);
+
+void SCALE(double out[3], double v[3], double scalar);
+
+double length(double v[3]);
+
+void normalize(double out[3], double in[3]);
+
+#endif/*VECMATH_H*/
diff --git a/samples/OpenGL/x11argb_opengl_glsl/Makefile b/samples/OpenGL/x11argb_opengl_glsl/Makefile
index e32b597..6c234cb 100644
--- a/samples/OpenGL/x11argb_opengl_glsl/Makefile
+++ b/samples/OpenGL/x11argb_opengl_glsl/Makefile
@@ -1,5 +1,3 @@
-CC=pcc
-
x11argb_opengl_glsl: x11argb_opengl_glsl.c Makefile
$(CC) -std=c99 -g3 -o x11argb_opengl_glsl x11argb_opengl_glsl.c -lX11 -lXrender -lGLEW -lm