You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
881 lines
24 KiB
881 lines
24 KiB
14 years ago
|
#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( QWidget * parent, const char * name )
|
||
|
: QGLWidget( 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();
|
||
|
|
||
|
QImage tex;
|
||
|
tex.load("opengl/qtlogo.png");
|
||
|
tex = QGLWidget::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()
|
||
|
{
|
||
|
QString 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 require
|
||
|
// 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( QMouseEvent *e )
|
||
|
{
|
||
|
oldPos = e->pos();
|
||
|
mouseButtonDown = TRUE;
|
||
|
}
|
||
|
|
||
|
void GLLandscape::mouseReleaseEvent( QMouseEvent *e )
|
||
|
{
|
||
|
oldPos = e->pos();
|
||
|
mouseButtonDown = FALSE;
|
||
|
}
|
||
|
|
||
|
void GLLandscape::mouseMoveEvent( QMouseEvent *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( QTimerEvent *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( QShowEvent * )
|
||
|
{
|
||
|
if (animationRunning)
|
||
|
animTimer = startTimer(20);
|
||
|
cubeTimer = startTimer(50);
|
||
|
}
|
||
|
|
||
|
void GLLandscape::hideEvent( QHideEvent * )
|
||
|
{
|
||
|
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();
|
||
|
}
|