前几天学习了OpenGL的绘图原理(其实就是坐标的不停变换变换),看到网上有个比较好的例程,于是学习了下,并在自己感兴趣的部分做了注释。

首先通过glMatrixMode(GL_MODELVIEW)设置当前操作的矩阵为模型视图矩阵,然后通过glPushMatrix()和glPopMatrix()函数对矩阵进行压栈出栈操作。

对矩阵进行压栈操作实际上是将当前的模型视图矩阵保存起来,相当于:我对一份代码或者数据进行修改,我对代码或者数据改来改去之后不想再啰啰嗦嗦麻麻烦烦的“逆操作”恢复代码或者数据的原貌,很简单,在操作代码或者数据之前先备份一下。

对矩阵进行出栈操作就是恢复栈顶矩阵对应的模型视图状态。相当于:我在操作一份代码或者数据前,先备份了它,现在我操作完达到我想要的效果了; 接下来我要基于原代码或者原数据进行其他操作,怎么办?恢复之前备份的数据呗。

当然,我不仅可以保存初始模型视图矩阵(对它进行压栈),而且还可以保存任何阶段的模型视图矩阵(只要有必要)。

代码基于传统的OpenGL,参照工程的附加依赖项就知道我用的是哪个版本了:glaux.lib;glu32.lib;opengl32.lib;glut32.lib;glut.lib;

代码如下:

#include <GL/glut.h>

void init(void)
{
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(-5.0, 5.0, -5.0, 5.0);  // 设置显示的范围是X:-5.0~5.0, Y:-5.0~5.0
    glMatrixMode(GL_MODELVIEW);  // 设置当前操作的矩阵为“模型视图矩阵”
}

void drawSquare(void)  // 绘制中心在原点,边长为2的正方形
{
    glBegin(GL_POLYGON);

    glVertex2f(-1.0f, -1.0f);  // 左下点
    glVertex2f(1.0f, -1.0f);  // 右下点
    glVertex2f(1.0f, 1.0f);  // 右上点
    glVertex2f(-1.0f, 1.0f);  // 左上点

    glEnd();
}

void myDraw(void)
{
    glClear(GL_COLOR_BUFFER_BIT);  // 清空

    // 将坐标原点移动到屏幕中心  类似于复位
    glLoadIdentity();

    // 压栈  栈顶为屏幕中心的模型视图矩阵
    glPushMatrix();

    // 移动坐标原点
    glTranslatef(0.0f, 2.0f, 0.0f);
    // 三个参数依次为模型在x,y,z轴方向的缩放比
    // 参数也可取负数,也可以理解为先关于某轴翻转180°,再缩放;
    glScalef(3.0, 0.5, 1.0);
    // 设置要使用的颜色  R、G、B  这里为红色
    glColor3f(1.0, 0.0, 0.0);
    drawSquare();

    // 出栈  恢复为原始模型视图矩阵
    glPopMatrix();

    // 压栈  栈顶为原始模型视图矩阵
    glPushMatrix();

    glTranslatef(-3, 0.0, 0.0);

    // 压栈  栈顶为中间左菱形(-3, 0, 0)的模型视图矩阵
    glPushMatrix();

    // 符合右手定则  (0.0, 0.0, 1.0)为绕着Z轴
    // +45.0代表右手定则按照Z轴的正向(从里到外)握,即逆时针方向
    glRotatef(45.0, 0.0, 0.0, 1.0);
    glColor3f(0.0, 1.0, 0.0);
    drawSquare();  // 左边菱形

    // 出栈  恢复为中间左菱形模型视图矩阵
    glPopMatrix();

    glTranslatef(3.0, 0.0, 0.0);

    // 压栈  经过坐标变换当前为屏幕中心了  栈顶为为屏幕中心模型视图矩阵
    glPushMatrix();

    glRotatef(45.0, 0.0, 0.0, 1.0);
    glColor3f(0.0, 0.7, 0.0);
    drawSquare();  // 中间菱形

    // 出栈  恢复为屏幕中心模型视图矩阵
    glPopMatrix();

    glTranslatef(3.0, 0.0, 0.0);

    // 压栈  栈顶为中间右菱形的模型视图矩阵
    glPushMatrix();

    glRotatef(45.0, 0.0, 0.0, 1.0);
    glColor3f(0.0, 0.4, 0.0);
    drawSquare();  // 右边菱形

    // 出栈  恢复中间右菱形的模型视图矩阵
    glPopMatrix();

    // 出栈  恢复屏幕中心模型视图矩阵
    glPopMatrix();

    glTranslatef(0.0, -3.0, 0.0);
    glScalef(4.0, 1.5, 1.0);
    glColor3f(0.0, 0.0, 1.0);
    drawSquare();  // 下面蓝色矩形

    glFlush();
}

void main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(600, 600);
    glutCreateWindow("几何变换函数综合示例");

    init();
    glutDisplayFunc(myDraw);
    glutMainLoop();
}

