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
00027
00028
00029
00030
00031
00032
00033 int minplanenums[3];
00034 int maxplanenums[3];
00035
00036
00037
00038
00039
00040
00041
00042 void CheckBSPBrush(bspbrush_t *brush)
00043 {
00044 int i, j;
00045 plane_t *plane1, *plane2;
00046
00047
00048 for (i = 0; i < brush->numsides; i++)
00049 {
00050 for (j = 0; j < brush->numsides; j++)
00051 {
00052 if (i == j) continue;
00053 plane1 = &mapplanes[brush->sides[i].planenum];
00054 plane2 = &mapplanes[brush->sides[j].planenum];
00055
00056 if (WindingsNonConvex(brush->sides[i].winding,
00057 brush->sides[j].winding,
00058 plane1->normal, plane2->normal,
00059 plane1->dist, plane2->dist))
00060 {
00061 Log_Print("non convex brush");
00062 break;
00063 }
00064 }
00065 }
00066 BoundBrush(brush);
00067
00068 for (i = 0; i < 3; i++)
00069 {
00070 if (brush->mins[i] < -MAX_MAP_BOUNDS || brush->maxs[i] > MAX_MAP_BOUNDS)
00071 {
00072 Log_Print("brush: bounds out of range\n");
00073 Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, brush->mins[i], i, brush->maxs[i]);
00074 break;
00075 }
00076 if (brush->mins[i] > MAX_MAP_BOUNDS || brush->maxs[i] < -MAX_MAP_BOUNDS)
00077 {
00078 Log_Print("brush: no visible sides on brush\n");
00079 Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, brush->mins[i], i, brush->maxs[i]);
00080 break;
00081 }
00082 }
00083 }
00084
00085
00086
00087
00088
00089
00090 void BSPBrushWindings(bspbrush_t *brush)
00091 {
00092 int i, j;
00093 winding_t *w;
00094 plane_t *plane;
00095
00096 for (i = 0; i < brush->numsides; i++)
00097 {
00098 plane = &mapplanes[brush->sides[i].planenum];
00099 w = BaseWindingForPlane(plane->normal, plane->dist);
00100 for (j = 0; j < brush->numsides && w; j++)
00101 {
00102 if (i == j) continue;
00103 plane = &mapplanes[brush->sides[j].planenum^1];
00104 ChopWindingInPlace(&w, plane->normal, plane->dist, 0);
00105 }
00106 brush->sides[i].winding = w;
00107 }
00108 }
00109
00110
00111
00112
00113
00114
00115
00116 bspbrush_t *TryMergeBrushes(bspbrush_t *brush1, bspbrush_t *brush2)
00117 {
00118 int i, j, k, n, shared;
00119 side_t *side1, *side2, *cs;
00120 plane_t *plane1, *plane2;
00121 bspbrush_t *newbrush;
00122
00123
00124 for (i = 0; i < 3; i++)
00125 {
00126 if (brush1->mins[i] > brush2->maxs[i] + 2
00127 || brush1->maxs[i] < brush2->mins[i] - 2)
00128 {
00129 return NULL;
00130 }
00131 }
00132
00133 shared = 0;
00134
00135 for (i = 0; i < brush1->numsides; i++)
00136 {
00137 side1 = &brush1->sides[i];
00138
00139 for (k = 0; k < brush2->numsides; k++)
00140 {
00141 side2 = &brush2->sides[k];
00142 if (side1->planenum == (side2->planenum^1))
00143 {
00144 shared++;
00145
00146 if (shared > 1) return NULL;
00147 break;
00148 }
00149 }
00150 if (k < brush2->numsides) continue;
00151
00152 for (j = 0; j < brush2->numsides; j++)
00153 {
00154 side2 = &brush2->sides[j];
00155
00156 for (n = 0; n < brush1->numsides; n++)
00157 {
00158 side1 = &brush1->sides[n];
00159 if (side1->planenum == (side2->planenum^1)) break;
00160 }
00161 if (n < brush1->numsides) continue;
00162
00163 side1 = &brush1->sides[i];
00164
00165
00166 if (side1->planenum == side2->planenum)
00167 {
00168 if (side1->texinfo != TEXINFO_NODE &&
00169 side2->texinfo != TEXINFO_NODE &&
00170 side1->texinfo != side2->texinfo) return NULL;
00171 continue;
00172 }
00173
00174 plane1 = &mapplanes[side1->planenum];
00175 plane2 = &mapplanes[side2->planenum];
00176
00177 if (WindingsNonConvex(side1->winding, side2->winding,
00178 plane1->normal, plane2->normal,
00179 plane1->dist, plane2->dist))
00180 {
00181 return NULL;
00182 }
00183 }
00184 }
00185 newbrush = AllocBrush(brush1->numsides + brush2->numsides);
00186 newbrush->original = brush1->original;
00187 newbrush->numsides = 0;
00188
00189
00190 for (i = 0; i < brush1->numsides; i++)
00191 {
00192 side1 = &brush1->sides[i];
00193
00194 for (n = 0; n < brush2->numsides; n++)
00195 {
00196 side2 = &brush2->sides[n];
00197
00198 if (side1->planenum == side2->planenum)
00199 {
00200 if (side1->texinfo == TEXINFO_NODE) side1->texinfo = side2->texinfo;
00201 if (side2->texinfo == TEXINFO_NODE) side2->texinfo = side1->texinfo;
00202 }
00203 }
00204 }
00205
00206 for (i = 0; i < brush1->numsides; i++)
00207 {
00208 side1 = &brush1->sides[i];
00209
00210 for (n = 0; n < brush2->numsides; n++)
00211 {
00212 side2 = &brush2->sides[n];
00213 if (side1->planenum == (side2->planenum ^ 1)) break;
00214 }
00215 if (n < brush2->numsides) continue;
00216
00217 for (n = 0; n < newbrush->numsides; n++)
00218 {
00219 cs = &newbrush->sides[n];
00220 if (cs->planenum == side1->planenum)
00221 {
00222 Log_Print("brush duplicate plane\n");
00223 break;
00224 }
00225 }
00226 if (n < newbrush->numsides) continue;
00227
00228 cs = &newbrush->sides[newbrush->numsides];
00229 newbrush->numsides++;
00230 *cs = *side1;
00231 }
00232 for (j = 0; j < brush2->numsides; j++)
00233 {
00234 side2 = &brush2->sides[j];
00235 for (n = 0; n < brush1->numsides; n++)
00236 {
00237 side1 = &brush1->sides[n];
00238
00239 if (side2->planenum == side1->planenum) break;
00240
00241 if (side2->planenum == (side1->planenum ^ 1)) break;
00242 }
00243 if (n < brush1->numsides) continue;
00244
00245 for (n = 0; n < newbrush->numsides; n++)
00246 {
00247 cs = &newbrush->sides[n];
00248 if (cs->planenum == side2->planenum)
00249 {
00250 Log_Print("brush duplicate plane\n");
00251 break;
00252 }
00253 }
00254 if (n < newbrush->numsides) continue;
00255
00256 cs = &newbrush->sides[newbrush->numsides];
00257 newbrush->numsides++;
00258 *cs = *side2;
00259 }
00260 BSPBrushWindings(newbrush);
00261 BoundBrush(newbrush);
00262 CheckBSPBrush(newbrush);
00263 return newbrush;
00264 }
00265
00266
00267
00268
00269
00270
00271 bspbrush_t *MergeBrushes(bspbrush_t *brushlist)
00272 {
00273 int nummerges, merged;
00274 bspbrush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
00275 bspbrush_t *lastb2;
00276
00277 if (!brushlist) return NULL;
00278
00279 qprintf("%5d brushes merged", nummerges = 0);
00280 do
00281 {
00282 for (tail = brushlist; tail; tail = tail->next)
00283 {
00284 if (!tail->next) break;
00285 }
00286 merged = 0;
00287 newbrushlist = NULL;
00288 for (b1 = brushlist; b1; b1 = brushlist)
00289 {
00290 lastb2 = b1;
00291 for (b2 = b1->next; b2; b2 = b2->next)
00292 {
00293
00294 if (b1->original->contents != b2->original->contents ||
00295 b1->original->expansionbbox != b2->original->expansionbbox) newbrush = NULL;
00296 else newbrush = TryMergeBrushes(b1, b2);
00297 if (newbrush)
00298 {
00299 tail->next = newbrush;
00300 lastb2->next = b2->next;
00301 brushlist = brushlist->next;
00302 FreeBrush(b1);
00303 FreeBrush(b2);
00304 for (tail = brushlist; tail; tail = tail->next)
00305 {
00306 if (!tail->next) break;
00307 }
00308 merged++;
00309 qprintf("\r%5d", nummerges++);
00310 break;
00311 }
00312 lastb2 = b2;
00313 }
00314
00315 if (!b2)
00316 {
00317 brushlist = brushlist->next;
00318
00319 b1->next = newbrushlist;
00320 newbrushlist = b1;
00321 }
00322 }
00323 brushlist = newbrushlist;
00324 } while(merged);
00325 qprintf("\n");
00326 return newbrushlist;
00327 }
00328
00329
00330
00331
00332
00333
00334 void SplitBrush2 (bspbrush_t *brush, int planenum,
00335 bspbrush_t **front, bspbrush_t **back)
00336 {
00337 SplitBrush (brush, planenum, front, back);
00338 #if 0
00339 if (*front && (*front)->sides[(*front)->numsides-1].texinfo == -1)
00340 (*front)->sides[(*front)->numsides-1].texinfo = (*front)->sides[0].texinfo;
00341 if (*back && (*back)->sides[(*back)->numsides-1].texinfo == -1)
00342 (*back)->sides[(*back)->numsides-1].texinfo = (*back)->sides[0].texinfo;
00343 #endif
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 bspbrush_t *SubtractBrush (bspbrush_t *a, bspbrush_t *b)
00355 {
00356 int i;
00357 bspbrush_t *front, *back;
00358 bspbrush_t *out, *in;
00359
00360 in = a;
00361 out = NULL;
00362 for (i = 0; i < b->numsides && in; i++)
00363 {
00364 SplitBrush2(in, b->sides[i].planenum, &front, &back);
00365 if (in != a) FreeBrush(in);
00366 if (front)
00367 {
00368 front->next = out;
00369 out = front;
00370 }
00371 in = back;
00372 }
00373 if (in)
00374 {
00375 FreeBrush (in);
00376 }
00377 else
00378 {
00379 FreeBrushList (out);
00380 return a;
00381 }
00382 return out;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 bspbrush_t *IntersectBrush (bspbrush_t *a, bspbrush_t *b)
00395 {
00396 int i;
00397 bspbrush_t *front, *back;
00398 bspbrush_t *in;
00399
00400 in = a;
00401 for (i=0 ; i<b->numsides && in ; i++)
00402 {
00403 SplitBrush2(in, b->sides[i].planenum, &front, &back);
00404 if (in != a) FreeBrush(in);
00405 if (front) FreeBrush(front);
00406 in = back;
00407 }
00408
00409 if (in == a) return NULL;
00410
00411 in->next = NULL;
00412 return in;
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422 qboolean BrushesDisjoint (bspbrush_t *a, bspbrush_t *b)
00423 {
00424 int i, j;
00425
00426
00427 for (i=0 ; i<3 ; i++)
00428 if (a->mins[i] >= b->maxs[i]
00429 || a->maxs[i] <= b->mins[i])
00430 return true;
00431
00432
00433 for (i=0 ; i<a->numsides ; i++)
00434 {
00435 for (j=0 ; j<b->numsides ; j++)
00436 {
00437 if (a->sides[i].planenum ==
00438 (b->sides[j].planenum^1) )
00439 return true;
00440 }
00441 }
00442
00443 return false;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 int IntersectionContents (int c1, int c2)
00455 {
00456 int out;
00457
00458 out = c1 | c2;
00459
00460 if (out & CONTENTS_SOLID) out = CONTENTS_SOLID;
00461
00462 return out;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471 bspbrush_t *ClipBrushToBox(bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs)
00472 {
00473 int i, j;
00474 bspbrush_t *front, *back;
00475 int p;
00476
00477 for (j=0 ; j<2 ; j++)
00478 {
00479 if (brush->maxs[j] > clipmaxs[j])
00480 {
00481 SplitBrush (brush, maxplanenums[j], &front, &back);
00482 if (front)
00483 FreeBrush (front);
00484 brush = back;
00485 if (!brush)
00486 return NULL;
00487 }
00488 if (brush->mins[j] < clipmins[j])
00489 {
00490 SplitBrush (brush, minplanenums[j], &front, &back);
00491 if (back)
00492 FreeBrush (back);
00493 brush = front;
00494 if (!brush)
00495 return NULL;
00496 }
00497 }
00498
00499
00500
00501 for (i=0 ; i<brush->numsides ; i++)
00502 {
00503 p = brush->sides[i].planenum & ~1;
00504 if (p == maxplanenums[0] || p == maxplanenums[1]
00505 || p == minplanenums[0] || p == minplanenums[1])
00506 {
00507 brush->sides[i].texinfo = TEXINFO_NODE;
00508 brush->sides[i].flags &= ~SFL_VISIBLE;
00509 }
00510 }
00511 return brush;
00512 }
00513
00514
00515
00516
00517
00518
00519 bspbrush_t *MakeBspBrushList(int startbrush, int endbrush,
00520 vec3_t clipmins, vec3_t clipmaxs)
00521 {
00522 mapbrush_t *mb;
00523 bspbrush_t *brushlist, *newbrush;
00524 int i, j;
00525 int c_faces;
00526 int c_brushes;
00527 int numsides;
00528 int vis;
00529 vec3_t normal;
00530 float dist;
00531
00532 for (i=0 ; i<2 ; i++)
00533 {
00534 VectorClear (normal);
00535 normal[i] = 1;
00536 dist = clipmaxs[i];
00537 maxplanenums[i] = FindFloatPlane(normal, dist);
00538 dist = clipmins[i];
00539 minplanenums[i] = FindFloatPlane(normal, dist);
00540 }
00541
00542 brushlist = NULL;
00543 c_faces = 0;
00544 c_brushes = 0;
00545
00546 for (i=startbrush ; i<endbrush ; i++)
00547 {
00548 mb = &mapbrushes[i];
00549
00550 numsides = mb->numsides;
00551 if (!numsides)
00552 continue;
00553
00554
00555 vis = 0;
00556 for (j=0 ; j<numsides ; j++)
00557 if ((mb->original_sides[j].flags & SFL_VISIBLE) && mb->original_sides[j].winding)
00558 vis++;
00559 #if 0
00560 if (!vis)
00561 continue;
00562 #endif
00563
00564 for (j=0 ; j<3 ; j++)
00565 if (mb->mins[j] >= clipmaxs[j]
00566 || mb->maxs[j] <= clipmins[j])
00567 break;
00568 if (j != 3)
00569 continue;
00570
00571
00572
00573
00574 newbrush = AllocBrush (mb->numsides);
00575 newbrush->original = mb;
00576 newbrush->numsides = mb->numsides;
00577 memcpy (newbrush->sides, mb->original_sides, numsides*sizeof(side_t));
00578 for (j=0 ; j<numsides ; j++)
00579 {
00580 if (newbrush->sides[j].winding)
00581 newbrush->sides[j].winding = CopyWinding (newbrush->sides[j].winding);
00582 if (newbrush->sides[j].surf & SURF_HINT)
00583 newbrush->sides[j].flags |= SFL_VISIBLE;
00584 }
00585 VectorCopy (mb->mins, newbrush->mins);
00586 VectorCopy (mb->maxs, newbrush->maxs);
00587
00588
00589
00590
00591 newbrush = ClipBrushToBox (newbrush, clipmins, clipmaxs);
00592 if (!newbrush)
00593 continue;
00594
00595 c_faces += vis;
00596 c_brushes++;
00597
00598 newbrush->next = brushlist;
00599 brushlist = newbrush;
00600 }
00601
00602 return brushlist;
00603 }
00604
00605
00606
00607
00608
00609
00610 bspbrush_t *AddBrushListToTail (bspbrush_t *list, bspbrush_t *tail)
00611 {
00612 bspbrush_t *walk, *next;
00613
00614 for (walk=list ; walk ; walk=next)
00615 {
00616 next = walk->next;
00617 walk->next = NULL;
00618 tail->next = walk;
00619 tail = walk;
00620 }
00621 return tail;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630 bspbrush_t *CullList(bspbrush_t *list, bspbrush_t *skip1)
00631 {
00632 bspbrush_t *newlist;
00633 bspbrush_t *next;
00634
00635 newlist = NULL;
00636
00637 for ( ; list ; list = next)
00638 {
00639 next = list->next;
00640 if (list == skip1)
00641 {
00642 FreeBrush (list);
00643 continue;
00644 }
00645 list->next = newlist;
00646 newlist = list;
00647 }
00648 return newlist;
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 qboolean BrushGE (bspbrush_t *b1, bspbrush_t *b2)
00700 {
00701 #ifdef ME
00702 if (create_aas)
00703 {
00704 if (b1->original->expansionbbox != b2->original->expansionbbox)
00705 {
00706 return false;
00707 }
00708
00709
00710 if ( (b1->original->contents & CONTENTS_LADDER)
00711 && !(b2->original->contents & CONTENTS_LADDER))
00712 {
00713 return false;
00714 }
00715 }
00716 #endif //ME
00717
00718 if ( (b1->original->contents & CONTENTS_DETAIL)
00719 && !(b2->original->contents & CONTENTS_DETAIL) )
00720 {
00721 return false;
00722 }
00723 if (b1->original->contents & CONTENTS_SOLID)
00724 {
00725 return true;
00726 }
00727 return false;
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737 bspbrush_t *ChopBrushes (bspbrush_t *head)
00738 {
00739 bspbrush_t *b1, *b2, *next;
00740 bspbrush_t *tail;
00741 bspbrush_t *keep;
00742 bspbrush_t *sub, *sub2;
00743 int c1, c2;
00744 int num_csg_iterations;
00745
00746 Log_Print("-------- Brush CSG ---------\n");
00747 Log_Print("%6d original brushes\n", CountBrushList (head));
00748
00749 num_csg_iterations = 0;
00750 qprintf("%6d output brushes", num_csg_iterations);
00751
00752 #if 0
00753 if (startbrush == 0)
00754 WriteBrushList ("before.gl", head, false);
00755 #endif
00756 keep = NULL;
00757
00758 newlist:
00759
00760 if (!head) return NULL;
00761
00762 for (tail = head; tail->next; tail = tail->next)
00763 ;
00764
00765 for (b1=head ; b1 ; b1=next)
00766 {
00767 next = b1->next;
00768
00769
00770 if (cancelconversion)
00771 {
00772 b1->next = keep;
00773 keep = b1;
00774 continue;
00775 }
00776
00777 for (b2 = b1->next; b2; b2 = b2->next)
00778 {
00779 if (BrushesDisjoint (b1, b2))
00780 continue;
00781
00782 sub = NULL;
00783 sub2 = NULL;
00784 c1 = 999999;
00785 c2 = 999999;
00786
00787 if (BrushGE (b2, b1))
00788 {
00789 sub = SubtractBrush (b1, b2);
00790 if (sub == b1)
00791 {
00792 continue;
00793 }
00794 if (!sub)
00795 {
00796 head = CullList (b1, b1);
00797 goto newlist;
00798 }
00799 c1 = CountBrushList (sub);
00800 }
00801
00802 if ( BrushGE (b1, b2) )
00803 {
00804 sub2 = SubtractBrush (b2, b1);
00805 if (sub2 == b2)
00806 continue;
00807 if (!sub2)
00808 {
00809 FreeBrushList (sub);
00810 head = CullList (b1, b2);
00811 goto newlist;
00812 }
00813 c2 = CountBrushList (sub2);
00814 }
00815
00816 if (!sub && !sub2)
00817 continue;
00818
00819
00820
00821 if (c1 > 1 && c2 > 1)
00822 {
00823 if (sub2)
00824 FreeBrushList (sub2);
00825 if (sub)
00826 FreeBrushList (sub);
00827 continue;
00828 }
00829
00830 if (c1 < c2)
00831 {
00832 if (sub2) FreeBrushList (sub2);
00833 tail = AddBrushListToTail (sub, tail);
00834 head = CullList (b1, b1);
00835 goto newlist;
00836 }
00837 else
00838 {
00839 if (sub) FreeBrushList (sub);
00840 tail = AddBrushListToTail (sub2, tail);
00841 head = CullList (b1, b2);
00842 goto newlist;
00843 }
00844 }
00845
00846 if (!b2)
00847 {
00848 b1->next = keep;
00849 keep = b1;
00850 }
00851 num_csg_iterations++;
00852 qprintf("\r%6d", num_csg_iterations);
00853 }
00854
00855 if (cancelconversion) return keep;
00856
00857 qprintf("\n");
00858 Log_Write("%6d output brushes\r\n", num_csg_iterations);
00859
00860 #if 0
00861 {
00862 WriteBrushList ("after.gl", keep, false);
00863 WriteBrushMap ("after.map", keep);
00864 }
00865 #endif
00866
00867 return keep;
00868 }
00869
00870
00871
00872
00873
00874
00875 bspbrush_t *InitialBrushList (bspbrush_t *list)
00876 {
00877 bspbrush_t *b;
00878 bspbrush_t *out, *newb;
00879 int i;
00880
00881
00882 out = NULL;
00883 for (b=list ; b ; b=b->next)
00884 {
00885 #if 0
00886 for (i=0 ; i<b->numsides ; i++)
00887 if (b->sides[i].flags & SFL_VISIBLE)
00888 break;
00889 if (i == b->numsides)
00890 continue;
00891 #endif
00892 newb = CopyBrush (b);
00893 newb->next = out;
00894 out = newb;
00895
00896
00897
00898 for (i=0 ; i<b->numsides ; i++)
00899 {
00900 newb->sides[i].original = &b->sides[i];
00901
00902 b->sides[i].flags &= ~SFL_VISIBLE;
00903 }
00904 }
00905
00906 return out;
00907 }
00908
00909
00910
00911
00912
00913
00914 bspbrush_t *OptimizedBrushList (bspbrush_t *list)
00915 {
00916 bspbrush_t *b;
00917 bspbrush_t *out, *newb;
00918 int i;
00919
00920
00921 out = NULL;
00922 for (b=list ; b ; b=b->next)
00923 {
00924 for (i=0 ; i<b->numsides ; i++)
00925 if (b->sides[i].flags & SFL_VISIBLE)
00926 break;
00927 if (i == b->numsides)
00928 continue;
00929 newb = CopyBrush (b);
00930 newb->next = out;
00931 out = newb;
00932 }
00933
00934
00935 return out;
00936 }
00937
00938
00939
00940
00941
00942
00943 tree_t *ProcessWorldBrushes(int brush_start, int brush_end)
00944 {
00945 bspbrush_t *brushes;
00946 tree_t *tree;
00947 node_t *node;
00948 vec3_t mins, maxs;
00949
00950
00951 mins[0] = map_mins[0] - 8;
00952 mins[1] = map_mins[1] - 8;
00953 mins[2] = map_mins[2] - 8;
00954
00955 maxs[0] = map_maxs[0] + 8;
00956 maxs[1] = map_maxs[1] + 8;
00957 maxs[2] = map_maxs[2] + 8;
00958
00959
00960 ResetBrushBSP();
00961
00962
00963
00964
00965
00966
00967 brushes = MakeBspBrushList(brush_start, brush_end, mins, maxs);
00968
00969
00970 if (!brushes)
00971 {
00972 node = AllocNode ();
00973 node->planenum = PLANENUM_LEAF;
00974 node->contents = CONTENTS_SOLID;
00975
00976 tree = Tree_Alloc();
00977 tree->headnode = node;
00978 VectorCopy(mins, tree->mins);
00979 VectorCopy(maxs, tree->maxs);
00980 }
00981 else
00982 {
00983
00984
00985 if (!nocsg)
00986 {
00987 brushes = ChopBrushes(brushes);
00988
00989
00990
00991
00992
00993 }
00994
00995 if (cancelconversion)
00996 {
00997 FreeBrushList(brushes);
00998 return NULL;
00999 }
01000
01001 tree = BrushBSP(brushes, mins, maxs);
01002 }
01003
01004 return tree;
01005 }