vis: use leafbits_t struct and helpers to represent vis bit strings
Importing parts of this from TyrQuake - means that the base type used for managing the bit vectors is unsigned long. Not really a performance win or anything here, just a bit nicer to not have to cast from (byte *) to (long *) - just adds a little extra work before writing out the compressed data. Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
parent
498286faa1
commit
815fd70265
|
|
@ -0,0 +1,69 @@
|
|||
/* Copyright (C) 2012-2013 Kevin Shanahan
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
See file, 'COPYING', for details.
|
||||
*/
|
||||
|
||||
#ifndef VIS_LEAFBITS_H
|
||||
#define VIS_LEAFBITS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Use some GCC builtins */
|
||||
#ifndef ffsl
|
||||
#define ffsl __builtin_ffsl
|
||||
#endif
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
#endif
|
||||
|
||||
typedef unsigned long leafblock_t;
|
||||
typedef struct {
|
||||
int numleafs;
|
||||
leafblock_t bits[]; /* Variable Sized */
|
||||
} leafbits_t;
|
||||
|
||||
int __ERRORLONGSIZE(void); /* to generate an error at link time */
|
||||
#define QBYTESHIFT(x) ((x) == 8 ? 6 : ((x) == 4 ? 5 : __ERRORLONGSIZE() ))
|
||||
#define LEAFSHIFT QBYTESHIFT(sizeof(leafblock_t))
|
||||
#define LEAFMASK ((sizeof(leafblock_t) << 3) - 1UL)
|
||||
|
||||
static inline int
|
||||
TestLeafBit(const leafbits_t *bits, int leafnum)
|
||||
{
|
||||
return !!(bits->bits[leafnum >> LEAFSHIFT] & (1UL << (leafnum & LEAFMASK)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
SetLeafBit(leafbits_t *bits, int leafnum)
|
||||
{
|
||||
bits->bits[leafnum >> LEAFSHIFT] |= 1UL << (leafnum & LEAFMASK);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ClearLeafBit(leafbits_t *bits, int leafnum)
|
||||
{
|
||||
bits->bits[leafnum >> LEAFSHIFT] &= ~(1UL << (leafnum & LEAFMASK));
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
LeafbitsSize(int numleafs)
|
||||
{
|
||||
return offsetof(leafbits_t, bits[(numleafs + LEAFMASK) >> LEAFSHIFT]);
|
||||
}
|
||||
|
||||
#endif /* VIS_LEAFBITS_H */
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
#include <common/cmdlib.h>
|
||||
#include <common/mathlib.h>
|
||||
#include <common/bspfile.h>
|
||||
#include <vis/leafbits.h>
|
||||
|
||||
#define PORTALFILE "PRT1"
|
||||
#define ON_EPSILON 0.1
|
||||
|
|
@ -41,7 +42,6 @@ typedef struct {
|
|||
vec3_t points[MAX_WINDING_FIXED]; // variable sized
|
||||
} winding_t;
|
||||
|
||||
|
||||
winding_t *NewWinding(int points);
|
||||
winding_t *CopyWinding(winding_t * w);
|
||||
void PlaneFromWinding(const winding_t * w, plane_t *plane);
|
||||
|
|
@ -54,8 +54,8 @@ typedef struct {
|
|||
int leaf; // neighbor
|
||||
winding_t *winding;
|
||||
pstatus_t status;
|
||||
byte *visbits;
|
||||
byte *mightsee;
|
||||
leafbits_t *visbits;
|
||||
leafbits_t *mightsee;
|
||||
int nummightsee;
|
||||
int numcansee;
|
||||
} portal_t;
|
||||
|
|
@ -90,7 +90,7 @@ typedef struct pstack_s {
|
|||
winding_t windings[STACK_WINDINGS]; // Fixed size windings
|
||||
int freewindings[STACK_WINDINGS];
|
||||
plane_t portalplane;
|
||||
byte *mightsee; // bit string
|
||||
leafbits_t *mightsee; // bit string
|
||||
plane_t separators[2][MAX_SEPARATORS]; /* Separator cache */
|
||||
int numseparators[2];
|
||||
} pstack_t;
|
||||
|
|
@ -102,7 +102,7 @@ winding_t *ClipStackWinding(winding_t *in, pstack_t *stack, plane_t *split);
|
|||
int c_noclip;
|
||||
|
||||
typedef struct {
|
||||
byte *leafvis; // bit string
|
||||
leafbits_t *leafvis;
|
||||
portal_t *base;
|
||||
pstack_t pstack_head;
|
||||
} threaddata_t;
|
||||
|
|
|
|||
41
vis/flow.c
41
vis/flow.c
|
|
@ -1,5 +1,6 @@
|
|||
#include <common/threads.h>
|
||||
#include <vis/vis.h>
|
||||
#include <vis/leafbits.h>
|
||||
|
||||
unsigned long c_chains;
|
||||
int c_vistest, c_mighttest;
|
||||
|
|
@ -15,8 +16,8 @@ CheckStack(leaf_t *leaf, threaddata_t *thread)
|
|||
for (p = thread->pstack_head.next; p; p = p->next)
|
||||
if (p->leaf == leaf)
|
||||
Error("%s: leaf recursion", __func__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
|
|
@ -156,8 +157,8 @@ RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t *prevstack)
|
|||
portal_t *p;
|
||||
plane_t backplane;
|
||||
leaf_t *leaf;
|
||||
int i, j;
|
||||
long *test, *might, *vis, more;
|
||||
int i, j, numblocks;
|
||||
leafblock_t *test, *might, *vis, more;
|
||||
|
||||
++c_chains;
|
||||
|
||||
|
|
@ -165,8 +166,8 @@ RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t *prevstack)
|
|||
CheckStack(leaf, thread);
|
||||
|
||||
// mark the leaf as visible
|
||||
if (!(thread->leafvis[leafnum >> 3] & (1 << (leafnum & 7)))) {
|
||||
thread->leafvis[leafnum >> 3] |= 1 << (leafnum & 7);
|
||||
if (!TestLeafBit(thread->leafvis, leafnum)) {
|
||||
SetLeafBit(thread->leafvis, leafnum);
|
||||
thread->base->numcansee++;
|
||||
}
|
||||
|
||||
|
|
@ -181,29 +182,31 @@ RecursiveLeafFlow(int leafnum, threaddata_t *thread, pstack_t *prevstack)
|
|||
for (i = 0; i < STACK_WINDINGS; i++)
|
||||
stack.freewindings[i] = 1;
|
||||
|
||||
stack.mightsee = malloc(leafbytes);
|
||||
might = (long *)stack.mightsee;
|
||||
vis = (long *)thread->leafvis;
|
||||
stack.mightsee = malloc(LeafbitsSize(portalleafs));
|
||||
might = stack.mightsee->bits;
|
||||
vis = thread->leafvis->bits;
|
||||
|
||||
// check all portals for flowing into other leafs
|
||||
for (i = 0; i < leaf->numportals; i++) {
|
||||
p = leaf->portals[i];
|
||||
|
||||
if (!(prevstack->mightsee[p->leaf >> 3] & (1 << (p->leaf & 7)))) {
|
||||
if (!TestLeafBit(prevstack->mightsee, p->leaf)) {
|
||||
c_leafskip++;
|
||||
continue; // can't possibly see it
|
||||
}
|
||||
// if the portal can't see anything we haven't allready seen, skip it
|
||||
if (p->status == pstat_done) {
|
||||
c_vistest++;
|
||||
test = (long *)p->visbits;
|
||||
test = p->visbits->bits;
|
||||
} else {
|
||||
c_mighttest++;
|
||||
test = (long *)p->mightsee;
|
||||
test = p->mightsee->bits;
|
||||
}
|
||||
|
||||
more = 0;
|
||||
for (j = 0; j < leaflongs; j++) {
|
||||
might[j] = ((long *)prevstack->mightsee)[j] & test[j];
|
||||
numblocks = (portalleafs + LEAFMASK) >> LEAFSHIFT;
|
||||
for (j = 0; j < numblocks; j++) {
|
||||
might[j] = prevstack->mightsee->bits[j] & test[j];
|
||||
more |= (might[j] & ~vis[j]);
|
||||
}
|
||||
|
||||
|
|
@ -358,8 +361,8 @@ PortalFlow(portal_t *p)
|
|||
if (p->status != pstat_working)
|
||||
Error("%s: reflowed", __func__);
|
||||
|
||||
p->visbits = malloc(leafbytes);
|
||||
memset(p->visbits, 0, leafbytes);
|
||||
p->visbits = malloc(LeafbitsSize(portalleafs));
|
||||
memset(p->visbits, 0, LeafbitsSize(portalleafs));
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.leafvis = p->visbits;
|
||||
|
|
@ -388,10 +391,10 @@ SimpleFlood(portal_t *srcportal, int leafnum, byte *portalsee)
|
|||
leaf_t *leaf;
|
||||
portal_t *p;
|
||||
|
||||
if (srcportal->mightsee[leafnum >> 3] & (1 << (leafnum & 7)))
|
||||
if (TestLeafBit(srcportal->mightsee, leafnum))
|
||||
return;
|
||||
|
||||
srcportal->mightsee[leafnum >> 3] |= (1 << (leafnum & 7));
|
||||
SetLeafBit(srcportal->mightsee, leafnum);
|
||||
srcportal->nummightsee++;
|
||||
|
||||
leaf = &leafs[leafnum];
|
||||
|
|
@ -433,8 +436,8 @@ BasePortalThread(void *dummy)
|
|||
//printf("\r%i of %i: %i%%", i, numportals * 2, 50 * i / numportals);
|
||||
//fflush(stdout);
|
||||
|
||||
p->mightsee = malloc(leafbytes);
|
||||
memset(p->mightsee, 0, leafbytes);
|
||||
p->mightsee = malloc(LeafbitsSize(portalleafs));
|
||||
memset(p->mightsee, 0, LeafbitsSize(portalleafs));
|
||||
|
||||
memset(portalsee, 0, numportals * 2);
|
||||
|
||||
|
|
|
|||
96
vis/vis.c
96
vis/vis.c
|
|
@ -3,6 +3,7 @@
|
|||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <vis/leafbits.h>
|
||||
#include <vis/vis.h>
|
||||
#include <common/log.h>
|
||||
#include <common/threads.h>
|
||||
|
|
@ -380,8 +381,8 @@ UpdateMightsee(const leaf_t *source, const leaf_t *dest)
|
|||
p = source->portals[i];
|
||||
if (p->status != pstat_none)
|
||||
continue;
|
||||
if (p->mightsee[leafnum >> 3] & (1 << (leafnum & 7))) {
|
||||
p->mightsee[leafnum >> 3] &= ~(1 << (leafnum & 7));
|
||||
if (TestLeafBit(p->mightsee, leafnum)) {
|
||||
ClearLeafBit(p->mightsee, leafnum);
|
||||
p->nummightsee--;
|
||||
c_mightseeupdate++;
|
||||
}
|
||||
|
|
@ -402,13 +403,12 @@ UpdateMightsee(const leaf_t *source, const leaf_t *dest)
|
|||
static void
|
||||
PortalCompleted(portal_t *completed)
|
||||
{
|
||||
int i, j, k, bit;
|
||||
int i, j, k, bit, numblocks;
|
||||
int leafnum;
|
||||
portal_t *p, *p2;
|
||||
leaf_t *myleaf;
|
||||
unsigned long *might, *vis, *check;
|
||||
unsigned long changed;
|
||||
byte *bcheck, bmask;
|
||||
const portal_t *p, *p2;
|
||||
const leaf_t *myleaf;
|
||||
const leafblock_t *might, *vis;
|
||||
leafblock_t changed;
|
||||
|
||||
ThreadLock();
|
||||
|
||||
|
|
@ -424,9 +424,10 @@ PortalCompleted(portal_t *completed)
|
|||
if (p->status != pstat_done)
|
||||
continue;
|
||||
|
||||
might = (unsigned long *)p->mightsee;
|
||||
vis = (unsigned long *)p->visbits;
|
||||
for (j = 0; j < leaflongs; j++) {
|
||||
might = p->mightsee->bits;
|
||||
vis = p->visbits->bits;
|
||||
numblocks = (portalleafs + LEAFMASK) >> LEAFSHIFT;
|
||||
for (j = 0; j < numblocks; j++) {
|
||||
changed = might[j] & ~vis[j];
|
||||
if (!changed)
|
||||
continue;
|
||||
|
|
@ -440,29 +441,21 @@ PortalCompleted(portal_t *completed)
|
|||
continue;
|
||||
p2 = myleaf->portals[k];
|
||||
if (p2->status == pstat_done)
|
||||
check = (unsigned long *)p2->visbits;
|
||||
changed &= ~p2->visbits->bits[j];
|
||||
else
|
||||
check = (unsigned long *)p2->mightsee;
|
||||
changed &= ~check[j];
|
||||
changed &= ~p2->mightsee->bits[j];
|
||||
if (!changed)
|
||||
break;
|
||||
}
|
||||
if (!changed)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Update mightsee for any of the changed bits that survived
|
||||
*/
|
||||
bcheck = (byte *)&changed;
|
||||
for (k = 0; k < sizeof(changed); k++, bcheck++) {
|
||||
if (!*bcheck)
|
||||
continue;
|
||||
for (bit = 0, bmask = 1; bit < 8; bit++, bmask <<= 1) {
|
||||
if (!(*bcheck & bmask))
|
||||
continue;
|
||||
leafnum = j * (sizeof(changed) << 3) + (k << 3) + bit;
|
||||
UpdateMightsee(leafs + leafnum, myleaf);
|
||||
}
|
||||
while (changed) {
|
||||
bit = ffsl(changed) - 1;
|
||||
changed &= ~(1UL << bit);
|
||||
leafnum = (j << LEAFSHIFT) + bit;
|
||||
UpdateMightsee(leafs + leafnum, myleaf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -507,33 +500,31 @@ LeafThread(void *unused)
|
|||
CompressRow
|
||||
===============
|
||||
*/
|
||||
int
|
||||
CompressRow(byte *vis, byte *dest)
|
||||
static int
|
||||
CompressRow(const byte *vis, byte *out)
|
||||
{
|
||||
int j;
|
||||
int rep;
|
||||
int visrow;
|
||||
byte *dest_p;
|
||||
int i, rep, numbytes;
|
||||
byte *dst;
|
||||
|
||||
dest_p = dest;
|
||||
visrow = (portalleafs + 7) >> 3;
|
||||
dst = out;
|
||||
numbytes = (portalleafs + 7) >> 3;
|
||||
|
||||
for (j = 0; j < visrow; j++) {
|
||||
*dest_p++ = vis[j];
|
||||
if (vis[j])
|
||||
for (i = 0; i < numbytes; i++) {
|
||||
*dst++ = vis[i];
|
||||
if (vis[i])
|
||||
continue;
|
||||
|
||||
rep = 1;
|
||||
for (j++; j < visrow; j++)
|
||||
if (vis[j] || rep == 255)
|
||||
for (i++; i < numbytes; i++)
|
||||
if (vis[i] || rep == 255)
|
||||
break;
|
||||
else
|
||||
rep++;
|
||||
*dest_p++ = rep;
|
||||
j--;
|
||||
*dst++ = rep;
|
||||
i--;
|
||||
}
|
||||
|
||||
return dest_p - dest;
|
||||
return dst - out;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -551,11 +542,11 @@ LeafFlow(int leafnum)
|
|||
{
|
||||
leaf_t *leaf;
|
||||
byte *outbuffer;
|
||||
byte compressed[MAX_MAP_LEAFS / 8];
|
||||
int i, j;
|
||||
byte *compressed;
|
||||
int i, j, shift;
|
||||
int numvis;
|
||||
byte *dest;
|
||||
portal_t *p;
|
||||
const portal_t *p;
|
||||
|
||||
//
|
||||
// flow through all portals, collecting visible bits
|
||||
|
|
@ -566,8 +557,11 @@ LeafFlow(int leafnum)
|
|||
p = leaf->portals[i];
|
||||
if (p->status != pstat_done)
|
||||
Error("portal not done");
|
||||
for (j = 0; j < leafbytes; j++)
|
||||
outbuffer[j] |= p->visbits[j];
|
||||
shift = 0;
|
||||
for (j = 0; j < leafbytes; j++) {
|
||||
outbuffer[j] |= (p->visbits->bits[j >> (LEAFSHIFT - 3)] >> shift) & 0xff;
|
||||
shift = (shift + 8) & LEAFMASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (outbuffer[leafnum >> 3] & (1 << (leafnum & 7)))
|
||||
|
|
@ -587,12 +581,9 @@ LeafFlow(int leafnum)
|
|||
logprint("leaf %4i : %4i visible\n", leafnum, numvis);
|
||||
totalvis += numvis;
|
||||
|
||||
#if 0
|
||||
i = (portalleafs + 7) >> 3;
|
||||
memcpy(compressed, outbuffer, i);
|
||||
#else
|
||||
/* Allocate for worst case where RLE might grow the data (unlikely) */
|
||||
compressed = malloc(portalleafs * 2 / 8);
|
||||
i = CompressRow(outbuffer, compressed);
|
||||
#endif
|
||||
|
||||
dest = vismap_p;
|
||||
vismap_p += i;
|
||||
|
|
@ -603,6 +594,7 @@ LeafFlow(int leafnum)
|
|||
dleafs[leafnum + 1].visofs = dest - vismap; // leaf 0 is a common solid
|
||||
|
||||
memcpy(dest, compressed, i);
|
||||
free(compressed);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue