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 #include "l_mem.h"
00025 #include "../botlib/aasfile.h"
00026 #include "aas_store.h"
00027 #include "aas_cfg.h"
00028
00029 #include <assert.h>
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 int c_nodes;
00051 int c_nonvis;
00052 int c_active_brushes;
00053 int c_solidleafnodes;
00054 int c_totalsides;
00055 int c_brushmemory;
00056 int c_peak_brushmemory;
00057 int c_nodememory;
00058 int c_peak_totalbspmemory;
00059
00060
00061
00062 #define PLANESIDE_EPSILON 0.001
00063
00064
00065
00066 typedef struct cname_s
00067 {
00068 int value;
00069 char *name;
00070 } cname_t;
00071
00072 cname_t contentnames[] =
00073 {
00074 {CONTENTS_SOLID,"CONTENTS_SOLID"},
00075 {CONTENTS_WINDOW,"CONTENTS_WINDOW"},
00076 {CONTENTS_AUX,"CONTENTS_AUX"},
00077 {CONTENTS_LAVA,"CONTENTS_LAVA"},
00078 {CONTENTS_SLIME,"CONTENTS_SLIME"},
00079 {CONTENTS_WATER,"CONTENTS_WATER"},
00080 {CONTENTS_MIST,"CONTENTS_MIST"},
00081 {LAST_VISIBLE_CONTENTS,"LAST_VISIBLE_CONTENTS"},
00082
00083 {CONTENTS_AREAPORTAL,"CONTENTS_AREAPORTAL"},
00084 {CONTENTS_PLAYERCLIP,"CONTENTS_PLAYERCLIP"},
00085 {CONTENTS_MONSTERCLIP,"CONTENTS_MONSTERCLIP"},
00086 {CONTENTS_CURRENT_0,"CONTENTS_CURRENT_0"},
00087 {CONTENTS_CURRENT_90,"CONTENTS_CURRENT_90"},
00088 {CONTENTS_CURRENT_180,"CONTENTS_CURRENT_180"},
00089 {CONTENTS_CURRENT_270,"CONTENTS_CURRENT_270"},
00090 {CONTENTS_CURRENT_UP,"CONTENTS_CURRENT_UP"},
00091 {CONTENTS_CURRENT_DOWN,"CONTENTS_CURRENT_DOWN"},
00092 {CONTENTS_ORIGIN,"CONTENTS_ORIGIN"},
00093 {CONTENTS_MONSTER,"CONTENTS_MONSTER"},
00094 {CONTENTS_DEADMONSTER,"CONTENTS_DEADMONSTER"},
00095 {CONTENTS_DETAIL,"CONTENTS_DETAIL"},
00096 {CONTENTS_Q2TRANSLUCENT,"CONTENTS_TRANSLUCENT"},
00097 {CONTENTS_LADDER,"CONTENTS_LADDER"},
00098 {0, 0}
00099 };
00100
00101 void PrintContents(int contents)
00102 {
00103 int i;
00104
00105 for (i = 0; contentnames[i].value; i++)
00106 {
00107 if (contents & contentnames[i].value)
00108 {
00109 Log_Write("%s,", contentnames[i].name);
00110 }
00111 }
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 void ResetBrushBSP(void)
00123 {
00124 c_nodes = 0;
00125 c_nonvis = 0;
00126 c_active_brushes = 0;
00127 c_solidleafnodes = 0;
00128 c_totalsides = 0;
00129 c_brushmemory = 0;
00130 c_peak_brushmemory = 0;
00131 c_nodememory = 0;
00132 c_peak_totalbspmemory = 0;
00133 }
00134
00135
00136
00137
00138
00139
00140 void FindBrushInTree (node_t *node, int brushnum)
00141 {
00142 bspbrush_t *b;
00143
00144 if (node->planenum == PLANENUM_LEAF)
00145 {
00146 for (b=node->brushlist ; b ; b=b->next)
00147 if (b->original->brushnum == brushnum)
00148 Log_Print ("here\n");
00149 return;
00150 }
00151 FindBrushInTree(node->children[0], brushnum);
00152 FindBrushInTree(node->children[1], brushnum);
00153 }
00154
00155
00156
00157
00158
00159
00160 void DrawBrushList (bspbrush_t *brush, node_t *node)
00161 {
00162 int i;
00163 side_t *s;
00164
00165 GLS_BeginScene ();
00166 for ( ; brush ; brush=brush->next)
00167 {
00168 for (i=0 ; i<brush->numsides ; i++)
00169 {
00170 s = &brush->sides[i];
00171 if (!s->winding)
00172 continue;
00173 if (s->texinfo == TEXINFO_NODE)
00174 GLS_Winding (s->winding, 1);
00175 else if (!(s->flags & SFL_VISIBLE))
00176 GLS_Winding (s->winding, 2);
00177 else
00178 GLS_Winding (s->winding, 0);
00179 }
00180 }
00181 GLS_EndScene ();
00182 }
00183
00184
00185
00186
00187
00188
00189 void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis)
00190 {
00191 int i;
00192 side_t *s;
00193 FILE *f;
00194
00195 qprintf ("writing %s\n", name);
00196 f = SafeOpenWrite (name);
00197
00198 for ( ; brush ; brush=brush->next)
00199 {
00200 for (i=0 ; i<brush->numsides ; i++)
00201 {
00202 s = &brush->sides[i];
00203 if (!s->winding)
00204 continue;
00205 if (onlyvis && !(s->flags & SFL_VISIBLE))
00206 continue;
00207 OutputWinding (brush->sides[i].winding, f);
00208 }
00209 }
00210
00211 fclose (f);
00212 }
00213
00214
00215
00216
00217
00218
00219 void PrintBrush (bspbrush_t *brush)
00220 {
00221 int i;
00222
00223 printf ("brush: %p\n", brush);
00224 for (i=0;i<brush->numsides ; i++)
00225 {
00226 pw(brush->sides[i].winding);
00227 printf ("\n");
00228 }
00229 }
00230
00231
00232
00233
00234
00235
00236
00237 void BoundBrush (bspbrush_t *brush)
00238 {
00239 int i, j;
00240 winding_t *w;
00241
00242 ClearBounds (brush->mins, brush->maxs);
00243 for (i=0 ; i<brush->numsides ; i++)
00244 {
00245 w = brush->sides[i].winding;
00246 if (!w)
00247 continue;
00248 for (j=0 ; j<w->numpoints ; j++)
00249 AddPointToBounds (w->p[j], brush->mins, brush->maxs);
00250 }
00251 }
00252
00253
00254
00255
00256
00257
00258 void CreateBrushWindings (bspbrush_t *brush)
00259 {
00260 int i, j;
00261 winding_t *w;
00262 side_t *side;
00263 plane_t *plane;
00264
00265 for (i=0 ; i<brush->numsides ; i++)
00266 {
00267 side = &brush->sides[i];
00268 plane = &mapplanes[side->planenum];
00269 w = BaseWindingForPlane (plane->normal, plane->dist);
00270 for (j=0 ; j<brush->numsides && w; j++)
00271 {
00272 if (i == j)
00273 continue;
00274 if (brush->sides[j].flags & SFL_BEVEL)
00275 continue;
00276 plane = &mapplanes[brush->sides[j].planenum^1];
00277 ChopWindingInPlace (&w, plane->normal, plane->dist, 0);
00278 }
00279
00280 side->winding = w;
00281 }
00282
00283 BoundBrush (brush);
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs)
00293 {
00294 bspbrush_t *b;
00295 int i;
00296 vec3_t normal;
00297 vec_t dist;
00298
00299 b = AllocBrush (6);
00300 b->numsides = 6;
00301 for (i=0 ; i<3 ; i++)
00302 {
00303 VectorClear (normal);
00304 normal[i] = 1;
00305 dist = maxs[i];
00306 b->sides[i].planenum = FindFloatPlane (normal, dist);
00307
00308 normal[i] = -1;
00309 dist = -mins[i];
00310 b->sides[3+i].planenum = FindFloatPlane (normal, dist);
00311 }
00312
00313 CreateBrushWindings (b);
00314
00315 return b;
00316 }
00317
00318
00319
00320
00321
00322
00323 int BrushOutOfBounds(bspbrush_t *brush, vec3_t mins, vec3_t maxs, float epsilon)
00324 {
00325 int i, j, n;
00326 winding_t *w;
00327 side_t *side;
00328
00329 for (i = 0; i < brush->numsides; i++)
00330 {
00331 side = &brush->sides[i];
00332 w = side->winding;
00333 for (j = 0; j < w->numpoints; j++)
00334 {
00335 for (n = 0; n < 3; n++)
00336 {
00337 if (w->p[j][n] < (mins[n] + epsilon) || w->p[j][n] > (maxs[n] - epsilon)) return true;
00338 }
00339 }
00340 }
00341 return false;
00342 }
00343
00344
00345
00346
00347
00348
00349 vec_t BrushVolume (bspbrush_t *brush)
00350 {
00351 int i;
00352 winding_t *w;
00353 vec3_t corner;
00354 vec_t d, area, volume;
00355 plane_t *plane;
00356
00357 if (!brush) return 0;
00358
00359
00360 w = NULL;
00361 for (i = 0; i < brush->numsides; i++)
00362 {
00363 w = brush->sides[i].winding;
00364 if (w) break;
00365 }
00366 if (!w) return 0;
00367 VectorCopy (w->p[0], corner);
00368
00369
00370 volume = 0;
00371 for ( ; i < brush->numsides; i++)
00372 {
00373 w = brush->sides[i].winding;
00374 if (!w) continue;
00375 plane = &mapplanes[brush->sides[i].planenum];
00376 d = -(DotProduct (corner, plane->normal) - plane->dist);
00377 area = WindingArea(w);
00378 volume += d * area;
00379 }
00380
00381 volume /= 3;
00382 return volume;
00383 }
00384
00385
00386
00387
00388
00389
00390 int CountBrushList (bspbrush_t *brushes)
00391 {
00392 int c;
00393
00394 c = 0;
00395 for ( ; brushes; brushes = brushes->next) c++;
00396 return c;
00397 }
00398
00399
00400
00401
00402
00403
00404 node_t *AllocNode (void)
00405 {
00406 node_t *node;
00407
00408 node = GetMemory(sizeof(*node));
00409 memset (node, 0, sizeof(*node));
00410 if (numthreads == 1)
00411 {
00412 c_nodememory += MemorySize(node);
00413 }
00414 return node;
00415 }
00416
00417
00418
00419
00420
00421
00422 bspbrush_t *AllocBrush (int numsides)
00423 {
00424 bspbrush_t *bb;
00425 int c;
00426
00427 c = (int)&(((bspbrush_t *)0)->sides[numsides]);
00428 bb = GetMemory(c);
00429 memset (bb, 0, c);
00430 if (numthreads == 1)
00431 {
00432 c_active_brushes++;
00433 c_brushmemory += MemorySize(bb);
00434 if (c_brushmemory > c_peak_brushmemory)
00435 c_peak_brushmemory = c_brushmemory;
00436 }
00437 return bb;
00438 }
00439
00440
00441
00442
00443
00444
00445 void FreeBrush (bspbrush_t *brushes)
00446 {
00447 int i;
00448
00449 for (i=0 ; i<brushes->numsides ; i++)
00450 if (brushes->sides[i].winding)
00451 FreeWinding(brushes->sides[i].winding);
00452 if (numthreads == 1)
00453 {
00454 c_active_brushes--;
00455 c_brushmemory -= MemorySize(brushes);
00456 if (c_brushmemory < 0) c_brushmemory = 0;
00457 }
00458 FreeMemory(brushes);
00459 }
00460
00461
00462
00463
00464
00465
00466 void FreeBrushList (bspbrush_t *brushes)
00467 {
00468 bspbrush_t *next;
00469
00470 for ( ; brushes; brushes = next)
00471 {
00472 next = brushes->next;
00473
00474 FreeBrush(brushes);
00475 }
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 bspbrush_t *CopyBrush (bspbrush_t *brush)
00485 {
00486 bspbrush_t *newbrush;
00487 int size;
00488 int i;
00489
00490 size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]);
00491
00492 newbrush = AllocBrush (brush->numsides);
00493 memcpy (newbrush, brush, size);
00494
00495 for (i=0 ; i<brush->numsides ; i++)
00496 {
00497 if (brush->sides[i].winding)
00498 newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
00499 }
00500
00501 return newbrush;
00502 }
00503
00504
00505
00506
00507
00508
00509 node_t *PointInLeaf (node_t *node, vec3_t point)
00510 {
00511 vec_t d;
00512 plane_t *plane;
00513
00514 while (node->planenum != PLANENUM_LEAF)
00515 {
00516 plane = &mapplanes[node->planenum];
00517 d = DotProduct (point, plane->normal) - plane->dist;
00518 if (d > 0)
00519 node = node->children[0];
00520 else
00521 node = node->children[1];
00522 }
00523
00524 return node;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533 #if 0
00534 int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane)
00535 {
00536 int side;
00537 int i;
00538 vec3_t corners[2];
00539 vec_t dist1, dist2;
00540
00541
00542 if (plane->type < 3)
00543 {
00544 side = 0;
00545 if (maxs[plane->type] > plane->dist+PLANESIDE_EPSILON)
00546 side |= PSIDE_FRONT;
00547 if (mins[plane->type] < plane->dist-PLANESIDE_EPSILON)
00548 side |= PSIDE_BACK;
00549 return side;
00550 }
00551
00552
00553
00554 for (i=0 ; i<3 ; i++)
00555 {
00556 if (plane->normal[i] < 0)
00557 {
00558 corners[0][i] = mins[i];
00559 corners[1][i] = maxs[i];
00560 }
00561 else
00562 {
00563 corners[1][i] = mins[i];
00564 corners[0][i] = maxs[i];
00565 }
00566 }
00567
00568 dist1 = DotProduct (plane->normal, corners[0]) - plane->dist;
00569 dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
00570 side = 0;
00571 if (dist1 >= PLANESIDE_EPSILON)
00572 side = PSIDE_FRONT;
00573 if (dist2 < PLANESIDE_EPSILON)
00574 side |= PSIDE_BACK;
00575
00576 return side;
00577 }
00578 #else
00579 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, plane_t *p)
00580 {
00581 float dist1, dist2;
00582 int sides;
00583
00584
00585 if (p->type < 3)
00586 {
00587 sides = 0;
00588 if (emaxs[p->type] > p->dist+PLANESIDE_EPSILON) sides |= PSIDE_FRONT;
00589 if (emins[p->type] < p->dist-PLANESIDE_EPSILON) sides |= PSIDE_BACK;
00590 return sides;
00591 }
00592
00593
00594 switch (p->signbits)
00595 {
00596 case 0:
00597 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00598 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00599 break;
00600 case 1:
00601 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00602 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00603 break;
00604 case 2:
00605 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00606 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00607 break;
00608 case 3:
00609 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00610 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00611 break;
00612 case 4:
00613 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00614 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00615 break;
00616 case 5:
00617 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00618 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00619 break;
00620 case 6:
00621 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00622 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00623 break;
00624 case 7:
00625 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00626 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00627 break;
00628 default:
00629 dist1 = dist2 = 0;
00630
00631 break;
00632 }
00633
00634 sides = 0;
00635 if (dist1 - p->dist >= PLANESIDE_EPSILON) sides = PSIDE_FRONT;
00636 if (dist2 - p->dist < PLANESIDE_EPSILON) sides |= PSIDE_BACK;
00637
00638
00639
00640 return sides;
00641 }
00642 #endif
00643
00644
00645
00646
00647
00648
00649 int QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits)
00650 {
00651 int i, num;
00652 plane_t *plane;
00653 int s;
00654
00655 *numsplits = 0;
00656
00657 plane = &mapplanes[planenum];
00658
00659 #ifdef ME
00660
00661 if (plane->type < 3)
00662 {
00663 if (plane->dist + PLANESIDE_EPSILON < brush->mins[plane->type])
00664 return PSIDE_FRONT;
00665 if (plane->dist - PLANESIDE_EPSILON > brush->maxs[plane->type])
00666 return PSIDE_BACK;
00667 }
00668 #endif //ME*/
00669
00670
00671
00672 for (i = 0; i < brush->numsides; i++)
00673 {
00674 num = brush->sides[i].planenum;
00675 if (num >= MAX_MAPFILE_PLANES)
00676 Error ("bad planenum");
00677 if (num == planenum)
00678 return PSIDE_BACK|PSIDE_FACING;
00679 if (num == (planenum ^ 1) )
00680 return PSIDE_FRONT|PSIDE_FACING;
00681
00682 }
00683
00684
00685 s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
00686
00687
00688 if (s == PSIDE_BOTH)
00689 {
00690 *numsplits += 3;
00691 }
00692
00693 return s;
00694 }
00695
00696
00697
00698
00699
00700
00701 int TestBrushToPlanenum (bspbrush_t *brush, int planenum,
00702 int *numsplits, qboolean *hintsplit, int *epsilonbrush)
00703 {
00704 int i, j, num;
00705 plane_t *plane;
00706 int s = 0;
00707 winding_t *w;
00708 vec_t d, d_front, d_back;
00709 int front, back;
00710 int type;
00711 float dist;
00712
00713 *numsplits = 0;
00714 *hintsplit = false;
00715
00716 plane = &mapplanes[planenum];
00717
00718 #ifdef ME
00719
00720 type = plane->type;
00721 if (type < 3)
00722 {
00723 dist = plane->dist;
00724 if (dist + PLANESIDE_EPSILON < brush->mins[type]) return PSIDE_FRONT;
00725 if (dist - PLANESIDE_EPSILON > brush->maxs[type]) return PSIDE_BACK;
00726 if (brush->mins[type] < dist - PLANESIDE_EPSILON &&
00727 brush->maxs[type] > dist + PLANESIDE_EPSILON) s = PSIDE_BOTH;
00728 }
00729
00730 if (s != PSIDE_BOTH)
00731 #endif //ME
00732 {
00733
00734
00735 for (i = 0; i < brush->numsides; i++)
00736 {
00737 num = brush->sides[i].planenum;
00738 if (num >= MAX_MAPFILE_PLANES) Error ("bad planenum");
00739 if (num == planenum)
00740 {
00741
00742 brush->sides[i].flags |= SFL_TESTED;
00743 return PSIDE_BACK|PSIDE_FACING;
00744 }
00745 if (num == (planenum ^ 1) )
00746 {
00747
00748 brush->sides[i].flags |= SFL_TESTED;
00749 return PSIDE_FRONT|PSIDE_FACING;
00750 }
00751 }
00752
00753
00754 s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
00755
00756 if (s != PSIDE_BOTH) return s;
00757 }
00758
00759
00760 d_front = d_back = 0;
00761
00762 for (i = 0; i < brush->numsides; i++)
00763 {
00764 if (brush->sides[i].texinfo == TEXINFO_NODE)
00765 continue;
00766 if (!(brush->sides[i].flags & SFL_VISIBLE))
00767 continue;
00768 w = brush->sides[i].winding;
00769 if (!w) continue;
00770 front = back = 0;
00771 for (j = 0; j < w->numpoints; j++)
00772 {
00773 d = DotProduct(w->p[j], plane->normal) - plane->dist;
00774 if (d > d_front) d_front = d;
00775 if (d < d_back) d_back = d;
00776 if (d > 0.1)
00777 front = 1;
00778 if (d < -0.1)
00779 back = 1;
00780 }
00781 if (front && back)
00782 {
00783 if ( !(brush->sides[i].surf & SURF_SKIP) )
00784 {
00785 (*numsplits)++;
00786 if (brush->sides[i].surf & SURF_HINT)
00787 {
00788 *hintsplit = true;
00789 }
00790 }
00791 }
00792 }
00793
00794 if ( (d_front > 0.0 && d_front < 1.0)
00795 || (d_back < 0.0 && d_back > -1.0) )
00796 (*epsilonbrush)++;
00797
00798 #if 0
00799 if (*numsplits == 0)
00800 {
00801 if (front) s = PSIDE_FRONT;
00802 else if (back) s = PSIDE_BACK;
00803 else s = 0;
00804 }
00805 #endif
00806
00807 return s;
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817 #define EDGE_LENGTH 0.2
00818 qboolean WindingIsTiny (winding_t *w)
00819 {
00820 #if 0
00821 if (WindingArea (w) < 1)
00822 return true;
00823 return false;
00824 #else
00825 int i, j;
00826 vec_t len;
00827 vec3_t delta;
00828 int edges;
00829
00830 edges = 0;
00831 for (i=0 ; i<w->numpoints ; i++)
00832 {
00833 j = i == w->numpoints - 1 ? 0 : i+1;
00834 VectorSubtract (w->p[j], w->p[i], delta);
00835 len = VectorLength (delta);
00836 if (len > EDGE_LENGTH)
00837 {
00838 if (++edges == 3)
00839 return false;
00840 }
00841 }
00842 return true;
00843 #endif
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853 qboolean WindingIsHuge (winding_t *w)
00854 {
00855 int i, j;
00856
00857 for (i=0 ; i<w->numpoints ; i++)
00858 {
00859 for (j=0 ; j<3 ; j++)
00860 if (w->p[i][j] < -BOGUS_RANGE+1 || w->p[i][j] > BOGUS_RANGE-1)
00861 return true;
00862 }
00863 return false;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872 void LeafNode(node_t *node, bspbrush_t *brushes)
00873 {
00874 bspbrush_t *b;
00875 int i;
00876
00877 node->side = NULL;
00878 node->planenum = PLANENUM_LEAF;
00879 node->contents = 0;
00880
00881 for (b = brushes; b; b = b->next)
00882 {
00883
00884
00885 if (b->original->contents & CONTENTS_SOLID)
00886 {
00887 for (i=0 ; i<b->numsides ; i++)
00888 if (b->sides[i].texinfo != TEXINFO_NODE)
00889 break;
00890 if (i == b->numsides)
00891 {
00892 node->contents = CONTENTS_SOLID;
00893 break;
00894 }
00895 }
00896 node->contents |= b->original->contents;
00897 }
00898
00899 if (create_aas)
00900 {
00901 node->expansionbboxes = 0;
00902 node->contents = 0;
00903 for (b = brushes; b; b = b->next)
00904 {
00905 node->expansionbboxes |= b->original->expansionbbox;
00906 node->contents |= b->original->contents;
00907 if (b->original->modelnum)
00908 node->modelnum = b->original->modelnum;
00909 }
00910 if (node->contents & CONTENTS_SOLID)
00911 {
00912 if (node->expansionbboxes != cfg.allpresencetypes)
00913 {
00914 node->contents &= ~CONTENTS_SOLID;
00915 }
00916 }
00917 }
00918
00919 node->brushlist = brushes;
00920 }
00921
00922
00923
00924
00925
00926
00927 void CheckPlaneAgainstParents (int pnum, node_t *node)
00928 {
00929 node_t *p;
00930
00931 for (p = node->parent; p; p = p->parent)
00932 {
00933 if (p->planenum == pnum) Error("Tried parent");
00934 }
00935 }
00936
00937
00938
00939
00940
00941
00942 qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
00943 {
00944 bspbrush_t *front, *back;
00945 qboolean good;
00946
00947 SplitBrush (node->volume, pnum, &front, &back);
00948
00949 good = (front && back);
00950
00951 if (front) FreeBrush (front);
00952 if (back) FreeBrush (back);
00953
00954 return good;
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 side_t *SelectSplitSide (bspbrush_t *brushes, node_t *node)
00966 {
00967 int value, bestvalue;
00968 bspbrush_t *brush, *test;
00969 side_t *side, *bestside;
00970 int i, pass, numpasses;
00971 int pnum;
00972 int s;
00973 int front, back, both, facing, splits;
00974 int bsplits;
00975 int bestsplits;
00976 int epsilonbrush;
00977 qboolean hintsplit = false;
00978
00979 bestside = NULL;
00980 bestvalue = -99999;
00981 bestsplits = 0;
00982
00983
00984
00985
00986
00987 numpasses = 2;
00988 for (pass = 0; pass < numpasses; pass++)
00989 {
00990 for (brush = brushes; brush; brush = brush->next)
00991 {
00992
00993
00994
00995
00996
00997 for (i = 0; i < brush->numsides; i++)
00998 {
00999 side = brush->sides + i;
01000
01001
01002 if (!side->winding)
01003 continue;
01004 if (side->texinfo == TEXINFO_NODE)
01005 continue;
01006 if (side->flags & SFL_TESTED)
01007 continue;
01008
01009
01010
01011
01012
01013
01014 if ((side->flags & SFL_CURVE) && (pass < 1))
01015 continue;
01016
01017 pnum = side->planenum;
01018 pnum &= ~1;
01019
01020 CheckPlaneAgainstParents (pnum, node);
01021
01022 if (!CheckPlaneAgainstVolume (pnum, node))
01023 continue;
01024
01025 front = 0;
01026 back = 0;
01027 both = 0;
01028 facing = 0;
01029 splits = 0;
01030 epsilonbrush = 0;
01031
01032
01033 for (test = brushes; test; test = test->next)
01034 {
01035 s = TestBrushToPlanenum (test, pnum, &bsplits, &hintsplit, &epsilonbrush);
01036
01037 splits += bsplits;
01038
01039
01040
01041 test->testside = s;
01042
01043 if (s & PSIDE_FACING) facing++;
01044 if (s & PSIDE_FRONT) front++;
01045 if (s & PSIDE_BACK) back++;
01046 if (s == PSIDE_BOTH) both++;
01047 }
01048
01049
01050 value = 5*facing - 5*splits - abs(front-back);
01051
01052
01053 if (mapplanes[pnum].type < 3)
01054 value+=5;
01055
01056 value -= epsilonbrush * 1000;
01057
01058
01059 if (hintsplit && !(side->surf & SURF_HINT) )
01060 value = -9999999;
01061
01062
01063
01064
01065 if (value > bestvalue)
01066 {
01067 bestvalue = value;
01068 bestside = side;
01069 bestsplits = splits;
01070 for (test = brushes; test ; test = test->next)
01071 test->side = test->testside;
01072 }
01073 }
01074 }
01075
01076
01077
01078 if (bestside)
01079 {
01080 if (pass > 1)
01081 {
01082 if (numthreads == 1) c_nonvis++;
01083 }
01084 if (pass > 0) node->detail_seperator = true;
01085 break;
01086 }
01087 }
01088
01089
01090
01091
01092 for (brush = brushes ; brush ; brush=brush->next)
01093 {
01094 for (i = 0; i < brush->numsides; i++)
01095 {
01096 brush->sides[i].flags &= ~SFL_TESTED;
01097 }
01098 }
01099
01100 return bestside;
01101 }
01102
01103
01104
01105
01106
01107
01108 int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane)
01109 {
01110 int i, j;
01111 winding_t *w;
01112 vec_t d, max;
01113 int side;
01114
01115 max = 0;
01116 side = PSIDE_FRONT;
01117 for (i=0 ; i<brush->numsides ; i++)
01118 {
01119 w = brush->sides[i].winding;
01120 if (!w)
01121 continue;
01122 for (j=0 ; j<w->numpoints ; j++)
01123 {
01124 d = DotProduct (w->p[j], plane->normal) - plane->dist;
01125 if (d > max)
01126 {
01127 max = d;
01128 side = PSIDE_FRONT;
01129 }
01130 if (-d > max)
01131 {
01132 max = -d;
01133 side = PSIDE_BACK;
01134 }
01135 }
01136 }
01137 return side;
01138 }
01139
01140
01141
01142
01143
01144
01145
01146
01147 void SplitBrush (bspbrush_t *brush, int planenum,
01148 bspbrush_t **front, bspbrush_t **back)
01149 {
01150 bspbrush_t *b[2];
01151 int i, j;
01152 winding_t *w, *cw[2], *midwinding;
01153 plane_t *plane, *plane2;
01154 side_t *s, *cs;
01155 float d, d_front, d_back;
01156
01157 *front = *back = NULL;
01158 plane = &mapplanes[planenum];
01159
01160
01161 d_front = d_back = 0;
01162 for (i=0 ; i<brush->numsides ; i++)
01163 {
01164 w = brush->sides[i].winding;
01165 if (!w)
01166 continue;
01167 for (j=0 ; j<w->numpoints ; j++)
01168 {
01169 d = DotProduct (w->p[j], plane->normal) - plane->dist;
01170 if (d > 0 && d > d_front)
01171 d_front = d;
01172 if (d < 0 && d < d_back)
01173 d_back = d;
01174 }
01175 }
01176
01177 if (d_front < 0.2)
01178 {
01179 *back = CopyBrush (brush);
01180 return;
01181 }
01182 if (d_back > -0.2)
01183 {
01184 *front = CopyBrush (brush);
01185 return;
01186 }
01187
01188
01189
01190 w = BaseWindingForPlane (plane->normal, plane->dist);
01191 for (i=0 ; i<brush->numsides && w ; i++)
01192 {
01193 plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
01194 ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0);
01195 }
01196
01197 if (!w || WindingIsTiny(w))
01198 {
01199 int side;
01200
01201 side = BrushMostlyOnSide (brush, plane);
01202 if (side == PSIDE_FRONT)
01203 *front = CopyBrush (brush);
01204 if (side == PSIDE_BACK)
01205 *back = CopyBrush (brush);
01206
01207 if (w) FreeWinding(w);
01208 return;
01209 }
01210
01211 if (WindingIsHuge (w))
01212 {
01213 Log_Write("WARNING: huge winding\n");
01214 }
01215
01216 midwinding = w;
01217
01218
01219
01220 for (i=0 ; i<2 ; i++)
01221 {
01222 b[i] = AllocBrush (brush->numsides+1);
01223 b[i]->original = brush->original;
01224 }
01225
01226
01227
01228 for (i=0 ; i<brush->numsides ; i++)
01229 {
01230 s = &brush->sides[i];
01231 w = s->winding;
01232 if (!w)
01233 continue;
01234 ClipWindingEpsilon (w, plane->normal, plane->dist,
01235 0 , &cw[0], &cw[1]);
01236 for (j=0 ; j<2 ; j++)
01237 {
01238 if (!cw[j])
01239 continue;
01240 #if 0
01241 if (WindingIsTiny (cw[j]))
01242 {
01243 FreeWinding (cw[j]);
01244 continue;
01245 }
01246 #endif
01247 cs = &b[j]->sides[b[j]->numsides];
01248 b[j]->numsides++;
01249 *cs = *s;
01250
01251
01252
01253 cs->winding = cw[j];
01254 cs->flags &= ~SFL_TESTED;
01255 }
01256 }
01257
01258
01259
01260
01261 for (i=0 ; i<2 ; i++)
01262 {
01263 BoundBrush (b[i]);
01264 for (j=0 ; j<3 ; j++)
01265 {
01266 if (b[i]->mins[j] < -MAX_MAP_BOUNDS || b[i]->maxs[j] > MAX_MAP_BOUNDS)
01267 {
01268 Log_Write("bogus brush after clip");
01269 break;
01270 }
01271 }
01272
01273 if (b[i]->numsides < 3 || j < 3)
01274 {
01275 FreeBrush (b[i]);
01276 b[i] = NULL;
01277 }
01278 }
01279
01280 if ( !(b[0] && b[1]) )
01281 {
01282 if (!b[0] && !b[1])
01283 Log_Write("split removed brush\r\n");
01284 else
01285 Log_Write("split not on both sides\r\n");
01286 if (b[0])
01287 {
01288 FreeBrush (b[0]);
01289 *front = CopyBrush (brush);
01290 }
01291 if (b[1])
01292 {
01293 FreeBrush (b[1]);
01294 *back = CopyBrush (brush);
01295 }
01296 return;
01297 }
01298
01299
01300 for (i=0 ; i<2 ; i++)
01301 {
01302 cs = &b[i]->sides[b[i]->numsides];
01303 b[i]->numsides++;
01304
01305 cs->planenum = planenum^i^1;
01306 cs->texinfo = TEXINFO_NODE;
01307 cs->flags &= ~SFL_VISIBLE;
01308 cs->flags &= ~SFL_TESTED;
01309 if (i==0)
01310 cs->winding = CopyWinding (midwinding);
01311 else
01312 cs->winding = midwinding;
01313 }
01314
01315 {
01316 vec_t v1;
01317 int i;
01318
01319 for (i = 0; i < 2; i++)
01320 {
01321 v1 = BrushVolume (b[i]);
01322 if (v1 < 1.0)
01323 {
01324 FreeBrush(b[i]);
01325 b[i] = NULL;
01326
01327 }
01328 }
01329 if (!b[0] && !b[1])
01330 {
01331 Log_Write("two tiny brushes\r\n");
01332 }
01333 }
01334
01335 *front = b[0];
01336 *back = b[1];
01337 }
01338
01339
01340
01341
01342
01343
01344 void SplitBrushList (bspbrush_t *brushes,
01345 node_t *node, bspbrush_t **front, bspbrush_t **back)
01346 {
01347 bspbrush_t *brush, *newbrush, *newbrush2;
01348 side_t *side;
01349 int sides;
01350 int i;
01351
01352 *front = *back = NULL;
01353
01354 for (brush = brushes; brush; brush = brush->next)
01355 {
01356 sides = brush->side;
01357
01358 if (sides == PSIDE_BOTH)
01359 {
01360 SplitBrush (brush, node->planenum, &newbrush, &newbrush2);
01361 if (newbrush)
01362 {
01363 newbrush->next = *front;
01364 *front = newbrush;
01365 }
01366 if (newbrush2)
01367 {
01368 newbrush2->next = *back;
01369 *back = newbrush2;
01370 }
01371 continue;
01372 }
01373
01374 newbrush = CopyBrush (brush);
01375
01376
01377
01378
01379 if (sides & PSIDE_FACING)
01380 {
01381