From 8cdb9ff6c4e00b8d681feb7419c43e05f94a33fa Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 9 Sep 2021 05:11:47 -0400 Subject: [PATCH] Initial attempt at leafbrushes --- common/bspfile.cc | 20 +++++++++-------- include/qbsp/map.hh | 4 ++++ include/qbsp/qbsp.hh | 2 ++ qbsp/qbsp.cc | 53 ++++++++++++++++++++++++++++++++++++++++++++ qbsp/writebsp.cc | 17 ++++++++++---- 5 files changed, 83 insertions(+), 13 deletions(-) diff --git a/common/bspfile.cc b/common/bspfile.cc index 97d68797..59393bb5 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -1072,15 +1072,17 @@ void Q2_Qbism_SwapBSPFile (q2bsp_qbism_t *bsp, qboolean todisk) // // visibility // - if (todisk) - j = bsp->dvis->numclusters; - else - j = LittleLong(bsp->dvis->numclusters); - bsp->dvis->numclusters = LittleLong (bsp->dvis->numclusters); - for (i=0 ; idvis->bitofs[i][0] = LittleLong (bsp->dvis->bitofs[i][0]); - bsp->dvis->bitofs[i][1] = LittleLong (bsp->dvis->bitofs[i][1]); + if (bsp->dvis) { + if (todisk) + j = bsp->dvis->numclusters; + else + j = LittleLong(bsp->dvis->numclusters); + bsp->dvis->numclusters = LittleLong (bsp->dvis->numclusters); + for (i=0 ; idvis->bitofs[i][0] = LittleLong (bsp->dvis->bitofs[i][0]); + bsp->dvis->bitofs[i][1] = LittleLong (bsp->dvis->bitofs[i][1]); + } } } diff --git a/include/qbsp/map.hh b/include/qbsp/map.hh index 9d2e6a91..8c87c4ec 100644 --- a/include/qbsp/map.hh +++ b/include/qbsp/map.hh @@ -167,6 +167,10 @@ typedef struct mapdata_s { std::vector exported_surfedges; std::vector exported_faces; std::vector exported_models; + std::vector exported_leafbrushes; + std::vector exported_brushsides; + std::vector exported_brushes; + std::string exported_entities; std::string exported_texdata; diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 50df411b..cce8327a 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -219,6 +219,8 @@ typedef struct node_s { int occupied; // 0=can't reach entity, 1 = has entity, >1 = distance from leaf with entity mapentity_t *occupant; // example occupant, for leak hunting bool detail_separator; // for vis portal generation. true if ALL faces on node, and on all descendant nodes/leafs, are detail. + uint32_t firstleafbrush; // Q2 + uint32_t numleafbrushes; bool opaque() const; } node_t; diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index c737f6f0..1b831e84 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -38,6 +39,54 @@ bool node_t::opaque() const { return contents.is_structural_sky_or_solid(options.target_version->game); } +static void ExportBrushList_r(const mapentity_t *entity, node_t *node) +{ + if (node->planenum == PLANENUM_LEAF) + { + if (node->visleafnum == -1) { + node->firstleafbrush = map.exported_leafbrushes.size(); + node->numleafbrushes = 0; + + int32_t b_id = 0; + + for (const brush_t *b = entity->brushes; b; b = b->next, b_id++) + { + if (aabb3f(qvec3f(node->mins[0], node->mins[1], node->mins[2]), qvec3f(node->maxs[0], node->maxs[1], node->maxs[2])).intersectWith( + aabb3f(qvec3f(b->mins[0], b->mins[1], b->mins[2]), qvec3f(b->maxs[0], b->maxs[1], b->maxs[2]))).valid) { + map.exported_leafbrushes.push_back(b_id); + node->numleafbrushes++; + } + } + } + + return; + } + + ExportBrushList_r(entity, node->children[0]); + ExportBrushList_r(entity, node->children[1]); +} + +static void ExportBrushList(const mapentity_t *entity, node_t *node) +{ + for (const brush_t *b = entity->brushes; b; b = b->next) + { + dbrush_t brush { (int32_t) map.exported_brushsides.size(), 0, b->contents.native }; + + for (const face_t *f = b->faces; f; f = f->next) + { + if (map.planes[f->planenum].outputplanenum == -1) { + continue; + } + map.exported_brushsides.push_back({ (uint32_t) map.planes[f->planenum].outputplanenum, map.mtexinfos[f->texinfo].outputnum.value_or(-1) }); + brush.numsides++; + } + + map.exported_brushes.push_back(brush); + } + + ExportBrushList_r(entity, node); +} + /* =============== ProcessEntity @@ -249,6 +298,10 @@ ProcessEntity(mapentity_t *entity, const int hullnum) firstface = MakeFaceEdges(entity, nodes); ExportDrawNodes(entity, nodes, firstface); + + if (options.target_version->game->id == GAME_QUAKE_II) { + ExportBrushList(entity, nodes); + } } FreeBrushes(entity); diff --git a/qbsp/writebsp.cc b/qbsp/writebsp.cc index 2b7e8b26..cae36c9d 100644 --- a/qbsp/writebsp.cc +++ b/qbsp/writebsp.cc @@ -226,8 +226,10 @@ ExportLeaf(mapentity_t *entity, node_t *node) static_cast(map.exported_marksurfaces.size()) - dleaf->firstmarksurface; // FIXME-Q2: fill in other things - dleaf->area = 0; + dleaf->area = 1; dleaf->cluster = node->viscluster; + dleaf->firstleafbrush = node->firstleafbrush; + dleaf->numleafbrushes = node->numleafbrushes; } /* @@ -443,6 +445,9 @@ WriteBSPFile() CopyVector(map.exported_surfedges, &bspdata.data.mbsp.numsurfedges, &bspdata.data.mbsp.dsurfedges); CopyVector(map.exported_edges, &bspdata.data.mbsp.numedges, &bspdata.data.mbsp.dedges); CopyVector(map.exported_models, &bspdata.data.mbsp.nummodels, &bspdata.data.mbsp.dmodels); + CopyVector(map.exported_leafbrushes, &bspdata.data.mbsp.numleafbrushes, &bspdata.data.mbsp.dleafbrushes); + CopyVector(map.exported_brushsides, &bspdata.data.mbsp.numbrushsides, &bspdata.data.mbsp.dbrushsides); + CopyVector(map.exported_brushes, &bspdata.data.mbsp.numbrushes, &bspdata.data.mbsp.dbrushes); CopyString(map.exported_entities, true, &bspdata.data.mbsp.entdatasize, (void**)&bspdata.data.mbsp.dentdata); CopyString(map.exported_texdata, false, &bspdata.data.mbsp.texdatasize, (void**)&bspdata.data.mbsp.dtexdata); @@ -454,9 +459,13 @@ WriteBSPFile() BSPX_AddLump(&bspdata, "BRUSHLIST", map.exported_bspxbrushes.data(), map.exported_bspxbrushes.size()); } - bspdata.data.mbsp.numareas = 1; - bspdata.data.mbsp.dareas = (darea_t *) malloc(sizeof(darea_t)); - bspdata.data.mbsp.dareas->firstareaportal = bspdata.data.mbsp.dareas->numareaportals = 0; + // FIXME: temp + bspdata.data.mbsp.numareaportals = 1; + bspdata.data.mbsp.dareaportals = (dareaportal_t *) calloc(bspdata.data.mbsp.numareaportals, sizeof(dareaportal_t)); + + bspdata.data.mbsp.numareas = 2; + bspdata.data.mbsp.dareas = (darea_t *) calloc(bspdata.data.mbsp.numareas, sizeof(darea_t)); + bspdata.data.mbsp.dareas[1].firstareaportal = 1; if (!ConvertBSPFormat(&bspdata, options.target_version)) { const bspversion_t* highLimitsFormat = nullptr;