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

map_hl.c File Reference

#include "qbsp.h"
#include "l_bsp_hl.h"
#include "aas_map.h"

Include dependency graph for map_hl.c:

Include dependency graph

Go to the source code of this file.

Defines

#define HLCONTENTS

Functions

void HL_BSPBrushToMapBrush (bspbrush_t *bspbrush, entity_t *mapent)
bspbrush_tHL_CreateBrushes_r (bspbrush_t *brush, int nodenum)
bspbrush_tHL_CreateBrushesFromBSP (int modelnum)
void HL_CreateMapBrushes (entity_t *mapent, int modelnum)
float HL_FaceOnWinding (hl_dface_t *face, winding_t *winding)
void HL_FixContentsTextures (bspbrush_t *brushlist)
void HL_LoadMapFromBSP (char *filename, int offset, int length)
bspbrush_tHL_MergeBrushes (bspbrush_t *brushlist, int modelnum)
void HL_ResetMapLoading (void)
int HL_SolidTree_r (int nodenum)
void HL_SplitBrush (bspbrush_t *brush, int planenum, int nodenum, bspbrush_t **front, bspbrush_t **back)
bspbrush_tHL_SplitBrushWithFace (bspbrush_t *brush, hl_dface_t *face)
bspbrush_tHL_TextureBrushes (bspbrush_t *brushlist, int modelnum)
int HL_TextureContents (char *name)

Variables

int hl_numbrushes
int hl_numclipbrushes


Define Documentation

#define HLCONTENTS
 

Definition at line 31 of file map_hl.c.


Function Documentation

void HL_BSPBrushToMapBrush bspbrush_t bspbrush,
entity_t mapent
 

Definition at line 945 of file map_hl.c.

References AAS_CreateMapBrushes(), AddBrushBevels(), mapbrush_s::brushnum, brushsides, bspbrush_t, mapbrush_s::contents, side_s::contents, mapbrush_s::entitynum, Error(), entity_t::firstbrush, side_s::flags, hl_numclipbrushes, 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, bspbrush_s::side, side_t, bspbrush_s::sides, side_s::surf, side_s::texinfo, and side_s::winding.

Referenced by HL_CreateMapBrushes().

00946 {
00947     mapbrush_t *mapbrush;
00948     side_t *side;
00949     int i, besttexinfo;
00950 
00951     if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
00952     Error ("nummapbrushes == MAX_MAPFILE_BRUSHES");
00953 
00954     mapbrush = &mapbrushes[nummapbrushes];
00955     mapbrush->original_sides = &brushsides[nummapbrushsides];
00956     mapbrush->entitynum = mapent - entities;
00957     mapbrush->brushnum = nummapbrushes - mapent->firstbrush;
00958     mapbrush->leafnum = -1;
00959     mapbrush->numsides = 0;
00960 
00961     besttexinfo = TEXINFO_NODE;
00962     for (i = 0; i < bspbrush->numsides; i++)
00963     {
00964         if (!bspbrush->sides[i].winding) continue;
00965         //
00966         if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00967             Error ("MAX_MAPFILE_BRUSHSIDES");
00968         side = &brushsides[nummapbrushsides];
00969         //the contents of the bsp brush is stored in the side variable
00970         side->contents = bspbrush->side;
00971         side->surf = 0;
00972         side->planenum = bspbrush->sides[i].planenum;
00973         side->texinfo = bspbrush->sides[i].texinfo;
00974         if (side->texinfo != TEXINFO_NODE)
00975         {
00976             //this brush side is textured
00977             side->flags |= SFL_TEXTURED;
00978             besttexinfo = side->texinfo;
00979         } //end if
00980         //
00981         nummapbrushsides++;
00982         mapbrush->numsides++;
00983     } //end for
00984     //
00985     if (besttexinfo == TEXINFO_NODE)
00986     {
00987         mapbrush->numsides = 0;
00988         hl_numclipbrushes++;
00989         return;
00990     } //end if
00991     //set the texinfo for all the brush sides without texture
00992     for (i = 0; i < mapbrush->numsides; i++)
00993     {
00994         if (mapbrush->original_sides[i].texinfo == TEXINFO_NODE)
00995         {
00996             mapbrush->original_sides[i].texinfo = besttexinfo;
00997         } //end if
00998     } //end for
00999     //contents of the brush
01000     mapbrush->contents = bspbrush->side;
01001     //
01002     if (create_aas)
01003     {
01004         //create the AAS brushes from this brush, add brush bevels
01005         AAS_CreateMapBrushes(mapbrush, mapent, true);
01006         return;
01007     } //end if
01008     //create windings for sides and bounds for brush
01009     MakeBrushWindings(mapbrush);
01010     //add brush bevels
01011     AddBrushBevels(mapbrush);
01012     //a new brush has been created
01013     nummapbrushes++;
01014     mapent->numbrushes++;
01015 } //end of the function HL_BSPBrushToMapBrush

Here is the call graph for this function:

bspbrush_t* HL_CreateBrushes_r bspbrush_t brush,
int  nodenum
 

Definition at line 342 of file map_hl.c.

References bspbrush_t, hl_dleaf_t::contents, Error(), FindFloatPlane(), FreeBrush(), HL_CONTENTS_CLIP, HL_CONTENTS_CURRENT_0, HL_CONTENTS_CURRENT_180, HL_CONTENTS_CURRENT_270, HL_CONTENTS_CURRENT_90, HL_CONTENTS_CURRENT_DOWN, HL_CONTENTS_CURRENT_UP, HL_CONTENTS_EMPTY, HL_CONTENTS_LAVA, HL_CONTENTS_ORIGIN, HL_CONTENTS_SKY, HL_CONTENTS_SLIME, HL_CONTENTS_SOLID, HL_CONTENTS_TRANSLUCENT, HL_CONTENTS_WATER, hl_dleafs, hl_dnodes, hl_dplanes, hl_numbrushes, HL_SplitBrush(), Log_Print(), bspbrush_s::next, hl_dnode_t::planenum, qprintf(), and bspbrush_s::side.

Referenced by HL_CreateBrushesFromBSP().

00343 {
00344     int planenum;
00345     bspbrush_t *front, *back;
00346     hl_dleaf_t *leaf;
00347 
00348     //if it is a leaf
00349     if (nodenum < 0)
00350     {
00351         leaf = &hl_dleafs[(-nodenum) - 1];
00352         if (leaf->contents != HL_CONTENTS_EMPTY)
00353         {
00354 #ifdef HL_PRINT
00355             qprintf("\r%5i", ++hl_numbrushes);
00356 #endif //HL_PRINT
00357         } //end if
00358         switch(leaf->contents)
00359         {
00360             case HL_CONTENTS_EMPTY:
00361             {
00362                 FreeBrush(brush);
00363                 return NULL;
00364             } //end case
00365             case HL_CONTENTS_SOLID:
00366 #ifdef HLCONTENTS
00367             case HL_CONTENTS_CLIP:
00368 #endif //HLCONTENTS
00369             case HL_CONTENTS_SKY:
00370 #ifdef HLCONTENTS
00371             case HL_CONTENTS_TRANSLUCENT:
00372 #endif //HLCONTENTS
00373             {
00374                 brush->side = CONTENTS_SOLID;
00375                 return brush;
00376             } //end case
00377             case HL_CONTENTS_WATER:
00378             {
00379                 brush->side = CONTENTS_WATER;
00380                 return brush;
00381             } //end case
00382             case HL_CONTENTS_SLIME:
00383             {
00384                 brush->side = CONTENTS_SLIME;
00385                 return brush;
00386             } //end case
00387             case HL_CONTENTS_LAVA:
00388             {
00389                 brush->side = CONTENTS_LAVA;
00390                 return brush;
00391             } //end case
00392 #ifdef HLCONTENTS
00393             //these contents should not be found in the BSP
00394             case HL_CONTENTS_ORIGIN:
00395             case HL_CONTENTS_CURRENT_0:
00396             case HL_CONTENTS_CURRENT_90:
00397             case HL_CONTENTS_CURRENT_180:
00398             case HL_CONTENTS_CURRENT_270:
00399             case HL_CONTENTS_CURRENT_UP:
00400             case HL_CONTENTS_CURRENT_DOWN:
00401             {
00402                 Error("HL_CreateBrushes_r: found contents %d in Half-Life BSP", leaf->contents);
00403                 return NULL;
00404             } //end case
00405 #endif //HLCONTENTS
00406             default:
00407             {
00408                 Error("HL_CreateBrushes_r: unknown contents %d in Half-Life BSP", leaf->contents);
00409                 return NULL;
00410             } //end default
00411         } //end switch
00412         return NULL;
00413     } //end if
00414     //if the rest of the tree is solid
00415     /*if (HL_SolidTree_r(nodenum))
00416     {
00417         brush->side = CONTENTS_SOLID;
00418         return brush;
00419     } //end if*/
00420     //
00421     planenum = hl_dnodes[nodenum].planenum;
00422     planenum = FindFloatPlane(hl_dplanes[planenum].normal, hl_dplanes[planenum].dist);
00423     //split the brush with the node plane
00424     HL_SplitBrush(brush, planenum, nodenum, &front, &back);
00425     //free the original brush
00426     FreeBrush(brush);
00427     //every node must split the brush in two
00428     if (!front || !back)
00429     {
00430         Log_Print("HL_CreateBrushes_r: WARNING node not splitting brush\n");
00431         //return NULL;
00432     } //end if
00433     //create brushes recursively
00434     if (front) front = HL_CreateBrushes_r(front, hl_dnodes[nodenum].children[0]);
00435     if (back) back = HL_CreateBrushes_r(back, hl_dnodes[nodenum].children[1]);
00436     //link the brushes if possible and return them
00437     if (front)
00438     {
00439         for (brush = front; brush->next; brush = brush->next);
00440         brush->next = back;
00441         return front;
00442     } //end if
00443     else
00444     {
00445         return back;
00446     } //end else
00447 } //end of the function HL_CreateBrushes_r

