简体   繁体   English

gluLookAt如何工作?

[英]How does gluLookAt work?

From my understanding, 根据我的理解,

gluLookAt(
        eye_x, eye_y, eye_z,
        center_x, center_y, center_z,   
        up_x, up_y, up_z
    );

is equivalent to: 相当于:

glRotatef(B, 0.0, 0.0, 1.0);
glRotatef(A, wx, wy, wz);
glTranslatef(-eye_x, -eye_y, -eye_z);

But when I print out the ModelView matrix, the call to glTranslatef() doesn't seem to work properly. 但是当我打印出ModelView矩阵时,对glTranslatef()的调用似乎无法正常工作。 Here is the code snippet: 这是代码片段:

#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>

#include <iomanip>
#include <iostream>
#include <string>

using namespace std;

static const int Rx = 0;
static const int Ry = 1;
static const int Rz = 2;

static const int Ux = 4;
static const int Uy = 5;
static const int Uz = 6;

static const int Ax = 8;
static const int Ay = 9;
static const int Az = 10;

static const int Tx = 12;
static const int Ty = 13;
static const int Tz = 14;

void init() {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    GLfloat lmodel_ambient[] = { 0.8, 0.0, 0.0, 0.0 };
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
}

void displayModelviewMatrix(float MV[16]) {
    int SPACING = 12;
    cout << left;
    cout << "\tMODELVIEW MATRIX\n";
    cout << "--------------------------------------------------" << endl;
    cout << setw(SPACING) << "R" << setw(SPACING) << "U" << setw(SPACING) << "A" << setw(SPACING) << "T" << endl;   
    cout << "--------------------------------------------------" << endl;
    cout << setw(SPACING) << MV[Rx] << setw(SPACING) << MV[Ux] << setw(SPACING) << MV[Ax]  << setw(SPACING) << MV[Tx] << endl;
    cout << setw(SPACING) << MV[Ry] << setw(SPACING) << MV[Uy] << setw(SPACING) << MV[Ay]  << setw(SPACING) << MV[Ty] << endl;
    cout << setw(SPACING) << MV[Rz] << setw(SPACING) << MV[Uz] << setw(SPACING) << MV[Az] << setw(SPACING)  << MV[Tz] << endl;
    cout << setw(SPACING) << MV[3] << setw(SPACING) << MV[7] << setw(SPACING) << MV[11] << setw(SPACING) << MV[15] << endl;
    cout << "--------------------------------------------------" << endl;
    cout << endl;
}

void reshape(int w, int h) {
    float ratio = static_cast<float>(w)/h;
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, ratio, 1.0, 425.0);
}

void draw() {
    float m[16];
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glGetFloatv(GL_MODELVIEW_MATRIX, m);
    gluLookAt(
        300.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f
    );
    glColor3f(1.0, 0.0, 0.0);
    glutSolidCube(100.0);
    glGetFloatv(GL_MODELVIEW_MATRIX, m);
    displayModelviewMatrix(m);
    glutSwapBuffers();
}


int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(400, 400);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Demo");
    glutReshapeFunc(reshape);
    glutDisplayFunc(draw);
    init();
    glutMainLoop();
    return 0;
} 

No matter what value I use for the eye vector: 无论我使用什么值的eye矢量:
300, 0, 0 or 300, 0, 0
0, 300, 0 or 0, 300, 0
0, 0, 300
the translation vector is the same, which doesn't make any sense because the order of code is in backward order so glTranslatef should run first, then the 2 rotations. 翻译向量是相同的,这没有任何意义,因为代码的顺序是向后的顺序,因此glTranslatef应首先运行,然后运行2次旋转。 Plus, the rotation matrix, is completely independent of the translation column (in the ModelView matrix), then what would cause this weird behavior? 另外,旋转矩阵完全独立于平移列(在ModelView矩阵中),那会导致这种奇怪的行为? Here is the output with the eye vector is (0.0f, 300.0f, 0.0f) 这是眼睛矢量的输出是(0.0f, 300.0f, 0.0f)

        MODELVIEW MATRIX
--------------------------------------------------
R           U           A           T
--------------------------------------------------
0           0           0           0
0           0           0           0
0           1           0           -300
0           0           0           1
--------------------------------------------------

I would expect the T column to be (0, -300, 0) ! 我希望T (0, -300, 0) So could anyone help me explain this? 那么有人可以帮我解释一下吗?

The implementation of gluLookAt from http://www.mesa3d.org http://www.mesa3d.org实施gluLookAt

void GLAPIENTRY
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
      GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
      GLdouble upz)
{
    float forward[3], side[3], up[3];
    GLfloat m[4][4];

    forward[0] = centerx - eyex;
    forward[1] = centery - eyey;
    forward[2] = centerz - eyez;

    up[0] = upx;
    up[1] = upy;
    up[2] = upz;

    normalize(forward);

    /* Side = forward x up */
    cross(forward, up, side);
    normalize(side);

    /* Recompute up as: up = side x forward */
    cross(side, forward, up);

    __gluMakeIdentityf(&m[0][0]);
    m[0][0] = side[0];
    m[1][0] = side[1];
    m[2][0] = side[2];

    m[0][1] = up[0];
    m[1][1] = up[1];
    m[2][1] = up[2];

    m[0][2] = -forward[0];
    m[1][2] = -forward[1];
    m[2][2] = -forward[2];

    glMultMatrixf(&m[0][0]);
    glTranslated(-eyex, -eyey, -eyez);
}

If we let a rotation and translation matrix like your modelview matrix 如果我们让旋转和平移矩阵像你的模型视图矩阵

