added camera control

This commit is contained in:
JISAUAY 2025-11-10 12:58:30 -06:00
parent 849291b620
commit 5f1bf88374

View File

@ -9,9 +9,15 @@
#include "Object3D.h" #include "Object3D.h"
// Window dimensions // Window dimensions
const unsigned int SCR_WIDTH = 800; unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600; unsigned int SCR_HEIGHT = 600;
// Jump
const float JUMP_COOLDOWN = 0.0f;
const float JUMP_POWER = 10.0f; // Initial Jump Speed
float last_jump = 0.0f;
// Camera
const float CAMERA_SPEED = 1.0f; const float CAMERA_SPEED = 1.0f;
const float MAX_CAMERA_SPEED = 2.0f; const float MAX_CAMERA_SPEED = 2.0f;
const float LOOK_SENSITIVITY = 0.1f; const float LOOK_SENSITIVITY = 0.1f;
@ -21,12 +27,146 @@ const float Z_NEAR = 0.1f;
bool WIREFRAME_MODE = true; bool WIREFRAME_MODE = true;
const float FOV = 90.0f; const float FOV = 90.0f;
bool W_pressed, S_pressed, A_pressed, D_pressed = false;
glm::mat4 projection = glm::mat4(1.0f); glm::mat4 projection = glm::mat4(1.0f);
Camera camera = Camera(CAMERA_SPEED, glm::vec3(0.0f, 0.0f, 3.0f)); Camera camera = Camera(CAMERA_SPEED, glm::vec3(0.0f, 0.0f, 3.0f));
// Callback function for when the window is resized // Callback function for when the window is resized
void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // glfw: whenever the window size changed (by OS or user resize) this callback function executes
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
SCR_WIDTH = width;
SCR_HEIGHT = height;
// Perspective needs to be recalculated on window size change
projection = glm::perspective(glm::radians(FOV), (float)SCR_WIDTH / (float)SCR_HEIGHT, Z_NEAR, Z_FAR);
}
float yaw, pitch = 0;
bool first_mouse = true;
bool mouse_lock = true;
float last_x = 400, last_y = 300;
// Mouse Look
void mouse_callback(GLFWwindow * window, double xpos, double ypos)
{
float x_offset = xpos - last_x;
float y_offset = ypos - last_y;
last_x = xpos;
last_y = ypos;
if (first_mouse)
{
first_mouse = false;
return;
}
x_offset *= LOOK_SENSITIVITY;
y_offset *= LOOK_SENSITIVITY;
yaw += x_offset;
pitch += y_offset;
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
glm::vec3 direction;
direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
direction.y = -sin(glm::radians(pitch));
direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
camera.target = glm::normalize(direction);
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void processInput(GLFWwindow *window)
{
float current_time = glfwGetTime();
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
// if (mouse_lock) {
// glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
// mouse_lock = false;
// } else {
// glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// mouse_lock = true;
// }
glfwSetWindowShouldClose(window, true);
}
// ---- Movement ----
// Forward / Backward
if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
camera.forward_velocity = camera.speed * glm::vec3(camera.target.x, 0.0f, camera.target.z);
W_pressed = true;
}
if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
{
camera.forward_velocity = -camera.speed * glm::vec3(camera.target.x, 0.0f, camera.target.z);
S_pressed = true;
}
if(glfwGetKey(window, GLFW_KEY_S) == GLFW_RELEASE && S_pressed)
{
camera.forward_velocity = glm::vec3(0.0f);
S_pressed = false;
}
if(glfwGetKey(window, GLFW_KEY_W) == GLFW_RELEASE && W_pressed)
{
camera.forward_velocity = glm::vec3(0.0f);
W_pressed = false;
}
// Horizontal
if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
{
camera.horizontal_velocity = -glm::normalize(glm::cross(glm::vec3(camera.target.x, 0.0f, camera.target.z), camera.worldUp)) * camera.speed;
A_pressed = true;
}
if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
{
camera.horizontal_velocity = glm::normalize(glm::cross(glm::vec3(camera.target.x, 0.0f, camera.target.z), camera.worldUp)) * camera.speed;
D_pressed = true;
}
if(glfwGetKey(window, GLFW_KEY_A) == GLFW_RELEASE && A_pressed)
{
camera.horizontal_velocity = glm::vec3(0.0f);
A_pressed = false;
}
if(glfwGetKey(window, GLFW_KEY_D) == GLFW_RELEASE && D_pressed)
{
camera.horizontal_velocity = glm::vec3(0.0f);
D_pressed = false;
}
// Jump
if(glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
// camera.velocity -= glm::normalize(glm::cross(camera.target, glm::normalize(glm::cross(camera.target, camera.worldUp)))) * camera.speed * 0.5f;
{
if (current_time - last_jump > JUMP_COOLDOWN && camera.position.y == 0)
{
camera.vertical_velocity.y = JUMP_POWER;
last_jump = current_time;
}
}
// Sprint
if(glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
camera.speed = CAMERA_SPEED * 7.5;
if(glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_RELEASE)
camera.speed = CAMERA_SPEED * 20;
} }
int main() { int main() {
@ -95,27 +235,41 @@ int main() {
if (WIREFRAME_MODE) if (WIREFRAME_MODE)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Setup mouse look
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mouse_callback);
// Setup projection matrix // Setup projection matrix
projection = glm::perspective(glm::radians(FOV), (float)SCR_WIDTH / (float)SCR_HEIGHT, Z_NEAR, Z_FAR); // This doesn't need to be recalculated every frame projection = glm::perspective(glm::radians(FOV), (float)SCR_WIDTH / (float)SCR_HEIGHT, Z_NEAR, Z_FAR); // This doesn't need to be recalculated every frame
glm::mat4 view = camera.getView(); glm::mat4 view;
double start_time = glfwGetTime();
double move_time = glfwGetTime();
// 6. --- The Render Loop --- // 6. --- The Render Loop ---
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
// Input (e.g., close window on ESC) // Input (e.g., close window on ESC)
// processInput(window); processInput(window);
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear screen glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Z-Buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Z-Buffer
view = camera.getView();
// Draw the triangle // Draw the triangle
shader.use(); shader.use();
shader.setMat4("u_mvp", projection * view); shader.setMat4("u_mvp", projection * view);
glBindVertexArray(VAO); // Bind the VAO (our triangle's "recipe") glBindVertexArray(VAO); // Bind the VAO (our triangle's "recipe")
glDrawElements(GL_TRIANGLES, cube.EBO_buffer.size(), GL_UNSIGNED_INT, nullptr); // Draw it! glDrawElements(GL_TRIANGLES, cube.EBO_buffer.size(), GL_UNSIGNED_INT, nullptr); // Draw it!
double end_time = glfwGetTime();
float time_since_last_move = end_time - move_time;
if (time_since_last_move >= 0.017)
{
camera.move(time_since_last_move);
move_time = end_time;
}
// Swap buffers and poll for events // Swap buffers and poll for events
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();