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

1.实验目的:

理解掌握OpenGL程序的模型视图变换。

2.实验内容:

(1)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换;

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

3.实验原理:

在OpenGL程序中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换。

1.在指定的视图变换之前,应该使用glLoadIdentity()函数把当前矩阵设置为单位矩阵。

2.在载入单位矩阵之后,使用gluLookAt()函数指定视图变换。如果程序没有调用gluLookAt(),那么照相机会设定为一个默认的位置和方向。在默认的情况下,照相机位于原点,指向Z轴负方向,朝上向量为(0,1,0)。

3.一般而言,display()函数包括:视图变换 + 模型变换 + 绘制图形的函数(如glutWireCube())。display()会在窗口被移动或者原来先遮住这个窗口的东西被移开时,被重复调用,并经过适当变换,保证绘制的图形是按照希望的方式进行绘制。

4.在调用glFrustum()设置投影变换之前,在reshape()函数中有一些准备工作:视口变换 + 投影变换 + 模型视图变换。由于投影变换,视口变换共同决定了场景是如何映射到计算机的屏幕上的,而且它们都与屏幕的宽度,高度密切相关,因此应该放在reshape()中。reshape()会在窗口初次创建,移动或改变时被调用。

总结起来,OpenGL中矩阵坐标之间的关系如下:

物体世界坐标*模型视图矩阵*投影矩阵*透视除法*规范化设备坐标→窗口坐标

以后面的示范代码为例:

(1)视图变换函数gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0,)设置照相机的位置

把照相机放在(0,0,5),镜头瞄准(0,0,0),朝上向量定为(0,1,0)朝上向量为照相机指定了一个唯一的方向。如果没有调用gluLookAt,照相机就设定一个默认的位置和方向,在默认情况下,照相机位于原点,指向Z轴的负方向,朝上向量为(0,1,0)

glLoadIdentity()函数把当前矩阵设置为单位矩阵。

(2)使用模型变换的目的是设置模型的位置和方向

(3)投影变换,指定投影变换类似于为照相机选择镜头,可以认为这种变换的目的是确定视野,并因此确定哪些物体位于视野之内以及他们能够被看到的程度。

除了考虑视野之外,投影变换确定物体如何投影到屏幕上,OpenGL提供了两种基本类型的投影,1、透视投影:远大近小;2、正投影:不影响相对大小,一般用于建筑和CAD应用程序中

(4)视口变换

视口变换指定一个图像在屏幕上所占的区域

(5)绘制场景

4.示范代码:

#include <GL/glut.h>

#include <stdlib.h>

static int year = 0, day = 0;

void init(void)

{

glClearColor (0.0, 0.0, 0.0, 0.0);

glShadeModel (GL_FLAT);

}

void display(void)

{

glClear (GL_COLOR_BUFFER_BIT);

glColor3f (1.0, 1.0, 1.0);

glPushMatrix();

glutWireSphere(1.0, 20, 16); /* draw sun */

glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);

glTranslatef (2.0, 0.0, 0.0);

glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);

glutWireSphere(0.2, 10, 8); /* draw smaller planet */

glPopMatrix();

glutSwapBuffers();

}

void reshape (int w, int h)

{

glViewport (0, 0, (GLsizei) w, (GLsizei) h);

glMatrixMode (GL_PROJECTION);

glLoadIdentity ();

gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}

void keyboard (unsigned char key, int x, int y)

{

switch (key) {

case ‘d‘:

day = (day + 10) % 360;

glutPostRedisplay();

break;

case ‘D‘:

day = (day - 10) % 360;

glutPostRedisplay();

break;

case ‘y‘:

year = (year + 5) % 360;

glutPostRedisplay();

break;

case ‘Y‘:

year = (year - 5) % 360;

glutPostRedisplay();

break;

case 27:

exit(0);

break;

default:

break;

}

}

int main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);

glutInitWindowSize (500, 500);

glutInitWindowPosition (100, 100);

glutCreateWindow (argv[0]);

init ();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutKeyboardFunc(keyboard);

glutMainLoop();

return 0;

}

代码说明:

上面所描述的这个程序绘制一个简单的太阳系,其中有一颗行星和一颗太阳,它们是用同一个球体绘制函数绘制的。为了编写这个程序,需要使用glRtate*()函数让这颗行星绕太阳旋转,并且绕自身的轴旋转。还需要使用glTranslate*()函数让这颗行星远离太阳系原点,移动到它自己的轨道上。记住,可以在glutWireSphere()函数中使用适当的参数,在绘制两个球体时指定球体的大小。

