gluLookAt ทำงานอย่างไร


9

จากความเข้าใจของฉัน

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)! ดังนั้นใครช่วยอธิบายได้บ้าง

การดำเนินการของgluLookAtจากhttp://www.mesa3d.org

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

คำตอบ:


7

gluLookAtจะหมุนและแปลโลกในทางที่กล้องจะอยู่ที่{0, 0, 0}และมองไปทางแกน z เชิงลบ นี่คือการตั้งค่ากล้องที่ใช้ใน OpenGL กล้องไม่เคยเคลื่อนไหวจริงๆโลกทำ ฟังดูสับสนไหม? เฮ้ใช่ให้ฉันลองอธิบาย :)

ให้นำตัวอย่างนี้:

eye    :  {300, 0, 0}
lookat :  {  0, 0, 0}
up     :  {  0, 1, 0}

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

ครั้งแรกที่เราจะต้องวิเคราะห์ส่วนที่หมุนของเมทริกซ์: R, และU Aที่คุณสามารถดูเวกเตอร์ที่เหมาะสม ( R) ไม่ได้อยู่ในแกน x อีกต่อไป{1, 0, 0}มันอยู่ในแกน {0, 0, 1}z นั่นหมายความว่ามันหมุนได้ 90 องศารอบแกน y เช่นเดียวกับตำแหน่งตา การหมุน{-300, 0, 0}90 องศารอบแกน y ทำให้มันจบลงที่{0, 0, -300}voila นั่นก็คือ

มันเป็น-300และไม่ได้300เพราะโลกจะถูกย้ายไปและไม่ได้กล้องเพื่อให้โลกมีการเคลื่อนไหวในทิศทางที่ตรงข้ามยังคง 300 {0, 0, 0}หน่วยอยู่ห่างจากกล้องไปที่ และอีกครั้งมันถูกย้ายไปทางแกน z ลบเพราะนั่นคือที่ที่กล้อง OpenGL ดูตามที่กล่าวไว้ข้างต้น


หมายเหตุ: มีความผิดปกติในตัวอย่างของคุณเวกเตอร์ปกติจากตำแหน่งตาถึงจุดที่มองต้องไม่เหมือนกันกับเวกเตอร์ up ดังนั้น:

eye    : {0, 300, 0}
lookat : {0,   0, 0}
up     : {0,   1, 0}    

normalize(eye - lookat): {0, 1, 0} -> the same as the up-vector

ในความเป็นจริงจะไม่ทำงานเราต้องเลือกอัพเวกเตอร์อีกตัวอย่าง {1, 0, 0}


ขอบคุณมากแม้ว่าฉันจะยังสับสนอยู่บ้างแม้ว่าฉันจะเข้าใจคำอธิบายของคุณ
Chan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.