学习OpenGL也有段时间了,前几篇将GL最基本的画图过程解析了一下,后面进阶的就随项目需要再学。因为之前一直是用glut这个实用工具包来开发很方便,但是会附带一个控制台的窗口,实在觉得有些low,因此就打算将GL嵌入到应用程序中去。
下面就把前几章学习的知识结合起来,在QT下实现GL的动画。之所以选QT而非MFC原因有2点,一则是QT是开源的,现在开源的东西都很热闹,所以我也凑凑热闹,之前用MFC做过别的上位机程序,我是个喜欢图新鲜的人;二则QT的移植性好,一次编译到处运行吧。
总结几处注意点:
1.glut的函数是一个也不能使用了,需要自己用QT的Widget类来创建应用窗口,同时再用QGLWidget类创建自己的GL类,将二者绑定在一起;
2.需要重载QGLWidget的三个重要函数initializeGL、resizeGL和paintGL;
3.glClear函数不属于initializeGL,即即使你写入它,在初始化的时候也不会被执行;
4.需要显示裁剪视口以及设定透视方法,这些在之前使用glut中函数的时候会被默认设置和创建窗口匹配。什么意思呢?就是如果不显示设定的话,你会被坐标定位搞得糊里糊涂。这个也是我第一次移植时候遇到的困扰,其实程序是正常运行的,但是要嘛图像歪斜要嘛看不到图像。如果以上一些设置成功,就能随心所欲绘制;
5.glut中的消息响应在QT中都有各自的类;
6.QT的类不比MFC类来的“苗条”,用到哪个查找哪个就ok。
最后上代码。
功能说明文件:
1 --use keyboard to control the cube 2 -w- accelerate the rolling speed; 3 -s- slow down the rolling speed; 4 -a- change the rolling direction; 5 -d- opposite with -a-; 6 -r- reset the initial state; 7 -c- change color
主函数文件:
1 #include<QApplication> 2 #include"myglwidget.h" 3 int main(int argc,char *argv[]) 4 { 5 QApplication MyApp(argc,argv); 6 MyGLWidget MyGL; 7 MyGL.show(); 8 return MyApp.exec(); 9 }
自定义GL类头文件:
1 #ifndef MYGLWIDGET_H 2 #define MYGLWIDGET_H 3 4 #include <QGLWidget> 5 #include<QTime> 6 #include<QTimerEvent> 7 #include<QKeyEvent> 8 class MyGLWidget : public QGLWidget 9 { 10 Q_OBJECT 11 public: 12 explicit MyGLWidget(QWidget *parent = 0); 13 14 signals: 15 private: 16 // GLfloat VertexData[24]; 17 // GLubyte VertexIndex[6][4]; 18 float m_rotate; 19 float m_speed; 20 bool m_angle; 21 GLubyte m_color_mode; 22 int m_T20msID; 23 void initializeGL(); 24 void resizeGL(int w, int h); 25 void paintGL(); 26 void timerEvent(QTimerEvent *); 27 void keyPressEvent(QKeyEvent *); 28 void Cross(GLfloat,GLubyte); 29 void ChangeColor(GLubyte mode,GLfloat value); 30 float GetRand(int,int); 31 void Draw(void); 32 void Cube(void); 33 public slots: 34 }; 35 36 #endif // MYGLWIDGET_H
自定义GL类实现:
1 #include "myglwidget.h" 2 static GLfloat VertexData[] = { 3 -0.5f, -0.5f, -0.5f, 4 0.5f, -0.5f, -0.5f, 5 -0.5f, 0.5f, -0.5f, 6 0.5f, 0.5f, -0.5f, 7 -0.5f, -0.5f, 0.5f, 8 0.5f, -0.5f, 0.5f, 9 -0.5f, 0.5f, 0.5f, 10 0.5f, 0.5f, 0.5f, 11 }; 12 static GLubyte VertexIndex[][4] = { 13 0, 2, 3, 1, 14 0, 4, 6, 2, 15 0, 1, 5, 4, 16 4, 5, 7, 6, 17 1, 3, 7, 5, 18 2, 6, 7, 3, 19 }; 20 MyGLWidget::MyGLWidget(QWidget *parent) : 21 QGLWidget(parent) 22 { 23 m_speed = 2.0; 24 m_angle = 0; 25 m_color_mode = 0; 26 m_rotate = 0; 27 m_T20msID = 0; 28 } 29 void MyGLWidget::initializeGL() 30 { 31 glClearColor(0,0,0,0); 32 glClearDepth(1); 33 glEnable(GL_DEPTH_TEST); 34 glDepthFunc(GL_LEQUAL); 35 m_T20msID = startTimer(20); 36 qsrand(QTime::currentTime().msec()); 37 } 38 void MyGLWidget::resizeGL(int w, int h) 39 { 40 glViewport(0,0,w,h); 41 glMatrixMode(GL_PROJECTION); 42 glLoadIdentity(); 43 if(w <= h) 44 glOrtho(-1, 1, -(GLfloat)h/(GLfloat)w, (GLfloat)h/(GLfloat)w, -1, 1); 45 else 46 glOrtho(-(GLfloat)w/(GLfloat)h, (GLfloat)w/(GLfloat)h, -1, 1, -1, 1); 47 } 48 void MyGLWidget::paintGL() 49 { 50 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 51 glMatrixMode(GL_MODELVIEW); 52 glLoadIdentity(); 53 Draw(); 54 } 55 void MyGLWidget::Cube(void) 56 { 57 //enable vertex_array 58 glEnableClientState(GL_VERTEX_ARRAY); 59 //load vertex_array data 60 glVertexPointer(3,GL_FLOAT,3*sizeof(GLfloat),VertexData); 61 //drawing operation 62 glDrawElements(GL_QUADS,sizeof(VertexData),GL_UNSIGNED_BYTE,VertexIndex); 63 } 64 void MyGLWidget::timerEvent(QTimerEvent *event) 65 { 66 if(m_T20msID == event->timerId()) 67 { 68 updateGL(); 69 } 70 } 71 float MyGLWidget::GetRand(int start, int end) 72 { 73 return start + (end - start)*qrand()/(RAND_MAX + 1.0); 74 } 75 void MyGLWidget::Cross(GLfloat coordinater,GLubyte face) 76 { 77 GLfloat rand; 78 switch(face) 79 { 80 //front 81 case 0: rand = (GetRand(0,10)-5)/10; 82 glBegin(GL_LINES); 83 glVertex3f(-0.5f,rand,coordinater); 84 glVertex3f(0.5f,rand,coordinater); 85 glEnd(); 86 rand = (GetRand(0,10)-5)/10; 87 glBegin(GL_LINES); 88 glVertex3f(rand,0.5f,coordinater); 89 glVertex3f(rand,-0.5f,coordinater); 90 glEnd(); 91 break; 92 //left 93 case 1: rand = (GetRand(0,10)-5)/10; 94 glBegin(GL_LINES); 95 glVertex3f(coordinater,-0.5f,rand); 96 glVertex3f(coordinater,0.5f,rand); 97 glEnd(); 98 rand = (GetRand(0,10)-5)/10; 99 glBegin(GL_LINES); 100 glVertex3f(coordinater,rand,0.5f); 101 glVertex3f(coordinater,rand,-0.5f); 102 glEnd(); 103 break; 104 case 2: rand = (GetRand(0,10)-5)/10; 105 glBegin(GL_LINES); 106 glVertex3f(-0.5f,coordinater,rand); 107 glVertex3f(0.5f,coordinater,rand); 108 glEnd(); 109 rand = (GetRand(0,10)-5)/10; 110 glBegin(GL_LINES); 111 glVertex3f(rand,coordinater,0.5f); 112 glVertex3f(rand,coordinater,-0.5f); 113 glEnd(); 114 break; 115 default:break; 116 } 117 } 118 void MyGLWidget::Draw() 119 { 120 m_rotate += (m_angle)?m_speed:-m_speed; 121 glRotatef(m_rotate,1,0,0); 122 glRotatef(m_rotate,0,1,0); 123 glRotatef(m_rotate,0,0,1); 124 glColor3f(0,0,0); 125 //front-red 126 Cube(); 127 int i; 128 for(i=0;i<50;i++) 129 { 130 //glColor3f(0,GetRand(0,33)/100,0); 131 ChangeColor(m_color_mode,GetRand(0,20)/100); 132 glLineWidth(GetRand(1,10)); 133 Cross(0.5f,0); 134 } 135 //back-green 136 for(i=0;i<50;i++) 137 { 138 //glColor3f(0,GetRand(0,20)/100,0); 139 ChangeColor(m_color_mode,GetRand(0,20)/100); 140 glLineWidth(GetRand(1,10)); 141 Cross(-0.5f,0); 142 } 143 //left-blue 144 for(i=0;i<50;i++) 145 { 146 //glColor3f(0,GetRand(46,66)/100,0); 147 ChangeColor(m_color_mode,GetRand(46,66)/100); 148 glLineWidth(GetRand(1,10)); 149 Cross(-0.5f,1); 150 } 151 //right 152 for(i=0;i<50;i++) 153 { 154 //glColor3f(0,GetRand(33,66)/100,0); 155 ChangeColor(m_color_mode,GetRand(46,66)/100); 156 glLineWidth(GetRand(1,10)); 157 Cross(0.5f,1); 158 } 159 //up 160 for(i=0;i<50;i++) 161 { 162 //glColor3f(0,GetRand(80,100)/100,0); 163 ChangeColor(m_color_mode,GetRand(80,100)/100); 164 glLineWidth(GetRand(1,10)); 165 Cross(0.5f,2); 166 } 167 //bottom 168 for(i=0;i<50;i++) 169 { 170 //glColor3f(0,GetRand(66,100)/100,0); 171 ChangeColor(m_color_mode,GetRand(80,100)/100); 172 glLineWidth(GetRand(1,10)); 173 Cross(-0.5f,2); 174 } 175 176 } 177 void MyGLWidget::ChangeColor(GLubyte mode,GLfloat value) 178 { 179 switch(mode) 180 { 181 case 0:glColor3f(0,value,0); 182 break; 183 case 1:glColor3f(value,0,0); 184 break; 185 case 2:glColor3f(0,0,value); 186 break; 187 case 3:glColor3f(value,value,0); 188 break; 189 case 4:glColor3f(value,0,value); 190 break; 191 case 5:glColor3f(0,value,value); 192 break; 193 case 6:glColor3f(value,value,value); 194 default:break; 195 } 196 } 197 void MyGLWidget::keyPressEvent(QKeyEvent *event) 198 { 199 switch(event->key()) 200 { 201 case Qt::Key_A:m_angle = 1; 202 break; 203 case Qt::Key_W:m_speed += 0.5; 204 break; 205 case Qt::Key_D:m_angle = 0; 206 break; 207 case Qt::Key_S:if((m_speed-0.25)<0) 208 m_speed = 0; 209 else 210 m_speed -= 0.25; 211 break; 212 case Qt::Key_R:m_speed = 2; 213 m_angle = 1; 214 break; 215 case Qt::Key_C:if(m_color_mode == 6) 216 m_color_mode = 0; 217 else 218 m_color_mode++; 219 break; 220 case Qt::Key_F:showFullScreen(); 221 break; 222 case Qt::Key_Escape:close(); 223 default:break; 224 } 225 }