转自:http://www.cnblogs.com/opengl/archive/2012/10/30/2747130.html

1.实验目的:

理解掌握一个OpenGL程序平移、旋转、缩放变换的方法。

2.实验内容:

(1)阅读实验原理,运行示范实验代码,掌握OpenGL程序平移、旋转、缩放变换的方法;

(2)根据示范代码,尝试完成实验作业;

3.实验原理:

(1)OpenGL下的几何变换

在OpenGL的核心库中,每一种几何变换都有一个独立的函数,所有变换都在三维空间中定义。

平移矩阵构造函数为glTranslate<f,d>(tx, ty, tz),作用是把当前矩阵和一个表示移动物体的矩阵相乘。tx, ty,tz指定这个移动物体的矩阵,它们可以是任意的实数值,后缀为f(单精度浮点float)或d(双精度浮点double),对于二维应用来说,tz=0.0。

旋转矩阵构造函数为glRotate<f,d>(theta, vx, vy, vz),作用是把当前矩阵和一个表示旋转物体的矩阵相乘。theta, vx, vy, vz指定这个旋转物体的矩阵,物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数theta表示旋转的角度。向量v=(vx, vy,vz)的分量可以是任意的实数值,该向量用于定义通过坐标原点的旋转轴的方向,后缀为f(单精度浮点float)或d(双精度浮点double),对于二维旋转来说,vx=0.0,vy=0.0,vz=1.0。

缩放矩阵构造函数为glScale<f,d>(sx, sy, sz),作用是把当前矩阵和一个表示缩放物体的矩阵相乘。sx, sy,sz指定这个缩放物体的矩阵,分别表示在x,y,z方向上的缩放比例,它们可以是任意的实数值,当缩放参数为负值时,该函数为反射矩阵,缩放相对于原点进行,后缀为f(单精度浮点float)或d(双精度浮点double)。

注意这里都是说“把当前矩阵和一个表示移动<旋转, 缩放>物体的矩阵相乘”,而不是直接说“这个函数就是旋转”或者“这个函数就是移动”,这是有原因的,马上就会讲到。

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

(2)OpenGL下的各种变换简介

我们生活在一个三维的世界——如果要观察一个物体,我们可以:

1、从不同的位置去观察它(人运动,选定某个位置去看)。(视图变换)

2、移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它(物体运动,让人看它的不同部分)。(模型变换)

3、如果把物体画下来,我们可以选择:是否需要一种“近大远小”的透视效果。另外,我们可能只希望看到物体的一部分,而不是全部(指定看的范围)。(投影变换)

4、我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部(指定在显示器窗口的那个位置显示)。(视口变换)

这些,都可以在OpenGL中实现。

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

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

glMatrixMode(GL_MODELVIEW);

该语句指定一个4×4的建模矩阵作为当前矩阵。

通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。把当前矩阵设置为单位矩阵的函数为:

glLoadIdentity();

我们在进行矩阵操作时,有可能需要先保存某个矩阵,过一段时间再恢复它。当我们需要保存时,调用glPushMatrix()函数,它相当于把当前矩阵压入堆栈。当需要恢复最近一次的保存时,调用glPopMatrix()函数,它相当于从堆栈栈顶弹出一个矩阵为当前矩阵。OpenGL规定堆栈的容量至少可以容纳32个矩阵,某些OpenGL实现中,堆栈的容量实际上超过了32个。因此不必过于担心矩阵的容量问题。

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

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

4.示范代码:

(1)、Translate示例

#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 myDraw1 (void)

{

glClear (GL_COLOR_BUFFER_BIT); //清空

glLoadIdentity(); //将当前矩阵设为单位矩阵

glColor3f (1.0, 0.0, 0.0);

drawSquare(); //在原点处绘制边长为2红色正方形

glTranslatef(2.0,3.0,0.0); //向右移动2单位,向上移动3单位

glColor3f (0.0, 1.0, 0.0);

drawSquare(); //绘制边长为2绿色正方形

glTranslatef(0.0,-3.0,0.0); //再向下移动3单位

glColor3f (0.0, 0.0, 1.0);

drawSquare(); //绘制边长为2蓝色正方形

glFlush ( );

}

void myDraw2 (void)

{

glClear (GL_COLOR_BUFFER_BIT); //清空

glLoadIdentity(); //将当前矩阵设为单位矩阵

glColor3f (1.0, 0.0, 0.0);

drawSquare(); //在原点处绘制边长为2红色正方形

glPushMatrix();

glTranslatef(2.0,3.0,0.0); //向右移动2单位,向上移动3单位

glColor3f (0.0, 1.0, 0.0);

drawSquare(); //绘制边长为2绿色正方形

glPopMatrix();

glTranslatef(2.0,0.0,0.0); //再向右移动2单位

glColor3f (0.0, 0.0, 1.0);

drawSquare(); //绘制边长为2蓝色正方形

glFlush ( );

}

void main (int argc, char** argv)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

glutInitWindowPosition (0, 0);

glutInitWindowSize (600, 600);

glutCreateWindow ("Translate函数示例");

init();

glutDisplayFunc (myDraw1);

glutMainLoop ( );

}

生成图形:

注意理解:myDraw1()和myDraw2()生成的图形完全相同,为什么?

(2)、Rotate示例

#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 myDraw1 (void)

{

glClear (GL_COLOR_BUFFER_BIT); //清空

glLoadIdentity(); //将当前矩阵设为单位矩阵

glColor3f (1.0, 0.0, 0.0);

drawSquare(); //在原点处绘制边长为2红色正方形

glTranslatef(2.0,3.0,0.0); //向右移动2单位,向上移动3单位

glRotatef(30,0.0,0.0,1.0); //顺时针旋转30角度

glColor3f (0.0, 1.0, 0.0);

drawSquare(); //绘制边长为2绿色正方形

glLoadIdentity(); //将当前矩阵设为单位矩阵

glTranslatef(-2.0,-3.0,0.0); //向左移动2单位,向下移动3单位

glRotatef(-30,0.0,0.0,1.0); //逆时针旋转30角度

glColor3f (0.0, 0.0, 1.0);

drawSquare(); //绘制边长为2蓝色正方形

glFlush ( );

}

void myDraw2 (void)

{

glClear (GL_COLOR_BUFFER_BIT); //清空

glLoadIdentity(); //将当前矩阵设为单位矩阵

glColor3f (1.0, 0.0, 0.0);

drawSquare(); //在原点处绘制边长为2红色正方形

glPushMatrix(); //把当前矩阵压入堆栈

glTranslatef(2.0,3.0,0.0); //向右移动2单位,向上移动3单位

glRotatef(30,0.0,0.0,1.0); //顺时针旋转30角度

glColor3f (0.0, 1.0, 0.0);

drawSquare(); //绘制边长为2绿色正方形

glPopMatrix(); //从堆栈栈顶弹出一个矩阵为当前矩阵

glTranslatef(-2.0,-3.0,0.0); //向左移动2单位,向下移动3单位

glRotatef(-30,0.0,0.0,1.0); //逆时针旋转30角度

glColor3f (0.0, 0.0, 1.0);

drawSquare(); //绘制边长为2蓝色正方形

glFlush ( );

}

void main (int argc, char** argv)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

glutInitWindowPosition (0, 0);

glutInitWindowSize (600, 600);

glutCreateWindow ("Rotate函数示例");

init();

glutDisplayFunc (myDraw1);

glutMainLoop ( );

}

生成图形:

注意理解:myDraw1()和myDraw2()生成的图形完全相同,为什么?

(3)、Scale示例

#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 myDraw1 (void)

{

glClear (GL_COLOR_BUFFER_BIT); //清空

glLoadIdentity(); //将当前矩阵设为单位矩阵

glColor3f (1.0, 0.0, 0.0);

drawSquare(); //在原点处绘制边长为2红色正方形

glTranslatef(2.0,3.0,0.0); //向右移动2单位,向上移动3单位

glScalef(1.0,1.5,1.0); //X和Z方向保持不变,Y方向放大为原来的1.5倍

glColor3f (0.0, 1.0, 0.0);

drawSquare(); //绘制边长为2绿色正方形

glLoadIdentity(); //将当前矩阵设为单位矩阵

glTranslatef(-2.0,-3.0,0.0); //向左移动2单位,向下移动3单位

glScalef(0.5,1.5,1.0); //Z方向保持不变,X方向缩小为原来的0.5倍,Y方向放大为原来的1.5倍

glColor3f (0.0, 0.0, 1.0);

drawSquare(); //绘制边长为2蓝色正方形

glFlush ( );

}

void myDraw2 (void)

{

glClear (GL_COLOR_BUFFER_BIT); //清空

glLoadIdentity(); //将当前矩阵设为单位矩阵

glColor3f (1.0, 0.0, 0.0);

drawSquare(); //在原点处绘制边长为2红色正方形

glPushMatrix(); //把当前矩阵压入堆栈

glTranslatef(2.0,3.0,0.0); //向右移动2单位,向上移动3单位

glScalef(1.0,1.5,1.0); //X和Z方向保持不变,Y方向放大为原来的1.5倍

glColor3f (0.0, 1.0, 0.0);

drawSquare(); //绘制边长为2绿色正方形

glPopMatrix(); //从堆栈栈顶弹出一个矩阵为当前矩阵

glTranslatef(-2.0,-3.0,0.0); //向左移动2单位,向下移动3单位

glScalef(0.5,1.5,1.0); //Z方向保持不变,X方向缩小为原来的0.5倍,Y方向放大为原来的1.5倍

glColor3f (0.0, 0.0, 1.0);

drawSquare(); //绘制边长为2蓝色正方形

glFlush ( );

}

void main (int argc, char** argv)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

glutInitWindowPosition (0, 0);

glutInitWindowSize (600, 600);

glutCreateWindow ("Scale函数示例");

init();

glutDisplayFunc (myDraw1);

glutMainLoop ( );

}

生成图形:

注意理解:myDraw1()和myDraw2()生成的图形完全相同,为什么?

(4)、综合示例

#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);

glScalef(3.0,0.5,1.0);

glColor3f (1.0, 0.0, 0.0);

drawSquare(); //上面红色矩形

glPopMatrix();

glPushMatrix();

glTranslatef(-3.0,0.0,0.0);

glPushMatrix();

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 ( );

}

生成图形:

5. 实验作业:

绘制如下图形:

提示:

(1)写一个绘制菱形的函数drawDiamond(void);

void drawDiamond(void) //绘制中心在原点的菱形

{

glBegin (GL_POLYGON); //顶点指定需要按逆时针方向

glVertex2f (0.0f,-1.0f);//下点

glVertex2f (2.0f,0.0f);//右点

glVertex2f (0.0f, 1.0f);//上点

glVertex2f (-2.0f,0.0f);//左点

glEnd ( );

}

(2)用几何变换绘制三个不同位置、旋转角度、颜色的菱形。

附:带批处理安装的GLUT安装包:http://files.cnblogs.com/opengl/glut-install.rar

实验3 OpenGL几何变换的更多相关文章

  1. 4.4.2 OpenGL几何变换编程实例

    程序运行结果如下图: #include <GL/glut.h> #include <stdlib.h> #include <math.h> /* 初始化显示窗口大小 ...

  2. 实验1 OpenGL初识

    实验预备知识 Windows下的OpenGL编程步骤简单介绍详见课程实验教学博客-实验准备安装GLUT包与创建工程: http://www.cnblogs.com/opengl/archive/201 ...

  3. 实验7 OpenGL光照

    一.实验目的: 了解掌握OpenGL程序的光照与材质,能正确使用光源与材质函数设置所需的绘制效果. 二.实验内容: (1)下载并运行Nate Robin教学程序包中的lightmaterial程序,试 ...

  4. OpenGL几何变换---翻译http://www.songho.ca/opengl/gl_projectionmatrix.html

    Overview 几何数据——顶点位置,和法向量(normal vectors),在OpenGL 管道raterization 处理过程之前可通过顶点运算(Vertex Operation)和基本组合 ...

  5. Computer Vision_33_SIFT:PCA-SIFT A More Distinctive Representation for Local Image Descriptors——2004

    此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...

  6. 图形学_opengl纹理映射

    学了半学期的图形学,除了几个用python或是matlab比较方便的实验外,用的大多数是opengl,在这总结一下纹理贴图实验中opengl的用法. 1.编译器连接静态库 有用到glaux.h的程序, ...

  7. OpenGL的几何变换[转]

    OpenGL的几何变换 1.实验目的: 理解掌握一个OpenGL程序平移.旋转.缩放变换的方法. 2.实验内容: (1)阅读实验原理,运行示范实验代码,掌握OpenGL程序平移.旋转.缩放变换的方法: ...

  8. OpenGL实例:几何变换

    OpenGL实例:几何变换 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 更多请查看:计算机图形学 1. 平移 #include <GL/glu ...

  9. OpenGL的几何变换4之内观察全景图

    上一次写了OpenGL的几何变换3之内观察全景图 上次采用的是图片分割化方式,这次采用数据分割化方式. 先说下思路,数据分割化方式呢,是只读取一张图片imgData,然后通过glTexCoord2f( ...

随机推荐

  1. LeetCode解题报告—— Best Time to Buy and Sell Stock

    Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of a gi ...

  2. js中的cookie使用和vue-cookie的使用

    在HTTP协议的定义中,采用了一种机制来记录客户端和服务器端交互的信息,这种机制被称为cookie,cookie规范定义了服务器和客户端交互信息的格式.生存期.使用范围.安全性. 在JavaScrip ...

  3. Download failed : Oracle JDK 7 is NOT installed,解决oracle jdk7的问题

    先了解下概念: jdk(java development kit),就是java的开发工具集,顾名思义就是做开发用的,其中包括javac,也就是java compiler等.jre(java runt ...

  4. vue 分页插件

    有个小问题就是最多显示3个分页,可以手动改一下配置参数就好.直接代码: <template> <div class="pageination_align"> ...

  5. Python的环境搭建——万丈高楼平地起

    Python的环境搭建,远程连接,端口映射,虚拟机 写在正文之前 python语言的开发环境还是相对比较简单的,但是也是有很多需要注意的地方,对于初次接触python或者以前很少用到虚拟环境的朋友来说 ...

  6. 为什么ArrayList remove报错

    不报错 List<String> userNames = new ArrayList<String>() {{ add("Hollis"); add(&qu ...

  7. bWAPP练习--injection篇SQL Injection (GET/Search)

    SQL注入: SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到 ...

  8. jsp有哪些内置对象作用分别是什么 分别有什么方法?

    JSP共有以下9个内置的对象: request 用户端请求,此请求会包含来自GET/POST请求的参数 response 网页传回用户端的回应 pageContext 网页的属性是在这里管理 sess ...

  9. XAML实时显示更新插件LiveXAML

     XAML实时显示更新插件LiveXAML LiveXAML是Visual Studio的第三方扩展插件.该插件可以从Visual Studio Marketplace下载,也可以从官网下载http: ...

  10. XPath中的text()和string()区别(转)

    原文地址 : http://blog.csdn.net/jiangchao858/article/details/63314426 本质区别 text()是一个node test,而string()是 ...