Chapter5 OpenGL变换

几种不同的变换:

  • 视图变换:从不同的位置去观察它
  • 模型变换:移动、旋转、放大、缩放
  • 近大远小的透视效果、投影变换

5.1 模型变换和视图变换

从“相对移动”的观点来看,改变观察点的位置与方向改变物体本身的位置与方向具有等效性。在OpenGL中,实现这两种功能甚至使用的是同样的函数。

由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为“模型视图矩阵”。设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数:

glMatrixMode(GL_MODELVIEW);

通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。这也只需要一行代码:

glLoadIdentity();

模型和视图变换主要涉及3个函数(对应移动旋转缩放):

  • glTranslate*把当前矩阵和一个表示移动物体的矩阵相乘。三个参数分别表示了在三个坐标上的位移值。
    void glTranslatef (GLfloat x, GLfloat y, GLfloat z);

  • glRotate*把当前矩阵和一个表示旋转物体的矩阵相乘。物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数angle表示旋转的角度。
    void glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLfloat z)

    使用右手定则,从大拇指的方向为(0,0,0)到(x,y,z)的方向,然后四指的方向为旋转的方向。

  • glScale*把当前矩阵和一个表示缩放物体的矩阵相乘。x,y,z分别表示在该方向上的缩放比例。
    void glScalef (GLfloat x, GLfloat y, GLfloat z)

需要特别注意的点如下!!!总的来说就是实际的变换的顺序和代码中写的顺序是相反的,原因是矩阵相乘的结合律

假设当前矩阵为单位矩阵,然后先乘以一个表示旋转的矩阵R,再乘以一个表示移动的矩阵T,最后得到的矩阵再乘上每一个顶点的坐标矩阵v。所以,经过变换得到的顶点坐标就是((RT)v)。由于矩阵乘法的结合率,((RT)v) = (R(Tv)),换句话说,实际上是先进行移动,然后进行旋转。即:实际变换的顺序与代码中写的顺序是相反的。由于“先移动后旋转”和“先旋转后移动”得到的结果很可能不同,初学的时候需要特别注意这一点。

或者,不如换一种思路?
让我们想象,坐标并不是固定不变的。旋转的时候,坐标系统随着物体旋转。移动的时候,坐标系统随着物体移动。如此一来,就不需要考虑代码的顺序反转的问题了。

以上都是针对改变物体的位置和方向来介绍的。如果要改变观察点的位置,除了配合使用glRotateglTranslate函数以外,还可以使用这个函数:gluLookAt。它的参数比较多,前三个参数表示了观察点的位置,中间三个参数表示了观察目标的位置,最后三个参数代表从(0,0,0)到(x,y,z)的直线,它表示了观察者认为的“上”方向。

void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
该函数定义一个视图矩阵,并与当前矩阵相乘。
第一组eyex, eyey,eyez相机在世界坐标的位置
第二组centerx,centery,centerz相机镜头对准的物体在世界坐标的位置
第三组upx,upy,upz相机向上的方向在世界坐标中的方向
你把相机想象成为你自己的脑袋:
第一组数据就是脑袋的位置
第二组数据就是眼睛看的物体的位置
第三组就是头顶朝向的方向(因为你可以歪着头看同一个物体)。
原文链接:https://blog.csdn.net/qq_34911636/article/details/86686906

5. 2 投影变换

投影变换就是定义一个可视空间,可视空间以外的物体不会被绘制到屏幕上。(注意,从现在起,坐标可以不再是-1.0到1.0了!)

OpenGL支持两种类型的投影变换:

  • 透视投影
  • 正投影

投影也是使用矩阵来实现的。如果需要操作投影矩阵,需要以GL_PROJECTION为参数调用glMatrixMode函数。

glMatrixMode(GL_PROJECTION);

通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。(和之前一样)

glLoadIdentity();

使用glFrustum函数可以将当前的可视空间设置为透视投影空间。其参数的意义如下图

也可以使用更常用的gluPerspective函数。

如果说gluLookAt定义了相机的位置,那么gluPerspective定义了相机的视野范围,比近裁面(near)近的不会被展示在视野里,同理,比远裁面(far)远的也不会。

void gluPerspective (GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far)

其参数的意义如下图:

正投影相当于在无限远处观察得到的结果,它只是一种理想状态。但对于计算机来说,使用正投影有可能获得更好的运行速度。

使用glOrtho函数可以将当前的可视空间设置为正投影空间。其参数的意义如下图:

如果绘制的图形空间本身就是二维的,可以使用gluOrtho2D。他的使用类似于glOrgho

5.3 视口变换

当一切工作已经就绪,只需要把像素绘制到屏幕上了。这时候还剩最后一个问题:应该把像素绘制到窗口的哪个区域呢?通常情况下,默认是完整的填充整个窗口,但我们完全可以只填充一半。

使用glViewport来定义视口。其中前两个参数定义了视口的左下脚(0,0表示最左下方),后两个参数分别是宽度和高度。

5.4 操作矩阵堆栈

我们在进行矩阵操作时,有可能需要先保存某个矩阵,过一段时间再恢复它。当我们需要保存时,调用glPushMatrix函数,它相当于把矩阵(相当于盘子)放到堆栈上。当需要恢复最近一次的保存时,调用glPopMatrix函数,它相当于把矩阵从堆栈上取下。

OpenGL规定堆栈的容量至少可以容纳32个矩阵,某些OpenGL实现中,堆栈的容量实际上超过了32个。因此不必过于担心矩阵的容量问题。

通常,用这种先保存后恢复的措施,比先变换再逆变换要更方便,更快速。

注意:模型视图矩阵和投影矩阵都有相应的堆栈。使用glMatrixMode来指定当前操作的究竟是模型视图矩阵还是投影矩阵。

5.5 综合举例

#include <GL/glut.h>
// 太阳、地球和月亮
// 假设每个月都是30天
// 一年12个月,共是360天
static int day = 200; // day的变化:从0到359
void myDisplay(void)
{//glEnable(GL_DEPTH_TEST); //启动深度测试(这样后绘制的图形如果在已经存在的图形的前面,它会被遮住,而不是遮住别人glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空颜色和深度缓冲glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(75, 1, 10, 400000000);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);// 绘制红色的“太阳”glColor3f(1.0f, 0.0f, 0.0f);glutSolidSphere(69600000, 20, 20);// 绘制蓝色的“地球”glColor3f(0.0f, 0.0f, 1.0f);glRotatef(day / 360.0 * 360.0, 0.0f, 0.0f, -1.0f);glTranslatef(150000000, 0.0f, 0.0f);glutSolidSphere(15945000, 20, 20);// 绘制黄色的“月亮”glColor3f(1.0f, 1.0f, 0.0f);glRotatef(day / 30.0 * 360.0 - day / 360.0 * 360.0, 0.0f, 0.0f, -1.0f);glTranslatef(38000000, 0.0f, 0.0f);glutSolidSphere(4345000, 20, 20);glFlush();
}int main(int argc, char* argv[])
{glutInit(&argc, argv);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式glutInitWindowPosition(100, 100); //设置窗口位置glutInitWindowSize(400, 400);//窗口大小glutCreateWindow("我的OpenGL程序"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数glutMainLoop(); //进行一个消息循环return 0;
}

OpenGL第五讲——模型视图变换和投影变换相关推荐

  1. 3、计算机图形学——模型视图变换、投影变换与视口变换

    一.模型视图变换 模型视图变换主要是为了让摄像机回归到世界坐标的原点并且和拍摄物体一起进行变换,便于计算 模型视图变换的根据就是物体和相机的相对位置不变,那么,投影得到的图片也是不变的 首先规定相机拍 ...

  2. 实验5 OpenGL模型视图变换

    1.实验目的: 理解掌握OpenGL程序的模型视图变换. 2.实验内容: (1)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换: (2)根据示范代码,尝试完成实验作业: 3.实 ...

  3. 计算机图形学笔记(观测变换、模型变换、视图变换、投影变换、视口变换)

    计算机图形学笔记(观测变换.模型变换.视图变换.投影变换.视口变换) 目录 计算机图形学笔记(观测变换.模型变换.视图变换.投影变换.视口变换) 一.简介 1.模型变换(Model transform ...

  4. 计算机图形学入门(二)-线性代数部分知识2视图变换和投影变换

    本章主要进行了视图/相机变换的求解,和两种投影变换的求解(正交投影.透视投影),并且简单的完善了3D旋转变换的介绍. 主要的学习过程来自下面的视频,本文只会有主要的基础内容,默认一些知识大家是掌握的, ...

  5. OpenGL学习笔记:模型变换、视图变换、投影变换 、视口变换、操作矩阵堆栈

    1. 模型变换和视图变换  从"相对移动"的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性.在OpenGL中,实现这两种功能甚至使用的是同样的函数. 由于模型 ...

  6. 图形学笔记(四)变换——三维变换(三维旋转与欧拉角)、MVP变换、视图变换、投影变换(正交投影与透视投影)

    图形学笔记(三)变换--缩放.镜像.切变 图形学笔记(五)光栅化--屏幕.像素.屏幕空间.视口变换.基础图元与三角形.采样.包围盒.锯齿或走样 文章目录 1 三维空间中的变换 1.1 三维空间中的齐次 ...

  7. 计算机图形学(三维观察投影线、视图变换、投影变换)

    一.三维观察流水线 概念:将建立的三维场景显示在二维视口的过程称为三维观察流水线. 在三维观察流水线中,也就是在将三维场景显示在二维视口的过程中,需要在不同坐标系下进行不同的操作,这些坐标系包括: 建 ...

  8. OpenGL之利用模型视图矩阵和投影矩阵让球体自动旋转

    核心业务 绘制球体(SetupRC()): // 绘制一个球体gltMakeSphere(torusBatch, 0.5f, 10, 20);glPolygonMode(GL_FRONT_AND_BA ...

  9. OpenGL(二)三维变换

    投影变换(三维物体到二维平面投影) 透视投影 void APIENTRY gluPerspective ( GLdouble fovy, //视角 GLdouble aspect, //宽高比 GLd ...

最新文章

  1. SPU表管理之更新SPU表数据
  2. VS2012生成ReactOS的VS工程失败(三)和 “ cl is not able to compile a simple test program“错误
  3. Verdi-ug --- nschema Tutorial
  4. java打印 a b c,创建一个java程序,按顺序给出3个术语作为输入(a,b,c)打印它们的根...
  5. 理论计算机科学研究生,清华大学理论计算机科学中心姚期智组招收保送研究生,请帮忙发到虎...
  6. 关于Oracle-SQL语句性能优化
  7. 1招提升Java单元测试ROI
  8. TypeError: format expected at most 2 arguments, got 7
  9. maven仓库如何加载瀚高数据库JDBC驱动
  10. 《黑客秘笈——渗透测试实用指南(第2版)》—第1章1.5节构建渗透测试环境...
  11. td超过的文字设置省略号
  12. Android 65536错误:Cannot fit requested classes in a single dex file
  13. offlc计算机等级报一级还是二级,请问计算机二级MS Office 和MS Office高级应用是一个东西吗?...
  14. java,内存,存储
  15. 作业20171127-4 事后诸葛亮会议
  16. 购买服务器,80端口的开启
  17. 这8大技术趋势,将塑造未来科技行业格局
  18. 移动web(h5页面)适配
  19. 苹果手机软件升级密码_金水区正规苹果手机怎么只换外屏价目表
  20. W32Dasm 的学习日记

热门文章

  1. 字节流与字符流的区别详解
  2. 攻防世界-MISC:give_you_flag
  3. Elasticsearch通关教程(五):如何通过SQL查询Elasticsearch
  4. vue+element小票打印、58小票打印机
  5. 医疗急救卡-数据API
  6. 计算机安全学第2版pdf,计算机安全学讲义_第三讲:消息认证.pdf
  7. 在64位虚拟机上编译C程序为32位的可执行文件
  8. 冲量在线携手滴普科技,共同面向客户提供全栈数字化创新服务
  9. druid连接池参数配置不当引起接口耗时长
  10. 【Linux基础】四、常用基本命令——文件权限类(ls -al,chmod,chown,chgrp)、搜索查找类(find,locate,grep,wc,which)