Correct rotation of the Open GL camera using GLM

I have a camera class that initializes like this:

CameraFP::CameraFP() { this->aspect_ratio = 800.0f / 600.0f; this->fov = 45.0f; this->near_plane = 0.1f; this->far_plane = 1000.0f; this->position = glm::vec3(0, 0, 0); this->target = position + glm::vec3(0, 0, -1); this->up = glm::vec3(0, 1, 0); this->m_rotation = glm::mat4(1.0); m_view = glm::lookAt(position, target, up); m_projection = glm::perspective(fov, aspect_ratio, near_plane, far_plane); } 

And here are the other import functions:

 void CameraFP::update(sf::Window *app) { process_keyboard(app); process_mouse(app); calculate_view(); } void CameraFP::process_keyboard(sf::Window *app) { const sf::Input *input = &app->GetInput(); up = m_rotation * glm::vec3(0, 1, 0); glm::vec3 forward = glm::vec3(0, 0, -1); glm::vec3 forward_rotated = m_rotation * forward; glm::vec3 right = glm::vec3(1, 0, 0); glm::vec3 right_rotated = m_rotation * right; if (input->IsKeyDown(sf::Key::W)) { position += forward_rotated; } if (input->IsKeyDown(sf::Key::S)) { position -= forward_rotated; } if (input->IsKeyDown(sf::Key::A)) { position -= right_rotated; } if (input->IsKeyDown(sf::Key::D)) { position += right_rotated; } } void CameraFP::process_mouse(sf::Window *app) { // TODO: Make the below constants, and take framerate into account GLfloat SPEED_X = 0.000001f; GLfloat SPEED_Y = 0.000001f; GLfloat mouse_x = app->GetInput().GetMouseX(); GLfloat mouse_y = app->GetInput().GetMouseY(); GLfloat mouse_x_delta = old_mouse_x - mouse_x; GLfloat mouse_y_delta = old_mouse_y - mouse_y; if (mouse_x_delta != 0 || mouse_y_delta != 0) { if (mouse_x_delta != 0) { y_rot += mouse_x_delta * SPEED_X; m_rotation = glm::rotate(m_rotation, y_rot, glm::vec3(0, 1, 0)); } if (mouse_y_delta != 0) { x_rot += mouse_y_delta * SPEED_Y; m_rotation = glm::rotate(m_rotation, x_rot, glm::vec3(1, 0, 0));; } } this->old_mouse_x = mouse_x; this->old_mouse_y = mouse_y; app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2); } void CameraFP::calculate_view() { glm::vec3 forward = glm::vec3(0, 0, -1); glm::vec3 forward_rotated = m_rotation * forward; target = position += glm::normalize(forward_rotated); m_view = glm::lookAt(position, target, up); } 

My problem is that when I compile the project, the compiler generates an error:

 \CameraFP.cpp|59|error: no match for 'operator*' in '((CameraFP*)this)->CameraFP::m_rotation * glm::detail::tvec3<float>(((const int&)((const int*)(&0))), ((const int&)((const int*)(&1))), ((const int&)((const int*)(&0))))'| 

From what I understand vec = mat4 * vec should give a rotated vector? Since I could not verify this code, I do not know if the function is working correctly.

Edit

Updated code in accordance with comments and tags. My problem is that I get a BSOD somewhere in the rendering function ...

 void CameraFP::process_keyboard(sf::Window *app) { const sf::Input *input = &app->GetInput(); up = m_rotation * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f); glm::vec4 forward = glm::vec4(0.0f, 0.0f, -1.0f, 0.0f); glm::vec4 forward_rotated = m_rotation * forward; glm::vec4 right = glm::vec4(1.0f, 0.0f, 0.0f, 0.0f); glm::vec4 right_rotated = m_rotation * right; if (input->IsKeyDown(sf::Key::W)) { position += forward_rotated; } if (input->IsKeyDown(sf::Key::S)) { position -= forward_rotated; } if (input->IsKeyDown(sf::Key::A)) { position -= right_rotated; } if (input->IsKeyDown(sf::Key::D)) { position += right_rotated; } } void CameraFP::process_mouse(sf::Window *app) { // TODO: Make the below constants, and take framerate into account GLfloat SPEED_X = 0.000001f; GLfloat SPEED_Y = 0.000001f; GLfloat mouse_x = app->GetInput().GetMouseX(); GLfloat mouse_y = app->GetInput().GetMouseY(); GLfloat mouse_x_delta = old_mouse_x - mouse_x; GLfloat mouse_y_delta = old_mouse_y - mouse_y; if (mouse_x_delta != 0 || mouse_y_delta != 0) { if (mouse_x_delta != 0) { y_rot += mouse_x_delta * SPEED_X; m_rotation = glm::rotate(m_rotation, y_rot, glm::vec3(0.0f, 1.0f, 0.0f)); } if (mouse_y_delta != 0) { x_rot += mouse_y_delta * SPEED_Y; m_rotation = glm::rotate(m_rotation, x_rot, glm::vec3(1.0f, 0.0f, 0.0f));; } } this->old_mouse_x = mouse_x; this->old_mouse_y = mouse_y; app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2); } void CameraFP::calculate_view() { glm::vec4 forward = glm::vec4(0.0f, 0.0f, -1.0f, 0.0f); glm::vec4 forward_rotated = m_rotation * forward; target = position += forward_rotated; m_view = glm::lookAt(v4tov3(position), v4tov3(target), v4tov3(up)); } glm::vec3 v4tov3(glm::vec4 v1) { return glm::vec3(v1.x, v1.y, v1.z); } 

Edit 2

The problem is now associated with turning the camera with the mouse, it just does not work, for some reason, changes on the x-axis of time multiply the effect by y and vice versa. Also, if I move the mouse left or right on the x axis (y rotation), the camera rotates left ...

 void CameraFP::process_mouse(sf::Clock *clock, sf::Window *app) { // TODO: Make the below constants, and take framerate into account GLfloat SPEED_X = 0.25f; GLfloat SPEED_Y = 0.25f; GLfloat screen_x = app->GetWidth(); GLfloat screen_y = app->GetHeight(); GLfloat mouse_x = float(screen_x / 2 - app->GetInput().GetMouseX()); GLfloat mouse_y = float(screen_y / 2 - app->GetInput().GetMouseY()); GLfloat mouse_x_delta = old_mouse_x - mouse_x; GLfloat mouse_y_delta = old_mouse_y - mouse_y; GLfloat current_time = clock->GetElapsedTime(); GLfloat delta_time = current_time - last_time; this->last_time = current_time; if (mouse_x_delta != 0 || mouse_y_delta != 0) { if (mouse_x_delta != 0) { y_rot += glm::radians(delta_time * SPEED_X * mouse_x); m_rotation = glm::rotate(m_rotation, y_rot, glm::vec3(0.0f, 1.0f, 0.0f)); std::cout << "Y Rotation: " << y_rot << "\n"; } if (mouse_y_delta != 0) { x_rot += glm::radians(delta_time * SPEED_Y * mouse_y); m_rotation = glm::rotate(m_rotation, x_rot, glm::vec3(1.0f, 0.0f, 0.0f)); std::cout << "X rotation: " << x_rot << "\n"; } } app->SetCursorPosition(screen_x / 2, screen_y / 2); this->old_mouse_x = float(screen_x / 2 - app->GetInput().GetMouseX()); this->old_mouse_y = float(screen_y / 2 - app->GetInput().GetMouseY()); } 
+6
source share
2 answers

Replace all glm :: vec3 (0, 1, 0); by glm :: vec3 (0.0f, 1.0f, 0.0f);

Regarding the multiplication of vec-mac, AquilaRapax is right that you can only multiply mat4 by vec4. But since you multiply directions, the 4th coordinate should be 0.0f, not 1.0f. This will result in ignoring translations (1.0 will call them into account, which you don't need)

For more information on matrices, see http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ .

However, it is often recommended to keep vec3 instead of vec4, mainly for clarity (i.e. glm :: vec3 mPosition instead of glm :: vec4 mPosition). Thus, it is convenient to have 2 functions similar to these (untested):

 glm::vec3 TransformDirection(glm::vec3 pDirection, glm::mat4 pMatrix){ return pMatrix * glm::vec4(pDirection, 0.0f); } glm::vec3 TransformPosition(glm::vec3 pDirection, glm::mat4 pMatrix){ return pMatrix * glm::vec4(pDirection, 1.0f); } 
+7
source

At the end of process::mouse you save the coordinates in old_mouse_x and old_mouse_y , but then move the cursor to the middle of the screen. If you do this, old_mouse_x and old_mouse_y will become invalid. What you need to do is set these variables after moving the cursor:

 app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2); this->old_mouse_x = app->GetWidth() / 2; this->old_mouse_y = app->GetHeight() / 2; 
0
source

Source: https://habr.com/ru/post/923835/


All Articles