From 623fc8c73de35bef0785f09bae8a3f607f8ed087 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Fri, 27 Apr 2012 20:43:08 +0200 Subject: qt_terr - a simple quadtree based terrain renderer with LOD --- samples/OpenGL/qt_terr/Makefile | 7 + samples/OpenGL/qt_terr/main.cpp | 582 ++++++++++++++++++++++++++++ samples/OpenGL/qt_terr/mountains.png | Bin 0 -> 9265856 bytes samples/OpenGL/qt_terr/mountains.ter | Bin 0 -> 526424 bytes samples/OpenGL/qt_terr/mountains.tgw | Bin 0 -> 3128 bytes samples/OpenGL/qt_terr/quad.cpp | 140 +++++++ samples/OpenGL/qt_terr/quad.h | 49 +++ samples/OpenGL/qt_terr/readme.txt | 14 + samples/OpenGL/qt_terr/terragen.cpp | 138 +++++++ samples/OpenGL/qt_terr/terragen.h | 6 + samples/OpenGL/qt_terr/terrain.cpp | 43 ++ samples/OpenGL/qt_terr/terrain.h | 26 ++ samples/OpenGL/qt_terr/vecmath.cpp | 39 ++ samples/OpenGL/qt_terr/vecmath.h | 16 + samples/OpenGL/x11argb_opengl_glsl/Makefile | 2 - 15 files changed, 1060 insertions(+), 2 deletions(-) create mode 100644 samples/OpenGL/qt_terr/Makefile create mode 100644 samples/OpenGL/qt_terr/main.cpp create mode 100644 samples/OpenGL/qt_terr/mountains.png create mode 100644 samples/OpenGL/qt_terr/mountains.ter create mode 100644 samples/OpenGL/qt_terr/mountains.tgw create mode 100644 samples/OpenGL/qt_terr/quad.cpp create mode 100644 samples/OpenGL/qt_terr/quad.h create mode 100644 samples/OpenGL/qt_terr/readme.txt create mode 100644 samples/OpenGL/qt_terr/terragen.cpp create mode 100644 samples/OpenGL/qt_terr/terragen.h create mode 100644 samples/OpenGL/qt_terr/terrain.cpp create mode 100644 samples/OpenGL/qt_terr/terrain.h create mode 100644 samples/OpenGL/qt_terr/vecmath.cpp create mode 100644 samples/OpenGL/qt_terr/vecmath.h 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 +#include +#include +#include +#include + +#include + +#define ILUT_USE_OPENGL 1 + +#include +#include +#include +#include +#include + +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=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(iMaxLOD0) + 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]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&&LODis_split() && LODquads[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 Binary files /dev/null and b/samples/OpenGL/qt_terr/mountains.png differ diff --git a/samples/OpenGL/qt_terr/mountains.ter b/samples/OpenGL/qt_terr/mountains.ter new file mode 100644 index 0000000..5f48ff0 Binary files /dev/null and b/samples/OpenGL/qt_terr/mountains.ter differ diff --git a/samples/OpenGL/qt_terr/mountains.tgw b/samples/OpenGL/qt_terr/mountains.tgw new file mode 100644 index 0000000..5162265 Binary files /dev/null and b/samples/OpenGL/qt_terr/mountains.tgw 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 +#include "quad.h" + +Quad::Quad() : + V(new std::vector) +{ + 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 * 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) +{ + 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 + +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*); + std::vector * 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 .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 + 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 +#include +#include +#include + +#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(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=(xtrack_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 + +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 +#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 -- cgit v1.2.3