精华内容
下载资源
问答
  • opengl绘制三维图形
    千次阅读
    2021-06-03 04:29:26

    从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发。

    OpenGL的全称是“Open Graphics Library”,意思是开放图形库,它定义了一个跨语言、跨平台的图形图像程序接口。对于Android开发者来说,OpenGL就是用来绘制三维图形的技术手段,当然OpenGL并不仅限于展示静止的三维图形,也能用来播放运动着的三维动画。不管是三维图形还是三维动画,都是力求在二维的手机屏幕上面展现模拟的真实世界场景,这个OpenGL的应用方向说到底,可不就是时下大热的虚拟现实么?

    eac80b7c6b274550e057bb6e692e725d.png

    看起来OpenGL是很高大上的样子,其实Android系统早已集成了相关的API,只要开发者按照函数要求依次调用,就能一步一步在手机屏幕上画出各式各样的三维物体了。不过对于初次接触OpenGL的开发者来说,三维绘图的概念可能过于抽象,所以为了方便读者理解,下面就以Android上的二维图形绘制为参考,亦步亦趋地逐步消化OpenGL的相关知识点。

    从前面的学习可以得知,每个Android界面上的控件,其实都是在某个视图上绘制规定的文字(如TextView),或者绘制指定的图像(如ImageView)。而TextView和ImageView都继承自基本视图View,这意味着首先要有一个专门的绘图场所,比如现实生活中的黑板、画板和桌子。然后还要有绘画作品的载体,比如显示生活中黑板的漆面,以及用于国画的宣纸、用于油画的油布等等,在Android系统中,这个绘画载体便是画布Canvas。有了绘图场所和绘画载体,还得有一把绘图工具,不管是勾勒线条还是涂抹颜料都少不了它,如果是写黑板报则有粉笔,如果是画国画则有毛笔,如果是画油画则有油画笔,如果是画Android控件则有画笔Paint。

    所以,只要具备了绘图场所、绘画载体、绘图工具,即可挥毫泼墨进行绘画创作啦。正如前面介绍的Android自定义控件那样,有了视图View、画布Canvas、画笔Paint,方能绘制炫彩多姿的各种控件。那么对于OpenGL的三维绘图来说,也同样需要具备这三种要素,分别是GLSurfaceView、GLSurfaceView.Renderer和GL10,其中GLSurfaceView继承自表面视图SurfaceView,对应于二维绘图的View;GLSurfaceView.Renderer是三维图形的渲染器,对应于二维绘图的Canvas;最后一个GL10自然相当于二维绘图的Paint了。有了GLSurfaceView、GLRender和GL10这三驾马车,Android才能实现OpenGL的三维图形渲染功能。

    具体到App编码上面,还得将GLSurfaceView、GLSurfaceView.Renderer和GL10这三个类有机结合起来,即通过函数调用关联它们三个小伙伴。首先从布局文件获得GLSurfaceView的控件对象,然后调用该对象的setRenderer方法设置三维渲染器,这个三维渲染器实现了GLSurfaceView.Renderer定义的三个视图函数,分别是onSurfaceCreated、onSurfaceChanged和onDrawFrame,这三个函数的输入参数都包含GL10,也就是说这三个函数都持有画笔对象。如此一来,绘图三要素的GLSurfaceView、GLSurfaceView.Renderer和GL10就互相关联了起来。

    可是,Renderer接口定义的onSurfaceCreated、onSurfaceChanged和onDrawFrame三个函数很是陌生,它们之间又有什么区别呢?为方便理解,接下来不妨继续套用Android二维绘图的有关概念,从Android自定义控件的主要流程得知,自定义一个二维控件,主要有以下四个步骤:

    1、声明自定义控件的构造函数,可在此进行控件属性初始赋值等初始化操作;

    2、重写onMeasure函数,可在此测量控件的宽度和高度;

    3、重写onLayout函数,可在此挪动控件的位置;

    4、重写onDraw函数,可在此绘制控件的形状、颜色、文字以及图案等等;

    于是前面提到Renderer接口定义的三个函数,它们的用途对照说明如下:

    1、onSurfaceCreated函数在GLSurfaceView创建时调用,相当于自定义控件的构造函数,一样可在此进行三维绘图的初始化操作;

    2、onSurfaceChanged函数在GLSurfaceView创建、恢复与改变时调用,在这里不但要定义三维空间的大小,还要定义三维物体的方位,所以该函数相当于完成了自定义控件的onMeasure和onLayout两个函数的功能;

    3、onDrawFrame顾名思义跟自定义控件的onDraw函数差不多,onDraw函数用于绘制二维图形的具体形状,而onDrawFrame函数用于绘制三维图形的具体形状;

    下面来个最简单的OpenGL例子,在布局文件中放置一个android.opengl.GLSurfaceView节点,后续的三维绘图动作将在该视图上开展。布局文件内容示例如下:

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

    android:id="@+id/glsv_content"

    android:layout_width="match_parent"

    android:layout_height="match_parent" />

    接着在Activity代码中获取这个GLSurfaceView对象,并给它注册一个三维图形的渲染器GLRender,此时自定义的渲染器GLRender必须重载onSurfaceCreated、onSurfaceChanged和onDrawFrame这三个函数。下面是对应的Activity代码框架例子:@Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_gl_cub);

    GLSurfaceView glsv_content = (GLSurfaceView) findViewById(R.id.glsv_content);

    // 注册渲染器

    glsv_content.setRenderer(new GLRender());

    }

    private class GLRender implements GLSurfaceView.Renderer {

    @Override

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    // 这里进行三维绘图的初始化操作

    }

    @Override

    public void onSurfaceChanged(GL10 gl, int width, int height) {

    // 这里要定义三维空间的大小,还要定义三维物体的方位

    }

    @Override

    public void onDrawFrame(GL10 gl) {

    // 这里绘制三维图形的具体形状

    }

    }

    更多相关内容
  • 计算机图形学的作业,内含实验报告、源代码以及模型数据,供参考。
  • 基于MFC的OpenGL三维绘图,从数据矩阵到三维图像,很值得学习,翻转、放大,好资源必须拿出来分享。
  • OpenGL渲染3D物体到屏幕上的过程其实类似我们平时用照相机拍照的过程,这个步骤大致如下: 一、把照相机固定在三脚架并让它对准场景(视图变换) 二、把场景中的物体调整摆放好(模型变换) 、选择照相机的镜头,并...

    OpenGL(十三)——Qt OpenGL绘制三维图形

    一、二维图形

    之前的文章介绍的都是二维的图形。在旋转的多面体那篇文章中绘制的也是一个三维的图形,本篇介绍三维的图形绘制。

    二、三维图形

    在之前VS2010版本下介绍过三维图形的绘制,见OpenGL(六)——创建三维图形,在这篇文章提到了绘制三维的大致步骤:

    3、可能有点绕,没关系,至少你记住下面这几个流程:

    OpenGL渲染3D物体到屏幕上的过程其实类似我们平时用照相机拍照的过程,这个步骤大致如下:
    一、把照相机固定在三脚架并让它对准场景(视图变换)

    二、把场景中的物体调整摆放好(模型变换)

    三、选择照相机的镜头,并调整放大倍数(投影变换)

    四、确定最终照片的大小(视口变换)


    其中视图变换必须要在模型变换之前,其它可以在任何时候。

    其实三维的绘制,就是二维图形的叠加,以正四面体为例,正四面体就是六个正方形,在一起绘制,叠加在了一起就是一个正方体(正四面体)。

    三、代码实现

    在上一篇的内容上作些扩展,我们现在开始生成真正的三维对象,而不是象前两节课中那样在三维世界中的二维对象。
    我们给三角形增加一个左侧面,一个右侧面,一个后侧面来生成一个金字塔(四棱锥)。
    给正方形增加左、右、上、下及背面生成一个立方体。
    我们混合金字塔上的颜色,创建一个平滑着色的对象。给立方体的每一面则来个不同的颜色。
    其实只需在上节课的代码上增加几行就可以了。

    现在把代码贴上:

    头文件:

    #include <QObject>
    #include <QWidget>
    #include <qgl.h>
    
    /*
    *绘制三维.
    */
    
    class NeHe_5_Widget : public QGLWidget
    {
        Q_OBJECT
    public:
        NeHe_5_Widget(QWidget *parent = 0);
        ~NeHe_5_Widget();
    
    protected:
        void initializeGL(); 
        void paintGL();     
        void resizeGL( int width, int height ); 
    
    private:
        GLfloat rTri;
        GLfloat rQuad;
    };

    cpp文件:

    #include "nehe_5_widget.h"
    
    #include <GL/glu.h>
    
    NeHe_5_Widget::NeHe_5_Widget(QWidget *parent):QGLWidget(parent)
    {
        setGeometry(0,0, 640, 480);
        rTri = 0.0;
        rQuad = 0.0;
    }
    
    NeHe_5_Widget::~NeHe_5_Widget()
    {
    
    }
    
    void NeHe_5_Widget::initializeGL()
    {
        glShadeModel( GL_SMOOTH );
    
    
        glClearColor( 0.0, 0.0, 0.0, 0.0 );
    
    
        glClearDepth( 1.0 );
        //设置深度缓存。
    
        glEnable( GL_DEPTH_TEST );
        //启用深度测试。
    
        glDepthFunc( GL_LEQUAL );
        //所作深度测试的类型。
    
        //上面这三行必须做的是关于depth buffer(深度缓存)的。将深度缓存设想为屏幕后面的层。深度缓存不断的对物体进入屏幕内部有多深进行跟踪。\
        我们本节的程序其实没有真正使用深度缓存,但几乎所有在屏幕上显示3D场景OpenGL程序都使用深度缓存。它的排序决定那个物体先画。这样您就不会将\
        一个圆形后面的正方形画到圆形上来。深度缓存是OpenGL十分重要的部分。
    
        glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
    
    }
    
    
    

    void NeHe_5_Widget::resizeGL( int width, int height )
    {
        if ( height == 0 )
        {
          height = 1;
        }
        //防止height为0。
    
        glViewport( 0, 0, (GLint)width, (GLint)height );
        //重置当前的视口(Viewport)。
    
        glMatrixMode( GL_PROJECTION );
        //选择投影矩阵。
    
        glLoadIdentity();
        //重置投影矩阵。
    
        gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
        //建立透视投影矩阵。
    
        glMatrixMode( GL_MODELVIEW );
        //选择模型观察矩阵。
    
        glLoadIdentity();
        //重置模型观察矩阵。
    
        
    }
    
    
    void NeHe_5_Widget::paintGL()
    {
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        //清楚屏幕和深度缓存。
        glLoadIdentity();
        //重置当前的模型观察矩阵。
    
        glTranslatef( -1.5,  0.0, -6.0 );
    
        glRotatef( rTri, 0.0, 1.0, 0.0);
    
    
        //! 有些人可能早已在上节课中的代码上尝试自行创建3D对象了。但经常有人来信问我:“我的对象怎么不会绕着其自身的轴旋转?看起来总是在满屏乱转。”\
        //! 要让您的对象绕自身的轴旋转,您必须让对象的中心坐标总是( 0.0, 0,0, 0,0 )。
        //! 下面的代码创建一个绕者其中心轴旋转的金字塔。金字塔的上顶点离中心一个单位,底面离中心也是一个单位。上顶点在底面的投影位于底面的中心。
        //! 注意所有的面-三角形都是逆时针次序绘制的。这点十分重要,在以后的课程中我会作出解释。现在,您只需明白要么都逆时针,要么都顺时针,\
        //! 但永远不要将两种次序混在一起,除非您有足够的理由必须这么做。
    
    
        glBegin( GL_TRIANGLES );
        glColor3f( 1.0, 0.0, 0.0 );
        glVertex3f(  0.0,  1.0,  0.0 ); //前侧面.
        glColor3f( 0.0, 1.0, 0.0 );
        glVertex3f( -1.0, -1.0,  1.0 );
        glColor3f( 0.0, 0.0, 1.0 );
        glVertex3f(  1.0, -1.0,  1.0 );
        //上面是我们绘制的金字塔的前侧面。因为所有的面都共享上顶点,我们将这点在所有的三角形中都设置为红色。底边上的两个顶点的颜色则是互斥的。\
        前侧面的左下顶点是绿色的,右下顶点是蓝色的。这样相邻右侧面的左下顶点是蓝色的,右下顶点是绿色的。这样四边形的底面上的点的颜色都是间隔排列的。\
    
        //还应注意到后面的三个侧面和前侧面处于同一个glBegin( GL_TRIANGLES )和glEnd()语句中间。因为我们是通过三角形来构造这个金字塔的。\
        OpenGL知道每三个点构成一个三角形。当它画完一个三角形之后,如果还有余下的点出现,它就以为新的三角形要开始绘制了。OpenGL在这里并不会将\
        四点画成一个四边形,而是假定新的三角形开始了。所以千万不要无意中增加任何多余的点。
        glColor3f( 1.0, 0.0, 0.0 );
        glVertex3f(  0.0,  1.0,  0.0 ); //右侧面.
        glColor3f( 0.0, 0.0, 1.0 );
        glVertex3f(  1.0, -1.0,  1.0 );
        glColor3f( 0.0, 1.0, 0.0 );
        glVertex3f(  1.0, -1.0, -1.0 );
        //绘制右侧面。注意其底边上的两个顶点的X坐标位于中心右侧的一个单位处。顶点则位于Y轴上的一单位处,且Z坐标正好处于底边的两顶点的Z坐标中心。\
        右侧面从上顶点开始向外侧倾斜至底边上。
    
        //这次的左下顶点用蓝色绘制,以保持与前侧面的右下顶点的一致。蓝色将从这个角向金字塔的前侧面和右侧面扩展并与其他颜色混合。
        glColor3f( 1.0, 0.0, 0.0 );
        glVertex3f(  0.0,  1.0,  0.0 );
        glColor3f( 0.0, 1.0, 0.0 );
        glVertex3f(  1.0, -1.0, -1.0 ); //后侧面
        glColor3f( 0.0, 0.0, 1.0 );
        glVertex3f( -1.0, -1.0, -1.0 );
    
    
        //后侧面。再次切换颜色。左下顶点又回到绿色,因为后侧面与右侧面共享这个角。
        glColor3f( 1.0, 0.0, 0.0 );
        glVertex3f(  0.0,  1.0,  0.0 ); //左侧面.
        glColor3f( 0.0, 0.0, 1.0 );
        glVertex3f( -1.0, -1.0, -1.0 );
        glColor3f( 0.0, 1.0, 0.0 );
        glVertex3f( -1.0, -1.0,  1.0 );
    
        //最后画左侧面。又要切换颜色。左下顶点是蓝色,与后侧面的右下顶点相同。右下顶点是蓝色,与前侧面的左下顶点相同。
    
        //到这里金字塔就画完了。因为金字塔只绕着Y轴旋转,我们永远都看不见底面,因而没有必要添加底面。如果您觉得有经验了,\
        尝试增加底面(正方形),并将金字塔绕X轴旋转来看看您是否作对了。确保底面四个顶点的颜色与侧面的颜色相匹配。
    
        glEnd();
    
    
        //接下来开始画立方体。他由六个四边形组成。所有的四边形都以逆时针次序绘制。就是说先画右上角,然后左上角、左下角、最后右下角。\
        您也许认为画立方体的背面的时候这个次序看起来好像顺时针,但别忘了我们从立方体的背后看背面的时候,\
         与您现在所想的正好相反。(译者注:您是从立方体的外面来观察立方体的。)
        glLoadIdentity();
        glTranslatef(  1.5,  0.0, -7.0 );
        //注意到这次我们将立方体移地更远离屏幕了。因为立方体的大小要比金字塔大,同样移入6个单位时,立方体看起来要大的多。这是透视的缘故。越远的对象看起来越小 :) 。
    
        glRotatef( rQuad,  1.0,  1.0,  1.0 );
        //旋转四边形。
        glBegin( GL_QUADS );
          glColor3f( 0.0, 1.0, 0.0 );
          glVertex3f(  1.0,  1.0, -1.0 );
          glVertex3f( -1.0,  1.0, -1.0 );
          glVertex3f( -1.0,  1.0,  1.0 );
          glVertex3f(  1.0,  1.0,  1.0 );
        //先画立方体的顶面。从中心上移一单位,注意Y坐标始终为一单位,表示这个四边形与Z轴平行。先画右上顶点,向右一单位,再屏幕向里一单位。\
          然后左上顶点,向左一单位,再屏幕向里一单位。然后是靠近观察者的左下和右下顶点。就是屏幕往外一单位。
    
          glColor3f( 1.0, 0.5, 0.0 );
          glVertex3f(  1.0, -1.0,  1.0 );
          glVertex3f( -1.0, -1.0,  1.0 );
          glVertex3f( -1.0, -1.0, -1.0 );
          glVertex3f(  1.0, -1.0, -1.0 );
          //底面的画法和顶面十分类似。只是Y坐标变成了-1。如果我们从立方体的下面来看立方体的话,您会注意到右上角离观察者最近,\
          因此我们先画离观察者最近的顶点。然后是左上顶点最后才是屏幕里面的左下和右下顶点。
    
          //如果您真的不在乎绘制多边形的次序(顺时针或者逆时针)的话,您可以直接拷贝顶面的代码,将Y坐标从1改成-1,也能够工作。\
            但一旦您进入象纹理映射这样的领域时,忽略绘制次序会导致十分怪异的结果。
          glColor3f( 1.0, 0.0, 0.0 );
          glVertex3f(  1.0,  1.0,  1.0 );
          glVertex3f( -1.0,  1.0,  1.0 );
          glVertex3f( -1.0, -1.0,  1.0 );
          glVertex3f(  1.0, -1.0,  1.0 );
    
          //立方体的前面。保持Z坐标为一单位,前面正对着我们。
    
          glColor3f( 1.0, 1.0, 0.0 );
          glVertex3f(  1.0, -1.0, -1.0 );
          glVertex3f( -1.0, -1.0, -1.0 );
          glVertex3f( -1.0,  1.0, -1.0 );
          glVertex3f(  1.0,  1.0, -1.0 );
    
          //立方体后面的绘制方法与前面类似。只是位于屏幕的里面。注意Z坐标现在保持-1不变。
    
          glColor3f( 0.0, 0.0, 1.0 );
          glVertex3f( -1.0,  1.0,  1.0 );
          glVertex3f( -1.0,  1.0, -1.0 );
          glVertex3f( -1.0, -1.0, -1.0 );
          glVertex3f( -1.0, -1.0,  1.0 );
    
          //还剩两个面就完成了。您会注意到总有一个坐标保持不变。这一次换成了X坐标。因为我们在画左侧面。
    
          glColor3f( 1.0, 0.0, 1.0 );
          glVertex3f(  1.0,  1.0, -1.0 );
          glVertex3f(  1.0,  1.0,  1.0 );
          glVertex3f(  1.0, -1.0,  1.0 );
          glVertex3f(  1.0, -1.0, -1.0 );
    
          //立方体的最后一个面了。X坐标保持为一单位。逆时针绘制。您愿意的话,留着这个面不画也可以,这样就是一个盒子:)
    
          glEnd();
    
        glTranslatef(  -1.5,  0.0,  0.0 );
        glColor3f( 1.0, 1.0, 0.0 );
        glBegin( GL_LINES );
        glVertex3f(0.0, 1.0, 0.0);
        glVertex3f(0.0, -1.0, 0.0);
        glEnd();
    
        rTri += 0.2;
        rQuad -= 0.15;
    
    }

    到这里您应该已经较好的掌握了在三维空间创建对象的方法。必须将OpenGL屏幕想象成一张很大的画纸,后面还带着许多透明的层。


    差不多就是个由大量的点组成的立方体。这些点从左至右、从上至下、从前到后的布满了这个立方体。如果您能想象的出在屏幕的深度方向,应该在设计新三维对象时没有任何问题。

    注:上面的代码中有这样一句注释,大家一定要注意:

    有些人可能早已在上节课中的代码上尝试自行创建3D对象了。但经常有人来信问我:“我的对象怎么不会绕着其自身的轴旋转?看起来总是在满屏乱转。要让您的对象绕自身的轴旋转,您必须让对象的中心坐标总是( 0.0, 0,0, 0,0 )。
    下面的代码创建一个绕者其中心轴旋转的金字塔。金字塔的上顶点离中心一个单位,底面离中心也是一个单位。上顶点在底面的投影位于底面的中心。
    注意所有的面-三角形都是逆时针次序绘制的。这点十分重要,在以后的课程中我会作出解释。现在,您只需明白要么都逆时针,要么都顺时针,但永远不要将两种次序混在一起,除非您有足够的理由必须这么做。

    四、运行

    代码写完之后,我们可以看一下运行的效果:

    上一篇:OpenGL(十二)——Qt OpenGL绕着坐标轴旋转多边形

    下一篇:OpenGL(十四)——Qt OpenGL纹理

    本文原创作者:冯一川(ifeng12358@163.com),未经作者授权同意,请勿转载。

    展开全文
  • VC++使用OpenGL绘制三维图形的实例
  • VC++使用OpenGL绘制三维图形的实例

    热门讨论 2010-06-05 20:43:56
    在vc++中使用opengl绘制三维图形的例子
  • opengl绘制三维汽车

    2020-10-20 17:00:45
    这是用OpenGL绘制的动态汽车.绘制的丑,但代码简单易懂,适合初学者. 这是用OpenGL绘制的动态汽车.绘制的丑,但代码简单易懂,适合初学者.
  • OpenGL绘制三维图形的流程

    千次阅读 2018-01-22 09:56:00
    对于Android开发者来说,OpenGL就是用来绘制三维图形的技术手段,当然OpenGL并不仅限于展示静止的三维图形,也能用来播放运动着的三维动画。不管是三维图形还是三维动画,都是力求在二维的手机屏幕上面展现模拟的...

    从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发。

    OpenGL的全称是“Open Graphics Library”,意思是开放图形库,它定义了一个跨语言、跨平台的图形图像程序接口。对于Android开发者来说,OpenGL就是用来绘制三维图形的技术手段,当然OpenGL并不仅限于展示静止的三维图形,也能用来播放运动着的三维动画。不管是三维图形还是三维动画,都是力求在二维的手机屏幕上面展现模拟的真实世界场景,这个OpenGL的应用方向说到底,可不就是时下大热的虚拟现实么?

    看起来OpenGL是很高大上的样子,其实Android系统早已集成了相关的API,只要开发者按照函数要求依次调用,就能一步一步在手机屏幕上画出各式各样的三维物体了。不过对于初次接触OpenGL的开发者来说,三维绘图的概念可能过于抽象,所以为了方便读者理解,下面就以Android上的二维图形绘制为参考,亦步亦趋地逐步消化OpenGL的相关知识点。

    从前面的学习可以得知,每个Android界面上的控件,其实都是在某个视图上绘制规定的文字(如TextView),或者绘制指定的图像(如ImageView)。而TextView和ImageView都继承自基本视图View,这意味着首先要有一个专门的绘图场所,比如现实生活中的黑板、画板和桌子。然后还要有绘画作品的载体,比如显示生活中黑板的漆面,以及用于国画的宣纸、用于油画的油布等等,在Android系统中,这个绘画载体便是画布Canvas。有了绘图场所和绘画载体,还得有一把绘图工具,不管是勾勒线条还是涂抹颜料都少不了它,如果是写黑板报则有粉笔,如果是画国画则有毛笔,如果是画油画则有油画笔,如果是画Android控件则有画笔Paint。

    所以,只要具备了绘图场所、绘画载体、绘图工具,即可挥毫泼墨进行绘画创作啦。正如前面介绍的Android自定义控件那样,有了视图View、画布Canvas、画笔Paint,方能绘制炫彩多姿的各种控件。那么对于OpenGL的三维绘图来说,也同样需要具备这三种要素,分别是GLSurfaceView、GLSurfaceView.Renderer和GL10,其中GLSurfaceView继承自表面视图SurfaceView,对应于二维绘图的View;GLSurfaceView.Renderer是三维图形的渲染器,对应于二维绘图的Canvas;最后一个GL10自然相当于二维绘图的Paint了。有了GLSurfaceView、GLRender和GL10这三驾马车,Android才能实现OpenGL的三维图形渲染功能。

    具体到App编码上面,还得将GLSurfaceView、GLSurfaceView.Renderer和GL10这三个类有机结合起来,即通过函数调用关联它们三个小伙伴。首先从布局文件获得GLSurfaceView的控件对象,然后调用该对象的setRenderer方法设置三维渲染器,这个三维渲染器实现了GLSurfaceView.Renderer定义的三个视图函数,分别是onSurfaceCreated、onSurfaceChanged和onDrawFrame,这三个函数的输入参数都包含GL10,也就是说这三个函数都持有画笔对象。如此一来,绘图三要素的GLSurfaceView、GLSurfaceView.Renderer和GL10就互相关联了起来。

    可是,Renderer接口定义的onSurfaceCreated、onSurfaceChanged和onDrawFrame三个函数很是陌生,它们之间又有什么区别呢?为方便理解,接下来不妨继续套用Android二维绘图的有关概念,从Android自定义控件的主要流程得知,自定义一个二维控件,主要有以下四个步骤:
    1、声明自定义控件的构造函数,可在此进行控件属性初始赋值等初始化操作;
    2、重写onMeasure函数,可在此测量控件的宽度和高度;
    3、重写onLayout函数,可在此挪动控件的位置;
    4、重写onDraw函数,可在此绘制控件的形状、颜色、文字以及图案等等;

    于是前面提到Renderer接口定义的三个函数,它们的用途对照说明如下:
    1、onSurfaceCreated函数在GLSurfaceView创建时调用,相当于自定义控件的构造函数,一样可在此进行三维绘图的初始化操作;
    2、onSurfaceChanged函数在GLSurfaceView创建、恢复与改变时调用,在这里不但要定义三维空间的大小,还要定义三维物体的方位,所以该函数相当于完成了自定义控件的onMeasure和onLayout两个函数的功能;
    3、onDrawFrame顾名思义跟自定义控件的onDraw函数差不多,onDraw函数用于绘制二维图形的具体形状,而onDrawFrame函数用于绘制三维图形的具体形状;下面来个最简单的OpenGL例子,在布局文件中放置一个android.opengl.GLSurfaceView节点,后续的三维绘图动作将在该视图上开展。布局文件内容示例如下:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <!-- 注意这里要使用控件的全路径android.opengl.GLSurfaceView -->
    
        <android.opengl.GLSurfaceView
            android:id="@+id/glsv_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

    接着在Activity代码中获取这个GLSurfaceView对象,并给它注册一个三维图形的渲染器GLRender,此时自定义的渲染器GLRender必须重载onSurfaceCreated、onSurfaceChanged和onDrawFrame这三个函数。下面是对应的Activity代码框架例子:

    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_gl_cub);
    		GLSurfaceView glsv_content = (GLSurfaceView) findViewById(R.id.glsv_content);
    		// 注册渲染器
    		glsv_content.setRenderer(new GLRender());
    	}
    
    	private class GLRender implements GLSurfaceView.Renderer {
    		@Override
    		public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    			// 这里进行三维绘图的初始化操作
    		}
    
    		@Override
    		public void onSurfaceChanged(GL10 gl, int width, int height) {
    			// 这里要定义三维空间的大小,还要定义三维物体的方位
    		}
    
    		@Override
    		public void onDrawFrame(GL10 gl) {
    			// 这里绘制三维图形的具体形状
    		}
    	}


     

    转载于:https://my.oschina.net/ouysh1981/blog/1610822

    展开全文
  • 摘要:VC/C++源码,图形处理,OpenGL,绘制图形 ...VC++使用OpenGL实现绘制三维图形,将根据窗口大小设置调整正射投影矩阵,绘制出茶壶的图形,需要比较综合点的OpenGL知识。 运行环境:Windows/Visual C/C++
  • 本文使用QGLWidget来绘制各种三维基本图形,包括立方体、圆柱体、圆锥、球体、圆环等等,涉及包括基本绘制以及上色、纹理、旋转等操作。 使用的软件版本:QT5.12 + QT Creater4.8.0 GLWidget.h ...

    本文使用QGLWidget来绘制各种三维基本图形,包括立方体、圆柱体、圆锥、球体、圆环等等,涉及包括基本绘制以及上色、纹理、旋转等操作。

    使用的软件版本:QT5.12 + QT Creater4.8.0

     GLWidget.h
    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
     
    #ifndef  GLWIDGET_H
    #define  GLWIDGET_H

    #include  <QGLWidget>

    class  GLWidget :  public  QGLWidget
    {
        Q_OBJECT

    public :
        GLWidget(QWidget *parent = 
    0 );
        ~GLWidget();

    protected :
        
    // 设置渲染环境
         void  initializeGL();
        
    // 绘制窗口
         void  paintGL();
        
    // 响应窗口的大小变化
         void  resizeGL( int  width,  int  height);

    private :
        
    // 场景渲染
         void  renderScene();
        
    // 场景渲染-基本图形
         void  renderBasicShape();
        
    // 场景渲染-立方体纹理
         void  renderTextureCube();
        
    // 场景渲染-圆柱体纹理
         void  renderTextureCylinder();
        
    // 绘制立方体
         void  drawCube();
        
    // 绘制圆形
         void  drawCircle();
        
    // 绘制圆柱体
         void  drawCylinder();
        
    // 绘制圆锥体
         void  drawCone();
        
    // 绘制四面体
         void  drawTetrahedron();
        
    // 绘制球体
         void  drawSphere(GLfloat xx =  0 . 0 ,
                        GLfloat yy = 
    0 . 0 ,
                        GLfloat zz = 
    0 . 0 ,
                        GLfloat radius = 
    1 . 0 ,
                        GLfloat M = 
    100 . 0 ,
                        GLfloat N = 
    100 . 0 );
        
    // 绘制圆环
         void  DrawTorus( double  Radius =  1 ,
                       
    double  TubeRadius =  0 . 2 ,
                       
    int  Sides =  20 ,
                       
    int  Rings =  30 );
        
    // 加载纹理
         void  loadGLTextures();


    private :
        
    // 旋转角度
        GLfloat  xRot;
        GLfloat  yRot;
        GLfloat  zRot;
        
    // 存储纹理
        GLuint texture[ 2 ];

    };
    #endif   // GLWIDGET_H

     

    GLWidget.cpp
    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
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
     
    #include   "GLWidget.h"
    #include  <qmath.h>

    #define  PI           3 . 14
    #define  ROT_DELTA    0 .5f

    void  qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
    {
        
    const  GLdouble ymax = zNear * tan(qDegreesToRadians(fovy) /  2 . 0 );
        
    const  GLdouble ymin = -ymax;
        
    const  GLdouble xmin = ymin * aspect;
        
    const  GLdouble xmax = ymax * aspect;
        glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
    }

    GLWidget::GLWidget(QWidget *parent)
        : QGLWidget(parent)
        , xRot(
    0 .0f)
        , yRot(
    0 .0f)
        , zRot(
    0 .0f)
    {
        
    // 设置画面的双缓冲和深度缓存
        setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer));
    }

    GLWidget::~GLWidget()
    {

    }

    void  GLWidget::initializeGL()
    {
        
    // 启用阴影平滑
        glShadeModel(GL_SMOOTH);
        
    // 白色背景
        glClearColor( 1 . 0 1 . 0 1 . 0 1 . 0 );
        
    // 设置深度缓存
        glClearDepth( 1 . 0 );
        
    // 启用深度测试
        glEnable(GL_DEPTH_TEST);
        
    // 所作深度测试的类型
        glDepthFunc(GL_LEQUAL);
        
    // 告诉系统对透视进行修正
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        
    // 启用2D纹理映射
        glEnable(GL_TEXTURE_2D);
        
    // 加载纹理
        loadGLTextures();
    }

    void  GLWidget::paintGL()
    {
        renderScene();
        update();
    }

    void  GLWidget::resizeGL( int  width,  int  height)
    {
        
    // 防止窗口大小变为0
         if  ( height ==  0  )
        {
            height = 
    1 ;
        }
        
    // 重置当前的视口
        glViewport( 0 0 , (GLint)width, (GLint)height);
        
    // 选择投影矩阵
        glMatrixMode(GL_PROJECTION);
        
    // 重置投影矩阵
        glLoadIdentity();
        
    // 设置视口的大小
        qgluPerspective( 45 . 0 , (GLdouble)width / (GLdouble)height,  0 . 1 100 . 0 );
        
    // 选择模型观察矩阵
        glMatrixMode(GL_MODELVIEW);
        
    // 重置投影矩阵
        glLoadIdentity();
    }

    // 绘制立方体
    void  GLWidget::drawCube()
    {
        glBegin(GL_QUAD_STRIP);         
    //填充凸多边形
        glColor3f( 1 0 0 );
        glVertex3f(
    0 .0f,  0 .0f,  0 .0f);
        glColor3f(
    1 1 0 );
        glVertex3f(
    0 .0f,  1 .0f,  0 .0f);
        glColor3f(
    0 1 0 );
        glVertex3f(
    1 .0f,  0 .0f,  0 .0f);
        glColor3f(
    0 1 1 );
        glVertex3f(
    1 .0f,  1 .0f,  0 .0f);
        glColor3f(
    1 0 0 );
        glVertex3f(
    1 .0f,  0 .0f, - 1 .0f);
        glColor3f(
    1 1 0 );
        glVertex3f(
    1 .0f,  1 .0f, - 1 .0f);
        glColor3f(
    0 1 0 );
        glVertex3f(
    0 .0f,  0 .0f, - 1 .0f);
        glColor3f(
    0 1 1 );
        glVertex3f(
    0 .0f,  1 .0f, - 1 .0f);
        glColor3f(
    1 0 0 );
        glVertex3f(
    0 .0f,  0 .0f,  0 .0f);
        glColor3f(
    1 1 0 );
        glVertex3f(
    0 .0f,  1 .0f,  0 .0f);
        glEnd();
        glBegin(GL_QUAD_STRIP);
        glColor3f(
    0 0 1 );
        glVertex3f(
    0 .0f,  0 .0f,  0 .0f);
        glColor3f(
    1 0 1 );
        glVertex3f(
    1 .0f,  0 .0f,  0 .0f);
        glColor3f(
    0 1 0 );
        glVertex3f(
    0 .0f,  0 .0f, - 1 .0f);
        glColor3f(
    1 0 0 );
        glVertex3f(
    1 .0f,  0 .0f, - 1 .0f);
        glColor3f(
    1 1 0 );
        glVertex3f(
    0 .0f,  1 .0f,  0 .0f);
        glColor3f(
    1 0 1 );
        glVertex3f(
    1 .0f,  1 .0f,  0 .0f);
        glColor3f(
    0 0 1 );
        glVertex3f(
    0 .0f,  1 .0f, - 1 .0f);
        glColor3f(
    1 0 0 );
        glVertex3f(
    1 .0f,  1 .0f, - 1 .0f);
        glEnd();
    }

    // 绘制圆形
    void  GLWidget::drawCircle()
    {
        glBegin(GL_TRIANGLE_FAN);           
    //扇形连续填充三角形串
        glVertex3f( 0 .0f,  0 .0f,  0 .0f);
        
    int  i =  0 ;
        
    for  (i =  0 ; i <=  360 ; i +=  15 )
        {
            
    float  p = i *  3 . 14  /  180 ;
            glColor3f(sin(p), cos(p), tan(p));
            glVertex3f(sin(p), cos(p), 
    0 .0f);
        }
        glEnd();
    }

    // 绘制圆柱体
    void  GLWidget::drawCylinder()
    {
        
    // 利用三角形和四边形等基本图元绘制底面圆圆心在坐标原点, 半径为 r,高为 h,方向沿 z 轴方向的圆柱;
         // 侧面用多个四边形,底面用多个三角形来表示
        glBegin(GL_QUAD_STRIP); //连续填充四边形串
         int  i =  0 ;
        
    for  (i =  0 ; i <=  360 ; i +=  15 )
        {
            
    float  p = i *  3 . 14  /  180 ;
            glVertex3f(sin(p), cos(p), 
    1 .0f);
            glVertex3f(sin(p), cos(p), 
    0 .0f);
        }
        glEnd();
        
    //bottom circle
        glColor3f( 1 0 0 );
        drawCircle();
        glTranslatef(
    0 0 1 );
        
    //top circle
        glColor3f( 0 0 1 );
        drawCircle();
        glColor3f(
    0 1 0 );
    }

    // 绘制圆锥体
    void  GLWidget::drawCone()
    {
        glBegin(GL_QUAD_STRIP);
    //连续填充四边形串
         int  i =  0 ;
        
    for  (i =  0 ; i <=  360 ; i +=  15 )
        {
            
    float  p = i *  3 . 14  /  180 ;
            glColor3f(sin(p), cos(p), 
    1 .0f);
            glVertex3f(
    0 0 1 .0f);
            glVertex3f(sin(p), cos(p), 
    0 .0f);
        }
        glEnd();
        
    //bottom circle
        glColor3f( 0 1 1 );
        drawCircle();
    }

    // 绘制四面体等
    void  GLWidget::drawTetrahedron()
    {
        glBegin(GL_QUADS);
        glNormal3f(
    0 0 , - 1 );
        glColor3f(
    1 . 0 0 . 0 0 . 0 );
        glVertex3f(-
    1 , - 1 0 );
        glColor3f(
    0 . 0 1 . 0 0 . 0 );
        glVertex3f(-
    1 1 0 );
        glColor3f(
    0 . 0 0 . 0 1 . 0 );
        glVertex3f(
    1 1 0 );
        glColor3f(
    1 . 0 1 . 0 0 . 0 );
        glVertex3f(
    1 , - 1 0 );
        glEnd();

        glBegin(GL_TRIANGLES);
        glNormal3f(
    0 , - 1 0 . 707 );
        glColor3f(
    0 . 0 1 . 0 1 . 0 );
        glVertex3f(-
    1 , - 1 0 );
        glColor3f(
    1 . 0 0 . 0 1 . 0 );
        glVertex3f(
    1 , - 1 0 );
        glColor3f(
    1 . 0 0 . 0 1 . 0 );
        glVertex3f(
    0 0 1 . 2 );
        glEnd();
        glBegin(GL_TRIANGLES);
        glNormal3f(
    1 0 0 . 707 );
        glColor3f(
    0 . 0 1 . 0 1 . 0 );
        glVertex3f(
    1 , - 1 0 );
        glColor3f(
    1 . 0 0 . 0 1 . 0 );
        glVertex3f(
    1 1 0 );
        glColor3f(
    1 . 0 0 . 0 1 . 0 );
        glVertex3f(
    0 0 1 . 2 );
        glEnd();
        glBegin(GL_TRIANGLES);
        glNormal3f(
    0 1 0 . 707 );
        glColor3f(
    0 . 0 1 . 0 1 . 0 );
        glVertex3f(
    1 1 0 );
        glColor3f(
    1 . 0 0 . 0 1 . 0 );
        glVertex3f(-
    1 1 0 );
        glColor3f(
    1 . 0 0 . 0 1 . 0 );
        glVertex3f(
    0 0 1 . 2 );
        glEnd();
        glBegin(GL_TRIANGLES);
        glNormal3f(-
    1 0 0 . 707 );
        glColor3f(
    1 . 0 0 . 0 1 . 0 );
        glVertex3f(-
    1 1 0 );
        glColor3f(
    0 . 0 1 . 0 1 . 0 );
        glVertex3f(-
    1 , - 1 0 );
        glColor3f(
    1 . 0 0 . 0 0 . 0 );
        glVertex3f(
    0 0 1 . 2 );
        glEnd();
    }

    // 绘制球体
    // 球心坐标为(x,y,z),球的半径为radius,M,N分别表示球体的横纵向被分成多少份
    void  GLWidget::drawSphere(GLfloat xx, GLfloat yy, GLfloat zz,
                              GLfloat radius, GLfloat M, GLfloat N)
    {
        
    // 选择使用的纹理
        glBindTexture(GL_TEXTURE_2D, texture[ 0 ]);

        
    float  step_z = PI / M;
        
    float  step_xy =  2  * PI / N;
        
    float  x[ 4 ], y[ 4 ], z[ 4 ];

        
    float  angle_z =  0 . 0 ;
        
    float  angle_xy =  0 . 0 ;
        
    int  i =  0 , j =  0 ;
        glBegin(GL_QUADS);
        
    for (i =  0 ; i < M; i++)
        {
            angle_z = i * step_z;

            
    for (j =  0 ; j < N; j++)
            {
                angle_xy = j * step_xy;

                x[
    0 ] = radius * sin(angle_z) * cos(angle_xy);
                y[
    0 ] = radius * sin(angle_z) * sin(angle_xy);
                z[
    0 ] = radius * cos(angle_z);

                x[
    1 ] = radius * sin(angle_z + step_z) * cos(angle_xy);
                y[
    1 ] = radius * sin(angle_z + step_z) * sin(angle_xy);
                z[
    1 ] = radius * cos(angle_z + step_z);

                x[
    2 ] = radius * sin(angle_z + step_z) * cos(angle_xy + step_xy);
                y[
    2 ] = radius * sin(angle_z + step_z) * sin(angle_xy + step_xy);
                z[
    2 ] = radius * cos(angle_z + step_z);

                x[
    3 ] = radius * sin(angle_z) * cos(angle_xy + step_xy);
                y[
    3 ] = radius * sin(angle_z) * sin(angle_xy + step_xy);
                z[
    3 ] = radius * cos(angle_z);
                
    for ( int  k =  0 ; k <  4 ; k++)
                {
                    glColor3f(sin(angle_z), cos(angle_z), tan(angle_z));
                    
    //glTexCoord2f(0.1f, 0.1f);
                    glVertex3f(xx + x[k], yy + y[k], zz + z[k]);
                }
            }
        }
        glEnd();
    }

    // 绘制圆环
    // 大半径Radius,小半径TubeRadius,边数Sides, 环数Rings
    void  GLWidget::DrawTorus( double  Radius,  double  TubeRadius,  int  Sides,  int  Rings)
    {
        
    double  sideDelta =  2 . 0  * PI / Sides;
        
    double  ringDelta =  2 . 0  * PI / Rings;
        
    double  theta =  0 ;
        
    double  cosTheta =  1 . 0 ;
        
    double  sinTheta =  0 . 0 ;

        
    double  phi, sinPhi, cosPhi;
        
    double  dist;
        glColor3f(
    1 0 0 );
        
    for  ( int  i =  0 ; i < Rings; i++)
        {
            
    double  theta1 = theta + ringDelta;
            
    double  cosTheta1 = cos(theta1);
            
    double  sinTheta1 = sin(theta1);

            glBegin(GL_QUAD_STRIP);
            phi = 
    0 ;
            
    for  ( int  j =  0 ; j <= Sides; j++)
            {
                phi = phi + sideDelta;
                cosPhi = cos(phi);
                sinPhi = sin(phi);
                dist = Radius + (TubeRadius * cosPhi);

                glNormal3f(cosTheta * cosPhi, sinTheta * cosPhi, sinPhi);
                glColor3f(cosTheta, sinTheta, sinPhi);
                glVertex3f(cosTheta * dist, sinTheta * dist, TubeRadius * sinPhi);

                glNormal3f(cosTheta1 * cosPhi, sinTheta1 * cosPhi, sinPhi);
                glColor3f(cosTheta1, sinTheta1, sinPhi);
                glVertex3f(cosTheta1 * dist, sinTheta1 * dist, TubeRadius * sinPhi);
            }
            glEnd();
            theta = theta1;
            cosTheta = cosTheta1;
            sinTheta = sinTheta1;
        }
    }

    // 加载纹理
    void  GLWidget::loadGLTextures()
    {
        QImage tex1, buf1;
        QImage tex2, buf2;
        
    if  (!buf1.load( ":/data/qt-logo.jpg" ))
        {
            
    // 如果载入不成功,自动生成一个128*128的32位色的绿色图片。
            qWarning( "Could not read image file!" );
            QImage dummy(
    128 128 , QImage::Format_RGB32);
            dummy.fill(Qt::green);
            buf1 = dummy;
        }

        
    if  (!buf2.load( ":/data/qt-wood.jpg" ))
        {
            
    // 如果载入不成功,自动生成一个128*128的32位色的绿色图片。
            qWarning( "Could not read image file!" );
            QImage dummy(
    128 128 , QImage::Format_RGB32);
            dummy.fill(Qt::green);
            buf2 = dummy;
        }

        
    //***********************************************//
         // 纹理0:qt-logo
         //***********************************************//
         //转换成纹理类型
        tex1 = QGLWidget::convertToGLFormat(buf1);
        
    // 创建纹理
        glGenTextures( 1 , &texture[ 0 ]);
        
    // 使用来自位图数据生成的典型纹理,将纹理名字texture[0]绑定到纹理目标上
        glBindTexture(GL_TEXTURE_2D, texture[ 0 ]);
        
    // WRAP参数:纹理坐标超出[0,0]到[1,1]的范围该怎么处理呢?
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        
    // Filter参数:纹理坐标映射到纹素位置(127.34,255.14)该怎么办?
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        
    // 纹理环境
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        
    // 将纹素数组从CPU传至GPU并且设置为当前纹理。
         // 在处理单一纹理时,你可以用,负责效率非常低。
         // 多纹理时可以参见纹理绑定。
        glTexImage2D(GL_TEXTURE_2D,  0 3 , tex1.width(), tex1.height(),  0 ,
                     GL_RGBA, GL_UNSIGNED_BYTE, tex1.bits());

        
    //***********************************************//
         // 纹理0:qt-logo
         //***********************************************//
        tex2 = QGLWidget::convertToGLFormat(buf2);
        glGenTextures(
    1 , &texture[ 1 ]);
        glBindTexture(GL_TEXTURE_2D, texture[
    1 ]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glTexImage2D(GL_TEXTURE_2D, 
    0 3 , tex2.width(), tex2.height(),  0 ,
                     GL_RGBA, GL_UNSIGNED_BYTE, tex2.bits());
        
    // 使用纹理
         // 首先调用glEnable( GL_TEXTURE_2D ),来启用2D纹理;
         // 然后绘制图形,并且为每个顶点指定ST坐标;
         // 最后调用glDisable( GL_TEXTURE_2D ).
    }

    // 场景渲染
    void  GLWidget::renderScene( void )
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();

        glPushMatrix();
        renderBasicShape();
        glPopMatrix();

        glPushMatrix();
        glTranslatef(-
    3 0 0 );
        renderTextureCube();
        glPopMatrix();

        glPushMatrix();
        glTranslatef(
    3 0 0 );
        renderTextureCylinder();
        glPopMatrix();
    }

    // 渲染基本图形
    void  GLWidget::renderBasicShape()
    {
        
    static   float  fRotAngle =  0 .0f;
        fRotAngle += ROT_DELTA;
        
    if  (fRotAngle >  360 )
            fRotAngle = 
    0 ;

        glPushMatrix();
        glColor3f(
    0 1 0 );
        glTranslatef(-
    3 3 , - 12 );
        glRotatef(fRotAngle, 
    1 1  ,  1 );
        drawCylinder();
        glPopMatrix();

        glPushMatrix();
        glColor3f(
    1 0 0 );
        glTranslatef(
    0 3 , - 12 );
        glRotatef(fRotAngle, 
    1 1  ,  1 );
        drawTetrahedron();
        glPopMatrix();

        glPushMatrix();
        glColor3f(
    1 0 0 );
        glTranslatef(
    3 3 , - 12 );
        glRotatef(fRotAngle, 
    1 1 1 );
        drawCircle();
        glPopMatrix();

        glPushMatrix();
        glColor3f(
    1 0 0 );
        glTranslatef(
    0 0 , - 15 );
        glRotatef(fRotAngle, 
    0 1 0 );
        drawSphere();
        glPopMatrix();

        glPushMatrix();
        glColor3f(
    0 1 1 );
        glTranslatef(-
    3 , - 3 , - 12 );
        glRotatef(fRotAngle, 
    1 1 1 );
        drawCube();
        glPopMatrix();

        glPushMatrix();
        glColor3f(
    1 0 1 );
        glTranslatef(
    0 , - 3 , - 12 );
        glRotatef(fRotAngle, 
    1 1 1 );
        DrawTorus();
        glPopMatrix();

        glPushMatrix();
        glColor3f(
    1 1 0 );
        glTranslatef(
    3 , - 3 , - 12 );
        glRotatef(fRotAngle, 
    1 1 1 );
        drawCone();
        glPopMatrix();
    }

    // 渲染纹理
    void  GLWidget::renderTextureCube()
    {
        
    // 纹理映射
        glColor3f( 1 . 0 1 . 0 1 . 0 );
        glTranslatef(
    0 .0f,  0 .0f, - 12 .0f);
        glRotatef(xRot, 
    1 . 0 0 . 0 0 . 0 );
        glRotatef(yRot, 
    0 . 0 1 . 0 0 . 0 );
        glRotatef(zRot, 
    0 . 0 0 . 0 1 . 0 );
        
    // 使用来自位图数据生成的典型纹理,将纹理名字texture[0]绑定到纹理目标上
        glBindTexture(GL_TEXTURE_2D, texture[ 0 ]);
        glBegin( GL_QUADS );
        glTexCoord2f( 
    0 . 0 0 . 0  );
        glVertex3f( -
    1 . 0 , - 1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 0 . 0  );
        glVertex3f(  
    1 . 0 , - 1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 1 . 0  );
        glVertex3f(  
    1 . 0 ,   1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    0 . 0 1 . 0  );
        glVertex3f( -
    1 . 0 ,   1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 0 . 0  );
        glVertex3f( -
    1 . 0 , - 1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    1 . 0 1 . 0  );
        glVertex3f( -
    1 . 0 ,   1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    0 . 0 1 . 0  );
        glVertex3f(  
    1 . 0 ,   1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    0 . 0 0 . 0  );
        glVertex3f(  
    1 . 0 , - 1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    0 . 0 1 . 0  );
        glVertex3f( -
    1 . 0 ,   1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    0 . 0 0 . 0  );
        glVertex3f( -
    1 . 0 ,   1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 0 . 0  );
        glVertex3f(  
    1 . 0 ,   1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 1 . 0  );
        glVertex3f(  
    1 . 0 ,   1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    1 . 0 1 . 0  );
        glVertex3f( -
    1 . 0 , - 1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    0 . 0 1 . 0  );
        glVertex3f(  
    1 . 0 , - 1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    0 . 0 0 . 0  );
        glVertex3f(  
    1 . 0 , - 1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 0 . 0  );
        glVertex3f( -
    1 . 0 , - 1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 0 . 0  );
        glVertex3f(  
    1 . 0 , - 1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    1 . 0 1 . 0  );
        glVertex3f(  
    1 . 0 ,   1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    0 . 0 1 . 0  );
        glVertex3f(  
    1 . 0 ,   1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    0 . 0 0 . 0  );
        glVertex3f(  
    1 . 0 , - 1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    0 . 0 0 . 0  );
        glVertex3f( -
    1 . 0 , - 1 . 0 , - 1 . 0  );
        glTexCoord2f( 
    1 . 0 0 . 0  );
        glVertex3f( -
    1 . 0 , - 1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    1 . 0 1 . 0  );
        glVertex3f( -
    1 . 0 ,   1 . 0 ,   1 . 0  );
        glTexCoord2f( 
    0 . 0 1 . 0  );
        glVertex3f( -
    1 . 0 ,   1 . 0 , - 1 . 0  );
        glEnd();
        xRot += ROT_DELTA;
        
    if  (xRot >  360 ) xRot =  0 ;
        yRot += ROT_DELTA;
        
    if  (yRot >  360 ) yRot =  0 ;
        zRot += ROT_DELTA;
        
    if  (zRot >  360 ) zRot =  0 ;
    }

    void  GLWidget::renderTextureCylinder()
    {
        
    // 纹理映射
        glTranslatef( 0 .0f,  0 .0f, - 12 .0f);
        glRotatef(xRot, 
    1 . 0 0 . 0 0 . 0 );
        
    //glRotatef(yRot, 0.0, 1.0, 0.0);
         //glRotatef(zRot, 0.0, 0.0, 1.0);
         // 选择使用的纹理
        glBindTexture(GL_TEXTURE_2D, texture[ 1 ]);
        
    // 利用三角形和四边形等基本图元绘制底面圆圆心在坐标原点, 半径为 r,高为 h,方向沿 z 轴方向的圆柱;
         // 侧面用多个四边形,底面用多个三角形来表示
        glBegin(GL_QUAD_STRIP); //连续填充四边形串
         int  i =  0 ;
        
    for  (i =  0 ; i <=  360 ; i +=  15 )
        {
            
    float  p = i *  3 . 14  /  180 ;
            
    //p和圆周是相对应的, 这里让纹理的横坐标随圆周扫过的角度一起改变,就能够将纹理图“刷”上去了,
             //而纵坐标设置为图像的高度和纹理高度的对应,这里合适的参数是根据实际测试得到的
            glTexCoord2f(p /  10 0 .1f);
            glVertex3f(sin(p), cos(p), 
    1 .0f);    //这个 1.0f指定的是高度h
            glTexCoord2f(p /  10 0 .0f);
            glVertex3f(sin(p), cos(p), 
    0 .0f);
        }
        glEnd();
        
    //bottom circle
        glBegin(GL_TRIANGLE_FAN);            //扇形连续填充三角形串
        glTexCoord2f( 0 .0f,  0 .0f);            //将纹理图(0, 0)映射到圆心
        glVertex3f( 0 .0f,  0 .0f,  0 .0f);
        
    for  (i =  0 ; i <=  360 ; i +=  15 )
        {
            
    float  p = i *  3 . 14  /  180 ;
            glTexCoord2f(
    1 .0f,  0 .0f);        //将纹理图(1, 0)映射到圆周
            glVertex3f(sin(p), cos(p),  0 .0f);
        }
        glEnd();
        glTranslatef(
    0 0 1 );               //设定高度为1,画上底面
         //top circle
        glBegin(GL_TRIANGLE_FAN);            //扇形连续填充三角形串
        glTexCoord2f( 0 .0f,  0 .0f);            //将纹理图(0, 0)映射到圆心
        glVertex3f( 0 .0f,  0 .0f,  0 .0f);
        
    for  (i =  0 ; i <=  360 ; i +=  15 )
        {
            
    float  p = i *  3 . 14  /  180 ;
            glTexCoord2f(
    1 .0f,  0 .0f);        //将纹理图(1, 0)映射到圆周
            glVertex3f(sin(p), cos(p),  0 .0f);
        }
        glEnd();

        xRot += ROT_DELTA;
        
    if  (xRot >  360 ) xRot =  0 ;
        yRot += ROT_DELTA;
        
    if  (yRot >  360 ) yRot =  0 ;
        zRot += ROT_DELTA;
        
    if  (zRot >  360 ) zRot =  0 ;
    }

    主函数调用

    main.cpp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    #include   "GLWidget.h"
    #include  <QApplication>
    #include  <QObject>

    int  main( int  argc,  char  *argv[])
    {
        QApplication a(argc, argv);

        GLWidget w;
        w.resize(
    600 600 );
        w.setWindowTitle(QObject::tr(
    "Michael's OpenGL Framework" ));
        w.show();

        
    return  a.exec();
    }

    运行效果

    转载于:https://www.cnblogs.com/MakeView660/p/10436685.html

    展开全文
  • OpenGL场景小作业
  • 在VC++6.0中使用OpenGL绘制三维图形的实例源代码,源代码比较复杂,它可以绘制3D立体效果图,长方体、正方体等,其功能类似一款简单的3D绘图工具,还有其它功能,你可以下载编译一下探个究竟! 源码下载地址:点击...
  • OpenGL绘制三维坐标图

    热门讨论 2013-03-23 17:42:48
    自制的基于MFC、OpenGL平台的三维坐标图程序,在vc2008编译通过
  • 在VC++中使用OpenGL实现绘制三维图形,是一个学习的好例子.
  • C#中使用tao.opengl绘制三维模型

    千次阅读 2021-03-15 19:21:22
     Opengl是一种C风格的图形库,即opengl中没有类和对象,只有大量的函数。Opengl在内部就是一个状态机,利用不同的函数来修改opengl状态机的状态,以达到需要的效果。  Tao框架是C#使用Opengl的一种图形库,其他可...
  • OPenGL笔记--创建三维图形(立方体)

    千次阅读 2022-03-23 12:04:35
    通过之前的学习,我们已经知道了如何创建多边形,立方体实际就是多边形围起来的三维图形,例如: 椎体是4个三角形围起来的三维图形; 正方体是6个正方形围起来的三维图形; 注意事项: 要让您的对象绕自身的轴...
  • 怎样用OpenGL画出这样的三维图形? ![图片说明](https://img-ask.csdn.net/upload/201912/18/1576673506_344636.gif) ![图片说明](https://img-ask.csdn.net/upload/201912/18/1576673585_794754.png) !...
  • OpenGL(六)——创建三维图形

    千次阅读 2020-05-08 17:33:00
    OpenGL(三)——创建三维图形 一、
  • 从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨...对于Android开发者来说,OpenGL就是用来绘制三维图形的技术手段,当然OpenGL并不仅限于展示静止的三维图形,也能用来播放运动着的三维动画。不管是三
  • OpenGL绘制图形、MFC创建界面1.OpenGL绘图步骤2.图形的旋转、位移、伸缩 1.OpenGL绘图步骤 简单说就是: 创建DC–>创建RC并同DC关联–>函数OnDraw()绘图–>释放资源 ①通过PIXELFORMATDESCRIPTOR结构设置...
  • OpenGL(三)三维图形绘制

    万次阅读 2018-09-13 09:21:08
    #include "stdafx.h" #include&lt;GL/freeglut.h&gt; #include&lt;GLFW/glfw3.h&... glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER... // 三维图形由三维空间中的三角形拼接而成 glBegin(...
  • OpenGL ES】三维图形绘制

    千次阅读 2022-03-16 14:05:57
    OpenGL ES 3.0 学习——3D 颜色的简单搭配: 不红+不绿+不蓝 = 黑 红+绿+蓝 = 白 红+绿 = 黄 红+蓝 = 紫 绿+蓝 = 青蓝 投影矩阵 投影主要分为正交投影和透视投影两种。 正交投影 没有近大远小的效果,是平行投影,...
  • OpenGL 绘制维图形

    千次阅读 2017-07-23 19:53:16
    OpenGL 绘制维图形 注:本文程序建立在OpenGL MFC单文档环境配置 在讲解绘制图形之前,先分享一下我在绘制图形的过程中,遇到的一个问题。 四月份中旬,同学找我做一个关于三维绘图的...
  • Android OpenGL ES (二) 绘制三维/空间坐标系 透明的立体图加三维向量和xyz坐标轴 源代码包,直接倒入eclips修改packadge便可用
  • 实现了QT下OpenGL的光源照射编程,模拟现实中的光源实现三维图形绘制,在Vs2017+QT插件平台下运行
  • openGL 小汽车

    2021-02-17 03:00:19
    利用键盘控制汽进、后退、转弯、加速和减速;车前 制作一个弹出菜单,上面的菜单项用来控制车身和车轮的颜色以及退出程序。 定义对应于ReShape事件的回调函数,使得当用户改变窗口的大小时,显示的汽车不会变形。
  • 在visualstudio下用OpenGL编写的程序,在同一窗口中绘制两只三维动物(本代码中为两只小猪),并可用键盘控制其分别沿x,y,z轴移动,分别绕自身的x,y,z轴旋转,还可放大缩小,详细操作请见代码中说明文档。
  • 本文在分析和研究OpenGL下实现三维真实感效果处理技术的基础上,在场景中绘制三维物体模型,定义了光照模型、材质属性、视口大小、投影方式和纹理映射,从而实现了三维图形的真实感显示,并具有改变光照条件,设置渲染...
  • OpenGL三维几何变换

    2021-06-24 16:08:31
    OpenGL平移 glTranslatef( Tx , Ty , Tz ) OpenGL—旋转 绕x轴旋转: glRotatef( degree, 1, 0, 0 ); 绕y轴旋转: glRotatef( degree, 0, 1, 0 ); 绕z轴旋转: glRotatef( degree, 0, 0, 1 ); 绕任意轴旋转: ...
  • OpenGL三维图形系统开发与实用技术.实用技术篇(源码)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,224
精华内容 4,889
关键字:

opengl绘制三维图形