Skip to content

Commit

Permalink
Merge pull request OpenEnroth#1850 from yoctozepto/fix/1831
Browse files Browse the repository at this point in the history
Fix minimap construction
  • Loading branch information
pskelton authored Oct 30, 2024
2 parents 7c8bd75 + aba3d53 commit 6d68c8c
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 59 deletions.
71 changes: 32 additions & 39 deletions src/Engine/Graphics/BspRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ void BspRenderer::AddFaceToRenderList_d3d(int node_id, int uFaceID) {
int pTransitionSector; // ax@11
// int dotdist; // edx@15

nodes[num_nodes].viewing_portal_id = -1;

if (uFaceID >= pIndoor->pFaces.size()) return;
if (uFaceID >= pIndoor->pFaces.size())
return;
BLVFace *pFace = &pIndoor->pFaces[uFaceID];

if (!pFace->isPortal()) {
Expand All @@ -31,49 +30,26 @@ void BspRenderer::AddFaceToRenderList_d3d(int node_id, int uFaceID) {

// portals are invisible faces marking the transition between sectors
// dont add the face we are looking through
if (nodes[node_id].uFaceID == uFaceID) return;

// if node_id 0 and bounding box check with portal - ie party stood next to portal
int boundingslack = 128;

if (!node_id &&
pFace->pBounding.intersectsCube(Vec3f(pCamera3D->vCameraPos.x, pCamera3D->vCameraPos.y, pCamera3D->vCameraPos.z), boundingslack)) {
// we are standing at the portal plane
pTransitionSector = pFace->uSectorID;
// draw back sector if we are already doing this sector
if (nodes[0].uSectorID == pTransitionSector)
pTransitionSector = pFace->uBackSectorID;
nodes[num_nodes].uSectorID = pTransitionSector;
nodes[num_nodes].uFaceID = uFaceID;

// set furstum to cam frustum
for (int loop = 0; loop < 4; loop++) {
nodes[num_nodes].ViewportNodeFrustum[loop].normal.x = pCamera3D->FrustumPlanes[loop].x;
nodes[num_nodes].ViewportNodeFrustum[loop].normal.y = pCamera3D->FrustumPlanes[loop].y;
nodes[num_nodes].ViewportNodeFrustum[loop].normal.z = pCamera3D->FrustumPlanes[loop].z;
nodes[num_nodes].ViewportNodeFrustum[loop].dist = -pCamera3D->FrustumPlanes[loop].w;
}

AddBspNodeToRenderList(++num_nodes - 1);
if (nodes[node_id].uFaceID == uFaceID)
return;
}

// check if portal is visible on screen

static RenderVertexSoft static_subAddFaceToRenderList_d3d_stru_F7AA08[64];
static RenderVertexSoft static_subAddFaceToRenderList_d3d_stru_F79E08[64];
static RenderVertexSoft originalFaceVertices[64];
static RenderVertexSoft clippedFaceVertices[64];

for (unsigned k = 0; k < pFace->uNumVertices; ++k) {
static_subAddFaceToRenderList_d3d_stru_F7AA08[k].vWorldPosition.x = pIndoor->pVertices[pFace->pVertexIDs[k]].x;
static_subAddFaceToRenderList_d3d_stru_F7AA08[k].vWorldPosition.y = pIndoor->pVertices[pFace->pVertexIDs[k]].y;
static_subAddFaceToRenderList_d3d_stru_F7AA08[k].vWorldPosition.z = pIndoor->pVertices[pFace->pVertexIDs[k]].z;
originalFaceVertices[k].vWorldPosition.x = pIndoor->pVertices[pFace->pVertexIDs[k]].x;
originalFaceVertices[k].vWorldPosition.y = pIndoor->pVertices[pFace->pVertexIDs[k]].y;
originalFaceVertices[k].vWorldPosition.z = pIndoor->pVertices[pFace->pVertexIDs[k]].z;
}

unsigned int pNewNumVertices = pFace->uNumVertices;

// accurate clip to current viewing nodes frustum
bool vertadj = pCamera3D->ClipFaceToFrustum(
static_subAddFaceToRenderList_d3d_stru_F7AA08, &pNewNumVertices,
static_subAddFaceToRenderList_d3d_stru_F79E08,
originalFaceVertices, &pNewNumVertices,
clippedFaceVertices,
nodes[node_id].ViewportNodeFrustum.data(), 4, 0, 0);

if (pNewNumVertices) {
Expand All @@ -86,7 +62,7 @@ void BspRenderer::AddFaceToRenderList_d3d(int node_id, int uFaceID) {

// calculates the portal bounding and frustum
bool bFrustumbuilt = CalcPortalShapePoly(
pFace, static_subAddFaceToRenderList_d3d_stru_F79E08,
pFace, clippedFaceVertices,
&pNewNumVertices, nodes[num_nodes].ViewportNodeFrustum.data(),
nodes[num_nodes].pPortalBounding.data());

Expand All @@ -99,6 +75,12 @@ void BspRenderer::AddFaceToRenderList_d3d(int node_id, int uFaceID) {
};

// avoid circular loops in portals
// a loop is triggered in "Mercenary Guild", see issue #417
// NOTE(yoctozepto): based on other code, we should avoid having the same sector id in two nodes as this
// causes faces to be added twice, yet simplifying this statement causes rendering issues
// in some places, notably the upper, open corridor in "Temple of Light" because it offers
// several ways (portals) to "look" at faces and some might be more limited in sight than others;
// see PR #1850 and issue #1704 for the discussion and save file
for (int test = 0; test < num_nodes; test++) {
if (nodes[test].uSectorID == nodes[num_nodes].uSectorID &&
nodes[test].uFaceID == nodes[num_nodes].uFaceID &&
Expand All @@ -108,9 +90,21 @@ void BspRenderer::AddFaceToRenderList_d3d(int node_id, int uFaceID) {
}

if (bFrustumbuilt) {
const int boundingslack = 128;

// NOTE(yoctozepto): when the party is standing near (in a `boundingslack`) a portal of the same node (`id == 0`), then we need to fix the frustum
// because it is likely to clip the view too much and miss to render the faces behind it
if (node_id == 0 &&
pFace->pBounding.intersectsCube(Vec3f(pCamera3D->vCameraPos.x, pCamera3D->vCameraPos.y, pCamera3D->vCameraPos.z), boundingslack)) {
for (int loop = 0; loop < 4; loop++) {
nodes[num_nodes].ViewportNodeFrustum[loop].normal.x = pCamera3D->FrustumPlanes[loop].x;
nodes[num_nodes].ViewportNodeFrustum[loop].normal.y = pCamera3D->FrustumPlanes[loop].y;
nodes[num_nodes].ViewportNodeFrustum[loop].normal.z = pCamera3D->FrustumPlanes[loop].z;
nodes[num_nodes].ViewportNodeFrustum[loop].dist = -pCamera3D->FrustumPlanes[loop].w;
}
}

// add portal sector to drawing list
assert(num_nodes < 150);
nodes[num_nodes].viewing_portal_id = uFaceID;
AddBspNodeToRenderList(++num_nodes - 1);
}
}
Expand Down Expand Up @@ -163,7 +157,6 @@ void PrepareBspRenderList_BLV() {

// blank viewing node
pBspRenderer->nodes[0].uFaceID = -1;
pBspRenderer->nodes[0].viewing_portal_id = -1;
pBspRenderer->num_nodes = 1;
AddBspNodeToRenderList(0);
}
Expand Down
3 changes: 1 addition & 2 deletions src/Engine/Graphics/BspRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

struct BspRenderer_ViewportNode {
int uSectorID = 0; // sector that this node shows
int uFaceID = 0;
int viewing_portal_id = 0; // face id of the portal through which we're seeing this node
int uFaceID = 0; // face id of the portal through which we're seeing this node
std::array<Planef, 4> ViewportNodeFrustum = {{}}; // frustum planes of portal
std::array<RenderVertexSoft, 4> pPortalBounding = {{}}; // extents of portal
};
Expand Down
22 changes: 10 additions & 12 deletions src/Engine/Graphics/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,12 @@ bool Camera3D::CullFaceToCameraFrustum(RenderVertexSoft *pInVertices,
bool Camera3D::CullFaceToFrustum(RenderVertexSoft *a1, unsigned int *pOutNumVertices,
RenderVertexSoft *pVertices, Planef *frustum,
signed int NumFrustumPlanes) {
if (NumFrustumPlanes <= 0) return false;
if (*pOutNumVertices <= 0) return false;
if (frustum == NULL) return true;
if (NumFrustumPlanes <= 0)
return false;
if (*pOutNumVertices <= 0)
return false;
if (frustum == NULL)
return true;

bool inside = false;
for (int p = 0; p < NumFrustumPlanes; p++) {
Expand All @@ -373,19 +376,14 @@ bool Camera3D::CullFaceToFrustum(RenderVertexSoft *a1, unsigned int *pOutNumVert
if (inside == false) break;
}

if (inside == false) {
*pOutNumVertices = 0;
return false;
} else {
if (inside) {
// copy in vcerts
memcpy(pVertices, a1, sizeof(RenderVertexSoft) * *pOutNumVertices);
// return true
return true;
} else {
*pOutNumVertices = 0;
}

assert(false);

return false;
return inside;
}

bool Camera3D::ClipFaceToFrustum(RenderVertexSoft *pInVertices,
Expand Down
10 changes: 4 additions & 6 deletions src/Engine/Graphics/Renderer/OpenGLRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4079,6 +4079,7 @@ void OpenGLRenderer::DrawIndoorFaces() {
if (uFaceID >= pIndoor->pFaces.size())
continue;
BLVFace *face = &pIndoor->pFaces[uFaceID];
face->uAttributes |= FACE_SeenByParty;

if (face->isPortal()) {
continue;
Expand All @@ -4105,8 +4106,8 @@ void OpenGLRenderer::DrawIndoorFaces() {
static RenderVertexSoft static_vertices_buff_in[64]; // buff in
static RenderVertexSoft static_vertices_calc_out[64]; // buff out - calc portal shape

// moved face to camera check to avoid missing minimap outlines
if (/*pCamera3D->is_face_faced_to_cameraBLV(face) ||*/ true) {
// check face is towards camera
if (pCamera3D->is_face_faced_to_cameraBLV(face)) {
uNumVerticesa = face->uNumVertices;

// copy to buff in
Expand Down Expand Up @@ -4135,10 +4136,7 @@ void OpenGLRenderer::DrawIndoorFaces() {

// check if this face is visible through current portal node
if (pCamera3D->CullFaceToFrustum(static_vertices_buff_in, &uNumVerticesa, static_vertices_calc_out, portalfrustumnorm, 4)) {
face->uAttributes |= FACE_SeenByParty;

// check face is towards camera
if (pCamera3D->is_face_faced_to_cameraBLV(face)) {
if (true) {
++pBLVRenderParams->uNumFacesRenderedThisFrame;
// load up verts here
int texlayer = 0;
Expand Down

0 comments on commit 6d68c8c

Please sign in to comment.