Rxx Rxy Rxz Tx 
Ryx Ryy Ryz Ty 
Rzx Rzy Rzz Tz 
 0   0   0   1 

act on an arbitrary vector 作用于任意向量

x
y
z
1

we get 我们得到

Rxx x + Rxy y + Rxz z  +  Tx 
Ryx x + Ryy y + Ryz z  +  Ty
Rzx x + Rzy y + Rzz z  +  Tz
1

(I'm writing things so vectors get multiplied by matrices on the left). (我正在写东西,所以矢量乘以左边的矩阵)。

This shows that the translation components of the matrix give the translation to apply after doing the rotation. 这表明矩阵的平移分量使得在旋转之后应用平移。 That's why they aren't the same as your (-eye_x, -eye_y, -eye_z) vector, because as you point out that translation is being done before the rotation. 这就是为什么它们与你的(-eye_x,-eye_y,-eye_z)向量不同,因为你指出翻译是在旋转之前完成的。

The reason that the translation is always along the -z direction is because in the view frame the -z direction points towards the centre. 平移始终沿-z方向的原因是因为在视图框中-z方向指向中心。 Since you always have the centre 300 units from the eye, all of your eye positions put the centre at (0, 0, -300) in the view frame. 由于您总是从眼睛中心有300个单位,所以您的所有眼睛位置都将中心位于视图框中的(0,0,-300)。 Therefore, because the centre starts at the origin before we do any translating, the translation to give it the correct co-orindates must be (0, 0, -300). 因此,因为在我们进行任何翻译之前,中心从原点开始,所以给它正确的共同条件的翻译必须是(0,0,-300)。

Also, you might have noticed this, but the modelview matrix you show is pathological because you have the up vector pointing along the view direction (from eye to centre). 此外,您可能已经注意到了这一点,但您显示的模型视图矩阵是病态的,因为您的向上矢量指向视图方向(从眼睛到中心)。 That explains why it has two full rows of zeros. 这就解释了为什么它有两行完整的零。

" I'm very confused about how the rotations are performed using the forward, up and side vectors in this code..." I think you should know something about "UVN camera".There is some theory about coordinates translates between two coordinate systems.In the above examle, the two coordinates are world coordinates and camera coordinates. “我对使用此代码中的向前,向上和向侧矢量如何执行旋转感到非常困惑......”我认为您应该对“UVN相机”有所了解。有一些关于两个坐标系之间的坐标转换的理论在上面的例子中,两个坐标是世界坐标和摄像机坐标。 And the result is: x 结果是:x 在此输入图像描述

N - The vector from the target to camera. N - 从目标到相机的矢量。 Also known as the 'look at' vector in some 3D literature. 在一些3D文献中也被称为“look at”向量。 This vector corresponds to the -Z axe. 该向量对应于-Z ax。

V - When standing upright this is the vector from your head to the sky. V - 直立时,这是从头部到天空的矢量。 If you are writing a flight simulator and the plane is reversed that vector may very well point to the ground. 如果你正在编写一个飞行模拟器并且平面被反转,那么矢量很可能指向地面。 This vector corresponds to the Y axe. 该向量对应于Y ax。

U - This vector points from the camera to its "right" side". It corresponds to the X axe. U - 此向量从摄像机指向“右侧”。它对应于X轴。

@Andon M. Coleman - how is the above diagram row major? @Andon M. Coleman - 上图如何排成行? Having a Row or Column major matrix is about the memory representation of 2D structures in 1D memory and has nothing to do with the above diagram of a 4x4 transformation matrix. 具有行或列主矩阵是关于1D存储器中的2D结构的存储器表示,并且与4x4变换矩阵的上述图无关。

If vectors U,V,N were written as columns as you seem to suggest, then you would have a camera-space to world-space transformation. 如果向量U,V,N被写为你似乎建议的列,那么你将有一个相机空间进行世界空间转换。

However, the input to the matrix is world-space position and the output is camera-space position and so the matrix is a transformation world-space to camera-space. 然而,矩阵的输入是世界空间位置,输出是摄像机空间位置,因此矩阵是相机空间的变换世界空间。

The reason U,V,N are transposed is because this is the inverse of the matrix you suggest and by using the property of orthogonal matrices, where their inverse is also its transpose. 转换U,V,N的原因是因为这是你建议的矩阵的逆矩阵,并且使用正交矩阵的性质,其中它们的逆也是它的转置。 That is, we write U,V,N vectors to the rows to get a world-space to camera-space transformation and U,V,N to the columns to get camera-space to world-space transform. 也就是说,我们将U,V,N向量写入行以获得世界空间到相机空间变换,将U,V,N写入列以获得相机空间到世界空间变换。

Also, the choice of multiplying with the world position on the right is because the diagram is using column vectors. 此外,选择与右侧的世界位置相乘是因为该图使用列向量。 We would left multiply if we were using row vectors. 如果我们使用行向量,我们会离开。 It has NOTHING to do with how we store the matrix in memory and has everything to do with how we multiply two matrices together, that is, do we convert our vector to a 1X4 or a 4X1 matrix before we multiply it with the 4x4 matrix. 它与我们如何将矩阵存储在存储器中没有任何关系,并且与我们如何将两个矩阵相乘的方式有关,也就是说,在将它们与4x4矩阵相乘之前,我们是否将矢量转换为1X4或4X1矩阵。

In short, the above diagram is fine, it's just a transformation from one space to another, please don't confuse the matter with talk about memory layout which is a programming detail. 简而言之,上面的图表很好,它只是从一个空间到另一个空间的转换,请不要把这个问题与关于内存布局的讨论混淆,这是一个编程细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM