vis: add detail brush / prt2 support
First pass at detail support as implemented in tyr-qbsp, using the PRT2 file format (hopefully nobody else already decided to use that?) Because the "leaf" terminology is pervasive across the source, I've left it there for now (so "leaf" usually now means "cluster") and added a few variables with the "_real" suffix when they actually mean the real leafs and not the clusters which vis still calls leafs. A bit disgusting, but it actually works so I'll go through and clean up naming, etc. later. Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
parent
3e12ff141d
commit
c0f9b19868
|
|
@ -25,6 +25,7 @@
|
||||||
#include <vis/leafbits.h>
|
#include <vis/leafbits.h>
|
||||||
|
|
||||||
#define PORTALFILE "PRT1"
|
#define PORTALFILE "PRT1"
|
||||||
|
#define PORTALFILE2 "PRT2"
|
||||||
#define ON_EPSILON 0.1
|
#define ON_EPSILON 0.1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -107,6 +108,7 @@ typedef struct {
|
||||||
|
|
||||||
extern int numportals;
|
extern int numportals;
|
||||||
extern int portalleafs;
|
extern int portalleafs;
|
||||||
|
extern int portalleafs_real;
|
||||||
|
|
||||||
extern portal_t *portals;
|
extern portal_t *portals;
|
||||||
extern leaf_t *leafs;
|
extern leaf_t *leafs;
|
||||||
|
|
@ -121,6 +123,7 @@ extern int testlevel;
|
||||||
|
|
||||||
extern byte *uncompressed;
|
extern byte *uncompressed;
|
||||||
extern int leafbytes;
|
extern int leafbytes;
|
||||||
|
extern int leafbytes_real;
|
||||||
extern int leaflongs;
|
extern int leaflongs;
|
||||||
|
|
||||||
extern char sourcefile[1024];
|
extern char sourcefile[1024];
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ CalcAmbientSounds(void)
|
||||||
float dists[NUM_AMBIENTS];
|
float dists[NUM_AMBIENTS];
|
||||||
float vol;
|
float vol;
|
||||||
|
|
||||||
for (i = 0; i < portalleafs; i++) {
|
for (i = 0; i < portalleafs_real; i++) {
|
||||||
leaf = &dleafs[i + 1];
|
leaf = &dleafs[i + 1];
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -92,9 +92,9 @@ CalcAmbientSounds(void)
|
||||||
for (j = 0; j < NUM_AMBIENTS; j++)
|
for (j = 0; j < NUM_AMBIENTS; j++)
|
||||||
dists[j] = 1020;
|
dists[j] = 1020;
|
||||||
|
|
||||||
vis = &uncompressed[i * leafbytes];
|
vis = &uncompressed[i * leafbytes_real];
|
||||||
|
|
||||||
for (j = 0; j < portalleafs; j++) {
|
for (j = 0; j < portalleafs_real; j++) {
|
||||||
if (!(vis[j >> 3] & (1 << (j & 7))))
|
if (!(vis[j >> 3] & (1 << (j & 7))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
||||||
155
vis/vis.c
155
vis/vis.c
|
|
@ -8,8 +8,15 @@
|
||||||
#include <common/log.h>
|
#include <common/log.h>
|
||||||
#include <common/threads.h>
|
#include <common/threads.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the portal file is "PRT2" format, then the leafs we are dealing with are
|
||||||
|
* really clusters of leaves. So, after the vis job is done we need to expand
|
||||||
|
* the clusters to the real leaf numbers before writing back to the bsp file.
|
||||||
|
*/
|
||||||
int numportals;
|
int numportals;
|
||||||
int portalleafs;
|
int portalleafs; /* leafs (PRT1) or clusters (PRT2) */
|
||||||
|
int portalleafs_real; /* real no. of leafs after expanding PRT2 clusters */
|
||||||
|
int *clustermap; /* mapping from real leaf to cluster number */
|
||||||
|
|
||||||
portal_t *portals;
|
portal_t *portals;
|
||||||
leaf_t *leafs;
|
leaf_t *leafs;
|
||||||
|
|
@ -25,10 +32,11 @@ static byte *vismap_end; // past visfile
|
||||||
|
|
||||||
int originalvismapsize;
|
int originalvismapsize;
|
||||||
|
|
||||||
byte *uncompressed; // [leafbytes*portalleafs]
|
byte *uncompressed; // [leafbytes_real*portalleafs_real]
|
||||||
|
|
||||||
int leafbytes; // (portalleafs+63)>>3
|
int leafbytes; // (portalleafs+63)>>3
|
||||||
int leaflongs;
|
int leaflongs;
|
||||||
|
int leafbytes_real; // (portalleafs_real+63)>>3
|
||||||
|
|
||||||
qboolean fastvis;
|
qboolean fastvis;
|
||||||
static int verbose = 0;
|
static int verbose = 0;
|
||||||
|
|
@ -604,6 +612,69 @@ LeafFlow(int leafnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ClusterFlow(int leafnum, leafbits_t *buffer)
|
||||||
|
{
|
||||||
|
leaf_t *leaf;
|
||||||
|
byte *outbuffer;
|
||||||
|
byte *compressed;
|
||||||
|
int i, j, len;
|
||||||
|
int numvis, numblocks;
|
||||||
|
byte *dest;
|
||||||
|
const portal_t *p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collect visible bits from all portals into buffer
|
||||||
|
*/
|
||||||
|
leaf = &leafs[clustermap[leafnum]];
|
||||||
|
numblocks = (portalleafs + LEAFMASK) >> LEAFSHIFT;
|
||||||
|
for (i = 0; i < leaf->numportals; i++) {
|
||||||
|
p = leaf->portals[i];
|
||||||
|
if (p->status != pstat_done)
|
||||||
|
Error("portal not done");
|
||||||
|
for (j = 0; j < numblocks; j++)
|
||||||
|
buffer->bits[j] |= p->visbits->bits[j];
|
||||||
|
}
|
||||||
|
if (TestLeafBit(buffer, clustermap[leafnum]))
|
||||||
|
logprint("WARNING: Leaf portals saw into leaf (%i)\n", leafnum);
|
||||||
|
SetLeafBit(buffer, clustermap[leafnum]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now expand the clusters into the full leaf visibility map
|
||||||
|
*/
|
||||||
|
numvis = 0;
|
||||||
|
outbuffer = uncompressed + leafnum * leafbytes_real;
|
||||||
|
for (i = 0; i < portalleafs_real; i++) {
|
||||||
|
if (TestLeafBit(buffer, clustermap[i])) {
|
||||||
|
outbuffer[i >> 3] |= (1 << (i & 7));
|
||||||
|
numvis++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compress the bit string
|
||||||
|
*/
|
||||||
|
if (verbose > 1)
|
||||||
|
logprint("leaf %4i : %4i visible\n", leafnum, numvis);
|
||||||
|
totalvis += numvis;
|
||||||
|
|
||||||
|
/* Allocate for worst case where RLE might grow the data (unlikely) */
|
||||||
|
compressed = malloc(portalleafs_real * 2 / 8);
|
||||||
|
len = CompressRow(outbuffer, (portalleafs_real + 7) >> 3, compressed);
|
||||||
|
|
||||||
|
dest = vismap_p;
|
||||||
|
vismap_p += len;
|
||||||
|
|
||||||
|
if (vismap_p > vismap_end)
|
||||||
|
Error("Vismap expansion overflow");
|
||||||
|
|
||||||
|
/* leaf 0 is a common solid */
|
||||||
|
dleafs[leafnum + 1].visofs = dest - vismap;
|
||||||
|
|
||||||
|
memcpy(dest, compressed, len);
|
||||||
|
free(compressed);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
CalcPortalVis
|
CalcPortalVis
|
||||||
|
|
@ -666,10 +737,22 @@ CalcVis(void)
|
||||||
//
|
//
|
||||||
// assemble the leaf vis lists by oring and compressing the portal lists
|
// assemble the leaf vis lists by oring and compressing the portal lists
|
||||||
//
|
//
|
||||||
for (i = 0; i < portalleafs; i++)
|
if (portalleafs == portalleafs_real) {
|
||||||
LeafFlow(i);
|
for (i = 0; i < portalleafs; i++)
|
||||||
|
LeafFlow(i);
|
||||||
|
} else {
|
||||||
|
leafbits_t *buffer;
|
||||||
|
|
||||||
logprint("average leafs visible: %i\n", totalvis / portalleafs);
|
logprint("Expanding clusters...\n");
|
||||||
|
buffer = malloc(LeafbitsSize(portalleafs));
|
||||||
|
for (i = 0; i < portalleafs_real; i++) {
|
||||||
|
memset(buffer, 0, LeafbitsSize(portalleafs));
|
||||||
|
ClusterFlow(i, buffer);
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint("average leafs visible: %i\n", totalvis / portalleafs_real);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -901,7 +984,7 @@ SetWindingSphere(winding_t *w)
|
||||||
void
|
void
|
||||||
LoadPortals(char *name)
|
LoadPortals(char *name)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j, count;
|
||||||
portal_t *p;
|
portal_t *p;
|
||||||
leaf_t *l;
|
leaf_t *l;
|
||||||
char magic[80];
|
char magic[80];
|
||||||
|
|
@ -922,16 +1005,35 @@ LoadPortals(char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fscanf(f, "%79s\n%i\n%i\n", magic, &portalleafs, &numportals) != 3)
|
/*
|
||||||
Error("%s: failed to read header", __func__);
|
* Parse the portal file header
|
||||||
if (strcmp(magic, PORTALFILE))
|
*/
|
||||||
Error("%s: not a portal file", __func__);
|
count = fscanf(f, "%79s\n", magic);
|
||||||
|
if (count != 1)
|
||||||
|
Error("%s: unknown header: %s\n", __func__, magic);
|
||||||
|
|
||||||
logprint("%4i portalleafs\n", portalleafs);
|
if (!strcmp(magic, PORTALFILE)) {
|
||||||
logprint("%4i numportals\n", numportals);
|
count = fscanf(f, "%i\n%i\n", &portalleafs, &numportals);
|
||||||
|
if (count != 2)
|
||||||
|
Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE);
|
||||||
|
portalleafs_real = portalleafs;
|
||||||
|
logprint("%6d leafs\n", portalleafs);
|
||||||
|
logprint("%6d portals\n", numportals);
|
||||||
|
} else if (!strcmp(magic, PORTALFILE2)) {
|
||||||
|
count = fscanf(f, "%i\n%i\n%i\n", &portalleafs_real, &portalleafs,
|
||||||
|
&numportals);
|
||||||
|
if (count != 3)
|
||||||
|
Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE);
|
||||||
|
logprint("%6d leafs\n", portalleafs_real);
|
||||||
|
logprint("%6d clusters\n", portalleafs);
|
||||||
|
logprint("%6d portals\n", numportals);
|
||||||
|
} else {
|
||||||
|
Error("%s: unknown header: %s\n", __func__, magic);
|
||||||
|
}
|
||||||
|
|
||||||
leafbytes = ((portalleafs + 63) & ~63) >> 3;
|
leafbytes = ((portalleafs + 63) & ~63) >> 3;
|
||||||
leaflongs = leafbytes / sizeof(long);
|
leaflongs = leafbytes / sizeof(long);
|
||||||
|
leafbytes_real = ((portalleafs_real + 63) & ~63) >> 3;
|
||||||
|
|
||||||
// each file portal is split into two memory portals
|
// each file portal is split into two memory portals
|
||||||
portals = malloc(2 * numportals * sizeof(portal_t));
|
portals = malloc(2 * numportals * sizeof(portal_t));
|
||||||
|
|
@ -940,7 +1042,7 @@ LoadPortals(char *name)
|
||||||
leafs = malloc(portalleafs * sizeof(leaf_t));
|
leafs = malloc(portalleafs * sizeof(leaf_t));
|
||||||
memset(leafs, 0, portalleafs * sizeof(leaf_t));
|
memset(leafs, 0, portalleafs * sizeof(leaf_t));
|
||||||
|
|
||||||
originalvismapsize = portalleafs * ((portalleafs + 7) / 8);
|
originalvismapsize = portalleafs_real * ((portalleafs_real + 7) / 8);
|
||||||
|
|
||||||
// FIXME - more intelligent allocation?
|
// FIXME - more intelligent allocation?
|
||||||
dvisdata = malloc(MAX_MAP_VISIBILITY);
|
dvisdata = malloc(MAX_MAP_VISIBILITY);
|
||||||
|
|
@ -1014,6 +1116,29 @@ LoadPortals(char *name)
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load the cluster expansion map if needed */
|
||||||
|
if (portalleafs != portalleafs_real) {
|
||||||
|
clustermap = malloc(portalleafs_real * sizeof(int));
|
||||||
|
for (i = 0; i < portalleafs; i++) {
|
||||||
|
while (1) {
|
||||||
|
int leafnum;
|
||||||
|
count = fscanf(f, "%i", &leafnum);
|
||||||
|
if (!count || count == EOF)
|
||||||
|
break;
|
||||||
|
if (leafnum < 0)
|
||||||
|
break;
|
||||||
|
if (leafnum >= portalleafs_real)
|
||||||
|
Error("Invalid leaf number in cluster map (%d >= %d",
|
||||||
|
leafnum, portalleafs_real);
|
||||||
|
clustermap[leafnum] = i;
|
||||||
|
}
|
||||||
|
if (count == EOF)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i < portalleafs)
|
||||||
|
Error("Couldn't read cluster map (%d / %d)\n", i, portalleafs);
|
||||||
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1104,8 +1229,8 @@ main(int argc, char **argv)
|
||||||
StripExtension(statetmpfile);
|
StripExtension(statetmpfile);
|
||||||
DefaultExtension(statetmpfile, ".vi0");
|
DefaultExtension(statetmpfile, ".vi0");
|
||||||
|
|
||||||
uncompressed = malloc(leafbytes * portalleafs);
|
uncompressed = malloc(leafbytes_real * portalleafs_real);
|
||||||
memset(uncompressed, 0, leafbytes * portalleafs);
|
memset(uncompressed, 0, leafbytes_real * portalleafs_real);
|
||||||
|
|
||||||
// CalcPassages ();
|
// CalcPassages ();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue