利用opengl画一个水波的曲面

1)首先说明一下静态水波的情况,静态水波其实可以看做是一个sin曲线旋转得到的曲面,从另一个角度上看,其实曲面就是在三维坐标中一系列sin曲线的聚合在一起的现象,而且这些曲线满足:

Opengl中的坐标系为右手系,设坐标系为X-Y-Z,则有对于每一个曲面而言都会有x = r *cos(2 * Pi / n *i), z = r * sin(2 * Pi/n *i), y = sin(r), 其中r的范围是x坐标的范围,n是曲线的条数,i代表了是第几条曲线;

具体在编程中实现如下:

 

其中(1.0 – x * factor)是为了实现波纹在远处的震荡越小而设置的,是一个递减函数来做为sin函数的幅值, sin(4*x)中的4是为了频率设置。

2)曲面的动态效果,可以理解为点的位移,也就是将sin(4*x*factor)改为sin(4*(x-num)*factor),num每次会移动的位移量,在opengl是通过为函数glutdleFunc()传递一个函数redisplay来实现的,redisplay函数每次都为将num值进行递增,也就是每次重画曲面的时候y的值都会平移变化,从而实现动态效果

代码如下:

/*
 * testopenglv1.cpp
 *
 *  Created on: 2015年9月27日
 *      Author: lenovo1
 */
#include <windows.h>
#include <GL/glut.h>
#include <math.h>

const GLfloat factor = 0.1f;
const GLfloat Pi = 3.1415926536f;
GLfloat num = 0.0f;
const int n = 400;
void myDisplay(void) {
    GLfloat x;
    //清除颜色,也就是将整个窗口清除为同一种颜色(黑色)
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0.5, 0.4, 0, 0, 0, 0, -0.5, 0.5);
    glBegin(GL_LINES);
    //设置线条的颜色
    glColor3f(0.2f, 0.5f, 0.6f);
    GLfloat eachPiece = 2 * Pi / n;
    //画n个线条来组成一个曲面,同时实现平移动画效果(num的平移)
    for (int i = 0; i < n; i += 1.0) {
        for (x = 0; x < 1.0f / factor; x += 0.01f) {
                glVertex3f(x*factor*cos(eachPiece * i), 2*(1.0-x*factor)*sin(4*x-num)*factor, x*factor*sin(eachPiece * i));
        }
    }
    glEnd();
    //双缓冲技术,会隐性的使用一次glFlush();
    glutSwapBuffers();
}

void redisplay() {
    num +=  0.1;
    glutPostRedisplay();
}

int main(int argc, char *argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

    glutInitWindowPosition(100, 100);
    glutInitWindowSize(800, 400);
    glutCreateWindow("水波");
    glutDisplayFunc(&myDisplay);
    glutIdleFunc(redisplay);

    glutMainLoop();
    return 0;
}

 

posted @ 2015-09-27 13:56  Kinthon  阅读(3836)  评论(0编辑  收藏  举报