Here is the call graph for this function:

bspbrush_t* HL_CreateBrushesFromBSP int  modelnum  ) 
 

Definition at line 454 of file map_hl.c.

References AddPointToBounds(), BrushFromBounds(), bspbrush_t, hl_dmodel_t::headnode, HL_CreateBrushes_r(), hl_dmodels, hl_dnodes, hl_numbrushes, i, Log_Print(), map_maxs, map_mins, bspbrush_s::maxs, hl_dnode_t::maxs, bspbrush_s::mins, hl_dnode_t::mins, qprintf(), vec3_t, and VectorCopy.

Referenced by HL_CreateMapBrushes().

00455 {
00456     bspbrush_t *brushlist;
00457     bspbrush_t *brush;
00458     hl_dnode_t *headnode;
00459     vec3_t mins, maxs;
00460     int i;
00461 
00462     //
00463     headnode = &hl_dnodes[hl_dmodels[modelnum].headnode[0]];
00464     //get the mins and maxs of the world
00465     VectorCopy(headnode->mins, mins);
00466     VectorCopy(headnode->maxs, maxs);
00467     //enlarge these mins and maxs
00468     for (i = 0; i < 3; i++)
00469     {
00470         mins[i] -= 8;
00471         maxs[i] += 8;
00472     } //end for
00473     //NOTE: have to add the BSP tree mins and maxs to the MAP mins and maxs
00474     AddPointToBounds(mins, map_mins, map_maxs);
00475     AddPointToBounds(maxs, map_mins, map_maxs);
00476     //
00477     if (!modelnum)
00478     {
00479         Log_Print("brush size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n",
00480                             map_mins[0], map_mins[1], map_mins[2],
00481                             map_maxs[0], map_maxs[1], map_maxs[2]);
00482     } //end if
00483     //create one huge brush containing the whole world
00484     brush = BrushFromBounds(mins, maxs);
00485     VectorCopy(mins, brush->mins);
00486     VectorCopy(maxs, brush->maxs);
00487     //
00488 #ifdef HL_PRINT
00489     qprintf("creating Half-Life brushes\n");
00490     qprintf("%5d brushes", hl_numbrushes = 0);
00491 #endif //HL_PRINT
00492     //create the brushes
00493     brushlist = HL_CreateBrushes_r(brush, hl_dmodels[modelnum].headnode[0]);
00494     //
00495 #ifdef HL_PRINT
00496     qprintf("\n");
00497 #endif //HL_PRINT
00498     //now we've got a list with brushes!
00499     return brushlist;
00500 } //end of the function HL_CreateBrushesFromBSP

