我是靠谱客的博主 忧郁美女,这篇文章主要介绍OpenGL-学习之路-简单二维几何变换及应用,现在分享给大家,希望可以做个参考。

简单二维几何变换


1. 回顾gluOrtho和glViewport


在OpenGL中,gluOtho和glViewport 为两个比较重要的投影变换函数。

-gluOrtho 是创建一个正交平行的视影体的矩阵,并把它与当前矩阵相乘,裁剪出要显示的部分。例如你画出了一个半径为1,中心点在圆点的二维图形圆形,gluOrtho2D作用在了 (0,1,0,1)。则最终显示了个1/4圆形。

-glViewport 则是定义了像素矩阵,最终图像将映射到该矩阵。例如,上面那个1/4圆形原本是显示在左下角,如果我们将glViewport  定义在(0,1,1,1),则该1/4圆形显示在了窗口的左上角。

简单来说: gluOrtho定义了显示的内容,glVieport则设置了显示的位置。

更详细内容:

http://www.cnblogs.com/yxnchinahlj/archive/2010/10/30/1865298.html

http://blog.csdn.net/lingedeng/article/details/7302204


2. 简单二维几何变换


简单二维几何的变换,可以通过 坐标变换 或 矩阵变换。两个方法各有长处,具体使用看实际情况。

下面是平移,旋转,缩放的简单二维图形变换。


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <glglut.h> #include <iostream> using namespace std; //transilate时,x,y上的增量 float i = 0,j=0; //rotate时的角度增量 GLint angle=0; //scale时,x,y上的增量 float s1 = 1, s2 = 1; void init() { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, 600.0, 0.0, 600.0); } void display() { glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(300+i, 300+j, 0); glRotatef(angle % 360, 0, 0, 1); glScalef(s1, s2, 0); glColor3f(0, 0.6, 0.5); glRectf(-100, 100, 100, -100); glFlush(); glutSwapBuffers(); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 'w': j++; break; case 's': j--; break; case 'a': i--; break; case 'd': i++; break; case 'q': angle += 10; break; case 'e': angle -= 10; break; case 'z': s1 += 0.1; break; case 'x': s2 += 0.1; break; case 'c': s1 -= 0.1; break; case 'v': s2 -= 0.1; break; } glutPostRedisplay(); } void main(int argc, char ** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(400, 50); glutInitWindowSize(600, 600); glutCreateWindow("Computer Graphics: 二维几何变换"); init(); glutDisplayFunc(display); cout << " w,s,a,d键 分别为上下左右平移" << endl; cout << " q,e键 分别为放大,缩小" << endl; cout << " z,x,c,v键 分别为长宽的放大缩小" << endl; glutKeyboardFunc(keyboard); glutMainLoop(); }


最后效果:



3. 应用——Sun,Earth,Moon


内容:画出三个圆分别代表,太阳,地球,月球,并且地球绕着太阳旋转,月亮绕着地球旋转。


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <glglut.h> #include <math.h> //旋转角度 GLint angle = 30; //地球旋转半径 GLdouble r1 = 100; //月球旋转半径 GLdouble r2 = 40; void init() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, 600.0, 0.0, 600.0); } //画圆函数,传入中心点坐标(x,y),以及半径r void drawCircle(double x, double y, double r) { double N = 30; //把圆N等分,则每一等分为 360/N=2Pi/N , 则旋转角度为 i*360/N=2*Pi*i/N double delta = 3.1415926*2.0 / N; glBegin(GL_TRIANGLE_FAN); for (int i = 0; i <= N; i++) { glVertex2f(x, y); glVertex2f(x + r*cos(delta*i), y + r*sin(delta*i)); glVertex2f(x + r*cos(delta*(i + 1)), y + r*sin(delta*(i + 1))); } glEnd(); } //坐标变换 void run() { glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //太阳 glColor3f(1.0f, 0.0f, 0.0f); drawCircle(300, 300, 20); //地球 int x0, y0; x0 = 300 + r1*cos((3.1415926*2.0 / 360)*(angle % 360)); y0 = 300 + r1*sin((3.1415926*2.0 / 360)*(angle % 360)); glColor3f(0.0, 0.5, 1.0); drawCircle(x0, y0, 15); //月球 int x1, y1; x1 = x0 + r2*cos((3.1415926*2.0 / 360)*(angle * 12 % 360)); y1 = y0 + r2*sin((3.1415926*2.0 / 360)*(angle * 12 % 360)); glColor3f(1.0, 1.0, 1.0); drawCircle(x1, y1, 5); glFlush(); glutSwapBuffers(); } //矩阵变换 /* void run() { glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //太阳 glTranslatef(300.0f, 300.0f, 0.0f); glColor3f(1.0f, 0.0f, 0.0f); drawCircle(0, 0, 20); //地球 glRotatef(angle % 360, 0, 0, 1); glTranslatef(r1, 0, 0); glColor3f(0.0f, 0.5f, 1.0f); drawCircle(0, 0, 15); //月球 glRotatef(angle * 12 % 360, 0, 0, 1); glTranslatef(r2, 0, 0); glColor3f(1.0f, 1.0f, 1.0f); drawCircle(0, 0, 5); glFlush(); glutSwapBuffers(); } */ void idle() { angle++; glutPostRedisplay(); } void main(int argc, char ** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(400, 50); glutInitWindowSize(600, 600); glutCreateWindow("Computer Graphics: Sun,Earth,Moon"); init(); glutDisplayFunc(run); glutIdleFunc(idle); glutMainLoop(); }


