[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.
This commit is contained in:
Bill Currie 2023-08-15 17:20:45 +09:00
parent c46e15af9b
commit 4028590240
5 changed files with 136 additions and 8 deletions

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -414,6 +414,8 @@ ProcessFile (void)
extract_entities ();
if (options.extract_hull)
extract_hull ();
if (options.extract_model)
extract_model ();
BSP_Free (bsp);
return;
}

View file

@ -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");
}
//@}