Here is the call graph for this function:

void HL_CreateMapBrushes entity_t mapent,
int  modelnum
 

Definition at line 1022 of file map_hl.c.

References bspbrush_t, FreeBrush(), HL_BSPBrushToMapBrush(), HL_CreateBrushesFromBSP(), HL_FixContentsTextures(), HL_MergeBrushes(), HL_TextureBrushes(), i, mapent, bspbrush_s::next, and qprintf().

Referenced by HL_LoadMapFromBSP().

01023 {
01024     bspbrush_t *brushlist, *brush, *nextbrush;
01025     int i;
01026 
01027     //create brushes from the model BSP tree
01028     brushlist = HL_CreateBrushesFromBSP(modelnum);
01029     //texture the brushes and split them when necesary
01030     brushlist = HL_TextureBrushes(brushlist, modelnum);
01031     //fix the contents textures of all brushes
01032     HL_FixContentsTextures(brushlist);
01033     //
01034     if (!nobrushmerge)
01035     {
01036         brushlist = HL_MergeBrushes(brushlist, modelnum);
01037         //brushlist = HL_MergeBrushes(brushlist, modelnum);
01038     } //end if
01039     //
01040     if (!modelnum) qprintf("converting brushes to map brushes\n");
01041     if (!modelnum) qprintf("%5d brushes", i = 0);
01042     for (brush = brushlist; brush; brush = nextbrush)
01043     {
01044         nextbrush = brush->next;
01045         HL_BSPBrushToMapBrush(brush, mapent);
01046         brush->next = NULL;
01047         FreeBrush(brush);
01048         if (!modelnum) qprintf("\r%5d", ++i);
01049     } //end for
01050     if (!modelnum) qprintf("\n");
01051 } //end of the function HL_CreateMapBrushes

Here is the call graph for this function:

float HL_FaceOnWinding hl_dface_t face,
winding_t winding
 

Definition at line 578 of file map_hl.c.

References abs(), ChopWindingInPlace(), CopyWinding(), CrossProduct(), hl_dplane_t::dist, DotProduct, hl_dface_t::firstedge, FreeWinding(), hl_dedges, hl_dplanes, hl_dsurfedges, hl_dvertexes, i, memcpy(), hl_dplane_t::normal, hl_dface_t::numedges, hl_dface_t::planenum, hl_dvertex_t::point, hl_dface_t::side, hl_dedge_t::v, v1, v2, vec3_t, vec_t, VectorNegate, VectorNormalize(), VectorSubtract, w, and WindingArea().

Referenced by HL_TextureBrushes().

