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

map_q2.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 //===========================================================================
00024 // ANSI, Area Navigational System Interface
00025 // AAS,  Area Awareness System
00026 //===========================================================================
00027 
00028 #include "qbsp.h"
00029 #include "l_mem.h"
00030 #include "../botlib/aasfile.h"          //aas_bbox_t
00031 #include "aas_store.h"      //AAS_MAX_BBOXES
00032 #include "aas_cfg.h"
00033 #include "aas_map.h"            //AAS_CreateMapBrushes
00034 #include "l_bsp_q2.h"
00035 
00036 
00037 #ifdef ME
00038 
00039 #define NODESTACKSIZE       1024
00040 
00041 int nodestack[NODESTACKSIZE];
00042 int *nodestackptr;
00043 int nodestacksize = 0;
00044 int brushmodelnumbers[MAX_MAPFILE_BRUSHES];
00045 int dbrushleafnums[MAX_MAPFILE_BRUSHES];
00046 int dplanes2mapplanes[MAX_MAPFILE_PLANES];
00047 
00048 #endif //ME
00049 
00050 //====================================================================
00051 
00052 //===========================================================================
00053 //
00054 // Parameter:               -
00055 // Returns:                 -
00056 // Changes Globals:     -
00057 //===========================================================================
00058 void Q2_CreateMapTexinfo(void)
00059 {
00060     int i;
00061 
00062     for (i = 0; i < numtexinfo; i++)
00063     {
00064         memcpy(map_texinfo[i].vecs, texinfo[i].vecs, sizeof(float) * 2 * 4);
00065         map_texinfo[i].flags = texinfo[i].flags;
00066         map_texinfo[i].value = texinfo[i].value;
00067         strcpy(map_texinfo[i].texture, texinfo[i].texture);
00068         map_texinfo[i].nexttexinfo = 0;
00069     } //end for
00070 } //end of the function Q2_CreateMapTexinfo
00071 
00072 /*
00073 ===========
00074 Q2_BrushContents
00075 ===========
00076 */
00077 int Q2_BrushContents (mapbrush_t *b)
00078 {
00079     int         contents;
00080     side_t      *s;
00081     int         i;
00082     int         trans;
00083 
00084     s = &b->original_sides[0];
00085     contents = s->contents;
00086     trans = texinfo[s->texinfo].flags;
00087     for (i = 1; i < b->numsides; i++, s++)
00088     {
00089         s = &b->original_sides[i];
00090         trans |= texinfo[s->texinfo].flags;
00091         if (s->contents != contents)
00092         {
00093             Log_Print("Entity %i, Brush %i: mixed face contents\n"
00094                 , b->entitynum, b->brushnum);
00095             Log_Print("texture name = %s\n", texinfo[s->texinfo].texture);
00096             break;
00097         }
00098     }
00099 
00100     // if any side is translucent, mark the contents
00101     // and change solid to window
00102     if ( trans & (SURF_TRANS33|SURF_TRANS66) )
00103     {
00104         contents |= CONTENTS_Q2TRANSLUCENT;
00105         if (contents & CONTENTS_SOLID)
00106         {
00107             contents &= ~CONTENTS_SOLID;
00108             contents |= CONTENTS_WINDOW;
00109         }
00110     }
00111 
00112     return contents;
00113 }
00114 
00115 #ifdef ME
00116 
00117 #define BBOX_NORMAL_EPSILON         0.0001
00118 
00119 //===========================================================================
00120 //
00121 // Parameter:               -
00122 // Returns:                 -
00123 // Changes Globals:     -
00124 //===========================================================================
00125 void MakeAreaPortalBrush(mapbrush_t *brush)
00126 {
00127     int sn;
00128     side_t *s;
00129 
00130     brush->contents = CONTENTS_AREAPORTAL;
00131 
00132     for (sn = 0; sn < brush->numsides; sn++)
00133     {
00134         s = brush->original_sides + sn;
00135         //make sure the surfaces are not hint or skip
00136         s->surf &= ~(SURF_HINT|SURF_SKIP);
00137         //
00138         s->texinfo = 0;
00139         s->contents = CONTENTS_AREAPORTAL;
00140     } //end for
00141 } //end of the function MakeAreaPortalBrush
00142 //===========================================================================
00143 //
00144 // Parameter:               -
00145 // Returns:                 -
00146 // Changes Globals:     -
00147 //===========================================================================
00148 void DPlanes2MapPlanes(void)
00149 {
00150     int i;
00151 
00152     for (i = 0; i < numplanes; i++)
00153     {
00154         dplanes2mapplanes[i] = FindFloatPlane(dplanes[i].normal, dplanes[i].dist);
00155     } //end for
00156 } //end of the function DPlanes2MapPlanes
00157 //===========================================================================
00158 //
00159 // Parameter:               -
00160 // Returns:                 -
00161 // Changes Globals:     -
00162 //===========================================================================
00163 void MarkVisibleBrushSides(mapbrush_t *brush)
00164 {
00165     int n, i, planenum;
00166     side_t *side;
00167     dface_t *face;
00168     //
00169     for (n = 0; n < brush->numsides; n++)
00170     {
00171         side = brush->original_sides + n;
00172         //if this side is a bevel or the leaf number of the brush is unknown
00173         if ((side->flags & SFL_BEVEL) || brush->leafnum < 0)
00174         {
00175             //this side is a valid splitter
00176             side->flags |= SFL_VISIBLE;
00177             continue;
00178         } //end if
00179         //assum this side will not be used as a splitter
00180         side->flags &= ~SFL_VISIBLE;
00181         //check if the side plane is used by a visible face
00182         for (i = 0; i < numfaces; i++)
00183         {
00184             face = &dfaces[i];
00185             planenum = dplanes2mapplanes[face->planenum];
00186             if ((planenum & ~1) == (side->planenum & ~1))
00187             {
00188                 //this side is a valid splitter
00189                 side->flags |= SFL_VISIBLE;
00190             } //end if
00191         } //end for
00192     } //end for
00193 } //end of the function MarkVisibleBrushSides
00194 
00195 #endif //ME
00196 
00197 /*
00198 =================
00199 Q2_ParseBrush
00200 =================
00201 */
00202 void Q2_ParseBrush (script_t *script, entity_t *mapent)
00203 {
00204     mapbrush_t *b;
00205     int i, j, k;
00206     int mt;
00207     side_t *side, *s2;
00208     int planenum;
00209     brush_texture_t td;
00210     int planepts[3][3];
00211     token_t token;
00212 
00213     if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
00214         Error ("nummapbrushes == MAX_MAPFILE_BRUSHES");
00215 
00216     b = &mapbrushes[nummapbrushes];
00217     b->original_sides = &brushsides[nummapbrushsides];
00218     b->entitynum = num_entities-1;
00219     b->brushnum = nummapbrushes - mapent->firstbrush;
00220     b->leafnum = -1;
00221 
00222     do
00223     {
00224         if (!PS_ReadToken(script, &token))
00225             break;
00226         if (!strcmp(token.string, "}") )
00227             break;
00228 
00229         //IDBUG: mixed use of MAX_MAPFILE_? and MAX_MAP_? this could
00230         //          lead to out of bound indexing of the arrays
00231         if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00232             Error ("MAX_MAPFILE_BRUSHSIDES");
00233         side = &brushsides[nummapbrushsides];
00234 
00235         //read the three point plane definition
00236         for (i = 0; i < 3; i++)
00237         {
00238             if (i != 0) PS_ExpectTokenString(script, "(");
00239             for (j = 0; j < 3; j++)
00240             {
00241                 PS_ExpectAnyToken(script, &token);
00242                 planepts[i][j] = atof(token.string);
00243             } //end for
00244             PS_ExpectTokenString(script, ")");
00245         } //end for
00246 
00247         //
00248         //read the texturedef
00249         //
00250         PS_ExpectAnyToken(script, &token);
00251         strcpy(td.name, token.string);
00252 
00253         PS_ExpectAnyToken(script, &token);
00254         td.shift[0] = atol(token.string);
00255         PS_ExpectAnyToken(script, &token);
00256         td.shift[1] = atol(token.string);
00257         PS_ExpectAnyToken(script, &token);
00258         td.rotate = atol(token.string);
00259         PS_ExpectAnyToken(script, &token);
00260         td.scale[0] = atof(token.string);
00261         PS_ExpectAnyToken(script, &token);
00262         td.scale[1] = atof(token.string);
00263 
00264         //find default flags and values
00265         mt = FindMiptex (td.name);
00266         td.flags = textureref[mt].flags;
00267         td.value = textureref[mt].value;
00268         side->contents = textureref[mt].contents;
00269         side->surf = td.flags = textureref[mt].flags;
00270 
00271         //check if there's a number available
00272         if (PS_CheckTokenType(script, TT_NUMBER, 0, &token))
00273         {
00274             side->contents = token.intvalue;
00275             PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
00276             side->surf = td.flags = token.intvalue;
00277             PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
00278             td.value = token.intvalue;
00279         }
00280 
00281         // translucent objects are automatically classified as detail
00282         if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
00283             side->contents |= CONTENTS_DETAIL;
00284         if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00285             side->contents |= CONTENTS_DETAIL;
00286         if (fulldetail)
00287             side->contents &= ~CONTENTS_DETAIL;
00288         if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
00289             | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
00290             side->contents |= CONTENTS_SOLID;
00291 
00292         // hints and skips are never detail, and have no content
00293         if (side->surf & (SURF_HINT|SURF_SKIP) )
00294         {
00295             side->contents = 0;
00296             side->surf &= ~CONTENTS_DETAIL;
00297         }
00298 
00299 #ifdef ME
00300         //for creating AAS... this side is textured
00301         side->flags |= SFL_TEXTURED;
00302 #endif //ME
00303         //
00304         // find the plane number
00305         //
00306         planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
00307         if (planenum == -1)
00308         {
00309             Log_Print("Entity %i, Brush %i: plane with no normal\n"
00310                 , b->entitynum, b->brushnum);
00311             continue;
00312         }
00313 
00314         //
00315         // see if the plane has been used already
00316         //
00317         for (k=0 ; k<b->numsides ; k++)
00318         {
00319             s2 = b->original_sides + k;
00320             if (s2->planenum == planenum)
00321             {
00322                 Log_Print("Entity %i, Brush %i: duplicate plane\n"
00323                     , b->entitynum, b->brushnum);
00324                 break;
00325             }
00326             if ( s2->planenum == (planenum^1) )
00327             {
00328                 Log_Print("Entity %i, Brush %i: mirrored plane\n"
00329                     , b->entitynum, b->brushnum);
00330                 break;
00331             }
00332         }
00333         if (k != b->numsides)
00334             continue;       // duplicated
00335 
00336         //
00337         // keep this side
00338         //
00339 
00340         side = b->original_sides + b->numsides;
00341         side->planenum = planenum;
00342         side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
00343             &td, vec3_origin);
00344 
00345         // save the td off in case there is an origin brush and we
00346         // have to recalculate the texinfo
00347         side_brushtextures[nummapbrushsides] = td;
00348 
00349         nummapbrushsides++;
00350         b->numsides++;
00351     } while (1);
00352 
00353     // get the content for the entire brush
00354     b->contents = Q2_BrushContents (b);
00355 
00356 #ifdef ME
00357     if (BrushExists(b))
00358     {
00359         c_squattbrushes++;
00360         b->numsides = 0;
00361         return;
00362     } //end if
00363 
00364     if (create_aas)
00365     {
00366         //create AAS brushes, and add brush bevels
00367         AAS_CreateMapBrushes(b, mapent, true);
00368         //NOTE: if we return here then duplicate plane errors occur for the non world entities
00369         return;
00370     } //end if
00371 #endif //ME
00372 
00373     // allow detail brushes to be removed 
00374     if (nodetail && (b->contents & CONTENTS_DETAIL) )
00375     {
00376         b->numsides = 0;
00377         return;
00378     }
00379 
00380     // allow water brushes to be removed
00381     if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
00382     {
00383         b->numsides = 0;
00384         return;
00385     }
00386 
00387     // create windings for sides and bounds for brush
00388     MakeBrushWindings (b);
00389 
00390     // brushes that will not be visible at all will never be
00391     // used as bsp splitters
00392     if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00393     {
00394         c_clipbrushes++;
00395         for (i=0 ; i<b->numsides ; i++)
00396             b->original_sides[i].texinfo = TEXINFO_NODE;
00397     }
00398 
00399     //
00400     // origin brushes are removed, but they set
00401     // the rotation origin for the rest of the brushes
00402     // in the entity.  After the entire entity is parsed,
00403     // the planenums and texinfos will be adjusted for
00404     // the origin brush
00405     //
00406     if (b->contents & CONTENTS_ORIGIN)
00407     {
00408         char    string[32];
00409         vec3_t  origin;
00410 
00411         if (num_entities == 1)
00412         {
00413             Error ("Entity %i, Brush %i: origin brushes not allowed in world"
00414                 , b->entitynum, b->brushnum);
00415             return;
00416         }
00417 
00418         VectorAdd (b->mins, b->maxs, origin);
00419         VectorScale (origin, 0.5, origin);
00420 
00421         sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
00422         SetKeyValue (&entities[b->entitynum], "origin", string);
00423 
00424         VectorCopy (origin, entities[b->entitynum].origin);
00425 
00426         // don't keep this brush
00427         b->numsides = 0;
00428 
00429         return;
00430     }
00431 
00432     AddBrushBevels(b);
00433 
00434     nummapbrushes++;
00435     mapent->numbrushes++;       
00436 }
00437 
00438 /*
00439 ================
00440 Q2_MoveBrushesToWorld
00441 
00442 Takes all of the brushes from the current entity and
00443 adds them to the world's brush list.
00444 
00445 Used by func_group and func_areaportal
00446 ================
00447 */
00448 void Q2_MoveBrushesToWorld (entity_t *mapent)
00449 {
00450     int         newbrushes;
00451     int         worldbrushes;
00452     mapbrush_t  *temp;
00453     int         i;
00454 
00455     // this is pretty gross, because the brushes are expected to be
00456     // in linear order for each entity
00457 
00458     newbrushes = mapent->numbrushes;
00459     worldbrushes = entities[0].numbrushes;
00460 
00461     temp = GetMemory(newbrushes*sizeof(mapbrush_t));
00462     memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
00463 
00464 #if 0       // let them keep their original brush numbers
00465     for (i=0 ; i<newbrushes ; i++)
00466         temp[i].entitynum = 0;
00467 #endif
00468 
00469     // make space to move the brushes (overlapped copy)
00470     memmove (mapbrushes + worldbrushes + newbrushes,
00471         mapbrushes + worldbrushes,
00472         sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
00473 
00474     // copy the new brushes down
00475     memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
00476 
00477     // fix up indexes
00478     entities[0].numbrushes += newbrushes;
00479     for (i=1 ; i<num_entities ; i++)
00480         entities[i].firstbrush += newbrushes;
00481     FreeMemory(temp);
00482 
00483     mapent->numbrushes = 0;
00484 }
00485 
00486 /*
00487 ================
00488 Q2_ParseMapEntity
00489 ================
00490 */
00491 qboolean    Q2_ParseMapEntity(script_t *script)
00492 {
00493     entity_t    *mapent;
00494     epair_t *e;
00495     side_t *s;
00496     int i, j;
00497     int startbrush, startsides;
00498     vec_t newdist;
00499     mapbrush_t *b;
00500     token_t token;
00501 
00502     if (!PS_ReadToken(script, &token)) return false;
00503 
00504     if (strcmp(token.string, "{") )
00505         Error ("ParseEntity: { not found");
00506     
00507     if (num_entities == MAX_MAP_ENTITIES)
00508         Error ("num_entities == MAX_MAP_ENTITIES");
00509 
00510     startbrush = nummapbrushes;
00511     startsides = nummapbrushsides;
00512 
00513     mapent = &entities[num_entities];
00514     num_entities++;
00515     memset (mapent, 0, sizeof(*mapent));
00516     mapent->firstbrush = nummapbrushes;
00517     mapent->numbrushes = 0;
00518 //  mapent->portalareas[0] = -1;
00519 //  mapent->portalareas[1] = -1;
00520 
00521     do
00522     {
00523         if (!PS_ReadToken(script, &token))
00524         {
00525             Error("ParseEntity: EOF without closing brace");
00526         } //end if
00527         if (!strcmp(token.string, "}")) break;
00528         if (!strcmp(token.string, "{"))
00529         {
00530             Q2_ParseBrush(script, mapent);
00531         } //end if
00532         else
00533         {
00534             PS_UnreadLastToken(script);
00535             e = ParseEpair(script);
00536             e->next = mapent->epairs;
00537             mapent->epairs = e;
00538         } //end else
00539     } while(1);
00540 
00541     GetVectorForKey(mapent, "origin", mapent->origin);
00542 
00543     //
00544     // if there was an origin brush, offset all of the planes and texinfo
00545     //
00546     if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
00547     {
00548         for (i=0 ; i<mapent->numbrushes ; i++)
00549         {
00550             b = &mapbrushes[mapent->firstbrush + i];
00551             for (j=0 ; j<b->numsides ; j++)
00552             {
00553                 s = &b->original_sides[j];
00554                 newdist = mapplanes[s->planenum].dist -
00555                     DotProduct (mapplanes[s->planenum].normal, mapent->origin);
00556                 s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
00557                 s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
00558                     &side_brushtextures[s-brushsides], mapent->origin);
00559             }
00560             MakeBrushWindings (b);
00561         }
00562     }
00563 
00564     // group entities are just for editor convenience
00565     // toss all brushes into the world entity
00566     if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
00567     {
00568         Q2_MoveBrushesToWorld (mapent);
00569         mapent->numbrushes = 0;
00570         return true;
00571     }
00572 
00573     // areaportal entities move their brushes, but don't eliminate
00574     // the entity
00575     if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
00576     {
00577         char    str[128];
00578 
00579         if (mapent->numbrushes != 1)
00580             Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
00581 
00582         b = &mapbrushes[nummapbrushes-1];
00583         b->contents = CONTENTS_AREAPORTAL;
00584         c_areaportals++;
00585         mapent->areaportalnum = c_areaportals;
00586         // set the portal number as "style"
00587         sprintf (str, "%i", c_areaportals);
00588         SetKeyValue (mapent, "style", str);
00589         Q2_MoveBrushesToWorld (mapent);
00590         return true;
00591     }
00592 
00593     return true;
00594 }
00595 
00596 //===================================================================
00597 
00598 /*
00599 ================
00600 LoadMapFile
00601 ================
00602 */
00603 void Q2_LoadMapFile(char *filename)
00604 {       
00605     int i;
00606     script_t *script;
00607 
00608     Log_Print("-- Q2_LoadMapFile --\n");
00609 #ifdef ME
00610     //loaded map type
00611     loadedmaptype = MAPTYPE_QUAKE2;
00612     //reset the map loading
00613     ResetMapLoading();
00614 #endif //ME
00615 
00616     script = LoadScriptFile(filename);
00617     if (!script)
00618     {
00619         Log_Print("couldn't open %s\n", filename);
00620         return;
00621     } //end if
00622     //white spaces and escape characters inside a string are not allowed
00623     SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
00624                                     SCFL_NOSTRINGESCAPECHARS |
00625                                     SCFL_PRIMITIVE);
00626 
00627     nummapbrushsides = 0;
00628     num_entities = 0;
00629     
00630     while (Q2_ParseMapEntity(script))
00631     {
00632     }
00633 
00634     ClearBounds (map_mins, map_maxs);
00635     for (i=0 ; i<entities[0].numbrushes ; i++)
00636     {
00637         if (mapbrushes[i].mins[0] > 4096)
00638             continue;   // no valid points
00639         AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
00640         AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
00641     } //end for
00642 
00643     PrintMapInfo();
00644 
00645     //free the script
00646     FreeScript(script);
00647 //  TestExpandBrushes ();
00648     //
00649     Q2_CreateMapTexinfo();
00650 } //end of the function Q2_LoadMapFile
00651 
00652 #ifdef ME       //Begin MAP loading from BSP file
00653 //===========================================================================
00654 //
00655 // Parameter:               -
00656 // Returns:                 -
00657 // Changes Globals:     -
00658 //===========================================================================
00659 void Q2_SetLeafBrushesModelNumbers(int leafnum, int modelnum)
00660 {
00661     int i, brushnum;
00662     dleaf_t *leaf;
00663 
00664     leaf = &dleafs[leafnum];
00665     for (i = 0; i < leaf->numleafbrushes; i++)
00666     {
00667         brushnum = dleafbrushes[leaf->firstleafbrush + i];
00668         brushmodelnumbers[brushnum] = modelnum;
00669         dbrushleafnums[brushnum] = leafnum;
00670     } //end for
00671 } //end of the function Q2_SetLeafBrushesModelNumbers
00672 //===========================================================================
00673 //
00674 // Parameter:               -
00675 // Returns:                 -
00676 // Changes Globals:     -
00677 //===========================================================================
00678 void Q2_InitNodeStack(void)
00679 {
00680     nodestackptr = nodestack;
00681     nodestacksize = 0;
00682 } //end of the function Q2_InitNodeStack
00683 //===========================================================================
00684 //
00685 // Parameter:               -
00686 // Returns:                 -
00687 // Changes Globals:     -
00688 //===========================================================================
00689 void Q2_PushNodeStack(int num)
00690 {
00691     *nodestackptr = num;
00692     nodestackptr++;
00693     nodestacksize++;
00694     //
00695     if (nodestackptr >= &nodestack[NODESTACKSIZE])
00696     {
00697         Error("Q2_PushNodeStack: stack overflow\n");
00698     } //end if
00699 } //end of the function Q2_PushNodeStack
00700 //===========================================================================
00701 //
00702 // Parameter:               -
00703 // Returns:                 -
00704 // Changes Globals:     -
00705 //===========================================================================
00706 int Q2_PopNodeStack(void)
00707 {
00708     //if the stack is empty
00709     if (nodestackptr <= nodestack) return -1;
00710     //decrease stack pointer
00711     nodestackptr--;
00712     nodestacksize--;
00713     //return the top value from the stack
00714     return *nodestackptr;
00715 } //end of the function Q2_PopNodeStack
00716 //===========================================================================
00717 //
00718 // Parameter:               -
00719 // Returns:                 -
00720 // Changes Globals:     -
00721 //===========================================================================
00722 void Q2_SetBrushModelNumbers(entity_t *mapent)
00723 {
00724     int n, pn;
00725     int leafnum;
00726 
00727     //
00728     Q2_InitNodeStack();
00729     //head node (root) of the bsp tree
00730     n = dmodels[mapent->modelnum].headnode;
00731     pn = 0;
00732     
00733     do
00734     {
00735         //if we are in a leaf (negative node number)
00736         if (n < 0)
00737         {
00738             //number of the leaf
00739             leafnum = (-n) - 1;
00740             //set the brush numbers
00741             Q2_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum);
00742             //walk back into the tree to find a second child to continue with
00743             for (pn = Q2_PopNodeStack(); pn >= 0; n = pn, pn = Q2_PopNodeStack())
00744             {
00745                 //if we took the first child at the parent node
00746                 if (dnodes[pn].children[0] == n) break;
00747             } //end for
00748             //if the stack wasn't empty (if not processed whole tree)
00749             if (pn >= 0)
00750             {
00751                 //push the parent node again
00752                 Q2_PushNodeStack(pn);
00753                 //we proceed with the second child of the parent node
00754                 n = dnodes[pn].children[1];
00755             } //end if
00756         } //end if
00757         else
00758         {
00759             //push the current node onto the stack
00760             Q2_PushNodeStack(n);
00761             //walk forward into the tree to the first child
00762             n = dnodes[n].children[0];
00763         } //end else
00764     } while(pn >= 0);
00765 } //end of the function Q2_SetBrushModelNumbers
00766 //===========================================================================
00767 //
00768 // Parameter:               -
00769 // Returns:                 -
00770 // Changes Globals:     -
00771 //===========================================================================
00772 void Q2_BSPBrushToMapBrush(dbrush_t *bspbrush, entity_t *mapent)
00773 {
00774     mapbrush_t *b;
00775     int i, k, n;
00776     side_t *side, *s2;
00777     int planenum;
00778     dbrushside_t *bspbrushside;
00779     dplane_t *bspplane;
00780 
00781     if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
00782         Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES");
00783 
00784     b = &mapbrushes[nummapbrushes];
00785     b->original_sides = &brushsides[nummapbrushsides];
00786     b->entitynum = mapent-entities;
00787     b->brushnum = nummapbrushes - mapent->firstbrush;
00788     b->leafnum = dbrushleafnums[bspbrush - dbrushes];
00789 
00790     for (n = 0; n < bspbrush->numsides; n++)
00791     {
00792         //pointer to the bsp brush side
00793         bspbrushside = &dbrushsides[bspbrush->firstside + n];
00794 
00795         if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00796         {
00797             Error ("MAX_MAPFILE_BRUSHSIDES");
00798         } //end if
00799         //pointer to the map brush side
00800         side = &brushsides[nummapbrushsides];
00801         //if the BSP brush side is textured
00802         if (brushsidetextured[bspbrush->firstside + n]) side->flags |= SFL_TEXTURED;
00803         else side->flags &= ~SFL_TEXTURED;
00804         //ME: can get side contents and surf directly from BSP file
00805         side->contents = bspbrush->contents;
00806         //if the texinfo is TEXINFO_NODE
00807         if (bspbrushside->texinfo < 0) side->surf = 0;
00808         else side->surf = texinfo[bspbrushside->texinfo].flags;
00809 
00810         // translucent objects are automatically classified as detail
00811         if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
00812             side->contents |= CONTENTS_DETAIL;
00813         if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00814             side->contents |= CONTENTS_DETAIL;
00815         if (fulldetail)
00816             side->contents &= ~CONTENTS_DETAIL;
00817         if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
00818             | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
00819             side->contents |= CONTENTS_SOLID;
00820 
00821         // hints and skips are never detail, and have no content
00822         if (side->surf & (SURF_HINT|SURF_SKIP) )
00823         {
00824             side->contents = 0;
00825             side->surf &= ~CONTENTS_DETAIL;
00826         }
00827 
00828         //ME: get a plane for this side
00829         bspplane = &dplanes[bspbrushside->planenum];
00830         planenum = FindFloatPlane(bspplane->normal, bspplane->dist);
00831         //
00832         // see if the plane has been used already
00833         //
00834         //ME: this really shouldn't happen!!!
00835         //ME: otherwise the bsp file is corrupted??
00836         //ME: still it seems to happen, maybe Johny Boy's
00837         //ME: brush bevel adding is crappy ?
00838         for (k = 0; k < b->numsides; k++)
00839         {
00840             s2 = b->original_sides + k;
00841 //          if (DotProduct (mapplanes[s2->planenum].normal, mapplanes[planenum].normal) > 0.999
00842 //                          && fabs(mapplanes[s2->planenum].dist - mapplanes[planenum].dist) < 0.01 )
00843 
00844             if (s2->planenum == planenum)
00845             {
00846                 Log_Print("Entity %i, Brush %i: duplicate plane\n"
00847                     , b->entitynum, b->brushnum);
00848                 break;
00849             }
00850             if ( s2->planenum == (planenum^1) )
00851             {
00852                 Log_Print("Entity %i, Brush %i: mirrored plane\n"
00853                     , b->entitynum, b->brushnum);
00854                 break;
00855             }
00856         }
00857         if (k != b->numsides)
00858             continue;       // duplicated
00859 
00860         //
00861         // keep this side
00862         //
00863         //ME: reset pointer to side, why? hell I dunno (pointer is set above already)
00864         side = b->original_sides + b->numsides;
00865         //ME: store the plane number
00866         side->planenum = planenum;
00867         //ME: texinfo is already stored when bsp is loaded
00868         //NOTE: check for TEXINFO_NODE, otherwise crash in Q2_BrushContents
00869         if (bspbrushside->texinfo < 0) side->texinfo = 0;
00870         else side->texinfo = bspbrushside->texinfo;
00871 
00872         // save the td off in case there is an origin brush and we
00873         // have to recalculate the texinfo
00874         // ME: don't need to recalculate because it's already done
00875         //     (for non-world entities) in the BSP file
00876 //      side_brushtextures[nummapbrushsides] = td;
00877 
00878         nummapbrushsides++;
00879         b->numsides++;
00880     } //end for
00881 
00882     // get the content for the entire brush
00883     b->contents = bspbrush->contents;
00884     Q2_BrushContents(b);
00885 
00886     if (BrushExists(b))
00887     {
00888         c_squattbrushes++;
00889         b->numsides = 0;
00890         return;
00891     } //end if
00892 
00893     //if we're creating AAS
00894     if (create_aas)
00895     {
00896         //create the AAS brushes from this brush, don't add brush bevels
00897         AAS_CreateMapBrushes(b, mapent, false);
00898         return;
00899     } //end if
00900 
00901     // allow detail brushes to be removed 
00902     if (nodetail && (b->contents & CONTENTS_DETAIL) )
00903     {
00904         b->numsides = 0;
00905         return;
00906     } //end if
00907 
00908     // allow water brushes to be removed
00909     if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
00910     {
00911         b->numsides = 0;
00912         return;
00913     } //end if
00914 
00915     // create windings for sides and bounds for brush
00916     MakeBrushWindings(b);
00917 
00918     //mark brushes without winding or with a tiny window as bevels
00919     MarkBrushBevels(b);
00920 
00921     // brushes that will not be visible at all will never be
00922     // used as bsp splitters
00923     if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00924     {
00925             c_clipbrushes++;
00926         for (i = 0; i < b->numsides; i++)
00927             b->original_sides[i].texinfo = TEXINFO_NODE;
00928     } //end for
00929 
00930     //
00931     // origin brushes are removed, but they set
00932     // the rotation origin for the rest of the brushes
00933     // in the entity.  After the entire entity is parsed,
00934     // the planenums and texinfos will be adjusted for
00935     // the origin brush
00936     //
00937     //ME: not needed because the entities in the BSP file already
00938     //    have an origin set
00939 //  if (b->contents & CONTENTS_ORIGIN)
00940 //  {
00941 //      char    string[32];
00942 //      vec3_t  origin;
00943 //
00944 //      if (num_entities == 1)
00945 //      {
00946 //          Error ("Entity %i, Brush %i: origin brushes not allowed in world"
00947 //              , b->entitynum, b->brushnum);
00948 //          return;
00949 //      }
00950 //
00951 //      VectorAdd (b->mins, b->maxs, origin);
00952 //      VectorScale (origin, 0.5, origin);
00953 //
00954 //      sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
00955 //      SetKeyValue (&entities[b->entitynum], "origin", string);
00956 //
00957 //      VectorCopy (origin, entities[b->entitynum].origin);
00958 //
00959 //      // don't keep this brush
00960 //      b->numsides = 0;
00961 //
00962 //      return;
00963 //  }
00964 
00965     //ME: the bsp brushes already have bevels, so we won't try to
00966     //    add them again (especially since Johny Boy's bevel adding might
00967     //    be crappy)
00968 //  AddBrushBevels(b);
00969 
00970     nummapbrushes++;
00971     mapent->numbrushes++;
00972 } //end of the function Q2_BSPBrushToMapBrush
00973 //===========================================================================
00974 //===========================================================================
00975 void Q2_ParseBSPBrushes(entity_t *mapent)
00976 {
00977     int i;
00978 
00979     //give all the brushes that belong to this entity the number of the
00980     //BSP model used by this entity
00981     Q2_SetBrushModelNumbers(mapent);
00982     //now parse all the brushes with the correct mapent->modelnum
00983     for (i = 0; i < numbrushes; i++)
00984     {
00985         if (brushmodelnumbers[i] == mapent->modelnum)
00986         {
00987             Q2_BSPBrushToMapBrush(&dbrushes[i], mapent);
00988         } //end if
00989     } //end for
00990 } //end of the function Q2_ParseBSPBrushes
00991 //===========================================================================
00992 //===========================================================================
00993 qboolean Q2_ParseBSPEntity(int entnum)
00994 {
00995     entity_t    *mapent;
00996     char *model;
00997     int startbrush, startsides;
00998 
00999     startbrush = nummapbrushes;
01000     startsides = nummapbrushsides;
01001 
01002     mapent = &entities[entnum];//num_entities];
01003     mapent->firstbrush = nummapbrushes;
01004     mapent->numbrushes = 0;
01005     mapent->modelnum = -1;  //-1 = no model
01006 
01007     model = ValueForKey(mapent, "model");
01008     if (model && strlen(model))
01009     {
01010         if (*model != '*')
01011         {
01012             Error("Q2_ParseBSPEntity: model number without leading *");
01013         } //end if
01014         //get the model number of this entity (skip the leading *)
01015         mapent->modelnum = atoi(&model[1]);
01016     } //end if
01017 
01018     GetVectorForKey(mapent, "origin", mapent->origin);
01019 
01020     //if this is the world entity it has model number zero
01021     //the world entity has no model key
01022     if (!strcmp("worldspawn", ValueForKey(mapent, "classname")))
01023     {
01024         mapent->modelnum = 0;
01025     } //end if
01026     //if the map entity has a BSP model (a modelnum of -1 is used for
01027     //entities that aren't using a BSP model)
01028     if (mapent->modelnum >= 0)
01029     {
01030         //parse the bsp brushes
01031         Q2_ParseBSPBrushes(mapent);
01032     } //end if
01033     //
01034     //the origin of the entity is already taken into account
01035     //
01036     //func_group entities can't be in the bsp file
01037     //
01038     //check out the func_areaportal entities
01039     if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
01040     {
01041         c_areaportals++;
01042         mapent->areaportalnum = c_areaportals;
01043         return true;
01044     } //end if
01045     return true;
01046 } //end of the function Q2_ParseBSPEntity
01047 //===========================================================================
01048 //
01049 // Parameter:               -
01050 // Returns:                 -
01051 // Changes Globals:     -
01052 //===========================================================================
01053 void Q2_LoadMapFromBSP(char *filename, int offset, int length)
01054 {
01055     int i;
01056 
01057     Log_Print("-- Q2_LoadMapFromBSP --\n");
01058     //loaded map type
01059     loadedmaptype = MAPTYPE_QUAKE2;
01060 
01061     Log_Print("Loading map from %s...\n", filename);
01062     //load the bsp file
01063     Q2_LoadBSPFile(filename, offset, length);
01064 
01065     //create an index from bsp planes to map planes
01066     //DPlanes2MapPlanes();
01067     //clear brush model numbers
01068     for (i = 0; i < MAX_MAPFILE_BRUSHES; i++)
01069         brushmodelnumbers[i] = -1;
01070 
01071     nummapbrushsides = 0;
01072     num_entities = 0;
01073 
01074     Q2_ParseEntities();
01075     //
01076     for (i = 0; i < num_entities; i++)
01077     {
01078         Q2_ParseBSPEntity(i);
01079     } //end for
01080 
01081     //get the map mins and maxs from the world model
01082     ClearBounds(map_mins, map_maxs);
01083     for (i = 0; i < entities[0].numbrushes; i++)
01084     {
01085         if (mapbrushes[i].mins[0] > 4096)
01086             continue;   //no valid points
01087         AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
01088         AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
01089     } //end for
01090 
01091     PrintMapInfo();
01092     //
01093     Q2_CreateMapTexinfo();
01094 } //end of the function Q2_LoadMapFromBSP
01095 
01096 void Q2_ResetMapLoading(void)
01097 {
01098     //reset for map loading from bsp
01099     memset(nodestack, 0, NODESTACKSIZE * sizeof(int));
01100     nodestackptr = NULL;
01101     nodestacksize = 0;
01102     memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int));
01103 } //end of the function Q2_ResetMapLoading
01104 
01105 //End MAP loading from BSP file
01106 #endif //ME
01107 
01108 //====================================================================
01109 
01110 /*
01111 ================
01112 TestExpandBrushes
01113 
01114 Expands all the brush planes and saves a new map out
01115 ================
01116 */
01117 void TestExpandBrushes (void)
01118 {
01119     FILE    *f;
01120     side_t  *s;
01121     int     i, j, bn;
01122     winding_t   *w;
01123     char    *name = "expanded.map";
01124     mapbrush_t  *brush;
01125     vec_t   dist;
01126 
01127     Log_Print("writing %s\n", name);
01128     f = fopen (name, "wb");
01129     if (!f)
01130         Error ("Can't write %s\n", name);
01131 
01132     fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
01133 
01134     for (bn=0 ; bn<nummapbrushes ; bn++)
01135     {
01136         brush = &mapbrushes[bn];
01137         fprintf (f, "{\n");
01138         for (i=0 ; i<brush->numsides ; i++)
01139         {
01140             s = brush->original_sides + i;
01141             dist = mapplanes[s->planenum].dist;
01142             for (j=0 ; j<3 ; j++)
01143                 dist += fabs( 16 * mapplanes[s->planenum].normal[j] );
01144 
01145             w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist);
01146 
01147             fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
01148             fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
01149             fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
01150 
01151             fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
01152             FreeWinding (w);
01153         }
01154         fprintf (f, "}\n");
01155     }
01156     fprintf (f, "}\n");
01157 
01158     fclose (f);
01159 
01160     Error ("can't proceed after expanding brushes");
01161 } //end of the function TestExpandBrushes
01162 

Generated on Thu Aug 25 12:37:18 2005 for Quake III Arena by  doxygen 1.3.9.1