#include "qbsp.h"
Include dependency graph for csg.c:

Go to the source code of this file.
|
||||||||||||
|
Definition at line 610 of file csg.c. References bspbrush_t, bspbrush_s::next, next, and walk(). Referenced by ChopBrushes(). 00611 {
00612 bspbrush_t *walk, *next;
00613
00614 for (walk=list ; walk ; walk=next)
00615 { // add to end of list
00616 next = walk->next;
00617 walk->next = NULL;
00618 tail->next = walk;
00619 tail = walk;
00620 } //end for
00621 return tail;
00622 } //end of the function AddBrushListToTail
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 422 of file csg.c. References a, b, bspbrush_t, i, j, bspbrush_s::maxs, bspbrush_s::mins, bspbrush_s::numsides, side_s::planenum, qboolean, and bspbrush_s::sides. Referenced by ChopBrushes(). 00423 {
00424 int i, j;
00425
00426 // check bounding boxes
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; // bounding boxes don't overlap
00431
00432 // check for opposing planes
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; // opposite planes, so not touching
00440 }
00441 }
00442
00443 return false; // might intersect
00444 } //end of the function BrushesDisjoint
|
|
||||||||||||
|
Definition at line 699 of file csg.c. References bspbrush_t, mapbrush_s::contents, mapbrush_s::expansionbbox, bspbrush_s::original, and qboolean. Referenced by ChopBrushes(). 00700 {
00701 #ifdef ME
00702 if (create_aas)
00703 {
00704 if (b1->original->expansionbbox != b2->original->expansionbbox)
00705 {
00706 return false;
00707 } //end if
00708 //never have something else bite a ladder brush
00709 //never have a ladder brush bite something else
00710 if ( (b1->original->contents & CONTENTS_LADDER)
00711 && !(b2->original->contents & CONTENTS_LADDER))
00712 {
00713 return false;
00714 } //end if
00715 } //end if
00716 #endif //ME
00717 // detail brushes never bite structural brushes
00718 if ( (b1->original->contents & CONTENTS_DETAIL)
00719 && !(b2->original->contents & CONTENTS_DETAIL) )
00720 {
00721 return false;
00722 } //end if
00723 if (b1->original->contents & CONTENTS_SOLID)
00724 {
00725 return true;
00726 } //end if
00727 return false;
00728 } //end of the function BrushGE
|
|
|
Definition at line 90 of file csg.c. References BaseWindingForPlane(), bspbrush_t, ChopWindingInPlace(), plane_t::dist, i, j, mapplanes, plane_t::normal, bspbrush_s::numsides, side_s::planenum, bspbrush_s::sides, w, and side_s::winding. Referenced by TryMergeBrushes(). 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); //CLIP_EPSILON);
00105 } //end for
00106 brush->sides[i].winding = w;
00107 } //end for
00108 } //end of the function BSPBrushWindings
|
Here is the call graph for this function:

|
|
Definition at line 42 of file csg.c. References BoundBrush(), bspbrush_t, plane_t::dist, i, j, Log_Print(), mapplanes, MAX_MAP_BOUNDS, bspbrush_s::maxs, bspbrush_s::mins, plane_t::normal, bspbrush_s::numsides, side_s::planenum, bspbrush_s::sides, side_s::winding, and WindingsNonConvex(). Referenced by Q1_BSPBrushToMapBrush(), and TryMergeBrushes(). 00043 {
00044 int i, j;
00045 plane_t *plane1, *plane2;
00046
00047 //check if the brush is convex... flipped planes make a brush non-convex
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 } //end if
00064 } //end for
00065 } //end for
00066 BoundBrush(brush);
00067 //check for out of bound brushes
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 } //end if
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 } //end if
00082 } //end for
00083 } //end of the function CheckBSPBrush
|
Here is the call graph for this function:

|
|
Definition at line 737 of file csg.c. References AddBrushListToTail(), BrushesDisjoint(), BrushGE(), bspbrush_t, CountBrushList(), CullList(), FreeBrushList(), head, Log_Print(), Log_Write(), bspbrush_s::next, next, qprintf(), SubtractBrush(), WriteBrushList(), and WriteBrushMap(). Referenced by ProcessWorldBrushes(). 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 // find tail
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 //if the conversion is cancelled
00770 if (cancelconversion)
00771 {
00772 b1->next = keep;
00773 keep = b1;
00774 continue;
00775 } //end if
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; // didn't really intersect
00793 } //end if
00794 if (!sub)
00795 { // b1 is swallowed by b2
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; // didn't really intersect
00807 if (!sub2)
00808 { // b2 is swallowed by b1
00809 FreeBrushList (sub);
00810 head = CullList (b1, b2);
00811 goto newlist;
00812 }
00813 c2 = CountBrushList (sub2);
00814 }
00815
00816 if (!sub && !sub2)
00817 continue; // neither one can bite
00818
00819 // only accept if it didn't fragment
00820 // (commenting this out allows full fragmentation)
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 } //end if
00837 else
00838 {
00839 if (sub) FreeBrushList (sub);
00840 tail = AddBrushListToTail (sub2, tail);
00841 head = CullList (b1, b2);
00842 goto newlist;
00843 } //end else
00844 } //end for
00845
00846 if (!b2)
00847 { // b1 is no longer intersecting anything, so keep it
00848 b1->next = keep;
00849 keep = b1;
00850 } //end if
00851 num_csg_iterations++;
00852 qprintf("\r%6d", num_csg_iterations);
00853 } //end for
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 } //end of the function ChopBrushes
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 471 of file csg.c. References bspbrush_t, side_s::flags, FreeBrush(), i, j, maxplanenums, bspbrush_s::maxs, minplanenums, bspbrush_s::mins, bspbrush_s::numsides, p, side_s::planenum, bspbrush_s::sides, SplitBrush(), and side_s::texinfo. Referenced by MakeBspBrushList(). 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 // remove any colinear faces
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 } //end of the function ClipBrushToBox
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 630 of file csg.c. References bspbrush_t, FreeBrush(), bspbrush_s::next, and next. Referenced by ChopBrushes(). 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 } //end of the function CullList
|
Here is the call graph for this function:

