zoukankan      html  css  js  c++  java
  • OpenGL_Qt学习笔记之_03(平面图形的着色和旋转)

           

      在这一节中主要简单介绍下怎样给平面几何着色,以及怎样让绘制出来的几何图形旋转起来。在上一节OpenGL_Qt学习笔记之_02(绘制简单平面几何图形) 中已经介绍了如何利用opengl画一些简单的图像,那么这一节就在上面的基础上给它着色,且让他旋转。

         实验基础

         首先来看着色,其实着色在上篇文章中已经用过,使用的是函数glColor3f()。一旦我们使用这个函数着色后且不更改颜色,则后面所绘的图形都是这个颜色了。我们给多边形着色时,表面上看都是给它的顶点着色,其实因为我们在initializeGL()函数中已经设置过glShapeModel(GL_SMOOTH),即颜色阴影是平滑模式。所以当我们给顶点设置后颜色后,其所构成的多边形内部就会按照一定规律自动填充颜色,且是平滑过渡。

         下面来看看旋转,首先是要了解opengl的一个三维空间,如下图所示:

      

         如果是按照X轴旋转的话,就是图中的指向视点那个轴了,NeHe教程中把沿x轴旋转比作成一台台钜,锯片中心的轴从左至右摆放,尖利的锯齿绕着X轴狂转,看起来要么向上转,要么向下转。把Y轴旋转比喻成巨大的龙卷风过程,龙卷风的中心从地面指向天空,垃圾和碎片围着Y轴从左向右或是从右向左狂转不止。把z轴旋转比喻成从正前方看着一台工作着的风扇。风扇的叶片绕着Z轴顺时针或逆时针狂转。这个比喻很形象。

         其实大家凭想象都能想出来是怎么转的,这里不再罗嗦了。Opengl中关于旋转使用的是函数:

      glRotatef( Angle, Xvector, Yvector, Zvector )

         Angle 通常是个变量代表对象转过的角度。 Xvector , Yvector 和 Zvector 三个参数则共同决定旋转轴的方向。比如(1,0,0)所描述的矢量经过X坐标轴的1个单位处并且方向向右。(-1,0,0)所描述的矢量经过X坐标轴的1个单位处,但方向向左。

         实验说明

         我在给圆着色时,每次给一个顶点赋值一种颜色,因为画圆是用三角形来逼近的,所以有很多顶点,且我这里给的顶点的颜色是随机赋值的,随机函数用的是Qt中自带的qrand(),

    qrand()%10表示产生0~9之间的整数,因此(GLfloat)(qrand()%10)/10则表示0.0~0.9之间的小数。

         在我这次试验中同样要注意,因为屏幕大小本身就2个单位的长和宽,所以设置旋转的轴时取值要适当,否则很难观察到旋转的效果。

         实验结果

         着色结果:

      

         旋转时截取的一张图效果:

      

         旋转的时候为了看到效果,可以不断改变窗口的大小,让GLWidget这个类不断执行paintGL()函数,实现重绘来看旋转效果。

         实验主要部分代码及解释(附录有工程code下载链接地址)。

         glwidget.cpp:

    #include "glwidget.h"
    #include "ui_glwidget.h"
    
    #include <QtGui>
    #include <QtCore>
    #include <QtOpenGL>
    
    #define GL_PI 3.1415926
    #define GL_RADIUX  0.2f
    
    GLWidget::GLWidget(QGLWidget *parent) :
        QGLWidget(parent),
        ui(new Ui::GLWidget)
    {
      //  setWindowTitle("The Opengl for Qt Framework");
        ui->setupUi(this);
        fullscreen = false;
        triangle_rotate = 0.0;
        quads_rotate = 0.0;
        circle_rotate = 0.0;
    }
    
    //这是对虚函数,这里是重写该函数
    void GLWidget::initializeGL()
    {
        setGeometry(300, 150, 500, 500);//设置窗口初始位置和大小
        glShadeModel(GL_SMOOTH);//设置阴影平滑模式
        glClearColor(0.0, 0.0, 0.0, 0.0);//改变窗口的背景颜色,不过我这里貌似设置后并没有什么效果
        glClearDepth(1.0);//设置深度缓存
        glEnable(GL_DEPTH_TEST);//允许深度测试
        glDepthFunc(GL_LEQUAL);//设置深度测试类型
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);//进行透视校正
    }
    
    void GLWidget::paintGL()
    {
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glClear()函数在这里就是对initializeGL()函数
                                                            //中设置的颜色和缓存深度等起作用
        glLoadIdentity();//重置当前的模型观察矩阵,该句执行完后,将焦点移动到了屏幕的中心
    
        /*下面几句代码是用来画三角形的,以glBegin()开始,glEnd()结束;glVertex3f为给定一个3维的顶点,坐标值为浮点型*/
        glTranslatef(-0.3, 0.3, -0.6);
        glRotatef(triangle_rotate, 0.2, 0.2, 0.0);//设置旋转的角度,这里为了观察,同时沿x轴和y轴做了旋转
        glBegin(GL_TRIANGLES);//GL_TRIANGLES代表为画三角形
        glVertex3f(0.0f, 0.2f, 0.0f);//上顶点坐标
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3f(-0.2f, -0.2f, 0.0f);//左下角坐标
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3f(0.2f, -0.2f, 0.0f);//右下角坐标
        glColor3f(0.0f, 0.0f, 1.0f);
        glEnd();//结束画完
        triangle_rotate += 0.05;  //为了看到动态效果,这里每次刷新后旋转的角度都加0.05
    
        glLoadIdentity();//重新焦点定位,同样是屏幕的中心
        glTranslatef(0.3f,0.3f,0.0f); // 向x轴正方向移动0.3个单位
        glRotatef(quads_rotate, 0.0, 0.2, 0.2);
        glColor3f(0.0f,1.0f,0.0f);//颜色设置放在这个地方,对下面的顶点设置都是有效的
    
        /*下面开始绘制四边形*/
        glBegin(GL_QUADS);
        glVertex3f(-0.2f, 0.2f, 0.0f); // 左上顶点
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3f( 0.2f, 0.2f, 0.0f); // 右上顶点
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3f( 0.2f, -0.2f, 0.0f); // 右下顶点
        glColor3f(0.0f, 0.0f, 1.0f);
        glVertex3f(-0.2f, -0.2f, 0.0f); // 左下顶点
        glColor3f(1.0f, 0.2f, 0.8f);
        glEnd(); // 四边形绘制结束
        quads_rotate += 0.05;
    
        glLoadIdentity();
        glTranslatef(0.0f, -0.3f, 0.0f);
        glColor3f(0.0f, 0.0f, 1.0f);
        glRotatef(circle_rotate, 0.2, 0.0, 0.2);
    
        /*这里用连续的三角形面积来逼近圆的面积实现圆周的画法*/
        GLint circle_points = 100, i = 0;
        glBegin(GL_TRIANGLE_FAN);
        for(int i = 0; i < circle_points; i++ )
        {
            double angle = 2*GL_PI*i/circle_points;
            //qrand()%10为产生0~10的整数,这里的颜色是随机产生的
            glColor3f((GLfloat)(qrand()%10)/10, (GLfloat)(qrand()%10)/10, (GLfloat)(qrand()%10)/10);
            glVertex3f(GL_RADIUX*cos(angle), GL_RADIUX*sin(angle), 0);
        }
        glEnd();
        circle_rotate += 0.05;
    
    }
    
    //该程序是设置opengl场景透视图,程序中至少被执行一次(程序启动时).
    void GLWidget::resizeGL(int width, int height)
    {
        if(0 == height)
            height = 1;//防止一条边为0
        glViewport(0, 0, (GLint)width, (GLint)height);//重置当前视口,本身不是重置窗口的,只不过是这里被Qt给封装好了
        glMatrixMode(GL_PROJECTION);//选择投影矩阵
        glLoadIdentity();//重置选择好的投影矩阵
       // gluPerspective(45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);//建立透视投影矩阵
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
    
    }
    void GLWidget::keyPressEvent(QKeyEvent *e)
    {
        switch(e->key())
        {
            //F1键为全屏和普通屏显示切换键
            case Qt::Key_F1:
                fullscreen = !fullscreen;
                if(fullscreen)
                    showFullScreen();
                else
                {
                    setGeometry(300, 150, 500, 500);
                    showNormal();
                }
                updateGL();
                break;
            //Ese为退出程序键
            case Qt::Key_Escape:
                close();
        }
    }
    
    GLWidget::~GLWidget()
    {
        delete ui;
    }

           

         总结:opengl中实现平面图形的着色和旋转,实现起来比较简单,只需要对对应的函数赋即可。

       参考资料:

       http://nehe.gamedev.net/ 

       http://www.owlei.com/DancingWind/

       http://blog.csdn.net/qp120291570/article/details/7853513

     

         附录:

         实验工程code下载

  • 相关阅读:
    Spring Cloud中关于Feign的常见问题总结
    Qt 格式转换问题 记录(好多方法)
    Qt事件机制(是动作发生后,一种通知对象的消息,是被动与主动的总和。先处理自己队列中的消息,然后再处理系统消息队列中的消息)
    Delphi 禁用x64位系统文件重定向功能
    QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用
    Qt 的几个核心机制总结之 布局(QWidget可以设置setSizePolicy,而QSizePolicy有Fixed,minimum,maximum,preferred,expanding,ignore等7个属性,还可以横竖分开)
    Dapper
    Yii2.0
    软件清单
    NET CORE 基础
  • 原文地址:https://www.cnblogs.com/tornadomeet/p/2653305.html
Copyright © 2011-2022 走看看