最后效果:


4, 应用——简单自行车动画


内容: 实现自行车模型在一个方向上的运动(轮子的滚动速度与自行车前进距离合适)


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <glglut.h> #include <math.h> #include <iostream> using namespace std; //自行车中心点坐标 double x = 100, y = 330; //车轮半径 double r = 30; //自行车旋转角,及旋转角速度 GLint angle = 0; GLint angleSpeed = 10; void init() { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, 600.0, 0.0, 600.0); } //画圆函数,传入中心点坐标(x,y),以及半径r void drawCircle(double x, double y, double r) { double N = 8; //把圆N等分,则每一等分为 360/N=2Pi/N double delta = 3.1415926*2.0 / N; //x0,y0,x1,y1分别代表该圆中第i和i+1个顶点的坐标,tmpx1,tmpy1,tmpx2,tmpy2则分别为对应顶点旋转后坐标. double x0, y0, x1, y1, tmpx1, tmpy1, tmpx2, tmpy2; glBegin(GL_LINE_LOOP); for (int i = 0; i <= N; i++) { //第i个顶点坐标 x0 = x + r*cos(delta*i); y0 = y + r*sin(delta*i); //旋转计算 tmpx1 = x + (x0 - x)*cos(angle % 360) - (y0 - y)*sin(angle % 360); tmpy1 = y + (x0 - x)*sin(angle % 360) + (y0 - y)*cos(angle % 360); //第i+1个顶点坐标 x1 = x + r*cos(delta*(i + 1)); y1 = y + r*sin(delta*(i + 1)); //旋转计算 tmpx2 = x + (x1 - x)*cos(angle % 360) - (y1 - y)*sin(angle % 360); tmpy2 = y + (x1 - x)*sin(angle % 360) + (y1 - y)*cos(angle % 360); glVertex2f(x, y); glVertex2f(tmpx1, tmpy1); glVertex2f(tmpx2, tmpy2); } glEnd(); } //坐标变换 void DisplayFunc() { glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //陆地横线 glColor3f(0.0, 0.0, 0.0); glBegin(GL_LINES); glVertex2i(0, 300); glVertex2i(600, 300); glEnd(); //自行车前后轮 //x0,y0为后轮中心点的x,y坐标 double x0, y0; x0 = x + 2 * 3.1415926*r*(double)angle / 360; drawCircle(x0, y, r); drawCircle(x0 + 90, y, r); //自行车横杠把手部分 glColor3f(0.0, 0.0, 0.0); glBegin(GL_LINES); glVertex2i(x0, y); glVertex2i(x0 + 90, y); glVertex2i(x0 + 90, y); glVertex2i(x0 + 44, y + 120); glVertex2i(x0 + 66, y + 144); glVertex2i(x0 + 44, y + 120); glVertex2i(x0 + 22, y + 96); glVertex2i(x0 + 44, y + 120); glEnd(); glFlush(); glutSwapBuffers(); } void MouseFunc(GLint button, GLint action, GLint x, GLint y) { if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) { angle += angleSpeed; glutPostRedisplay(); } if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN) { angle -= angleSpeed; glutPostRedisplay(); } } void main(int argc, char ** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(400, 50); glutInitWindowSize(600, 600); glutCreateWindow("Computer Graphics:Bike"); init(); glutDisplayFunc(DisplayFunc); cout << "鼠标左键前进,右键后退" << endl; glutMouseFunc(MouseFunc); glutMainLoop(); }

最后效果:



最后

以上就是忧郁美女最近收集整理的关于OpenGL-学习之路-简单二维几何变换及应用的全部内容,更多相关OpenGL-学习之路-简单二维几何变换及应用内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(91)

评论列表共有 0 条评论

立即
投稿
返回
顶部