OpenGL学习(四) 几何变换

线性变换

仿射变换:包括平移、旋转以及比例变换。这种变换能够保持直线建的平行性,并且可逆。

射影变换:包括透视变换等。由于这些变换都是将三维实体投影到二维空间,所以不可逆。

齐次坐标系

    OpenGL实际是在四维坐标中定义的,坐标为(x,y,z,w)在三维点空间上显示为(x/w,y/w,z/w),不定义w的话,w默认为1。

故我们用于建模、观察以及投影的所有变换都可由4*4的矩阵直接作用于齐次坐标系中的点和向量得到。

模型-视图变换和投影变换

    每个顶点都经过当前模型-视图矩阵和投影矩阵定义的两个变换。一开始这两个矩阵均被设为4*4的单位矩阵。模型-视图矩阵用于对摄影机定位,而投影矩阵指定了投影以及剪裁体,并将顶点映射至一个归一化的坐标系中。

平移

    void glTranslate<fd>(type x,type y,type z)

//通过将以参数dx,dy,dz为参数的平移矩阵与当前做右乘来改变当前矩阵,type为GLfloat或GLdouble.

如果我们想所有的顶点沿着z轴负方向平移一个单位,可以这样做

    glMatriMode(GL_MODELVIEW);
    glLoadIdentify();
    glTranslatef(0.0,0.0,-1.0);

联级变换

    如果没使用glLoadIdentify()则两次平移变换就组合在一起或级联,从而形成一次复合变换。

旋转变换

    void glRotate<fd>(type angle,type dx,type dy,type dz)

//形成一个旋转轴为(dx,dy,dz)的旋转矩阵,旋转不动点为原点坐标原点。type为GLfloat或GLdouble。

若要绕着任意固定的点旋转,则可以先将该点平移至原点,然后使用glRotate*()实现所期望的旋转。最后,我们还需要通过一次平移在将该不动点平移回去。

比例变换

    void glScale<fd>(type sx,type sy,type sz)

//根据比例因子sx,sy和sz创建一个比例变换矩阵,其不动点位于原点处。type可取GLfloat和GLdouble

一个旋转的立方体:

#include <gl/glut.h>
#include <math.h>
#include <vector>
#include <iostream>

using namespace std;

int axis=0;
float theta[3];

GLfloat vertices[]={
	-1.0,-1.0,1.0,
	-1.0,1.0,1.0,
	1.0,1.0,1.0,
	1.0,-1.0,1.0,
	-1.0,-1.0,-1.0,
	-1.0,1.0,-1.0,
	1.0,1.0,-1.0,
	1.0,-1.0,-1.0
};                              //定义立方体的8个顶点

GLint index[]={
	0,3,2,1,
	2,3,7,6,
	3,0,4,7,
	1,2,6,5,
	4,5,6,7,
	5,4,0,1
};                              //定义每个面所需要那几个顶点

GLfloat colors[]={
	1.0,0.0,0.0,
	0.0,1.0,1.0,
	1.0,1.0,0.0,
	0.0,1.0,0.0,
	0.0,0.0,1.0,
	1.0,0.0,1.0,
	1.0,1.0,0.0,
	0.0,1.0,1.0
};                             //定义六个面的颜色

void init()
{
	glClearColor(0.0,0.0,0.0,0.0);      //指定屏幕背景为黑色
	glColor3f(1.0,1.0,1.0);             //设置绘制颜色为白色
	glShadeModel(GL_FLAT);              //设置颜色插值为平面模式
}

void display()
{
	glEnable(GL_DEPTH_TEST);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         //清理屏幕颜色为我们指定的颜色

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);

	glVertexPointer(3,GL_FLOAT,0,vertices);
	glColorPointer(3,GL_FLOAT,0,colors);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glRotatef(theta[0],1.0,0.0,0.0);
	glRotatef(theta[1],0.0,1.0,0.0);
	glRotatef(theta[2],0.0,0.0,1.0);
	glDrawElements(GL_QUADS,24,GL_UNSIGNED_INT,index);

	glFlush();                       //强制以上绘图操作执行
}

