使用opengl制作一个简单的由线组成的荡漾的水波

时间:2022-09-10 17:12:08

    先说一下大题思路:水波,我们取出他的横切面其实就是一条曲线,所以在绘制的时候我们可以使用多个三角函数以及其他函数的叠加来实现这条曲线,我们从上到下去看这个水波,其实就是一个圆,可以理解是n个横切面的合成。综上所述,所以我们可以直接构造多条曲线去合成我们的水波,至于使波纹往外边荡漾出去,我们通过每个切面的位移来实现。

     说回代码实现,首先,通过glutInit(&argc, argv)进行初始化,然后设置窗口位置和大小,和标题,接着调用一个glutReshapeFunc调用自己写的myReshape去规定视图:

1 void myReshape(GLsizei w, GLsizei h) {
2     // if the height is large than w, we should use the glViewport to adjust it 
3     if (w < h) {       
4         glViewport(0, 0, w, w);
5     } else {
6         glViewport(0, 0, w, h);
7     }
8 }

    然后使用glutDisplayFunc去调用你的display函数去绘制图形:

 1 void myDisplay(void) {
 2     GLfloat x;
 3     //set the backgroud color
 4     glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
 5     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 6     //set the point we look it
 7     glMatrixMode(GL_MODELVIEW);
 8     //replaces the current matrix with the identity matrix
 9     glLoadIdentity();
10     gluLookAt(0, -0.5, 0.4, 0, 0, 0, 0, 0, 0.5);
11 
12     glBegin(GL_LINES);
13     //set the color of the line
14     glColor3f(0.5f, 1.0f, 1.0f);
15     //draw the line
16     for (float i = 0.0f; i < 360.0; i += 3.0) {
17         for (x = 0; x < 1.0f / factor; x += 0.01f) {        
18                 glVertex3f(x*factor*cos(i), cos(2 * x-num)*factor, x*factor*sin(i));
19         }
20     }
21     glEnd();
22     glFlush();
23     glutSwapBuffers();
24 }

    其中 glClearColor(0.7f, 0.7f, 0.7f, 1.0f) 是规定了背景颜色。 gluLookAt(0, -0.5, 0.4, 0, 0, 0, 0, 0, 0.5)规定了你的视角,就是你从哪个角度去看。注意,这里要加上glMatrixMode(GL_MODELVIEW) 和glLoadIdentity(),前一个规定了处理模式,第二行是恢复初始坐标系,不加的话绘出的图像会很怪(参见http://blog.csdn.net/shuaihj/article/details/7228265)。

   画图的时候我设置了线的颜色为0.5f, 1.0f, 1.0f, 然后通过一个for循环画120条线,对于每条线,都是以坐标原点为起点,x*factor*cos(i)为X轴坐标,x*factor*sin(i)为Z轴坐标,cos(2 * x-num)*factor为y轴坐标,水波荡漾的效果就是通过改变num的值,实现不断位移实现的。glutSwapBuffers()用于实现双缓冲,这样子动画效果更好,不卡顿。

   为了实现动画,用glutIdleFunc调用你的动画函数spinCube:

1 void spinCube() {
2     num = num + 0.1;
3     glutPostRedisplay();
4 }

 

    glutPostRedisplay 标记当前窗口需要重新绘制,num用于改变每次循环时候的位移位置。

    最后调用glutMainLoop()进行循环即可大功告成。

效果如下(截图看不出荡漾效果):

  使用opengl制作一个简单的由线组成的荡漾的水波  使用opengl制作一个简单的由线组成的荡漾的水波

详细代码如下:

 

 1 #include <GL/glut.h>
 2 #include <math.h>
 3 
 4 const GLfloat factor = 0.1f;
 5 GLfloat num = 0.0f;
 6 void myDisplay(void) {
 7     GLfloat x;
 8     //set the backgroud color
 9     glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
10     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
11     //set the point we look it
12     glMatrixMode(GL_MODELVIEW);
13     //replaces the current matrix with the identity matrix
14     glLoadIdentity();
15     gluLookAt(0, -0.5, 0.4, 0, 0, 0, 0, 0, 0.5);
16 
17     glBegin(GL_LINES);
18     //set the color of the line
19     glColor3f(0.5f, 1.0f, 1.0f);
20     //draw the line
21     for (float i = 0.0f; i < 360.0; i += 3.0) {
22         for (x = 0; x < 1.0f / factor; x += 0.01f) {        
23                 glVertex3f(x*factor*cos(i), cos(2 * x-num)*factor, x*factor*sin(i));
24         }
25     }
26     glEnd();
27     glFlush();
28     glutSwapBuffers();
29 }
30 
31 void spinCube() {
32     num = num + 0.1;
33     glutPostRedisplay();
34 }
35 
36 void myReshape(GLsizei w, GLsizei h) {
37     // if the height is large than w, we should use the glViewport to adjust it 
38     if (w < h) {       
39         glViewport(0, 0, w, w);
40     } else {
41         glViewport(0, 0, w, h);
42     }
43 }
44 
45 int main(int argc, char *argv[]) {
46     // init
47     glutInit(&argc, argv);
48     //set mode
49     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
50     //set the position
51     glutInitWindowPosition(100, 100);
52     //set the width and weigth
53     glutInitWindowSize(1200, 700);
54     glutCreateWindow("很荡漾的水波");
55     glutReshapeFunc(myReshape);
56     glutDisplayFunc(&myDisplay);
57     //to set the action
58     glutIdleFunc(spinCube);
59     //loop
60     glutMainLoop();
61     return 0;
62 }