📄 map_q2.c
字号:
// brushes that will not be visible at all will never be
// used as bsp splitters
if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
{
c_clipbrushes++;
for (i=0 ; i<b->numsides ; i++)
b->original_sides[i].texinfo = TEXINFO_NODE;
}
//
// 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;
}
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;
}
AddBrushBevels(b);
nummapbrushes++;
mapent->numbrushes++;
}
/*
================
Q2_MoveBrushesToWorld
Takes all of the brushes from the current entity and
adds them to the world's brush list.
Used by func_group and func_areaportal
================
*/
void Q2_MoveBrushesToWorld (entity_t *mapent)
{
int newbrushes;
int worldbrushes;
mapbrush_t *temp;
int i;
// this is pretty gross, because the brushes are expected to be
// in linear order for each entity
newbrushes = mapent->numbrushes;
worldbrushes = entities[0].numbrushes;
temp = GetMemory(newbrushes*sizeof(mapbrush_t));
memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
#if 0 // let them keep their original brush numbers
for (i=0 ; i<newbrushes ; i++)
temp[i].entitynum = 0;
#endif
// make space to move the brushes (overlapped copy)
memmove (mapbrushes + worldbrushes + newbrushes,
mapbrushes + worldbrushes,
sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
// copy the new brushes down
memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
// fix up indexes
entities[0].numbrushes += newbrushes;
for (i=1 ; i<num_entities ; i++)
entities[i].firstbrush += newbrushes;
FreeMemory(temp);
mapent->numbrushes = 0;
}
/*
================
Q2_ParseMapEntity
================
*/
qboolean Q2_ParseMapEntity(script_t *script)
{
entity_t *mapent;
epair_t *e;
side_t *s;
int i, j;
int startbrush, startsides;
vec_t newdist;
mapbrush_t *b;
token_t token;
if (!PS_ReadToken(script, &token)) return false;
if (strcmp(token.string, "{") )
Error ("ParseEntity: { not found");
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 (!PS_ReadToken(script, &token))
{
Error("ParseEntity: EOF without closing brace");
} //end if
if (!strcmp(token.string, "}")) break;
if (!strcmp(token.string, "{"))
{
Q2_ParseBrush(script, mapent);
} //end if
else
{
PS_UnreadLastToken(script);
e = ParseEpair(script);
e->next = mapent->epairs;
mapent->epairs = e;
} //end else
} while(1);
GetVectorForKey(mapent, "origin", mapent->origin);
//
// 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);
s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
&side_brushtextures[s-brushsides], mapent->origin);
}
MakeBrushWindings (b);
}
}
// group entities are just for editor convenience
// toss all brushes into the world entity
if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
{
Q2_MoveBrushesToWorld (mapent);
mapent->numbrushes = 0;
return true;
}
// areaportal entities move their brushes, but don't eliminate
// the entity
if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
{
char str[128];
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"
sprintf (str, "%i", c_areaportals);
SetKeyValue (mapent, "style", str);
Q2_MoveBrushesToWorld (mapent);
return true;
}
return true;
}
//===================================================================
/*
================
LoadMapFile
================
*/
void Q2_LoadMapFile(char *filename)
{
int i;
script_t *script;
Log_Print("-- Q2_LoadMapFile --\n");
#ifdef ME
//loaded map type
loadedmaptype = MAPTYPE_QUAKE2;
//reset the map loading
ResetMapLoading();
#endif //ME
script = LoadScriptFile(filename);
if (!script)
{
Log_Print("couldn't open %s\n", filename);
return;
} //end if
//white spaces and escape characters inside a string are not allowed
SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
SCFL_NOSTRINGESCAPECHARS |
SCFL_PRIMITIVE);
nummapbrushsides = 0;
num_entities = 0;
while (Q2_ParseMapEntity(script))
{
}
ClearBounds (map_mins, map_maxs);
for (i=0 ; i<entities[0].numbrushes ; i++)
{
if (mapbrushes[i].mins[0] > 4096)
continue; // no valid points
AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
} //end for
PrintMapInfo();
//free the script
FreeScript(script);
// TestExpandBrushes ();
//
Q2_CreateMapTexinfo();
} //end of the function Q2_LoadMapFile
#ifdef ME //Begin MAP loading from BSP file
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q2_SetLeafBrushesModelNumbers(int leafnum, int modelnum)
{
int i, brushnum;
dleaf_t *leaf;
leaf = &dleafs[leafnum];
for (i = 0; i < leaf->numleafbrushes; i++)
{
brushnum = dleafbrushes[leaf->firstleafbrush + i];
brushmodelnumbers[brushnum] = modelnum;
dbrushleafnums[brushnum] = leafnum;
} //end for
} //end of the function Q2_SetLeafBrushesModelNumbers
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q2_InitNodeStack(void)
{
nodestackptr = nodestack;
nodestacksize = 0;
} //end of the function Q2_InitNodeStack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q2_PushNodeStack(int num)
{
*nodestackptr = num;
nodestackptr++;
nodestacksize++;
//
if (nodestackptr >= &nodestack[NODESTACKSIZE])
{
Error("Q2_PushNodeStack: stack overflow\n");
} //end if
} //end of the function Q2_PushNodeStack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Q2_PopNodeStack(void)
{
//if the stack is empty
if (nodestackptr <= nodestack) return -1;
//decrease stack pointer
nodestackptr--;
nodestacksize--;
//return the top value from the stack
return *nodestackptr;
} //end of the function Q2_PopNodeStack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q2_SetBrushModelNumbers(entity_t *mapent)
{
int n, pn;
int leafnum;
//
Q2_InitNodeStack();
//head node (root) of the bsp tree
n = 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
Q2_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum);
//walk back into the tree to find a second child to continue with
for (pn = Q2_PopNodeStack(); pn >= 0; n = pn, pn = Q2_PopNodeStack())
{
//if we took the first child at the parent node
if (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
Q2_PushNodeStack(pn);
//we proceed with the second child of the parent node
n = dnodes[pn].children[1];
} //end if
} //end if
else
{
//push the current node onto the stack
Q2_PushNodeStack(n);
//walk forward into the tree to the first child
n = dnodes[n].children[0];
} //end else
} while(pn >= 0);
} //end of the function Q2_SetBrushModelNumbers
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q2_BSPBrushToMapBrush(dbrush_t *bspbrush, entity_t *mapent)
{
mapbrush_t *b;
int i, k, n;
side_t *side, *s2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -