簡體   English   中英

gluLookAt如何工作?

[英]How does gluLookAt work?

根據我的理解,

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

相當於:

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

但是當我打印出ModelView矩陣時,對glTranslatef()的調用似乎無法正常工作。 這是代碼片段:

#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;
} 

無論我使用什么值的eye矢量:
300, 0, 0
0, 300, 0
0, 0, 300
翻譯向量是相同的,這沒有任何意義,因為代碼的順序是向后的順序,因此glTranslatef應首先運行,然后運行2次旋轉。 另外,旋轉矩陣完全獨立於平移列(在ModelView矩陣中),那會導致這種奇怪的行為? 這是眼睛矢量的輸出是(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
--------------------------------------------------

我希望T (0, -300, 0) 那么有人可以幫我解釋一下嗎?

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);
}

如果我們讓旋轉和平移矩陣像你的模型視圖矩陣

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

作用於任意向量

x
y
z
1

我們得到

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

(我正在寫東西,所以矢量乘以左邊的矩陣)。

這表明矩陣的平移分量使得在旋轉之后應用平移。 這就是為什么它們與你的(-eye_x,-eye_y,-eye_z)向量不同,因為你指出翻譯是在旋轉之前完成的。

平移始終沿-z方向的原因是因為在視圖框中-z方向指向中心。 由於您總是從眼睛中心有300個單位,所以您的所有眼睛位置都將中心位於視圖框中的(0,0,-300)。 因此,因為在我們進行任何翻譯之前,中心從原點開始,所以給它正確的共同條件的翻譯必須是(0,0,-300)。

此外,您可能已經注意到了這一點,但您顯示的模型視圖矩陣是病態的,因為您的向上矢量指向視圖方向(從眼睛到中心)。 這就解釋了為什么它有兩行完整的零。

“我對使用此代碼中的向前,向上和向側矢量如何執行旋轉感到非常困惑......”我認為您應該對“UVN相機”有所了解。有一些關於兩個坐標系之間的坐標轉換的理論在上面的例子中,兩個坐標是世界坐標和攝像機坐標。 結果是:x 在此輸入圖像描述

N - 從目標到相機的矢量。 在一些3D文獻中也被稱為“look at”向量。 該向量對應於-Z ax。

V - 直立時,這是從頭部到天空的矢量。 如果你正在編寫一個飛行模擬器並且平面被反轉,那么矢量很可能指向地面。 該向量對應於Y ax。

U - 此向量從攝像機指向“右側”。它對應於X軸。

@Andon M. Coleman - 上圖如何排成行? 具有行或列主矩陣是關於1D存儲器中的2D結構的存儲器表示,並且與4x4變換矩陣的上述圖無關。

如果向量U,V,N被寫為你似乎建議的列,那么你將有一個相機空間進行世界空間轉換。

然而,矩陣的輸入是世界空間位置,輸出是攝像機空間位置,因此矩陣是相機空間的變換世界空間。

轉換U,V,N的原因是因為這是你建議的矩陣的逆矩陣,並且使用正交矩陣的性質,其中它們的逆也是它的轉置。 也就是說,我們將U,V,N向量寫入行以獲得世界空間到相機空間變換,將U,V,N寫入列以獲得相機空間到世界空間變換。

此外,選擇與右側的世界位置相乘是因為該圖使用列向量。 如果我們使用行向量,我們會離開。 它與我們如何將矩陣存儲在存儲器中沒有任何關系,並且與我們如何將兩個矩陣相乘的方式有關,也就是說,在將它們與4x4矩陣相乘之前,我們是否將矢量轉換為1X4或4X1矩陣。

簡而言之,上面的圖表很好,它只是從一個空間到另一個空間的轉換,請不要把這個問題與關於內存布局的討論混淆,這是一個編程細節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM