📄 flow.cpp
字号:
// check all portals for flowing into other leafs
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
pnum = p - portals;
if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
{
continue; // can't possibly see it
}
// if the portal can't see anything we haven't allready seen, skip it
if (p->status == stat_done)
{
test = (long *)p->portalvis;
}
else
{
test = (long *)p->portalflood;
}
more = 0;
for (j=0 ; j<portallongs ; j++)
{
might[j] = ((long *)prevstack->mightsee)[j] & test[j];
more |= (might[j] & ~vis[j]);
}
if ( !more && CheckBit( thread->base->portalvis, pnum ) )
{ // can't see anything new
continue;
}
// get plane of portal, point normal into the neighbor leaf
stack.portalplane = p->plane;
VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
backplane.dist = -p->plane.dist;
stack.portal = p;
stack.next = NULL;
stack.freewindings[0] = 1;
stack.freewindings[1] = 1;
stack.freewindings[2] = 1;
float d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
d -= thread->pstack_head.portalplane.dist;
if (d < -p->radius)
{
continue;
}
else if (d > p->radius)
{
stack.pass = p->winding;
}
else
{
stack.pass = ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
if (!stack.pass)
continue;
}
d = DotProduct (thread->base->origin, p->plane.normal);
d -= p->plane.dist;
if (d > thread->base->radius)
{
continue;
}
else if (d < -thread->base->radius)
{
stack.source = prevstack->source;
}
else
{
stack.source = ChopWinding (prevstack->source, &stack, &backplane);
if (!stack.source)
continue;
}
if (!prevstack->pass)
{ // the second leaf can only be blocked if coplanar
// mark the portal as visible
SetBit( thread->base->portalvis, pnum );
RecursiveLeafFlow (p->leaf, thread, &stack);
continue;
}
stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, false, &stack);
if (!stack.pass)
continue;
stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, true, &stack);
if (!stack.pass)
continue;
// mark the portal as visible
SetBit( thread->base->portalvis, pnum );
// flow through it for real
RecursiveLeafFlow (p->leaf, thread, &stack);
}
}
/*
===============
PortalFlow
generates the portalvis bit vector
===============
*/
void PortalFlow (int iThread, int portalnum)
{
threaddata_t data;
int i;
portal_t *p;
int c_might, c_can;
p = sorted_portals[portalnum];
p->status = stat_working;
c_might = CountBits (p->portalflood, g_numportals*2);
memset (&data, 0, sizeof(data));
data.base = p;
data.pstack_head.portal = p;
data.pstack_head.source = p->winding;
data.pstack_head.portalplane = p->plane;
for (i=0 ; i<portallongs ; i++)
((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
p->status = stat_done;
c_can = CountBits (p->portalvis, g_numportals*2);
qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n",
(int)(p - portals), c_might, c_can, data.c_chains);
}
/*
===============================================================================
This is a rough first-order aproximation that is used to trivially reject some
of the final calculations.
Calculates portalfront and portalflood bit vectors
thinking about:
typedef struct passage_s
{
struct passage_s *next;
struct portal_s *to;
stryct sep_s *seperators;
byte *mightsee;
} passage_t;
typedef struct portal_s
{
struct passage_s *passages;
int leaf; // leaf portal faces into
} portal_s;
leaf = portal->leaf
clear
for all portals
calc portal visibility
clear bit vector
for all passages
passage visibility
for a portal to be visible to a passage, it must be on the front of
all separating planes, and both portals must be behind the mew portal
===============================================================================
*/
int c_flood, c_vis;
/*
==================
SimpleFlood
==================
*/
void SimpleFlood (portal_t *srcportal, int leafnum)
{
int i;
leaf_t *leaf;
portal_t *p;
int pnum;
leaf = &leafs[leafnum];
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
pnum = p - portals;
if ( !CheckBit( srcportal->portalfront, pnum ) )
continue;
if ( CheckBit( srcportal->portalflood, pnum ) )
continue;
SetBit( srcportal->portalflood, pnum );
SimpleFlood (srcportal, p->leaf);
}
}
/*
==============
BasePortalVis
==============
*/
void BasePortalVis (int iThread, int portalnum)
{
int j, k;
portal_t *tp, *p;
float d;
winding_t *w;
Vector segment;
double dist2, minDist2;
// get the portal
p = portals+portalnum;
//
// allocate memory for bitwise vis solutions for this portal
//
p->portalfront = (byte*)malloc (portalbytes);
memset (p->portalfront, 0, portalbytes);
p->portalflood = (byte*)malloc (portalbytes);
memset (p->portalflood, 0, portalbytes);
p->portalvis = (byte*)malloc (portalbytes);
memset (p->portalvis, 0, portalbytes);
//
// test the given portal against all of the portals in the map
//
for (j=0, tp = portals ; j<g_numportals*2 ; j++, tp++)
{
// don't test against itself
if (j == portalnum)
continue;
//
//
//
w = tp->winding;
for (k=0 ; k<w->numpoints ; k++)
{
d = DotProduct (w->points[k], p->plane.normal) - p->plane.dist;
if (d > ON_VIS_EPSILON)
break;
}
if (k == w->numpoints)
continue; // no points on front
//
//
//
w = p->winding;
for (k=0 ; k<w->numpoints ; k++)
{
d = DotProduct (w->points[k], tp->plane.normal) - tp->plane.dist;
if (d < -ON_VIS_EPSILON)
break;
}
if (k == w->numpoints)
continue; // no points on front
//
// if using radius visibility -- check to see if any portal points lie inside of the
// radius given
//
if( g_bUseRadius )
{
w = tp->winding;
minDist2 = 1024000000.0; // 32000^2
for( k = 0; k < w->numpoints; k++ )
{
VectorSubtract( w->points[k], p->origin, segment );
dist2 = ( segment[0] * segment[0] ) + ( segment[1] * segment[1] ) + ( segment[2] * segment[2] );
if( dist2 < minDist2 )
{
minDist2 = dist2;
}
}
if( minDist2 > g_VisRadius )
continue;
}
// add current portal to given portal's list of visible portals
SetBit( p->portalfront, j );
}
SimpleFlood (p, p->leaf);
p->nummightsee = CountBits (p->portalflood, g_numportals*2);
// Msg ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
c_flood += p->nummightsee;
}
/*
===============================================================================
This is a second order aproximation
Calculates portalvis bit vector
WAAAAAAY too slow.
===============================================================================
*/
/*
==================
RecursiveLeafBitFlow
==================
*/
void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
{
portal_t *p;
leaf_t *leaf;
int i, j;
long more;
int pnum;
byte newmight[MAX_PORTALS/8];
leaf = &leafs[leafnum];
// check all portals for flowing into other leafs
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
pnum = p - portals;
// if some previous portal can't see it, skip
if ( !CheckBit( mightsee, pnum ) )
continue;
// if this portal can see some portals we mightsee, recurse
more = 0;
for (j=0 ; j<portallongs ; j++)
{
((long *)newmight)[j] = ((long *)mightsee)[j]
& ((long *)p->portalflood)[j];
more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
}
if (!more)
continue; // can't see anything new
SetBit( cansee, pnum );
RecursiveLeafBitFlow (p->leaf, newmight, cansee);
}
}
/*
==============
BetterPortalVis
==============
*/
void BetterPortalVis (int portalnum)
{
portal_t *p;
p = portals+portalnum;
RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
// build leaf vis information
p->nummightsee = CountBits (p->portalvis, g_numportals*2);
c_vis += p->nummightsee;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -