Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

portals.c File Reference

#include "qbsp.h"
#include "l_mem.h"

Include dependency graph for portals.c:

Include dependency graph

Go to the source code of this file.

Defines

#define BASE_WINDING_EPSILON   0.001
#define SIDESPACE   8
#define SPLIT_WINDING_EPSILON   0.001

Functions

void AddPortalToNodes (portal_t *p, node_t *front, node_t *back)
portal_tAllocPortal (void)
winding_tBaseWindingForNode (node_t *node)
void CalcNodeBounds (node_t *node)
int ClusterContents (node_t *node)
void FillOutside (node_t *headnode)
void FillOutside_r (node_t *node)
void FindAreas_r (node_t *node)
void FindPortalSide (portal_t *p)
void FloodAreas (tree_t *tree)
void FloodAreas_r (node_t *node)
qboolean FloodEntities (tree_t *tree)
void FloodPortals (node_t *firstnode)
void FloodPortals_r (node_t *node, int dist)
void FreePortal (portal_t *p)
void MakeHeadnodePortals (tree_t *tree)
void MakeNodePortal (node_t *node)
void MakeTreePortals (tree_t *tree)
void MakeTreePortals_r (node_t *node)
void MarkVisibleSides (tree_t *tree, int startbrush, int endbrush)
void MarkVisibleSides_r (node_t *node)
void P_AddNodeToList (node_t *node)
node_tP_NextNodeFromList (void)
qboolean PlaceOccupant (node_t *headnode, vec3_t origin, entity_t *occupant)
qboolean Portal_EntityFlood (portal_t *p, int s)
qboolean Portal_VisFlood (portal_t *p)
void PrintPortal (portal_t *p)
void RemovePortalFromNode (portal_t *portal, node_t *l)
void SetAreaPortalAreas_r (node_t *node)
void SplitNodePortals (node_t *node)
int VisibleContents (int contents)
qboolean WindingIsTiny (winding_t *w)

Variables

int c_active_portals
int c_areas
int c_boundary
int c_boundary_sides
int c_inside
int c_numportalizednodes
int c_outside
int c_peak_portals
int c_portalmemory
int c_solid
int c_tinyportals
int numrec
node_tp_firstnode
node_tp_lastnode


Define Documentation

#define BASE_WINDING_EPSILON   0.001
 

Definition at line 361 of file portals.c.

Referenced by BaseWindingForNode().

#define SIDESPACE   8
 

Definition at line 293 of file portals.c.

#define SPLIT_WINDING_EPSILON   0.001
 

Definition at line 362 of file portals.c.

Referenced by SplitNodePortals().


Function Documentation

void AddPortalToNodes portal_t p,
node_t front,
node_t back
 

Definition at line 192 of file portals.c.

References Error(), portal_s::next, node_t, portal_s::nodes, p, portal_t, and node_s::portals.

00193 {
00194     if (p->nodes[0] || p->nodes[1])
00195         Error ("AddPortalToNode: allready included");
00196 
00197     p->nodes[0] = front;
00198     p->next[0] = front->portals;
00199     front->portals = p;
00200     
00201     p->nodes[1] = back;
00202     p->next[1] = back->portals;
00203     back->portals = p;
00204 } //end of the function AddPortalToNodes

Here is the call graph for this function:

portal_t* AllocPortal void   ) 
 

Definition at line 39 of file portals.c.

References c_active_portals, c_peak_portals, c_portalmemory, GetMemory(), MemorySize(), memset(), numthreads, p, and portal_t.

Referenced by MakeHeadnodePortals(), MakeNodePortal(), and SplitNodePortals().

00040 {
00041     portal_t    *p;
00042     
00043     p = GetMemory(sizeof(portal_t));
00044     memset (p, 0, sizeof(portal_t));
00045 
00046     if (numthreads == 1)
00047     {
00048         c_active_portals++;
00049         if (c_active_portals > c_peak_portals)
00050         {
00051             c_peak_portals = c_active_portals;
00052         } //end if
00053         c_portalmemory += MemorySize(p);    
00054     } //end if
00055 
00056 //  p->nextportal = portallist;
00057 //  portallist = p;
00058     
00059     return p;
00060 } //end of the function AllocPortal

