The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
This commit is contained in:
commit
dbe4ddb103
1409 changed files with 806066 additions and 0 deletions
418
q3map/writebsp.c
Normal file
418
q3map/writebsp.c
Normal file
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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 ; i<nummapplanes ; i++, mp++)
|
||||
{
|
||||
dp = &dplanes[numplanes];
|
||||
VectorCopy ( mp->normal, 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 ; i<num_entities ; i++ ) {
|
||||
if ( entities[i].brushes || entities[i].patches ) {
|
||||
sprintf ( value, "*%i", models );
|
||||
models++;
|
||||
SetKeyValue (&entities[i], "model", value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
SetLightStyles
|
||||
============
|
||||
*/
|
||||
#define MAX_SWITCHED_LIGHTS 32
|
||||
void SetLightStyles (void)
|
||||
{
|
||||
int stylenum;
|
||||
const char *t;
|
||||
entity_t *e;
|
||||
int i, j;
|
||||
char value[10];
|
||||
char lighttargets[MAX_SWITCHED_LIGHTS][64];
|
||||
|
||||
|
||||
// any light that is controlled (has a targetname)
|
||||
// must have a unique style number generated for it
|
||||
|
||||
stylenum = 0;
|
||||
for (i=1 ; i<num_entities ; i++)
|
||||
{
|
||||
e = &entities[i];
|
||||
|
||||
t = ValueForKey (e, "classname");
|
||||
if (Q_strncasecmp (t, "light", 5))
|
||||
continue;
|
||||
t = ValueForKey (e, "targetname");
|
||||
if (!t[0])
|
||||
continue;
|
||||
|
||||
// find this targetname
|
||||
for (j=0 ; j<stylenum ; j++)
|
||||
if (!strcmp (lighttargets[j], t))
|
||||
break;
|
||||
if (j == stylenum)
|
||||
{
|
||||
if (stylenum == MAX_SWITCHED_LIGHTS)
|
||||
Error ("stylenum == MAX_SWITCHED_LIGHTS");
|
||||
strcpy (lighttargets[j], t);
|
||||
stylenum++;
|
||||
}
|
||||
sprintf (value, "%i", 32 + j);
|
||||
SetKeyValue (e, "style", value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
BeginBSPFile
|
||||
==================
|
||||
*/
|
||||
void BeginBSPFile( void ) {
|
||||
// these values may actually be initialized
|
||||
// if the file existed when loaded, so clear them explicitly
|
||||
nummodels = 0;
|
||||
numnodes = 0;
|
||||
numbrushsides = 0;
|
||||
numleafsurfaces = 0;
|
||||
numleafbrushes = 0;
|
||||
|
||||
// leave leaf 0 as an error, because leafs are referenced as
|
||||
// negative number nodes
|
||||
numleafs = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
EndBSPFile
|
||||
============
|
||||
*/
|
||||
void EndBSPFile( void ) {
|
||||
char path[1024];
|
||||
|
||||
EmitPlanes ();
|
||||
UnparseEntities ();
|
||||
|
||||
// write the map
|
||||
sprintf (path, "%s.bsp", source);
|
||||
_printf ("Writing %s\n", path);
|
||||
WriteBSPFile (path);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
|
||||
/*
|
||||
============
|
||||
EmitBrushes
|
||||
============
|
||||
*/
|
||||
void EmitBrushes ( bspbrush_t *brushes ) {
|
||||
int j;
|
||||
dbrush_t *db;
|
||||
bspbrush_t *b;
|
||||
dbrushside_t *cp;
|
||||
|
||||
for ( b = brushes ; b ; b = b->next ) {
|
||||
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 ; j<b->numsides ; 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++;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue