diff options
Diffstat (limited to 'q3map/writebsp.c')
| -rwxr-xr-x | q3map/writebsp.c | 418 | 
1 files changed, 418 insertions, 0 deletions
diff --git a/q3map/writebsp.c b/q3map/writebsp.c new file mode 100755 index 0000000..7a56d88 --- /dev/null +++ b/q3map/writebsp.c @@ -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++;
 +}
 +
  | 
