From 0e948660ff8c4ade59baf134bc754e02c2a08524 Mon Sep 17 00:00:00 2001 From: tovjemam Date: Thu, 14 Aug 2025 22:23:18 +0200 Subject: [PATCH] Fix portal disappearance when teleporting --- src/game/entity.cpp | 1 + src/gfx/renderer.cpp | 44 +++++++++++++++++++++++++++++--------------- src/gfx/renderer.hpp | 2 +- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/game/entity.cpp b/src/game/entity.cpp index 2973ba2..6a16b00 100644 --- a/src/game/entity.cpp +++ b/src/game/entity.cpp @@ -100,6 +100,7 @@ void game::Entity::Move(glm::vec3& velocity, float dt) if (sd < 0.0f) { std::swap(occu_, other_occu_); // Swap occurrences + touching_portal_ = touching_portal_->link; // Switch to the linked portal } } diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 36974d6..a66b9f9 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -172,8 +172,34 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta return; // Eye is behind the portal plane, skip } + const game::Portal& other_portal = *portal.link; + + glm::mat4 portal_mesh_trans = portal.trans; + glm::vec4 new_clip_plane = other_portal.plane; + glm::vec3 portal_verts[4] = { + portal.verts[0], + portal.verts[1], + portal.verts[2], + portal.verts[3] + }; + + if (eye_plane_sd < min_portal_distance_) + { + float how_much_shift = min_portal_distance_ - eye_plane_sd; + + portal_mesh_trans = glm::translate(portal_mesh_trans, + glm::vec3(0.0f, how_much_shift, 0.0f)); // Shift portal mesh to avoid clipping + + new_clip_plane.w += how_much_shift; // Shift the clip plane as well + + for (size_t i = 0; i < 4; ++i) + { + portal_verts[i] -= glm::vec3(portal.plane) * how_much_shift; // Shift portal vertices + } + } + collision::AABB2 portal_aabb; - if (!ComputePortalScreenAABB(portal, params.view_proj, portal_aabb)) + if (!ComputeQuadScreenAABB(portal_verts, params.view_proj, portal_aabb)) { return; // Portal is fully behind the camera, skip } @@ -183,21 +209,9 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta return; // Portal AABB does not intersect with the screen AABB, skip } - const game::Portal& other_portal = *portal.link; const game::Sector& other_sector = *other_portal.sector; - glm::mat4 portal_mesh_trans = portal.trans; - glm::vec4 new_clip_plane = other_portal.plane; - if (eye_plane_sd < min_portal_distance_) - { - float how_much_shift = min_portal_distance_ - eye_plane_sd; - - portal_mesh_trans = glm::translate(portal_mesh_trans, - glm::vec3(0.0f, how_much_shift, 0.0f)); // Shift portal mesh to avoid clipping - - new_clip_plane.w += how_much_shift; // Shift the clip plane as well - } // Open portal @@ -236,14 +250,14 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } -bool gfx::Renderer::ComputePortalScreenAABB(const game::Portal& portal, const glm::mat4 view_proj, collision::AABB2& aabb) +bool gfx::Renderer::ComputeQuadScreenAABB(const glm::vec3* verts, const glm::mat4 view_proj, collision::AABB2& aabb) { size_t num_behind = 0; glm::vec4 clip[4]; for (size_t i = 0; i < 4; ++i) { - glm::vec4 vert = glm::vec4(portal.verts[i], 1.0f); + glm::vec4 vert = glm::vec4(verts[i], 1.0f); clip[i] = view_proj * vert; if (clip[i].w <= 0.0f) diff --git a/src/gfx/renderer.hpp b/src/gfx/renderer.hpp index 97582c8..5c13b2b 100644 --- a/src/gfx/renderer.hpp +++ b/src/gfx/renderer.hpp @@ -53,7 +53,7 @@ namespace gfx void DrawSector(const DrawSectorParams& params); void DrawPortal(const DrawSectorParams& params, const game::Portal& portal); - static bool ComputePortalScreenAABB(const game::Portal& portal, const glm::mat4 view_proj, collision::AABB2& aabb); + static bool ComputeQuadScreenAABB(const glm::vec3* verts, const glm::mat4 view_proj, collision::AABB2& aabb); void DrawPortalPlane(const DrawSectorParams& params, const game::Portal& portal, const glm::mat4& trans, bool clear_depth); };