为了绘制这个太阳系,首先需要设置一个投影变换和一个视图变换。在这个例子中,可以使用glutPerspective()和gluLookat().

绘制太阳比较简单,因为它应该位于全局固定坐标系统的原点,也就是球体函数进行绘图的位置。因此,绘制太阳时并不需要移动,可以使用glRotate*()函数绕一个任意的轴旋转。绘制一颗绕太阳旋转的行星要求进行几次模型变换。这颗行星需要每天绕自己的轴旋转一周,每年沿着自己的轨道绕太阳旋转一周。

为了确定模型变换的顺序,可以从局部坐标系统的角度考虑。首先,调用初始的glRotate*()函数对局部坐标系统进行旋转,这个局部坐标系统最初与全局固定坐标系统是一致的。接着,可以调用glTranslate*()把局部坐标系统移动到行星轨道上的一个位置。移动的距离应该等于轨道的半径。因此,第一个glRotate*()函数实际上确定了这颗行星从什么地方开始绕太阳旋转(或者说,从一年的什么时候开始)。

第二次调用glRotate*()使局部坐标轴进行旋转,因此确定了这颗行星在一天中的时间。当调用了这些函数变换之后,就可以绘制这颗行星了。

5. 实验提高

(1)尝试在太阳系中增加一颗卫星,一颗行星。提示:使用glPushMatrix()和glPopMatrix()在适当的时候保存和恢复坐标系统的位置。如果打算绘制几颗卫星绕同一颗行星旋转,需要在移动每颗卫星的位置之前保存坐标系统,并在绘制每颗卫星之后恢复坐标系统。

(2)尝试把行星的轴倾斜。

清华版CG 实验5 OpenGL模型视图变换,布布扣,bubuko.com

时间: 2024-08-13 19:52:54

清华版CG 实验5 OpenGL模型视图变换的相关文章

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

1.实验目的: 理解掌握OpenGL二维平移.旋转.缩放变换的方法. 2.实验内容: (1)阅读实验原理,运行示范实验代码,掌握OpenGL程序平移.旋转.缩放变换的方法: (2)根据示范代码,尝试完成实验作业: 3.实验原理: (1)OpenGL下的几何变换 在OpenGL的核心库中,每一种几何变换都有一个独立的函数,所有变换都在三维空间中定义. 平移矩阵构造函数为glTranslate<f,d>(tx, ty, tz),作用是把当前矩阵和一个表示移动物体的矩阵相乘.tx, ty,tz指定这

清华版CG 实验7 OpenGL光照

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

清华版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曲线是唯一的.在折线的各顶点中,只有第一点和最后一点在曲线上且作为曲线的起始处和终止处,其他的点用于控制曲线的形状及阶次.曲线的形状趋向于多

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

上一节我们提到了如何在一张画布上画一个简单几何图形,通过创建画布,获取WebGLRendering上下文,创建一个简单的着色器,然后将一些顶点数据绑定到gl的Buffer中,最后通过绑定buffer数据,提供buffer中顶点数据的情况,执行渲染绘制方法,将数据结果从buffer中刷新到帧缓存中.整个流程十分清晰明了,可是通过对比原来OpenGL中的整个流程,我们会发现其中还缺少了一些很重要的处理步骤,虽然我们创建了属于自己的着色器,可并没有对顶点数据进行类似于顶点处理管线中的模型视图变换.透视

OpenGL的视图变换与OSG漫游器

在OpenGL固定管线内容中有一个过程是进行视图变换,主要目的是将世界坐标变换到相机坐标空间中,OpenGL的视图变换所处的位置如下图所示: 在OSG中通过重写漫游器的时候需要实现的4个虚函数与这个变换是一致的(详细参考另一篇文章  <osg中漫游器的原理(一)>) 相机视图变换 在OpenGL中初始位置场景的世界坐标与相机坐标是在一起的,视点的方向是Z轴的负方向, 相机位置经过变换之后可以处于世界坐标系中的任何位置,可以通过两个变换:旋转和平移将相机移动到场景中的任意位置,如下图所示: 在O

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

产生目标场景的过程类似于用照相机进行拍照: (1) 把照相机固定在三角架上,并让他对准场景从不同位置观察场景(视图变换) gluLookAt (2) 对场景进行安排,使各个物体在照片中的位置是我们所希望的 移动,旋转或者放大缩小场景中的物体(模型变换) glTranslate* ,glRotate* ,glScale* (3) 选择照相机镜头,并调整放大倍数(调焦) 显示物体时,可以选择物体是如何投影到屏幕上(投影变换) glFrustum , gluPerspective , glOrtho