From ca0fbba4bf2b105a9254c5da304b72880b161157 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 18 Sep 2021 00:02:32 -0600 Subject: [PATCH 1/2] qbsp: write correct .prt file for Q2 (PRT1 with clusters) --- qbsp/portals.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/qbsp/portals.cc b/qbsp/portals.cc index 31ef1947..14f42dbb 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -252,6 +252,17 @@ static void WritePortalfile(node_t *headnode, portal_state_t *state) if (!portalFile) Error("Failed to open %s: %s", options.szBSPName, strerror(errno)); + // q2 uses a PRT1 file, but with clusters. + // (Since q2bsp natively supports clusters, we don't need PRT2.) + if (options.target_game->id == GAME_QUAKE_II) { + fprintf(portalFile, "PRT1\n"); + fprintf(portalFile, "%d\n", state->num_visclusters); + fprintf(portalFile, "%d\n", state->num_visportals); + WritePortals_r(headnode, portalFile, true); + fclose(portalFile); + return; + } + /* If no detail clusters, just use a normal PRT1 format */ if (!state->uses_detail) { fprintf(portalFile, "PRT1\n"); From 195921a91612c92112ad44678a7780e06f56c8ce Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 18 Sep 2021 00:04:33 -0600 Subject: [PATCH 2/2] vis: various fixes for vising q2 maps --- vis/vis.cc | 67 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/vis/vis.cc b/vis/vis.cc index 88f868d0..f1036683 100644 --- a/vis/vis.cc +++ b/vis/vis.cc @@ -16,8 +16,8 @@ */ int numportals; int portalleafs; /* leafs (PRT1) or clusters (PRT2) */ -int portalleafs_real; /* real no. of leafs after expanding PRT2 clusters */ -int *clustermap; /* mapping from real leaf to cluster number */ +int portalleafs_real; /* real no. of leafs after expanding PRT2 clusters. Not used for Q2. */ +int *clustermap; /* mapping from real leaf to cluster number. Not used for Q2. */ portal_t *portals; leaf_t *leafs; @@ -39,7 +39,7 @@ uint8_t *uncompressed_q2; // [leafbytes*portalleafs] int leafbytes; // (portalleafs+63)>>3 int leaflongs; -int leafbytes_real; // (portalleafs_real+63)>>3 +int leafbytes_real; // (portalleafs_real+63)>>3, not used for Q2. /* Options - TODO: collect these in a struct */ qboolean fastvis; @@ -658,9 +658,14 @@ static void ClusterFlow(int clusternum, leafbits_t *buffer, const mbsp_t *bsp) * increment totalvis by * (# of real leafs in this cluster) x (# of real leafs visible from this cluster) */ - for (i = 0; i < portalleafs_real; i++) { - if (clustermap[i] == clusternum) { - totalvis += numvis; + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + // FIXME: not sure what this is supposed to be? + totalvis += numvis; + } else { + for (i = 0; i < portalleafs_real; i++) { + if (clustermap[i] == clusternum) { + totalvis += numvis; + } } } @@ -683,9 +688,9 @@ static void ClusterFlow(int clusternum, leafbits_t *buffer, const mbsp_t *bsp) leaf->visofs = dest - vismap; // Set pointers - for (i = 0; i < portalleafs_real; i++) { - if (bsp->dleafs[i + 1].cluster == clusternum) { - bsp->dleafs[i + 1].visofs = leaf->visofs; + for (i = 1; i < bsp->numleafs; i++) { + if (bsp->dleafs[i].cluster == clusternum) { + bsp->dleafs[i].visofs = leaf->visofs; } } @@ -752,7 +757,10 @@ void CalcVis(const mbsp_t *bsp) // // assemble the leaf vis lists by oring and compressing the portal lists // - if (portalleafs == portalleafs_real) { + if (portalleafs == portalleafs_real && bsp->loadversion->game->id != GAME_QUAKE_II) { + // Legacy, non-detail Q1 vis codepath + // FIXME: Should be possible to remove this and just use ClusterFlow even on Q1 maps + // with no detail. for (i = 0; i < portalleafs; i++) LeafFlow(i, &bsp->dleafs[i + 1], bsp); } else { @@ -766,9 +774,16 @@ void CalcVis(const mbsp_t *bsp) } int64_t avg = totalvis; - avg /= static_cast(portalleafs_real); - logprint("average leafs visible: %i\n", static_cast(avg)); + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + avg /= static_cast(portalleafs); + + logprint("average clusters visible: %i\n", static_cast(avg)); + } else { + avg /= static_cast(portalleafs_real); + + logprint("average leafs visible: %i\n", static_cast(avg)); + } } /* @@ -1026,8 +1041,8 @@ void LoadPortals(char *name, mbsp_t *bsp) Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE); if (bsp->loadversion->game->id == GAME_QUAKE_II) { - portalleafs_real = bsp->numleafs; - logprint("%6d leafs\n", portalleafs_real); + // since q2bsp has native cluster support, we shouldn't look at portalleafs_real at all. + portalleafs_real = 0; logprint("%6d clusters\n", portalleafs); logprint("%6d portals\n", numportals); } else { @@ -1039,6 +1054,9 @@ void LoadPortals(char *name, mbsp_t *bsp) count = fscanf(f, "%i\n%i\n%i\n", &portalleafs_real, &portalleafs, &numportals); if (count != 3) Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE); + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + Error("%s: %s can not be used with Q2\n", __func__, PORTALFILE2); + } logprint("%6d leafs\n", portalleafs_real); logprint("%6d clusters\n", portalleafs); logprint("%6d portals\n", numportals); @@ -1046,6 +1064,9 @@ void LoadPortals(char *name, mbsp_t *bsp) count = fscanf(f, "%i\n%i\n%i\n", &portalleafs, &numportals, &portalleafs_real); if (count != 3) Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE); + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + Error("%s: %s can not be used with Q2\n", __func__, PORTALFILEAM); + } logprint("%6d leafs\n", portalleafs_real); logprint("%6d clusters\n", portalleafs); logprint("%6d portals\n", numportals); @@ -1055,7 +1076,12 @@ void LoadPortals(char *name, mbsp_t *bsp) leafbytes = ((portalleafs + 63) & ~63) >> 3; leaflongs = leafbytes / sizeof(long); - leafbytes_real = ((portalleafs_real + 63) & ~63) >> 3; + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + // not used in Q2 + leafbytes_real = 0; + } else { + leafbytes_real = ((portalleafs_real + 63) & ~63) >> 3; + } // each file portal is split into two memory portals portals = new portal_t[numportals * 2] { }; @@ -1138,13 +1164,10 @@ void LoadPortals(char *name, mbsp_t *bsp) } /* Load the cluster expansion map if needed */ - /*if (bsp->loadversion->game->id == GAME_QUAKE_II) { - clustermap = new int[bsp->numleafs]; - - for (int32_t i = 0; i < bsp->numleafs; i++) { - clustermap[i] = bsp->dleafs[i + 1].cluster; - } - } else */if (portalleafs != portalleafs_real) { + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + // not used + clustermap = nullptr; + } else if (portalleafs != portalleafs_real) { clustermap = new int[portalleafs_real]; if (!strcmp(magic, PORTALFILE2)) { for (i = 0; i < portalleafs; i++) {