Here is the call graph for this function:

winding_t* BaseWindingForNode node_t node  ) 
 

Definition at line 364 of file portals.c.

References BASE_WINDING_EPSILON, BaseWindingForPlane(), node_s::children, ChopWindingInPlace(), plane_t::dist, mapplanes, n, node_t, plane_t::normal, node_s::parent, node_s::planenum, vec3_origin, vec3_t, vec_t, VectorSubtract, and w.

00365 {
00366     winding_t   *w;
00367     node_t      *n;
00368     plane_t     *plane;
00369     vec3_t      normal;
00370     vec_t       dist;
00371 
00372     w = BaseWindingForPlane (mapplanes[node->planenum].normal
00373         , mapplanes[node->planenum].dist);
00374 
00375     // clip by all the parents
00376     for (n=node->parent ; n && w ; )
00377     {
00378         plane = &mapplanes[n->planenum];
00379 
00380         if (n->children[0] == node)
00381         {   // take front
00382             ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON);
00383         }
00384         else
00385         {   // take back
00386             VectorSubtract (vec3_origin, plane->normal, normal);
00387             dist = -plane->dist;
00388             ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON);
00389         }
00390         node = n;
00391         n = n->parent;
00392     }
00393 
00394     return w;
00395 } //end of the function BaseWindingForNode

Here is the call graph for this function:

void CalcNodeBounds node_t node  ) 
 

Definition at line 588 of file portals.c.

References AddPointToBounds(), ClearBounds(), i, node_s::maxs, node_s::mins, portal_s::next, node_t, portal_s::nodes, winding_t::numpoints, winding_t::p, p, portal_t, node_s::portals, s, and portal_s::winding.

00589 {
00590     portal_t    *p;
00591     int         s;
00592     int         i;
00593 
00594     // calc mins/maxs for both leaves and nodes
00595     ClearBounds (node->mins, node->maxs);
00596     for (p = node->portals ; p ; p = p->next[s])    
00597     {
00598         s = (p->nodes[1] == node);
00599         for (i=0 ; i<p->winding->numpoints ; i++)
00600             AddPointToBounds (p->winding->p[i], node->mins, node->maxs);
00601     }
00602 } //end of the function CalcNodeBounds

Here is the call graph for this function:

int ClusterContents node_t node  ) 
 

Definition at line 101 of file portals.c.

References c, node_s::children, node_s::contents, node_t, and node_s::planenum.

Referenced by Portal_VisFlood().

00102 {
00103     int     c1, c2, c;
00104 
00105     if (node->planenum == PLANENUM_LEAF)
00106         return node->contents;
00107 
00108     c1 = ClusterContents(node->children[0]);
00109     c2 = ClusterContents(node->children[1]);
00110     c = c1|c2;
00111 
00112     // a cluster may include some solid detail areas, but
00113     // still be seen into
00114     if ( ! (c1&CONTENTS_SOLID) || ! (c2&CONTENTS_SOLID) )
00115         c &= ~CONTENTS_SOLID;
00116     return c;
00117 } //end of the function ClusterContents

void FillOutside node_t headnode  ) 
 

Definition at line 961 of file portals.c.

00962 {
00963     c_outside = 0;
00964     c_inside = 0;
00965     c_solid = 0;
00966     Log_Print("------- FillOutside --------\n");
00967     FillOutside_r (headnode);
00968     Log_Print("%5i solid leaves\n", c_solid);
00969     Log_Print("%5i leaves filled\n", c_outside);
00970     Log_Print("%5i inside leaves\n", c_inside);
00971 } //end of the function FillOutside

void FillOutside_r node_t node  ) 
 

Definition at line 927 of file portals.c.

References c_inside, c_outside, c_solid, node_s::children, node_s::contents, FillOutside_r(), node_t, node_s::occupied, and node_s::planenum.

00928 {
00929     if (node->planenum != PLANENUM_LEAF)
00930     {
00931         FillOutside_r (node->children[0]);
00932         FillOutside_r (node->children[1]);
00933         return;
00934     } //end if
00935     // anything not reachable by an entity
00936     // can be filled away (by setting solid contents)
00937     if (!node->occupied)
00938     {
00939         if (!(node->contents & CONTENTS_SOLID))
00940         {
00941             c_outside++;
00942             node->contents |= CONTENTS_SOLID;
00943         } //end if
00944         else
00945         {
00946             c_solid++;
00947         } //end else
00948     } //end if
00949     else
00950     {
00951         c_inside++;
00952     } //end else
00953 } //end of the function FillOutside_r

Here is the call graph for this function:

void FindAreas_r node_t node  ) 
 

Definition at line 1046 of file portals.c.

References node_s::area, c_areas, node_s::children, node_s::contents, FindAreas_r(), FloodAreas_r(), node_t, node_s::occupied, and node_s::planenum.

01047 {
01048     if (node->planenum != PLANENUM_LEAF)
01049     {
01050         FindAreas_r (node->children[0]);
01051         FindAreas_r (node->children[1]);
01052         return;
01053     }
01054 
01055     if (node->area)
01056         return;     // allready got it
01057 
01058     if (node->contents & CONTENTS_SOLID)
01059         return;
01060 
01061     if (!node->occupied)
01062         return;         // not reachable by entities
01063 
01064     // area portals are allways only flooded into, never
01065     // out of
01066     if (node->contents == CONTENTS_AREAPORTAL)
01067         return;
01068 
01069     c_areas++;
01070     FloodAreas_r (node);
01071 } //end of the function FindAreas_r

Here is the call graph for this function:

void FindPortalSide portal_t p  ) 
 

Definition at line 1175 of file portals.c.

References node_s::brushlist, bspbrush_t, mapbrush_s::contents, node_s::contents, DotProduct, side_s::flags, i, j, Log_Print(), mapbrush_t, mapplanes, n, bspbrush_s::next, node_t, portal_s::nodes, plane_t::normal, mapbrush_s::numsides, portal_s::onnode, bspbrush_s::original, mapbrush_s::original_sides, p, p2, side_s::planenum, node_s::planenum, portal_t, portal_s::side, side_t, portal_s::sidefound, side_s::texinfo, and VisibleContents().

Referenced by MarkVisibleSides_r().

01176 {
01177     int         viscontents;
01178     bspbrush_t  *bb;
01179     mapbrush_t  *brush;
01180     node_t      *n;
01181     int         i,j;
01182     int         planenum;
01183     side_t      *side, *bestside;
01184     float       dot, bestdot;
01185     plane_t     *p1, *p2;
01186 
01187     // decide which content change is strongest
01188     // solid > lava > water, etc
01189     viscontents = VisibleContents (p->nodes[0]->contents ^ p->nodes[1]->contents);
01190     if (!viscontents)
01191         return;
01192 
01193     planenum = p->onnode->planenum;
01194     bestside = NULL;
01195     bestdot = 0;
01196 
01197     for (j=0 ; j<2 ; j++)
01198     {
01199         n = p->nodes[j];
01200         p1 = &mapplanes[p->onnode->planenum];
01201         for (bb=n->brushlist ; bb ; bb=bb->next)
01202         {
01203             brush = bb->original;
01204             if ( !(brush->contents & viscontents) )
01205                 continue;
01206             for (i=0 ; i<brush->numsides ; i++)
01207             {
01208                 side = &brush->original_sides[i];
01209                 if (side->flags & SFL_BEVEL)
01210                     continue;
01211                 if (side->texinfo == TEXINFO_NODE)
01212                     continue;       // non-visible
01213                 if ((side->planenum&~1) == planenum)
01214                 {   // exact match
01215                     bestside = &brush->original_sides[i];
01216                     goto gotit;
01217                 } //end if
01218                 // see how close the match is
01219                 p2 = &mapplanes[side->planenum&~1];
01220                 dot = DotProduct (p1->normal, p2->normal);
01221                 if (dot > bestdot)
01222                 {
01223                     bestdot = dot;
01224                     bestside = side;
01225                 } //end if
01226             } //end for
01227         } //end for
01228     } //end for
01229 
01230 gotit:
01231     if (!bestside)
01232         Log_Print("WARNING: side not found for portal\n");
01233 
01234     p->sidefound = true;
01235     p->side = bestside;
01236 } //end of the function FindPortalSide

