mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-17 06:30:44 +01:00
3de2a98db4
apparently model_t->leafs goes from 1 to model_t->numleafs, not from 0 to model_t->numleafs-1
168 lines
4.7 KiB
C
168 lines
4.7 KiB
C
#include "vk_common.h"
|
|
#include "xash3d_types.h"
|
|
#include "protocol.h"
|
|
#include "const.h"
|
|
#include "bspfile.h"
|
|
#include "mod_local.h"
|
|
|
|
#include "vk_light.h"
|
|
|
|
#define PR(...) gEngine.Con_Reportf(__VA_ARGS__)
|
|
|
|
// FIXME copied from mod_bmodel.c
|
|
// TODO would it be possible to not decompress each time, but instead get a list of all leaves?
|
|
static byte g_visdata[(MAX_MAP_LEAFS+7)/8]; // intermediate buffer
|
|
byte *Mod_DecompressPVS( const byte *in, int visbytes )
|
|
{
|
|
byte *out;
|
|
int c;
|
|
|
|
out = g_visdata;
|
|
|
|
if( !in )
|
|
{
|
|
// no vis info, so make all visible
|
|
while( visbytes )
|
|
{
|
|
*out++ = 0xff;
|
|
visbytes--;
|
|
}
|
|
return g_visdata;
|
|
}
|
|
|
|
do
|
|
{
|
|
if( *in )
|
|
{
|
|
*out++ = *in++;
|
|
continue;
|
|
}
|
|
|
|
c = in[1];
|
|
in += 2;
|
|
|
|
while( c )
|
|
{
|
|
*out++ = 0;
|
|
c--;
|
|
}
|
|
} while( out - g_visdata < visbytes );
|
|
|
|
return g_visdata;
|
|
}
|
|
|
|
|
|
static void DumpLeaves( void ) {
|
|
model_t *map = gEngine.pfnGetModelByIndex( 1 );
|
|
const world_static_t *world = gEngine.GetWorld();
|
|
ASSERT(map);
|
|
|
|
PR("visbytes=%d leafs: %d:\n", world->visbytes, map->numleafs);
|
|
for (int i = 0; i < map->numleafs; ++i) {
|
|
const mleaf_t* leaf = map->leafs + i;
|
|
PR(" %d: contents=%d numsurfaces=%d cluster=%d\n",
|
|
i, leaf->contents, leaf->nummarksurfaces, leaf->cluster);
|
|
|
|
// TODO: mark which surfaces belong to which leaves
|
|
// TODO: figure out whether this relationship is stable (surface belongs to only one leaf)
|
|
|
|
// print out PVS
|
|
{
|
|
int pvs_count = 0;
|
|
const byte *visdata = Mod_DecompressPVS(leaf->compressed_vis, world->visbytes);
|
|
if (!visdata) continue;
|
|
PR(" PVS:");
|
|
for (int j = 0; j < map->numleafs; ++j) {
|
|
if (CHECKVISBIT(visdata, map->leafs[j].cluster /* FIXME cluster (j+1) or j??!?!*/)) {
|
|
pvs_count++;
|
|
PR(" %d", j);
|
|
}
|
|
}
|
|
PR(" TOTAL: %d\n", pvs_count);
|
|
}
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
model_t *map;
|
|
const world_static_t *world;
|
|
FILE *f;
|
|
} traversal_context_t;
|
|
|
|
static void visitLeaf(const mleaf_t *leaf, const mnode_t *parent, const traversal_context_t *ctx) {
|
|
const int parent_index = parent - ctx->map->nodes;
|
|
int pvs_count = 0;
|
|
const byte *visdata = Mod_DecompressPVS(leaf->compressed_vis, ctx->world->visbytes);
|
|
int num_emissive = 0;
|
|
|
|
// ??? empty leaf?
|
|
if (leaf->cluster < 0) // || leaf->nummarksurfaces == 0)
|
|
return;
|
|
|
|
fprintf(ctx->f, "\"N%d\" -> \"L%d\"\n", parent_index, leaf->cluster);
|
|
for (int i = 0; i < leaf->nummarksurfaces; ++i) {
|
|
const msurface_t *surf = leaf->firstmarksurface[i];
|
|
const int surf_index = surf - ctx->map->surfaces;
|
|
const int texture_num = surf->texinfo->texture->gl_texturenum;
|
|
const qboolean emissive = texture_num >= 0 && g_lights.map.emissive_textures[texture_num].set;
|
|
|
|
if (emissive) num_emissive++;
|
|
|
|
fprintf(ctx->f, "L%d -> S%d [color=\"#%s\"; dir=\"none\"];\n",
|
|
leaf->cluster, surf_index, emissive ? "ff0000ff" : "00000040");
|
|
}
|
|
|
|
if (!visdata)
|
|
return;
|
|
|
|
for (int j = 0; j < ctx->map->numleafs; ++j) {
|
|
if (CHECKVISBIT(visdata, ctx->map->leafs[j].cluster)) {
|
|
pvs_count++;
|
|
}
|
|
}
|
|
|
|
fprintf(ctx->f, "\"L%d\" [label=\"Leaf cluster %d\\npvs_count: %d\\nummarksurfaces: %d\\n num_emissive: %d\"; style=filled; fillcolor=\"%s\"; ];\n",
|
|
leaf->cluster, leaf->cluster, pvs_count, leaf->nummarksurfaces, num_emissive,
|
|
num_emissive > 0 ? "red" : "transparent"
|
|
);
|
|
}
|
|
|
|
static void visitNode(const mnode_t *node, const mnode_t *parent, const traversal_context_t *ctx) {
|
|
if (node->contents < 0) {
|
|
visitLeaf((const mleaf_t*)node, parent, ctx);
|
|
} else {
|
|
const int parent_index = parent ? parent - ctx->map->nodes : -1;
|
|
const int node_index = node - ctx->map->nodes;
|
|
fprintf(ctx->f, "\"N%d\" -> \"N%d\"\n", parent_index, node_index);
|
|
fprintf(ctx->f, "\"N%d\" [label=\"numsurfaces: %d\\nfirstsurface: %d\"];\n",
|
|
node_index, node->numsurfaces, node->firstsurface);
|
|
visitNode(node->children[0], node, ctx);
|
|
visitNode(node->children[1], node, ctx);
|
|
}
|
|
}
|
|
|
|
void traverseBSP( void ) {
|
|
const traversal_context_t ctx = {
|
|
.map = gEngine.pfnGetModelByIndex( 1 ),
|
|
.world = gEngine.GetWorld(),
|
|
.f = fopen("bsp.dot", "w"),
|
|
};
|
|
|
|
fprintf(ctx.f, "digraph bsp { node [shape=box];\n");
|
|
visitNode(ctx.map->nodes, NULL, &ctx);
|
|
fprintf(ctx.f,
|
|
"subgraph surfaces {rank = max; style= filled; color = lightgray;\n");
|
|
for (int i = 0; i < ctx.map->numsurfaces; i++) {
|
|
const msurface_t *surf = ctx.map->surfaces + i;
|
|
const int texture_num = surf->texinfo->texture->gl_texturenum;
|
|
fprintf(ctx.f, "S%d [rank=\"max\"; label=\"S%d\\ntexture: %s\\nnumedges: %d\\ntexture_num=%d\"; style=filled; fillcolor=\"%s\";];\n",
|
|
i, i,
|
|
surf->texinfo && surf->texinfo->texture ? surf->texinfo->texture->name : "NULL",
|
|
surf->numedges, texture_num,
|
|
(texture_num >= 0 && g_lights.map.emissive_textures[texture_num].set) ? "red" : "transparent" );
|
|
}
|
|
fprintf(ctx.f, "}\n}\n");
|
|
fclose(ctx.f);
|
|
//exit(0);
|
|
}
|