引言

opengl提供的几何变换函数和绘图函数是完全分开的,并没有指定一个变换矩阵然后再绘图的API。
opengl是先使用几何变换函数,此时相当于永久改变了坐标系,此后的所有绘图操作都相当于在新坐标系下进行。
如 glTranslatef(100, 100, 0); 相当于把当前坐标轴向x轴正向和y轴正向同时移动100个单位,此后所有的绘图函数都参照此新坐标系进行。此时如果在新坐标系原点绘制一个点,相当于在原坐标系的(100,100)处绘制一个点

opengl一共有四个矩阵栈,应用于不同的变换用途,对物体进行几何变换时。首先需要调用glMatrixMode(GL_MODELVIEW);
切换到几何变换矩阵栈
使用glLoadIdentity();将当前矩阵设置为单位矩阵,代表无任何变换。
之后调用的所有矩阵变换函数都相当于右乘一个变换矩阵。只要不调用glLoadIdentity();重置为单位矩阵,所有的变换函数都会累乘起来。
所以在两个不同的变换之间需要重置变换矩阵。

opengl一共提供了三种简易的几何变换,使用时只要调用几个简单的函数,内部就会自动根据这些参数构建矩阵。
同时也提供了自己直接构建矩阵的函数。
以下是一些具体的例子。



opengl二维平移变换

    //opengl平移变换//绘制变换前的矩形glColor3f(1, 0, 0);glRecti(100, 100,200,200);//重置矩阵变换栈glMatrixMode(GL_MODELVIEW);glLoadIdentity();//构建平移矩阵glTranslatef(200, 0, 0);//绘制变换后的矩形glColor3f(0, 1, 0);glRecti(100, 100, 200, 200);

opengl使用glTranslatef构建平移矩阵,参数分别为朝x,y,z轴移动的方向,二维变换时第三个参数设为0,代表在z轴上不发生移动。
最后绘制矩形,可以看到矩形向右移动了200像素



opengl二维旋转变换

    //opengl旋转变换//绘制变换前的矩形glColor3f(1, 0, 0);glRecti(100, 100, 200, 200);//重置矩阵变换栈glMatrixMode(GL_MODELVIEW);glLoadIdentity();//构建旋转矩阵glRotatef(30, 0, 0, 1);//绘制变换后的矩形glColor3f(0, 1, 0);glRecti(100, 100, 200, 200);

opengl没有专为二维平面构建旋转矩阵的函数,所以只能使用三维旋转函数来构建二维旋转矩阵。

在三维中进行一次旋转需要确定旋转轴和旋转角度,其中旋转轴即三维空间中的一条直线,需要同时用一个三维点和一个三维方向向量来确定,或者使用两个三维点来确定一条直线。所以需要六个参数来确定一条旋转轴。而opengl没有一个单独的函数来完成绕指定旋转轴的旋转。opengl的旋转轴默认经过原点,只能指定朝向,因此只需要三个参数。想要完成绕任意旋转轴旋转需要复合平移变换。

opengl使用 glRotatef函数构建旋转矩阵。一共有四个参数。第一个参数为旋转角度,后面三个参数确定旋转轴的朝向,此轴默认经过原点。在二维变换中,旋转轴即为任意垂直于xy平面的一个向量,因此填入(0,0,1)。需要注意的是第一个参数为角度而不是弧度,许多其他图形系统的API都为弧度。

以下为绕经过原点并垂直于xy平面的旋转轴逆时针旋转30度的效果。



opengl二维缩放变换

    //opengl缩放变换//绘制变换前的矩形glColor3f(1, 0, 0);glRecti(100, 100, 200, 200);//重置矩阵变换栈glMatrixMode(GL_MODELVIEW);glLoadIdentity();//构建缩放矩阵glScalef(0.5, 0.5, 0);//绘制变换后的矩形glColor3f(0, 1, 0);glRecti(100, 100, 200, 200);

opengl也没有专为二维平面构建缩放矩阵的函数,所以只能使用三维缩放函数来构建二维缩放矩阵。
opengl使用 glScalef函数构建缩放矩阵。有三个参数,分别是沿x,y,z轴的缩放参数,大于1代表扩大,小于1代表缩小。要构建二维缩放矩阵只要把第三个参数设为1即可,代表在z轴上不发生变化。
缩放变化同时还需要一个缩放参照点,因为缩放变化不仅改变自身大小,也改变了自身到缩放点的距离。
可以看到进行变换之后,绿色矩阵不仅更小了,而且离原点更近了,这就是因为opengl默认使用原点作为缩放变换的参照点。



绕指定点旋转

通过上面三个例子,我们可以看到,除了平移变换不需要参照点之外,旋转变换和缩放变换都是需要一个参照点的,而opengl默认他们为原点。那么如果需要设置这个点的话,就需要嵌套矩阵,沿着任意点缩放也是同理。
以绕物体自身中心旋转为例,需要先用平移矩阵将物体的中心移动到原点,旋转之后再将其移动到原位置,一共需要嵌套三个矩阵。

    //opengl绕中心旋转变换glMatrixMode(GL_MODELVIEW);glLoadIdentity();//逆旋转矩阵,即把物体移动回原来的位置glTranslatef(150, 150,0);//复合旋转矩阵glRotatef(45, 0, 0, 1);//构建平移矩阵将物体中心移动到原点glTranslatef(-150, -150, 0);glColor3f(1, 0, 0);glRecti(100, 100, 200, 200);

运行代码之后物体绕自己的中心旋转了45度。
需要注意的是opengl的变换函数最后调用函数的是最先应用的矩阵,所以看复合矩阵代码时应该从下往上看,才是正确的矩阵应用顺序。
此例中就是glTranslatef(-150, -150, 0);构建的矩阵最先被应用于变换中
用数学语言来说就是从上到下矩阵依次右乘于前一个矩阵。
如A* B *C 构成一个复合矩阵,那么最右边的C是最先被应用的。



对称于指定轴

opengl没有原生的对称方法,可以自己使用glLoadMatrixf或glMultMatrixf来构建一个对称矩阵。
因为矩阵在opengl内部以齐次坐标表示,所以即使只需要进行二维变换,也需要输入4*4=16个参数。
对着y轴对称的齐次矩阵为

    GLfloat arr[16] ={-1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};

对称于指定轴变换,则需要先把该轴通过变换重合于坐标轴,然后进行对称操作之后再使用逆对称变换回原位置。
以一个矩阵沿着y=x-50对称为例,
先将其平移成经过原点的直线,再旋转使其于y轴重合,然后乘上对着y轴对称的矩阵,然后再用逆矩阵将他变换回原位置。
矩阵变换部分同样需要从下往上读,才是正确的变换顺序。
代码如下

    //opengl对称于指定轴glMatrixMode(GL_MODELVIEW);glLoadIdentity();//画出该轴作为参考glColor3f(0, 0, 1);glBegin(GL_LINES);glVertex2i(0, -50);glVertex2i(500, 450);glEnd();//画出原矩形glColor3f(1, 0, 0);glRecti(400, 200, 450, 250);// 逆平移回原位置glTranslatef(50, 0, 0);//逆旋转45glRotatef(-45, 0, 0, 1);//乘上对称矩阵GLfloat arr[16] ={-1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};glMultMatrixf(arr);//旋转45度使其重合于y轴(也可以重合于x轴,只要之后进行对应的逆变换即可)glRotatef(45, 0, 0, 1);//先把对称轴平移到原点glTranslatef(-50, 0, 0);glColor3f(0, 1, 0);glRecti(400, 200, 450, 250);

效果如下



绕指定点旋绕2

再来一个绕指定点旋转的例子,此时该点不在对象内部。
使用for循环每次绕(200,200)点旋转10度,同时画出了旋转中心到物体中心的参考线

//opengl绕指定点旋转2//假设绕点(200,200)旋转360度glMatrixMode(GL_MODELVIEW);glLoadIdentity();for (int i = 0; i < 36; i++){glColor3f(1-1/36.f*i, 1/36.f*i, 0);glRecti(100, 100, 120, 120);//画出参考线glColor3f(0, 0, 0);glBegin(GL_LINES);glVertex2f(200, 200);glVertex2f(110, 110);glEnd();glTranslatef(200, 200, 0);glRotatef(10, 0, 0, 1);glTranslatef(-200, -200, 0);}



opengl斜切变换

斜切变换需要自己构建矩阵,斜切变换相当于固定一条坐标轴不变而旋转另一条坐标轴,即旋转后坐标轴不相互垂直。

    //opengl斜切变换glMatrixMode(GL_MODELVIEW);glLoadIdentity();glColor3f(0, 0, 1);glRecti(100, 100, 200, 200);GLfloat arr[16] ={1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1};glMultMatrixf(arr);glColor3f(0, 1, 1);glRecti(100, 100, 200, 200);

效果如下,此时坐标轴之间不相互垂直



以上代码只要加到display函数里即可运行

#include<glut.h>
int main(int argc, char** argv)
{    glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(500, 500);glutInitWindowSize(500, 500);glutCreateWindow("title");init();glutDisplayFunc(display);glutMainLoop();}
void display()
{}
void init()
{glClearColor(1, 1, 1, 1);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, 500, 0, 500);
}

opengl二维几何变换实例相关推荐

  1. OpenGL——二维几何变换

    平移.旋转.缩放的实现 #include<iostream> #include <math.h> #include<Windows.h> #include < ...

  2. 计算机图形学头歌实训平台作业OpenGL二维几何变换

    二维几何变换 第1关 正方形的平移与缩放 第2关 正方形的平移和旋转 第3关 正方形的变换组合 第4关 三菱形状 第1关 正方形的平移与缩放 // 提示:写完代码请保存之后再进行评测 #include ...

  3. 计算机图形学基础:实验5 OpenGL二维几何变换

    1.实验目的: 理解并掌握OpenGL二维平移.旋转.缩放变换的方法. 2.实验内容: 阅读实验原理,掌握OpenGL程序平移.旋转.缩放变换的方法. 根据示范代码,完成实验作业. 3.实验原理: ( ...

  4. 计算机图形与OpenGL学习五(二维几何变换1.平移、旋转、缩放)

    二维几何变换(平移.旋转.缩放) 本章涉及数学变换比较多,代码是次要的,数学理论可自己推导一下. [二维平移] 通过将二维量加到一个点的坐标上来生成一个新的坐标位置,可以实现一次平移.将平移距离加到原 ...

  5. 计算机图形学笔记——第7章 二维几何变换 Python

    第7章 二维几何变换 应用于对象几何描述并改变它的位置.方向或大小的操作称为几何变换(geometric transformation). 几何变换有时也称为建模变换(modeling transfo ...

  6. 计算机图形学 学习笔记 二维几何变换

    应用于对象几何描述并改变它的位置.方向或大小的操作称为几何变换. 几何变换有时也称为建模变换.建模变换一般用于构造场景或给出由多个部分组合而成的复杂对象的层次式描述等.另一方面,几何变换能用来描述动画 ...

  7. c语言二维图形变换程序,【计算机图形学】3-2 二维几何变换根本代码

    [计算机图形学]3-2 二维几何变换基本代码 返回目录 基本理论参见:[计算机图形学]3-1 二维几何变换基本理论 注:这里不考虑插值的问题. 全部的代码都在https://github.com/Cy ...

  8. python随机生成二维列表_对python产生随机的二维数组实例详解

    对python产生随机的二维数组实例详解 最近找遍了python的各个函数发现无法直接生成随机的二维数组,其中包括random()相关的各种方法,都没有得到想要的结果.最后在一篇博客中受到启发,通过列 ...

  9. python中的二维数组_Python中的二维数组实例(list与numpy.array)

    关于python中的二维数组,主要有list和numpy.array两种. 好吧,其实还有matrices,但它必须是2维的,而numpy arrays (ndarrays) 可以是多维的. 我们主要 ...

最新文章

  1. linux sort 排序命令简介
  2. linux gcc 包含头文件 动态库 静态库 链接路径问题
  3. 区块链BaaS云服务(21)腾讯CCGP“治理链”
  4. window 任务管理器
  5. make run_py时ImportError: No module named cv2
  6. HALCON示例程序dem_trees.hdev提取树
  7. Java 反射机制详解:私有方法调用头大?如何通过反射调用类中的私有方法?
  8. tushare调用API获取金融相关数据
  9. ggplot2作图详解:标尺(scale)设置
  10. php大量邮件,PHPMailer批量发送邮件的实例代码
  11. 游戏音效制作初学者的福音—入门级软件介绍
  12. markdown画图之一:流程图(flowchart)
  13. if语句——python
  14. [极致用户体验] 网页里的「返回」应该用 history.back 还是 push ?
  15. 最新kali之nmap
  16. 图片批量重命名方法(超详细 无需辅助软件 本地运行)
  17. uTorrent 2.2.1 高级参数设置详解及优化(转载)
  18. 将汉字转换为拼音或者翻转
  19. 【python】数组内某数加一如何实现?
  20. 阿里巴巴惠普_阿里巴巴UCAN设计课程学习笔记

热门文章

  1. 在线考试系统/在线学习系统
  2. Leetcode动态规划专题(共38道)
  3. strace java_Linux strace命令
  4. python查看网速,python如何查看系统网络流量的信息
  5. DIY 一个树莓派无人机
  6. ABBYY Lingvo European for Mac(万能词典) v1.12.0
  7. 正面管教PHP沙龙,“正面管教”家长沙龙活动回顾
  8. 电工实训考核装置柜式双面型QY-W760C
  9. Java数据结构之栈详解
  10. Android工程师遇到瓶颈后转行什么最好?https://blog.csdn.net/feiyu1947/article/details/86438086