|
|
Definition at line 875 of file csg.c. References b, bspbrush_t, CopyBrush(), side_s::flags, i, bspbrush_s::next, bspbrush_s::numsides, side_s::original, and bspbrush_s::sides. 00876 {
00877 bspbrush_t *b;
00878 bspbrush_t *out, *newb;
00879 int i;
00880
00881 // only return brushes that have visible faces
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 // clear visible, so it must be set by MarkVisibleFaces_r
00897 // to be used in the optimized list
00898 for (i=0 ; i<b->numsides ; i++)
00899 {
00900 newb->sides[i].original = &b->sides[i];
00901 // newb->sides[i].visible = true;
00902 b->sides[i].flags &= ~SFL_VISIBLE;
00903 }
00904 }
00905
00906 return out;
00907 } //end of the function InitialBrushList
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 394 of file csg.c. References b, bspbrush_t, FreeBrush(), i, in, bspbrush_s::next, bspbrush_s::numsides, side_s::planenum, bspbrush_s::sides, and SplitBrush2(). 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 } //end for
00408
00409 if (in == a) return NULL;
00410
00411 in->next = NULL;
00412 return in;
00413 } //end of the function IntersectBrush
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 454 of file csg.c. 00455 {
00456 int out;
00457
00458 out = c1 | c2;
00459
00460 if (out & CONTENTS_SOLID) out = CONTENTS_SOLID;
00461
00462 return out;
00463 } //end of the function IntersectionContents
|
|
||||||||||||||||||||
|
Definition at line 519 of file csg.c. 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 // make sure the brush has at least one face showing
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; // no faces at all
00562 #endif
00563 // if the brush is outside the clip area, skip it
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 // make a copy of the brush
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; // hints are always visible
00584 }
00585 VectorCopy (mb->mins, newbrush->mins);
00586 VectorCopy (mb->maxs, newbrush->maxs);
00587
00588 //
00589 // carve off anything outside the clip box
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 } //end of the function MakeBspBrushList
|
|
|
Definition at line 271 of file csg.c. References bspbrush_t, mapbrush_s::contents, mapbrush_s::expansionbbox, FreeBrush(), bspbrush_s::next, bspbrush_s::original, qprintf(), and TryMergeBrushes(). 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 } //end for
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 //if the brushes don't have the same contents
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 } //end for
00308 merged++;
00309 qprintf("\r%5d", nummerges++);
00310 break;
00311 } //end if
00312 lastb2 = b2;
00313 } //end for
00314 //if b1 can't be merged with any of the other brushes
00315 if (!b2)
00316 {
00317 brushlist = brushlist->next;
00318 //keep b1
00319 b1->next = newbrushlist;
00320 newbrushlist = b1;
00321 } //end else
00322 } //end for
00323 brushlist = newbrushlist;
00324 } while(merged);
00325 qprintf("\n");
00326 return newbrushlist;
00327 } //end of the function MergeBrushes
|
Here is the call graph for this function:

