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

map_q1.c File Reference

#include "qbsp.h"
#include "l_bsp_q1.h"
#include "aas_map.h"

Include dependency graph for map_q1.c:

Include dependency graph

Go to the source code of this file.

Functions

void Q1_BSPBrushToMapBrush (bspbrush_t *bspbrush, entity_t *mapent)
bspbrush_tQ1_CreateBrushes_r (bspbrush_t *brush, int nodenum)
bspbrush_tQ1_CreateBrushesFromBSP (int modelnum)
void Q1_CreateMapBrushes (entity_t *mapent, int modelnum)
float Q1_FaceArea (q1_dface_t *face)
float Q1_FaceOnWinding (q1_dface_t *face, winding_t *winding)
void Q1_FacePlane (q1_dface_t *face, vec3_t normal, float *dist)
void Q1_FixContentsTextures (bspbrush_t *brushlist)
void Q1_LoadMapFromBSP (char *filename, int offset, int length)
bspbrush_tQ1_MergeBrushes (bspbrush_t *brushlist, int modelnum)
q1_dleaf_tQ1_PointInLeaf (int startnode, vec3_t point)
void Q1_ResetMapLoading (void)
int Q1_SolidTree_r (int nodenum)
void Q1_SplitBrush (bspbrush_t *brush, int planenum, int nodenum, bspbrush_t **front, bspbrush_t **back)
bspbrush_tQ1_SplitBrushWithFace (bspbrush_t *brush, q1_dface_t *face)
bspbrush_tQ1_TextureBrushes (bspbrush_t *brushlist, int modelnum)
int Q1_TextureContents (char *name)

Variables

int q1_numbrushes
int q1_numclipbrushes


Function Documentation

void Q1_BSPBrushToMapBrush bspbrush_t bspbrush,
entity_t mapent
 

Definition at line 1001 of file map_q1.c.

References AAS_CreateMapBrushes(), AddBrushBevels(), mapbrush_s::brushnum, brushsides, bspbrush_t, CheckBSPBrush(), mapbrush_s::contents, side_s::contents, mapbrush_s::entitynum, Error(), entity_t::firstbrush, side_s::flags, i, mapbrush_s::leafnum, MakeBrushWindings(), mapbrush_t, mapbrushes, mapent, entity_t::numbrushes, nummapbrushes, nummapbrushsides, bspbrush_s::numsides, mapbrush_s::numsides, mapbrush_s::original_sides, side_s::planenum, q1_numclipbrushes, bspbrush_s::side, side_t, bspbrush_s::sides, side_s::surf, side_s::texinfo, and side_s::winding.

Referenced by Q1_CreateMapBrushes().

01002 {
01003     mapbrush_t *mapbrush;
01004     side_t *side;
01005     int i, besttexinfo;
01006 
01007     CheckBSPBrush(bspbrush);
01008 
01009     if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
01010     Error ("nummapbrushes == MAX_MAPFILE_BRUSHES");
01011 
01012     mapbrush = &mapbrushes[nummapbrushes];
01013     mapbrush->original_sides = &brushsides[nummapbrushsides];
01014     mapbrush->entitynum = mapent - entities;
01015     mapbrush->brushnum = nummapbrushes - mapent->firstbrush;
01016     mapbrush->leafnum = -1;
01017     mapbrush->numsides = 0;
01018 
01019     besttexinfo = TEXINFO_NODE;
01020     for (i = 0; i < bspbrush->numsides; i++)
01021     {
01022         if (!bspbrush->sides[i].winding) continue;
01023         //
01024         if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
01025             Error ("MAX_MAPFILE_BRUSHSIDES");
01026         side = &brushsides[nummapbrushsides];
01027         //the contents of the bsp brush is stored in the side variable
01028         side->contents = bspbrush->side;
01029         side->surf = 0;
01030         side->planenum = bspbrush->sides[i].planenum;
01031         side->texinfo = bspbrush->sides[i].texinfo;
01032         if (side->texinfo != TEXINFO_NODE)
01033         {
01034             //this brush side is textured
01035             side->flags |= SFL_TEXTURED;
01036             besttexinfo = side->texinfo;
01037         } //end if
01038         //
01039         nummapbrushsides++;
01040         mapbrush->numsides++;
01041     } //end for
01042     //
01043     if (besttexinfo == TEXINFO_NODE)
01044     {
01045         mapbrush->numsides = 0;
01046         q1_numclipbrushes++;
01047         return;
01048     } //end if
01049     //set the texinfo for all the brush sides without texture
01050     for (i = 0; i < mapbrush->numsides; i++)
01051     {
01052         if (mapbrush->original_sides[i].texinfo == TEXINFO_NODE)
01053         {
01054             mapbrush->original_sides[i].texinfo = besttexinfo;
01055         } //end if
01056     } //end for
01057     //contents of the brush
01058     mapbrush->contents = bspbrush->side;
01059     //
01060     if (create_aas)
01061     {
01062         //create the AAS brushes from this brush, add brush bevels
01063         AAS_CreateMapBrushes(mapbrush, mapent, true);
01064         return;
01065     } //end if
01066     //create windings for sides and bounds for brush
01067     MakeBrushWindings(mapbrush);
01068     //add brush bevels
01069     AddBrushBevels(mapbrush);
01070     //a new brush has been created
01071     nummapbrushes++;
01072     mapent->numbrushes++;
01073 } //end of the function Q1_BSPBrushToMapBrush

Here is the call graph for this function:

bspbrush_t* Q1_CreateBrushes_r bspbrush_t brush,
int  nodenum
 

Definition at line 316 of file map_q1.c.

References bspbrush_t, q1_dleaf_t::contents, Error(), FindFloatPlane(), FreeBrush(), Log_Print(), bspbrush_s::next, q1_dnode_t::planenum, Q1_CONTENTS_EMPTY, Q1_CONTENTS_LAVA, Q1_CONTENTS_SKY, Q1_CONTENTS_SLIME, Q1_CONTENTS_SOLID, Q1_CONTENTS_WATER, q1_dleafs, q1_dnodes, q1_dplanes, q1_numbrushes, Q1_SplitBrush(), qprintf(), and bspbrush_s::side.

Referenced by Q1_CreateBrushesFromBSP().

00317 {
00318     int planenum;
00319     bspbrush_t *front, *back;
00320     q1_dleaf_t *leaf;
00321 
00322     //if it is a leaf
00323     if (nodenum < 0)
00324     {
00325         leaf = &q1_dleafs[(-nodenum) - 1];
00326         if (leaf->contents != Q1_CONTENTS_EMPTY)
00327         {
00328 #ifdef Q1_PRINT
00329             qprintf("\r%5i", ++q1_numbrushes);
00330 #endif //Q1_PRINT
00331         } //end if
00332         switch(leaf->contents)
00333         {
00334             case Q1_CONTENTS_EMPTY:
00335             {
00336                 FreeBrush(brush);
00337                 return NULL;
00338             } //end case
00339             case Q1_CONTENTS_SOLID:
00340 #ifdef HLCONTENTS
00341             case Q1_CONTENTS_CLIP:
00342 #endif HLCONTENTS
00343             case Q1_CONTENTS_SKY:
00344 #ifdef HLCONTENTS
00345             case Q1_CONTENTS_TRANSLUCENT:
00346 #endif HLCONTENTS
00347             {
00348                 brush->side = CONTENTS_SOLID;
00349                 return brush;
00350             } //end case
00351             case Q1_CONTENTS_WATER:
00352             {
00353                 brush->side = CONTENTS_WATER;
00354                 return brush;
00355             } //end case
00356             case Q1_CONTENTS_SLIME:
00357             {
00358                 brush->side = CONTENTS_SLIME;
00359                 return brush;
00360             } //end case
00361             case Q1_CONTENTS_LAVA:
00362             {
00363                 brush->side = CONTENTS_LAVA;
00364                 return brush;
00365             } //end case
00366 #ifdef HLCONTENTS
00367             //these contents should not be found in the BSP
00368             case Q1_CONTENTS_ORIGIN:
00369             case Q1_CONTENTS_CURRENT_0:
00370             case Q1_CONTENTS_CURRENT_90:
00371             case Q1_CONTENTS_CURRENT_180:
00372             case Q1_CONTENTS_CURRENT_270:
00373             case Q1_CONTENTS_CURRENT_UP:
00374             case Q1_CONTENTS_CURRENT_DOWN:
00375             {
00376                 Error("Q1_CreateBrushes_r: found contents %d in Half-Life BSP", leaf->contents);
00377                 return NULL;
00378             } //end case
00379 #endif HLCONTENTS
00380             default:
00381             {
00382                 Error("Q1_CreateBrushes_r: unknown contents %d in Half-Life BSP", leaf->contents);
00383                 return NULL;
00384             } //end default
00385         } //end switch
00386         return NULL;
00387     } //end if
00388     //if the rest of the tree is solid
00389     /*if (Q1_SolidTree_r(nodenum))
00390     {
00391         brush->side = CONTENTS_SOLID;
00392         return brush;
00393     } //end if*/
00394     //
00395     planenum = q1_dnodes[nodenum].planenum;
00396     planenum = FindFloatPlane(q1_dplanes[planenum].normal, q1_dplanes[planenum].dist);
00397     //split the brush with the node plane
00398     Q1_SplitBrush(brush, planenum, nodenum, &front, &back);
00399     //free the original brush
00400     FreeBrush(brush);
00401     //every node must split the brush in two
00402     if (!front || !back)
00403     {
00404         Log_Print("Q1_CreateBrushes_r: WARNING node not splitting brush\n");
00405         //return NULL;
00406     } //end if
00407     //create brushes recursively
00408     if (front) front = Q1_CreateBrushes_r(front, q1_dnodes[nodenum].children[0]);
00409     if (back) back = Q1_CreateBrushes_r(back, q1_dnodes[nodenum].children[1]);
00410     //link the brushes if possible and return them
00411     if (front)
00412     {
00413         for (brush = front; brush->next; brush = brush->next);
00414         brush->next = back;
00415         return front;
00416     } //end if
00417     else
00418     {
00419         return back;
00420     } //end else
00421 } //end of the function Q1_CreateBrushes_r

Here is the call graph for this function:

bspbrush_t* Q1_CreateBrushesFromBSP int  modelnum  ) 
 

Definition at line 428 of file map_q1.c.

References AddPointToBounds(), BrushFromBounds(), bspbrush_t, q1_dmodel_t::headnode, i, Log_Print(), map_maxs, map_mins, bspbrush_s::maxs, q1_dnode_t::maxs, bspbrush_s::mins, q1_dnode_t::mins, Q1_CreateBrushes_r(), q1_dmodels, q1_dnodes, q1_numbrushes, qprintf(), vec3_t, and VectorCopy.

Referenced by Q1_CreateMapBrushes().

00429 {
00430     bspbrush_t *brushlist;
00431     bspbrush_t *brush;
00432     q1_dnode_t *headnode;
00433     vec3_t mins, maxs;
00434     int i;
00435 
00436     //
00437     headnode = &q1_dnodes[q1_dmodels[modelnum].headnode[0]];
00438     //get the mins and maxs of the world
00439     VectorCopy(headnode->mins, mins);
00440     VectorCopy(headnode->maxs, maxs);
00441     //enlarge these mins and maxs
00442     for (i = 0; i < 3; i++)
00443     {
00444         mins[i] -= 8;
00445         maxs[i] += 8;
00446     } //end for
00447     //NOTE: have to add the BSP tree mins and maxs to the MAP mins and maxs
00448     AddPointToBounds(mins, map_mins, map_maxs);
00449     AddPointToBounds(maxs, map_mins, map_maxs);
00450     //
00451     if (!modelnum)
00452     {
00453         Log_Print("brush size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n",
00454                             map_mins[0], map_mins[1], map_mins[2],
00455                             map_maxs[0], map_maxs[1], map_maxs[2]);
00456     } //end if
00457     //create one huge brush containing the whole world
00458     brush = BrushFromBounds(mins, maxs);
00459     VectorCopy(mins, brush->mins);
00460     VectorCopy(maxs, brush->maxs);
00461     //
00462 #ifdef Q1_PRINT
00463     qprintf("creating Quake brushes\n");
00464     qprintf("%5d brushes", q1_numbrushes = 0);
00465 #endif //Q1_PRINT
00466     //create the brushes
00467     brushlist = Q1_CreateBrushes_r(brush, q1_dmodels[modelnum].headnode[0]);
00468     //
00469 #ifdef Q1_PRINT
00470     qprintf("\n");
00471 #endif //Q1_PRINT
00472     //now we've got a list with brushes!
00473     return brushlist;
00474 } //end of the function Q1_CreateBrushesFromBSP

Here is the call graph for this function:

void Q1_CreateMapBrushes entity_t mapent,
int  modelnum
 

Definition at line 1080 of file map_q1.c.

References bspbrush_t, FreeBrush(), i, mapent, bspbrush_s::next, Q1_BSPBrushToMapBrush(), Q1_CreateBrushesFromBSP(), Q1_FixContentsTextures(), Q1_MergeBrushes(), Q1_TextureBrushes(), and qprintf().

Referenced by Q1_LoadMapFromBSP().

01081 {
01082     bspbrush_t *brushlist, *brush, *nextbrush;
01083     int i;
01084 
01085     //create brushes from the model BSP tree
01086     brushlist = Q1_CreateBrushesFromBSP(modelnum);
01087     //texture the brushes and split them when necesary
01088     brushlist = Q1_TextureBrushes(brushlist, modelnum);
01089     //fix the contents textures of all brushes
01090     Q1_FixContentsTextures(brushlist);
01091     //
01092     if (!nobrushmerge)
01093     {
01094         brushlist = Q1_MergeBrushes(brushlist, modelnum);
01095         //brushlist = Q1_MergeBrushes(brushlist, modelnum);
01096     } //end if
01097     //
01098     if (!modelnum) qprintf("converting brushes to map brushes\n");
01099     if (!modelnum) qprintf("%5d brushes", i = 0);
01100     for (brush = brushlist; brush; brush = nextbrush)
01101     {
01102         nextbrush = brush->next;
01103         Q1_BSPBrushToMapBrush(brush, mapent);
01104         brush->next = NULL;
01105         FreeBrush(brush);
01106         if (!modelnum) qprintf("\r%5d", ++i);
01107     } //end for
01108     if (!modelnum) qprintf("\n");
01109 } //end of the function Q1_CreateMapBrushes

Here is the call graph for this function:

float Q1_FaceArea q1_dface_t face  ) 
 

Definition at line 508 of file map_q1.c.

References CrossProduct(), q1_dface_t::firstedge, i, q1_dface_t::numedges, q1_dvertex_t::point, q1_dedges, q1_dvertexes, q1_dedge_t::v, v, vec3_t, vec_t, VectorLength(), and VectorSubtract.

00509 {
00510     int i;
00511     float total;
00512     vec_t *v;
00513     vec3_t d1, d2, cross;
00514     q1_dedge_t *edge;
00515 
00516     edge = &q1_dedges[face->firstedge];
00517     v = q1_dvertexes[edge->v[0]].point;
00518 
00519     total = 0;
00520     for (i = 1; i < face->numedges - 1; i++)
00521     {
00522         edge = &q1_dedges[face->firstedge + i];
00523         VectorSubtract(q1_dvertexes[edge->v[0]].point, v, d1);
00524         VectorSubtract(q1_dvertexes[edge->v[1]].point, v, d2);
00525         CrossProduct(d1, d2, cross);
00526         total += 0.5 * VectorLength(cross);
00527     } //end for
00528     return total;
00529 } //end of the function AAS_FaceArea

Here is the call graph for this function:

float Q1_FaceOnWinding q1_dface_t face,
winding_t winding
 

Definition at line 634 of file map_q1.c.

References abs(), ChopWindingInPlace(), CopyWinding(), CrossProduct(), q1_dplane_t::dist, DotProduct, q1_dface_t::firstedge, FreeWinding(), i, memcpy(), q1_dplane_t::normal, q1_dface_t::numedges, q1_dface_t::planenum, q1_dvertex_t::point, q1_dedges, q1_dplanes, q1_dsurfedges, q1_dvertexes, q1_dface_t::side, q1_dedge_t::v, v1, v2, vec3_t, vec_t, VectorNegate, VectorNormalize(), VectorSubtract, w, and WindingArea().

Referenced by Q1_TextureBrushes().

00635 {
00636     int i, edgenum, side;
00637     float dist, area;
00638     q1_dplane_t plane;
00639     vec_t *v1, *v2;
00640     vec3_t normal, edgevec;
00641     winding_t *w;
00642 
00643     //
00644     w = CopyWinding(winding);
00645     memcpy(&plane, &q1_dplanes[face->planenum], sizeof(q1_dplane_t));
00646     //check on which side of the plane the face is
00647     if (face->side)
00648     {
00649         VectorNegate(plane.normal, plane.normal);
00650         plane.dist = -plane.dist;
00651     } //end if
00652     for (i = 0; i < face->numedges && w; i++)
00653     {
00654         //get the first and second vertex of the edge
00655         edgenum = q1_dsurfedges[face->firstedge + i];
00656         side = edgenum > 0;
00657         //if the face plane is flipped
00658         v1 = q1_dvertexes[q1_dedges[abs(edgenum)].v[side]].point;
00659         v2 = q1_dvertexes[q1_dedges[abs(edgenum)].v[!side]].point;
00660         //create a plane through the edge vector, orthogonal to the face plane
00661         //and with the normal vector pointing out of the face
00662         VectorSubtract(v1, v2, edgevec);
00663         CrossProduct(edgevec, plane.normal, normal);
00664         VectorNormalize(normal);
00665         dist = DotProduct(normal, v1);
00666         //
00667         ChopWindingInPlace(&w, normal, dist, 0.9); //CLIP_EPSILON
00668     } //end for
00669     if (w)
00670     {
00671         area = WindingArea(w);
00672         FreeWinding(w);
00673         return area;
00674     } //end if
00675     return 0;
00676 } //end of the function Q1_FaceOnWinding

Here is the call graph for this function:

void Q1_FacePlane q1_dface_t face,
vec3_t  normal,
float *  dist
 

Definition at line 536 of file map_q1.c.

References abs(), CrossProduct(), DotProduct, q1_dface_t::firstedge, q1_dvertex_t::point, q1_dedges, q1_dsurfedges, q1_dvertexes, q1_dedge_t::v, v1, v2, vec3_t, vec_t, VectorNormalize(), and VectorSubtract.

00537 {
00538     vec_t *v1, *v2, *v3;
00539     vec3_t vec1, vec2;
00540     int side, edgenum;
00541 
00542     edgenum = q1_dsurfedges[face->firstedge];
00543     side = edgenum < 0;
00544     v1 = q1_dvertexes[q1_dedges[abs(edgenum)].v[side]].point;
00545     v2 = q1_dvertexes[q1_dedges[abs(edgenum)].v[!side]].point;
00546     edgenum = q1_dsurfedges[face->firstedge+1];
00547     side = edgenum < 0;
00548     v3 = q1_dvertexes[q1_dedges[abs(edgenum)].v[!side]].point;
00549     //
00550     VectorSubtract(v2, v1, vec1);
00551     VectorSubtract(v3, v1, vec2);
00552 
00553     CrossProduct(vec1, vec2, normal);
00554     VectorNormalize(normal);
00555     *dist = DotProduct(v1, normal);
00556 } //end of the function Q1_FacePlane

Here is the call graph for this function:

void Q1_FixContentsTextures bspbrush_t brushlist  ) 
 

Definition at line 939 of file map_q1.c.

References bspbrush_t, CONTENTS_SLIME, CONTENTS_WATER, i, Log_Print(), map_texinfo, bspbrush_s::next, bspbrush_s::numsides, Q1_TextureContents(), bspbrush_s::side, bspbrush_s::sides, side_s::texinfo, and texture.

Referenced by Q1_CreateMapBrushes().

00940 {
00941     int i, texinfonum;
00942     bspbrush_t *brush;
00943 
00944     for (brush = brushlist; brush; brush = brush->next)
00945     {
00946         //only fix the textures of water, slime and lava brushes
00947         if (brush->side != CONTENTS_WATER &&
00948             brush->side != CONTENTS_SLIME &&
00949             brush->side != CONTENTS_LAVA) continue;
00950         //
00951         for (i = 0; i < brush->numsides; i++)
00952         {
00953             texinfonum = brush->sides[i].texinfo;
00954             if (Q1_TextureContents(map_texinfo[texinfonum].texture) == brush->side) break;
00955         } //end for
00956         //if no specific contents texture was found
00957         if (i >= brush->numsides)
00958         {
00959             texinfonum = -1;
00960             for (i = 0; i < map_numtexinfo; i++)
00961             {
00962                 if (Q1_TextureContents(map_texinfo[i].texture) == brush->side)
00963                 {
00964                     texinfonum = i;
00965                     break;
00966                 } //end if
00967             } //end for
00968         } //end if
00969         //
00970         if (texinfonum >= 0)
00971         {
00972             //give all the brush sides this contents texture
00973             for (i = 0; i < brush->numsides; i++)
00974             {
00975                 brush->sides[i].texinfo = texinfonum;
00976             } //end for
00977         } //end if
00978         else Log_Print("brush contents %d with wrong textures\n", brush->side);
00979         //
00980     } //end for
00981     /*
00982     for (brush = brushlist; brush; brush = brush->next)
00983     {
00984         //give all the brush sides this contents texture
00985         for (i = 0; i < brush->numsides; i++)
00986         {
00987             if (Q1_TextureContents(map_texinfo[texinfonum].texture) != brush->side)
00988             {
00989                 Error("brush contents %d with wrong contents textures %s\n", brush->side,
00990                             Q1_TextureContents(map_texinfo[texinfonum].texture));
00991             } //end if
00992         } //end for
00993     } //end for*/
00994 } //end of the function Q1_FixContentsTextures

Here is the call graph for this function:

void Q1_LoadMapFromBSP char *  filename,
int  offset,
int  length
 

Definition at line 1125 of file map_q1.c.

References atoi, ClearBounds(), entities, entity_t::firstbrush, i, length(), loadedmaptype, Log_Print(), map_maxs, map_mins, entity_t::numbrushes, nummapbrushes, offset, Q1_CreateMapBrushes(), Q1_LoadBSPFile(), q1_numclipbrushes, Q1_ParseEntities(), qprintf(), strcmp(), and ValueForKey().

Referenced by LoadMapFromBSP().

01126 {
01127     int i, modelnum;
01128     char *model, *classname;
01129 
01130     Log_Print("-- Q1_LoadMapFromBSP --\n");
01131     //the loaded map type
01132     loadedmaptype = MAPTYPE_QUAKE1;
01133     //
01134     qprintf("loading map from %s at %d\n", filename, offset);
01135     //load the Half-Life BSP file
01136     Q1_LoadBSPFile(filename, offset, length);
01137     //
01138     q1_numclipbrushes = 0;
01139     //CreatePath(path);
01140     //Q1_CreateQ2WALFiles(path);
01141     //parse the entities from the BSP
01142     Q1_ParseEntities();
01143     //clear the map mins and maxs
01144     ClearBounds(map_mins, map_maxs);
01145     //
01146     qprintf("creating Quake1 brushes\n");
01147     if (lessbrushes) qprintf("creating minimum number of brushes\n");
01148     else qprintf("placing textures correctly\n");
01149     //
01150     for (i = 0; i < num_entities; i++)
01151     {
01152         entities[i].firstbrush = nummapbrushes;
01153         entities[i].numbrushes = 0;
01154         //
01155         classname = ValueForKey(&entities[i], "classname");
01156         if (classname && !strcmp(classname, "worldspawn"))
01157         {
01158             modelnum = 0;
01159         } //end if
01160         else
01161         {
01162             //
01163             model = ValueForKey(&entities[i], "model");
01164             if (!model || *model != '*') continue;
01165             model++;
01166             modelnum = atoi(model);
01167         } //end else
01168         //create map brushes for the entity
01169         Q1_CreateMapBrushes(&entities[i], modelnum);
01170     } //end for
01171     //
01172     qprintf("%5d map brushes\n", nummapbrushes);
01173     qprintf("%5d clip brushes\n", q1_numclipbrushes);
01174 } //end of the function Q1_LoadMapFromBSP

Here is the call graph for this function:

bspbrush_t* Q1_MergeBrushes bspbrush_t brushlist,
int  modelnum
 

Definition at line 563 of file map_q1.c.

References bspbrush_t, FreeBrush(), bspbrush_s::next, qprintf(), bspbrush_s::side, and TryMergeBrushes().

Referenced by Q1_CreateMapBrushes().

00564 {
00565     int nummerges, merged;
00566     bspbrush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
00567     bspbrush_t *lastb2;
00568 
00569     if (!brushlist) return NULL;
00570 
00571     if (!modelnum) qprintf("%5d brushes merged", nummerges = 0);
00572     do
00573     {
00574         for (tail = brushlist; tail; tail = tail->next)
00575         {
00576             if (!tail->next) break;
00577         } //end for
00578         merged = 0;
00579         newbrushlist = NULL;
00580         for (b1 = brushlist; b1; b1 = brushlist)
00581         {
00582             lastb2 = b1;
00583             for (b2 = b1->next; b2; b2 = b2->next)
00584             {
00585                 //can't merge brushes with different contents
00586                 if (b1->side != b2->side) newbrush = NULL;
00587                 else newbrush = TryMergeBrushes(b1, b2);
00588                 //if a merged brush is created
00589                 if (newbrush)
00590                 {
00591                     //copy the brush contents
00592                     newbrush->side = b1->side;
00593                     //add the new brush to the end of the list
00594                     tail->next = newbrush;
00595                     //remove the second brush from the list
00596                     lastb2->next = b2->next;
00597                     //remove the first brush from the list
00598                     brushlist = brushlist->next;
00599                     //free the merged brushes
00600                     FreeBrush(b1);
00601                     FreeBrush(b2);
00602                     //get a new tail brush
00603                     for (tail = brushlist; tail; tail = tail->next)
00604                     {
00605                         if (!tail->next) break;
00606                     } //end for
00607                     merged++;
00608                     if (!modelnum) qprintf("\r%5d", nummerges++);
00609                     break;
00610                 } //end if
00611                 lastb2 = b2;
00612             } //end for
00613             //if b1 can't be merged with any of the other brushes
00614             if (!b2)
00615             {
00616                 brushlist = brushlist->next;
00617                 //keep b1
00618                 b1->next = newbrushlist;
00619                 newbrushlist = b1;
00620             } //end else
00621         } //end for
00622         brushlist = newbrushlist;
00623     } while(merged);
00624     if (!modelnum) qprintf("\n");
00625     return newbrushlist;
00626 } //end of the function Q1_MergeBrushes

Here is the call graph for this function:

q1_dleaf_t* Q1_PointInLeaf int  startnode,
vec3_t  point
 

Definition at line 481 of file map_q1.c.

References q1_dnode_t::children, q1_dplane_t::dist, DotProduct, q1_dplane_t::normal, q1_dnode_t::planenum, point, q1_dleafs, q1_dnodes, q1_dplanes, and vec_t.

00482 {
00483     int nodenum;
00484     vec_t   dist;
00485     q1_dnode_t *node;
00486     q1_dplane_t *plane;
00487 
00488     nodenum = startnode;
00489     while (nodenum >= 0)
00490     {
00491         node = &q1_dnodes[nodenum];
00492         plane = &q1_dplanes[node->planenum];
00493         dist = DotProduct(point, plane->normal) - plane->dist;
00494         if (dist > 0)
00495             nodenum = node->children[0];
00496         else
00497             nodenum = node->children[1];
00498     } //end while
00499 
00500     return &q1_dleafs[-nodenum - 1];
00501 } //end of the function Q1_PointInLeaf

void Q1_ResetMapLoading void   ) 
 

Definition at line 1116 of file map_q1.c.

01117 {
01118 } //end of the function Q1_ResetMapLoading

int Q1_SolidTree_r int  nodenum  ) 
 

Definition at line 265 of file map_q1.c.

References q1_dleaf_t::contents, Q1_CONTENTS_EMPTY, Q1_CONTENTS_LAVA, Q1_CONTENTS_SKY, Q1_CONTENTS_SLIME, Q1_CONTENTS_SOLID, Q1_CONTENTS_WATER, q1_dleafs, and q1_dnodes.

00266 {
00267     if (nodenum < 0)
00268     {
00269         switch(q1_dleafs[(-nodenum) - 1].contents)
00270         {
00271             case Q1_CONTENTS_EMPTY:
00272             {
00273                 return false;
00274             } //end case
00275             case Q1_CONTENTS_SOLID:
00276 #ifdef HLCONTENTS
00277             case Q1_CONTENTS_CLIP:
00278 #endif HLCONTENTS
00279             case Q1_CONTENTS_SKY:
00280 #ifdef HLCONTENTS
00281             case Q1_CONTENTS_TRANSLUCENT:
00282 #endif HLCONTENTS
00283             {
00284                 return true;
00285             } //end case
00286             case Q1_CONTENTS_WATER:
00287             case Q1_CONTENTS_SLIME:
00288             case Q1_CONTENTS_LAVA:
00289 #ifdef HLCONTENTS
00290             //these contents should not be found in the BSP
00291             case Q1_CONTENTS_ORIGIN:
00292             case Q1_CONTENTS_CURRENT_0:
00293             case Q1_CONTENTS_CURRENT_90:
00294             case Q1_CONTENTS_CURRENT_180:
00295             case Q1_CONTENTS_CURRENT_270:
00296             case Q1_CONTENTS_CURRENT_UP:
00297             case Q1_CONTENTS_CURRENT_DOWN:
00298 #endif HLCONTENTS
00299             default:
00300             {
00301                 return false;
00302             } //end default
00303         } //end switch
00304         return false;
00305     } //end if
00306     if (!Q1_SolidTree_r(q1_dnodes[nodenum].children[0])) return false;
00307     if (!Q1_SolidTree_r(q1_dnodes[nodenum].children[1])) return false;
00308     return true;
00309 } //end of the function Q1_SolidTree_r

void Q1_SplitBrush bspbrush_t brush,
int  planenum,
int  nodenum,
bspbrush_t **  front,
bspbrush_t **  back
 

Definition at line 63 of file map_q1.c.

References AllocBrush(), b, BaseWindingForPlane(), BoundBrush(), BrushMostlyOnSide(), BrushVolume(), bspbrush_t, ChopWindingInPlace(), ClipWindingEpsilon(), CopyBrush(), CopyWinding(), d, plane_t::dist, DotProduct, side_s::flags, FreeBrush(), FreeWinding(), i, j, Log_Print(), mapplanes, bspbrush_s::maxs, bspbrush_s::mins, plane_t::normal, winding_t::numpoints, bspbrush_s::numsides, bspbrush_s::original, winding_t::p, side_s::planenum, s, side_t, bspbrush_s::sides, side_s::surf, side_s::texinfo, v1, vec_t, w, side_s::winding, WindingIsHuge(), and WindingIsTiny().

Referenced by Q1_CreateBrushes_r().

00065 {
00066     bspbrush_t *b[2];
00067     int i, j;
00068     winding_t *w, *cw[2], *midwinding;
00069     plane_t *plane, *plane2;
00070     side_t *s, *cs;
00071     float d, d_front, d_back;
00072 
00073     *front = *back = NULL;
00074     plane = &mapplanes[planenum];
00075 
00076     // check all points
00077     d_front = d_back = 0;
00078     for (i=0 ; i<brush->numsides ; i++)
00079     {
00080         w = brush->sides[i].winding;
00081         if (!w)
00082             continue;
00083         for (j=0 ; j<w->numpoints ; j++)
00084         {
00085             d = DotProduct (w->p[j], plane->normal) - plane->dist;
00086             if (d > 0 && d > d_front)
00087                 d_front = d;
00088             if (d < 0 && d < d_back)
00089                 d_back = d;
00090         } //end for
00091     } //end for
00092 
00093     if (d_front < 0.1) // PLANESIDE_EPSILON)
00094     {   // only on back
00095         *back = CopyBrush (brush);
00096         Log_Print("Q1_SplitBrush: only on back\n");
00097         return;
00098     } //end if
00099     if (d_back > -0.1) // PLANESIDE_EPSILON)
00100     {   // only on front
00101         *front = CopyBrush (brush);
00102         Log_Print("Q1_SplitBrush: only on front\n");
00103         return;
00104     } //end if
00105 
00106     // create a new winding from the split plane
00107 
00108     w = BaseWindingForPlane (plane->normal, plane->dist);
00109     for (i = 0; i < brush->numsides && w; i++)
00110     {
00111         plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
00112         ChopWindingInPlace(&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
00113     } //end for
00114 
00115     if (!w || WindingIsTiny(w))
00116     {   // the brush isn't really split
00117         int     side;
00118 
00119         Log_Print("Q1_SplitBrush: no split winding\n");
00120         side = BrushMostlyOnSide (brush, plane);
00121         if (side == PSIDE_FRONT)
00122             *front = CopyBrush (brush);
00123         if (side == PSIDE_BACK)
00124             *back = CopyBrush (brush);
00125         return;
00126     }
00127 
00128     if (WindingIsHuge(w))
00129     {
00130         Log_Print("Q1_SplitBrush: WARNING huge split winding\n");
00131     } //end of
00132 
00133     midwinding = w;
00134 
00135     // split it for real
00136 
00137     for (i = 0; i < 2; i++)
00138     {
00139         b[i] = AllocBrush (brush->numsides+1);
00140         b[i]->original = brush->original;
00141     } //end for
00142 
00143     // split all the current windings
00144 
00145     for (i=0 ; i<brush->numsides ; i++)
00146     {
00147         s = &brush->sides[i];
00148         w = s->winding;
00149         if (!w)
00150             continue;
00151         ClipWindingEpsilon (w, plane->normal, plane->dist,
00152             0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
00153         for (j=0 ; j<2 ; j++)
00154         {
00155             if (!cw[j])
00156                 continue;
00157 #if 0
00158             if (WindingIsTiny (cw[j]))
00159             {
00160                 FreeWinding (cw[j]);
00161                 continue;
00162             }
00163 #endif
00164             cs = &b[j]->sides[b[j]->numsides];
00165             b[j]->numsides++;
00166             *cs = *s;
00167 //          cs->planenum = s->planenum;
00168 //          cs->texinfo = s->texinfo;
00169 //          cs->visible = s->visible;
00170 //          cs->original = s->original;
00171             cs->winding = cw[j];
00172             cs->flags &= ~SFL_TESTED;
00173         } //end for
00174     } //end for
00175 
00176 
00177     // see if we have valid polygons on both sides
00178 
00179     for (i=0 ; i<2 ; i++)
00180     {
00181         BoundBrush (b[i]);
00182         for (j=0 ; j<3 ; j++)
00183         {
00184             if (b[i]->mins[j] < -4096 || b[i]->maxs[j] > 4096)
00185             {
00186                 Log_Print("Q1_SplitBrush: bogus brush after clip\n");
00187                 break;
00188             } //end if
00189         } //end for
00190 
00191         if (b[i]->numsides < 3 || j < 3)
00192         {
00193             FreeBrush (b[i]);
00194             b[i] = NULL;
00195             Log_Print("Q1_SplitBrush: numsides < 3\n");
00196         } //end if
00197     } //end for
00198 
00199     if ( !(b[0] && b[1]) )
00200     {
00201         if (!b[0] && !b[1])
00202             Log_Print("Q1_SplitBrush: split removed brush\n");
00203         else
00204             Log_Print("Q1_SplitBrush: split not on both sides\n");
00205         if (b[0])
00206         {
00207             FreeBrush (b[0]);
00208             *front = CopyBrush (brush);
00209         } //end if
00210         if (b[1])
00211         {
00212             FreeBrush (b[1]);
00213             *back = CopyBrush (brush);
00214         } //end if
00215         return;
00216     } //end if
00217 
00218     // add the midwinding to both sides
00219     for (i = 0; i < 2; i++)
00220     {
00221         cs = &b[i]->sides[b[i]->numsides];
00222         b[i]->numsides++;
00223 
00224         cs->planenum = planenum^i^1;
00225         cs->texinfo = 0;
00226         //store the node number in the surf to find the texinfo later on
00227         cs->surf = nodenum;
00228         //
00229         cs->flags &= ~SFL_VISIBLE;
00230         cs->flags &= ~SFL_TESTED;
00231         cs->flags &= ~SFL_TEXTURED;
00232         if (i==0)
00233             cs->winding = CopyWinding (midwinding);
00234         else
00235             cs->winding = midwinding;
00236     } //end for
00237 
00238 
00239 {
00240     vec_t v1;
00241     int i;
00242 
00243     for (i=0 ; i<2 ; i++)
00244     {
00245         v1 = BrushVolume (b[i]);
00246         if (v1 < 1)
00247         {
00248             FreeBrush (b[i]);
00249             b[i] = NULL;
00250             Log_Print("Q1_SplitBrush: tiny volume after clip\n");
00251         } //end if
00252     } //end for
00253 } //*/
00254 
00255     *front = b[0];
00256     *back = b[1];
00257 } //end of the function Q1_SplitBrush

Here is the call graph for this function:

bspbrush_t* Q1_SplitBrushWithFace bspbrush_t brush,
q1_dface_t face
 

Definition at line 685 of file map_q1.c.

References abs(), bspbrush_t, CrossProduct(), q1_dplane_t::dist, DotProduct, FindFloatPlane(), q1_dface_t::firstedge, FreeBrush(), FreeBrushList(), i, Log_Print(), memcpy(), bspbrush_s::next, q1_dplane_t::normal, q1_dface_t::numedges, q1_dface_t::planenum, q1_dvertex_t::point, q1_dedges, q1_dplanes, q1_dsurfedges, q1_dvertexes, bspbrush_s::side, q1_dface_t::side, SplitBrush(), q1_dedge_t::v, v1, v2, vec3_t, vec_t, VectorNegate, VectorNormalize(), and VectorSubtract.

Referenced by Q1_TextureBrushes().

00686 {
00687