From 4028590240b52d1c6f365d5bd3b95d373f03a7d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Aug 2023 17:20:45 +0900 Subject: [PATCH] [qfbsp] Add an option to extract models to C Probably not a good idea for large maps, but handy for generating C structs for small test maps. Does not include vertices or surfaces, just the bsp tree itself for now. --- tools/qfbsp/include/options.h | 1 + tools/qfbsp/include/readbsp.h | 4 ++ tools/qfbsp/source/options.c | 31 +++++++--- tools/qfbsp/source/qfbsp.c | 2 + tools/qfbsp/source/readbsp.c | 106 ++++++++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 8 deletions(-) diff --git a/tools/qfbsp/include/options.h b/tools/qfbsp/include/options.h index a260037e3..009a432f0 100644 --- a/tools/qfbsp/include/options.h +++ b/tools/qfbsp/include/options.h @@ -48,6 +48,7 @@ typedef struct { bool extract_textures; bool extract_entities; bool extract_hull; + bool extract_model; bool smart_leak; bool usehulls; bool watervis; diff --git a/tools/qfbsp/include/readbsp.h b/tools/qfbsp/include/readbsp.h index 5887a68ea..3cdb05e65 100644 --- a/tools/qfbsp/include/readbsp.h +++ b/tools/qfbsp/include/readbsp.h @@ -47,6 +47,10 @@ void extract_entities (void); */ void extract_hull (void); +/** Write a brush from the map's bsp to a C file. +*/ +void extract_model (void); + ///@} #endif//qfbsp_readbsp_h diff --git a/tools/qfbsp/source/options.c b/tools/qfbsp/source/options.c index 8b5995dce..04826d514 100644 --- a/tools/qfbsp/source/options.c +++ b/tools/qfbsp/source/options.c @@ -48,6 +48,16 @@ const char *this_program; +enum { + long_opt_base = 255, + + extract_textures, + extract_entities, + extract_hull, + extract_model, + smart_leak, +}; + static struct option const long_options[] = { {"quiet", no_argument, 0, 'q'}, {"verbose", no_argument, 0, 'v'}, @@ -60,10 +70,11 @@ static struct option const long_options[] = { {"onlyents", no_argument, 0, 'e'}, {"portal", no_argument, 0, 'p'}, {"info", no_argument, 0, 'i'}, - {"extract-textures", no_argument, 0, 256}, - {"extract-entities", no_argument, 0, 257}, - {"extract-hull", no_argument, 0, 258}, - {"smart-leak", no_argument, 0, 259}, + {"extract-textures", no_argument, 0, extract_textures}, + {"extract-entities", no_argument, 0, extract_entities}, + {"extract-hull", no_argument, 0, extract_hull}, + {"extract-model", no_argument, 0, extract_model}, + {"smart-leak", no_argument, 0, smart_leak}, {"usehulls", no_argument, 0, 'u'}, {"hullnum", required_argument, 0, 'H'}, {"subdivide", required_argument, 0, 's'}, @@ -174,19 +185,23 @@ DecodeArgs (int argc, char **argv) options.extract = true; options.portal = true; break; - case 256: // extract-textures + case extract_textures: options.extract = true; options.extract_textures = true; break; - case 257: // extract-entities + case extract_entities: options.extract = true; options.extract_entities = true; break; - case 258: // extract-hull + case extract_hull: options.extract = true; options.extract_hull = true; break; - case 259: // smart-leak + case extract_model: + options.extract = true; + options.extract_model = true; + break; + case smart_leak: options.smart_leak = true; break; case 'u': // usehulls diff --git a/tools/qfbsp/source/qfbsp.c b/tools/qfbsp/source/qfbsp.c index d23f83f2c..a52b96e33 100644 --- a/tools/qfbsp/source/qfbsp.c +++ b/tools/qfbsp/source/qfbsp.c @@ -414,6 +414,8 @@ ProcessFile (void) extract_entities (); if (options.extract_hull) extract_hull (); + if (options.extract_model) + extract_model (); BSP_Free (bsp); return; } diff --git a/tools/qfbsp/source/readbsp.c b/tools/qfbsp/source/readbsp.c index fce4e4e84..a7aa4d703 100644 --- a/tools/qfbsp/source/readbsp.c +++ b/tools/qfbsp/source/readbsp.c @@ -472,4 +472,110 @@ extract_hull (void) Qprintf (hf, "};\n"); } +static void +setparent (int32_t node_id, int32_t parent_id, + int32_t *leaf_parents, int32_t *node_parents) +{ + if (node_id < 0) { + leaf_parents[~node_id] = parent_id; + return; + } + node_parents[node_id] = parent_id; + auto node = bsp->nodes + node_id; + setparent (node->children[0], node_id, leaf_parents, node_parents); + setparent (node->children[1], node_id, leaf_parents, node_parents); +} + +void +extract_model (void) +{ +// hullfile = output_file (".c"); + const char *hullfile; + QFile *hf; + + hullfile = output_file (".c"); + if (strcmp (hullfile, "-") == 0) + hf = Qdopen (1, "wt"); + else + hf = Qopen (hullfile, "wt"); + + Qprintf (hf, "static mleaf_t leafs[] = {\n"); + // skip leaf 0 + for (uint32_t i = 1; i < bsp->numleafs; i++) { + auto leaf = bsp->leafs[i]; + Qprintf (hf, "\t[%d] = {\n", i); + Qprintf (hf, "\t\t.contents = %d,\n", leaf.contents); + Qprintf (hf, "\t\t.mins = { %g, %g, %g },\n", VectorExpand (leaf.mins)); + Qprintf (hf, "\t\t.maxs = { %g, %g, %g },\n", VectorExpand (leaf.maxs)); + //FIXME vis + Qprintf (hf, "\t},\n"); + } + Qprintf (hf, "};\n"); + Qprintf (hf, "\n"); + Qprintf (hf, "static mnode_t nodes[] = {\n"); + for (uint32_t i = 0; i < bsp->numnodes; i++) { + auto node = bsp->nodes[i]; + auto plane = bsp->planes[node.planenum]; + Qprintf (hf, "\t[%d] = {\n", i); + Qprintf (hf, "\t\t.plane = { %g, %g, %g, %g },\n", + VectorExpand (plane.normal), -plane.dist); + Qprintf (hf, "\t\t.type = %d,\n", plane.type); + Qprintf (hf, "\t\t.children = { %d, %d },\n", + node.children[0], node.children[1]); + Qprintf (hf, "\t\t.minmaxs = { %g, %g, %g,\n", + VectorExpand (node.maxs)); + Qprintf (hf, "\t\t\t\t\t %g, %g, %g },\n", VectorExpand (node.maxs)); + Qprintf (hf, "\t},\n"); + } + Qprintf (hf, "};\n"); + Qprintf (hf, "\n"); + + int32_t *leaf_parents = malloc (sizeof (int32_t[bsp->numleafs])); + int32_t *node_parents = malloc (sizeof (int32_t[bsp->numnodes])); + setparent (0, -1, leaf_parents, node_parents); + Qprintf (hf, "static int32_t leaf_parents[] = {\n"); + for (uint32_t i = 0; i < bsp->numleafs; i++) { + Qprintf (hf, "\t[%d] = %d,\n", i, leaf_parents[i]); + } + Qprintf (hf, "};\n"); + Qprintf (hf, "\n"); + Qprintf (hf, "static int32_t node_parents[] = {\n"); + for (uint32_t i = 0; i < bsp->numnodes; i++) { + Qprintf (hf, "\t[%d] = %d,\n", i, node_parents[i]); + } + Qprintf (hf, "};\n"); + Qprintf (hf, "\n"); + Qprintf (hf, "static int32_t leaf_flags[] = {\n"); + Qprintf (hf, "\t//FIXME\n"); + Qprintf (hf, "};\n"); + Qprintf (hf, "\n"); + Qprintf (hf, "static char entities[] = { 0 };\n"); + + Qprintf (hf, "\n"); + Qprintf (hf, "static model_t models[] = {\n"); + for (uint32_t i = 0; i < bsp->nummodels; i++) { + auto model = bsp->models[i]; + float r1 = sqrt (DotProduct (model.mins, model.mins)); + float r2 = sqrt (DotProduct (model.maxs, model.maxs)); + Qprintf (hf, "\t[%d] = {\n", i); + Qprintf (hf, "\t\t.type = mod_brush,\n"); + Qprintf (hf, "\t\t.radius = %g,\n", max (r1, r2)); + Qprintf (hf, "\t\t.mins = { %g, %g, %g },\n", VectorExpand(model.maxs)); + Qprintf (hf, "\t\t.maxs = { %g, %g, %g },\n", VectorExpand(model.maxs)); + Qprintf (hf, "\t\t.brush = {\n"); + Qprintf (hf, "\t\t\t.modleafs = %d,\n", model.visleafs + 1); + Qprintf (hf, "\t\t\t.visleafs = %d,\n", model.visleafs); + Qprintf (hf, "\t\t\t.numnodes = %zd,\n", bsp->numnodes); + Qprintf (hf, "\t\t\t.nodes = nodes,\n"); + Qprintf (hf, "\t\t\t.leafs = leafs,\n"); + Qprintf (hf, "\t\t\t.entities = entities,\n"); + Qprintf (hf, "\t\t\t.leaf_parents = leaf_parents,\n"); + Qprintf (hf, "\t\t\t.node_parents = node_parents,\n"); + Qprintf (hf, "\t\t\t.leaf_flags = leaf_flags,\n"); + Qprintf (hf, "\t\t},\n"); + Qprintf (hf, "\t},\n"); + } + Qprintf (hf, "};\n"); +} + //@}