// // Created by Bram on 11/12/2024. // #include #include "Camera.h" #include "GamePadController.h" dae::Camera::Camera(const dae::Vector3 &_origin, float _fovAngle) : origin{_origin}, fovAngle{_fovAngle} { SetFOV(_fovAngle); } void dae::Camera::Initialize(float _fovAngle, dae::Vector3 _origin, float _aspect) { fovAngle = _fovAngle; fov = tanf((fovAngle * TO_RADIANS) / 2.f); aspect = _aspect; origin = _origin; } void dae::Camera::SetFOV(float _fovAngle) { fovAngle = _fovAngle; fov = tanf((fovAngle * TO_RADIANS) / 2.f); } void dae::Camera::CalculateViewMatrix() { viewMatrix = Matrix::CreateLookAtLH(origin, origin + forward, Vector3::UnitY); Matrix temp = viewMatrix; invViewMatrix = temp.Inverse(); right = invViewMatrix.GetAxisX(); up = invViewMatrix.GetAxisY(); forward = invViewMatrix.GetAxisZ(); } void dae::Camera::CalculateProjectionMatrix() { //TODO W3 ProjectionMatrix = Matrix::CreatePerspectiveFovLH(fov, aspect, zNear, zFar); //DirectX Implementation => https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovlh } void dae::Camera::Update(const dae::Timer *pTimer) { const float deltaTime = pTimer->GetElapsed(); //Keyboard Input const uint8_t *pKeyboardState = SDL_GetKeyboardState(nullptr); Vector3 zDirection{0.f, 0.f, 0.f}; const Vector3 xDirection{0.f, 0.f, 0.f}; const Vector3 yDirection{0.f, 0.f, 0.f}; float MovementSpeed{10.f}; if (pKeyboardState[SDL_SCANCODE_LSHIFT]) { MovementSpeed *= 2; } if (pKeyboardState[SDL_SCANCODE_W]) { origin += forward * deltaTime * MovementSpeed; } if (pKeyboardState[SDL_SCANCODE_A]) { origin -= right * deltaTime * MovementSpeed; } if (pKeyboardState[SDL_SCANCODE_S]) { origin -= forward * deltaTime * MovementSpeed; } if (pKeyboardState[SDL_SCANCODE_D]) { origin += right * deltaTime * MovementSpeed; } if (pKeyboardState[SDL_SCANCODE_E]) { origin += up * deltaTime * MovementSpeed; } if (pKeyboardState[SDL_SCANCODE_Q]) { origin -= up * deltaTime * MovementSpeed; } bool rightStickMoved = false; constexpr float DEADZONE = 5000; if (GamePadController::GetInstance().isAnyControllerConnected()) { //Controller float LeftStickX = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_LEFTX); float LeftStickY = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_LEFTY); float RightStickX = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_RIGHTX); float RightStickY = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_RIGHTY); if (std::abs(LeftStickX) > DEADZONE) { float correctedValue = remap(LeftStickX, -32767.f, 32767.f, -1.f, 1.f); origin += right * deltaTime * MovementSpeed * correctedValue; } if (std::abs(LeftStickY) > DEADZONE) { float correctedValue = -remap(LeftStickY, -32767, 32767, -1, 1); origin += forward * deltaTime * MovementSpeed * correctedValue; } //Look around Controller float lookMultiplier = 2.f; if (std::abs(RightStickX) > DEADZONE) { float correctedValue = remap(RightStickX, -32767.f, 32767.f, -1.f, 1.f); totalYaw += correctedValue * deltaTime * lookMultiplier; rightStickMoved = true; } if (std::abs(RightStickY) > DEADZONE) { float correctedValue = -remap(RightStickY, -32767.f, 32767.f, -1.f, 1.f); totalPitch += correctedValue * deltaTime * lookMultiplier; rightStickMoved = true; } //Controller Up and Down Triggers float LeftTrigger = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_TRIGGERLEFT); float RightTrigger = GamePadController::GetInstance().GetAxis(PLAYER1, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); if (std::abs(LeftTrigger) > DEADZONE) { float correctedValue = remap(LeftTrigger, 0.f, 32767.f, 0.f, 1.f); origin -= up * deltaTime * MovementSpeed * correctedValue; } if (std::abs(RightTrigger) > DEADZONE) { float correctedValue = remap(RightTrigger, 0.f, 32767.f, 0.f, 1.f); origin += up * deltaTime * MovementSpeed * correctedValue; } } //Mouse Input bool mousePosChange{false}; int mouseX{}, mouseY{}; const uint32_t mouseState = SDL_GetRelativeMouseState(&mouseX, &mouseY); mouseY *= -1; if (mouseState == SDL_BUTTON_X1) //rmb { totalYaw += (static_cast(mouseX) * mouseSens) * TO_RADIANS; totalPitch += (static_cast(mouseY) * mouseSens) * TO_RADIANS; mousePosChange = true; } else if (mouseState == SDL_BUTTON_LEFT) { zDirection = forward.Normalized() * static_cast(-mouseY); totalYaw += static_cast(mouseX) * mouseSens * TO_RADIANS; mousePosChange = true; } else if (mouseState == SDL_BUTTON_X2) //lmb + rmb { origin.y -= static_cast(mouseY) / 2; mousePosChange = true; } origin += ((zDirection + xDirection + yDirection) * cameraSpeed * deltaTime); if (mousePosChange || rightStickMoved) { const Matrix yawMatrix{Matrix::CreateRotationY(totalYaw)}; const Matrix pitchMatrix{Matrix::CreateRotationX(totalPitch)}; const Matrix finalRotation{pitchMatrix * yawMatrix}; forward = finalRotation.TransformVector(Vector3::UnitZ); forward.Normalize(); } //Update Matrices CalculateViewMatrix(); CalculateProjectionMatrix(); } dae::Matrix dae::Camera::GetViewProjectionMatrix() const { return viewMatrix * ProjectionMatrix; } const dae::Vector3 & dae::Camera::GetPosition() const { return origin; } const dae::Vector3 dae::Camera::GetRotation() const { return {totalPitch, totalYaw, 0.f}; } void dae::Camera::SetPosition(const dae::Vector3 &position) { origin = position; CalculateViewMatrix(); CalculateProjectionMatrix(); } void dae::Camera::SetRotation(const dae::Vector3 &rotation) { totalPitch = rotation.x; totalYaw = rotation.y; const Matrix yawMatrix{Matrix::CreateRotationY(totalYaw)}; const Matrix pitchMatrix{Matrix::CreateRotationX(totalPitch)}; const Matrix finalRotation{pitchMatrix * yawMatrix}; forward = finalRotation.TransformVector(Vector3::UnitZ); forward.Normalize(); CalculateViewMatrix(); CalculateProjectionMatrix(); }