00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "qbsp.h"
00024
00025
00026 int c_faceLeafs;
00027
00028
00029
00030
00031
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
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
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
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
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;
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;
00122 if ( plane->type < 3 ) {
00123 value+=5;
00124 }
00125 value += split->priority;
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
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
00172 if ( splitPlaneNum == -1 ) {
00173 node->planenum = PLANENUM_LEAF;
00174 c_faceLeafs++;
00175 return;
00176 }
00177
00178
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
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
00251
00252
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
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
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
00333 f->hint = qtrue;
00334 }
00335 flist = f;
00336 }
00337 }
00338
00339 return flist;
00340 }
00341
00342
00343
00344
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
00371 f->hint = qtrue;
00372 }
00373 flist = f;
00374 }
00375 }
00376
00377 return flist;
00378 }
00379