Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

csg.c File Reference

#include "qbsp.h"

Include dependency graph for csg.c:

Include dependency graph

Go to the source code of this file.

Functions

bspbrush_tAddBrushListToTail (bspbrush_t *list, bspbrush_t *tail)
qboolean BrushesDisjoint (bspbrush_t *a, bspbrush_t *b)
qboolean BrushGE (bspbrush_t *b1, bspbrush_t *b2)
void BSPBrushWindings (bspbrush_t *brush)
void CheckBSPBrush (bspbrush_t *brush)
bspbrush_tChopBrushes (bspbrush_t *head)
bspbrush_tClipBrushToBox (bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs)
bspbrush_tCullList (bspbrush_t *list, bspbrush_t *skip1)
bspbrush_tInitialBrushList (bspbrush_t *list)
bspbrush_tIntersectBrush (bspbrush_t *a, bspbrush_t *b)
int IntersectionContents (int c1, int c2)
bspbrush_tMakeBspBrushList (int startbrush, int endbrush, vec3_t clipmins, vec3_t clipmaxs)
bspbrush_tMergeBrushes (bspbrush_t *brushlist)
bspbrush_tOptimizedBrushList (bspbrush_t *list)
tree_tProcessWorldBrushes (int brush_start, int brush_end)
void SplitBrush2 (bspbrush_t *brush, int planenum, bspbrush_t **front, bspbrush_t **back)
bspbrush_tSubtractBrush (bspbrush_t *a, bspbrush_t *b)
bspbrush_tTryMergeBrushes (bspbrush_t *brush1, bspbrush_t *brush2)

Variables

int maxplanenums [3]
int minplanenums [3]


Function Documentation

bspbrush_t* AddBrushListToTail bspbrush_t list,
bspbrush_t tail
 

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:

qboolean BrushesDisjoint bspbrush_t a,
bspbrush_t b
 

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

qboolean BrushGE bspbrush_t b1,
bspbrush_t b2
 

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

void BSPBrushWindings bspbrush_t brush  ) 
 

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:

void CheckBSPBrush bspbrush_t brush  ) 
 

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:

bspbrush_t* ChopBrushes bspbrush_t head  ) 
 

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:

bspbrush_t* ClipBrushToBox bspbrush_t brush,
vec3_t  clipmins,
vec3_t  clipmaxs
 

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:

bspbrush_t* CullList bspbrush_t list,
bspbrush_t skip1
 

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:

bspbrush_t* InitialBrushList bspbrush_t list  ) 
 

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:

bspbrush_t* IntersectBrush bspbrush_t a,
bspbrush_t b
 

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:

int IntersectionContents int  c1,
int  c2
 

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

bspbrush_t* MakeBspBrushList int  startbrush,
int  endbrush,
vec3_t  clipmins,
vec3_t  clipmaxs
 

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

bspbrush_t* MergeBrushes bspbrush_t brushlist  ) 
 

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:

bspbrush_t* OptimizedBrushList bspbrush_t list  ) 
 

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:

tree_t* ProcessWorldBrushes int  brush_start,
int  brush_end
 

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:

void SplitBrush2 bspbrush_t brush,
int  planenum,
bspbrush_t **  front,
bspbrush_t **  back
 

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:

bspbrush_t* SubtractBrush bspbrush_t a,
bspbrush_t b
 

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:

bspbrush_t* TryMergeBrushes bspbrush_t brush1,
bspbrush_t brush2
 

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<