Here is the call graph for this function:

void FloodAreas tree_t tree  ) 
 

Definition at line 1161 of file portals.c.

01162 {
01163     Log_Print("--- FloodAreas ---\n");
01164     FindAreas_r (tree->headnode);
01165     SetAreaPortalAreas_r (tree->headnode);
01166     Log_Print("%5i areas\n", c_areas);
01167 } //end of the function FloodAreas

void FloodAreas_r node_t node  ) 
 

Definition at line 989 of file portals.c.

References node_s::area, b, node_s::brushlist, bspbrush_t, c_areas, node_s::contents, e, entities, mapbrush_s::entitynum, FloodAreas_r(), Log_Print(), portal_s::next, node_t, portal_s::nodes, node_s::occupied, bspbrush_s::original, p, Portal_EntityFlood(), portal_t, entity_t::portalareas, node_s::portals, and s.

00990 {
00991     portal_t    *p;
00992     int         s;
00993     bspbrush_t  *b;
00994     entity_t    *e;
00995 
00996     if (node->contents == CONTENTS_AREAPORTAL)
00997     {
00998         // this node is part of an area portal
00999         b = node->brushlist;
01000         e = &entities[b->original->entitynum];
01001 
01002         // if the current area has allready touched this
01003         // portal, we are done
01004         if (e->portalareas[0] == c_areas || e->portalareas[1] == c_areas)
01005             return;
01006 
01007         // note the current area as bounding the portal
01008         if (e->portalareas[1])
01009         {
01010             Log_Print("WARNING: areaportal entity %i touches > 2 areas\n", b->original->entitynum);
01011             return;
01012         }
01013         if (e->portalareas[0])
01014             e->portalareas[1] = c_areas;
01015         else
01016             e->portalareas[0] = c_areas;
01017 
01018         return;
01019     } //end if
01020 
01021     if (node->area)
01022         return;     // allready got it
01023     node->area = c_areas;
01024 
01025     for (p=node->portals ; p ; p = p->next[s])
01026     {
01027         s = (p->nodes[1] == node);
01028 #if 0
01029         if (p->nodes[!s]->occupied)
01030             continue;
01031 #endif
01032         if (!Portal_EntityFlood (p, s))
01033             continue;
01034 
01035         FloodAreas_r (p->nodes[!s]);
01036     } //end for
01037 } //end of the function FloodAreas_r

Here is the call graph for this function:

qboolean FloodEntities tree_t tree  ) 
 

Definition at line 843 of file portals.c.

00844 {
00845     int i;
00846     int x, y;
00847     vec3_t origin;
00848     char *cl;
00849     qboolean inside;
00850     node_t *headnode;
00851 
00852     headnode = tree->headnode;
00853     Log_Print("------ FloodEntities -------\n");
00854     inside = false;
00855     tree->outside_node.occupied = 0;
00856 
00857     //start at entity 1 not the world ( = 0)
00858     for (i = 1; i < num_entities; i++)
00859     {
00860         GetVectorForKey(&entities[i], "origin", origin);
00861         if (VectorCompare(origin, vec3_origin)) continue;
00862 
00863         cl = ValueForKey(&entities[i], "classname");
00864         origin[2] += 1; //so objects on floor are ok
00865 
00866 //      Log_Print("flooding from entity %d: %s\n", i, cl);
00867         //nudge playerstart around if needed so clipping hulls allways
00868         //have a valid point
00869         if (!strcmp(cl, "info_player_start"))
00870         {
00871             for (x = -16; x <= 16; x += 16)
00872             {
00873                 for (y = -16; y <= 16; y += 16)
00874                 {
00875                     origin[0] += x;
00876                     origin[1] += y;
00877                     if (PlaceOccupant(headnode, origin, &entities[i]))
00878                     {
00879                         inside = true;
00880                         x = 999; //stop for this info_player_start
00881                         break;
00882                     } //end if
00883                     origin[0] -= x;
00884                     origin[1] -= y;
00885                 } //end for
00886             } //end for
00887         } //end if
00888         else
00889         {
00890             if (PlaceOccupant(headnode, origin, &entities[i]))
00891             {
00892                 inside = true;
00893             } //end if
00894         } //end else
00895     } //end for
00896 
00897     if (!inside)
00898     {
00899         Log_Print("WARNING: no entities inside\n");
00900     } //end if
00901     else if (tree->outside_node.occupied)
00902     {
00903         Log_Print("WARNING: entity reached from outside\n");
00904     } //end else if
00905 
00906     return (qboolean)(inside && !tree->outside_node.occupied);
00907 } //end of the function FloodEntities

