glulookat函数Word文档格式.docx
《glulookat函数Word文档格式.docx》由会员分享,可在线阅读,更多相关《glulookat函数Word文档格式.docx(12页珍藏版)》请在冰点文库上搜索。
5.
upX,
upY,
upZ);
官网关于此函数的描述:
gluLookAt
通过指定一个视点、外表场景中心的参考点以及up向量来构造一个视变换矩阵。
这个矩阵将代表场景中心的参考点映射到-Z轴,视点映射成为原点。
当使用一个特定的投影矩阵时,场景的中心就映射到视口的中心。
类似地,由up向量描述的方向投影到投影平面成为+y轴,这样它在视口中向上指向。
up向量必须不能与从视点到参考点的直线平行。
那么如何确定u-v-n坐标系呢?
计算公式如下:
这里需要注意:
OpenGL中使用的相机坐标系是右手坐标系,UVN坐标系是左手坐标系。
在构造实际变换矩阵的过程中,OpenGL
需要将-n轴翻转为相机坐标系的+z轴,uv轴定位相机坐标系的+x和+y轴。
这与推导相机变换矩阵一文最后的结果矩阵有所不同。
如何构造视变换矩阵?
视变换就是在相机坐标系下解释世界坐标系下的点。
而这个变换矩阵的构造,可以看做将相机坐标系变换到与原来的世界坐标系重合。
而将世界坐标系变换到与相机坐标系重合,可以看做是这个所求变换的逆过程。
将世界坐标系变换到与相机坐标系重合,实际上进展了两个步骤:
第一步将世界坐标系旋转一定角度记作变换R,再将世界坐标系平移到视点位置记作T,那么这个变换矩阵记为M=TR。
要将世界坐标系的点变换到照相机坐标系下,需要使用矩阵M的逆矩阵,即:
inverse(M)=inverse(R)*inverse(T)。
即所求变换矩阵为inverse(M)。
平移矩阵的逆矩阵形式简单,就是取平移量(eyex,eyey,eyez)的相反数,即:
那么现在的关键是如何求出旋转矩阵R?
上面我们构造的UVN坐标系u-v-n3个基向量可以构造成矩阵:
注意这里对n轴进展了翻转,构成右手照相机坐标系。
怎么看这个矩阵A呢,矩阵A实际上代表的就是一个旋转矩阵(从矩阵形式上看出)。
旋转矩阵的一个特点就是它是正交矩阵,即有inverse(A)=transpose(A).(A^-1=A^T)
很多教材和博客都说,这里A矩阵可以看做是将世界坐标系转换到与照相机坐标系重合时的旋转矩阵,这一点怎么理解呢?
个人理解,矩阵A第四列为0,0,0,1,可以看做是世界坐标系和照相机坐标系原点重合;
根据?
理解坐标系及坐标变换(上)?
中所讲,矩阵前3列即变换后的基向量,那么这个基向量(都是单位向量)是如何计算出来的呢?
就是通过旋转原来的世界坐标系的基向量来构造的。
因此,可以说矩阵A代表的就是将世界坐标系旋转到与相机坐标系重合时的旋转矩阵R,即R=A。
那么inverse(R)=inverse(A)=transpose(A)
即为:
所以gluLookAt所求变换矩阵inverse(M)为:
gluLookAt的默认值是(0,0,0,0,0,-1,0,1,0);
通过计算可得出:
u=(1,0,0),v=(0,1,0),n=(0,0,-1),这样构成的矩阵M^-1即为单位矩阵。
下面通过代码来验证下结论。
代码绘制一个立方体,设置为透视投影,并通过gluLookAt设置相机方位来查看立方体。
注意,为了便于观察视变换矩阵,这里并没有进展其他模型变换;
手动计算矩阵时使用了数学库glm来进展向量点积和叉积运算。
1.//计算gluLookAt矩阵
3.#include
<
GL/glew.h>
4.#include
GL/freeglut.h>
5.#include
glm/glm.hpp>
6.#include
iostream>
7.#pragma
comment(lib,"
freeglut.lib"
)
8.#pragma
glew32.lib"
9.
10.void
userInit();
11.void
display(
void
);
12.void
keyboardAction(
unsigned
char
key,
int
x,
y
13.void
reshape(int
w,int
h);
14.
15.int
main(
argc,
**argv
16.{
17.
glutInit(&
argv);
//初始化GLUT
18.
19.
glutInitDisplayMode(
GLUT_RGBA|GLUT_DOUBLE);
20.
glutInitWindowPosition(100,100);
21.
glutInitWindowSize(
512,
512
22.
glutCreateWindow(
"
demo"
23.
24.
glewInit();
//使用GLEW时,使用该函数初始化GLEW
25.
//自定义的初始化函数
26.
glutReshapeFunc(reshape);
27.
glutDisplayFunc(
display
28.
glutKeyboardFunc(
keyboardAction
29.
glutMainLoop();
30.
return
0;
31.}
32.//自定义初始化函数
33.void
userInit()
34.{
35.
glClearColor(
0.0,
0.0
36.
glColor4f(0.6f,0.5f,0.0,0.0);
37.}
38.//设置视变换矩阵
39.void
setViewMatrix(GLdouble
*theMatrix,GLdouble
eyex,GLdouble
eyey,GLdouble
eyez,
40.
targetx,GLdouble
targety,GLdouble
targetz,
41.
vupx,GLdouble
vupy,GLdouble
vupz)
42.{
43.
glm:
:
vec3
eye(eyex,eyey,eyez),target(targetx,targety,targetz),vup(vupx,vupy,vupz);
44.
//构造n轴
45.
nvec(target-eye);
46.
nvec=glm:
normalize(nvec);
47.
//构造u轴
48.
vup
=
normalize(vup);
49.
uvec
cross(nvec,vup);
50.
uvec=glm:
normalize(uvec);
51.
//构造v轴
52.
vvec
cross(uvec,nvec);
53.
vvec=glm:
normalize(vvec);
54.
//设置4x4矩阵
55.
memset(theMatrix,0,sizeof(GLdouble)*16);
56.
57.
theMatrix[0]
uvec.x;
58.
theMatrix[4]
uvec.y;
59.
theMatrix[8]
uvec.z;
60.
theMatrix[12
]
-glm:
dot(eye,uvec);
61.
62.
theMatrix[1]
vvec.x;
63.
theMatrix[5]
vvec.y;
64.
theMatrix[9]
vvec.z;
65.
theMatrix[13]
dot(eye,vvec);
66.
67.
//注意这行数据
68.
theMatrix[2]
-nvec.x;
69.
theMatrix[6]
-nvec.y;
70.
theMatrix[10]
-nvec.z;
71.
theMatrix[14]
dot(eye,nvec);
72.
73.
theMatrix[15]
1.0;
74.}
75.void
h)
76.{
77.
glViewport(0,0,GLsizei(w),GLsizei(h));
78.
glMatrixMode(GL_PROJECTION);
79.
glLoadIdentity();
80.
gluPerspective(60.0,(GLfloat)w/(GLfloat)h,1.0,10.0);
81.
glMatrixMode(GL_MODELVIEW);
82.
83.
84.
//gluLookAt(2.0,0.0,1.8,0.0,0.0,0.0,0.0,1.0,0.0);
85.
86.
//手动构造视变换矩阵
87.
theMatrix[16];
88.
setViewMatrix(theMatrix,2.0,0.0,1.8,0.0,0.0,0.0,0.0,1.0,0.0);
89.
glMultMatrixd(theMatrix);
90.
91.
//打印当前模视变换矩阵容
92.
modelViewMat[16];
93.
glGetDoublev(GL_MODELVIEW_MATRIX,modelViewMat);
94.
for(int
i
i<
4;
i++)
95.
j=0;
j<
j++)
96.
{
97.
fprintf(stdout,"
%-.4f\t"
modelViewMat[i+4*j]);
98.
if((j+1)
%4
==
0)
\n"
99.
}
100.}
101.//绘制回调函数
102.void
103.{
104.
glClear(
GL_COLOR_BUFFER_BIT);
//去除颜色缓存
105.
glLineWidth(2.0);
106.
glutWireCube(1.0);
107.
glutSwapBuffers();
108.}
109.//键盘按键回调函数
110.void
111.{
112.
switch(
key
113.
case
033:
//
Escape
114.
'
q'
Q'
115.
exit(
EXIT_SUCCESS
116.
break;
117.
118.}
使用gluLookAt如以下图左右所示:
手动计算视变换矩阵,效果如以下图所示:
可以看出两者是一样的,二者的视变换矩阵打印出来均为:
0.6690
0.0000
-0.74330.0000
0.0000
1.0000
0.0000
0.7433
0.6690
-2.6907
1.0000
至此证明了上述推导的矩阵确实为OpenGL中使用的视变换矩阵。
关于OpenGLgluLookAt官网提供了参考实现,可以查看:
GluLookAtcode;
另外关于顶部正朝向vup的理解有更好的通俗解释,可以查看:
Opengl---gluLookAt函数详解。