|
|
Definition at line 914 of file csg.c. References b, bspbrush_t, CopyBrush(), side_s::flags, i, bspbrush_s::next, bspbrush_s::numsides, and bspbrush_s::sides. 00915 {
00916 bspbrush_t *b;
00917 bspbrush_t *out, *newb;
00918 int i;
00919
00920 // only return brushes that have visible faces
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 } //end for
00933
00934 // WriteBrushList ("vis.gl", out, true);
00935 return out;
00936 } //end of the function OptimizeBrushList
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 943 of file csg.c. References AllocNode(), BrushBSP(), bspbrush_t, ChopBrushes(), node_s::contents, FreeBrushList(), MakeBspBrushList(), map_maxs, map_mins, node_t, node_s::planenum, ResetBrushBSP(), tree(), Tree_Alloc(), vec3_t, and VectorCopy. Referenced by AAS_Create(). 00944 {
00945 bspbrush_t *brushes;
00946 tree_t *tree;
00947 node_t *node;
00948 vec3_t mins, maxs;
00949
00950 //take the whole world
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 //reset the brush bsp
00960 ResetBrushBSP();
00961
00962 // the makelist and chopbrushes could be cached between the passes...
00963
00964 //create a list with brushes that are within the given mins/maxs
00965 //some brushes will be cut and only the part that falls within the
00966 //mins/maxs will be in the bush list
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 } //end if
00981 else
00982 {
00983 //Carves any intersecting solid brushes into the minimum number
00984 //of non-intersecting brushes.
00985 if (!nocsg)
00986 {
00987 brushes = ChopBrushes(brushes);
00988 /*
00989 if (create_aas)
00990 {
00991 brushes = MergeBrushes(brushes);
00992 } //end if*/
00993 } //end if
00994 //if the conversion is cancelled
00995 if (cancelconversion)
00996 {
00997 FreeBrushList(brushes);
00998 return NULL;
00999 } //end if
01000 //create the actual bsp tree
01001 tree = BrushBSP(brushes, mins, maxs);
01002 } //end else
01003 //return the tree
01004 return tree;
01005 } //end of the function ProcessWorldBrushes
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 334 of file csg.c. References bspbrush_t, bspbrush_s::sides, SplitBrush(), and side_s::texinfo. Referenced by IntersectBrush(), and SubtractBrush(). 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; // not -1
00341 if (*back && (*back)->sides[(*back)->numsides-1].texinfo == -1)
00342 (*back)->sides[(*back)->numsides-1].texinfo = (*back)->sides[0].texinfo; // not -1
00343 #endif
00344 } //end of the function SplitBrush2
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 354 of file csg.c. References b, bspbrush_t, FreeBrush(), FreeBrushList(), i, in, bspbrush_s::next, bspbrush_s::numsides, side_s::planenum, bspbrush_s::sides, and SplitBrush2(). Referenced by ChopBrushes(). 00355 { // a - b = out (list)
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 { // add to list
00368 front->next = out;
00369 out = front;
00370 } //end if
00371 in = back;
00372 } //end for
00373 if (in)
00374 {
00375 FreeBrush (in);
00376 } //end if
00377 else
00378 { // didn't really intersect
00379 FreeBrushList (out);
00380 return a;
00381 } //end else
00382 return out;
00383 } //end of the function SubtractBrush
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 116 of file csg.c. References AllocBrush(), BoundBrush(), bspbrush_t, BSPBrushWindings(), CheckBSPBrush(), plane_t::dist, i, j, k, Log_Print(), mapplanes, bspbrush_s::maxs, bspbrush_s::mins, n, plane_t::normal, bspbrush_s::numsides, bspbrush_s::original, side_s::planenum, side_t, bspbrush_s::sides, side_s::texinfo, TEXINFO_NODE, side_s::winding, and WindingsNonConvex(). Referenced by HL_MergeBrushes(), MergeBrushes(), and Q1_MergeBrushes(). 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 //check for bounding box overlapp
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 } //end if
00131 } //end for
00132 //
00133 shared = 0;
00134 //check if the brush is convex... flipped planes make a brush non-convex
00135 for (i = 0; i < brush1->numsides; i++)
00136 {
00137 side1 = &brush1->sides[i];
00138 //don't check the "shared" sides
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 //there may only be ONE shared side
00146 if (shared > 1) return NULL;
00147 break;
00148 } //end if
00149 } //end for
00150 if (k < brush2->numsides) continue;
00151 //
00152 for (j = 0; j < brush2->numsides; j++)
00153 {
00154 side2 = &brush2->sides[j];
00155 //don't check the "shared" sides
00156 for (n = 0; n < brush1->numsides; n++)
00157 {
00158 side1 = &brush1->sides[n];
00159 if (side1->planenum == (side2->planenum^1)) break;
00160 } //end for
00161 if (n < brush1->numsides) continue;
00162 //
00163 side1 = &brush1->sides[i];
00164 //if the side is in the same plane
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 } //end if
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 } //end if
00183 } //end for
00184 } //end for
00185 newbrush = AllocBrush(brush1->numsides + brush2->numsides);
00186 newbrush->original = brush1->original;
00187 newbrush->numsides = 0;
00188 //newbrush->side = brush1->side; //brush contents
00189 //fix texinfos for sides lying in the same plane
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 //if both sides are in the same plane get the texinfo right
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 } //end if
00203 } //end for
00204 } //end for
00205 //
00206 for (i = 0; i < brush1->numsides; i++)
00207 {
00208 side1 = &brush1->sides[i];
00209 //don't add the "shared" sides
00210 for (n = 0; n < brush2->numsides; n++)
00211 {
00212 side2 = &brush2->sides[n];
00213 if (side1->planenum == (side2->planenum ^ 1)) break;
00214 } //end for
00215 if (n < brush2->numsides) continue;
00216 //
00217 for< |