From f35fd7287e6ed63ebc244d7f356d391c2962f41e Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Fri, 10 Feb 2023 18:01:12 +0100 Subject: [PATCH] Made an attempt at detecting T-junctions in geometry and correcting the vertices for that. It sort of works but it doesn't have the desired effect yet. Back to the drawing board. --- bsp.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.cpp | 13 ++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/bsp.h b/bsp.h index 7c6a8f2..50d106c 100644 --- a/bsp.h +++ b/bsp.h @@ -383,4 +383,62 @@ typedef struct World return outFaces; } + std::vector findTjunctions(const Vec3& point) const + { + std::vector outTangents; + for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx) + { + const face_t* face = &faces[faceIdx]; + const plane_t* plane = &planes[face->plane_id]; + + // Check if the point lies on the face's plane (it's not strictly necessary to do this, but this check makes the whole function a lot faster) + if (fabs(plane->pointDistance(point)) > 0.01) + continue; + + Vec3 faceNormal = face->side ? -plane->normal : plane->normal; + + // Check if the point is located on one of the face's edges + for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx) + { + int edgeIdx = edgeList[face->ledge_id + edgeListIdx]; + + Vec3 v0, v1; + if (edgeIdx > 0) + { + const edge_t* edge = &edges[edgeIdx]; + v0 = vertices[edge->vertex0].toVec(); + v1 = vertices[edge->vertex1].toVec(); + } + else + { + const edge_t* edge = &edges[-edgeIdx]; + v0 = vertices[edge->vertex1].toVec(); + v1 = vertices[edge->vertex0].toVec(); + } + + Vec3 p0 = v0 - point; + Vec3 p1 = v1 - point; + double m0 = p0.magnitude(); + double m1 = p1.magnitude(); + + if ((m0 * m1) <= 0.01) + { + // Point is on one of the face's vertices, this is not a T-junction + break; + } + + double dot = p0.dotProduct(p1) / (m0 * m1); + if (dot <= -0.99) + { + // Point is on one of the face's edges, in-between its two vertices. This is a T-junction. + Vec3 edgeDir = (v1 - v0).normalized(); + Vec3 tangent = faceNormal.crossProduct(edgeDir); + outTangents.push_back(tangent); + } + } + } + + return outTangents; + } + } world_t; diff --git a/main.cpp b/main.cpp index 2debcd4..de6545d 100644 --- a/main.cpp +++ b/main.cpp @@ -273,7 +273,18 @@ int process_faces(const world_t* world, const TextureList& textures) std::vector outVertices; for (auto vertIter = inVertices.begin(); vertIter != inVertices.end(); ++vertIter) { - const Vec3& inVertex = *vertIter; + Vec3 inVertex = *vertIter; + + // Detect T-junctions and try to close the gaps a bit + auto edgeTangents = world->findTjunctions(inVertex); + if (edgeTangents.size() > 0) + { + for (auto edgeIter = edgeTangents.begin(); edgeIter != edgeTangents.end(); ++edgeIter) + { + // Move the vertex slightly into the adjacent face + //inVertex = inVertex + (*edgeIter) * (1.0f / WORLDSCALE); + } + } ps1bsp_vertex_t outVertex = { 0 }; // Ensure we don't overflow 16-bit short values. Most Quake maps will stay within these bounds so it *should* be fine (for now).