vis: Try to propogate some extra vis info from completed portals

When a portal is completed, check the updated vis information for leafs
that can no longer be seen from the leaf the portal is attached to. Update
the portals on these no-longer-visible leaves to indicated that they can
no longer see our leaf.

Seems to be at least a small gain on my test maps. I suspect there is
some further improvement to be gained by taking better advantage of this
optimisation by changing out choice of portals in GetNextPortal. Couldn't
find anything trivial that worked though.

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2012-12-25 21:32:26 +10:30
parent 725da016a4
commit 2bbcdff931
2 changed files with 120 additions and 4 deletions

View File

@ -370,8 +370,6 @@ PortalFlow(portal_t * p)
data.pstack_head.mightsee = p->mightsee;
RecursiveLeafFlow(p->leaf, &data, &data.pstack_head);
p->status = pstat_done;
}

122
vis/vis.c
View File

@ -22,7 +22,7 @@ int progress;
portal_t *portals;
leaf_t *leafs;
int c_portaltest, c_portalpass, c_portalcheck;
int c_portaltest, c_portalpass, c_portalcheck, c_mightseeupdate;
int c_noclip = 0;
qboolean showgetleaf = true;
@ -370,6 +370,121 @@ GetNextPortal(void)
return ret;
}
/*
=============
UpdateMightSee
Called after completing a portal and finding that the source leaf is no
longer visible from the dest leaf. Visibility is symetrical, so the reverse
must also be true. Update mightsee for any portals on the source leaf which
haven't yet started processing.
Called with the lock held.
=============
*/
static void
UpdateMightsee(const leaf_t *source, const leaf_t *dest)
{
int i, leafnum;
portal_t *p;
leafnum = dest - leafs;
for (i = 0; i < source->numportals; i++) {
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));
p->nummightsee--;
c_mightseeupdate++;
}
}
}
/*
=============
PortalCompleted
Mark the portal completed and propogate new vis information across
to the complementry portals.
Called with the lock held.
=============
*/
static void
PortalCompleted(portal_t *completed)
{
int i, j, k, bit;
int leafnum;
portal_t *p, *p2;
leaf_t *myleaf;
unsigned long *might, *vis, *check;
unsigned long changed;
byte *bcheck, bmask;
LOCK;
completed->status = pstat_done;
/*
* For each portal on the leaf, check the leafs we eliminated from
* mightsee during the full vis so far.
*/
myleaf = &leafs[completed->leaf];
for (i = 0; i < myleaf->numportals; i++) {
p = myleaf->portals[i];
if (p->status != pstat_done)
continue;
might = (unsigned long *)p->mightsee;
vis = (unsigned long *)p->visbits;
for (j = 0; j < leaflongs; j++) {
changed = might[j] & ~vis[j];
if (!changed)
continue;
/*
* If any of these changed bits are still visible from another
* portal, we can't update yet.
*/
for (k = 0; k < myleaf->numportals; k++) {
if (k == i)
continue;
p2 = myleaf->portals[k];
if (p2->status == pstat_done)
check = (unsigned long *)p2->visbits;
else
check = (unsigned long *)p2->mightsee;
changed &= ~check[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);
}
}
}
}
UNLOCK;
}
/*
==============
LeafThread
@ -387,6 +502,8 @@ LeafThread(void *unused)
PortalFlow(p);
PortalCompleted(p);
if (verbose) {
printf("\r");
logprint("portal:%4i mightsee:%4i cansee:%4i\n",
@ -566,7 +683,8 @@ CalcPortalVis(void)
if (verbose) {
logprint("portalcheck: %i portaltest: %i portalpass: %i\n",
c_portalcheck, c_portaltest, c_portalpass);
logprint("c_vistest: %i c_mighttest: %i\n", c_vistest, c_mighttest);
logprint("c_vistest: %i c_mighttest: %i c_mightseeupdate %i\n",
c_vistest, c_mighttest, c_mightseeupdate);
}
}