Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

l_bsp_q3.c (25771B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 #include "l_cmd.h"
     24 #include "l_math.h"
     25 #include "l_mem.h"
     26 #include "l_log.h"
     27 #include "l_poly.h"
     28 #include "../botlib/l_script.h"
     29 #include "l_qfiles.h"
     30 #include "l_bsp_q3.h"
     31 #include "l_bsp_ent.h"
     32 
     33 void Q3_ParseEntities (void);
     34 void Q3_PrintBSPFileSizes(void);
     35 
     36 void GetLeafNums (void);
     37 
     38 //=============================================================================
     39 
     40 #define WCONVEX_EPSILON		0.5
     41 
     42 
     43 int				q3_nummodels;
     44 q3_dmodel_t		*q3_dmodels;//[MAX_MAP_MODELS];
     45 
     46 int				q3_numShaders;
     47 q3_dshader_t	*q3_dshaders;//[Q3_MAX_MAP_SHADERS];
     48 
     49 int				q3_entdatasize;
     50 char			*q3_dentdata;//[Q3_MAX_MAP_ENTSTRING];
     51 
     52 int				q3_numleafs;
     53 q3_dleaf_t		*q3_dleafs;//[Q3_MAX_MAP_LEAFS];
     54 
     55 int				q3_numplanes;
     56 q3_dplane_t		*q3_dplanes;//[Q3_MAX_MAP_PLANES];
     57 
     58 int				q3_numnodes;
     59 q3_dnode_t		*q3_dnodes;//[Q3_MAX_MAP_NODES];
     60 
     61 int				q3_numleafsurfaces;
     62 int				*q3_dleafsurfaces;//[Q3_MAX_MAP_LEAFFACES];
     63 
     64 int				q3_numleafbrushes;
     65 int				*q3_dleafbrushes;//[Q3_MAX_MAP_LEAFBRUSHES];
     66 
     67 int				q3_numbrushes;
     68 q3_dbrush_t		*q3_dbrushes;//[Q3_MAX_MAP_BRUSHES];
     69 
     70 int				q3_numbrushsides;
     71 q3_dbrushside_t	*q3_dbrushsides;//[Q3_MAX_MAP_BRUSHSIDES];
     72 
     73 int				q3_numLightBytes;
     74 byte			*q3_lightBytes;//[Q3_MAX_MAP_LIGHTING];
     75 
     76 int				q3_numGridPoints;
     77 byte			*q3_gridData;//[Q3_MAX_MAP_LIGHTGRID];
     78 
     79 int				q3_numVisBytes;
     80 byte			*q3_visBytes;//[Q3_MAX_MAP_VISIBILITY];
     81 
     82 int				q3_numDrawVerts;
     83 q3_drawVert_t	*q3_drawVerts;//[Q3_MAX_MAP_DRAW_VERTS];
     84 
     85 int				q3_numDrawIndexes;
     86 int				*q3_drawIndexes;//[Q3_MAX_MAP_DRAW_INDEXES];
     87 
     88 int				q3_numDrawSurfaces;
     89 q3_dsurface_t	*q3_drawSurfaces;//[Q3_MAX_MAP_DRAW_SURFS];
     90 
     91 int				q3_numFogs;
     92 q3_dfog_t		*q3_dfogs;//[Q3_MAX_MAP_FOGS];
     93 
     94 char			q3_dbrushsidetextured[Q3_MAX_MAP_BRUSHSIDES];
     95 
     96 extern qboolean forcesidesvisible;
     97 
     98 //===========================================================================
     99 //
    100 // Parameter:			-
    101 // Returns:				-
    102 // Changes Globals:		-
    103 //===========================================================================
    104 void Q3_FreeMaxBSP(void)
    105 {
    106 	if (q3_dmodels) FreeMemory(q3_dmodels);
    107 	q3_dmodels = NULL;
    108 	q3_nummodels = 0;
    109 	if (q3_dshaders) FreeMemory(q3_dshaders);
    110 	q3_dshaders = NULL;
    111 	q3_numShaders = 0;
    112 	if (q3_dentdata) FreeMemory(q3_dentdata);
    113 	q3_dentdata = NULL;
    114 	q3_entdatasize = 0;
    115 	if (q3_dleafs) FreeMemory(q3_dleafs);
    116 	q3_dleafs = NULL;
    117 	q3_numleafs = 0;
    118 	if (q3_dplanes) FreeMemory(q3_dplanes);
    119 	q3_dplanes = NULL;
    120 	q3_numplanes = 0;
    121 	if (q3_dnodes) FreeMemory(q3_dnodes);
    122 	q3_dnodes = NULL;
    123 	q3_numnodes = 0;
    124 	if (q3_dleafsurfaces) FreeMemory(q3_dleafsurfaces);
    125 	q3_dleafsurfaces = NULL;
    126 	q3_numleafsurfaces = 0;
    127 	if (q3_dleafbrushes) FreeMemory(q3_dleafbrushes);
    128 	q3_dleafbrushes = NULL;
    129 	q3_numleafbrushes = 0;
    130 	if (q3_dbrushes) FreeMemory(q3_dbrushes);
    131 	q3_dbrushes = NULL;
    132 	q3_numbrushes = 0;
    133 	if (q3_dbrushsides) FreeMemory(q3_dbrushsides);
    134 	q3_dbrushsides = NULL;
    135 	q3_numbrushsides = 0;
    136 	if (q3_lightBytes) FreeMemory(q3_lightBytes);
    137 	q3_lightBytes = NULL;
    138 	q3_numLightBytes = 0;
    139 	if (q3_gridData) FreeMemory(q3_gridData);
    140 	q3_gridData = NULL;
    141 	q3_numGridPoints = 0;
    142 	if (q3_visBytes) FreeMemory(q3_visBytes);
    143 	q3_visBytes = NULL;
    144 	q3_numVisBytes = 0;
    145 	if (q3_drawVerts) FreeMemory(q3_drawVerts);
    146 	q3_drawVerts = NULL;
    147 	q3_numDrawVerts = 0;
    148 	if (q3_drawIndexes) FreeMemory(q3_drawIndexes);
    149 	q3_drawIndexes = NULL;
    150 	q3_numDrawIndexes = 0;
    151 	if (q3_drawSurfaces) FreeMemory(q3_drawSurfaces);
    152 	q3_drawSurfaces = NULL;
    153 	q3_numDrawSurfaces = 0;
    154 	if (q3_dfogs) FreeMemory(q3_dfogs);
    155 	q3_dfogs = NULL;
    156 	q3_numFogs = 0;
    157 } //end of the function Q3_FreeMaxBSP
    158 
    159 
    160 //===========================================================================
    161 //
    162 // Parameter:			-
    163 // Returns:				-
    164 // Changes Globals:		-
    165 //===========================================================================
    166 void Q3_PlaneFromPoints(vec3_t p0, vec3_t p1, vec3_t p2, vec3_t normal, float *dist)
    167 {
    168 	vec3_t t1, t2;
    169 
    170 	VectorSubtract(p0, p1, t1);
    171 	VectorSubtract(p2, p1, t2);
    172 	CrossProduct(t1, t2, normal);
    173 	VectorNormalize(normal);
    174 
    175 	*dist = DotProduct(p0, normal);
    176 } //end of the function PlaneFromPoints
    177 //===========================================================================
    178 //
    179 // Parameter:				-
    180 // Returns:					-
    181 // Changes Globals:		-
    182 //===========================================================================
    183 void Q3_SurfacePlane(q3_dsurface_t *surface, vec3_t normal, float *dist)
    184 {
    185 	int i;
    186 	float *p0, *p1, *p2;
    187 	vec3_t t1, t2;
    188 
    189 	p0 = q3_drawVerts[surface->firstVert].xyz;
    190 	for (i = 1; i < surface->numVerts-1; i++)
    191 	{
    192 		p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
    193 		p2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
    194 		VectorSubtract(p0, p1, t1);
    195 		VectorSubtract(p2, p1, t2);
    196 		CrossProduct(t1, t2, normal);
    197 		VectorNormalize(normal);
    198 		if (VectorLength(normal)) break;
    199 	} //end for*/
    200 /*
    201 	float dot;
    202 	for (i = 0; i < surface->numVerts; i++)
    203 	{
    204 		p0 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
    205 		p1 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
    206 		p2 = q3_drawVerts[surface->firstVert + ((i+2) % surface->numVerts)].xyz;
    207 		VectorSubtract(p0, p1, t1);
    208 		VectorSubtract(p2, p1, t2);
    209 		VectorNormalize(t1);
    210 		VectorNormalize(t2);
    211 		dot = DotProduct(t1, t2);
    212 		if (dot > -0.9 && dot < 0.9 &&
    213 			VectorLength(t1) > 0.1 && VectorLength(t2) > 0.1) break;
    214 	} //end for
    215 	CrossProduct(t1, t2, normal);
    216 	VectorNormalize(normal);
    217 */
    218 	if (VectorLength(normal) < 0.9)
    219 	{
    220 		printf("surface %d bogus normal vector %f %f %f\n", surface - q3_drawSurfaces, normal[0], normal[1], normal[2]);
    221 		printf("t1 = %f %f %f, t2 = %f %f %f\n", t1[0], t1[1], t1[2], t2[0], t2[1], t2[2]);
    222 		for (i = 0; i < surface->numVerts; i++)
    223 		{
    224 			p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
    225 			Log_Print("p%d = %f %f %f\n", i, p1[0], p1[1], p1[2]);
    226 		} //end for
    227 	} //end if
    228 	*dist = DotProduct(p0, normal);
    229 } //end of the function Q3_SurfacePlane
    230 //===========================================================================
    231 //
    232 // Parameter:				-
    233 // Returns:					-
    234 // Changes Globals:		-
    235 //===========================================================================
    236 q3_dplane_t *q3_surfaceplanes;
    237 
    238 void Q3_CreatePlanarSurfacePlanes(void)
    239 {
    240 	int i;
    241 	q3_dsurface_t *surface;
    242 
    243 	Log_Print("creating planar surface planes...\n");
    244 	q3_surfaceplanes = (q3_dplane_t *) GetClearedMemory(q3_numDrawSurfaces * sizeof(q3_dplane_t));
    245 
    246 	for (i = 0; i < q3_numDrawSurfaces; i++)
    247 	{
    248 		surface = &q3_drawSurfaces[i];
    249 		if (surface->surfaceType != MST_PLANAR) continue;
    250 		Q3_SurfacePlane(surface, q3_surfaceplanes[i].normal, &q3_surfaceplanes[i].dist);
    251 		//Log_Print("normal = %f %f %f, dist = %f\n", q3_surfaceplanes[i].normal[0],
    252 		//											q3_surfaceplanes[i].normal[1],
    253 		//											q3_surfaceplanes[i].normal[2], q3_surfaceplanes[i].dist);
    254 	} //end for
    255 } //end of the function Q3_CreatePlanarSurfacePlanes
    256 //===========================================================================
    257 //
    258 // Parameter:				-
    259 // Returns:					-
    260 // Changes Globals:		-
    261 //===========================================================================
    262 /*
    263 void Q3_SurfacePlane(q3_dsurface_t *surface, vec3_t normal, float *dist)
    264 {
    265 	//take the plane information from the lightmap vector
    266 	//VectorCopy(surface->lightmapVecs[2], normal);
    267 	//calculate plane dist with first surface vertex
    268 	//*dist = DotProduct(q3_drawVerts[surface->firstVert].xyz, normal);
    269 	Q3_PlaneFromPoints(q3_drawVerts[surface->firstVert].xyz,
    270 						q3_drawVerts[surface->firstVert+1].xyz,
    271 						q3_drawVerts[surface->firstVert+2].xyz, normal, dist);
    272 } //end of the function Q3_SurfacePlane*/
    273 //===========================================================================
    274 // returns the amount the face and the winding overlap
    275 //
    276 // Parameter:				-
    277 // Returns:					-
    278 // Changes Globals:		-
    279 //===========================================================================
    280 float Q3_FaceOnWinding(q3_dsurface_t *surface, winding_t *winding)
    281 {
    282 	int i;
    283 	float dist, area;
    284 	q3_dplane_t plane;
    285 	vec_t *v1, *v2;
    286 	vec3_t normal, edgevec;
    287 	winding_t *w;
    288 
    289 	//copy the winding before chopping
    290 	w = CopyWinding(winding);
    291 	//retrieve the surface plane
    292 	Q3_SurfacePlane(surface, plane.normal, &plane.dist);
    293 	//chop the winding with the surface edge planes
    294 	for (i = 0; i < surface->numVerts && w; i++)
    295 	{
    296 		v1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
    297 		v2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
    298 		//create a plane through the edge from v1 to v2, orthogonal to the
    299 		//surface plane and with the normal vector pointing inward
    300 		VectorSubtract(v2, v1, edgevec);
    301 		CrossProduct(edgevec, plane.normal, normal);
    302 		VectorNormalize(normal);
    303 		dist = DotProduct(normal, v1);
    304 		//
    305 		ChopWindingInPlace(&w, normal, dist, -0.1); //CLIP_EPSILON
    306 	} //end for
    307 	if (w)
    308 	{
    309 		area = WindingArea(w);
    310 		FreeWinding(w);
    311 		return area;
    312 	} //end if
    313 	return 0;
    314 } //end of the function Q3_FaceOnWinding
    315 //===========================================================================
    316 // creates a winding for the given brush side on the given brush
    317 //
    318 // Parameter:				-
    319 // Returns:					-
    320 // Changes Globals:		-
    321 //===========================================================================
    322 winding_t *Q3_BrushSideWinding(q3_dbrush_t *brush, q3_dbrushside_t *baseside)
    323 {
    324 	int i;
    325 	q3_dplane_t *baseplane, *plane;
    326 	winding_t *w;
    327 	q3_dbrushside_t *side;
    328 	
    329 	//create a winding for the brush side with the given planenumber
    330 	baseplane = &q3_dplanes[baseside->planeNum];
    331 	w = BaseWindingForPlane(baseplane->normal, baseplane->dist);
    332 	for (i = 0; i < brush->numSides && w; i++)
    333 	{
    334 		side = &q3_dbrushsides[brush->firstSide + i];
    335 		//don't chop with the base plane
    336 		if (side->planeNum == baseside->planeNum) continue;
    337 		//also don't use planes that are almost equal
    338 		plane = &q3_dplanes[side->planeNum];
    339 		if (DotProduct(baseplane->normal, plane->normal) > 0.999
    340 				&& fabs(baseplane->dist - plane->dist) < 0.01) continue;
    341 		//
    342 		plane = &q3_dplanes[side->planeNum^1];
    343 		ChopWindingInPlace(&w, plane->normal, plane->dist, -0.1); //CLIP_EPSILON);
    344 	} //end for
    345 	return w;
    346 } //end of the function Q3_BrushSideWinding
    347 //===========================================================================
    348 // fix screwed brush texture references
    349 //
    350 // Parameter:				-
    351 // Returns:					-
    352 // Changes Globals:		-
    353 //===========================================================================
    354 qboolean WindingIsTiny(winding_t *w);
    355 
    356 void Q3_FindVisibleBrushSides(void)
    357 {
    358 	int i, j, k, we, numtextured, numsides;
    359 	float dot;
    360 	q3_dplane_t *plane;
    361 	q3_dbrushside_t *brushside;
    362 	q3_dbrush_t *brush;
    363 	q3_dsurface_t *surface;
    364 	winding_t *w;
    365 
    366 	memset(q3_dbrushsidetextured, false, Q3_MAX_MAP_BRUSHSIDES);
    367 	//
    368 	numsides = 0;
    369 	//create planes for the planar surfaces
    370 	Q3_CreatePlanarSurfacePlanes();
    371 	Log_Print("searching visible brush sides...\n");
    372 	Log_Print("%6d brush sides", numsides);
    373 	//go over all the brushes
    374 	for (i = 0; i < q3_numbrushes; i++)
    375 	{
    376 		brush = &q3_dbrushes[i];
    377 		//go over all the sides of the brush
    378 		for (j = 0; j < brush->numSides; j++)
    379 		{
    380 			qprintf("\r%6d", numsides++);
    381 			brushside = &q3_dbrushsides[brush->firstSide + j];
    382 			//
    383 			w = Q3_BrushSideWinding(brush, brushside);
    384 			if (!w)
    385 			{
    386 				q3_dbrushsidetextured[brush->firstSide + j] = true;
    387 				continue;
    388 			} //end if
    389 			else
    390 			{
    391 				//RemoveEqualPoints(w, 0.2);
    392 				if (WindingIsTiny(w))
    393 				{
    394 					FreeWinding(w);
    395 					q3_dbrushsidetextured[brush->firstSide + j] = true;
    396 					continue;
    397 				} //end if
    398 				else
    399 				{
    400 					we = WindingError(w);
    401 					if (we == WE_NOTENOUGHPOINTS
    402 						|| we == WE_SMALLAREA
    403 						|| we == WE_POINTBOGUSRANGE
    404 //						|| we == WE_NONCONVEX
    405 						)
    406 					{
    407 						FreeWinding(w);
    408 						q3_dbrushsidetextured[brush->firstSide + j] = true;
    409 						continue;
    410 					} //end if
    411 				} //end else
    412 			} //end else
    413 			if (WindingArea(w) < 20)
    414 			{
    415 				q3_dbrushsidetextured[brush->firstSide + j] = true;
    416 				continue;
    417 			} //end if
    418 			//find a face for texturing this brush
    419 			for (k = 0; k < q3_numDrawSurfaces; k++)
    420 			{
    421 				surface = &q3_drawSurfaces[k];
    422 				if (surface->surfaceType != MST_PLANAR) continue;
    423 				//
    424 				//Q3_SurfacePlane(surface, plane.normal, &plane.dist);
    425 				plane = &q3_surfaceplanes[k];
    426 				//the surface plane and the brush side plane should be pretty much the same
    427 				if (fabs(fabs(plane->dist) - fabs(q3_dplanes[brushside->planeNum].dist)) > 5) continue;
    428 				dot = DotProduct(plane->normal, q3_dplanes[brushside->planeNum].normal);
    429 				if (dot > -0.9 && dot < 0.9) continue;
    430 				//if the face is partly or totally on the brush side
    431 				if (Q3_FaceOnWinding(surface, w))
    432 				{
    433 					q3_dbrushsidetextured[brush->firstSide + j] = true;
    434 					//Log_Write("Q3_FaceOnWinding");
    435 					break;
    436 				} //end if
    437 			} //end for
    438 			FreeWinding(w);
    439 		} //end for
    440 	} //end for
    441 	qprintf("\r%6d brush sides\n", numsides);
    442 	numtextured = 0;
    443 	for (i = 0; i < q3_numbrushsides; i++)
    444 	{
    445 		if (forcesidesvisible) q3_dbrushsidetextured[i] = true;
    446 		if (q3_dbrushsidetextured[i]) numtextured++;
    447 	} //end for
    448 	Log_Print("%d brush sides textured out of %d\n", numtextured, q3_numbrushsides);
    449 } //end of the function Q3_FindVisibleBrushSides
    450 
    451 /*
    452 =============
    453 Q3_SwapBlock
    454 
    455 If all values are 32 bits, this can be used to swap everything
    456 =============
    457 */
    458 void Q3_SwapBlock( int *block, int sizeOfBlock ) {
    459 	int		i;
    460 
    461 	sizeOfBlock >>= 2;
    462 	for ( i = 0 ; i < sizeOfBlock ; i++ ) {
    463 		block[i] = LittleLong( block[i] );
    464 	}
    465 } //end of the function Q3_SwapBlock
    466 
    467 /*
    468 =============
    469 Q3_SwapBSPFile
    470 
    471 Byte swaps all data in a bsp file.
    472 =============
    473 */
    474 void Q3_SwapBSPFile( void ) {
    475 	int				i;
    476 	
    477 	// models	
    478 	Q3_SwapBlock( (int *)q3_dmodels, q3_nummodels * sizeof( q3_dmodels[0] ) );
    479 
    480 	// shaders (don't swap the name)
    481 	for ( i = 0 ; i < q3_numShaders ; i++ ) {
    482 		q3_dshaders[i].contentFlags = LittleLong( q3_dshaders[i].contentFlags );
    483 		q3_dshaders[i].surfaceFlags = LittleLong( q3_dshaders[i].surfaceFlags );
    484 	}
    485 
    486 	// planes
    487 	Q3_SwapBlock( (int *)q3_dplanes, q3_numplanes * sizeof( q3_dplanes[0] ) );
    488 	
    489 	// nodes
    490 	Q3_SwapBlock( (int *)q3_dnodes, q3_numnodes * sizeof( q3_dnodes[0] ) );
    491 
    492 	// leafs
    493 	Q3_SwapBlock( (int *)q3_dleafs, q3_numleafs * sizeof( q3_dleafs[0] ) );
    494 
    495 	// leaffaces
    496 	Q3_SwapBlock( (int *)q3_dleafsurfaces, q3_numleafsurfaces * sizeof( q3_dleafsurfaces[0] ) );
    497 
    498 	// leafbrushes
    499 	Q3_SwapBlock( (int *)q3_dleafbrushes, q3_numleafbrushes * sizeof( q3_dleafbrushes[0] ) );
    500 
    501 	// brushes
    502 	Q3_SwapBlock( (int *)q3_dbrushes, q3_numbrushes * sizeof( q3_dbrushes[0] ) );
    503 
    504 	// brushsides
    505 	Q3_SwapBlock( (int *)q3_dbrushsides, q3_numbrushsides * sizeof( q3_dbrushsides[0] ) );
    506 
    507 	// vis
    508 	((int *)&q3_visBytes)[0] = LittleLong( ((int *)&q3_visBytes)[0] );
    509 	((int *)&q3_visBytes)[1] = LittleLong( ((int *)&q3_visBytes)[1] );
    510 
    511 	// drawverts (don't swap colors )
    512 	for ( i = 0 ; i < q3_numDrawVerts ; i++ ) {
    513 		q3_drawVerts[i].lightmap[0] = LittleFloat( q3_drawVerts[i].lightmap[0] );
    514 		q3_drawVerts[i].lightmap[1] = LittleFloat( q3_drawVerts[i].lightmap[1] );
    515 		q3_drawVerts[i].st[0] = LittleFloat( q3_drawVerts[i].st[0] );
    516 		q3_drawVerts[i].st[1] = LittleFloat( q3_drawVerts[i].st[1] );
    517 		q3_drawVerts[i].xyz[0] = LittleFloat( q3_drawVerts[i].xyz[0] );
    518 		q3_drawVerts[i].xyz[1] = LittleFloat( q3_drawVerts[i].xyz[1] );
    519 		q3_drawVerts[i].xyz[2] = LittleFloat( q3_drawVerts[i].xyz[2] );
    520 		q3_drawVerts[i].normal[0] = LittleFloat( q3_drawVerts[i].normal[0] );
    521 		q3_drawVerts[i].normal[1] = LittleFloat( q3_drawVerts[i].normal[1] );
    522 		q3_drawVerts[i].normal[2] = LittleFloat( q3_drawVerts[i].normal[2] );
    523 	}
    524 
    525 	// drawindexes
    526 	Q3_SwapBlock( (int *)q3_drawIndexes, q3_numDrawIndexes * sizeof( q3_drawIndexes[0] ) );
    527 
    528 	// drawsurfs
    529 	Q3_SwapBlock( (int *)q3_drawSurfaces, q3_numDrawSurfaces * sizeof( q3_drawSurfaces[0] ) );
    530 
    531 	// fogs
    532 	for ( i = 0 ; i < q3_numFogs ; i++ ) {
    533 		q3_dfogs[i].brushNum = LittleLong( q3_dfogs[i].brushNum );
    534 	}
    535 }
    536 
    537 
    538 
    539 /*
    540 =============
    541 Q3_CopyLump
    542 =============
    543 */
    544 int Q3_CopyLump( q3_dheader_t	*header, int lump, void **dest, int size ) {
    545 	int		length, ofs;
    546 
    547 	length = header->lumps[lump].filelen;
    548 	ofs = header->lumps[lump].fileofs;
    549 	
    550 	if ( length % size ) {
    551 		Error ("Q3_LoadBSPFile: odd lump size");
    552 	}
    553 
    554 	*dest = GetMemory(length);
    555 
    556 	memcpy( *dest, (byte *)header + ofs, length );
    557 
    558 	return length / size;
    559 }
    560 
    561 /*
    562 =============
    563 CountTriangles
    564 =============
    565 */
    566 void CountTriangles( void ) {
    567 	int i, numTris, numPatchTris;
    568 	q3_dsurface_t *surface;
    569 
    570 	numTris = numPatchTris = 0;
    571 	for ( i = 0; i < q3_numDrawSurfaces; i++ ) {
    572 		surface = &q3_drawSurfaces[i];
    573 
    574 		numTris += surface->numIndexes / 3;
    575 
    576 		if ( surface->patchWidth ) {
    577 			numPatchTris += surface->patchWidth * surface->patchHeight * 2;
    578 		}
    579 	}
    580 
    581 	Log_Print( "%6d triangles\n", numTris );
    582 	Log_Print( "%6d patch tris\n", numPatchTris );
    583 }
    584 
    585 /*
    586 =============
    587 Q3_LoadBSPFile
    588 =============
    589 */
    590 void	Q3_LoadBSPFile(struct quakefile_s *qf)
    591 {
    592 	q3_dheader_t	*header;
    593 
    594 	// load the file header
    595 	//LoadFile(filename, (void **)&header, offset, length);
    596 	//
    597 	LoadQuakeFile(qf, (void **)&header);
    598 
    599 	// swap the header
    600 	Q3_SwapBlock( (int *)header, sizeof(*header) );
    601 
    602 	if ( header->ident != Q3_BSP_IDENT ) {
    603 		Error( "%s is not a IBSP file", qf->filename );
    604 	}
    605 	if ( header->version != Q3_BSP_VERSION ) {
    606 		Error( "%s is version %i, not %i", qf->filename, header->version, Q3_BSP_VERSION );
    607 	}
    608 
    609 	q3_numShaders = Q3_CopyLump( header, Q3_LUMP_SHADERS, (void *) &q3_dshaders, sizeof(q3_dshader_t) );
    610 	q3_nummodels = Q3_CopyLump( header, Q3_LUMP_MODELS, (void *) &q3_dmodels, sizeof(q3_dmodel_t) );
    611 	q3_numplanes = Q3_CopyLump( header, Q3_LUMP_PLANES, (void *) &q3_dplanes, sizeof(q3_dplane_t) );
    612 	q3_numleafs = Q3_CopyLump( header, Q3_LUMP_LEAFS, (void *) &q3_dleafs, sizeof(q3_dleaf_t) );
    613 	q3_numnodes = Q3_CopyLump( header, Q3_LUMP_NODES, (void *) &q3_dnodes, sizeof(q3_dnode_t) );
    614 	q3_numleafsurfaces = Q3_CopyLump( header, Q3_LUMP_LEAFSURFACES, (void *) &q3_dleafsurfaces, sizeof(q3_dleafsurfaces[0]) );
    615 	q3_numleafbrushes = Q3_CopyLump( header, Q3_LUMP_LEAFBRUSHES, (void *) &q3_dleafbrushes, sizeof(q3_dleafbrushes[0]) );
    616 	q3_numbrushes = Q3_CopyLump( header, Q3_LUMP_BRUSHES, (void *) &q3_dbrushes, sizeof(q3_dbrush_t) );
    617 	q3_numbrushsides = Q3_CopyLump( header, Q3_LUMP_BRUSHSIDES, (void *) &q3_dbrushsides, sizeof(q3_dbrushside_t) );
    618 	q3_numDrawVerts = Q3_CopyLump( header, Q3_LUMP_DRAWVERTS, (void *) &q3_drawVerts, sizeof(q3_drawVert_t) );
    619 	q3_numDrawSurfaces = Q3_CopyLump( header, Q3_LUMP_SURFACES, (void *) &q3_drawSurfaces, sizeof(q3_dsurface_t) );
    620 	q3_numFogs = Q3_CopyLump( header, Q3_LUMP_FOGS, (void *) &q3_dfogs, sizeof(q3_dfog_t) );
    621 	q3_numDrawIndexes = Q3_CopyLump( header, Q3_LUMP_DRAWINDEXES, (void *) &q3_drawIndexes, sizeof(q3_drawIndexes[0]) );
    622 
    623 	q3_numVisBytes = Q3_CopyLump( header, Q3_LUMP_VISIBILITY, (void *) &q3_visBytes, 1 );
    624 	q3_numLightBytes = Q3_CopyLump( header, Q3_LUMP_LIGHTMAPS, (void *) &q3_lightBytes, 1 );
    625 	q3_entdatasize = Q3_CopyLump( header, Q3_LUMP_ENTITIES, (void *) &q3_dentdata, 1);
    626 
    627 	q3_numGridPoints = Q3_CopyLump( header, Q3_LUMP_LIGHTGRID, (void *) &q3_gridData, 8 );
    628 
    629 	CountTriangles();
    630 
    631 	FreeMemory( header );		// everything has been copied out
    632 		
    633 	// swap everything
    634 	Q3_SwapBSPFile();
    635 
    636 	Q3_FindVisibleBrushSides();
    637 
    638 	//Q3_PrintBSPFileSizes();
    639 }
    640 
    641 
    642 //============================================================================
    643 
    644 /*
    645 =============
    646 Q3_AddLump
    647 =============
    648 */
    649 void Q3_AddLump( FILE *bspfile, q3_dheader_t *header, int lumpnum, void *data, int len ) {
    650 	q3_lump_t *lump;
    651 
    652 	lump = &header->lumps[lumpnum];
    653 	
    654 	lump->fileofs = LittleLong( ftell(bspfile) );
    655 	lump->filelen = LittleLong( len );
    656 	SafeWrite( bspfile, data, (len+3)&~3 );
    657 }
    658 
    659 /*
    660 =============
    661 Q3_WriteBSPFile
    662 
    663 Swaps the bsp file in place, so it should not be referenced again
    664 =============
    665 */
    666 void	Q3_WriteBSPFile( char *filename )
    667 {
    668 	q3_dheader_t	outheader, *header;
    669 	FILE		*bspfile;
    670 
    671 	header = &outheader;
    672 	memset( header, 0, sizeof(q3_dheader_t) );
    673 	
    674 	Q3_SwapBSPFile();
    675 
    676 	header->ident = LittleLong( Q3_BSP_IDENT );
    677 	header->version = LittleLong( Q3_BSP_VERSION );
    678 	
    679 	bspfile = SafeOpenWrite( filename );
    680 	SafeWrite( bspfile, header, sizeof(q3_dheader_t) );	// overwritten later
    681 
    682 	Q3_AddLump( bspfile, header, Q3_LUMP_SHADERS, q3_dshaders, q3_numShaders*sizeof(q3_dshader_t) );
    683 	Q3_AddLump( bspfile, header, Q3_LUMP_PLANES, q3_dplanes, q3_numplanes*sizeof(q3_dplane_t) );
    684 	Q3_AddLump( bspfile, header, Q3_LUMP_LEAFS, q3_dleafs, q3_numleafs*sizeof(q3_dleaf_t) );
    685 	Q3_AddLump( bspfile, header, Q3_LUMP_NODES, q3_dnodes, q3_numnodes*sizeof(q3_dnode_t) );
    686 	Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHES, q3_dbrushes, q3_numbrushes*sizeof(q3_dbrush_t) );
    687 	Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHSIDES, q3_dbrushsides, q3_numbrushsides*sizeof(q3_dbrushside_t) );
    688 	Q3_AddLump( bspfile, header, Q3_LUMP_LEAFSURFACES, q3_dleafsurfaces, q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0]) );
    689 	Q3_AddLump( bspfile, header, Q3_LUMP_LEAFBRUSHES, q3_dleafbrushes, q3_numleafbrushes*sizeof(q3_dleafbrushes[0]) );
    690 	Q3_AddLump( bspfile, header, Q3_LUMP_MODELS, q3_dmodels, q3_nummodels*sizeof(q3_dmodel_t) );
    691 	Q3_AddLump( bspfile, header, Q3_LUMP_DRAWVERTS, q3_drawVerts, q3_numDrawVerts*sizeof(q3_drawVert_t) );
    692 	Q3_AddLump( bspfile, header, Q3_LUMP_SURFACES, q3_drawSurfaces, q3_numDrawSurfaces*sizeof(q3_dsurface_t) );
    693 	Q3_AddLump( bspfile, header, Q3_LUMP_VISIBILITY, q3_visBytes, q3_numVisBytes );
    694 	Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTMAPS, q3_lightBytes, q3_numLightBytes );
    695 	Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTGRID, q3_gridData, 8 * q3_numGridPoints );
    696 	Q3_AddLump( bspfile, header, Q3_LUMP_ENTITIES, q3_dentdata, q3_entdatasize );
    697 	Q3_AddLump( bspfile, header, Q3_LUMP_FOGS, q3_dfogs, q3_numFogs * sizeof(q3_dfog_t) );
    698 	Q3_AddLump( bspfile, header, Q3_LUMP_DRAWINDEXES, q3_drawIndexes, q3_numDrawIndexes * sizeof(q3_drawIndexes[0]) );
    699 	
    700 	fseek (bspfile, 0, SEEK_SET);
    701 	SafeWrite (bspfile, header, sizeof(q3_dheader_t));
    702 	fclose (bspfile);	
    703 }
    704 
    705 //============================================================================
    706 
    707 /*
    708 =============
    709 Q3_PrintBSPFileSizes
    710 
    711 Dumps info about current file
    712 =============
    713 */
    714 void Q3_PrintBSPFileSizes( void )
    715 {
    716 	if ( !num_entities )
    717 	{
    718 		Q3_ParseEntities();
    719 	}
    720 
    721 	Log_Print ("%6i models       %7i\n"
    722 		,q3_nummodels, (int)(q3_nummodels*sizeof(q3_dmodel_t)));
    723 	Log_Print ("%6i shaders      %7i\n"
    724 		,q3_numShaders, (int)(q3_numShaders*sizeof(q3_dshader_t)));
    725 	Log_Print ("%6i brushes      %7i\n"
    726 		,q3_numbrushes, (int)(q3_numbrushes*sizeof(q3_dbrush_t)));
    727 	Log_Print ("%6i brushsides   %7i\n"
    728 		,q3_numbrushsides, (int)(q3_numbrushsides*sizeof(q3_dbrushside_t)));
    729 	Log_Print ("%6i fogs         %7i\n"
    730 		,q3_numFogs, (int)(q3_numFogs*sizeof(q3_dfog_t)));
    731 	Log_Print ("%6i planes       %7i\n"
    732 		,q3_numplanes, (int)(q3_numplanes*sizeof(q3_dplane_t)));
    733 	Log_Print ("%6i entdata      %7i\n", num_entities, q3_entdatasize);
    734 
    735 	Log_Print ("\n");
    736 
    737 	Log_Print ("%6i nodes        %7i\n"
    738 		,q3_numnodes, (int)(q3_numnodes*sizeof(q3_dnode_t)));
    739 	Log_Print ("%6i leafs        %7i\n"
    740 		,q3_numleafs, (int)(q3_numleafs*sizeof(q3_dleaf_t)));
    741 	Log_Print ("%6i leafsurfaces %7i\n"
    742 		,q3_numleafsurfaces, (int)(q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0])));
    743 	Log_Print ("%6i leafbrushes  %7i\n"
    744 		,q3_numleafbrushes, (int)(q3_numleafbrushes*sizeof(q3_dleafbrushes[0])));
    745 	Log_Print ("%6i drawverts    %7i\n"
    746 		,q3_numDrawVerts, (int)(q3_numDrawVerts*sizeof(q3_drawVerts[0])));
    747 	Log_Print ("%6i drawindexes  %7i\n"
    748 		,q3_numDrawIndexes, (int)(q3_numDrawIndexes*sizeof(q3_drawIndexes[0])));
    749 	Log_Print ("%6i drawsurfaces %7i\n"
    750 		,q3_numDrawSurfaces, (int)(q3_numDrawSurfaces*sizeof(q3_drawSurfaces[0])));
    751 
    752 	Log_Print ("%6i lightmaps    %7i\n"
    753 		,q3_numLightBytes / (LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*3), q3_numLightBytes );
    754 	Log_Print ("       visibility   %7i\n"
    755 		, q3_numVisBytes );
    756 }
    757 
    758 /*
    759 ================
    760 Q3_ParseEntities
    761 
    762 Parses the q3_dentdata string into entities
    763 ================
    764 */
    765 void Q3_ParseEntities (void)
    766 {
    767 	script_t *script;
    768 
    769 	num_entities = 0;
    770 	script = LoadScriptMemory(q3_dentdata, q3_entdatasize, "*Quake3 bsp file");
    771 	SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
    772 									SCFL_NOSTRINGESCAPECHARS);
    773 
    774 	while(ParseEntity(script))
    775 	{
    776 	} //end while
    777 
    778 	FreeScript(script);
    779 } //end of the function Q3_ParseEntities
    780 
    781 
    782 /*
    783 ================
    784 Q3_UnparseEntities
    785 
    786 Generates the q3_dentdata string from all the entities
    787 ================
    788 */
    789 void Q3_UnparseEntities (void)
    790 {
    791 	char *buf, *end;
    792 	epair_t *ep;
    793 	char line[2048];
    794 	int i;
    795 	
    796 	buf = q3_dentdata;
    797 	end = buf;
    798 	*end = 0;
    799 	
    800 	for (i=0 ; i<num_entities ; i++)
    801 	{
    802 		ep = entities[i].epairs;
    803 		if (!ep)
    804 			continue;	// ent got removed
    805 		
    806 		strcat (end,"{\n");
    807 		end += 2;
    808 				
    809 		for (ep = entities[i].epairs ; ep ; ep=ep->next)
    810 		{
    811 			sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
    812 			strcat (end, line);
    813 			end += strlen(line);
    814 		}
    815 		strcat (end,"}\n");
    816 		end += 2;
    817 
    818 		if (end > buf + Q3_MAX_MAP_ENTSTRING)
    819 			Error ("Entity text too long");
    820 	}
    821 	q3_entdatasize = end - buf + 1;
    822 } //end of the function Q3_UnparseEntities
    823 
    824