/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. This file is part of Quake III Arena source code. Quake III Arena source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake III Arena source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "qbsp.h" /* ============ EmitShader ============ */ int EmitShader( const char *shader ) { int i; shaderInfo_t *si; if ( !shader ) { shader = "noshader"; } for ( i = 0 ; i < numShaders ; i++ ) { if ( !Q_stricmp( shader, dshaders[i].shader ) ) { return i; } } if ( i == MAX_MAP_SHADERS ) { Error( "MAX_MAP_SHADERS" ); } numShaders++; strcpy( dshaders[i].shader, shader ); si = ShaderInfoForShader( shader ); dshaders[i].surfaceFlags = si->surfaceFlags; dshaders[i].contentFlags = si->contents; return i; } /* ============ EmitPlanes There is no oportunity to discard planes, because all of the original brushes will be saved in the map. ============ */ void EmitPlanes (void) { int i; dplane_t *dp; plane_t *mp; mp = mapplanes; for (i=0 ; inormal, dp->normal); dp->dist = mp->dist; numplanes++; } } /* ================== EmitLeaf ================== */ void EmitLeaf (node_t *node) { dleaf_t *leaf_p; bspbrush_t *b; drawSurfRef_t *dsr; // emit a leaf if (numleafs >= MAX_MAP_LEAFS) Error ("MAX_MAP_LEAFS"); leaf_p = &dleafs[numleafs]; numleafs++; leaf_p->cluster = node->cluster; leaf_p->area = node->area; // // write bounding box info // VectorCopy (node->mins, leaf_p->mins); VectorCopy (node->maxs, leaf_p->maxs); // // write the leafbrushes // leaf_p->firstLeafBrush = numleafbrushes; for ( b = node->brushlist ; b ; b = b->next ) { if ( numleafbrushes >= MAX_MAP_LEAFBRUSHES ) { Error( "MAX_MAP_LEAFBRUSHES" ); } dleafbrushes[numleafbrushes] = b->original->outputNumber; numleafbrushes++; } leaf_p->numLeafBrushes = numleafbrushes - leaf_p->firstLeafBrush; // // write the surfaces visible in this leaf // if ( node->opaque ) { return; // no leaffaces in solids } // add the drawSurfRef_t drawsurfs leaf_p->firstLeafSurface = numleafsurfaces; for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { if ( numleafsurfaces >= MAX_MAP_LEAFFACES) Error ("MAX_MAP_LEAFFACES"); dleafsurfaces[numleafsurfaces] = dsr->outputNumber; numleafsurfaces++; } leaf_p->numLeafSurfaces = numleafsurfaces - leaf_p->firstLeafSurface; } /* ============ EmitDrawNode_r ============ */ int EmitDrawNode_r (node_t *node) { dnode_t *n; int i; if (node->planenum == PLANENUM_LEAF) { EmitLeaf (node); return -numleafs; } // emit a node if (numnodes == MAX_MAP_NODES) Error ("MAX_MAP_NODES"); n = &dnodes[numnodes]; numnodes++; VectorCopy (node->mins, n->mins); VectorCopy (node->maxs, n->maxs); if (node->planenum & 1) Error ("WriteDrawNodes_r: odd planenum"); n->planeNum = node->planenum; // // recursively output the other nodes // for (i=0 ; i<2 ; i++) { if (node->children[i]->planenum == PLANENUM_LEAF) { n->children[i] = -(numleafs + 1); EmitLeaf (node->children[i]); } else { n->children[i] = numnodes; EmitDrawNode_r (node->children[i]); } } return n - dnodes; } //========================================================= /* ============ SetModelNumbers ============ */ void SetModelNumbers (void) { int i; int models; char value[10]; models = 1; for ( i=1 ; inext ) { if ( numbrushes == MAX_MAP_BRUSHES ) { Error( "MAX_MAP_BRUSHES" ); } b->outputNumber = numbrushes; db = &dbrushes[numbrushes]; numbrushes++; db->shaderNum = EmitShader( b->contentShader->shader ); db->firstSide = numbrushsides; // don't emit any generated backSide sides db->numSides = 0; for ( j=0 ; jnumsides ; j++ ) { if ( b->sides[j].backSide ) { continue; } if ( numbrushsides == MAX_MAP_BRUSHSIDES ) { Error( "MAX_MAP_BRUSHSIDES "); } cp = &dbrushsides[numbrushsides]; db->numSides++; numbrushsides++; cp->planeNum = b->sides[j].planenum; cp->shaderNum = EmitShader( b->sides[j].shaderInfo->shader ); } } } /* ================== BeginModel ================== */ void BeginModel( void ) { dmodel_t *mod; bspbrush_t *b; entity_t *e; vec3_t mins, maxs; parseMesh_t *p; int i; if ( nummodels == MAX_MAP_MODELS ) { Error( "MAX_MAP_MODELS" ); } mod = &dmodels[nummodels]; // // bound the brushes // e = &entities[entity_num]; ClearBounds (mins, maxs); for ( b = e->brushes ; b ; b = b->next ) { if ( !b->numsides ) { continue; // not a real brush (origin brush, etc) } AddPointToBounds (b->mins, mins, maxs); AddPointToBounds (b->maxs, mins, maxs); } for ( p = e->patches ; p ; p = p->next ) { for ( i = 0 ; i < p->mesh.width * p->mesh.height ; i++ ) { AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs ); } } VectorCopy (mins, mod->mins); VectorCopy (maxs, mod->maxs); mod->firstSurface = numDrawSurfaces; mod->firstBrush = numbrushes; EmitBrushes( e->brushes ); } /* ================== EndModel ================== */ void EndModel( node_t *headnode ) { dmodel_t *mod; qprintf ("--- EndModel ---\n"); mod = &dmodels[nummodels]; EmitDrawNode_r (headnode); mod->numSurfaces = numDrawSurfaces - mod->firstSurface; mod->numBrushes = numbrushes - mod->firstBrush; nummodels++; }