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

writebsp.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 #include "qbsp.h"
00023 
00024 /*
00025 ============
00026 EmitShader
00027 ============
00028 */
00029 int EmitShader( const char *shader ) {
00030     int             i;
00031     shaderInfo_t    *si;
00032 
00033     if ( !shader ) {
00034         shader = "noshader";
00035     }
00036 
00037     for ( i = 0 ; i < numShaders ; i++ ) {
00038         if ( !Q_stricmp( shader, dshaders[i].shader ) ) {
00039             return i;
00040         }
00041     }
00042 
00043     if ( i == MAX_MAP_SHADERS ) {
00044         Error( "MAX_MAP_SHADERS" );
00045     }
00046     numShaders++;
00047     strcpy( dshaders[i].shader, shader );
00048 
00049     si = ShaderInfoForShader( shader );
00050     dshaders[i].surfaceFlags = si->surfaceFlags;
00051     dshaders[i].contentFlags = si->contents;
00052 
00053     return i;
00054 }
00055 
00056 
00057 /*
00058 ============
00059 EmitPlanes
00060 
00061 There is no oportunity to discard planes, because all of the original
00062 brushes will be saved in the map.
00063 ============
00064 */
00065 void EmitPlanes (void)
00066 {
00067     int         i;
00068     dplane_t    *dp;
00069     plane_t     *mp;
00070 
00071     mp = mapplanes;
00072     for (i=0 ; i<nummapplanes ; i++, mp++)
00073     {
00074         dp = &dplanes[numplanes];
00075         VectorCopy ( mp->normal, dp->normal);
00076         dp->dist = mp->dist;
00077         numplanes++;
00078     }
00079 }
00080 
00081 
00082 
00083 /*
00084 ==================
00085 EmitLeaf
00086 ==================
00087 */
00088 void EmitLeaf (node_t *node)
00089 {
00090     dleaf_t             *leaf_p;
00091     bspbrush_t          *b;
00092     drawSurfRef_t       *dsr;
00093 
00094     // emit a leaf
00095     if (numleafs >= MAX_MAP_LEAFS)
00096         Error ("MAX_MAP_LEAFS");
00097 
00098     leaf_p = &dleafs[numleafs];
00099     numleafs++;
00100 
00101     leaf_p->cluster = node->cluster;
00102     leaf_p->area = node->area;
00103 
00104     //
00105     // write bounding box info
00106     //  
00107     VectorCopy (node->mins, leaf_p->mins);
00108     VectorCopy (node->maxs, leaf_p->maxs);
00109     
00110     //
00111     // write the leafbrushes
00112     //
00113     leaf_p->firstLeafBrush = numleafbrushes;
00114     for ( b = node->brushlist ; b ; b = b->next ) {
00115         if ( numleafbrushes >= MAX_MAP_LEAFBRUSHES ) {
00116             Error( "MAX_MAP_LEAFBRUSHES" );
00117         }
00118         dleafbrushes[numleafbrushes] = b->original->outputNumber;
00119         numleafbrushes++;
00120     }
00121     leaf_p->numLeafBrushes = numleafbrushes - leaf_p->firstLeafBrush;
00122 
00123     //
00124     // write the surfaces visible in this leaf
00125     //
00126     if ( node->opaque ) {
00127         return;     // no leaffaces in solids
00128     }
00129     
00130     // add the drawSurfRef_t drawsurfs
00131     leaf_p->firstLeafSurface = numleafsurfaces;
00132     for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) {
00133         if ( numleafsurfaces >= MAX_MAP_LEAFFACES)
00134             Error ("MAX_MAP_LEAFFACES");
00135         dleafsurfaces[numleafsurfaces] = dsr->outputNumber;
00136         numleafsurfaces++;          
00137     }
00138 
00139 
00140     leaf_p->numLeafSurfaces = numleafsurfaces - leaf_p->firstLeafSurface;
00141 }
00142 
00143 
00144 /*
00145 ============
00146 EmitDrawNode_r
00147 ============
00148 */
00149 int EmitDrawNode_r (node_t *node)
00150 {
00151     dnode_t *n;
00152     int     i;
00153 
00154     if (node->planenum == PLANENUM_LEAF)
00155     {
00156         EmitLeaf (node);
00157         return -numleafs;
00158     }
00159 
00160     // emit a node  
00161     if (numnodes == MAX_MAP_NODES)
00162         Error ("MAX_MAP_NODES");
00163     n = &dnodes[numnodes];
00164     numnodes++;
00165 
00166     VectorCopy (node->mins, n->mins);
00167     VectorCopy (node->maxs, n->maxs);
00168 
00169     if (node->planenum & 1)
00170         Error ("WriteDrawNodes_r: odd planenum");
00171     n->planeNum = node->planenum;
00172 
00173     //
00174     // recursively output the other nodes
00175     //  
00176     for (i=0 ; i<2 ; i++)
00177     {
00178         if (node->children[i]->planenum == PLANENUM_LEAF)
00179         {
00180             n->children[i] = -(numleafs + 1);
00181             EmitLeaf (node->children[i]);
00182         }
00183         else
00184         {
00185             n->children[i] = numnodes;  
00186             EmitDrawNode_r (node->children[i]);
00187         }
00188     }
00189 
00190     return n - dnodes;
00191 }
00192 
00193 //=========================================================
00194 
00195 
00196 
00197 /*
00198 ============
00199 SetModelNumbers
00200 ============
00201 */
00202 void SetModelNumbers (void)
00203 {
00204     int     i;
00205     int     models;
00206     char    value[10];
00207 
00208     models = 1;
00209     for ( i=1 ; i<num_entities ; i++ ) {
00210         if ( entities[i].brushes || entities[i].patches ) {
00211             sprintf ( value, "*%i", models );
00212             models++;
00213             SetKeyValue (&entities[i], "model", value);
00214         }
00215     }
00216 
00217 }
00218 
00219 /*
00220 ============
00221 SetLightStyles
00222 ============
00223 */
00224 #define MAX_SWITCHED_LIGHTS 32
00225 void SetLightStyles (void)
00226 {
00227     int     stylenum;
00228     const char  *t;
00229     entity_t    *e;
00230     int     i, j;
00231     char    value[10];
00232     char    lighttargets[MAX_SWITCHED_LIGHTS][64];
00233 
00234 
00235     // any light that is controlled (has a targetname)
00236     // must have a unique style number generated for it
00237 
00238     stylenum = 0;
00239     for (i=1 ; i<num_entities ; i++)
00240     {
00241         e = &entities[i];
00242 
00243         t = ValueForKey (e, "classname");
00244         if (Q_strncasecmp (t, "light", 5))
00245             continue;
00246         t = ValueForKey (e, "targetname");
00247         if (!t[0])
00248             continue;
00249         
00250         // find this targetname
00251         for (j=0 ; j<stylenum ; j++)
00252             if (!strcmp (lighttargets[j], t))
00253                 break;
00254         if (j == stylenum)
00255         {
00256             if (stylenum == MAX_SWITCHED_LIGHTS)
00257                 Error ("stylenum == MAX_SWITCHED_LIGHTS");
00258             strcpy (lighttargets[j], t);
00259             stylenum++;
00260         }
00261         sprintf (value, "%i", 32 + j);
00262         SetKeyValue (e, "style", value);
00263     }
00264 
00265 }
00266 
00267 //===========================================================
00268 
00269 /*
00270 ==================
00271 BeginBSPFile
00272 ==================
00273 */
00274 void BeginBSPFile( void ) {
00275     // these values may actually be initialized
00276     // if the file existed when loaded, so clear them explicitly
00277     nummodels = 0;
00278     numnodes = 0;
00279     numbrushsides = 0;
00280     numleafsurfaces = 0;
00281     numleafbrushes = 0;
00282 
00283     // leave leaf 0 as an error, because leafs are referenced as
00284     // negative number nodes
00285     numleafs = 1;
00286 }
00287 
00288 
00289 /*
00290 ============
00291 EndBSPFile
00292 ============
00293 */
00294 void EndBSPFile( void ) {
00295     char    path[1024];
00296 
00297     EmitPlanes ();
00298     UnparseEntities ();
00299 
00300     // write the map
00301     sprintf (path, "%s.bsp", source);
00302     _printf ("Writing %s\n", path);
00303     WriteBSPFile (path);
00304 }
00305 
00306 
00307 //===========================================================
00308 
00309 /*
00310 ============
00311 EmitBrushes
00312 ============
00313 */
00314 void EmitBrushes ( bspbrush_t *brushes ) {
00315     int             j;
00316     dbrush_t        *db;
00317     bspbrush_t      *b;
00318     dbrushside_t    *cp;
00319 
00320     for ( b = brushes ; b ; b = b->next ) {
00321         if ( numbrushes == MAX_MAP_BRUSHES ) {
00322             Error( "MAX_MAP_BRUSHES" );
00323         }
00324         b->outputNumber = numbrushes;
00325         db = &dbrushes[numbrushes];
00326         numbrushes++;
00327 
00328         db->shaderNum = EmitShader( b->contentShader->shader );
00329         db->firstSide = numbrushsides;
00330 
00331         // don't emit any generated backSide sides
00332         db->numSides = 0;
00333         for ( j=0 ; j<b->numsides ; j++ ) {
00334             if ( b->sides[j].backSide ) {
00335                 continue;
00336             }
00337             if ( numbrushsides == MAX_MAP_BRUSHSIDES ) {
00338                 Error( "MAX_MAP_BRUSHSIDES ");
00339             }
00340             cp = &dbrushsides[numbrushsides];
00341             db->numSides++;
00342             numbrushsides++;
00343             cp->planeNum = b->sides[j].planenum;
00344             cp->shaderNum = EmitShader( b->sides[j].shaderInfo->shader );
00345         }
00346     }
00347 
00348 }
00349 
00350 
00351 /*
00352 ==================
00353 BeginModel
00354 ==================
00355 */
00356 void BeginModel( void ) {
00357     dmodel_t    *mod;
00358     bspbrush_t  *b;
00359     entity_t    *e;
00360     vec3_t      mins, maxs;
00361     parseMesh_t *p;
00362     int         i;
00363 
00364     if ( nummodels == MAX_MAP_MODELS ) {
00365         Error( "MAX_MAP_MODELS" );
00366     }
00367     mod = &dmodels[nummodels];
00368 
00369     //
00370     // bound the brushes
00371     //
00372     e = &entities[entity_num];
00373 
00374     ClearBounds (mins, maxs);
00375     for ( b = e->brushes ; b ; b = b->next ) {
00376         if ( !b->numsides ) {
00377             continue;   // not a real brush (origin brush, etc)
00378         }
00379         AddPointToBounds (b->mins, mins, maxs);
00380         AddPointToBounds (b->maxs, mins, maxs);
00381     }
00382 
00383     for ( p = e->patches ; p ; p = p->next ) {
00384         for ( i = 0 ; i < p->mesh.width * p->mesh.height ; i++ ) {
00385             AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs );
00386         }
00387     }
00388 
00389     VectorCopy (mins, mod->mins);
00390     VectorCopy (maxs, mod->maxs);
00391 
00392     mod->firstSurface = numDrawSurfaces;
00393     mod->firstBrush = numbrushes;
00394 
00395     EmitBrushes( e->brushes );
00396 }
00397 
00398 
00399 
00400 
00401 /*
00402 ==================
00403 EndModel
00404 ==================
00405 */
00406 void EndModel( node_t *headnode ) {
00407     dmodel_t    *mod;
00408 
00409     qprintf ("--- EndModel ---\n");
00410 
00411     mod = &dmodels[nummodels];
00412     EmitDrawNode_r (headnode);
00413     mod->numSurfaces = numDrawSurfaces - mod->firstSurface;
00414     mod->numBrushes = numbrushes - mod->firstBrush;
00415 
00416     nummodels++;
00417 }
00418 

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