资讯详情

OpenGL之几何、投影、裁剪、视口变换以及全局变换与局部变换

一、转换概念

1.1 在这里插入图片描述 1.2

变换主要分为四个步骤,主要分为四个步骤Vertex operations顶点信息的阶段操作将在操作的顶点信息。

从三维模型到二维图形的主要转换过程,注意各种窗口的差异。

  • :虚拟窗口与特定的硬件设备无关。
  • :视觉与相关硬件设备有关。

1.3 OpenGL相关函数在中间变换

1.4

1.4.1 点P(x,y,z)平移到 P’(x’,y’,z平移向量为T(?x,?y,?z)

x’ = x ?x; y’ = y ?y; z’ = z ?z;

向量表达为:P’ = P T;

矩阵为矩阵形式: 但上述矩阵表达并不完美,因此可以进行齐次化,使矩阵的表达结构统一,OpenGL中采用4 x 4 表示矩阵。 OpenGL调用平移函数glTranslatef(?x,?y,?z)当构建平移矩阵时。

1.4.2

点P(x,y,z)缩放后得到点P’( x’,y’,z’) ,即乘以缩放因子:

x’ = x * S x S_x Sx; y’ = y * S y S_y Sy; z’ = z * S z S_z Sz;

向量表达:P’ = P * S,表现为矩阵形式,并齐次化。 OpenGL调用平移函数glScalef( S x S_x Sx​, S y S_y Sy​, S z S_z Sz​)时,就构造了一个缩放矩阵。 缩放中心在原点(0,0,0),若仅缩放图形的大小,不改变图形的位置,即: 可以采用组合的方式来实现,即先平移到缩放中心,在缩放,再平移到原来的位置。 glTranslatef(- x p x_p xp​,- y p y_p yp​,- z p z_p zp​) glScalef( S x S_x Sx​, S y S_y Sy​, S z S_z Sz​) glTranslatef( x p x_p xp​, y p y_p yp​, z p z_p zp​)

1.4.3

点P绕z轴逆时针选旋转 α 角: P(x,y)、P(x’,y’)点的极坐标形式为: 则可以把x’,y’,z’表示出来: 将其表达为矩阵形式: 同理,可以推导出沿y轴和沿x轴的旋转:

实现沿任意向量( A x A_x Ax​、 A y A_y Ay​、 A z A_z Az​)的旋转: 在OpenGL中,构建了一个新的坐标系统O x y z ‾ \overline{xyz} xyz​,该坐标系以向量( A x A_x Ax​、 A y A_y Ay​、 A z A_z Az​)为z轴,让后将顶点从Oxyz坐标中变换到O x y z ‾ \overline{xyz} xyz​中,直观理解为点的位置不变,但在不同坐标系中的坐标不一样,再绕z轴旋转,最后将旋转后的顶点从O x y z ‾ \overline{xyz} xyz​坐标系变换到Oxyz坐标系中。

  • 坐标系Oxyz → \rightarrow → O x y z ‾ \overline{xyz} xyz​ :矩阵A;
  • 旋转;
  • 坐标系O x y z ‾ \overline{xyz} xyz​ → \rightarrow → Oxyz :矩阵 A T A^T AT(转置矩阵),实际上应该为 A − 1 A^{-1} A−1(逆矩阵),因为A是一个正交矩阵,因此 A − 1 A^{-1} A−1 == A T A^T AT; glRotate(angle,x,y,z);

1.5 采用矩阵形式来表达几何变换,可以方便把各种变换组合起来,也可以减少计算量,最终只需要一个矩阵作用与顶点数据。

在OpenGL中,当前模型的变换矩阵为:M,调用glTranslatef()函数时,会生成一个矩阵T,让后将矩阵T右乘于矩阵M,即:

M’ = M * T;

当在调用glRotatef()函数时,会生成一个R矩阵,右乘于矩阵 M’:

M’’ = M’ * R;

当最终将矩阵作用于顶点P(x,y,z)时,为:

M’’ * P = (M * T * R ) * P;

1.6 在1.5中,我们注意到,顶点P位于矩阵 M’'的右边,可以看出,P点是先旋转,再平移,再进行M变换,为什么矩阵是写在原矩阵的右边,而最终的矩阵要写在顶点P的左边呢?后面我们将进行解答。

1.7 矩阵的应用 图元P1、P2经过了变换T1、T2、… 、Tn,OpenGL中是先进行一系列的变换矩阵的处理,最后再作用于图元(点,三角形,三角形带,四边形等都称为Primitive)。

glLoadIdentity();			//初始化矩阵M为单位矩阵,M = I;
	Tranformation T1;
	...
	Tranformation Tn;       //变换,M = I * T1 * ... * Tn;
	Primitive P1;
	Primitive P2;

P1经过变换T1、T2;P2经过变换T3、T4;OpenGL中基本的逻辑顺序为:

glLoadIdentity();			//初始化矩阵M为单位矩阵,M = I;
	Tranformation T1;
	Tranformation T2;       //变换,M = I * T1 *T2;
	Primitive P1;
glLoadIdentity();			//初始化矩阵M为单位矩阵,M = I
	Tranformation T3;
	Tranformation T4;       //变换,M = I * T3 *T4;
	Primitive P2;

二、矩阵的管理

2.1 OpenGL中采用来管理矩阵,主要采用** glPushMatrix() 和 glPopMatrix() **函数。

  • 假设P1、P2有相同的变换 T c T_c Tc​;P1有经过了变换T1、T2;P2经过了变换T3、T4,则伪码为:
glLoadIdentity();
	Transformation Tc;
glPushMatrix();
	Transformation T1;
	Transformation T2;
	Primitive P1;
glPopMatrix();
glPushMatrix();
	Transformation T3;
	Transformation T4;
	Primitive P2;
glPopMatrix();

glPushMatrix()起到了保护环境的作用;glPopMatrix()起到了恢复环境的作用,两者一般配合起来使用,起到了隔离的作用,中间的部分不会对 glPushMatrix()和glPopMatrix()之外的操作产生影响。

glPushMatrix();
	glTranslatef(-1.0, 0.0, 0.0);
	glRotatef((GLfloat)shoulder,0.0,0.0,1.0);
	glTranslatef(1.0, 0.0, 0.0);
	glPushMatrix();
		glScalef(2.0,0.4,1.0);
		glutWireCube(1.0);
	glPopMatrix();
	glPushMatrix();
		glScalef(1.0,0.4,1.0);
		glRotatef((GLfloat)elbow,0.0,0.0,1.0);
		glTranslatef(1.0, 0.0, 0.0);
		glScalef(2.0,0.4,1.0);
		glutWireCube(1.0);
	glPopMatrix();
glPopMatrix();
	

2.2

  • glLoadIdentity(): 使栈顶矩阵为单位矩阵;

  • glTranslate*(),glRotate*(),glScale*():栈顶矩阵左乘于变换矩阵;

  • glPushMatrix():将栈顶矩阵复制一份,入栈。

  • glPopMatrix() : 退栈,恢复到Push之前的状态;

三、模型变换与视点变换

3.1 Model-View Transformation

视点不变。变换模型位置;

3.2 View transformation

物体不变,变换视点位置,如漫游功能。

两种变换是可以统一的,也可以相互转化。 glMatrixMode(GL_MODELVIEW)用来设置操作的堆栈,即管理模型与视点变换的堆栈。因为模型变换与视点变换是相对的,在OpenGL中,我们可以认为视点总是不变的,所有的变换都是模型变换。

3.3 gluLookAt()函数

void glutLookAt(eyex,eyey,eyez,centerx,centery,centerz,upx,upy,upz),可以用来实现漫游功能,即视点变换,通过指定摄像机的视线方向,中心点和上方向,就可以实现漫游功能。

glTranslate()、glRotate()、glScale()都可以理解为视点不动,变换模型,而gluLookAt()是模拟物体不动,变换视点的控制效果。本质上两者都一样,gluLookAt()函数也是计算了一个变换矩阵。

四、全局变换与局部变换

4.1 Global transformation:全局坐标系变换模式,固定坐标系模型,图形模式;如下变换,物体的局部坐标也随着物体改变;

4.2 Local transformation : 局部坐标系变换模式,活动坐标系模式,空间模式。如下变换模式,物体在局部坐标系中变换。第一种采用与全局变换顺序一样的矩阵进行局部变换;第二种与全局坐标相反的矩阵进行局部变换。

4.3 两种变换方式产生的效果完全不一样,但是两种方法之间又具有联系,

4.4

4.5

局部变换在子模型相对于父模型的变换中很有用,可以很方便的进行变换,而全局变换则比较复杂;在OpenGL中,单次的变换是全局变换,而组合的多次变换则是局部变换。

4.6 例子

glLoadIdentity();
glTranslatef(10.0f,0.0f,0.0f);
glRotatef(45.0f,0.0f,0.0f,1.0f);

glBegin(GL_QUADS);
...
glEnd();

生成的矩阵:

最终作用于顶点: 通过变换的过程可以理解:代码里面是先平移、再旋转、而实际作用于顶点时,将矩阵放在了点的左边,是先旋转,再平移,这就是局部变换的逆变换就是全局变换的含义。

注意:

附录:中国大学Mooc,图形编程技术,北京林业大学,杨刚

标签: 电感磁珠upz1005d121

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台