简单理解OpenGL模型视图变换的更多相关文章

  1. OpenGL模型视图变换、投影变换、视口变换的理解

    OpenGL中不设置模型,投影,视口,所绘制的几何图形的坐标只能是-1到1(X轴向右,Y轴向上,Z轴垂直屏幕向外). 产生目标场景的过程类似于用照相机进行拍照: (1)把照相机固定在三角架上,并让他对 ...

  2. OpenGL学习笔记4——模型视图变换

    以日月地为例的一个模型视图变换.绕了比较多的弯路,下面是几个注意点总结. 注意点: 1.GL函数对模型的操作是基于当前局部坐标系,即模型坐标系而非世界坐标系,二者只在第一次初始化完毕之后才重合: 2. ...

  3. 【GISER&&Painter】Chapter02:WebGL中的模型视图变换

    上一节我们提到了如何在一张画布上画一个简单几何图形,通过创建画布,获取WebGLRendering上下文,创建一个简单的着色器,然后将一些顶点数据绑定到gl的Buffer中,最后通过绑定buffer数 ...

  4. OpenGL的视图变换、模型变换、投影变换、视口变换

    产生目标场景的过程类似于用照相机进行拍照: (1) 把照相机固定在三角架上,并让他对准场景从不同位置观察场景(视图变换) gluLookAt (2) 对场景进行安排,使各个物体在照片中的位置是我们所希 ...

  5. Opengl使用模型视图变换移动光源

    光源绕一个物体旋转,按下鼠标左键时,光源位置旋转. #include <GL/glut.h> static int spin = 0;static GLdouble x_1 = 0.0;s ...

  6. OpenGL 模型视图投影矩阵 仿射矩阵

    矩阵基础知识 要对矩阵进行运算,必须先要了解矩阵的计算公式,这个知识的内容涉及到了线性代数. 我们知道在Cocos2dx中,有关于平移,旋转,缩放等等操作,都必须要进行矩阵的乘法. 只需要一张图就能理 ...

  7. OpenGL(五) 三维变换之模型视图矩阵

    计算机三维图形学中,一个基本的任务是如何描述三维空间中一个物体位置的变化,也就是如何 描述物体的运动.通常情况下,物体位置的变化包含三个基本的变化:平移.旋转和缩放,物体的运动也可以用这三个基本的运动 ...

  8. OpenGl学习笔记3之模型变换、视图变换、投影变换、视口变换介绍

    模型变换.视图变换.投影变换.视口变换介绍 opengl中存在四种变换,分别是模型变换,视图变换,投影变换,视口变换.这四种变换是图形渲染的基本操作,实质上这四种变换都是由矩阵乘法表示(这些操作都是由 ...

  9. 详解OpenGL中的各种变换(投影变换,模型变换,视图变换)(完)——法线变换

    前面两节内容已经说完了所有的三种变换.也就是说我们现在程序里面既不需要glLookAt(),也不需要gluPerspective(),这些矩阵我们都可以自己写.然后,再用glMultMatrix()来 ...

随机推荐

  1. C#只能运行一个实例程序的方法

    互斥进程(程序), 简单点说,就是在系统中只能有该程序的一个实例运行. 现在很多软件都有这功能,如Maxthon 可以设置为"只允许打开一个窗体",还有Bitcomet等. 我也是 ...

  2. 《天书夜读:从汇编语言到windows内核编程》六 驱动、设备、与请求

    1)跳入到基础篇的内核编程第7章,驱动入口函数DriverEnter的返回值决定驱动程序是否加载成功,当打算反汇编阅读驱动内核程序时,可寻找该位置. 2)DRIVER_OBJECT下的派遣函数(分发函 ...

  3. [转载] 一致性hash算法释义

    转载自http://www.cnblogs.com/haippy/archive/2011/12/10/2282943.html 一致性Hash算法背景 一致性哈希算法在1997年由麻省理工学院的Ka ...

  4. 模仿J2EE的session机制的App后端会话信息管理

    此文章只将思想,不提供具体完整实现(博主太懒,懒得整理),有疑问或想了解的可以私信或评论 背景 在传统的java web 中小型项目中,一般使用session暂存会话信息,比如登录者的身份信息等.此机 ...

  5. bootstrap --> reset css

    /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) */ html, ...

  6. [转]the service mysql57 failed the most recent status[/br]mysql57 was not found解决办法

    转自:http://forums.mysql.com/read.php?169,622722,622877#msg-622877 安装完mysql5.7.12后想要stop或者restart都会出现以 ...

  7. PHP中MD5函数漏洞

    题目描述 一个网页,不妨设URL为http://haha.com,打开之后是这样的 if (isset($_GET['a']) and isset($_GET['b'])) { if ($_GET[' ...

  8. R-CNN论文翻译

    R-CNN论文翻译 Rich feature hierarchies for accurate object detection and semantic segmentation 用于精确物体定位和 ...

  9. TypeScript入门,使用TypeScript编写第三方控件的方式!

    这是一篇新手篇的typescript插件编写方式!!!! 源码完整地址:https://gitee.com/dissucc/typescriptLearn 1.环境安装 node下载 下载地址:htt ...

  10. webuploader 实现图片批量上传

    1.导入资源 2.JSP代码 <div class="page-container"> <div class="row cl"> < ...