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

facebsp.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 #include "qbsp.h"
00024 
00025 
00026 int         c_faceLeafs;
00027 
00028 
00029 /*
00030 ================
00031 AllocBspFace
00032 ================
00033 */
00034 bspface_t   *AllocBspFace( void ) {
00035     bspface_t   *f;
00036 
00037     f = malloc(sizeof(*f));
00038     memset( f, 0, sizeof(*f) );
00039 
00040     return f;
00041 }
00042 
00043 /*
00044 ================
00045 FreeBspFace
00046 ================
00047 */
00048 void    FreeBspFace( bspface_t *f ) {
00049     if ( f->w ) {
00050         FreeWinding( f->w );
00051     }
00052     free( f );
00053 }
00054 
00055 
00056 /*
00057 ================
00058 SelectSplitPlaneNum
00059 ================
00060 */
00061 int hintsplit;
00062 
00063 #define BLOCK_SIZE  1024
00064 int SelectSplitPlaneNum( node_t *node, bspface_t *list ) {
00065     bspface_t   *split;
00066     bspface_t   *check;
00067     bspface_t   *bestSplit;
00068     int         splits, facing, front, back;
00069     int         side;
00070     plane_t     *plane;
00071     int         value, bestValue;
00072     int         i;
00073     vec3_t      normal;
00074     float       dist;
00075     int         planenum;
00076 
00077     hintsplit = qfalse;
00078     // if it is crossing a 1k block boundary, force a split
00079     for ( i = 0 ; i < 2 ; i++ ) {
00080         dist = BLOCK_SIZE * ( floor( node->mins[i] / BLOCK_SIZE ) + 1 );    
00081         if ( node->maxs[i] > dist ) {
00082             VectorClear( normal );
00083             normal[i] = 1;
00084             planenum = FindFloatPlane( normal, dist );
00085             return planenum;
00086         }
00087     }
00088 
00089     // pick one of the face planes
00090     bestValue = -99999;
00091     bestSplit = list;
00092 
00093     for ( split = list ; split ; split = split->next ) {
00094         split->checked = qfalse;
00095     }
00096 
00097     for ( split = list ; split ; split = split->next ) {
00098         if ( split->checked ) {
00099             continue;
00100         }
00101         plane = &mapplanes[ split->planenum ];
00102         splits = 0;
00103         facing = 0;
00104         front = 0;
00105         back = 0;
00106         for ( check = list ; check ; check = check->next ) {
00107             if ( check->planenum == split->planenum ) {
00108                 facing++;
00109                 check->checked = qtrue; // won't need to test this plane again
00110                 continue;
00111             }
00112             side = WindingOnPlaneSide( check->w, plane->normal, plane->dist );
00113             if ( side == SIDE_CROSS ) {
00114                 splits++;
00115             } else if ( side == SIDE_FRONT ) {
00116                 front++;
00117             } else if ( side == SIDE_BACK ) {
00118                 back++;
00119             }
00120         }
00121         value =  5*facing - 5*splits; // - abs(front-back);
00122         if ( plane->type < 3 ) {
00123             value+=5;       // axial is better
00124         }
00125         value += split->priority;       // prioritize hints higher
00126 
00127         if ( value > bestValue ) {
00128             bestValue = value;
00129             bestSplit = split;
00130         }
00131     }
00132 
00133     if ( bestValue == -99999 ) {
00134         return -1;
00135     }
00136 
00137     if (bestSplit->hint)
00138         hintsplit = qtrue;
00139 
00140     return bestSplit->planenum;
00141 }
00142 
00143 int CountFaceList( bspface_t *list ) {
00144     int     c;
00145     c = 0;
00146     for ( ; list ; list = list->next ) {
00147         c++;
00148     }
00149     return c;
00150 }
00151 
00152 /*
00153 ================
00154 BuildFaceTree_r
00155 ================
00156 */
00157 void    BuildFaceTree_r( node_t *node, bspface_t *list ) {
00158     bspface_t   *split;
00159     bspface_t   *next;
00160     int         side;
00161     plane_t     *plane;
00162     bspface_t   *newFace;
00163     bspface_t   *childLists[2];
00164     winding_t   *frontWinding, *backWinding;
00165     int         i;
00166     int         splitPlaneNum;
00167 
00168     i = CountFaceList( list );
00169 
00170     splitPlaneNum = SelectSplitPlaneNum( node, list );
00171     // if we don't have any more faces, this is a node
00172     if ( splitPlaneNum == -1 ) {
00173         node->planenum = PLANENUM_LEAF;
00174         c_faceLeafs++;
00175         return;
00176     }
00177 
00178     // partition the list
00179     node->planenum = splitPlaneNum;
00180     node->hint = hintsplit;
00181     plane = &mapplanes[ splitPlaneNum ];
00182     childLists[0] = NULL;
00183     childLists[1] = NULL;
00184     for ( split = list ; split ; split = next ) {
00185         next = split->next;
00186 
00187         if ( split->planenum == node->planenum ) {
00188             FreeBspFace( split );
00189             continue;
00190         }
00191 
00192         side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
00193 
00194         if ( side == SIDE_CROSS ) {
00195             ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
00196                 &frontWinding, &backWinding );
00197             if ( frontWinding ) {
00198                 newFace = AllocBspFace();
00199                 newFace->w = frontWinding;
00200                 newFace->next = childLists[0];
00201                 newFace->planenum = split->planenum;
00202                 newFace->priority = split->priority;
00203                 newFace->hint = split->hint;
00204                 childLists[0] = newFace;
00205             }
00206             if ( backWinding ) {
00207                 newFace = AllocBspFace();
00208                 newFace->w = backWinding;
00209                 newFace->next = childLists[1];
00210                 newFace->planenum = split->planenum;
00211                 newFace->priority = split->priority;
00212                 newFace->hint = split->hint;
00213                 childLists[1] = newFace;
00214             }
00215             FreeBspFace( split );
00216         } else if ( side == SIDE_FRONT ) {
00217             split->next = childLists[0];
00218             childLists[0] = split;
00219         } else if ( side == SIDE_BACK ) {
00220             split->next = childLists[1];
00221             childLists[1] = split;
00222         }
00223     }
00224 
00225 
00226     // recursively process children
00227     for ( i = 0 ; i < 2 ; i++ ) {
00228         node->children[i] = AllocNode();
00229         node->children[i]->parent = node;
00230         VectorCopy( node->mins, node->children[i]->mins );
00231         VectorCopy( node->maxs, node->children[i]->maxs );
00232     }
00233 
00234     for ( i = 0 ; i < 3 ; i++ ) {
00235         if ( plane->normal[i] == 1 ) {
00236             node->children[0]->mins[i] = plane->dist;
00237             node->children[1]->maxs[i] = plane->dist;
00238             break;
00239         }
00240     }
00241 
00242     for ( i = 0 ; i < 2 ; i++ ) {
00243         BuildFaceTree_r ( node->children[i], childLists[i]);
00244     }
00245 }
00246 
00247 
00248 /*
00249 ================
00250 FaceBSP
00251 
00252 List will be freed before returning
00253 ================
00254 */
00255 tree_t *FaceBSP( bspface_t *list ) {
00256     tree_t      *tree;
00257     bspface_t   *face;
00258     int         i;
00259     int         count;
00260 
00261     qprintf( "--- FaceBSP ---\n" );
00262 
00263     tree = AllocTree ();
00264 
00265     count = 0;
00266     for ( face = list ; face ; face = face->next ) {
00267         count++;
00268         for ( i = 0 ; i < face->w->numpoints ; i++ ) {
00269             AddPointToBounds( face->w->p[i], tree->mins, tree->maxs);
00270         }
00271     }
00272     qprintf( "%5i faces\n", count );
00273 
00274     tree->headnode = AllocNode();
00275     VectorCopy( tree->mins, tree->headnode->mins );
00276     VectorCopy( tree->maxs, tree->headnode->maxs );
00277     c_faceLeafs = 0;
00278 
00279     BuildFaceTree_r ( tree->headnode, list );
00280 
00281     qprintf( "%5i leafs\n", c_faceLeafs );
00282 
00283     return tree;
00284 }
00285 
00286 
00287 /*
00288 =================
00289 BspFaceForPortal
00290 =================
00291 */
00292 bspface_t *BspFaceForPortal( portal_t *p ) {
00293     bspface_t   *f;
00294 
00295     f = AllocBspFace();
00296     f->w = CopyWinding( p->winding );
00297     f->planenum = p->onnode->planenum & ~1;
00298 
00299     return f;
00300 }
00301 
00302 
00303 
00304 /*
00305 =================
00306 MakeStructuralBspFaceList
00307 =================
00308 */
00309 bspface_t   *MakeStructuralBspFaceList( bspbrush_t *list ) {
00310     bspbrush_t  *b;
00311     int         i;
00312     side_t      *s;
00313     winding_t   *w;
00314     bspface_t   *f, *flist;
00315 
00316     flist = NULL;
00317     for ( b = list ; b ; b = b->next ) {
00318         if ( b->detail ) {
00319             continue;
00320         }
00321         for ( i = 0 ; i < b->numsides ; i++ ) {
00322             s = &b->sides[i];
00323             w = s->winding;
00324             if ( !w ) {
00325                 continue;
00326             }
00327             f = AllocBspFace();
00328             f->w = CopyWinding( w );
00329             f->planenum = s->planenum & ~1;
00330             f->next = flist;
00331             if (s->surfaceFlags & SURF_HINT) {
00332                 //f->priority = HINT_PRIORITY;
00333                 f->hint = qtrue;
00334             }
00335             flist = f;
00336         }
00337     }
00338 
00339     return flist;
00340 }
00341 
00342 /*
00343 =================
00344 MakeVisibleBspFaceList
00345 =================
00346 */
00347 bspface_t   *MakeVisibleBspFaceList( bspbrush_t *list ) {
00348     bspbrush_t  *b;
00349     int         i;
00350     side_t      *s;
00351     winding_t   *w;
00352     bspface_t   *f, *flist;
00353 
00354     flist = NULL;
00355     for ( b = list ; b ; b = b->next ) {
00356         if ( b->detail ) {
00357             continue;
00358         }
00359         for ( i = 0 ; i < b->numsides ; i++ ) {
00360             s = &b->sides[i];
00361             w = s->visibleHull;
00362             if ( !w ) {
00363                 continue;
00364             }
00365             f = AllocBspFace();
00366             f->w = CopyWinding( w );
00367             f->planenum = s->planenum & ~1;
00368             f->next = flist;
00369             if (s->surfaceFlags & SURF_HINT) {
00370                 //f->priority = HINT_PRIORITY;
00371                 f->hint = qtrue;
00372             }
00373             flist = f;
00374         }
00375     }
00376 
00377     return flist;
00378 }
00379 

Generated on Thu Aug 25 12:38:20 2005 for Quake III Arena by  doxygen 1.3.9.1