📄 gllandscape.cpp
字号:
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 * ){ 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 ) { startTimer( 20 ); animationRunning = TRUE; } else { killTimers(); animationRunning = FALSE; }}void GLLandscape::showEvent( QShowEvent * ){ if ( animationRunning ) startTimer( 20 ); }void GLLandscape::hideEvent( QHideEvent * ){ if ( animationRunning ) killTimers();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -