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.
Đ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
@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. –