void FloodPortals node_t firstnode  ) 
 

Definition at line 728 of file portals.c.

References firstnode, portal_s::next, node_t, portal_s::nodes, node_s::occupied, p, P_AddNodeToList(), P_NextNodeFromList(), Portal_EntityFlood(), portal_t, node_s::portals, and s.

Referenced by PlaceOccupant().

00729 {
00730     node_t *node;
00731     portal_t *p;
00732     int s;
00733 
00734     firstnode->occupied = 1;
00735     P_AddNodeToList(firstnode);
00736 
00737     for (node = P_NextNodeFromList(); node; node = P_NextNodeFromList())
00738     {
00739         for (p = node->portals; p; p = p->next[s])
00740         {
00741             s = (p->nodes[1] == node);
00742             //if the node at the other side of the portal is occupied already
00743             if (p->nodes[!s]->occupied) continue;
00744             //if it isn't possible to flood through this portal
00745             if (!Portal_EntityFlood(p, s)) continue;
00746             //
00747             p->nodes[!s]->occupied = node->occupied + 1;
00748             //
00749             P_AddNodeToList(p->nodes[!s]);
00750         } //end for
00751     } //end for
00752 } //end of the function FloodPortals

Here is the call graph for this function:

void FloodPortals_r node_t node,
int  dist
 

Definition at line 761 of file portals.c.

References Error(), FloodPortals_r(), Log_Print(), portal_s::next, node_t, portal_s::nodes, numrec, node_s::occupied, p, Portal_EntityFlood(), portal_t, node_s::portals, and s.

00762 {
00763     portal_t *p;
00764     int s;
00765 //  int i;
00766 
00767     Log_Print("\r%6d", ++numrec);
00768 
00769     if (node->occupied) Error("FloodPortals_r: node already occupied\n");
00770     if (!node)
00771     {
00772         Error("FloodPortals_r: NULL node\n");
00773     } //end if*/
00774     node->occupied = dist;
00775 
00776     for (p = node->portals; p; p = p->next[s])
00777     {
00778         s = (p->nodes[1] == node);
00779         //if the node at the other side of the portal is occupied already
00780         if (p->nodes[!s]->occupied) continue;
00781         //if it isn't possible to flood through this portal
00782         if (!Portal_EntityFlood(p, s)) continue;
00783         //flood recursively through the current portal
00784         FloodPortals_r(p->nodes[!s], dist+1);
00785     } //end for
00786     Log_Print("\r%6d", --numrec);
00787 } //end of the function FloodPortals_r

Here is the call graph for this function:

void FreePortal portal_t p  ) 
 

Definition at line 67 of file portals.c.

00068 {
00069     if (p->winding) FreeWinding(p->winding);
00070     if (numthreads == 1)
00071     {
00072         c_active_portals--;
00073         c_portalmemory -= MemorySize(p);
00074     } //end if
00075     FreeMemory(p);
00076 } //end of the function FreePortal

void MakeHeadnodePortals tree_t tree  ) 
 

Definition at line 295 of file portals.c.

