利用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; }