2013-08-09 38 views
7

Tôi đang sử dụng glm để tạo một lớp máy ảnh và tôi đang gặp phải một số vấn đề với chức năng tìm kiếm. Tôi đang sử dụng một quaternion để đại diện cho luân chuyển, nhưng tôi muốn sử dụng chức năng tìm kiếm viết trước của glm để tránh trùng lặp mã. Đây là chức năng tìm kiếm của tôi ngay bây giờ:Chuyển đổi glm :: ma trận tìm kiếm thành quaternion và quay lại

void Camera::LookAt(float x, float y, float z) { 
    glm::mat4 lookMat = glm::lookAt(position, glm::vec3(x, y, z), glm::vec3(0, 1, 0)); 
    rotation = glm::toQuat(lookMat); 
} 

Tuy nhiên khi tôi gọi LookAt(0.0f,0.0f,0.0f), máy ảnh của tôi không được xoay đến điểm đó. Khi tôi gọi glm::eulerangles(rotation) sau cuộc gọi tìm kiếm, tôi nhận được một vec3 với các giá trị sau: (180.0f, 0.0f, 180.0f). position là (0.0f, 0.0f, -10.0f), vì vậy tôi không nên quay vòng để xem xét 0,0,0. Đây là chức năng tạo ma trận chế độ xem:

glm::mat4 Camera::GetView() { 
    view = glm::toMat4(rotation) * glm::translate(glm::mat4(), position); 
    return view; 
} 

Tại sao tôi không nhận được quaternion chính xác và cách sửa mã của tôi?

Trả lời

0

Tôi muốn sử dụng chức năng tìm kiếm được viết trước của glm để tránh trùng lặp mã.

Nhưng đó là không mã trùng lặp. Ma trận xuất phát từ số glm::lookat chỉ là mat4. Đi qua chuyển đổi từ một quaternion đến 3 vectơ, chỉ để glm::lookat có thể chuyển đổi nó trở lại thành một định hướng chỉ là một sự lãng phí thời gian. Bạn đã hoàn thành 85% công việc của lookat; chỉ cần làm phần còn lại.

+1

Điều này thực sự không có câu trả lời thỏa mãn, vì có thể có lý do để thực sự giữ một quaternion thay thế. Nói "chỉ cần sử dụng ma trận" là không có trả lời khi ai đó hỏi bạn một cách để tạo ra một lookat-quaternion. – opatut

+0

@opatut: Tôi không nói "chỉ sử dụng ma trận". Tôi nói không có điểm nào trong việc biến đổi một quaternion thành 3 véc tơ nhìn vào với mục đích duy nhất là tạo ra một ma trận, khi bạn chỉ có thể sử dụng trực tiếp quaternion. –

1

Tôi chạy vào một cái gì đó tương tự, câu trả lời ngắn là lookMat của bạn có thể cần phải được đảo ngược/transposed, bởi vì nó là một máy quay (ít nhất là trong trường hợp của tôi), trái ngược với một vòng quay thế giới. Xoay thế giới sẽ là một nghịch đảo của một vòng quay camera.

Tôi có một m_current_quat là một quaternion lưu trữ xoay máy ảnh hiện tại. Tôi đã sửa lỗi vấn đề bằng cách in ra ma trận được tạo ra bởi glm :: lookAt và so sánh với ma trận kết quả mà tôi nhận được bằng cách áp dụng m_current_quat và bản dịch bởi m_camera_position. Đây là mã có liên quan cho thử nghiệm của tôi.

void PrintMatrix(const GLfloat m[16], const string &str) 
{ 
    printf("%s:\n", str.c_str()); 

    for (int i=0; i<4; i++) 
    { 
     printf("["); 
     //for (int j=i*4+0; j<i*4+4; j++) // row major, 0, 1, 2, 3 
     for (int j=i+0; j<16; j+=4) // OpenGL is column major by default, 0, 4, 8, 12 
     { 
      //printf("%d, ", j);   // print matrix index 
      printf("%.2f, ", m[j]); 

     } 
     printf("]\n"); 
    } 
    printf("\n"); 
} 

void CameraQuaternion::SetLookAt(glm::vec3 look_at) 
{ 
    m_camera_look_at = look_at; 

    // update the initial camera direction and up 
    //m_initial_camera_direction = glm::normalize(m_camera_look_at - m_camera_position); 
    //glm::vec3 initial_right_vector = glm::cross(m_initial_camera_direction, glm::vec3(0, 1, 0)); 
    //m_initial_camera_up = glm::cross(initial_right_vector, m_initial_camera_direction); 

    m_camera_direction = glm::normalize(m_camera_look_at - m_camera_position); 
    glm::vec3 right_vector = glm::cross(m_camera_direction, glm::vec3(0, 1, 0)); 
    m_camera_up = glm::cross(right_vector, m_camera_direction); 


    glm::mat4 lookat_matrix = glm::lookAt(m_camera_position, m_camera_look_at, m_camera_up); 

    // Note: m_current_quat quat stores the camera rotation with respect to the camera space 
    // The lookat_matrix produces a transformation for world space, where we rotate the world 
    // with the camera at the origin 
    // Our m_current_quat need to be an inverse, which is accompolished by transposing the lookat_matrix 
    // since the rotation matrix is orthonormal. 
    m_current_quat = glm::toQuat(glm::transpose(lookat_matrix));  

    // Testing: Make sure our model view matrix after gluLookAt, glmLookAt, and m_current_quat agrees 
    GLfloat current_model_view_matrix[16];    

    //Test 1: gluLookAt 
    gluLookAt(m_camera_position.x, m_camera_position.y, m_camera_position.z, 
       m_camera_look_at.x, m_camera_look_at.y, m_camera_look_at.z, 
       m_camera_up.x, m_camera_up.y, m_camera_up.z);  
    glGetFloatv(GL_MODELVIEW_MATRIX, current_model_view_matrix);       
    PrintMatrix(current_model_view_matrix, "Model view after gluLookAt"); 

    //Test 2: glm::lookAt 
    lookat_matrix = glm::lookAt(m_camera_position, m_camera_look_at, m_camera_up); 
    PrintMatrix(glm::value_ptr(lookat_matrix), "Model view after glm::lookAt"); 

    //Test 3: m_current_quat 
    glLoadIdentity(); 
    glMultMatrixf(glm::value_ptr(glm::transpose(glm::mat4_cast(m_current_quat)))); 
    glTranslatef(-m_camera_position.x, -m_camera_position.y, -m_camera_position.z); 
    glGetFloatv(GL_MODELVIEW_MATRIX, current_model_view_matrix);       
    PrintMatrix(current_model_view_matrix, "Model view after quaternion transform");  

    return; 
} 

Hy vọng điều này sẽ hữu ích.

0

Bạn nhận (hoặc tốt hơn: a) xoay đúng.

Khi tôi gọi glm::eulerangles(rotation) sau khi cuộc gọi lookat, tôi nhận được một vec3 với các giá trị sau: (180.0f, 0.0f, 180.0f). position là (0.0f, 0.0f, -10.0f), vì vậy tôi không nên xoay vòng để xem ở 0,0,0.

glm tuân theo quy ước của hàm cố định GL cũ. Và ở đó, không gian mắt được định nghĩa là máy ảnh được đặt ở gốc, với x pointng ở bên phải, y và nhìn theo hướng -z. Vì bạn muốn nhìn theo hướng dương z, máy ảnh phải bật. Bây giờ, như một con người, tôi đã mô tả rằng như một vòng quay 180 độ xung quanh y, nhưng một vòng quay 180 độ xung quanh x kết hợp với một vòng quay 180 độ xung quanh z sẽ có tác dụng tương tự.

4

Để khắc phục lỗi này, bạn chỉ cần đảo ngược vòng quay của quaternion bạn nhận bởi conjugating nó như thế này:

using namespace glm; 

quat orientation = conjugate(toQuat(lookAt(vecA, vecB, up))); 

đoán tốt nhất của tôi cho nguyên nhân sẽ là, GLM mà làm cho nó một chuyển động quay máy ảnh phải xoay vòng thế giới, ngược lại với vòng quay của người xem.

+0

upvote, chỉ giúp tôi chuyển đổi một vector hướng sợ hãi thành một quaternion thích hợp – Avithohol

Các vấn đề liên quan