Map Sin
Map Sin
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
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
===========================================================================
*/
//-----------------------------------------------------------------------------
//
// $Logfile:: /MissionPack/code/bspc/map_sin.c $
#include "qbsp.h"
#include "l_bsp_sin.h"
#include "aas_map.h" //AAS_CreateMapBrushes
//====================================================================
/*
===========
Sin_BrushContents
===========
*/
s = &b->original_sides[0];
contents = s->contents;
#ifdef SIN
if (contents & CONTENTS_FENCE)
{
// contents |= CONTENTS_TRANSLUCENT;
contents |= CONTENTS_DETAIL;
contents |= CONTENTS_DUMMYFENCE;
contents &= ~CONTENTS_SOLID;
contents &= ~CONTENTS_FENCE;
contents |= CONTENTS_WINDOW;
}
#endif
return contents;
} //*/
//============================================================================
/*
=================
ParseBrush
=================
*/
void ParseBrush (entity_t *mapent)
{
mapbrush_t *b;
int i,j, k;
int mt;
side_t *side, *s2;
int planenum;
brush_texture_t td;
#ifdef SIN
textureref_t newref;
#endif
int planepts[3][3];
if (nummapbrushes == MAX_MAP_BRUSHES)
Error ("nummapbrushes == MAX_MAP_BRUSHES");
b = &mapbrushes[nummapbrushes];
b->original_sides = &brushsides[nummapbrushsides];
b->entitynum = num_entities-1;
b->brushnum = nummapbrushes - mapent->firstbrush;
do
{
if (!GetToken (true))
break;
if (!strcmp (token, "}") )
break;
if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
Error ("MAX_MAP_BRUSHSIDES");
side = &brushsides[nummapbrushsides];
//
// read the texturedef
//
GetToken (false);
strcpy (td.name, token);
GetToken (false);
td.shift[0] = atoi(token);
GetToken (false);
td.shift[1] = atoi(token);
GetToken (false);
#ifdef SIN
td.rotate = atof(token);
#else
td.rotate = atoi(token);
#endif
GetToken (false);
td.scale[0] = atof(token);
GetToken (false);
td.scale[1] = atof(token);
ParseSurfaceInfo( &newref );
MergeRefs( &bsp_textureref[mt], &newref, &td.tref );
side->contents = td.tref.contents;
side->surf = td.tref.flags;
#else
td.flags = textureref[mt].flags;
if (TokenAvailable())
{
GetToken (false);
side->contents = atoi(token);
GetToken (false);
side->surf = td.flags = atoi(token);
GetToken (false);
td.value = atoi(token);
}
#endif
//
// find the plane number
//
planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
if (planenum == -1)
{
printf ("Entity %i, Brush %i: plane with no normal\n"
, b->entitynum, b->brushnum);
continue;
}
//
// see if the plane has been used already
//
for (k=0 ; k<b->numsides ; k++)
//
// keep this side
//
#endif
nummapbrushsides++;
b->numsides++;
} while (1);
//
// origin brushes are removed, but they set
// the rotation origin for the rest of the brushes
// in the entity. After the entire entity is parsed,
// the planenums and texinfos will be adjusted for
// the origin brush
//
if (b->contents & CONTENTS_ORIGIN)
{
char string[32];
vec3_t origin;
if (num_entities == 1)
{
Error ("Entity %i, Brush %i: origin brushes not allowed in world"
, b->entitynum, b->brushnum);
return;
}
AddBrushBevels (b);
nummapbrushes++;
mapent->numbrushes++;
} //*/
/*
================
MoveBrushesToWorld
newbrushes = mapent->numbrushes;
worldbrushes = entities[0].numbrushes;
temp = malloc(newbrushes*sizeof(mapbrush_t));
memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
// fix up indexes
entities[0].numbrushes += newbrushes;
for (i=1 ; i<num_entities ; i++)
entities[i].firstbrush += newbrushes;
free (temp);
/*
================
ParseMapEntity
================
*/
qboolean Sin_ParseMapEntity (void)
{
entity_t *mapent;
epair_t *e;
side_t *s;
int i, j;
int startbrush, startsides;
vec_t newdist;
mapbrush_t *b;
if (!GetToken (true))
return false;
if (num_entities == MAX_MAP_ENTITIES)
Error ("num_entities == MAX_MAP_ENTITIES");
startbrush = nummapbrushes;
startsides = nummapbrushsides;
mapent = &entities[num_entities];
num_entities++;
memset (mapent, 0, sizeof(*mapent));
mapent->firstbrush = nummapbrushes;
mapent->numbrushes = 0;
// mapent->portalareas[0] = -1;
// mapent->portalareas[1] = -1;
do
{
if (!GetToken (true))
Error ("ParseEntity: EOF without closing brace");
if (!strcmp (token, "}") )
break;
if (!strcmp (token, "{") )
ParseBrush (mapent);
else
{
e = ParseEpair ();
#ifdef SIN
//HACK HACK HACK
// MED Gotta do this here
if ( !stricmp(e->key, "surfacefile") )
{
#ifdef SIN
if (!(strlen(ValueForKey(mapent, "origin"))) && ((num_entities-1) != 0))
{
mapbrush_t *brush;
vec3_t origin;
char string[32];
vec3_t mins, maxs;
int start, end;
// Calculate bounds
start = mapent->firstbrush;
end = start + mapent->numbrushes;
ClearBounds (mins, maxs);
#ifdef SIN
if (
//
// if there was an origin brush, offset all of the planes and texinfo
//
if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
{
for (i=0 ; i<mapent->numbrushes ; i++)
{
b = &mapbrushes[mapent->firstbrush + i];
for (j=0 ; j<b->numsides ; j++)
{
s = &b->original_sides[j];
newdist = mapplanes[s->planenum].dist -
DotProduct (mapplanes[s->planenum].normal, mapent->origin);
s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
#ifdef SIN
s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
&side_brushtextures[s-brushsides], mapent->origin, &side_newrefs[s-brushsides]);
//
// save off lightinfo
//
s->lightinfo = LightinfoForBrushTexture ( &side_brushtextures[s-brushsides] );
#else
s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
&side_brushtextures[s-brushsides], mapent->origin);
#endif
}
MakeBrushWindings (b);
}
}
if (mapent->numbrushes != 1)
Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
b = &mapbrushes[nummapbrushes-1];
b->contents = CONTENTS_AREAPORTAL;
c_areaportals++;
mapent->areaportalnum = c_areaportals;
// set the portal number as "style"
return true;
} //end of the function Sin_ParseMapEntity */
//===================================================================
/*
================
LoadMapFile
================
*/
void Sin_LoadMapFile (char *filename)
{
int i;
#ifdef SIN
int num_detailsides=0;
int num_detailbrushes=0;
int num_worldsides=0;
int num_worldbrushes=0;
int j,k;
#endif
LoadScriptFile (filename);
nummapbrushsides = 0;
num_entities = 0;
leaf = &sin_dleafs[leafnum];
for (i = 0; i < leaf->numleafbrushes; i++)
{
brushnum = sin_dleafbrushes[leaf->firstleafbrush + i];
brushmodelnumbers[brushnum] = modelnum;
dbrushleafnums[brushnum] = leafnum;
} //end for
} //end of the function Sin_SetLeafBrushesModelNumbers
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Sin_InitNodeStack(void)
{
nodestackptr = nodestack;
nodestacksize = 0;
} //end of the function Sin_InitNodeStack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Sin_PushNodeStack(int num)
{
*nodestackptr = num;
nodestackptr++;
nodestacksize++;
//
if (nodestackptr >= &nodestack[NODESTACKSIZE])
{
Error("Sin_PushNodeStack: stack overflow\n");
} //end if
//
Sin_InitNodeStack();
//head node (root) of the bsp tree
n = sin_dmodels[mapent->modelnum].headnode;
pn = 0;
do
{
//if we are in a leaf (negative node number)
if (n < 0)
{
//number of the leaf
leafnum = (-n) - 1;
//set the brush numbers
Sin_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum);
//walk back into the tree to find a second child to continue with
for (pn = Sin_PopNodeStack(); pn >= 0; n = pn, pn = Sin_PopNodeStack())
{
//if we took the first child at the parent node
if (sin_dnodes[pn].children[0] == n) break;
} //end for
//if the stack wasn't empty (if not processed whole tree)
if (pn >= 0)
{
//push the parent node again
Sin_PushNodeStack(pn);
b = &mapbrushes[nummapbrushes];
b->original_sides = &brushsides[nummapbrushsides];
b->entitynum = mapent-entities;
b->brushnum = nummapbrushes - mapent->firstbrush;
b->leafnum = dbrushleafnums[bspbrush - sin_dbrushes];
//
// keep this side
//
//ME: reset pointer to side, why? hell I dunno (pointer is set above already)
nummapbrushsides++;
b->numsides++;
} //end for
if (BrushExists(b))
{
c_squattbrushes++;
b->numsides = 0;
return;
} //end if
//
// origin brushes are removed, but they set
// the rotation origin for the rest of the brushes
// in the entity. After the entire entity is parsed,
// the planenums and texinfos will be adjusted for
// the origin brush
//
//ME: not needed because the entities in the BSP file already
// have an origin set
// if (b->contents & CONTENTS_ORIGIN)
// {
// char string[32];
// vec3_t origin;
//
// if (num_entities == 1)
// {
// Error ("Entity %i, Brush %i: origin brushes not allowed in world"
// , b->entitynum, b->brushnum);
// return;
// }
//
// VectorAdd (b->mins, b->maxs, origin);
// VectorScale (origin, 0.5, origin);
//
// sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
// SetKeyValue (&entities[b->entitynum], "origin", string);
//
// VectorCopy (origin, entities[b->entitynum].origin);
//
// // don't keep this brush
// b->numsides = 0;
//
// return;
// }
nummapbrushes++;
mapent->numbrushes++;
//give all the brushes that belong to this entity the number of the
//BSP model used by this entity
Sin_SetBrushModelNumbers(mapent);
//now parse all the brushes with the correct mapent->modelnum
for (i = 0; i < sin_numbrushes; i++)
{
if (brushmodelnumbers[i] == mapent->modelnum)
{
testnum++;
Sin_BSPBrushToMapBrush(&sin_dbrushes[i], mapent);
} //end if
} //end for
} //end of the function Sin_ParseBSPBrushes
//===========================================================================
//===========================================================================
qboolean Sin_ParseBSPEntity(int entnum)
{
entity_t *mapent;
char *model;
int startbrush, startsides;
startbrush = nummapbrushes;
startsides = nummapbrushsides;
mapent = &entities[entnum];//num_entities];
mapent->firstbrush = nummapbrushes;
mapent->numbrushes = 0;
mapent->modelnum = -1; //-1 = no model
nummapbrushsides = 0;
num_entities = 0;
Sin_ParseEntities();
//
for (i = 0; i < num_entities; i++)
{
Sin_ParseBSPEntity(i);
} //end for
//get the map mins and maxs from the world model
void Sin_ResetMapLoading(void)
{
//reset for map loading from bsp
memset(nodestack, 0, NODESTACKSIZE * sizeof(int));
nodestackptr = NULL;
nodestacksize = 0;
memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int));
} //end of the function Sin_ResetMapLoading
#endif //ME