Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

map_q2.c (30781B)


      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 //===========================================================================
     24 // ANSI, Area Navigational System Interface
     25 // AAS,  Area Awareness System
     26 //===========================================================================
     27 
     28 #include "qbsp.h"
     29 #include "l_mem.h"
     30 #include "../botlib/aasfile.h"			//aas_bbox_t
     31 #include "aas_store.h"		//AAS_MAX_BBOXES
     32 #include "aas_cfg.h"
     33 #include "aas_map.h"			//AAS_CreateMapBrushes
     34 #include "l_bsp_q2.h"
     35 
     36 
     37 #ifdef ME
     38 
     39 #define NODESTACKSIZE		1024
     40 
     41 int nodestack[NODESTACKSIZE];
     42 int *nodestackptr;
     43 int nodestacksize = 0;
     44 int brushmodelnumbers[MAX_MAPFILE_BRUSHES];
     45 int dbrushleafnums[MAX_MAPFILE_BRUSHES];
     46 int dplanes2mapplanes[MAX_MAPFILE_PLANES];
     47 
     48 #endif //ME
     49 
     50 //====================================================================
     51 
     52 //===========================================================================
     53 //
     54 // Parameter:				-
     55 // Returns:					-
     56 // Changes Globals:		-
     57 //===========================================================================
     58 void Q2_CreateMapTexinfo(void)
     59 {
     60 	int i;
     61 
     62 	for (i = 0; i < numtexinfo; i++)
     63 	{
     64 		memcpy(map_texinfo[i].vecs, texinfo[i].vecs, sizeof(float) * 2 * 4);
     65 		map_texinfo[i].flags = texinfo[i].flags;
     66 		map_texinfo[i].value = texinfo[i].value;
     67 		strcpy(map_texinfo[i].texture, texinfo[i].texture);
     68 		map_texinfo[i].nexttexinfo = 0;
     69 	} //end for
     70 } //end of the function Q2_CreateMapTexinfo
     71 
     72 /*
     73 ===========
     74 Q2_BrushContents
     75 ===========
     76 */
     77 int	Q2_BrushContents (mapbrush_t *b)
     78 {
     79 	int			contents;
     80 	side_t		*s;
     81 	int			i;
     82 	int			trans;
     83 
     84 	s = &b->original_sides[0];
     85 	contents = s->contents;
     86 	trans = texinfo[s->texinfo].flags;
     87 	for (i = 1; i < b->numsides; i++, s++)
     88 	{
     89 		s = &b->original_sides[i];
     90 		trans |= texinfo[s->texinfo].flags;
     91 		if (s->contents != contents)
     92 		{
     93 			Log_Print("Entity %i, Brush %i: mixed face contents\n"
     94 				, b->entitynum, b->brushnum);
     95 			Log_Print("texture name = %s\n", texinfo[s->texinfo].texture);
     96 			break;
     97 		}
     98 	}
     99 
    100 	// if any side is translucent, mark the contents
    101 	// and change solid to window
    102 	if ( trans & (SURF_TRANS33|SURF_TRANS66) )
    103 	{
    104 		contents |= CONTENTS_Q2TRANSLUCENT;
    105 		if (contents & CONTENTS_SOLID)
    106 		{
    107 			contents &= ~CONTENTS_SOLID;
    108 			contents |= CONTENTS_WINDOW;
    109 		}
    110 	}
    111 
    112 	return contents;
    113 }
    114 
    115 #ifdef ME
    116 
    117 #define BBOX_NORMAL_EPSILON			0.0001
    118 
    119 //===========================================================================
    120 //
    121 // Parameter:				-
    122 // Returns:					-
    123 // Changes Globals:		-
    124 //===========================================================================
    125 void MakeAreaPortalBrush(mapbrush_t *brush)
    126 {
    127 	int sn;
    128 	side_t *s;
    129 
    130 	brush->contents = CONTENTS_AREAPORTAL;
    131 
    132 	for (sn = 0; sn < brush->numsides; sn++)
    133 	{
    134 		s = brush->original_sides + sn;
    135 		//make sure the surfaces are not hint or skip
    136 		s->surf &= ~(SURF_HINT|SURF_SKIP);
    137 		//
    138 		s->texinfo = 0;
    139 		s->contents = CONTENTS_AREAPORTAL;
    140 	} //end for
    141 } //end of the function MakeAreaPortalBrush
    142 //===========================================================================
    143 //
    144 // Parameter:				-
    145 // Returns:					-
    146 // Changes Globals:		-
    147 //===========================================================================
    148 void DPlanes2MapPlanes(void)
    149 {
    150 	int i;
    151 
    152 	for (i = 0; i < numplanes; i++)
    153 	{
    154 		dplanes2mapplanes[i] = FindFloatPlane(dplanes[i].normal, dplanes[i].dist);
    155 	} //end for
    156 } //end of the function DPlanes2MapPlanes
    157 //===========================================================================
    158 //
    159 // Parameter:				-
    160 // Returns:					-
    161 // Changes Globals:		-
    162 //===========================================================================
    163 void MarkVisibleBrushSides(mapbrush_t *brush)
    164 {
    165 	int n, i, planenum;
    166 	side_t *side;
    167 	dface_t *face;
    168 	//
    169 	for (n = 0; n < brush->numsides; n++)
    170 	{
    171 		side = brush->original_sides + n;
    172 		//if this side is a bevel or the leaf number of the brush is unknown
    173 		if ((side->flags & SFL_BEVEL) || brush->leafnum < 0)
    174 		{
    175 			//this side is a valid splitter
    176 			side->flags |= SFL_VISIBLE;
    177 			continue;
    178 		} //end if
    179 		//assum this side will not be used as a splitter
    180 		side->flags &= ~SFL_VISIBLE;
    181 		//check if the side plane is used by a visible face
    182 		for (i = 0; i < numfaces; i++)
    183 		{
    184 			face = &dfaces[i];
    185 			planenum = dplanes2mapplanes[face->planenum];
    186 			if ((planenum & ~1) == (side->planenum & ~1))
    187 			{
    188 				//this side is a valid splitter
    189 				side->flags |= SFL_VISIBLE;
    190 			} //end if
    191 		} //end for
    192 	} //end for
    193 } //end of the function MarkVisibleBrushSides
    194 
    195 #endif //ME
    196 
    197 /*
    198 =================
    199 Q2_ParseBrush
    200 =================
    201 */
    202 void Q2_ParseBrush (script_t *script, entity_t *mapent)
    203 {
    204 	mapbrush_t *b;
    205 	int i, j, k;
    206 	int mt;
    207 	side_t *side, *s2;
    208 	int planenum;
    209 	brush_texture_t td;
    210 	int planepts[3][3];
    211 	token_t token;
    212 
    213 	if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
    214 		Error ("nummapbrushes == MAX_MAPFILE_BRUSHES");
    215 
    216 	b = &mapbrushes[nummapbrushes];
    217 	b->original_sides = &brushsides[nummapbrushsides];
    218 	b->entitynum = num_entities-1;
    219 	b->brushnum = nummapbrushes - mapent->firstbrush;
    220 	b->leafnum = -1;
    221 
    222 	do
    223 	{
    224 		if (!PS_ReadToken(script, &token))
    225 			break;
    226 		if (!strcmp(token.string, "}") )
    227 			break;
    228 
    229 		//IDBUG: mixed use of MAX_MAPFILE_? and MAX_MAP_? this could
    230 		//			lead to out of bound indexing of the arrays
    231 		if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
    232 			Error ("MAX_MAPFILE_BRUSHSIDES");
    233 		side = &brushsides[nummapbrushsides];
    234 
    235 		//read the three point plane definition
    236 		for (i = 0; i < 3; i++)
    237 		{
    238 			if (i != 0) PS_ExpectTokenString(script, "(");
    239 			for (j = 0; j < 3; j++)
    240 			{
    241 				PS_ExpectAnyToken(script, &token);
    242 				planepts[i][j] = atof(token.string);
    243 			} //end for
    244 			PS_ExpectTokenString(script, ")");
    245 		} //end for
    246 
    247 		//
    248 		//read the texturedef
    249 		//
    250 		PS_ExpectAnyToken(script, &token);
    251 		strcpy(td.name, token.string);
    252 
    253 		PS_ExpectAnyToken(script, &token);
    254 		td.shift[0] = atol(token.string);
    255 		PS_ExpectAnyToken(script, &token);
    256 		td.shift[1] = atol(token.string);
    257 		PS_ExpectAnyToken(script, &token);
    258 		td.rotate = atol(token.string);
    259 		PS_ExpectAnyToken(script, &token);
    260 		td.scale[0] = atof(token.string);
    261 		PS_ExpectAnyToken(script, &token);
    262 		td.scale[1] = atof(token.string);
    263 
    264 		//find default flags and values
    265 		mt = FindMiptex (td.name);
    266 		td.flags = textureref[mt].flags;
    267 		td.value = textureref[mt].value;
    268 		side->contents = textureref[mt].contents;
    269 		side->surf = td.flags = textureref[mt].flags;
    270 
    271 		//check if there's a number available
    272 		if (PS_CheckTokenType(script, TT_NUMBER, 0, &token))
    273 		{
    274 			side->contents = token.intvalue;
    275 			PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
    276 			side->surf = td.flags = token.intvalue;
    277 			PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
    278 			td.value = token.intvalue;
    279 		}
    280 
    281 		// translucent objects are automatically classified as detail
    282 		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
    283 			side->contents |= CONTENTS_DETAIL;
    284 		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
    285 			side->contents |= CONTENTS_DETAIL;
    286 		if (fulldetail)
    287 			side->contents &= ~CONTENTS_DETAIL;
    288 		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
    289 			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
    290 			side->contents |= CONTENTS_SOLID;
    291 
    292 		// hints and skips are never detail, and have no content
    293 		if (side->surf & (SURF_HINT|SURF_SKIP) )
    294 		{
    295 			side->contents = 0;
    296 			side->surf &= ~CONTENTS_DETAIL;
    297 		}
    298 
    299 #ifdef ME
    300 		//for creating AAS... this side is textured
    301 		side->flags |= SFL_TEXTURED;
    302 #endif //ME
    303 		//
    304 		// find the plane number
    305 		//
    306 		planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
    307 		if (planenum == -1)
    308 		{
    309 			Log_Print("Entity %i, Brush %i: plane with no normal\n"
    310 				, b->entitynum, b->brushnum);
    311 			continue;
    312 		}
    313 
    314 		//
    315 		// see if the plane has been used already
    316 		//
    317 		for (k=0 ; k<b->numsides ; k++)
    318 		{
    319 			s2 = b->original_sides + k;
    320 			if (s2->planenum == planenum)
    321 			{
    322 				Log_Print("Entity %i, Brush %i: duplicate plane\n"
    323 					, b->entitynum, b->brushnum);
    324 				break;
    325 			}
    326 			if ( s2->planenum == (planenum^1) )
    327 			{
    328 				Log_Print("Entity %i, Brush %i: mirrored plane\n"
    329 					, b->entitynum, b->brushnum);
    330 				break;
    331 			}
    332 		}
    333 		if (k != b->numsides)
    334 			continue;		// duplicated
    335 
    336 		//
    337 		// keep this side
    338 		//
    339 
    340 		side = b->original_sides + b->numsides;
    341 		side->planenum = planenum;
    342 		side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
    343 			&td, vec3_origin);
    344 
    345 		// save the td off in case there is an origin brush and we
    346 		// have to recalculate the texinfo
    347 		side_brushtextures[nummapbrushsides] = td;
    348 
    349 		nummapbrushsides++;
    350 		b->numsides++;
    351 	} while (1);
    352 
    353 	// get the content for the entire brush
    354 	b->contents = Q2_BrushContents (b);
    355 
    356 #ifdef ME
    357 	if (BrushExists(b))
    358 	{
    359 		c_squattbrushes++;
    360 		b->numsides = 0;
    361 		return;
    362 	} //end if
    363 
    364 	if (create_aas)
    365 	{
    366 		//create AAS brushes, and add brush bevels
    367 		AAS_CreateMapBrushes(b, mapent, true);
    368 		//NOTE: if we return here then duplicate plane errors occur for the non world entities
    369 		return;
    370 	} //end if
    371 #endif //ME
    372 
    373 	// allow detail brushes to be removed 
    374 	if (nodetail && (b->contents & CONTENTS_DETAIL) )
    375 	{
    376 		b->numsides = 0;
    377 		return;
    378 	}
    379 
    380 	// allow water brushes to be removed
    381 	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
    382 	{
    383 		b->numsides = 0;
    384 		return;
    385 	}
    386 
    387 	// create windings for sides and bounds for brush
    388 	MakeBrushWindings (b);
    389 
    390 	// brushes that will not be visible at all will never be
    391 	// used as bsp splitters
    392 	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
    393 	{
    394 		c_clipbrushes++;
    395 		for (i=0 ; i<b->numsides ; i++)
    396 			b->original_sides[i].texinfo = TEXINFO_NODE;
    397 	}
    398 
    399 	//
    400 	// origin brushes are removed, but they set
    401 	// the rotation origin for the rest of the brushes
    402 	// in the entity.  After the entire entity is parsed,
    403 	// the planenums and texinfos will be adjusted for
    404 	// the origin brush
    405 	//
    406 	if (b->contents & CONTENTS_ORIGIN)
    407 	{
    408 		char	string[32];
    409 		vec3_t	origin;
    410 
    411 		if (num_entities == 1)
    412 		{
    413 			Error ("Entity %i, Brush %i: origin brushes not allowed in world"
    414 				, b->entitynum, b->brushnum);
    415 			return;
    416 		}
    417 
    418 		VectorAdd (b->mins, b->maxs, origin);
    419 		VectorScale (origin, 0.5, origin);
    420 
    421 		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
    422 		SetKeyValue (&entities[b->entitynum], "origin", string);
    423 
    424 		VectorCopy (origin, entities[b->entitynum].origin);
    425 
    426 		// don't keep this brush
    427 		b->numsides = 0;
    428 
    429 		return;
    430 	}
    431 
    432 	AddBrushBevels(b);
    433 
    434 	nummapbrushes++;
    435 	mapent->numbrushes++;		
    436 }
    437 
    438 /*
    439 ================
    440 Q2_MoveBrushesToWorld
    441 
    442 Takes all of the brushes from the current entity and
    443 adds them to the world's brush list.
    444 
    445 Used by func_group and func_areaportal
    446 ================
    447 */
    448 void Q2_MoveBrushesToWorld (entity_t *mapent)
    449 {
    450 	int			newbrushes;
    451 	int			worldbrushes;
    452 	mapbrush_t	*temp;
    453 	int			i;
    454 
    455 	// this is pretty gross, because the brushes are expected to be
    456 	// in linear order for each entity
    457 
    458 	newbrushes = mapent->numbrushes;
    459 	worldbrushes = entities[0].numbrushes;
    460 
    461 	temp = GetMemory(newbrushes*sizeof(mapbrush_t));
    462 	memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
    463 
    464 #if	0		// let them keep their original brush numbers
    465 	for (i=0 ; i<newbrushes ; i++)
    466 		temp[i].entitynum = 0;
    467 #endif
    468 
    469 	// make space to move the brushes (overlapped copy)
    470 	memmove (mapbrushes + worldbrushes + newbrushes,
    471 		mapbrushes + worldbrushes,
    472 		sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
    473 
    474 	// copy the new brushes down
    475 	memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
    476 
    477 	// fix up indexes
    478 	entities[0].numbrushes += newbrushes;
    479 	for (i=1 ; i<num_entities ; i++)
    480 		entities[i].firstbrush += newbrushes;
    481 	FreeMemory(temp);
    482 
    483 	mapent->numbrushes = 0;
    484 }
    485 
    486 /*
    487 ================
    488 Q2_ParseMapEntity
    489 ================
    490 */
    491 qboolean	Q2_ParseMapEntity(script_t *script)
    492 {
    493 	entity_t	*mapent;
    494 	epair_t *e;
    495 	side_t *s;
    496 	int i, j;
    497 	int startbrush, startsides;
    498 	vec_t newdist;
    499 	mapbrush_t *b;
    500 	token_t token;
    501 
    502 	if (!PS_ReadToken(script, &token)) return false;
    503 
    504 	if (strcmp(token.string, "{") )
    505 		Error ("ParseEntity: { not found");
    506 	
    507 	if (num_entities == MAX_MAP_ENTITIES)
    508 		Error ("num_entities == MAX_MAP_ENTITIES");
    509 
    510 	startbrush = nummapbrushes;
    511 	startsides = nummapbrushsides;
    512 
    513 	mapent = &entities[num_entities];
    514 	num_entities++;
    515 	memset (mapent, 0, sizeof(*mapent));
    516 	mapent->firstbrush = nummapbrushes;
    517 	mapent->numbrushes = 0;
    518 //	mapent->portalareas[0] = -1;
    519 //	mapent->portalareas[1] = -1;
    520 
    521 	do
    522 	{
    523 		if (!PS_ReadToken(script, &token))
    524 		{
    525 			Error("ParseEntity: EOF without closing brace");
    526 		} //end if
    527 		if (!strcmp(token.string, "}")) break;
    528 		if (!strcmp(token.string, "{"))
    529 		{
    530 			Q2_ParseBrush(script, mapent);
    531 		} //end if
    532 		else
    533 		{
    534 			PS_UnreadLastToken(script);
    535 			e = ParseEpair(script);
    536 			e->next = mapent->epairs;
    537 			mapent->epairs = e;
    538 		} //end else
    539 	} while(1);
    540 
    541 	GetVectorForKey(mapent, "origin", mapent->origin);
    542 
    543 	//
    544 	// if there was an origin brush, offset all of the planes and texinfo
    545 	//
    546 	if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
    547 	{
    548 		for (i=0 ; i<mapent->numbrushes ; i++)
    549 		{
    550 			b = &mapbrushes[mapent->firstbrush + i];
    551 			for (j=0 ; j<b->numsides ; j++)
    552 			{
    553 				s = &b->original_sides[j];
    554 				newdist = mapplanes[s->planenum].dist -
    555 					DotProduct (mapplanes[s->planenum].normal, mapent->origin);
    556 				s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
    557 				s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
    558 					&side_brushtextures[s-brushsides], mapent->origin);
    559 			}
    560 			MakeBrushWindings (b);
    561 		}
    562 	}
    563 
    564 	// group entities are just for editor convenience
    565 	// toss all brushes into the world entity
    566 	if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
    567 	{
    568 		Q2_MoveBrushesToWorld (mapent);
    569 		mapent->numbrushes = 0;
    570 		return true;
    571 	}
    572 
    573 	// areaportal entities move their brushes, but don't eliminate
    574 	// the entity
    575 	if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
    576 	{
    577 		char	str[128];
    578 
    579 		if (mapent->numbrushes != 1)
    580 			Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
    581 
    582 		b = &mapbrushes[nummapbrushes-1];
    583 		b->contents = CONTENTS_AREAPORTAL;
    584 		c_areaportals++;
    585 		mapent->areaportalnum = c_areaportals;
    586 		// set the portal number as "style"
    587 		sprintf (str, "%i", c_areaportals);
    588 		SetKeyValue (mapent, "style", str);
    589 		Q2_MoveBrushesToWorld (mapent);
    590 		return true;
    591 	}
    592 
    593 	return true;
    594 }
    595 
    596 //===================================================================
    597 
    598 /*
    599 ================
    600 LoadMapFile
    601 ================
    602 */
    603 void Q2_LoadMapFile(char *filename)
    604 {		
    605 	int i;
    606 	script_t *script;
    607 
    608 	Log_Print("-- Q2_LoadMapFile --\n");
    609 #ifdef ME
    610 	//loaded map type
    611 	loadedmaptype = MAPTYPE_QUAKE2;
    612 	//reset the map loading
    613 	ResetMapLoading();
    614 #endif //ME
    615 
    616 	script = LoadScriptFile(filename);
    617 	if (!script)
    618 	{
    619 		Log_Print("couldn't open %s\n", filename);
    620 		return;
    621 	} //end if
    622 	//white spaces and escape characters inside a string are not allowed
    623 	SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
    624 									SCFL_NOSTRINGESCAPECHARS |
    625 									SCFL_PRIMITIVE);
    626 
    627 	nummapbrushsides = 0;
    628 	num_entities = 0;
    629 	
    630 	while (Q2_ParseMapEntity(script))
    631 	{
    632 	}
    633 
    634 	ClearBounds (map_mins, map_maxs);
    635 	for (i=0 ; i<entities[0].numbrushes ; i++)
    636 	{
    637 		if (mapbrushes[i].mins[0] > 4096)
    638 			continue;	// no valid points
    639 		AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
    640 		AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
    641 	} //end for
    642 
    643 	PrintMapInfo();
    644 
    645 	//free the script
    646 	FreeScript(script);
    647 //	TestExpandBrushes ();
    648 	//
    649 	Q2_CreateMapTexinfo();
    650 } //end of the function Q2_LoadMapFile
    651 
    652 #ifdef ME		//Begin MAP loading from BSP file
    653 //===========================================================================
    654 //
    655 // Parameter:				-
    656 // Returns:					-
    657 // Changes Globals:		-
    658 //===========================================================================
    659 void Q2_SetLeafBrushesModelNumbers(int leafnum, int modelnum)
    660 {
    661 	int i, brushnum;
    662 	dleaf_t *leaf;
    663 
    664 	leaf = &dleafs[leafnum];
    665 	for (i = 0; i < leaf->numleafbrushes; i++)
    666 	{
    667 		brushnum = dleafbrushes[leaf->firstleafbrush + i];
    668 		brushmodelnumbers[brushnum] = modelnum;
    669 		dbrushleafnums[brushnum] = leafnum;
    670 	} //end for
    671 } //end of the function Q2_SetLeafBrushesModelNumbers
    672 //===========================================================================
    673 //
    674 // Parameter:				-
    675 // Returns:					-
    676 // Changes Globals:		-
    677 //===========================================================================
    678 void Q2_InitNodeStack(void)
    679 {
    680 	nodestackptr = nodestack;
    681 	nodestacksize = 0;
    682 } //end of the function Q2_InitNodeStack
    683 //===========================================================================
    684 //
    685 // Parameter:				-
    686 // Returns:					-
    687 // Changes Globals:		-
    688 //===========================================================================
    689 void Q2_PushNodeStack(int num)
    690 {
    691 	*nodestackptr = num;
    692 	nodestackptr++;
    693 	nodestacksize++;
    694 	//
    695 	if (nodestackptr >= &nodestack[NODESTACKSIZE])
    696 	{
    697 		Error("Q2_PushNodeStack: stack overflow\n");
    698 	} //end if
    699 } //end of the function Q2_PushNodeStack
    700 //===========================================================================
    701 //
    702 // Parameter:				-
    703 // Returns:					-
    704 // Changes Globals:		-
    705 //===========================================================================
    706 int Q2_PopNodeStack(void)
    707 {
    708 	//if the stack is empty
    709 	if (nodestackptr <= nodestack) return -1;
    710 	//decrease stack pointer
    711 	nodestackptr--;
    712 	nodestacksize--;
    713 	//return the top value from the stack
    714 	return *nodestackptr;
    715 } //end of the function Q2_PopNodeStack
    716 //===========================================================================
    717 //
    718 // Parameter:				-
    719 // Returns:					-
    720 // Changes Globals:		-
    721 //===========================================================================
    722 void Q2_SetBrushModelNumbers(entity_t *mapent)
    723 {
    724 	int n, pn;
    725 	int leafnum;
    726 
    727 	//
    728 	Q2_InitNodeStack();
    729 	//head node (root) of the bsp tree
    730 	n = dmodels[mapent->modelnum].headnode;
    731 	pn = 0;
    732 	
    733 	do
    734 	{
    735 		//if we are in a leaf (negative node number)
    736 		if (n < 0)
    737 		{
    738 			//number of the leaf
    739 			leafnum = (-n) - 1;
    740 			//set the brush numbers
    741 			Q2_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum);
    742 			//walk back into the tree to find a second child to continue with
    743 			for (pn = Q2_PopNodeStack(); pn >= 0; n = pn, pn = Q2_PopNodeStack())
    744 			{
    745 				//if we took the first child at the parent node
    746 				if (dnodes[pn].children[0] == n) break;
    747 			} //end for
    748 			//if the stack wasn't empty (if not processed whole tree)
    749 			if (pn >= 0)
    750 			{
    751 				//push the parent node again
    752 				Q2_PushNodeStack(pn);
    753 				//we proceed with the second child of the parent node
    754 				n = dnodes[pn].children[1];
    755 			} //end if
    756 		} //end if
    757 		else
    758 		{
    759 			//push the current node onto the stack
    760 			Q2_PushNodeStack(n);
    761 			//walk forward into the tree to the first child
    762 			n = dnodes[n].children[0];
    763 		} //end else
    764 	} while(pn >= 0);
    765 } //end of the function Q2_SetBrushModelNumbers
    766 //===========================================================================
    767 //
    768 // Parameter:				-
    769 // Returns:					-
    770 // Changes Globals:		-
    771 //===========================================================================
    772 void Q2_BSPBrushToMapBrush(dbrush_t *bspbrush, entity_t *mapent)
    773 {
    774 	mapbrush_t *b;
    775 	int i, k, n;
    776 	side_t *side, *s2;
    777 	int planenum;
    778 	dbrushside_t *bspbrushside;
    779 	dplane_t *bspplane;
    780 
    781 	if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
    782 		Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES");
    783 
    784 	b = &mapbrushes[nummapbrushes];
    785 	b->original_sides = &brushsides[nummapbrushsides];
    786 	b->entitynum = mapent-entities;
    787 	b->brushnum = nummapbrushes - mapent->firstbrush;
    788 	b->leafnum = dbrushleafnums[bspbrush - dbrushes];
    789 
    790 	for (n = 0; n < bspbrush->numsides; n++)
    791 	{
    792 		//pointer to the bsp brush side
    793 		bspbrushside = &dbrushsides[bspbrush->firstside + n];
    794 
    795 		if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
    796 		{
    797 			Error ("MAX_MAPFILE_BRUSHSIDES");
    798 		} //end if
    799 		//pointer to the map brush side
    800 		side = &brushsides[nummapbrushsides];
    801 		//if the BSP brush side is textured
    802 		if (brushsidetextured[bspbrush->firstside + n]) side->flags |= SFL_TEXTURED;
    803 		else side->flags &= ~SFL_TEXTURED;
    804 		//ME: can get side contents and surf directly from BSP file
    805 		side->contents = bspbrush->contents;
    806 		//if the texinfo is TEXINFO_NODE
    807 		if (bspbrushside->texinfo < 0) side->surf = 0;
    808 		else side->surf = texinfo[bspbrushside->texinfo].flags;
    809 
    810 		// translucent objects are automatically classified as detail
    811 		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
    812 			side->contents |= CONTENTS_DETAIL;
    813 		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
    814 			side->contents |= CONTENTS_DETAIL;
    815 		if (fulldetail)
    816 			side->contents &= ~CONTENTS_DETAIL;
    817 		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
    818 			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
    819 			side->contents |= CONTENTS_SOLID;
    820 
    821 		// hints and skips are never detail, and have no content
    822 		if (side->surf & (SURF_HINT|SURF_SKIP) )
    823 		{
    824 			side->contents = 0;
    825 			side->surf &= ~CONTENTS_DETAIL;
    826 		}
    827 
    828 		//ME: get a plane for this side
    829 		bspplane = &dplanes[bspbrushside->planenum];
    830 		planenum = FindFloatPlane(bspplane->normal, bspplane->dist);
    831 		//
    832 		// see if the plane has been used already
    833 		//
    834 		//ME: this really shouldn't happen!!!
    835 		//ME: otherwise the bsp file is corrupted??
    836 		//ME: still it seems to happen, maybe Johny Boy's
    837 		//ME: brush bevel adding is crappy ?
    838 		for (k = 0; k < b->numsides; k++)
    839 		{
    840 			s2 = b->original_sides + k;
    841 //			if (DotProduct (mapplanes[s2->planenum].normal, mapplanes[planenum].normal) > 0.999
    842 //							&& fabs(mapplanes[s2->planenum].dist - mapplanes[planenum].dist) < 0.01 )
    843 
    844 			if (s2->planenum == planenum)
    845 			{
    846 				Log_Print("Entity %i, Brush %i: duplicate plane\n"
    847 					, b->entitynum, b->brushnum);
    848 				break;
    849 			}
    850 			if ( s2->planenum == (planenum^1) )
    851 			{
    852 				Log_Print("Entity %i, Brush %i: mirrored plane\n"
    853 					, b->entitynum, b->brushnum);
    854 				break;
    855 			}
    856 		}
    857 		if (k != b->numsides)
    858 			continue;		// duplicated
    859 
    860 		//
    861 		// keep this side
    862 		//
    863 		//ME: reset pointer to side, why? hell I dunno (pointer is set above already)
    864 		side = b->original_sides + b->numsides;
    865 		//ME: store the plane number
    866 		side->planenum = planenum;
    867 		//ME: texinfo is already stored when bsp is loaded
    868 		//NOTE: check for TEXINFO_NODE, otherwise crash in Q2_BrushContents
    869 		if (bspbrushside->texinfo < 0) side->texinfo = 0;
    870 		else side->texinfo = bspbrushside->texinfo;
    871 
    872 		// save the td off in case there is an origin brush and we
    873 		// have to recalculate the texinfo
    874 		// ME: don't need to recalculate because it's already done
    875 		//     (for non-world entities) in the BSP file
    876 //		side_brushtextures[nummapbrushsides] = td;
    877 
    878 		nummapbrushsides++;
    879 		b->numsides++;
    880 	} //end for
    881 
    882 	// get the content for the entire brush
    883 	b->contents = bspbrush->contents;
    884 	Q2_BrushContents(b);
    885 
    886 	if (BrushExists(b))
    887 	{
    888 		c_squattbrushes++;
    889 		b->numsides = 0;
    890 		return;
    891 	} //end if
    892 
    893 	//if we're creating AAS
    894 	if (create_aas)
    895 	{
    896 		//create the AAS brushes from this brush, don't add brush bevels
    897 		AAS_CreateMapBrushes(b, mapent, false);
    898 		return;
    899 	} //end if
    900 
    901 	// allow detail brushes to be removed 
    902 	if (nodetail && (b->contents & CONTENTS_DETAIL) )
    903 	{
    904 		b->numsides = 0;
    905 		return;
    906 	} //end if
    907 
    908 	// allow water brushes to be removed
    909 	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
    910 	{
    911 		b->numsides = 0;
    912 		return;
    913 	} //end if
    914 
    915 	// create windings for sides and bounds for brush
    916 	MakeBrushWindings(b);
    917 
    918 	//mark brushes without winding or with a tiny window as bevels
    919 	MarkBrushBevels(b);
    920 
    921 	// brushes that will not be visible at all will never be
    922 	// used as bsp splitters
    923 	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
    924 	{
    925 			c_clipbrushes++;
    926 		for (i = 0; i < b->numsides; i++)
    927 			b->original_sides[i].texinfo = TEXINFO_NODE;
    928 	} //end for
    929 
    930 	//
    931 	// origin brushes are removed, but they set
    932 	// the rotation origin for the rest of the brushes
    933 	// in the entity.  After the entire entity is parsed,
    934 	// the planenums and texinfos will be adjusted for
    935 	// the origin brush
    936 	//
    937 	//ME: not needed because the entities in the BSP file already
    938 	//    have an origin set
    939 //	if (b->contents & CONTENTS_ORIGIN)
    940 //	{
    941 //		char	string[32];
    942 //		vec3_t	origin;
    943 //
    944 //		if (num_entities == 1)
    945 //		{
    946 //			Error ("Entity %i, Brush %i: origin brushes not allowed in world"
    947 //				, b->entitynum, b->brushnum);
    948 //			return;
    949 //		}
    950 //
    951 //		VectorAdd (b->mins, b->maxs, origin);
    952 //		VectorScale (origin, 0.5, origin);
    953 //
    954 //		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
    955 //		SetKeyValue (&entities[b->entitynum], "origin", string);
    956 //
    957 //		VectorCopy (origin, entities[b->entitynum].origin);
    958 //
    959 //		// don't keep this brush
    960 //		b->numsides = 0;
    961 //
    962 //		return;
    963 //	}
    964 
    965 	//ME: the bsp brushes already have bevels, so we won't try to
    966 	//    add them again (especially since Johny Boy's bevel adding might
    967 	//    be crappy)
    968 //	AddBrushBevels(b);
    969 
    970 	nummapbrushes++;
    971 	mapent->numbrushes++;
    972 } //end of the function Q2_BSPBrushToMapBrush
    973 //===========================================================================
    974 //===========================================================================
    975 void Q2_ParseBSPBrushes(entity_t *mapent)
    976 {
    977 	int i;
    978 
    979 	//give all the brushes that belong to this entity the number of the
    980 	//BSP model used by this entity
    981 	Q2_SetBrushModelNumbers(mapent);
    982 	//now parse all the brushes with the correct mapent->modelnum
    983 	for (i = 0; i < numbrushes; i++)
    984 	{
    985 		if (brushmodelnumbers[i] == mapent->modelnum)
    986 		{
    987 			Q2_BSPBrushToMapBrush(&dbrushes[i], mapent);
    988 		} //end if
    989 	} //end for
    990 } //end of the function Q2_ParseBSPBrushes
    991 //===========================================================================
    992 //===========================================================================
    993 qboolean Q2_ParseBSPEntity(int entnum)
    994 {
    995 	entity_t	*mapent;
    996 	char *model;
    997 	int startbrush, startsides;
    998 
    999 	startbrush = nummapbrushes;
   1000 	startsides = nummapbrushsides;
   1001 
   1002 	mapent = &entities[entnum];//num_entities];
   1003 	mapent->firstbrush = nummapbrushes;
   1004 	mapent->numbrushes = 0;
   1005 	mapent->modelnum = -1;	//-1 = no model
   1006 
   1007 	model = ValueForKey(mapent, "model");
   1008 	if (model && strlen(model))
   1009 	{
   1010 		if (*model != '*')
   1011 		{
   1012 			Error("Q2_ParseBSPEntity: model number without leading *");
   1013 		} //end if
   1014 		//get the model number of this entity (skip the leading *)
   1015 		mapent->modelnum = atoi(&model[1]);
   1016 	} //end if
   1017 
   1018 	GetVectorForKey(mapent, "origin", mapent->origin);
   1019 
   1020 	//if this is the world entity it has model number zero
   1021 	//the world entity has no model key
   1022 	if (!strcmp("worldspawn", ValueForKey(mapent, "classname")))
   1023 	{
   1024 		mapent->modelnum = 0;
   1025 	} //end if
   1026 	//if the map entity has a BSP model (a modelnum of -1 is used for
   1027 	//entities that aren't using a BSP model)
   1028 	if (mapent->modelnum >= 0)
   1029 	{
   1030 		//parse the bsp brushes
   1031 		Q2_ParseBSPBrushes(mapent);
   1032 	} //end if
   1033 	//
   1034 	//the origin of the entity is already taken into account
   1035 	//
   1036 	//func_group entities can't be in the bsp file
   1037 	//
   1038 	//check out the func_areaportal entities
   1039 	if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
   1040 	{
   1041 		c_areaportals++;
   1042 		mapent->areaportalnum = c_areaportals;
   1043 		return true;
   1044 	} //end if
   1045 	return true;
   1046 } //end of the function Q2_ParseBSPEntity
   1047 //===========================================================================
   1048 //
   1049 // Parameter:				-
   1050 // Returns:					-
   1051 // Changes Globals:		-
   1052 //===========================================================================
   1053 void Q2_LoadMapFromBSP(char *filename, int offset, int length)
   1054 {
   1055 	int i;
   1056 
   1057 	Log_Print("-- Q2_LoadMapFromBSP --\n");
   1058 	//loaded map type
   1059 	loadedmaptype = MAPTYPE_QUAKE2;
   1060 
   1061 	Log_Print("Loading map from %s...\n", filename);
   1062 	//load the bsp file
   1063 	Q2_LoadBSPFile(filename, offset, length);
   1064 
   1065 	//create an index from bsp planes to map planes
   1066 	//DPlanes2MapPlanes();
   1067 	//clear brush model numbers
   1068 	for (i = 0; i < MAX_MAPFILE_BRUSHES; i++)
   1069 		brushmodelnumbers[i] = -1;
   1070 
   1071 	nummapbrushsides = 0;
   1072 	num_entities = 0;
   1073 
   1074 	Q2_ParseEntities();
   1075 	//
   1076 	for (i = 0; i < num_entities; i++)
   1077 	{
   1078 		Q2_ParseBSPEntity(i);
   1079 	} //end for
   1080 
   1081 	//get the map mins and maxs from the world model
   1082 	ClearBounds(map_mins, map_maxs);
   1083 	for (i = 0; i < entities[0].numbrushes; i++)
   1084 	{
   1085 		if (mapbrushes[i].mins[0] > 4096)
   1086 			continue;	//no valid points
   1087 		AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
   1088 		AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
   1089 	} //end for
   1090 
   1091 	PrintMapInfo();
   1092 	//
   1093 	Q2_CreateMapTexinfo();
   1094 } //end of the function Q2_LoadMapFromBSP
   1095 
   1096 void Q2_ResetMapLoading(void)
   1097 {
   1098 	//reset for map loading from bsp
   1099 	memset(nodestack, 0, NODESTACKSIZE * sizeof(int));
   1100 	nodestackptr = NULL;
   1101 	nodestacksize = 0;
   1102 	memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int));
   1103 } //end of the function Q2_ResetMapLoading
   1104 
   1105 //End MAP loading from BSP file
   1106 #endif //ME
   1107 
   1108 //====================================================================
   1109 
   1110 /*
   1111 ================
   1112 TestExpandBrushes
   1113 
   1114 Expands all the brush planes and saves a new map out
   1115 ================
   1116 */
   1117 void TestExpandBrushes (void)
   1118 {
   1119 	FILE	*f;
   1120 	side_t	*s;
   1121 	int		i, j, bn;
   1122 	winding_t	*w;
   1123 	char	*name = "expanded.map";
   1124 	mapbrush_t	*brush;
   1125 	vec_t	dist;
   1126 
   1127 	Log_Print("writing %s\n", name);
   1128 	f = fopen (name, "wb");
   1129 	if (!f)
   1130 		Error ("Can't write %s\n", name);
   1131 
   1132 	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
   1133 
   1134 	for (bn=0 ; bn<nummapbrushes ; bn++)
   1135 	{
   1136 		brush = &mapbrushes[bn];
   1137 		fprintf (f, "{\n");
   1138 		for (i=0 ; i<brush->numsides ; i++)
   1139 		{
   1140 			s = brush->original_sides + i;
   1141 			dist = mapplanes[s->planenum].dist;
   1142 			for (j=0 ; j<3 ; j++)
   1143 				dist += fabs( 16 * mapplanes[s->planenum].normal[j] );
   1144 
   1145 			w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist);
   1146 
   1147 			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
   1148 			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
   1149 			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
   1150 
   1151 			fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
   1152 			FreeWinding (w);
   1153 		}
   1154 		fprintf (f, "}\n");
   1155 	}
   1156 	fprintf (f, "}\n");
   1157 
   1158 	fclose (f);
   1159 
   1160 	Error ("can't proceed after expanding brushes");
   1161 } //end of the function TestExpandBrushes
   1162