00579 {
00580     int i, edgenum, side;
00581     float dist, area;
00582     hl_dplane_t plane;
00583     vec_t *v1, *v2;
00584     vec3_t normal, edgevec;
00585     winding_t *w;
00586 
00587     //
00588     w = CopyWinding(winding);
00589     memcpy(&plane, &hl_dplanes[face->planenum], sizeof(hl_dplane_t));
00590     //check on which side of the plane the face is
00591     if (face->side)
00592     {
00593         VectorNegate(plane.normal, plane.normal);
00594         plane.dist = -plane.dist;
00595     } //end if
00596     for (i = 0; i < face->numedges && w; i++)
00597     {
00598         //get the first and second vertex of the edge
00599         edgenum = hl_dsurfedges[face->firstedge + i];
00600         side = edgenum > 0;
00601         //if the face plane is flipped
00602         v1 = hl_dvertexes[hl_dedges[abs(edgenum)].v[side]].point;
00603         v2 = hl_dvertexes[hl_dedges[abs(edgenum)].v[!side]].point;
00604         //create a plane through the edge vector, orthogonal to the face plane
00605         //and with the normal vector pointing out of the face
00606         VectorSubtract(v1, v2, edgevec);
00607         CrossProduct(edgevec, plane.normal, normal);
00608         VectorNormalize(normal);
00609         dist = DotProduct(normal, v1);
00610         //
00611         ChopWindingInPlace(&w, normal, dist, 0.9); //CLIP_EPSILON
00612     } //end for
00613     if (w)
00614     {
00615         area = WindingArea(w);
00616         FreeWinding(w);
00617         return area;
00618     } //end if
00619     return 0;
00620 } //end of the function HL_FaceOnWinding

Here is the call graph for this function:

void HL_FixContentsTextures bspbrush_t brushlist  ) 
 

Definition at line 883 of file map_hl.c.

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

Referenced by HL_CreateMapBrushes().

00884 {
00885     int i, texinfonum;
00886     bspbrush_t *brush;
00887 
00888     for (brush = brushlist; brush; brush = brush->next)
00889     {
00890         //only fix the textures of water, slime and lava brushes
00891         if (brush->side != CONTENTS_WATER &&
00892             brush->side != CONTENTS_SLIME &&
00893             brush->side != CONTENTS_LAVA) continue;
00894         //
00895         for (i = 0; i < brush->numsides; i++)
00896         {
00897             texinfonum = brush->sides[i].texinfo;
00898             if (HL_TextureContents(map_texinfo[texinfonum].texture) == brush->side) break;
00899         } //end for
00900         //if no specific contents texture was found
00901         if (i >= brush->numsides)
00902         {
00903             texinfonum = -1;
00904             for (i = 0; i < map_numtexinfo; i++)
00905             {
00906                 if (HL_TextureContents(map_texinfo[i].texture) == brush->side)
00907                 {
00908                     texinfonum = i;
00909                     break;
00910                 } //end if
00911             } //end for
00912         } //end if
00913         //
00914         if (texinfonum >= 0)
00915         {
00916             //give all the brush sides this contents texture
00917             for (i = 0; i < brush->numsides; i++)
00918             {
00919                 brush->sides[i].texinfo = texinfonum;
00920             } //end for
00921         } //end if
00922         else Log_Print("brush contents %d with wrong textures\n", brush->side);
00923         //
00924     } //end for
00925     /*
00926     for (brush = brushlist; brush; brush = brush->next)
00927     {
00928         //give all the brush sides this contents texture
00929         for (i = 0; i < brush->numsides; i++)
00930         {
00931             if (HL_TextureContents(map_texinfo[texinfonum].texture) != brush->side)
00932             {
00933                 Error("brush contents %d with wrong contents textures %s\n", brush->side,
00934                             HL_TextureContents(map_texinfo[texinfonum].texture));
00935             } //end if
00936         } //end for
00937     } //end for*/
00938 } //end of the function HL_FixContentsTextures

Here is the call graph for this function:

void HL_LoadMapFromBSP char *  filename,
int  offset,
int  length
 

Definition at line 1067 of file map_hl.c.

References atoi, ClearBounds(), entities, entity_t::firstbrush, HL_CreateMapBrushes(), HL_LoadBSPFile(), hl_numclipbrushes, HL_ParseEntities(), i, length(), loadedmaptype, Log_Print(), map_maxs, map_mins, entity_t::numbrushes, nummapbrushes, offset, qprintf(), strcmp(), and ValueForKey().

Referenced by LoadMapFromBSP().

01068 {
01069     int i, modelnum;
01070     char *model, *classname;
01071 
01072     Log_Print("-- HL_LoadMapFromBSP --\n");
01073     //loaded map type
01074     loadedmaptype = MAPTYPE_HALFLIFE;
01075     //
01076     qprintf("loading map from %s at %d\n", filename, offset);
01077     //load the Half-Life BSP file
01078     HL_LoadBSPFile(filename, offset, length);
01079     //
01080     hl_numclipbrushes = 0;
01081     //parse the entities from the BSP
01082     HL_ParseEntities();
01083     //clear the map mins and maxs
01084     ClearBounds(map_mins, map_maxs);
01085     //
01086     qprintf("creating Half-Life brushes\n");
01087     if (lessbrushes) qprintf("creating minimum number of brushes\n");
01088     else qprintf("placing textures correctly\n");
01089     //
01090     for (i = 0; i < num_entities; i++)
01091     {
01092         entities[i].firstbrush = nummapbrushes;
01093         entities[i].numbrushes = 0;
01094         //
01095         classname = ValueForKey(&entities[i], "classname");
01096         if (classname && !strcmp(classname, "worldspawn"))
01097         {
01098             modelnum = 0;
01099         } //end if
01100         else
01101         {
01102             //
01103             model = ValueForKey(&entities[i], "model");
01104             if (!model || *model != '*') continue;
01105             model++;
01106             modelnum = atoi(model);
01107         } //end else
01108         //create map brushes for the entity
01109         HL_CreateMapBrushes(&entities[i], modelnum);
01110     } //end for
01111     //
01112     qprintf("%5d map brushes\n", nummapbrushes);
01113     qprintf("%5d clip brushes\n", hl_numclipbrushes);
01114 } //end of the function HL_LoadMapFromBSP

Here is the call graph for this function:

bspbrush_t* HL_MergeBrushes bspbrush_t brushlist,
int  modelnum
 

Definition at line 507 of file map_hl.c.

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

Referenced by HL_CreateMapBrushes().

00508 {
00509     int nummerges, merged;
00510     bspbrush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
00511     bspbrush_t *lastb2;
00512 
00513     if (!brushlist) return NULL;
00514 
00515     if (!modelnum) qprintf("%5d brushes merged", nummerges = 0);
00516     do
00517     {
00518         for (tail = brushlist; tail; tail = tail->next)
00519         {
00520             if (!tail->next) break;
00521         } //end for
00522         merged = 0;
00523         newbrushlist = NULL;
00524         for (b1 = brushlist; b1; b1 = brushlist)
00525         {
00526             lastb2 = b1;
00527             for (b2 = b1->next; b2; b2 = b2->next)
00528             {
00529                 //can't merge brushes with different contents
00530                 if (b1->side != b2->side) newbrush = NULL;
00531                 else newbrush = TryMergeBrushes(b1, b2);
00532                 //if a merged brush is created
00533                 if (newbrush)
00534                 {
00535                     //copy the brush contents
00536                     newbrush->side = b1->side;
00537                     //add the new brush to the end of the list
00538                     tail->next = newbrush;
00539                     //remove the second brush from the list
00540                     lastb2->next = b2->next;
00541                     //remove the first brush from the list
00542                     brushlist = brushlist->next;
00543                     //free the merged brushes
00544                     FreeBrush(b1);
00545                     FreeBrush(b2);
00546                     //get a new tail brush
00547                     for (tail = brushlist; tail; tail = tail->next)
00548                     {
00549                         if (!tail->next) break;
00550                     } //end for
00551                     merged++;
00552                     if (!modelnum) qprintf("\r%5d", nummerges++);
00553                     break;
00554                 } //end if
00555                 lastb2 = b2;
00556             } //end for
00557             //if b1 can't be merged with any of the other brushes
00558             if (!b2)
00559             {
00560                 brushlist = brushlist->next;
00561                 //keep b1
00562                 b1->next = newbrushlist;
00563                 newbrushlist = b1;
00564             } //end else
00565         } //end for
00566         brushlist = newbrushlist;
00567     } while(merged);
00568     if (!modelnum) qprintf("\n");
00569     return newbrushlist;
00570 } //end of the function HL_MergeBrushes

Here is the call graph for this function:

void HL_ResetMapLoading void   ) 
 

Definition at line 1058 of file map_hl.c.

01059 {
01060 } //end of the function HL_ResetMapLoading

int HL_SolidTree_r int  nodenum  ) 
 

Definition at line 291 of file map_hl.c.

References hl_dleaf_t::contents, HL_CONTENTS_CLIP, HL_CONTENTS_CURRENT_0, HL_CONTENTS_CURRENT_180, HL_CONTENTS_CURRENT_270, HL_CONTENTS_CURRENT_90, HL_CONTENTS_CURRENT_DOWN, HL_CONTENTS_CURRENT_UP, HL_CONTENTS_EMPTY, HL_CONTENTS_LAVA, HL_CONTENTS_ORIGIN, HL_CONTENTS_SKY, HL_CONTENTS_SLIME, HL_CONTENTS_SOLID, HL_CONTENTS_TRANSLUCENT, HL_CONTENTS_WATER, hl_dleafs, and hl_dnodes.

00292 {
00293     if (nodenum < 0)
00294     {
00295         switch(hl_dleafs[(-nodenum) - 1].contents)
00296         {
00297             case HL_CONTENTS_EMPTY:
00298             {
00299                 return false;
00300             } //end case
00301             case HL_CONTENTS_SOLID:
00302 #ifdef HLCONTENTS
00303             case HL_CONTENTS_CLIP:
00304 #endif //HLCONTENTS
00305             case HL_CONTENTS_SKY:
00306 #ifdef HLCONTENTS
00307             case HL_CONTENTS_TRANSLUCENT:
00308 #endif //HLCONTENTS
00309             {
00310                 return true;
00311             } //end case
00312             case HL_CONTENTS_WATER:
00313             case HL_CONTENTS_SLIME:
00314             case HL_CONTENTS_LAVA:
00315 #ifdef HLCONTENTS
00316             //these contents should not be found in the BSP
00317             case HL_CONTENTS_ORIGIN:
00318             case HL_CONTENTS_CURRENT_0:
00319             case HL_CONTENTS_CURRENT_90:
00320             case HL_CONTENTS_CURRENT_180:
00321             case HL_CONTENTS_CURRENT_270:
00322             case HL_CONTENTS_CURRENT_UP:
00323             case HL_CONTENTS_CURRENT_DOWN:
00324 #endif //HLCONTENTS
00325             default:
00326             {
00327                 return false;
00328             } //end default
00329         } //end switch
00330         return false;
00331     } //end if
00332     if (!HL_SolidTree_r(hl_dnodes[nodenum].children[0])) return false;
00333     if (!HL_SolidTree_r(hl_dnodes[nodenum].children[1])) return false;
00334     return true;
00335 } //end of the function HL_SolidTree_r

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

Definition at line 90 of file map_hl.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 HL_CreateBrushes_r().

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

Here is the call graph for this function:

bspbrush_t* HL_SplitBrushWithFace bspbrush_t brush,
hl_dface_t face
 

Definition at line 629 of file map_hl.c.

References abs(), bspbrush_t, CrossProduct(), hl_dplane_t::dist, DotProduct, FindFloatPlane(), hl_dface_t::firstedge, FreeBrush(), FreeBrushList(), hl_dedges, hl_dplanes, hl_dsurfedges, hl_dvertexes, i, Log_Print(), memcpy(), bspbrush_s::next, hl_dplane_t::normal, hl_dface_t::numedges, hl_dface_t::planenum, hl_dvertex_t::point, bspbrush_s::side, hl_dface_t::side, SplitBrush(), hl_dedge_t::v, v1, v2, vec3_t, vec_t, VectorNegate, VectorNormalize(), and VectorSubtract.

Referenced by HL_TextureBrushes().

00630 {
00631     int i, edgenum, side, planenum, splits;
00632     float dist;
00633     hl_dplane_t plane;
00634     vec_t *v1, *v2;
00635     vec3_t normal, edgevec;
00636     bspbrush_t *front, *back, *brushlist;
00637 
00638     memcpy(&plane, &hl_dplanes[face->planenum], sizeof(hl_dplane_t));
00639     //check on which side of the plane the face is
00640     if (face->side)
00641     {
00642         VectorNegate(plane.normal, plane.normal);
00643         plane.dist = -plane.dist;
00644     } //end if
00645     splits = 0;
00646     brushlist = NULL;
00647     for (i = 0; i < face->numedges; i++)
00648     {
00649         //get the first and second vertex of the edge
00650         edgenum = hl_dsurfedges[face->firstedge + i];
00651         side = edgenum > 0;
00652         //if the face plane is flipped
00653         v1 = hl_dvertexes[hl_dedges[abs(edgenum)].v[side]].point;
00654         v2 = hl_dvertexes[hl_dedges[abs(edgenum)].v[!side]].point;
00655         //create a plane through the edge vector, orthogonal to the face plane
00656         //and with the normal vector pointing out of the face
00657         VectorSubtract(v1, v2, edgevec);
00658         CrossProduct(edgevec, plane.normal, normal);
00659         VectorNormalize(normal);
00660         dist = DotProduct(normal, v1);
00661         //
00662         planenum = FindFloatPlane(normal, dist);
00663         //split the current brush
00664         SplitBrush(brush, planenum, &front, &back);
00665         //if there is a back brush just put it in the list
00666         if (back)
00667         {
00668             //copy the brush contents
00669             back->side = brush->side;
00670             //
00671             back->next = brushlist;
00672             brushlist = back;
00673             splits++;
00674         } //end if
00675         if (!front)
00676         {
00677             Log_Print("HL_SplitBrushWithFace: no new brush\n");
00678             FreeBrushList(brushlist);
00679             return NULL;
00680         } //end if
00681         //copy the brush contents
00682         front->side = brush->side;
00683         //continue splitting the front brush
00684         brush = front;
00685     } //end for
00686     if (!splits)
00687     {
00688         FreeBrush(front);
00689         return NULL;
00690     } //end if
00691     front->next = brushlist;
00692     brushlist = front;
00693     return brushlist;
00694 } //end of the function HL_SplitBrushWithFace

Here is the call graph for this function:

bspbrush_t* HL_TextureBrushes bspbrush_t brushlist,
int  modelnum
 

Definition at line 701 of file map_hl.c.

References bspbrush_t, byte, hl_dmiptexlump_t::dataofs, hl_texinfo_s::flags, map_texinfo_t::flags, side_s::flags, FreeBrush(), hl_dfaces, hl_dnodes, HL_FaceOnWinding(), hl_miptex_t, HL_SplitBrushWithFace(), hl_texinfo, i, Log_Write(), map_numtexinfo, map_texinfo, memcpy(), hl_texinfo_s::miptex, n, hl_miptex_s::name, bspbrush_s::next, map_texinfo_t::nexttexinfo, numbrushes, bspbrush_s::numsides, hl_dnode_t::planenum, hl_dface_t::planenum, qprintf(), side_t, bspbrush_s::sides, strcpy(), side_s::surf, side_s::texinfo, hl_dface_t::texinfo, texture, map_texinfo_t::value, vec_t, vecs, hl_texinfo_s::vecs, map_texinfo_t::vecs, VectorLength(), and side_s::winding.

Referenced by HL_CreateMapBrushes().

00702 {
00703     float area, largestarea;
00704     int i, n, texinfonum, sn, numbrushes, ofs;
00705     int bestfacenum, sidenodenum;
00706     side_t *side;
00707     hl_dmiptexlump_t *miptexlump;
00708     hl_miptex_t *miptex;
00709     bspbrush_t *brush, *nextbrush, *prevbrush, *newbrushes, *brushlistend;
00710     vec_t defaultvec[4] = {1, 0, 0, 0};
00711 
00712     if (!modelnum) qprintf("texturing brushes\n");
00713     if (!modelnum) qprintf("%5d brushes", numbrushes = 0);
00714     //get a pointer to the last brush in the list
00715     for (brushlistend = brushlist; brushlistend; brushlistend = brushlistend->next)
00716     {
00717         if (!brushlistend->