diff --git a/include/Defines.h b/include/Defines.h index 78c2487..79cb783 100644 --- a/include/Defines.h +++ b/include/Defines.h @@ -114,6 +114,14 @@ struct Mat4 { return reinterpret_cast(this)[offset]; } + T* data() { + return reinterpret_cast(this); + } + + const T* data() const{ + return reinterpret_cast(this); + } + T at(std::size_t row, std::size_t column) const { return operator[](row * MATRIX_SIZE + column); } diff --git a/include/misc/Maths.h b/include/misc/Maths.h index 9f78b89..a83842d 100644 --- a/include/misc/Maths.h +++ b/include/misc/Maths.h @@ -10,6 +10,11 @@ namespace maths { // Vectors // ////////////////////////////////////////////////////////////////// +template +Vec2 operator+(const Vec2& vect, const Vec2& other) { + return {vect.x + other.x, vect.y + other.y}; +} + template Vec3 operator- (const Vec3& vect) { return { -vect.x, -vect.y, -vect.z }; @@ -32,6 +37,13 @@ Vec3 Normalize(const Vec3& vect) { return { vect.x / length, vect.y / length, vect.z / length }; } +template +Vec4 Normalize(const Vec4& vect) { + T length = std::sqrt(vect.x * vect.x + vect.y * vect.y + vect.z * vect.z + vect.w * vect.w); + + return { vect.x / length, vect.y / length, vect.z / length, vect.w / length }; +} + template T Dot(const Vec3& vect, const Vec3& other) { return vect.x * other.x + vect.y * other.y + vect.z * other.z; @@ -59,9 +71,9 @@ template Vec4 Dot(const Mat4& mat, const Vec4& vect) { return { Dot(*reinterpret_cast*>(&mat), vect), - Dot(*reinterpret_cast*>(&mat[Mat4::MATRIX_SIZE]), vect), - Dot(*reinterpret_cast*>(&mat[2 * Mat4::MATRIX_SIZE]), vect), - Dot(*reinterpret_cast*>(&mat[3 * Mat4::MATRIX_SIZE]), vect), + Dot(*reinterpret_cast*>(mat.data() + Mat4::MATRIX_SIZE), vect), + Dot(*reinterpret_cast*>(mat.data() + 2 * Mat4::MATRIX_SIZE), vect), + Dot(*reinterpret_cast*>(mat.data() + 3 * Mat4::MATRIX_SIZE), vect), }; } diff --git a/include/render/Renderer.h b/include/render/Renderer.h index 8d19841..9bad578 100644 --- a/include/render/Renderer.h +++ b/include/render/Renderer.h @@ -9,6 +9,15 @@ namespace td { namespace render { +struct Camera { + Mat4f viewMatrix; + Mat4f projectionMatrix; + Mat4f InvViewMatrix; + Mat4f InvProjectionMatrix; + + Vec3f CamPos; +}; + class Renderer { public: static constexpr float m_AnimationSpeed = 2.0f; @@ -24,9 +33,7 @@ private: Vec3f m_BackgroundColor; - bool m_IsometricView = true; - float m_IsometricShade = m_IsometricView; - Vec2f m_CamPos{}; + Camera m_Camera {}; public: Renderer(); ~Renderer(); @@ -41,15 +48,12 @@ public: void SetZoom(float zoom); void SetCamMovement(const Vec2f& mov); - void SetCamPos(const Vec2f& newPos); - void SetIsometricView(bool isometric); // false = 2D true = Isometric + void SetCamPos(const Vec3f& newPos); void SetBackgroundColor(const Vec3f& color) { m_BackgroundColor = color; } - Vec2f GetCursorWorldPos(const Vec2f& cursorPos, float aspectRatio, float zoom, float windowWidth, float windowHeight); + Vec2f GetCursorWorldPos(const Vec2f& cursorPos, float windowWidth, float windowHeight); private: - void UpdateIsometricView(); - void UpdateIsometricFade(); void InitShaders(); }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 38869e5..58633d9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -12,6 +12,9 @@ #include "misc/Easing.h" #include "misc/Maths.h" +#include +#include + namespace td { namespace render { @@ -23,14 +26,6 @@ Renderer::~Renderer() { } -void Renderer::UpdateIsometricView() { - //float isometricEased = utils::EaseInOutExpo(m_IsometricShade); - m_WorldShader->Start(); - //m_WorldShader->SetIsometricView(isometricEased); - m_EntityShader->Start(); - //m_EntityShader->SetIsometricView(isometricEased); -} - void Renderer::InitShaders() { m_WorldShader = std::make_unique(); m_WorldShader->LoadShader(); @@ -75,34 +70,18 @@ void Renderer::RenderModel(const Model& model) { model.vao->Unbind(); } -void Renderer::UpdateIsometricFade() { - static std::uint64_t lastTime = utils::GetTime(); - if (m_IsometricShade != static_cast(m_IsometricView)) { - float step = static_cast(utils::GetTime() - lastTime) / 1000.0f * m_AnimationSpeed; - if (m_IsometricShade < m_IsometricView) { - m_IsometricShade += step; - } else { - m_IsometricShade -= step; - } - m_IsometricShade = std::min(m_IsometricShade, 1.0f); - m_IsometricShade = std::max(m_IsometricShade, 0.0f); - UpdateIsometricView(); - } - lastTime = utils::GetTime(); -} - void Renderer::Prepare() { glClear(GL_COLOR_BUFFER_BIT); glClearColor(m_BackgroundColor.r, m_BackgroundColor.g, m_BackgroundColor.b, 0); - UpdateIsometricFade(); } void Renderer::Resize(int width, int height) { - Mat4f projectionMatrix = maths::Perspective(80.0f / 180.0f * M_PI, static_cast(width) / height, 0.1f, 160.0f); + m_Camera.projectionMatrix = maths::Perspective(80.0f / 180.0f * M_PI, static_cast(width) / height, 0.1f, 160.0f); + m_Camera.InvProjectionMatrix = maths::Inverse(m_Camera.projectionMatrix); m_WorldShader->Start(); - m_WorldShader->SetProjectionMatrix(projectionMatrix); + m_WorldShader->SetProjectionMatrix(m_Camera.projectionMatrix); m_EntityShader->Start(); - m_WorldShader->SetProjectionMatrix(projectionMatrix); + m_WorldShader->SetProjectionMatrix(m_Camera.projectionMatrix); glViewport(0, 0, width, height); } @@ -114,37 +93,39 @@ void Renderer::SetZoom(float zoom) { } void Renderer::SetCamMovement(const Vec2f& mov) { - m_CamPos.x += mov.x; - m_CamPos.y += -mov.y; - SetCamPos(m_CamPos); + m_Camera.CamPos.x += mov.x; + m_Camera.CamPos.y += -mov.y; + SetCamPos(m_Camera.CamPos); } -void Renderer::SetCamPos(const Vec2f& newPos) { - m_CamPos = newPos; - Mat4f viewMatrix = maths::Look({m_CamPos.x, 50, m_CamPos.y}, {0, -1, -0.0001}, {0, 1, 0}); +void Renderer::SetCamPos(const Vec3f& newPos) { + m_Camera.CamPos = newPos; + m_Camera.viewMatrix = maths::Look(m_Camera.CamPos, {0, -1, -0.0001}, {0, 1, 0}); + m_Camera.InvViewMatrix = maths::Inverse(m_Camera.viewMatrix); m_WorldShader->Start(); - m_WorldShader->SetViewMatrix(viewMatrix); + m_WorldShader->SetViewMatrix(m_Camera.viewMatrix); m_EntityShader->Start(); - m_EntityShader->SetViewMatrix(viewMatrix); + m_EntityShader->SetViewMatrix(m_Camera.viewMatrix); } -void Renderer::SetIsometricView(bool isometric) { - m_IsometricView = isometric; -} +Vec2f Renderer::GetCursorWorldPos(const Vec2f& cursorPos, float windowWidth, float windowHeight) { -Vec2f Renderer::GetCursorWorldPos(const Vec2f& cursorPos, float aspectRatio, float zoom, float windowWidth, float windowHeight) { - float isometricEased = utils::EaseInOutExpo(m_IsometricShade); + float relativeX = 1 - (cursorPos.x / windowWidth * 2); + float relativeY = 1 - (cursorPos.y / windowHeight * 2); - float relativeX = (cursorPos.x / windowWidth * 2) - 1; - float relativeY = (cursorPos.y / windowHeight * 2) - 1; + Vec4f rayClip {relativeX, relativeY, -1.0f, 1.0f}; - float deltaX = relativeX * aspectRatio / zoom; - float deltaY = relativeY / zoom; + Vec4f rayEye = maths::Dot(m_Camera.InvProjectionMatrix , rayClip); + rayEye = {rayEye.x, rayEye.y, -1.0f, 0.0f}; - float worldX = m_CamPos.x + deltaX * (1 - isometricEased) + (0.5 * deltaX + deltaY) * isometricEased; - float worldY = m_CamPos.y + deltaY * (1 - isometricEased) + (-0.5 * deltaX + deltaY) * isometricEased; + Vec4f rayWorld = maths::Dot(m_Camera.InvViewMatrix, rayEye); + rayWorld.w = 0; + + maths::Normalize(rayWorld); - return { worldX, worldY }; + float lambda = - m_Camera.CamPos.y / rayWorld.y; + + return {lambda * rayWorld.x + m_Camera.CamPos.x, lambda * rayWorld.z + m_Camera.CamPos.z}; } diff --git a/src/render/WorldRenderer.cpp b/src/render/WorldRenderer.cpp index 2293b97..a26acd5 100644 --- a/src/render/WorldRenderer.cpp +++ b/src/render/WorldRenderer.cpp @@ -169,7 +169,7 @@ void WorldRenderer::Click() { void WorldRenderer::SetCamPos(float camX, float camY) { m_CamPos = { camX, camY }; - m_Renderer->SetCamPos(m_CamPos); + m_Renderer->SetCamPos({ camX, 50, camY }); } void WorldRenderer::DetectClick() { @@ -232,11 +232,11 @@ void WorldRenderer::OnTowerRemove(game::TowerPtr tower) { Vec2f WorldRenderer::GetCursorWorldPos() const { ImGuiIO& io = ImGui::GetIO(); - return m_Renderer->GetCursorWorldPos({ io.MousePos.x, io.MousePos.y }, Display::GetAspectRatio(), m_Zoom, Display::GetWindowWidth(), Display::GetWindowHeight()); + return m_Renderer->GetCursorWorldPos({ io.MousePos.x, io.MousePos.y }, Display::GetWindowWidth(), Display::GetWindowHeight()); } Vec2f WorldRenderer::GetClickWorldPos() const { - return m_Renderer->GetCursorWorldPos(m_LastClicked, Display::GetAspectRatio(), m_Zoom, Display::GetWindowWidth(), Display::GetWindowHeight()); + return m_Renderer->GetCursorWorldPos(m_LastClicked, Display::GetWindowWidth(), Display::GetWindowHeight()); } } // namespace render diff --git a/src/render/gui/FrameMenu.cpp b/src/render/gui/FrameMenu.cpp index 49a6057..eb433bc 100644 --- a/src/render/gui/FrameMenu.cpp +++ b/src/render/gui/FrameMenu.cpp @@ -18,9 +18,6 @@ void FrameMenu::Render() { if (ImGui::Checkbox("V-Sync", &m_VSync)) { SDL_GL_SetSwapInterval(m_VSync); } - if (ImGui::Checkbox("Vue Isometrique ?", &m_IsometricView)) { - GetClient()->GetRenderer()->SetIsometricView(m_IsometricView); - } #if !defined(NDEBUG) ImGui::Checkbox("Demo Window", &m_ShowDemoWindow);