00296 {
00297     vec3_t      bounds[2];
00298     int         i, j, n;
00299     portal_t    *p, *portals[6];
00300     plane_t     bplanes[6], *pl;
00301     node_t *node;
00302 
00303     node = tree->headnode;
00304 
00305 // pad with some space so there will never be null volume leaves
00306     for (i=0 ; i<3 ; i++)
00307     {
00308         bounds[0][i] = tree->mins[i] - SIDESPACE;
00309         bounds[1][i] = tree->maxs[i] + SIDESPACE;
00310         if ( bounds[0][i] > bounds[1][i] ) {
00311             Error("empty BSP tree");
00312         }
00313     }
00314     
00315     tree->outside_node.planenum = PLANENUM_LEAF;
00316     tree->outside_node.brushlist = NULL;
00317     tree->outside_node.portals = NULL;
00318     tree->outside_node.contents = 0;
00319 
00320     for (i=0 ; i<3 ; i++)
00321         for (j=0 ; j<2 ; j++)
00322         {
00323             n = j*3 + i;
00324 
00325             p = AllocPortal ();
00326             portals[n] = p;
00327             
00328             pl = &bplanes[n];
00329             memset (pl, 0, sizeof(*pl));
00330             if (j)
00331             {
00332                 pl->normal[i] = -1;
00333                 pl->dist = -bounds[j][i];
00334             }
00335             else
00336             {
00337                 pl->normal[i] = 1;
00338                 pl->dist = bounds[j][i];
00339             }
00340             p->plane = *pl;
00341             p->winding = BaseWindingForPlane (pl->normal, pl->dist);
00342             AddPortalToNodes (p, node, &tree->outside_node);
00343         }
00344         
00345 // clip the basewindings by all the other planes
00346     for (i=0 ; i<6 ; i++)
00347     {
00348         for (j=0 ; j<6 ; j++)
00349         {
00350             if (j == i) continue;
00351             ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON);
00352         } //end for
00353     } //end for
00354 } //end of the function MakeHeadNodePortals

void MakeNodePortal node_t node  ) 
 

Definition at line 406 of file portals.c.

00407 {
00408     portal_t    *new_portal, *p;
00409     winding_t   *w;
00410     vec3_t      normal;
00411     float       dist;
00412     int         side;
00413 
00414     w = BaseWindingForNode (node);
00415 
00416     // clip the portal by all the other portals in the node
00417     for (p = node->portals; p && w; p = p->next[side])  
00418     {
00419         if (p->nodes[0] == node)
00420         {
00421             side = 0;
00422             VectorCopy (p->plane.normal, normal);
00423             dist = p->plane.dist;
00424         } //end if
00425         else if (p->nodes[1] == node)
00426         {
00427             side = 1;
00428             VectorSubtract (vec3_origin, p->plane.normal, normal);
00429             dist = -p->plane.dist;
00430         } //end else if
00431         else
00432         {
00433             Error ("MakeNodePortal: mislinked portal");
00434         } //end else
00435         ChopWindingInPlace (&w, normal, dist, 0.1);
00436     } //end for
00437 
00438     if (!w)
00439     {
00440         return;
00441     } //end if
00442 
00443     if (WindingIsTiny (w))
00444     {
00445         c_tinyportals++;
00446         FreeWinding(w);
00447         return;
00448     } //end if
00449 
00450 #ifdef DEBUG
00451 /* //NOTE: don't use this winding ok check
00452     // all the invalid windings only have a degenerate edge
00453     if (WindingError(w))
00454     {
00455         Log_Print("MakeNodePortal: %s\n", WindingErrorString());
00456         FreeWinding(w);
00457         return;
00458     } //end if*/
00459 #endif //DEBUG
00460 
00461 
00462     new_portal = AllocPortal();
00463     new_portal->plane = mapplanes[node->planenum];
00464 
00465 #ifdef ME
00466     new_portal->planenum = node->planenum;
00467 #endif //ME
00468 
00469     new_portal->onnode = node;
00470     new_portal->winding = w;
00471     AddPortalToNodes (new_portal, node->children[0], node->children[1]);
00472 } //end of the function MakeNodePortal

void MakeTreePortals tree_t tree  ) 
 

Definition at line 649 of file portals.c.

00650 {
00651 
00652 #ifdef ME
00653     Log_Print("---- Node Portalization ----\n");
00654     c_numportalizednodes = 0;
00655     c_portalmemory = 0;
00656     qprintf("%6d nodes portalized", c_numportalizednodes);
00657 #endif //ME
00658 
00659     MakeHeadnodePortals(tree);
00660     MakeTreePortals_r(tree->headnode);
00661 
00662 #ifdef ME
00663     qprintf("\n");
00664     Log_Write("%6d nodes portalized\r\n", c_numportalizednodes);
00665     Log_Print("%6d tiny portals\r\n", c_tinyportals);
00666     Log_Print("%6d KB of portal memory\r\n", c_portalmemory >> 10);
00667     Log_Print("%6i KB of winding memory\r\n", WindingMemory() >> 10);
00668 #endif //ME
00669 } //end of the function MakeTreePortals

