#pragma once #include #include #include struct Camera { glm::vec3 position; glm::vec3 front; glm::vec3 up; glm::vec3 right; glm::vec3 world_up; float yaw; // horizontal angle, degrees float pitch; // vertical angle, degrees float fov; float speed; float sensitivity; // Mouse state float last_x, last_y; bool first_mouse; bool cursor_captured; }; inline Camera camera_init(glm::vec3 position, float scr_width, float scr_height) { Camera c; c.position = position; c.world_up = glm::vec3(0.0f, 1.0f, 0.0f); c.yaw = -90.0f; // face -Z by default c.pitch = -20.0f; c.fov = 60.0f; c.speed = 5.0f; c.sensitivity = 0.1f; c.last_x = scr_width * 0.5f; c.last_y = scr_height * 0.5f; c.first_mouse = true; c.cursor_captured = false; // Compute initial vectors from yaw/pitch glm::vec3 front; front.x = cos(glm::radians(c.yaw)) * cos(glm::radians(c.pitch)); front.y = sin(glm::radians(c.pitch)); front.z = sin(glm::radians(c.yaw)) * cos(glm::radians(c.pitch)); c.front = glm::normalize(front); c.right = glm::normalize(glm::cross(c.front, c.world_up)); c.up = glm::normalize(glm::cross(c.right, c.front)); return c; } inline glm::mat4 camera_view(const Camera &c) { return glm::lookAt(c.position, c.position + c.front, c.up); } inline glm::mat4 camera_projection(const Camera &c, float aspect) { return glm::perspective(glm::radians(c.fov), aspect, 0.1f, 1000.0f); } // Call every frame with GLFW window inline void camera_keyboard(Camera &c, GLFWwindow *window, float dt) { if (!c.cursor_captured) return; float vel = c.speed * dt; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) c.position += c.front * vel; if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) c.position -= c.front * vel; if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) c.position -= c.right * vel; if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) c.position += c.right * vel; if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) c.position += c.world_up * vel; if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) c.position -= c.world_up * vel; } // Call from your GLFW cursor position callback inline void camera_mouse(Camera &c, double xpos, double ypos) { if (!c.cursor_captured) return; if (c.first_mouse) { c.last_x = (float)xpos; c.last_y = (float)ypos; c.first_mouse = false; } float dx = ((float)xpos - c.last_x) * c.sensitivity; float dy = (c.last_y - (float)ypos) * c.sensitivity; // inverted Y c.last_x = (float)xpos; c.last_y = (float)ypos; c.yaw += dx; c.pitch += dy; if (c.pitch > 89.0f) c.pitch = 89.0f; if (c.pitch < -89.0f) c.pitch = -89.0f; glm::vec3 front; front.x = cos(glm::radians(c.yaw)) * cos(glm::radians(c.pitch)); front.y = sin(glm::radians(c.pitch)); front.z = sin(glm::radians(c.yaw)) * cos(glm::radians(c.pitch)); c.front = glm::normalize(front); c.right = glm::normalize(glm::cross(c.front, c.world_up)); c.up = glm::normalize(glm::cross(c.right, c.front)); } // Call from scroll callback inline void camera_scroll(Camera &c, double yoffset) { c.fov -= (float)yoffset; if (c.fov < 10.0f) c.fov = 10.0f; if (c.fov > 90.0f) c.fov = 90.0f; }