Fix portal disappearance when teleporting

This commit is contained in:
tovjemam 2025-08-14 22:23:18 +02:00
parent d0ecf09b06
commit 0e948660ff
3 changed files with 31 additions and 16 deletions

View File

@ -100,6 +100,7 @@ void game::Entity::Move(glm::vec3& velocity, float dt)
if (sd < 0.0f) if (sd < 0.0f)
{ {
std::swap(occu_, other_occu_); // Swap occurrences std::swap(occu_, other_occu_); // Swap occurrences
touching_portal_ = touching_portal_->link; // Switch to the linked portal
} }
} }

View File

@ -172,22 +172,16 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta
return; // Eye is behind the portal plane, skip return; // Eye is behind the portal plane, skip
} }
collision::AABB2 portal_aabb;
if (!ComputePortalScreenAABB(portal, params.view_proj, portal_aabb))
{
return; // Portal is fully behind the camera, skip
}
if (!portal_aabb.CollidesWith(params.screen_aabb))
{
return; // Portal AABB does not intersect with the screen AABB, skip
}
const game::Portal& other_portal = *portal.link; const game::Portal& other_portal = *portal.link;
const game::Sector& other_sector = *other_portal.sector;
glm::mat4 portal_mesh_trans = portal.trans; glm::mat4 portal_mesh_trans = portal.trans;
glm::vec4 new_clip_plane = other_portal.plane; 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_) if (eye_plane_sd < min_portal_distance_)
{ {
@ -197,8 +191,28 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta
glm::vec3(0.0f, how_much_shift, 0.0f)); // Shift portal mesh to avoid clipping 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 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 (!ComputeQuadScreenAABB(portal_verts, params.view_proj, portal_aabb))
{
return; // Portal is fully behind the camera, skip
}
if (!portal_aabb.CollidesWith(params.screen_aabb))
{
return; // Portal AABB does not intersect with the screen AABB, skip
}
const game::Sector& other_sector = *other_portal.sector;
// Open portal // Open portal
glStencilFunc(GL_EQUAL, params.recursion, 0xFF); glStencilFunc(GL_EQUAL, params.recursion, 0xFF);
@ -236,14 +250,14 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 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; size_t num_behind = 0;
glm::vec4 clip[4]; glm::vec4 clip[4];
for (size_t i = 0; i < 4; ++i) 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; clip[i] = view_proj * vert;
if (clip[i].w <= 0.0f) if (clip[i].w <= 0.0f)

View File

@ -53,7 +53,7 @@ namespace gfx
void DrawSector(const DrawSectorParams& params); void DrawSector(const DrawSectorParams& params);
void DrawPortal(const DrawSectorParams& params, const game::Portal& portal); 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); void DrawPortalPlane(const DrawSectorParams& params, const game::Portal& portal, const glm::mat4& trans, bool clear_depth);
}; };