diff options
Diffstat (limited to 'examples/demo/opengl/gllandscape.cpp')
-rw-r--r-- | examples/demo/opengl/gllandscape.cpp | 880 |
1 files changed, 880 insertions, 0 deletions
diff --git a/examples/demo/opengl/gllandscape.cpp b/examples/demo/opengl/gllandscape.cpp new file mode 100644 index 000000000..0aa836687 --- /dev/null +++ b/examples/demo/opengl/gllandscape.cpp @@ -0,0 +1,880 @@ +#include <qimage.h> +#include "gllandscape.h" + + +#include <math.h> + +#include "fbm.h" + +#ifndef PI +#define PI 3.14159 +#endif + +#if defined(Q_CC_MSVC) +#pragma warning(disable:4305) // init: truncation from const double to float +#pragma warning(disable:4244) // init: truncation from const double to float +#endif + +GLLandscape::GLLandscape( TQWidget * parent, const char * name ) + : TQGLWidget( parent, name ) +{ + mouseButtonDown = FALSE; + animationRunning = FALSE; + oldX = oldY = oldZ = 0.0; + landscape = 0; + vertexNormals = 0; + normals = 0; + wave = 0; + wt = 0; + cubeRot = 0; + createGrid( 50 ); + setWireframe( 0 ); +} + +GLLandscape::~GLLandscape() +{ + destroyGrid(); +} + +void GLLandscape::initializeGL() +{ + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) views[AxisView].model ); + + glTranslatef( 0.0, 0.0, -50.0 ); + glRotatef( -45, 1, 0, 0 ); + glRotatef( -45, 0, 0, 1 ); + glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) views[CurrentView].model ); + glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) views[DefaultView].model ); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + /* Use GL utility library function to obtain desired view */ + gluPerspective( 60, 1, 1, 250 ); + glGetFloatv( GL_PROJECTION_MATRIX, (GLfloat *)views[CurrentView].projection ); + glGetFloatv( GL_PROJECTION_MATRIX, (GLfloat *)views[DefaultView].projection ); + + qglClearColor( black ); + glDepthFunc( GL_LESS ); + calculateVertexNormals(); + + TQImage tex; + tex.load("opengl/qtlogo.png"); + tex = TQGLWidget::convertToGLFormat(tex); // flipped 32bit RGBA + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, + GL_RGBA, GL_UNSIGNED_BYTE, tex.bits()); + initDisplayLists(); +} + +void GLLandscape::resizeGL( int width, int height ) +{ + glViewport( 0, 0, width, height ); +} + +void GLLandscape::paintGL() +{ + TQString str; + GLboolean lighting; + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + switch ( mode ) { + case Wireframe: + drawWireframe(); + str = tr( "Wireframe" ); + break; + case Filled: + drawFilled(); + str = tr( "Flat shaded" ); + break; + case SmoothShaded: + str = tr( "Smooth shaded" ); + drawSmoothShaded(); + break; + case Landscape: + drawSmoothShaded(); + str = tr( "Landscape" ); + break; + } + glGetBooleanv( GL_LIGHTING, &lighting ); + if ( lighting ) + glDisable( GL_LIGHTING ); + qglColor( white ); + renderText(15, height() - 15, str); + drawAxis(); + drawCube(); + if ( lighting ) + glEnable( GL_LIGHTING ); +} + +void GLLandscape::drawAxis() +{ + glPushAttrib(GL_ALL_ATTRIB_BITS); + glViewport(15, 20, 50, 50); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(-1.1, 1.1, -1.1, 1.1, 0.1, 10); + glTranslatef(0, 0, -1.2); + glRotatef(-45, 1, 0, 0); + glRotatef(-45, 0, 0, 1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf((GLfloat *) views[AxisView].model); + + glCallList(axisList); + qglColor(white); + renderText(1.1f, 0, 0, "x"); + renderText(0, 1.1f, 0, "y"); + renderText(0, 0, 1.1f, "z"); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glPopAttrib(); +} + +void GLLandscape::drawCube() +{ + glPushAttrib(GL_ALL_ATTRIB_BITS); + glViewport(width()-75, 0, 75, 75); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glOrtho(-1.1, 1.1, -1.1, 1.1, 0.1, 10); + glTranslatef(0, 0, -1.2); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glRotatef(cubeRot, 1, 0, 0); + glRotatef(cubeRot, 0, 1, 0); + glRotatef(cubeRot, 0, 0, 1); + glTranslatef(-0.5, -0.5, -0.5); + + glCallList(cubeList); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glPopAttrib(); +} + +void GLLandscape::drawWireframe() +{ + qglColor( white ); + glBegin( GL_LINES ); + { + for ( int y = 0; y < (gridSize-1); y++ ) + for ( int x = 0; x < (gridSize-1); x++) { + glVertex3f( x-gridHalf, y-gridHalf, landscape[x][y] ); + glVertex3f( x+1-gridHalf, y-gridHalf, landscape[x+1][y] ); + glVertex3f( x-gridHalf, y-gridHalf, landscape[x][y] ); + glVertex3f( x+1-gridHalf, y+1-gridHalf, landscape[x+1][y+1] ); + + glVertex3f( x-gridHalf, y-gridHalf, landscape[x][y] ); + glVertex3f( x-gridHalf, y+1-gridHalf, landscape[x][y+1] ); + } + } + glEnd(); + glBegin( GL_LINE_STRIP ); + { + for ( int x = 0; x < gridSize; x++ ) { + glVertex3f( x-gridHalf, gridHalf-1, landscape[x][gridSize-1] ); + } + } + glEnd(); + glBegin( GL_LINE_STRIP ); + { + for ( int y = 0; y < gridSize; y++ ) { + glVertex3f( gridHalf-1, y-gridHalf, landscape[gridSize-1][y] ); + } + } + glEnd(); +} + +void GLLandscape::drawFilled() +{ + for ( int y = 0; y < gridSize-1; y++ ) + for ( int x = 0; x < gridSize-1; x++ ) { + qglColor( red ); + glBegin( GL_TRIANGLE_STRIP ); + { + glVertex3f(x-gridHalf,y-gridHalf, landscape[x][y]); + glVertex3f(x+1-gridHalf,y-gridHalf, landscape[x+1][y]); + glVertex3f(x-gridHalf,y+1-gridHalf, landscape[x][y+1]); + } + glEnd(); + qglColor( white ); + glBegin( GL_TRIANGLE_STRIP ); + { + glVertex3f(x+1-gridHalf,y-gridHalf, landscape[x+1][y]); + glVertex3f(x+1-gridHalf,y+1-gridHalf, landscape[x+1][y+1]); + glVertex3f(x-gridHalf,y+1-gridHalf, landscape[x][y+1]); + } + glEnd(); + } +} + +void GLLandscape::drawSmoothShaded() +{ + if ( mode == SmoothShaded ) { + GLfloat materialAmbient[] = { 0.00, 0.00, 1.0, 0.0 }; + GLfloat materialShininess[] = { 128.0 }; + GLfloat materialSpecular[] = { 1.0, 1.0, 1.0, 0.0 }; + + glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular ); + glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient ); + glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess ); + } else { + GLfloat materialAmbient[] = { 0.20, 0.33, 0.20, 0.0 }; + GLfloat materialShininess[] = { 1.0 }; + GLfloat materialSpecular[] = { 0.1, 0.1, 0.1, 0.1 }; + + glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular ); + glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient ); + glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess ); + } + + for ( int y = 0; y < gridSize-1; y++ ) + for ( int x = 0; x < gridSize-1; x++ ) { + glBegin( GL_POLYGON ); + { + glNormal3dv(vertexNormals[x][y].n); + glVertex3f(x-gridHalf,y-gridHalf,landscape[x][y]); + + glNormal3dv(vertexNormals[x+1][y].n); + glVertex3f(x+1-gridHalf, y-gridHalf, landscape[x+1][y]); + + glNormal3dv(vertexNormals[x+1][y+1].n); + glVertex3f(x+1-gridHalf, y+1-gridHalf, landscape[x+1][y+1]); + } + glEnd(); + + glBegin( GL_POLYGON ); + { + glNormal3dv(vertexNormals[x][y].n); + glVertex3f(x-gridHalf,y-gridHalf, landscape[x][y]); + + glNormal3dv(vertexNormals[x+1][y+1].n); + glVertex3f(x+1-gridHalf,y+1-gridHalf, landscape[x+1][y+1]); + + glNormal3dv(vertexNormals[x][y+1].n); + glVertex3f(x-gridHalf,y+1-gridHalf, landscape[x][y+1]); + } + glEnd(); + } + + // Draw water + if ( mode == Landscape ) { + GLfloat materialAmbient[] = { 0.00, 0.00, 1.0, 0.0 }; + GLfloat materialShininess[] = { 128.0 }; + GLfloat materialSpecular[] = { 1.0, 1.0, 1.0, 0.0 }; + + glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular ); + glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient ); + glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess ); + + glEnable( GL_BLEND ); + glBegin( GL_POLYGON ); + { + glNormal3f( 0, 0, 1 ); + glVertex3f( -gridHalf, -gridHalf, .2 ); + glNormal3f( 0, 0, 1 ); + glVertex3f( -gridHalf, gridHalf, .2 ); + glNormal3f( 0, 0, 1 ); + glVertex3f( gridHalf, gridHalf, .2 ); + glNormal3f( 0, 0, 1 ); + glVertex3f( gridHalf, -gridHalf, .2 ); + + } + glEnd(); + glDisable( GL_BLEND ); + } +} + +void GLLandscape::setGridSize( int size ) +{ + destroyGrid(); // destroy old grid + createGrid( size ); // create new grid + initializeGL(); + updateGL(); +} + +void GLLandscape::createGrid( int size ) +{ + if ( (size % 2) != 0 ) + size++; + gridSize = size; + gridHalf = gridSize / 2; + initFractals = TRUE; + landscape = new double*[gridSize]; + normals = new gridNormals*[gridSize]; + vertexNormals = new avgNormals*[gridSize]; + wt = new double*[gridSize]; + wave = new double*[gridSize]; + for ( int i = 0; i < gridSize; i++ ) { + landscape[i] = new double[gridSize]; + normals[i] = new gridNormals[gridSize]; + vertexNormals[i] = new avgNormals[gridSize]; + wt[i] = new double[gridSize]; + wave[i] = new double[gridSize]; + + memset( landscape[i], 0, gridSize*sizeof(double) ); + memset( normals[i], 0, gridSize*sizeof(gridNormals) ); + memset( vertexNormals[i], 0, gridSize*sizeof(avgNormals) ); + memset( wt[i], 0, gridSize*sizeof(double) ); + memset( wave[i], 0, gridSize*sizeof(double) ); + } +} + +void GLLandscape::destroyGrid() +{ + if ( landscape != NULL ) { + for( int i = 0; i < gridSize; i++ ) { + delete[] landscape[i]; + delete[] normals[i]; + delete[] vertexNormals[i]; + delete[] wt[i]; + delete[] wave[i]; + } + delete[] landscape; + delete[] normals; + delete[] vertexNormals; + delete[] wt; + delete[] wave; + } + landscape = 0; +} + +void GLLandscape::rotate( GLfloat deg, Axis axis ) +{ + makeCurrent(); + glMatrixMode( GL_MODELVIEW ); + for ( int i = DefaultView; i <= AxisView; i++ ) { + glLoadMatrixf((GLfloat *) views[i].model); + if ( axis == XAxis ) + glRotatef( deg, 1, 0, 0 ); + else if ( axis == YAxis ) + glRotatef( deg, 0, 1, 0 ); + else + glRotatef( deg, 0, 0, 1 ); + glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) views[i].model); + } + glLoadMatrixf((GLfloat *) views[CurrentView].model); +} + +void GLLandscape::rotateX( int deg ) +{ + static int oldDeg = 0; + + rotate( deg-oldDeg, XAxis ); + oldDeg = deg; + updateGL(); +} + +void GLLandscape::rotateY( int deg ) +{ + static int oldDeg = 0; + + rotate( deg-oldDeg, YAxis ); + oldDeg = deg; + updateGL(); +} + +void GLLandscape::rotateZ( int deg ) +{ + static int oldDeg = 0; + + rotate( deg-oldDeg, ZAxis ); + oldDeg = deg; + updateGL(); +} + +void GLLandscape::zoom( int z ) +{ + float zoom; + if ( z < 100 ) { + zoom = 1 + 4.99 - (z*5.0 / 100.0); + } else { + z = 200 - z; + zoom = z / 100.0; + } + makeCurrent(); + glMatrixMode( GL_MODELVIEW ); + // Always scale the original model matrix + glLoadMatrixf((GLfloat *) views[DefaultView].model); + glScalef( zoom, zoom, zoom ); + glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) views[CurrentView].model); + updateGL(); +} + +void GLLandscape::resetGrid() +{ + setGridSize( gridSize ); +} + +void GLLandscape::fractalize() +{ + Vector p; + double value; + double roughness = 0.5; + int frequency = 50; + + p.x = p.y = p.z = 0; + // Initialise fbm routine + if ( initFractals ) { + initFractals = FALSE; + value = fBm( p, roughness, 2.0, 8.0, 1 ); + } + + // Fractalize grid + for ( int x = 0; x < gridSize; x++ ) { + for ( int y = 0; y < gridSize; y++ ) { + p.x = (double) x / (101 - frequency); + p.y = (double) y / (101 - frequency); + p.z = (double) landscape[x][y] / (101 - frequency); + value = fBm(p, roughness, 2.0, 8.0, 0); + landscape[x][y] += value; + } + } + calculateVertexNormals(); + updateGL(); +} + + +// +// Calculate the vector cross product of v and w, store result in n. +// +static void crossProduct( double v[3], double w[3], double n[3] ) +{ + n[0] = v[1]*w[2]-w[1]*v[2]; + n[1] = w[0]*v[2]-v[0]*w[2]; + n[2] = v[0]*w[1]-w[0]*v[1]; +} + +void GLLandscape::calculateVertexNormals() +{ + double len, v[3], v2[3], w[3], w2[3], n[3], n2[3]; + + // Calculate the surface normals for all polygons in the + // height field + for ( int i = 0; i < (gridSize-1); i++ ) + for ( int k = 0; k < (gridSize-1); k++ ) { + /* Lower poly normal */ + v[0] = 1; // (i+1)-i + v[1] = 0; // k-k + v[2] = landscape[i+1][k]-landscape[i][k]; + w[0] = 1; // (i+1)-i + w[1] = 1; // (k+1)-k + w[2] = landscape[i+1][k+1]-landscape[i][k]; + crossProduct( v, w, n ); + len = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); + normals[i][k].l[0] = n[0]/len; + normals[i][k].l[1] = n[1]/len; + normals[i][k].l[2] = n[2]/len; + + /* Upper poly normal */ + v2[0] = -1.0; // i-(i+1); + v2[1] = 0.0; // (k+1)-(k+1); + v2[2] = landscape[i][k+1]-landscape[i+1][k+1]; + w2[0] = -1.0; // i-(i+1); + w2[1] = -1.0; // k-(k+1); + w2[2] = landscape[i][k]-landscape[i+1][k+1]; + crossProduct( v2, w2, n2 ); + len = sqrt(n2[0]*n2[0]+n2[1]*n2[1]+n2[2]*n2[2]); + normals[i][k].u[0] = n2[0]/len; + normals[i][k].u[1] = n2[1]/len; + normals[i][k].u[2] = n2[2]/len; + } + + // Calculate proper vertex normals + averageNormals(); +} + +void GLLandscape::averageNormals() +{ + // Calculate the average surface normal for a vertex based on + // the normals of the surrounding polygons + for ( int i = 0; i < gridSize; i++ ) + for ( int k = 0; k < gridSize; k++ ) { + if ( i > 0 && k > 0 && i < (gridSize-1) && k < (gridSize-1) ) { + // For vertices that are *not* on the edge of the height field + for ( int t = 0; t < 3; t++ ) // X, Y and Z components + vertexNormals[i][k].n[t] = ( normals[i][k].u[t] + + normals[i][k].l[t] + + normals[i][k-1].u[t] + + normals[i-1][k-1].u[t] + + normals[i-1][k-1].l[t] + + normals[i-1][k].l[t] )/6.0; + } else { + // Vertices that are on the edge of the height field retquire + // special attention.. + if ( i == 0 && k == 0 ) { + for ( int t = 0; t < 3; t++ ) + vertexNormals[i][k].n[t] = ( normals[i][k].u[t] + + normals[i][k].l[t] )/2.0; + } else if ( i == gridSize-1 && k == gridSize-1 ) { + for ( int t = 0; t < 3; t++ ) + vertexNormals[i][k].n[t] = ( normals[i][k].u[t] + + normals[i][k].l[t] )/2.0; + } else if ( i == gridSize-1) { + for ( int t = 0; t < 3; t++ ) + vertexNormals[i][k].n[t] = vertexNormals[i-1][k].n[t]; + } else if ( k == gridSize-1 ) { + for ( int t = 0; t < 3; t++ ) + vertexNormals[i][k].n[t] = vertexNormals[i][k-1].n[t]; + } else if ( k > 0 ) { + for ( int t = 0; t < 3; t++ ) + vertexNormals[i][k].n[t] = (normals[i][k].u[t] + + normals[i][k].l[t] + + normals[i][k-1].u[t])/3.0; + } else if ( i > 0 ) { + for ( int t = 0; t < 3; t++ ) + vertexNormals[i][k].n[t] = (normals[i][k].u[t] + + normals[i][k].l[t] + + normals[i-1][k].l[t])/3.0; + } + } + } +} + +void GLLandscape::setWireframe( int state ) +{ + if ( state != 1 ) { + // Enable line antialiasing + makeCurrent(); + glEnable( GL_LINE_SMOOTH ); + glEnable( GL_BLEND ); + glDisable( GL_DEPTH_TEST ); + glDisable( GL_LIGHTING ); + glDisable( GL_NORMALIZE ); + + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE ); + + mode = Wireframe; + updateGL(); + } +} + +void GLLandscape::setFilled( int state ) +{ + if ( state != 1 ) { + makeCurrent(); + glEnable( GL_DEPTH_TEST ); + glDisable( GL_LINE_SMOOTH ); + glDisable( GL_BLEND ); + glDisable( GL_LIGHTING ); + glDisable( GL_NORMALIZE ); + + mode = Filled; + updateGL(); + } +} + +void GLLandscape::setSmoothShaded( int state ) +{ + if ( state != 1 ) { + makeCurrent(); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_LIGHTING ); + glEnable( GL_LIGHT0 ); + glEnable( GL_NORMALIZE ); + glDisable( GL_LINE_SMOOTH ); + glDisable( GL_BLEND ); + + glShadeModel( GL_SMOOTH ); + glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE ); + + // Setup lighting and material properties + GLfloat position[] = { 15.0, -15.0, 15.0, 0.0 }; + GLfloat ambient[] = { 0.50, 0.50, 0.50, 0.0 }; + GLfloat diffuse[] = { 1.00, 1.00, 1.00, 0.0 }; + GLfloat specular[] = { 1.0, 1.0, 1.0, 0.0 }; + GLfloat materialAmbient[] = { 0.00, 0.00, 1.0, 0.0 }; + // GLfloat materialDiffuse[] = { 1.00, 1.00, 1.0, 0.0 }; + GLfloat materialShininess[] = { 128.0 }; + GLfloat materialSpecular[] = { 1.0, 1.0, 1.0, 0.0 }; + + glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular ); + // glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse ); + glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient ); + glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess ); + + glLightfv( GL_LIGHT0, GL_POSITION, position ); + glLightfv( GL_LIGHT0, GL_AMBIENT, ambient ); + glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse ); + glLightfv( GL_LIGHT0, GL_SPECULAR, specular ); + + mode = SmoothShaded; + calculateVertexNormals(); + updateGL(); + } +} + +void GLLandscape::setLandscape( int state ) +{ + if ( state != 1 ) { + makeCurrent(); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_LIGHTING ); + glEnable( GL_LIGHT0 ); + glEnable( GL_NORMALIZE ); + glDisable( GL_LINE_SMOOTH ); + glDisable( GL_BLEND ); + + glShadeModel( GL_SMOOTH ); + glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE ); + + // Setup lighting and material properties + GLfloat position[] = { 15.0, -15.0, 15.0, 0.0 }; + GLfloat ambient[] = { 0.50, 0.50, 0.50, 0.0 }; + GLfloat diffuse[] = { 1.00, 1.00, 1.00, 0.0 }; + GLfloat specular[] = { 1.0, 1.0, 1.0, 0.0 }; + + glLightfv( GL_LIGHT0, GL_POSITION, position ); + glLightfv( GL_LIGHT0, GL_AMBIENT, ambient ); + glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse ); + glLightfv( GL_LIGHT0, GL_SPECULAR, specular ); + + glBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR ); + + mode = Landscape; + calculateVertexNormals(); + updateGL(); + } +} + +void GLLandscape::mousePressEvent( TQMouseEvent *e ) +{ + oldPos = e->pos(); + mouseButtonDown = TRUE; +} + +void GLLandscape::mouseReleaseEvent( TQMouseEvent *e ) +{ + oldPos = e->pos(); + mouseButtonDown = FALSE; +} + +void GLLandscape::mouseMoveEvent( TQMouseEvent *e ) +{ + GLfloat rx = (GLfloat) (e->x() - oldPos.x()) / width(); + GLfloat ry = (GLfloat) (e->y() - oldPos.y()) / height(); + + if ( e->state() == LeftButton ) { + // Left button down - rotate around X and Y axes + oldX = 180*ry; + oldY = 180*rx; + rotate( oldX, XAxis ); + rotate( oldY, YAxis ); + updateGL(); + } else if ( e->state() == RightButton ) { + // Right button down - rotate around X and Z axes + oldX = 180*ry; + oldZ = 180*rx; + rotate( oldX, XAxis ); + rotate( oldZ, ZAxis ); + updateGL(); + } + oldPos = e->pos(); +} + +void GLLandscape::timerEvent( TQTimerEvent *e ) +{ + if (e->timerId() == cubeTimer) { + cubeRot += 1; + if (!animationRunning) + updateGL(); + return; + } + + int dx, dy; // disturbance point + float s, v, W, t; + int i, j; + + if ( mode == Landscape ) { + dx = dy = 0; + } else { + dx = dy = gridSize >> 1; + } + W = 0.3; + v = -4; // wave speed + + for ( i = 0; i < gridSize; i++ ) + for ( j = 0; j < gridSize; j++ ) + { + s = sqrt( (double) ( (j - dx) * (j - dx) + (i - dy) * (i - dy) ) ); + wt[i][j] += 0.1; + t = s / v; + + if ( mode == Landscape ) { + if ( (landscape[i][j] + wave[i][j]) < 0 ) + landscape[i][j] -= wave[i][j]; + if ( (dy - j != 0) || (dx - i != 0) ) + wave[i][j] = (3 * sin( 2 * PI * W * (wt[i][j] + t ))) / + (0.2*(sqrt( pow((double)(dx-i), 2) + pow((double)(dy-j), 2))+2)); + else + wave[i][j] = ( 3 * sin( 2 * PI * W * ( wt[i][j] + t ) ) ); + if ( landscape[i][j] + wave[i][j] < 0 ) + landscape[i][j] += wave[i][j]; + + } else { + landscape[i][j] -= wave[i][j]; + + if ( s != 0 ) + wave[i][j] = 2 * sin(2 * PI * W * ( wt[i][j] + t )) / + (0.2*(s + 2)); + else + wave[i][j] = 2 * sin( 2 * PI * W * ( wt[i][j] + t ) ); + landscape[i][j] += wave[i][j]; + } + + } + if ( mode == SmoothShaded || mode == Landscape ) + calculateVertexNormals(); + updateGL(); +} + +void GLLandscape::toggleWaveAnimation( bool state ) +{ + if (state) { + animTimer = startTimer(20); + animationRunning = TRUE; + } else { + killTimer(animTimer); + animationRunning = FALSE; + } +} + +void GLLandscape::showEvent( TQShowEvent * ) +{ + if (animationRunning) + animTimer = startTimer(20); + cubeTimer = startTimer(50); +} + +void GLLandscape::hideEvent( TQHideEvent * ) +{ + if (animationRunning) + killTimer(animTimer); + killTimer(cubeTimer); +} + +void GLLandscape::initDisplayLists() +{ + // axisList + axisList = glGenLists(1); + glNewList(axisList, GL_COMPILE); + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_DEPTH_TEST); + glColor3f(1.0, 0.0, 0.0); + glBegin(GL_LINES); + { + glColor3f(1.0, 0.0, 0.0); + glVertex3f(-1.0f, 0, 0); // x axis + glVertex3f(1.0f, 0, 0); + + glVertex3f(1.0f, 0, 0); + glVertex3f(0.8f, 0.2f, 0); + glVertex3f(1.0f, 0, 0); + glVertex3f(0.8f, -.2f, 0); + + glColor3f(0.0, 1.0, 0.0); + glVertex3f(0, -1.0f, 0); // y axis + glVertex3f(0, 1.0f, 0); + + glVertex3f(0, 1.0f, 0); + glVertex3f(0.2f, 0.8f, 0); + glVertex3f(0, 1.0f, 0); + glVertex3f(-0.2f, 0.8f, 0); + + glColor3f(0.5, 0.5, 1.0); + glVertex3f(0, 0, -1.0f); // z axis + glVertex3f(0, 0, 1.0f); + + glVertex3f(0, 0, 1.0f); + glVertex3f(0, 0.2f, 0.8f); + glVertex3f(0, 0, 1.0f); + glVertex3f(0,-0.2f, 0.8f); + } + glEnd(); + + glEndList(); + + // cubeList + cubeList = glGenLists(1); + glNewList(cubeList, GL_COMPILE); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); + + glBegin( GL_QUADS ); + { + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); + + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 ); + + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, 1.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 0.0, 0.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 0.0, 0.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); + + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 ); + + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 ); + + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 ); + glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 0.0, 1.0 ); + glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); + } + glEnd(); + glDisable(GL_TEXTURE_2D); + + glEndList(); +} |