void MakeTreePortals_r node_t node  ) 
 

Definition at line 611 of file portals.c.

References c_numportalizednodes, CalcNodeBounds(), node_s::children, i, Log_Print(), MakeNodePortal(), MakeTreePortals_r(), MAX_MAP_BOUNDS, node_s::maxs, node_s::mins, node_t, node_s::planenum, qprintf(), and SplitNodePortals().

00612 {
00613     int     i;
00614 
00615 #ifdef ME
00616     qprintf("\r%6d", ++c_numportalizednodes);
00617     if (cancelconversion) return;
00618 #endif //ME
00619 
00620     CalcNodeBounds (node);
00621     if (node->mins[0] >= node->maxs[0])
00622     {
00623         Log_Print("WARNING: node without a volume\n");
00624     }
00625 
00626     for (i=0 ; i<3 ; i++)
00627     {
00628         if (node->mins[i] < -MAX_MAP_BOUNDS || node->maxs[i] > MAX_MAP_BOUNDS)
00629         {
00630             Log_Print("WARNING: node with unbounded volume\n");
00631             break;
00632         }
00633     }
00634     if (node->planenum == PLANENUM_LEAF)
00635         return;
00636 
00637     MakeNodePortal (node);
00638     SplitNodePortals (node);
00639 
00640     MakeTreePortals_r (node->children[0]);
00641     MakeTreePortals_r (node->children[1]);
00642 } //end of the function MakeTreePortals_r

Here is the call graph for this function:

void MarkVisibleSides tree_t tree,
int  startbrush,
int  endbrush
 

Definition at line 1276 of file portals.c.

References side_s::flags, i, j, Log_Print(), mapbrush_t, mapbrushes, MarkVisibleSides_r(), mapbrush_s::numsides, mapbrush_s::original_sides, and tree().

01277 {
01278     int     i, j;
01279     mapbrush_t  *mb;
01280     int     numsides;
01281 
01282     Log_Print("--- MarkVisibleSides ---\n");
01283 
01284     // clear all the visible flags
01285     for (i=startbrush ; i<endbrush ; i++)
01286     {
01287         mb = &mapbrushes[i];
01288 
01289         numsides = mb->numsides;
01290         for (j=0 ; j<numsides ; j++)
01291             mb->original_sides[j].flags &= ~SFL_VISIBLE;
01292     }
01293 
01294     // set visible flags on the sides that are used by portals
01295     MarkVisibleSides_r (tree->headnode);
01296 } //end of the function MarkVisibleSides

Here is the call graph for this function:

void MarkVisibleSides_r node_t node  ) 
 

Definition at line 1243 of file portals.c.

References node_s::children, node_s::contents, FindPortalSide(), side_s::flags, portal_s::next, node_t, portal_s::nodes, portal_s::onnode, p, node_s::planenum, portal_t, node_s::portals, s, portal_s::side, and portal_s::sidefound.

Referenced by MarkVisibleSides().

01244 {
01245     portal_t *p;
01246     int s;
01247 
01248     if (node->planenum != PLANENUM_LEAF)
01249     {
01250         MarkVisibleSides_r (node->children[0]);
01251         MarkVisibleSides_r (node->children[1]);
01252         return;
01253     } //end if
01254 
01255     // empty leaves are never boundary leaves
01256     if (!node->contents) return;
01257 
01258     // see if there is a visible face
01259     for (p=node->portals ; p ; p = p->next[!s])
01260     {
01261         s = (p->nodes[0] == node);
01262         if (!p->onnode)
01263             continue;       // edge of world
01264         if (!p->sidefound)
01265             FindPortalSide (p);
01266         if (p->side)
01267             p->side->flags |= SFL_VISIBLE;
01268     } //end for
01269 } //end of the function MarkVisibleSides_r

Here is the call graph for this function: