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

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

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