void reshape(int w,int h)
{
	glMatrixMode(GL_PROJECTION);       //设置为投影模式
	glLoadIdentity();
	glOrtho(-2.0,2.0,-2.0,2.0,-2.0,2.0);

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

void mouse(int button,int state,int x,int y)
{
	if (button==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
	{
		axis=0;
	}
	if (button==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN)
	{
		axis=1;
	}
	if (button==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)
	{
		axis=2;
	}
}

void SpinIdle()
{
	theta[axis]+=0.1;
	if(theta[axis] >360.0)  theta[axis] -=360.0;
	glutPostRedisplay();
}

int main(int argc,char**argv)
{
	glutInit(&argc,argv);                           //初始化glut
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);    //设置窗口模式为单缓冲和RGB模式
	glutInitWindowSize(500,500);                    //设置窗口大小
	init();
	glutCreateWindow("test");                       //设置窗口标题
	glutDisplayFunc(display);                       //设置绘图回调函数
	glutReshapeFunc(reshape);                       //设置窗口回调函数
	glutMouseFunc(mouse);
	glutIdleFunc(SpinIdle);
	glutMainLoop();                                 //开始循环,等待响应
	return 0;
}

运行并适当点击鼠标改变角度可以得到如下结果:

    

直接设置矩阵

    void glLoadMatrix<fd>(type* m)

//将type类型(可取GLfloat或者GLdouble的数组m加载为当前矩阵)

时间: 2024-10-12 03:27:51

OpenGL学习(四) 几何变换的相关文章

OpenGL学习08_几何变换

OpenGL需要通过视图变换,模型变换,投影变换,视口变换,绘制场景这一系列步骤将图像绘制出来. 1.模型变换和视图变换 从"相对移动"的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性.在OpenGL中,实现这两种功能甚至使用的是同样的函数.由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为"模型视图矩阵".设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数. glMatrixMode(G

OpenGL学习之路(四)

1 引子 上次读书笔记主要是学习了应用三维坐标变换矩阵对二维的图形进行变换,并附带介绍了GLSL语言的编译.链接相关的知识,之后介绍了GLSL中变量的修饰符,着重介绍了uniform修饰符,来向着色器程序传入输入参数. 这次读书笔记的内容相对有趣一些,主要是和园友们分享讨论三维坐标变换矩阵在三维几何体上的应用,以及介绍一下如何实现三维图形与用户操作的交互.这一次笔记在三维编程中也是非常重要的——我们最后开发的三维程序最终就是要和目标用户进行交互的. 之前一直没有在博客上放过gif格式的动画图片,

OpenGL学习进程(6)第四课:点、边和图形(一)点

本节是OpenGL学习的第四个课时,下面介绍OpenGL点的相关知识:     (1)点的概念:     数学上的点,只有位置,没有大小.但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点.一般情况下,OpenGL中的点将被画成单个的像素,虽然它可能足够小,但并不会是无穷小.同一像素上,OpenGL可以绘制许多坐标只有稍微不同的点,但该像素的具体颜色将取决于OpenGL的实现. 点是OpenGL中绘制一切的基础.     (2)如何绘制点: 1)OpenGL为点的绘制提供了一系列函数

拓幻图形学工程师教学手册(第一讲)|一字一字敲出OpenGL学习教程

动机首先申明,我是拓幻科技图形处理工程师,自己接触OpenGL,图形图像等方面也有六年多了,很多人其实并不了解这方面,也不了解如何系统地去学,我觉得基于我硕士时期的课程和经验给大家.这些资料和经验也得感谢我的老师,来自普渡大学的终生教授迈克 贝利(Mike Bailey). 以此连载OpenGL学习教程,给大家讲解,一起学习一下,不对之处,欢迎大家指出讨论. 所有渲染工作都离不开OpenGL, 着色器(Shader)这些,如果你和我一样对图形处理比较感兴趣的话,可能你和当初的我有着同样的困惑:如

OpenGL学习进程(3)第一课:初始化窗体

    本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体:     (1)显示一个有蓝色背景的窗体: #include <GL/glut.h> #include <stdlib.h> void display(void) { /* clear all pixels */ glClear (GL_COLOR_BUFFER_BIT); glFlush (); } int main(int argc, char** argv) { glutInit(&argc, a

OpenGL学习进程(11)第八课:颜色绘制的详解

    本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. RGBA模式与索引模式的区别: 计算机必须为每个像素保存一些数据,在RGBA模式中数据就代表了颜色:而颜色索引模式中数据代表了一个索引,要获取真正的颜色值还需要查索引表.数据的数量是由帧缓存中的位面决定的.一个位面为一个像素的一个位的数据.假如是8位面的颜色,每个像素就有8个颜色位,因此就有2的8次方

OpenGL学习之路(五)

1 引子 不知不觉我们已经进入到读书笔记(五)了,我们先对前四次读书笔记做一个总结.前四次读书笔记主要是学习了如何使用OpenGL来绘制几何图形(包括二维几何体和三维几何体),并学习了平移.旋转.缩放坐标变换矩阵的理论推导和实践应用. 这一次读书笔记,我们一起来学习OpenGL中常用的坐标系以及坐标变换.在OpenGL中有几个坐标系,初学者常常被它们搞得晕头转向:为什么需要这些坐标系?各个坐标系有什么作用?……本文就来学习一下这些OpenGL中常用坐标系. 之后来看看投影矩阵的推导,投影变换矩阵

OpenGL学习进程(5)第三课:视口与裁剪区域

本节是OpenGL学习的第三个课时,下面介绍如何运用显示窗体的视口和裁剪区域:     (1)知识点引入:     1)问题现象: 当在窗体中绘制图形后,拉伸窗体图形形状会发生变化: #include <GL/glut.h> #include <math.h> const float Pi = 3.1415926f; const int n = 1000; const float R = 0.8f; void init(void) { glClearColor(0.0,0.0,0.

OpenGL学习进程(10)第七课:四边形绘制与动画基础

    本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图元用于绘制四边形,它根据每四个顶点绘制一个四边形. 注意:在使用四边形时必需记住四边形的四个角必须位于同一个平面中(不存在弯曲的四边形). 2)四边形带(GL_QUAD_STRIP) 该图元指定一个连接的四边形带.它们都保持相同方向的环绕. 3)通用多边形GL_POLYGON 我们可以用它绘制任意数