📄 gllandscape.cpp
字号:
#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#endifGLLandscape::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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -