清华版CG 实验3 OpenGL几何变换

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.示范代码:

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

}

运行结果如图A.3(a)所示。

(a) 程序结果 (b) 作业图形结果

图A.3 实验3

5. 实验提高

绘制如图A.3(b)所示图形。有关提示可参见课程实验教学博客页面。

清华版CG 实验3 OpenGL几何变换,布布扣,bubuko.com

时间: 2024-11-08 02:38:11

清华版CG 实验3 OpenGL几何变换的相关文章

清华版CG 实验7 OpenGL光照

一.实验目的: 了解掌握OpenGL程序的光照与材质,能正确使用光源与材质函数设置所需的绘制效果. 二.实验内容: (1)下载并运行Nate Robin教学程序包中的lightmaterial程序,试验不同的光照与材质系数: (2)运行示范代码1,了解光照与材质函数使用. 三.实验原理: 为在场景中增加光照,需要执行以下步骤: (1) 设置一个或多个光源,设定它的有关属性: (2) 选择一种光照模型: (3) 设置物体的材料属性. 具体见教材第8章8.6节用OpenGL生成真实感图形的相关内容.

清华版CG 实验5 OpenGL模型视图变换

1.实验目的: 理解掌握OpenGL程序的模型视图变换. 2.实验内容: (1)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换: (2)根据示范代码,尝试完成实验作业: 3.实验原理: 在OpenGL程序中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换. 1.在指定的视图变换之前,应该使用glLoadIdentity()函数把当前矩阵设置为单位矩阵. 2.在载入单位矩阵之后,使用gluLookAt()函数指定视图变换.如果程序没有调用g

清华版CG 实验8 OpenGL交互

1.实验目的: 理解掌握一个OpenGL程序的常见交互方法. 2.实验内容: (1)运行示范代码,掌握程序鼠标交互方法.鼠标坐标获取方法: (2)尝试为示范代码添加键盘与菜单控制.绘制直线功能: 3.实验原理: 要想在OpenGL中处理鼠标事件非常的方便,GLUT已经为我们的注册好了函数,只要我们提供一个方法.使用函数glutMouseFunc,就可以帮我们注册我们的函数,这样当发生鼠标事件时就会自动调用我们的方法. 函数的原型是: void glutMouseFunc(void(*func)(

清华版CG 实验2 直线生成算法实现

1.实验目的: 理解基本图形元素光栅化的基本原理,掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法. 2.实验内容: (1) 根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果: (2) 指出示范程序采用的算法,以此为基础将其改造为中点线算法或Bresenham算法,写入实验报告: (3) 根据示范代码,将其改造为圆的光栅化算法,写入实验报告: (4) 了解和使用OpenGL的生成直线的命令,来验证程序运行结果. 3.实验原理: 示范代码原理参见教材直线

清华版CG 实验4 编码裁剪算法

1.实验目的: 了解二维图形裁剪的原理(点的裁剪.直线的裁剪.多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法. 2.实验内容: (1) 理解直线裁剪的原理(Cohen-Surtherland算法.梁友栋算法) (2) 利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线. (3) 调试.编译.修改程序. (4) 尝试实现梁友栋裁剪算法. 3.实验原理: 编码裁剪算法中,为了快速判断一条直线段与矩形窗口的位置关系,采用了如图A.4所示的空间划分和编码方案.

清华版CG 实验6 Bezier曲线生成

1.实验目的: 了解曲线的生成原理,掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法. 2.实验内容: (1) 结合示范代码了解曲线生成原理与算法实现,尤其是Bezier曲线: (2) 调试.编译.修改示范程序. 3.实验原理: Bezier曲线是通过一组多边形折线的顶点来定义的.如果折线的顶点固定不变,则由其定义的Bezier曲线是唯一的.在折线的各顶点中,只有第一点和最后一点在曲线上且作为曲线的起始处和终止处,其他的点用于控制曲线的形状及阶次.曲线的形状趋向于多

实验3 OpenGL几何变换

转自:http://www.cnblogs.com/opengl/archive/2012/10/30/2747130.html 1.实验目的: 理解掌握一个OpenGL程序平移.旋转.缩放变换的方法. 2.实验内容: (1)阅读实验原理,运行示范实验代码,掌握OpenGL程序平移.旋转.缩放变换的方法: (2)根据示范代码,尝试完成实验作业: 3.实验原理: (1)OpenGL下的几何变换 在OpenGL的核心库中,每一种几何变换都有一个独立的函数,所有变换都在三维空间中定义. 平移矩阵构造函

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

Overview 几何数据——顶点位置,和法向量(normal vectors),在OpenGL 管道raterization 处理过程之前可通过顶点运算(Vertex Operation)和基本组合运算改变这些数据. Object Coordinates 对象的本地坐标系——任何变换之前的最初位置.为了变换(transformation)这些对象,可以调用glRotate(),glTranslatef(),glScalef()这些方法. Eye Coordinates 使用GL_MODELVI

Assignment 4 OpenGL中正十二面体追踪球实现(平移、旋转、多面体线框体切换)

一.使用平台    windows  8.1     visual  studio  2012    二.使用方法     鼠标左键控制旋转,鼠标右键控制平移,点击鼠标中键出现菜单可选多面体 或线框体绘制.     键盘↑↓←→控制平移,F1 和 F2 键分别为多面体和线框体绘制的切换.  三.实现简述     主函数  在 main 函数中与这次实验相关的主要有以下几个函数:  glutReshapeFunc(myReshape);  //窗口改变时重新设