diff --git a/bsputil/bsputil.cc b/bsputil/bsputil.cc index 71166ff2..a7af2a58 100644 --- a/bsputil/bsputil.cc +++ b/bsputil/bsputil.cc @@ -471,7 +471,7 @@ int main(int argc, char **argv) printf( "usage: bsputil [--replace-entities] [--extract-entities] [--extract-textures] [--convert bsp29|bsp2|bsp2rmq|q2bsp] [--check] [--modelinfo]\n" "[--check] [--compare otherbsp] [--findfaces x y z nx ny nz] [--settexinfo facenum texinfonum]\n" - "[--decompile] [--decompile-geomonly] bspfile\n"); + "[--decompile] [--decompile-geomonly] [--decompile-hull n] bspfile\n"); exit(1); } @@ -618,10 +618,18 @@ int main(int argc, char **argv) WriteBSPFile(source, &bspdata); return 0; - } else if (!strcmp(argv[i], "--decompile") || !strcmp(argv[i], "--decompile-geomonly") || - !strcmp(argv[i], "--decompile-ignore-brushes")) { + } else if (!strcmp(argv[i], "--decompile") + || !strcmp(argv[i], "--decompile-geomonly") + || !strcmp(argv[i], "--decompile-ignore-brushes") + || !strcmp(argv[i], "--decompile-hull")) { const bool geomOnly = !strcmp(argv[i], "--decompile-geomonly"); const bool ignoreBrushes = !strcmp(argv[i], "--decompile-ignore-brushes"); + const bool hull = !strcmp(argv[i], "--decompile-hull"); + + int hullnum = 0; + if (hull) { + hullnum = std::stoi(argv[i + 1]); + } source.replace_extension(""); source.replace_filename(source.stem().string() + "-decompile"); @@ -636,6 +644,7 @@ int main(int argc, char **argv) decomp_options options; options.geometryOnly = geomOnly; options.ignoreBrushes = ignoreBrushes; + options.hullnum = hullnum; DecompileBSP(&bsp, options, f); diff --git a/bsputil/decompile.cpp b/bsputil/decompile.cpp index 3356df77..ada255d1 100644 --- a/bsputil/decompile.cpp +++ b/bsputil/decompile.cpp @@ -983,7 +983,7 @@ static void DecompileClipNode(std::vector &planestack, const mbs } static void AddMapBoundsToStack( - std::vector &planestack, const mbsp_t *bsp, const bsp2_dnode_t *headnode) + std::vector &planestack, const mbsp_t *bsp, const aabb3d &bounds) { for (int i = 0; i < 3; ++i) { for (int sign = 0; sign < 2; ++sign) { @@ -994,9 +994,9 @@ static void AddMapBoundsToStack( double dist; if (sign == 0) { // positive - dist = headnode->maxs[i]; + dist = bounds.maxs()[i]; } else { - dist = -headnode->mins[i]; + dist = -bounds.mins()[i]; } // we want outward-facing planes @@ -1101,7 +1101,21 @@ static void DecompileEntity( // If we have brush info, we'll use that directly // TODO: support BSPX brushes too - if (bsp->loadversion->game->id == GAME_QUAKE_II && !options.ignoreBrushes) { + if (options.hullnum > 0) { + // recursively visit the clipnodes to gather up a list of clipnode leafs to decompile + + std::vector stack; + std::vector tasks; + AddMapBoundsToStack(stack, bsp, aabb3d(qvec3d(model->mins), qvec3d(model->maxs))); + + DecompileClipNode(stack, bsp, &bsp->dclipnodes[model->headnode[options.hullnum]], tasks); + + // decompile the leafs in parallel + compiledBrushes.resize(tasks.size()); + tbb::parallel_for(static_cast(0), tasks.size(), [&](const size_t &i) { + compiledBrushes[i] = DecompileLeafTaskGeometryOnly(bsp, tasks[i], brush_offset); + }); + } else if (bsp->loadversion->game->id == GAME_QUAKE_II && !options.ignoreBrushes) { std::unordered_map brushes; auto handle_leaf = [&brushes, bsp, model](const mleaf_t *leaf) { @@ -1159,10 +1173,9 @@ static void DecompileEntity( std::vector stack; std::vector tasks; - AddMapBoundsToStack(stack, bsp, headnode); + AddMapBoundsToStack(stack, bsp, aabb3d(qvec3d(headnode->mins), qvec3d(headnode->maxs))); DecompileNode(stack, bsp, headnode, tasks); - //DecompileClipNode(stack, bsp, &bsp->dclipnodes[model->headnode[1]], tasks); // decompile the leafs in parallel compiledBrushes.resize(tasks.size()); diff --git a/bsputil/decompile.h b/bsputil/decompile.h index 777df663..66cf7b17 100644 --- a/bsputil/decompile.h +++ b/bsputil/decompile.h @@ -19,6 +19,8 @@ struct decomp_options * Intended for visualizing leafs. */ bool ignoreBrushes = false; + + int hullnum = 0; }; void DecompileBSP(const mbsp_t *bsp, const decomp_options &options, std::ofstream &file);