From 4f83bb738c2a4655332b808c2dcd7b2c253bf9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Viveiros=20Guilherme?= Date: Wed, 2 Oct 2024 16:54:06 +0200 Subject: [PATCH] Rotational camera added. World Space movement adde --- project/src/Camera.h | 122 +++++++++++++++++++++++++++++++++++++-- project/src/Matrix.cpp | 63 ++++++++++++++------ project/src/Renderer.cpp | 10 +++- project/src/Scene.cpp | 40 +++++++++++++ project/src/Scene.h | 17 ++++++ project/src/Utils.h | 36 +++++++----- project/src/main.cpp | 3 +- 7 files changed, 248 insertions(+), 43 deletions(-) diff --git a/project/src/Camera.h b/project/src/Camera.h index 134b6fb..1c9239e 100644 --- a/project/src/Camera.h +++ b/project/src/Camera.h @@ -1,8 +1,10 @@ #pragma once +#include #include #include #include "Maths.h" +#include "SDL_events.h" #include "Timer.h" namespace dae @@ -20,6 +22,10 @@ namespace dae Vector3 origin{}; float fovAngle{ 90.f }; + float previousfovAngle{ fovAngle }; + float FOV{ tan((fovAngle * (PI / 180)) / 2) }; + float rotSpeed{10}; + float movSpeed{ 11 }; Vector3 forward{ Vector3::UnitZ }; Vector3 up{ Vector3::UnitY }; @@ -33,25 +39,129 @@ namespace dae Matrix CalculateCameraToWorld() { - //todo: W2 - throw std::runtime_error("Not Implemented Yet"); - return {}; + + Vector4 Right{ Vector3{}.Cross(Vector3::UnitY,forward).Normalized() ,0 }; + Vector4 Up{ Vector3{}.Cross(forward,Right).Normalized(),0 }; + Vector4 TVec{ origin ,1 }; + Matrix Onb{ Right,Up,forward, TVec }; + + return Onb; } void Update(Timer* pTimer) { + SDL_SetRelativeMouseMode(SDL_TRUE); + + if (fovAngle != previousfovAngle) + { + FOV = tan ((fovAngle * (PI / 180)) / 2); + + previousfovAngle = fovAngle; + } + + SDL_Event event; + + //if (SDL_PollEvent(&event)) + //{ + // if (SDL_MOUSEMOTION == event.type) + // { + // int x, y; + + // SDL_GetMouseState(&x, &y); + + // forward = Matrix::CreateRotation(x * rotSpeed * pTimer->GetElapsed(), y * rotSpeed * pTimer->GetElapsed(), 1).TransformVector(forward); + // } + //} + // + + + + const float deltaTime = pTimer->GetElapsed(); //Keyboard Input const uint8_t* pKeyboardState = SDL_GetKeyboardState(nullptr); - //Mouse Input int mouseX{}, mouseY{}; const uint32_t mouseState = SDL_GetRelativeMouseState(&mouseX, &mouseY); - //todo: W2 - //throw std::runtime_error("Not Implemented Yet"); + + // Move Forward + if (pKeyboardState[SDL_SCANCODE_W]) + { + Matrix forwardMovement = Matrix::CreateTranslation(0, 0, movSpeed); + origin = forwardMovement.TransformPoint(origin); + } + + // Move Backward + if (pKeyboardState[SDL_SCANCODE_S]) + { + Matrix backwardMovement = Matrix::CreateTranslation(0, 0, -movSpeed); + origin = backwardMovement.TransformPoint(origin); + } + + // Strafe Left + if (pKeyboardState[SDL_SCANCODE_A]) + { + Matrix leftMovement = Matrix::CreateTranslation(-movSpeed, 0, 0); + origin = leftMovement.TransformPoint(origin); + } + + // Strafe Right + if (pKeyboardState[SDL_SCANCODE_D]) + { + Matrix rightMovement = Matrix::CreateTranslation(movSpeed, 0, 0); + origin = rightMovement.TransformPoint(origin); + } + + + // Process mouse movements (relative to the last frame) + if (mouseState & SDL_BUTTON(SDL_BUTTON_RIGHT)) + { + + if (mouseX != 0 || mouseY != 0) + { + if (forward.z < 0) + { + forward = Matrix::CreateRotation(-(mouseY / rotSpeed) * deltaTime, (mouseX / rotSpeed) * deltaTime, 0).TransformVector(forward); + } + + else + { + forward = Matrix::CreateRotation((mouseY / rotSpeed) * deltaTime, (mouseX / rotSpeed) * deltaTime, 0).TransformVector(forward); + } + + } + } + + + + /* Vector3 moveVector = forward.Normalized() * movSpeed * deltaTime;; + + Vector3 rightVector = Vector3{}.Cross(up , forward).Normalized() * movSpeed * deltaTime; + + if (pKeyboardState[SDL_SCANCODE_W]) + { + origin += moveVector; + } + + if (pKeyboardState[SDL_SCANCODE_S]) + { + origin -= moveVector; + } + + if (pKeyboardState[SDL_SCANCODE_D]) + { + origin += rightVector; + } + + if (pKeyboardState[SDL_SCANCODE_A]) + { + origin -= rightVector; + }*/ + + } }; } diff --git a/project/src/Matrix.cpp b/project/src/Matrix.cpp index a031bbf..22f627f 100644 --- a/project/src/Matrix.cpp +++ b/project/src/Matrix.cpp @@ -103,9 +103,14 @@ namespace dae { Matrix Matrix::CreateTranslation(float x, float y, float z) { - //todo W2 - throw std::runtime_error("Not Implemented Yet"); - return {}; + + Matrix tMatrix{ Vector4{1,0,0,0}, + Vector4{0,1,0,0}, + Vector4{0,0,1,0}, + Vector4{x,y,z,1} }; + + return tMatrix; + } Matrix Matrix::CreateTranslation(const Vector3& t) @@ -115,30 +120,47 @@ namespace dae { Matrix Matrix::CreateRotationX(float pitch) { - //todo W2 - throw std::runtime_error("Not Implemented Yet"); - return {}; + + Matrix rMatrix{ Vector4{1,0,0,0}, + Vector4{0,cos(pitch),sin(pitch),0}, + Vector4{0,-sin(pitch),cos(pitch),0}, + Vector4{0,0,0,1}}; + + return rMatrix; + } Matrix Matrix::CreateRotationY(float yaw) { - //todo W2 - throw std::runtime_error("Not Implemented Yet"); - return {}; + + Matrix rMatrix{ Vector4{cos(yaw),0,-sin(yaw),0}, + Vector4{0,1,0,0}, + Vector4{sin(yaw),0,cos(yaw),0}, + Vector4{0,0,0,1} }; + + return rMatrix; + } Matrix Matrix::CreateRotationZ(float roll) { - //todo W2 - throw std::runtime_error("Not Implemented Yet"); - return {}; + + Matrix rMatrix{ Vector4{cos(roll),sin(roll),0,0}, + Vector4{-sin(roll),cos(roll),0,0}, + Vector4{0,0,1,0}, + Vector4{0,0,0,1} }; + + return rMatrix; + } Matrix Matrix::CreateRotation(const Vector3& r) { - //todo W2 - throw std::runtime_error("Not Implemented Yet"); - return {}; + + Matrix rMatrix{ CreateRotationX(r.x) * CreateRotationY(r.y) * CreateRotationZ(r.z)}; + + return rMatrix; + } Matrix Matrix::CreateRotation(float pitch, float yaw, float roll) @@ -148,9 +170,14 @@ namespace dae { Matrix Matrix::CreateScale(float sx, float sy, float sz) { - //todo W2 - throw std::runtime_error("Not Implemented Yet"); - return {}; + + Matrix sMatrix{ Vector4{sx,0,0,0}, + Vector4{0,sy,0,0}, + Vector4{0,0,sz,0}, + Vector4{0,0,0,1} }; + + return sMatrix; + } Matrix Matrix::CreateScale(const Vector3& s) diff --git a/project/src/Renderer.cpp b/project/src/Renderer.cpp index 8eb49ad..db335a7 100644 --- a/project/src/Renderer.cpp +++ b/project/src/Renderer.cpp @@ -23,6 +23,8 @@ Renderer::Renderer(SDL_Window * pWindow) : SDL_GetWindowSize(pWindow, &m_Width, &m_Height); m_AspectRatio = (m_Width / float(m_Height)) ; m_pBufferPixels = static_cast(m_pBuffer->pixels); + + } void Renderer::Render(Scene* pScene) const @@ -31,6 +33,8 @@ void Renderer::Render(Scene* pScene) const auto& materials = pScene->GetMaterials(); auto& lights = pScene->GetLights(); + const Matrix cameraToWorld = camera.CalculateCameraToWorld(); + for (int px{}; px < m_Width; ++px) { for (int py{}; py < m_Height; ++py) @@ -41,11 +45,13 @@ void Renderer::Render(Scene* pScene) const //creates a vector that holds a coordinate in 3D space dependent on which pixel the loop is on - Vector3 rayDirection{ float((2 * ((px + 0.5) / m_Width) - 1) * m_AspectRatio),float(1 - 2 * ((py + 0.5) / m_Height)),1}; + Vector3 rayDirection{ float((2 * ((px + 0.5) / m_Width) - 1) * m_AspectRatio * camera.FOV),float((1 - 2 * ((py + 0.5) / m_Height)) * camera.FOV),1}; rayDirection.Normalize(); + rayDirection = cameraToWorld.TransformVector(rayDirection); + //Creates a Ray from origin to the point where the current pixel in loop is - Ray viewRay{ {0,0,0},rayDirection}; + Ray viewRay{ camera.origin,rayDirection }; //Sets screen to black ColorRGB finalColor{ }; diff --git a/project/src/Scene.cpp b/project/src/Scene.cpp index 7859054..7d5184c 100644 --- a/project/src/Scene.cpp +++ b/project/src/Scene.cpp @@ -153,4 +153,44 @@ namespace dae { AddPlane({ 0.f, 0.f, 125.f }, { 0.f, 0.f,-1.f }, matId_Solid_Magenta); } #pragma endregion + + + void Scene_W2::Initialize() + { + m_Camera.origin = { 0.f,3.f,-9.f }; + m_Camera.fovAngle = 45.f; + + //default: Material id0 >> SolidColorMaterial (RED) + constexpr unsigned char matId_Solid_Red = 0; + const unsigned char matId_Solid_Blue = AddMaterial(new Material_SolidColor{ colors::Blue }); + + const unsigned char matId_Solid_Yellow = AddMaterial(new Material_SolidColor{ colors::Yellow }); + const unsigned char matId_Solid_Green = AddMaterial(new Material_SolidColor{ colors::Green }); + const unsigned char matId_Solid_Magenta = AddMaterial(new Material_SolidColor{ colors::Magenta }); + const unsigned char matId_Solid_Porple = AddMaterial(new Material_SolidColor{ ColorRGB(207, 159, 255)}); + + //Plane + AddPlane({ -5.f,0.f,0.f }, { 1.f,0.f,0.f }, matId_Solid_Green); + AddPlane({ 5.f,0.f,0.f }, { -1.f,0.f,0.f }, matId_Solid_Green); + AddPlane({ 0.f,0.f,0.f }, { 0.f,1.f,0.f }, matId_Solid_Yellow); + AddPlane({ 0.f,10.f,0.f }, { 0.f,-1.f,0.f }, matId_Solid_Yellow); + AddPlane({ 0.f,0.f,10.f }, { 0.f,0.f,-1.f }, matId_Solid_Magenta); + + //Spheres + AddSphere({-1.75f,1.f,0.f}, .75f, matId_Solid_Red); + AddSphere({0.f,1.f,0.f}, .75f, matId_Solid_Blue); + AddSphere({ 1.75f,1.f,0.f }, .75f, matId_Solid_Red); + AddSphere({ -1.75f,3.f,0.f }, .75f, matId_Solid_Blue); + AddSphere({ 0.f,3.f,0.f }, .75f, matId_Solid_Red); + AddSphere({ 1.75f,3.f,0.f }, .75f, matId_Solid_Blue); + + + + AddSphere({ 0.f,5.f,0.f }, .75f, matId_Solid_Porple); + + //Light + AddPointLight({ 0.f,5.f,-5.f }, 70.f, colors::White); + + } + } diff --git a/project/src/Scene.h b/project/src/Scene.h index 38fc88e..cd6a46c 100644 --- a/project/src/Scene.h +++ b/project/src/Scene.h @@ -77,4 +77,21 @@ namespace dae void Initialize() override; }; + + //WEEK 2 Test Scene + class Scene_W2 final : public Scene + { + public: + Scene_W2() = default; + ~Scene_W2() override = default; + + Scene_W2(const Scene_W2&) = delete; + Scene_W2(Scene_W2&&) noexcept = delete; + Scene_W2& operator=(const Scene_W2&) = delete; + Scene_W2& operator=(Scene_W2&&) noexcept = delete; + + void Initialize() override; + }; + + } diff --git a/project/src/Utils.h b/project/src/Utils.h index ec6b936..6ecda45 100644 --- a/project/src/Utils.h +++ b/project/src/Utils.h @@ -31,23 +31,27 @@ namespace dae float t0 = tca - thc; float t1 = tca + thc; - Vector3 point{ ray.origin + t0 * ray.direction }; - Vector3 point2{ ray.origin + t1 * ray.direction }; - - if (Vector3(ray.direction,point).SqrMagnitude() > Vector3(ray.direction, point2).SqrMagnitude()) + if (t0 >= ray.min && t0 < ray.max && t1 >= ray.min && t1 < ray.max) { - hitRecord.origin = Vector3(ray.direction, point2); - hitRecord.normal = Vector3(sphere.origin, Vector3(ray.direction, point2)).Normalized(); - hitRecord.t = t1; - return true; + Vector3 point{ ray.origin + t0 * ray.direction }; + Vector3 point2{ ray.origin + t1 * ray.direction }; + + if (Vector3(ray.direction, point).SqrMagnitude() > Vector3(ray.direction, point2).SqrMagnitude()) + { + hitRecord.origin = Vector3(ray.direction, point2); + hitRecord.normal = Vector3(sphere.origin, Vector3(ray.direction, point2)).Normalized(); + hitRecord.t = t1; + return true; + } + if (Vector3(ray.direction, point).SqrMagnitude() < Vector3(ray.direction, point2).SqrMagnitude()) + { + hitRecord.origin = Vector3(ray.direction, point); + hitRecord.normal = Vector3(sphere.origin, Vector3(ray.direction, point)).Normalized(); + hitRecord.t = t0; + return true; + } + } - - hitRecord.origin = Vector3(ray.direction, point); - hitRecord.normal = Vector3(sphere.origin, Vector3(ray.direction, point)).Normalized(); - hitRecord.t = t0; - return true; - - } @@ -63,7 +67,7 @@ namespace dae { float t = Vector3::Dot(plane.origin - ray.origin, plane.normal) / Vector3::Dot(ray.direction ,plane.normal); - if (t >= 0) + if (t >= ray.min && t < ray.max) { hitRecord.didHit = true; hitRecord.t = t; diff --git a/project/src/main.cpp b/project/src/main.cpp index 953031e..8fcce7e 100644 --- a/project/src/main.cpp +++ b/project/src/main.cpp @@ -47,9 +47,10 @@ int main(int argc, char* args[]) const auto pTimer = new Timer(); const auto pRenderer = new Renderer(pWindow); - const auto pScene = new Scene_W1(); + const auto pScene = new Scene_W2(); pScene->Initialize(); + //Start loop pTimer->Start();