UFO: Alien Invasion
Loading...
Searching...
No Matches
bspbrush.cpp
Go to the documentation of this file.
1
4
5/*
6Copyright (C) 1997-2001 Id Software, Inc.
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23*/
24
25#include "bsp.h"
26#include "map.h"
27
28extern int c_nodes;
29extern int c_nonvis;
31
32
36static void BoundBrush (bspbrush_t* brush)
37{
38 brush->brBox.setNegativeVolume();
39 for (int i = 0; i < brush->numsides; i++) {
40 winding_t* w = brush->sides[i].winding;
41 if (!w)
42 continue;
43 for (int j = 0; j < w->numpoints; j++)
44 brush->brBox.add(w->p[j]);
45 }
46}
47
48
53static void CreateBrushWindings (bspbrush_t* brush)
54{
55 for (int i = 0; i < brush->numsides; i++) {
56 side_t* side = &brush->sides[i];
57 const plane_t* plane = &mapplanes[side->planenum];
58
59 /* evidence that winding_t represents a hessian normal plane */
60 winding_t* w = BaseWindingForPlane(plane->normal, plane->dist);
61
62 for (int j = 0; j < brush->numsides && w; j++) {
63 if (i == j)
64 continue;
65 /* back side clipaway */
66 if (brush->sides[j].planenum == (side->planenum ^ 1))
67 continue;
68 if (brush->sides[j].bevel)
69 continue;
70 plane = &mapplanes[brush->sides[j].planenum ^ 1];
71 ChopWindingInPlace(&w, plane->normal, plane->dist, 0); /*CLIP_EPSILON); */
72
73 /* fix broken windings that would generate trifans */
74 if (!FixWinding(w))
75 Verb_Printf(VERB_EXTRA, "removed degenerated edge(s) from winding\n");
76 }
77
78 side->winding = w;
79 }
80
81 BoundBrush(brush);
82}
83
87bspbrush_t* BrushFromBounds (const vec3_t mins, const vec3_t maxs)
88{
89 vec3_t normal;
90
91 bspbrush_t* b = AllocBrush(6);
92 b->numsides = 6;
93 for (int i = 0; i < 3; i++) {
94 VectorClear(normal);
95 normal[i] = 1;
96 vec_t dist = maxs[i];
97 b->sides[i].planenum = FindOrCreateFloatPlane(normal, dist);
98
99 normal[i] = -1;
100 dist = -mins[i];
101 b->sides[3 + i].planenum = FindOrCreateFloatPlane(normal, dist);
102 }
103
105
106 return b;
107}
108
112static vec_t BrushVolume (const bspbrush_t* brush)
113{
114 int i;
115 const winding_t* w;
116 vec3_t corner;
117 vec_t volume;
118
119 if (!brush)
120 return 0;
121
122 /* grab the first valid point as the corner */
123 w = nullptr;
124 for (i = 0; i < brush->numsides; i++) {
125 w = brush->sides[i].winding;
126 if (w)
127 break;
128 }
129 if (!w)
130 return 0;
131 VectorCopy(w->p[0], corner);
132
133 /* make tetrahedrons to all other faces */
134 volume = 0;
135 for (; i < brush->numsides; i++) {
136 w = brush->sides[i].winding;
137 if (w) {
138 const plane_t* plane = &mapplanes[brush->sides[i].planenum];
139 const vec_t d = -(DotProduct(corner, plane->normal) - plane->dist);
140 const vec_t area = WindingArea(w);
141 volume += d * area;
142 }
143 }
144
145 volume /= 3;
146 return volume;
147}
148
153{
154 int c;
155
156 c = 0;
157 for (; brushes; brushes = brushes->next)
158 c++;
159 return c;
160}
161
166bspbrush_t* AllocBrush (int numsides)
167{
168 const size_t size = sizeof(bspbrush_t) + sizeof(side_t) * (numsides - STANDARD_NUMBER_OF_BRUSHSIDES);
169
170 if (threadstate.numthreads == 1)
172
173 return (bspbrush_t*)Mem_Alloc(size);
174}
175
179void FreeBrush (bspbrush_t* brushes)
180{
181 for (int i = 0; i < brushes->numsides; i++)
182 if (brushes->sides[i].winding)
183 FreeWinding(brushes->sides[i].winding);
184 Mem_Free(brushes);
185 if (threadstate.numthreads == 1)
187}
188
194{
195 bspbrush_t* next;
196
197 for (; brushes; brushes = next) {
198 next = brushes->next;
199 FreeBrush(brushes);
200 }
201}
202
208{
209 const size_t size = sizeof(bspbrush_t) + sizeof(side_t) * (brush->numsides - STANDARD_NUMBER_OF_BRUSHSIDES);
210
211 bspbrush_t* newbrush = AllocBrush(brush->numsides);
212 memcpy(newbrush, brush, size);
213
214 for (int i = 0; i < brush->numsides; i++) {
215 const side_t* side = &brush->sides[i];
216 if (side->winding)
217 newbrush->sides[i].winding = CopyWinding(side->winding);
218 }
219
220 return newbrush;
221}
222
223
224static int TestBrushToPlanenum (bspbrush_t* brush, uint16_t planenum,
225 int* numsplits, bool* hintsplit, int* epsilonbrush)
226{
227 int i, s;
228 plane_t* plane;
229 dBspPlane_t plane2;
230 vec_t d_front, d_back;
231 int front, back;
232
233 *numsplits = 0;
234 *hintsplit = false;
235
236 /* if the brush actually uses the planenum,
237 * we can tell the side for sure */
238 for (i = 0; i < brush->numsides; i++) {
239 const uint16_t num = brush->sides[i].planenum;
240 if (num == planenum)
241 return (PSIDE_BACK | PSIDE_FACING);
242 if (num == (planenum ^ 1))
243 return (PSIDE_FRONT | PSIDE_FACING);
244 }
245
246 /* box on plane side */
247 plane = &mapplanes[planenum];
248
249 /* Convert to cBspPlane */
250 VectorCopy(plane->normal, plane2.normal);
251 plane2.dist = plane->dist;
252 plane2.type = plane->type;
253 s = TR_BoxOnPlaneSide(brush->brBox.mins, brush->brBox.maxs, &plane2);
254
255 if (s != PSIDE_BOTH)
256 return s;
257
258 /* if both sides, count the visible faces split */
259 d_front = d_back = 0;
260
261 for (i = 0; i < brush->numsides; i++) {
262 const side_t* side = &brush->sides[i];
263 const winding_t* w;
264 if (side->texinfo == TEXINFO_NODE)
265 continue; /* on node, don't worry about splits */
266 if (!side->visible)
267 continue; /* we don't care about non-visible */
268 w = side->winding;
269 if (!w)
270 continue;
271 front = back = 0;
272 for (int j = 0; j < w->numpoints; j++) {
273 const vec_t d = DotProduct(w->p[j], plane->normal) - plane->dist;
274 if (d > d_front)
275 d_front = d;
276 if (d < d_back)
277 d_back = d;
278
279 if (d > 0.1) /* PLANESIDE_EPSILON) */
280 front = 1;
281 else if (d < -0.1) /* PLANESIDE_EPSILON) */
282 back = 1;
283 }
284 if (front && back) {
285 (*numsplits)++;
286 if (side->surfaceFlags & SURF_HINT)
287 *hintsplit = true;
288 }
289 }
290
291 if ((d_front > 0.0 && d_front < 1.0) || (d_back < 0.0 && d_back > -1.0))
292 (*epsilonbrush)++;
293
294 return s;
295}
296
301{
302 bspbrush_t* b;
303 uint32_t contentFlags = 0;
304
305 for (b = brushlist; b; b = b->next) {
306 /* if the brush is solid and all of its sides are on nodes,
307 * it eats everything */
308 if ((b->original->contentFlags & CONTENTS_SOLID) && !(b->original->contentFlags & CONTENTS_PASSABLE)) {
309 int i;
310 for (i = 0; i < b->numsides; i++)
311 if (b->sides[i].texinfo != TEXINFO_NODE)
312 break;
313 if (i == b->numsides) {
314 contentFlags = CONTENTS_SOLID;
315 break;
316 }
317 }
318 contentFlags |= b->original->contentFlags;
319 }
320
321 return contentFlags;
322}
323
328static int BrushMostlyOnSide (const bspbrush_t* brush, const plane_t* plane)
329{
330 vec_t max = 0;
331 int side = PSIDE_FRONT;
332
333 for (int i = 0; i < brush->numsides; i++) {
334 const winding_t* w = brush->sides[i].winding;
335 if (!w)
336 continue;
337 for (int j = 0; j < w->numpoints; j++) {
338 const vec_t d = DotProduct(w->p[j], plane->normal) - plane->dist;
339 if (d > max) {
340 max = d;
341 side = PSIDE_FRONT;
342 }
343 if (-d > max) {
344 max = -d;
345 side = PSIDE_BACK;
346 }
347 }
348 }
349 return side;
350}
351
352#define TESTING_MOCK_SPLIT 1
353#if TESTING_MOCK_SPLIT
357static bool DoesPlaneSplitBrush (const bspbrush_t* brush, int planenum)
358{
359 plane_t* plane = &mapplanes[planenum];
360 int front_cnt = 0, back_cnt = 0;
361
362 /* check all points */
363 for (int i = 0; i < brush->numsides; i++) {
364 winding_t* w = brush->sides[i].winding;
365 if (!w)
366 continue;
367 for (int j = 0; j < w->numpoints; j++) {
368 const float d = DotProduct(w->p[j], plane->normal) - plane->dist;
369 if (d > 0.1f) /* PLANESIDE_EPSILON) */
370 front_cnt++;
371 if (d < -0.1f) /* PLANESIDE_EPSILON) */
372 back_cnt++;
373 }
374 }
375
376 /* if brush vertices are both in front and back of given plane, in splits brush */
377 return front_cnt && back_cnt ;
378}
379#endif
380
381#if TESTING_MOCK_SPLIT
382/* DoesPlaneSplitBrush does not yet work for all maps, namely city_train.map
383 * Until we know why, let's use the old stuff. */
384static bool CheckPlaneAgainstVolume (int pnum, const bspbrush_t* volume)
385{
386 bool good;
387
388 good = DoesPlaneSplitBrush(volume, pnum);
389
390 return good;
391}
392
393#else
394static bool CheckPlaneAgainstVolume (uint16_t pnum, const bspbrush_t* volume)
395{
396 bspbrush_t* front, *back;
397 bool good;
398
399 SplitBrush(volume, pnum, &front, &back);
400
401 good = (front && back);
402
403 if (front)
404 FreeBrush(front);
405 if (back)
406 FreeBrush(back);
407
408 return good;
409}
410#endif
417{
418 int value;
419 bspbrush_t* brush, *test;
420 int i, pass;
421 int front, back, both, facing, splits;
422 int bsplits, epsilonbrush;
423 bool hintsplit;
424
425 if (!volume)
426 return nullptr; /* can't split empty brush */
427
428 side_t* bestside = nullptr;
429 int bestvalue = -99999;
430
437 int numpasses = 4;
438 for (pass = 0; pass < numpasses; pass++) {
439 for (brush = brushes; brush; brush = brush->next) {
440 if ((pass & 1) && !(brush->original->contentFlags & CONTENTS_DETAIL))
441 continue;
442 if (!(pass & 1) && (brush->original->contentFlags & CONTENTS_DETAIL))
443 continue;
444 for (i = 0; i < brush->numsides; i++) {
445 uint16_t pnum;
446 side_t* side = &brush->sides[i];
447 if (side->bevel)
448 continue; /* never use a bevel as a spliter */
449 if (!side->winding)
450 continue; /* nothing visible, so it can't split */
451 if (side->texinfo == TEXINFO_NODE)
452 continue; /* already a node splitter */
453 if (side->tested)
454 continue; /* we already have metrics for this plane */
455 if (side->surfaceFlags & SURF_SKIP)
456 continue; /* skip surfaces are never chosen */
457 if (side->visible ^ (pass < 2))
458 continue; /* only check visible faces on first pass */
459
460 pnum = side->planenum;
461 pnum &= ~1; /* always use positive facing plane */
462
463 if (!CheckPlaneAgainstVolume(pnum, volume))
464 continue; /* would produce a tiny volume */
465
466 front = 0;
467 back = 0;
468 both = 0;
469 facing = 0;
470 splits = 0;
471 epsilonbrush = 0;
472 hintsplit = false;
473
474 for (test = brushes; test; test = test->next) {
475 const int s = TestBrushToPlanenum(test, pnum, &bsplits, &hintsplit, &epsilonbrush);
476
477 splits += bsplits;
478 if (bsplits && (s & PSIDE_FACING))
479 Sys_Error("PSIDE_FACING with splits");
480
481 test->testside = s;
482 /* if the brush shares this face, don't bother
483 * testing that facenum as a splitter again */
484 if (s & PSIDE_FACING) {
485 facing++;
486 for (int j = 0; j < test->numsides; j++) {
487 if ((test->sides[j].planenum &~ 1) == pnum)
488 test->sides[j].tested = true;
489 }
490 }
491 if (s & PSIDE_FRONT)
492 front++;
493 if (s & PSIDE_BACK)
494 back++;
495 if (s == PSIDE_BOTH)
496 both++;
497 }
498
499 /* give a value estimate for using this plane */
500
501 value = 5 * facing - 5 * splits - abs(front - back);
502 if (AXIAL(&mapplanes[pnum]))
503 value += 5; /* axial is better */
504 value -= epsilonbrush * 1000; /* avoid! */
505
506 /* never split a hint side except with another hint */
507 if (hintsplit && !(side->surfaceFlags & SURF_HINT))
508 value = -9999999;
509
510 /* save off the side test so we don't need
511 * to recalculate it when we actually seperate
512 * the brushes */
513 if (value > bestvalue) {
514 bestvalue = value;
515 bestside = side;
516 for (test = brushes; test; test = test->next)
517 test->side = test->testside;
518 }
519 }
520 }
521
522 /* if we found a good plane, don't bother trying any other passes */
523 if (bestside) {
524 if (pass > 1) {
525 if (threadstate.numthreads == 1)
526 c_nonvis++;
527 }
528 break;
529 }
530 }
531
532 /* clear all the tested flags we set */
533 for (brush = brushes; brush; brush = brush->next) {
534 for (i = 0; i < brush->numsides; i++)
535 brush->sides[i].tested = false;
536 }
537
538 return bestside;
539}
540
544void SplitBrush (const bspbrush_t* brush, uint16_t planenum, bspbrush_t** front, bspbrush_t** back)
545{
546 bspbrush_t* b[2];
547 int i, j;
548 winding_t* w, *cw[2], *midwinding;
549 plane_t* plane;
550 float d_front, d_back;
551
552 *front = *back = nullptr;
553 plane = &mapplanes[planenum];
554
555 /* check all points */
556 d_front = d_back = 0;
557 for (i = 0; i < brush->numsides; i++) {
558 w = brush->sides[i].winding;
559 if (!w)
560 continue;
561 for (j = 0; j < w->numpoints; j++) {
562 const float d = DotProduct(w->p[j], plane->normal) - plane->dist;
563 if (d > 0 && d > d_front)
564 d_front = d;
565 else if (d < 0 && d < d_back)
566 d_back = d;
567 }
568 }
569 if (d_front < 0.1) { /* PLANESIDE_EPSILON) */
570 /* only on back */
571 *back = CopyBrush(brush);
572 return;
573 }
574 if (d_back > -0.1) { /* PLANESIDE_EPSILON) */
575 /* only on front */
576 *front = CopyBrush(brush);
577 return;
578 }
579
580 /* create a new winding from the split plane */
581 w = BaseWindingForPlane(plane->normal, plane->dist);
582 for (i = 0; i < brush->numsides && w; i++) {
583 plane_t* plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
584 ChopWindingInPlace(&w, plane2->normal, plane2->dist, 0); /* PLANESIDE_EPSILON); */
585 }
586
587 /* the brush isn't really split */
588 if (!w || WindingIsTiny(w)) {
589 const int side = BrushMostlyOnSide(brush, plane);
590 if (side == PSIDE_FRONT)
591 *front = CopyBrush(brush);
592 else if (side == PSIDE_BACK)
593 *back = CopyBrush(brush);
594 return;
595 }
596
597 if (WindingIsHuge(w)) {
600 Com_Printf("WARNING: Large winding\n");
601 }
602
603 midwinding = w;
604
605 /* split it for real */
606 for (i = 0; i < 2; i++) {
607 b[i] = AllocBrush(brush->numsides + 1);
608 b[i]->original = brush->original;
609 }
610
611 /* split all the current windings */
612 for (i = 0; i < brush->numsides; i++) {
613 const side_t* s = &brush->sides[i];
614 w = s->winding;
615 if (!w)
616 continue;
617 ClipWindingEpsilon(w, plane->normal, plane->dist,
618 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
619 for (j = 0; j < 2; j++) {
620 side_t* cs;
621
622 if (!cw[j])
623 continue;
624
625 cs = &b[j]->sides[b[j]->numsides];
626 b[j]->numsides++;
627 *cs = *s;
628
629 cs->winding = cw[j];
630 cs->tested = false;
631 }
632 }
633
634 /* see if we have valid polygons on both sides */
635 for (i = 0; i < 2; i++) {
636 BoundBrush(b[i]);
637 for (j = 0; j < 3; j++) {
638 if (b[i]->brBox.mins[j] < -MAX_WORLD_WIDTH || b[i]->brBox.maxs[j] > MAX_WORLD_WIDTH) {
641 Verb_Printf(VERB_EXTRA, "bogus brush after clip\n");
642 break;
643 }
644 }
645
646 if (b[i]->numsides < 3 || j < 3) {
647 FreeBrush(b[i]);
648 b[i] = nullptr;
649 }
650 }
651
652 if (!(b[0] && b[1])) {
655 if (!b[0] && !b[1])
656 Verb_Printf(VERB_EXTRA, "split removed brush\n");
657 else
658 Verb_Printf(VERB_EXTRA, "split not on both sides\n");
659 if (b[0]) {
660 FreeBrush(b[0]);
661 *front = CopyBrush(brush);
662 }
663 if (b[1]) {
664 FreeBrush(b[1]);
665 *back = CopyBrush(brush);
666 }
667 return;
668 }
669
670 /* add the midwinding to both sides */
671 for (i = 0; i < 2; i++) {
672 side_t* cs = &b[i]->sides[b[i]->numsides];
673 b[i]->numsides++;
674
675 cs->planenum = planenum ^ i ^ 1;
676 cs->texinfo = TEXINFO_NODE;
677 cs->visible = false;
678 cs->tested = false;
679 if (i == 0)
680 cs->winding = CopyWinding(midwinding);
681 else
682 cs->winding = midwinding;
683 }
684
685 for (i = 0; i < 2; i++) {
686 const vec_t v1 = BrushVolume(b[i]);
687 if (v1 < 1.0) {
688 FreeBrush(b[i]);
689 b[i] = nullptr;
692 Verb_Printf(VERB_EXTRA, "tiny volume after clip\n");
693 }
694 }
695
696 *front = b[0];
697 *back = b[1];
698}
699
700void SplitBrushList (bspbrush_t* brushes, uint16_t planenum, bspbrush_t** front, bspbrush_t** back)
701{
702 bspbrush_t* brush;
703
704 *front = *back = nullptr;
705
706 for (brush = brushes; brush; brush = brush->next) {
707 const int sides = brush->side;
708 bspbrush_t* newbrush;
709
710 if (sides == PSIDE_BOTH) { /* split into two brushes */
711 bspbrush_t* newbrush2;
712 SplitBrush(brush, planenum, &newbrush, &newbrush2);
713 if (newbrush) {
714 newbrush->next = *front;
715 Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to front list.\n", newbrush->original->brushnum);
716 *front = newbrush;
717 }
718 if (newbrush2) {
719 newbrush2->next = *back;
720 Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to back list.\n", newbrush2->original->brushnum);
721 *back = newbrush2;
722 }
723 continue;
724 }
725
726 newbrush = CopyBrush(brush);
727
728 /* if the planenum is actually a part of the brush
729 * find the plane and flag it as used so it won't be tried
730 * as a splitter again */
731 if (sides & PSIDE_FACING) {
732 for (int i = 0; i < newbrush->numsides; i++) {
733 side_t* side = newbrush->sides + i;
734 if ((side->planenum & ~1) == planenum)
735 side->texinfo = TEXINFO_NODE;
736 }
737 }
738
739 if (sides & PSIDE_FRONT) {
740 newbrush->next = *front;
741 *front = newbrush;
742 Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to front list.\n", newbrush->original->brushnum);
743 continue;
744 }
745 if (sides & PSIDE_BACK) {
746 newbrush->next = *back;
747 Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to back list.\n", newbrush->original->brushnum);
748 *back = newbrush;
749 continue;
750 }
751 Verb_Printf(VERB_DUMP, "SplitBrushList: Brush %i fell off the map.\n", newbrush->original->brushnum);
752 }
753}
754
755
759void BrushlistCalcStats (bspbrush_t* brushlist, AABB& blBox)
760{
761 bspbrush_t* b;
762 int c_faces = 0, c_nonvisfaces = 0, c_brushes = 0;
763
764 for (b = brushlist; b; b = b->next) {
765 c_brushes++;
766
767 vec_t volume = BrushVolume(b);
768 if (volume < config.microvolume) {
769 Com_Printf("\nWARNING: entity %i, brush %i: microbrush, volume %.3g\n",
770 b->original->entitynum, b->original->brushnum, volume);
771 }
772
773 for (int i = 0; i < b->numsides; i++) {
774 side_t* side = &b->sides[i];
775 if (side->bevel)
776 continue;
777 if (!side->winding)
778 continue;
779 if (side->texinfo == TEXINFO_NODE)
780 continue;
781 if (side->visible)
782 c_faces++;
783 else
784 c_nonvisfaces++;
785 }
786
787 blBox.add(b->brBox);
788 }
789
790 Verb_Printf(VERB_EXTRA, "%5i brushes\n", c_brushes);
791 Verb_Printf(VERB_EXTRA, "%5i visible faces\n", c_faces);
792 Verb_Printf(VERB_EXTRA, "%5i nonvisible faces\n", c_nonvisfaces);
793}
plane_t mapplanes[MAX_MAP_PLANES]
Definition map.cpp:43
uint16_t FindOrCreateFloatPlane(vec3_t normal, vec_t dist)
Definition map.cpp:194
bspbrush_t * CopyBrush(const bspbrush_t *brush)
Duplicates the brush, the sides, and the windings.
Definition bspbrush.cpp:207
bspbrush_t * BrushFromBounds(const vec3_t mins, const vec3_t maxs)
Creates a new axial brush.
Definition bspbrush.cpp:87
static bool CheckPlaneAgainstVolume(int pnum, const bspbrush_t *volume)
Definition bspbrush.cpp:384
void FreeBrushList(bspbrush_t *brushes)
Definition bspbrush.cpp:193
void FreeBrush(bspbrush_t *brushes)
Definition bspbrush.cpp:179
bspbrush_t * AllocBrush(int numsides)
Definition bspbrush.cpp:166
side_t * SelectSplitSide(bspbrush_t *brushes, bspbrush_t *volume)
Using a heuristic, choses one of the sides out of the brushlist to partition the brushes with.
Definition bspbrush.cpp:416
static bool DoesPlaneSplitBrush(const bspbrush_t *brush, int planenum)
Checks if the plane splits the brush.
Definition bspbrush.cpp:357
static void BoundBrush(bspbrush_t *brush)
Sets the mins/maxs based on the windings.
Definition bspbrush.cpp:36
int c_nodes
Definition tree.cpp:27
static vec_t BrushVolume(const bspbrush_t *brush)
Returns the volume of the given brush.
Definition bspbrush.cpp:112
static void CreateBrushWindings(bspbrush_t *brush)
makes basewindigs for sides and mins/maxs for the brush
Definition bspbrush.cpp:53
void SplitBrush(const bspbrush_t *brush, uint16_t planenum, bspbrush_t **front, bspbrush_t **back)
Generates two new brushes, leaving the original unchanged.
Definition bspbrush.cpp:544
uint32_t BrushListCalcContents(bspbrush_t *brushlist)
Collects the contentsflags of the brushes in the given list.
Definition bspbrush.cpp:300
int CountBrushList(bspbrush_t *brushes)
Returns the amount of brushes in the given brushlist.
Definition bspbrush.cpp:152
static int c_active_brushes
Definition bspbrush.cpp:30
static int TestBrushToPlanenum(bspbrush_t *brush, uint16_t planenum, int *numsplits, bool *hintsplit, int *epsilonbrush)
Definition bspbrush.cpp:224
void BrushlistCalcStats(bspbrush_t *brushlist, AABB &blBox)
Counts the faces and calculate the aabb.
Definition bspbrush.cpp:759
static int BrushMostlyOnSide(const bspbrush_t *brush, const plane_t *plane)
Checks on which side a of plane the brush is.
Definition bspbrush.cpp:328
int c_nonvis
Definition tree.cpp:28
void SplitBrushList(bspbrush_t *brushes, uint16_t planenum, bspbrush_t **front, bspbrush_t **back)
Definition bspbrush.cpp:700
#define STANDARD_NUMBER_OF_BRUSHSIDES
Definition bspbrush.h:34
Definition aabb.h:42
vec3_t maxs
Definition aabb.h:258
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition aabb.h:98
vec3_t mins
Definition aabb.h:257
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition aabb.cpp:57
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define CONTENTS_DETAIL
Definition defines.h:251
#define PSIDE_BOTH
Definition defines.h:369
#define TEXINFO_NODE
Definition defines.h:48
#define CONTENTS_SOLID
Definition defines.h:223
#define CONTENTS_PASSABLE
Definition defines.h:244
#define SURF_SKIP
Definition defines.h:262
#define PSIDE_BACK
Definition defines.h:368
#define SURF_HINT
Definition defines.h:261
#define PSIDE_FRONT
Definition defines.h:367
#define MAX_WORLD_WIDTH
-MAX_WORLD_WIDTH up tp +MAX_WORLD_WIDTH
Definition defines.h:288
#define PSIDE_FACING
Definition defines.h:370
#define AXIAL(p)
Definition defines.h:201
static int c_faces
Definition faces.cpp:34
void Sys_Error(const char *error,...)
Definition g_main.cpp:421
voidpf void uLong size
Definition ioapi.h:42
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_Alloc(size)
Definition mem.h:40
void FreeWinding(winding_t *w)
Definition polylib.cpp:46
void ChopWindingInPlace(winding_t **inout, const vec3_t normal, const vec_t dist, const vec_t epsilon)
Definition polylib.cpp:299
bool WindingIsTiny(winding_t *w)
Returns true if the winding would be crunched out of existance by the vertex snapping.
Definition polylib.cpp:407
bool WindingIsHuge(const winding_t *w)
Returns true if the winding still has one of the points from basewinding for plane.
Definition polylib.cpp:427
winding_t * BaseWindingForPlane(const vec3_t normal, const vec_t dist)
Definition polylib.cpp:116
bool FixWinding(winding_t *w)
removes degenerate edges from a winding
Definition polylib.cpp:478
vec_t WindingArea(const winding_t *w)
Definition polylib.cpp:81
winding_t * CopyWinding(const winding_t *w)
Copy a winding with all its points allocated.
Definition polylib.cpp:185
void ClipWindingEpsilon(const winding_t *in, const vec3_t normal, const vec_t dist, const vec_t epsilon, winding_t **front, winding_t **back)
Definition polylib.cpp:204
QGL_EXTERN GLint i
Definition r_gl.h:113
struct mapbrush_s * original
Definition bspbrush.h:40
AABB brBox
Definition bspbrush.h:37
struct bspbrush_s * next
Definition bspbrush.h:36
int testside
Definition bspbrush.h:39
int numsides
Definition bspbrush.h:41
side_t sides[STANDARD_NUMBER_OF_BRUSHSIDES]
Definition bspbrush.h:42
vec3_t normal
Definition typedefs.h:373
float dist
Definition typedefs.h:374
Definition map.h:98
int type
Definition map.h:105
vec_t dist
Definition map.h:100
vec3_t normal
Definition map.h:99
Definition map.h:60
uint16_t planenum
Definition map.h:61
winding_t * winding
Definition map.h:63
uint32_t surfaceFlags
Definition map.h:66
int texinfo
Definition map.h:62
bool visible
Definition map.h:67
bool tested
Definition map.h:68
bool bevel
Definition map.h:69
for storing the vertices of the side of a brush or other polygon
Definition polylib.h:30
int numpoints
Definition polylib.h:31
vec3_t p[4]
Definition polylib.h:32
static config_t config
Definition test_all.cpp:43
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
@ VERB_EXTRA
Definition shared.h:46
@ VERB_DUMP
Definition shared.h:47
threadstate_t threadstate
Definition threads.cpp:32
int TR_BoxOnPlaneSide(const vec3_t mins, const vec3_t maxs, const TR_PLANE_TYPE *plane)
Returns PSIDE_FRONT, PSIDE_BACK, or PSIDE_BOTH.
Definition tracing.cpp:542
float vec_t
Definition ufotypes.h:37
vec_t vec3_t[3]
Definition ufotypes.h:39
#define VectorClear(a)
Definition vector.h:55
#define VectorCopy(src, dest)
Definition vector.h:51
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition vector.h:44