From 9c46e7f4da478a005906c57f98d4b007fe01d54c Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 8 Jan 2023 23:51:00 -0700 Subject: [PATCH] bsputils: prototype DecompressAllVis --- common/bsputils.cc | 68 ++++++++++++++++++++++++++++++++++++++ include/common/bsputils.hh | 4 +++ 2 files changed, 72 insertions(+) diff --git a/common/bsputils.cc b/common/bsputils.cc index f4d1013b..80957b6c 100644 --- a/common/bsputils.cc +++ b/common/bsputils.cc @@ -603,6 +603,16 @@ size_t DecompressedVisSize(const mbsp_t *bsp) return (bsp->dmodels[0].visleafs + 7) / 8; } +int VisleafToLeafnum(int visleaf) +{ + return visleaf + 1; +} + +int LeafnumToVisleaf(int leafnum) +{ + return leafnum - 1; +} + // from DarkPlaces (Mod_Q1BSP_DecompressVis) void DecompressVis(const uint8_t *in, const uint8_t *inend, uint8_t *out, uint8_t *outend) { @@ -645,6 +655,64 @@ void DecompressVis(const uint8_t *in, const uint8_t *inend, uint8_t *out, uint8_ } } +/** + * Decompress visdata for the entire map, and returns a map of: + * + * - Q2: cluster number to decompressed visdata + * - Q1/others: visofs to decompressed visdata + * + * Q1 uses visofs as the map key, rather than e.g. visleaf number or leaf number, because if func_detail is in use, + * many leafs will share the same visofs. This avoids storing the same visdata redundantly. + */ +std::unordered_map> DecompressAllVis(const mbsp_t *bsp, bool trans_water) +{ + std::unordered_map> result; + + const size_t decompressed_size = DecompressedVisSize(bsp); + + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + const int num_clusters = bsp->dvis.bit_offsets.size(); + + for (int cluster = 0; cluster < num_clusters; ++cluster) { + if (bsp->dvis.get_bit_offset(VIS_PVS, cluster) >= bsp->dvis.bits.size()) { + logging::print("DecompressAllVis: invalid visofs for cluster {}\n", cluster); + continue; + } + + std::vector decompressed(decompressed_size); + DecompressVis(bsp->dvis.bits.data() + bsp->dvis.get_bit_offset(VIS_PVS, cluster), + bsp->dvis.bits.data() + bsp->dvis.bits.size(), decompressed.data(), decompressed.data() + decompressed.size()); + result[cluster] = std::move(decompressed); + } + } else { + for (int leafnum = 0; leafnum < bsp->dleafs.size(); ++leafnum) { + auto &leaf = bsp->dleafs[leafnum]; + if (leaf.visofs < 0) { + continue; + } + + const int map_key = leaf.visofs; + + if (result.find(map_key) != result.end()) { + // already decompressed this cluster + continue; + } + + if (leaf.visofs >= bsp->dvis.bits.size()) { + logging::print("DecompressAllVis: invalid visofs for leaf {}\n", leafnum); + continue; + } + + std::vector decompressed(decompressed_size); + DecompressVis(bsp->dvis.bits.data() + leaf.visofs, + bsp->dvis.bits.data() + bsp->dvis.bits.size(), decompressed.data(), decompressed.data() + decompressed.size()); + result[map_key] = std::move(decompressed); + } + } + + return result; +} + bspx_decoupled_lm_perface BSPX_DecoupledLM(const bspxentries_t &entries, int face_num) { auto &lump_bytes = entries.at("DECOUPLED_LM"); diff --git a/include/common/bsputils.hh b/include/common/bsputils.hh index c6219d59..65d5033a 100644 --- a/include/common/bsputils.hh +++ b/include/common/bsputils.hh @@ -29,6 +29,7 @@ #include #include #include +#include const dmodelh2_t *BSP_GetWorldModel(const mbsp_t *bsp); int Face_GetNum(const mbsp_t *bsp, const mface_t *f); @@ -107,7 +108,10 @@ void Face_DebugPrint(const mbsp_t *bsp, const mface_t *face); void CompressRow(const uint8_t *vis, const size_t numbytes, std::back_insert_iterator> it); size_t DecompressedVisSize(const mbsp_t *bsp); +int VisleafToLeafnum(int visleaf); +int LeafnumToVisleaf(int leafnum); void DecompressVis(const uint8_t *in, const uint8_t *inend, uint8_t *out, uint8_t *outend); +std::unordered_map> DecompressAllVis(const mbsp_t *bsp, bool trans_water = false); bspx_decoupled_lm_perface BSPX_DecoupledLM(const bspxentries_t &entries, int face_num);