MODEL LOADING BABY WORKS
This commit is contained in:
+78
-116
@@ -6,11 +6,13 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include "glm/gtx/norm.hpp"
|
||||
|
||||
|
||||
Camera::Camera(const glm::vec3& position, const glm::vec3& up): m_position{position}, m_up{up} {
|
||||
Camera::Camera(const glm::vec3& position, const glm::vec3& up)
|
||||
: m_position{position}, m_up{up} {
|
||||
// Initialize yaw to -90 degrees so the camera faces -Z by default
|
||||
m_yaw = -glm::half_pi<float>();
|
||||
m_pitch = 0.0f;
|
||||
}
|
||||
|
||||
void Camera::Update(float deltaTime) {
|
||||
@@ -22,166 +24,126 @@ void Camera::Update(float deltaTime) {
|
||||
moveSpeed *= 2.0f;
|
||||
}
|
||||
|
||||
// Controller speed boost (pad0 LB)
|
||||
const SDL_JoystickID pad0 = input.GetPadInstanceId(0);
|
||||
if (pad0 >= 0 && input.IsPadButtonDown(pad0, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) {
|
||||
moveSpeed *= 3.0f;
|
||||
}
|
||||
|
||||
// Clamp pitch like your old code
|
||||
m_pitch = glm::clamp(m_pitch, -glm::half_pi<float>() + 0.01f, glm::half_pi<float>() - 0.01f);
|
||||
|
||||
// =========================
|
||||
// Movement (Keyboard)
|
||||
// Look Input (Keyboard & Controller)
|
||||
// =========================
|
||||
glm::vec3 move(0.0f);
|
||||
|
||||
if (input.IsKeyDown(SDL_SCANCODE_W)) move += m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_S)) move -= m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_D)) move += m_right;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_A)) move -= m_right;
|
||||
|
||||
if (input.IsKeyDown(SDL_SCANCODE_Q)) move += m_up;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_E)) move -= m_up;
|
||||
|
||||
if (glm::length2(move) > 0.0f) {
|
||||
move = glm::normalize(move);
|
||||
m_position += move * (moveSpeed * deltaTime);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Movement (Controller)
|
||||
// =========================
|
||||
if (pad0 >= 0) {
|
||||
const float lx = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTX); // [-1..1]
|
||||
const float ly = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTY); // [-1..1]
|
||||
|
||||
// SDL Y is typically +down, so invert for "forward"
|
||||
glm::vec3 padMove(0.0f);
|
||||
padMove += m_forward * (-ly);
|
||||
padMove += m_right * ( lx);
|
||||
|
||||
// Triggers for vertical movement (optional)
|
||||
// SDL controller triggers are axes too: 0..1-ish after normalization in our helper, but signless.
|
||||
// With our NormalizeAxis, triggers will sit near 0 until pressed (depending on mapping).
|
||||
// If your NormalizeAxis maps triggers weirdly, swap to raw event value approach.
|
||||
const float lt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
|
||||
const float rt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
|
||||
const float vertical = (rt - lt);
|
||||
padMove += m_up * vertical;
|
||||
|
||||
if (glm::length2(padMove) > 0.0001f) {
|
||||
// do NOT normalize: preserve analog magnitude for smooth movement
|
||||
m_position += padMove * (moveSpeed * deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Look (Keyboard arrows only)
|
||||
// =========================
|
||||
// Use radians/sec so framerate-independent
|
||||
const float keyLookSpeed = glm::radians(120.0f); // degrees per second
|
||||
|
||||
const float keyLookSpeed = glm::radians(120.0f);
|
||||
if (input.IsKeyDown(SDL_SCANCODE_UP)) m_pitch += keyLookSpeed * deltaTime;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_DOWN)) m_pitch -= keyLookSpeed * deltaTime;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_LEFT)) m_yaw -= keyLookSpeed * deltaTime;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_RIGHT)) m_yaw += keyLookSpeed * deltaTime;
|
||||
|
||||
// =========================
|
||||
// Look (Controller right stick)
|
||||
// =========================
|
||||
if (pad0 >= 0) {
|
||||
const float rx = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_RIGHTX);
|
||||
const float ry = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_RIGHTY);
|
||||
|
||||
const float padLookSpeed = 2.2f; // radians/sec at full deflection
|
||||
const float padLookSpeed = 2.2f;
|
||||
m_yaw += rx * padLookSpeed * deltaTime;
|
||||
m_pitch += ry * padLookSpeed * deltaTime;
|
||||
m_pitch -= ry * padLookSpeed * deltaTime; // Inverted to match stick convention
|
||||
}
|
||||
|
||||
// Clamp pitch again after modifications
|
||||
// Clamp pitch to prevent flipping over the top
|
||||
m_pitch = glm::clamp(m_pitch, -glm::half_pi<float>() + 0.01f, glm::half_pi<float>() - 0.01f);
|
||||
|
||||
// Recompute basis from yaw/pitch (same convention you used)
|
||||
const glm::mat4 yawMatrix = glm::rotate(glm::mat4(1.0f), -m_yaw, glm::vec3(0, 1, 0));
|
||||
const glm::mat4 pitchMatrix = glm::rotate(glm::mat4(1.0f), m_pitch, glm::vec3(0, 0, 1));
|
||||
const glm::mat4 rotation = yawMatrix * pitchMatrix;
|
||||
// =========================
|
||||
// Update Basis Vectors
|
||||
// =========================
|
||||
// Standard Spherical to Cartesian coordinates (Y-Up, Right-Handed)
|
||||
glm::vec3 front;
|
||||
front.x = cos(m_yaw) * cos(m_pitch);
|
||||
front.y = sin(m_pitch);
|
||||
front.z = sin(m_yaw) * cos(m_pitch);
|
||||
|
||||
m_forward = glm::normalize(glm::vec3(rotation * glm::vec4(1, 0, 0, 0))); // +X forward
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_forward = glm::normalize(front);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0))); // World Up
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
// keep target mode off when manually controlled
|
||||
m_useTarget = false;
|
||||
// =========================
|
||||
// Movement Input
|
||||
// =========================
|
||||
glm::vec3 move(0.0f);
|
||||
if (input.IsKeyDown(SDL_SCANCODE_W)) move += m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_S)) move -= m_forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_D)) move += m_right;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_A)) move -= m_right;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_Q)) move += glm::vec3(0, 1, 0); // Absolute Up
|
||||
if (input.IsKeyDown(SDL_SCANCODE_E)) move -= glm::vec3(0, 1, 0); // Absolute Down
|
||||
|
||||
if (glm::length2(move) > 0.0f) {
|
||||
m_position += glm::normalize(move) * (moveSpeed * deltaTime);
|
||||
}
|
||||
|
||||
// Controller Movement
|
||||
if (pad0 >= 0) {
|
||||
const float lx = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
const float ly = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
const float lt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
|
||||
const float rt = input.GetPadAxis(pad0, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
|
||||
|
||||
glm::vec3 padMove = (m_forward * -ly) + (m_right * lx) + (glm::vec3(0, 1, 0) * (lt - rt));
|
||||
if (glm::length2(padMove) > 0.0001f) {
|
||||
m_position += padMove * (moveSpeed * deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
m_useTarget = false;
|
||||
CalculateProjectionMatrix();
|
||||
CalculateViewMatrix();
|
||||
}
|
||||
|
||||
void Camera::CalculateViewMatrix() {
|
||||
if (m_useTarget) {
|
||||
m_forward = glm::normalize(m_target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
m_viewMatrix = glm::lookAt(m_position, m_target, m_up);
|
||||
m_viewMatrix = glm::lookAt(m_position, m_target, glm::vec3(0, 1, 0));
|
||||
} else {
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position + m_forward, m_up);
|
||||
}
|
||||
|
||||
m_invMatrix = glm::inverse(m_viewMatrix);
|
||||
}
|
||||
|
||||
void Camera::CalculateProjectionMatrix() {
|
||||
// RH_ZO: Right-Handed, Zero-to-One depth (Vulkan/D3D standard)
|
||||
m_projectionMatrix = glm::perspectiveRH_ZO(glm::radians(fovAngle), m_aspectRatio, m_zNear, m_zFar);
|
||||
|
||||
// CRITICAL VULKAN FIX: Flip Y-axis
|
||||
// This keeps the world upright and fixes winding order issues
|
||||
m_projectionMatrix[1][1] *= -1;
|
||||
}
|
||||
|
||||
void Camera::ClearTarget() {
|
||||
m_useTarget = false;
|
||||
m_forward = glm::normalize(m_target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
}
|
||||
|
||||
void Camera::SetTarget(const glm::vec3& target) {
|
||||
m_target = target;
|
||||
m_useTarget = true;
|
||||
// m_forward = glm::normalize(m_target - m_position);
|
||||
// m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
// m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
}
|
||||
|
||||
void Camera::Target(const glm::vec3& target) {
|
||||
glm::vec3 directionToTarget = glm::normalize(target - m_position);
|
||||
|
||||
m_forward = glm::normalize(target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position + m_forward, m_up);
|
||||
m_invMatrix = glm::inverse(m_viewMatrix);
|
||||
}
|
||||
// ---------------------------------------------------------
|
||||
// Helpers to keep orientation consistent
|
||||
// ---------------------------------------------------------
|
||||
|
||||
void Camera::SetRotation(float yawRadians, float pitchRadians) {
|
||||
m_yaw = yawRadians;
|
||||
m_pitch = glm::clamp(
|
||||
pitchRadians,
|
||||
-glm::half_pi<float>() + 0.001f,
|
||||
glm::half_pi<float>() - 0.001f
|
||||
);
|
||||
m_pitch = glm::clamp(pitchRadians, -glm::half_pi<float>() + 0.001f, glm::half_pi<float>() - 0.001f);
|
||||
|
||||
// Yaw around world Y, pitch around local Z (same convention you used)
|
||||
const glm::mat4 yawMatrix = glm::rotate(glm::mat4(1.0f), -m_yaw, glm::vec3(0, 1, 0));
|
||||
const glm::mat4 pitchMatrix = glm::rotate(glm::mat4(1.0f), m_pitch, glm::vec3(0, 0, 1));
|
||||
const glm::mat4 rotation = yawMatrix * pitchMatrix;
|
||||
|
||||
// Forward is +X in your camera space
|
||||
m_forward = glm::normalize(glm::vec3(rotation * glm::vec4(1, 0, 0, 0)));
|
||||
glm::vec3 front;
|
||||
front.x = cos(m_yaw) * cos(m_pitch);
|
||||
front.y = sin(m_pitch);
|
||||
front.z = sin(m_yaw) * cos(m_pitch);
|
||||
m_forward = glm::normalize(front);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
m_useTarget = false; // rotation overrides target mode
|
||||
}
|
||||
|
||||
void Camera::SetRotation(const glm::vec2& yawPitchRadians) {
|
||||
SetRotation(yawPitchRadians.x, yawPitchRadians.y);
|
||||
}
|
||||
|
||||
void Camera::SetTarget(const glm::vec3& target) {
|
||||
}
|
||||
|
||||
void Camera::ClearTarget() {
|
||||
}
|
||||
|
||||
void Camera::Target(const glm::vec3& target) {
|
||||
m_target = target;
|
||||
m_useTarget = true;
|
||||
m_forward = glm::normalize(target - m_position);
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user