This program 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.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
#include "quakedef.h"
-byte mod_novis[MAX_MAP_LEAFS/8];
+byte mod_novis[(MAX_MAP_LEAFS + 7)/ 8];
qboolean hlbsp; // LordHavoc: true if it is a HalfLife BSP file (version 30)
-cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", true};
-cvar_t halflifebsp = {"halflifebsp", "0"};
-cvar_t r_novis = {"r_novis", "0"};
+cvar_t gl_subdivide_size = {CVAR_SAVE, "gl_subdivide_size", "128"};
+cvar_t halflifebsp = {0, "halflifebsp", "0"};
+cvar_t r_novis = {0, "r_novis", "0"};
/*
===============
Cvar_RegisterVariable (&gl_subdivide_size);
Cvar_RegisterVariable (&halflifebsp);
Cvar_RegisterVariable (&r_novis);
- memset (mod_novis, 0xff, sizeof(mod_novis));
+ memset(mod_novis, 0xff, sizeof(mod_novis));
+}
+
+void Mod_Brush_SERAddEntity(void)
+{
+ R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL);
}
/*
mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
{
mnode_t *node;
-
+
// if (!model || !model->nodes)
// Sys_Error ("Mod_PointInLeaf: bad model");
mnode_t *node;
float d;
mplane_t *plane;
-
+
if (!model || !model->nodes)
Sys_Error ("Mod_PointInLeaf: bad model");
else
node = node->children[1];
}
-
+
return NULL; // never reached
}
*/
Mod_DecompressVis
===================
*/
-byte *Mod_DecompressVis (byte *in, model_t *model)
+static byte *Mod_DecompressVis (byte *in, model_t *model)
{
static byte decompressed[MAX_MAP_LEAFS/8];
int c;
*out++ = 0xff;
row--;
}
- return decompressed;
+ return decompressed;
}
*/
*out++ = *in++;
continue;
}
-
+
c = in[1];
in += 2;
while (c)
c--;
}
} while (out - decompressed < row);
-
+
return decompressed;
}
Mod_LoadTextures
=================
*/
-void Mod_LoadTextures (lump_t *l)
+static void Mod_LoadTextures (lump_t *l)
{
int i, j, k, num, max, altmax, mtwidth, mtheight, *dofs;
miptex_t *dmiptex;
m = (dmiptexlump_t *)(mod_base + l->fileofs);
m->nummiptex = LittleLong (m->nummiptex);
-
+
loadmodel->numtextures = m->nummiptex;
loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), va("%s texture headers", loadname));
Host_Error ("Texture %s is corrupt or incomplete\n", dmiptex->name);
mtdata = (byte *)dmiptex + j;
}
-
+
if ((mtwidth & 15) || (mtheight & 15))
Host_Error ("Texture %s is not 16 aligned", dmiptex->name);
// LordHavoc: rewriting the map texture loader for GLQuake
tx = Hunk_AllocName (sizeof(texture_t), va("%s textures", loadname));
+ memset(tx, 0, sizeof(texture_t));
+ tx->anim_total = 0;
+ tx->alternate_anims = NULL;
loadmodel->textures[i] = tx;
// LordHavoc: force all names to lowercase and make sure they are terminated while copying
// find the number of frames in the animation
memset (anims, 0, sizeof(anims));
memset (altanims, 0, sizeof(altanims));
+ max = altmax = 0;
- max = tx->name[1];
- altmax = 0;
- if (max >= '0' && max <= '9')
- {
- max -= '0';
- altmax = 0;
- anims[max] = tx;
- max++;
- }
- else if (max >= 'a' && max <= 'j')
- {
- altmax = max - 'a';
- max = 0;
- altanims[altmax] = tx;
- altmax++;
- }
- else
- Host_Error ("Bad animating texture %s", tx->name);
-
- for (j = i + 1;j < m->nummiptex;j++)
+ for (j = i;j < m->nummiptex;j++)
{
tx2 = loadmodel->textures[j];
- if (!tx2 || tx2->name[0] != '+')
- continue;
- if (strcmp (tx2->name+2, tx->name+2))
+ if (!tx2 || tx2->name[0] != '+' || strcmp (tx2->name+2, tx->name+2))
continue;
num = tx2->name[1];
if (num >= '0' && num <= '9')
- {
- num -= '0';
- anims[num] = tx2;
- if (num+1 > max)
- max = num + 1;
- }
+ anims[num - '0'] = tx2;
else if (num >= 'a' && num <= 'j')
- {
- num = num - 'a';
- altanims[num] = tx2;
- if (num+1 > altmax)
- altmax = num+1;
- }
+ altanims[num - 'a'] = tx2;
else
Host_Error ("Bad animating texture %s", tx->name);
}
+ for (j = 0;j < 10;j++)
+ {
+ if (anims[j] != NULL)
+ max = j + 1;
+ if (altanims[j] != NULL)
+ altmax = j + 1;
+ }
+
// link them all together
for (j = 0;j < max;j++)
{
if (!tx2)
Host_Error ("Missing frame %i of %s", j, tx->name);
tx2->anim_total = max;
- if (altmax)
- tx2->alternate_anims = altanims[0];
+ tx2->alternate_anims = altanims[0]; // NULL if there is no alternate
for (k = 0;k < 10;k++)
- tx2->anim_frames[k] = anims[j];
+ tx2->anim_frames[k] = anims[k];
}
+
for (j = 0;j < altmax;j++)
{
tx2 = altanims[j];
if (!tx2)
Host_Error ("Missing frame %i of %s", j, tx->name);
tx2->anim_total = altmax;
- if (max)
- tx2->alternate_anims = anims[0];
+ tx2->alternate_anims = anims[0]; // NULL if there is no alternate
for (k = 0;k < 10;k++)
- tx2->anim_frames[k] = altanims[j];
+ tx2->anim_frames[k] = altanims[k];
}
}
}
Mod_LoadLighting
=================
*/
-void Mod_LoadLighting (lump_t *l)
+static void Mod_LoadLighting (lump_t *l)
{
int i;
byte *in, *out, *data;
Mod_LoadVisibility
=================
*/
-void Mod_LoadVisibility (lump_t *l)
+static void Mod_LoadVisibility (lump_t *l)
{
if (!l->filelen)
{
Mod_LoadEntities
=================
*/
-void Mod_LoadEntities (lump_t *l)
+static void Mod_LoadEntities (lump_t *l)
{
if (!l->filelen)
{
Mod_LoadVertexes
=================
*/
-void Mod_LoadVertexes (lump_t *l)
+static void Mod_LoadVertexes (lump_t *l)
{
dvertex_t *in;
mvertex_t *out;
Mod_LoadSubmodels
=================
*/
-void Mod_LoadSubmodels (lump_t *l)
+static void Mod_LoadSubmodels (lump_t *l)
{
dmodel_t *in;
dmodel_t *out;
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
- { // spread the mins / maxs by a pixel
+ {
+ // spread the mins / maxs by a pixel
out->mins[j] = LittleFloat (in->mins[j]) - 1;
out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
out->origin[j] = LittleFloat (in->origin[j]);
Mod_LoadEdges
=================
*/
-void Mod_LoadEdges (lump_t *l)
+static void Mod_LoadEdges (lump_t *l)
{
dedge_t *in;
medge_t *out;
Mod_LoadTexinfo
=================
*/
-void Mod_LoadTexinfo (lump_t *l)
+static void Mod_LoadTexinfo (lump_t *l)
{
texinfo_t *in;
mtexinfo_t *out;
miptex = LittleLong (in->miptex);
out->flags = LittleLong (in->flags);
-
+
if (!loadmodel->textures)
{
out->texture = &r_notexture_mip; // checkerboard texture
Fills in s->texturemins[] and s->extents[]
================
*/
-void CalcSurfaceExtents (msurface_t *s)
+static void CalcSurfaceExtents (msurface_t *s)
{
float mins[2], maxs[2], val;
int i,j, e;
maxs[0] = maxs[1] = -99999;
tex = s->texinfo;
-
+
for (i=0 ; i<s->numedges ; i++)
{
e = loadmodel->surfedges[s->firstedge+i];
Mod_LoadFaces
=================
*/
-void Mod_LoadFaces (lump_t *l)
+static void Mod_LoadFaces (lump_t *l)
{
dface_t *in;
msurface_t *out;
for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
{
out->firstedge = LittleLong(in->firstedge);
- out->numedges = LittleShort(in->numedges);
+ out->numedges = LittleShort(in->numedges);
out->flags = 0;
planenum = LittleShort(in->planenum);
side = LittleShort(in->side);
if (side)
- out->flags |= SURF_PLANEBACK;
+ out->flags |= SURF_PLANEBACK;
out->plane = loadmodel->planes + planenum;
out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
CalcSurfaceExtents (out);
-
+
// lighting info
for (i=0 ; i<MAXLIGHTMAPS ; i++)
else if (hlbsp) // LordHavoc: HalfLife map (bsp version 30)
out->samples = loadmodel->lightdata + i;
else // LordHavoc: white lighting (bsp version 29)
- out->samples = loadmodel->lightdata + (i * 3);
-
+ out->samples = loadmodel->lightdata + (i * 3);
+
// set the drawing flags flag
-
+
// if (!strncmp(out->texinfo->texture->name,"sky",3)) // sky
// LordHavoc: faster check
if ((out->texinfo->texture->name[0] == 's' || out->texinfo->texture->name[0] == 'S')
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
-
+
// if (!strncmp(out->texinfo->texture->name,"*",1)) // turbulent
if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check
{
if (!strncmp(out->texinfo->texture->name,"*lava",5)
|| !strncmp(out->texinfo->texture->name,"*teleport",9)
|| !strncmp(out->texinfo->texture->name,"*rift",5)) // Scourge of Armagon texture
- out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
+ out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID);
for (i=0 ; i<2 ; i++)
{
out->extents[i] = 16384;
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
-
- out->flags |= SURF_CLIPSOLID;
+
+ if (!out->texinfo->texture->transparent)
+ out->flags |= SURF_CLIPSOLID;
}
}
Mod_SetParent
=================
*/
-void Mod_SetParent (mnode_t *node, mnode_t *parent)
+static void Mod_SetParent (mnode_t *node, mnode_t *parent)
{
node->parent = parent;
if (node->contents < 0)
Mod_LoadNodes
=================
*/
-void Mod_LoadNodes (lump_t *l)
+static void Mod_LoadNodes (lump_t *l)
{
int i, j, count, p;
dnode_t *in;
for ( i=0 ; i<count ; i++, in++, out++)
{
-// for (j=0 ; j<3 ; j++)
-// {
-// out->mins[j] = LittleShort (in->mins[j]);
-// out->maxs[j] = LittleShort (in->maxs[j]);
-// }
+ for (j=0 ; j<3 ; j++)
+ {
+ out->mins[j] = LittleShort (in->mins[j]);
+ out->maxs[j] = LittleShort (in->maxs[j]);
+ }
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
Mod_LoadLeafs
=================
*/
-void Mod_LoadLeafs (lump_t *l)
+static void Mod_LoadLeafs (lump_t *l)
{
dleaf_t *in;
mleaf_t *out;
out->firstmarksurface = loadmodel->marksurfaces +
LittleShort(in->firstmarksurface);
out->nummarksurfaces = LittleShort(in->nummarksurfaces);
-
+
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
Mod_LoadClipnodes
=================
*/
-void Mod_LoadClipnodes (lump_t *l)
+static void Mod_LoadClipnodes (lump_t *l)
{
dclipnode_t *in, *out;
int i, count;
Duplicate the drawing hull structure as a clipping hull
=================
*/
-void Mod_MakeHull0 (void)
+static void Mod_MakeHull0 (void)
{
mnode_t *in;
dclipnode_t *out;
hull_t *hull;
hull = &loadmodel->hulls[0];
-
+
in = loadmodel->nodes;
count = loadmodel->numnodes;
out = Hunk_AllocName ( count*sizeof(*out), va("%s hull0", loadname));
Mod_LoadMarksurfaces
=================
*/
-void Mod_LoadMarksurfaces (lump_t *l)
-{
+static void Mod_LoadMarksurfaces (lump_t *l)
+{
int i, j, count;
short *in;
msurface_t **out;
-
+
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
Mod_LoadSurfedges
=================
*/
-void Mod_LoadSurfedges (lump_t *l)
-{
+static void Mod_LoadSurfedges (lump_t *l)
+{
int i, count;
int *in, *out;
Mod_LoadPlanes
=================
*/
-void Mod_LoadPlanes (lump_t *l)
+static void Mod_LoadPlanes (lump_t *l)
{
int i, j;
mplane_t *out;
dplane_t *in;
int count;
-
+
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
NewWinding
==================
*/
-winding_t *NewWinding (int points)
+static winding_t *NewWinding (int points)
{
winding_t *w;
int size;
Host_Error("NewWinding: too many points\n");
size = (int)((winding_t *)0)->points[points];
- w = malloc (size);
+ w = qmalloc (size);
memset (w, 0, size);
return w;
}
-void FreeWinding (winding_t *w)
+static void FreeWinding (winding_t *w)
{
- free (w);
+ qfree (w);
}
/*
BaseWindingForPlane
=================
*/
-winding_t *BaseWindingForPlane (mplane_t *p)
+static winding_t *BaseWindingForPlane (mplane_t *p)
{
vec3_t org, vright, vup;
winding_t *w;
it will be clipped away.
==================
*/
-winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon)
+static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon)
{
vec_t dists[MAX_POINTS_ON_WINDING + 1];
int sides[MAX_POINTS_ON_WINDING + 1];
new windings will be created.
==================
*/
-void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, winding_t **back)
+static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, winding_t **back)
{
vec_t dists[MAX_POINTS_ON_WINDING + 1];
int sides[MAX_POINTS_ON_WINDING + 1];
AllocPortal
===========
*/
-portal_t *AllocPortal (void)
+static portal_t *AllocPortal (void)
{
portal_t *p;
- p = malloc(sizeof(portal_t));
+ p = qmalloc(sizeof(portal_t));
memset(p, 0, sizeof(portal_t));
p->chain = portalchain;
portalchain = p;
return p;
}
-void Mod_FinalizePortals(void)
+static void Mod_RecursiveRecalcNodeBBox(mnode_t *node)
+{
+ // calculate children first
+ if (node->children[0]->contents >= 0)
+ Mod_RecursiveRecalcNodeBBox(node->children[0]);
+ if (node->children[1]->contents >= 0)
+ Mod_RecursiveRecalcNodeBBox(node->children[1]);
+
+ // make combined bounding box from children
+ node->mins[0] = min(node->children[0]->mins[0], node->children[1]->mins[0]);
+ node->mins[1] = min(node->children[0]->mins[1], node->children[1]->mins[1]);
+ node->mins[2] = min(node->children[0]->mins[2], node->children[1]->mins[2]);
+ node->maxs[0] = max(node->children[0]->maxs[0], node->children[1]->maxs[0]);
+ node->maxs[1] = max(node->children[0]->maxs[1], node->children[1]->maxs[1]);
+ node->maxs[2] = max(node->children[0]->maxs[2], node->children[1]->maxs[2]);
+}
+
+static void Mod_FinalizePortals(void)
{
int i, j, numportals, numpoints;
portal_t *p, *pnext;
p = p->chain;
}
+// Hunk_Check();
+
+ Mod_RecursiveRecalcNodeBBox(loadmodel->nodes);
+
+// Hunk_Check();
+
// tally up portal and point counts
p = portalchain;
numportals = 0;
numpoints = 0;
while(p)
{
- if (p->winding && p->nodes[0] != p->nodes[1] && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID)
+ // note: this check must match the one below or it will usually corrupt the hunk
+ // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
+ if (p->winding && p->nodes[0] != p->nodes[1]
+ && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
+ && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
{
numportals += 2;
numpoints += p->winding->numpoints * 2;
if (p->winding)
{
+ // note: this check must match the one below or it will usually corrupt the hunk
// the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
- if (p->nodes[0] != p->nodes[1] && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID)
+ if (p->nodes[0] != p->nodes[1]
+ && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
+ && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
{
// first make the back to front portal (forward portal)
portal->points = point;
}
FreeWinding(p->winding);
}
- free(p);
+ qfree(p);
p = pnext;
}
}
AddPortalToNodes
=============
*/
-void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
+static void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
{
if (!front)
Host_Error ("AddPortalToNodes: NULL front node");
RemovePortalFromNode
=============
*/
-void RemovePortalFromNodes(portal_t *portal)
+static void RemovePortalFromNodes(portal_t *portal)
{
int i;
mnode_t *node;
}
else if (portal->nodes[1] == node)
{
- *portalpointer = portal->next[1];
+ *portalpointer = portal->next[1];
portal->nodes[1] = NULL;
}
else
}
}
-void Mod_RecursiveNodePortals (mnode_t *node)
+static void Mod_RecursiveNodePortals (mnode_t *node)
{
int side;
mnode_t *front, *back, *other_node;
}
*/
-void Mod_MakePortals(void)
+static void Mod_MakePortals(void)
{
// Con_Printf("building portals for %s\n", loadmodel->name);
int i, j;
dheader_t *header;
dmodel_t *bm;
-
+
loadmodel->type = mod_brush;
-
+
header = (dheader_t *)buffer;
i = LittleLong (header->version);
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
// load into heap
-
+
// LordHavoc: had to move entity loading above everything to allow parsing various settings from worldspawn
Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
Mod_MakeHull0 ();
Mod_MakePortals();
-
+
mod->numframes = 2; // regular and alternate animation
-
+
//
// set up the submodels (FIXME: this is confusing)
//
for (i = 0;i < mod->numsubmodels;i++)
{
+ int k, l;
+ float dist, modelyawradius, modelradius, *vec;
+ msurface_t *surf;
+
+ mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
+ mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
+ modelyawradius = 0;
+ modelradius = 0;
+
bm = &mod->submodels[i];
mod->hulls[0].firstclipnode = bm->headnode[0];
mod->hulls[j].firstclipnode = bm->headnode[j];
mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
}
-
+
mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces;
-
- VectorCopy (bm->maxs, mod->maxs);
- VectorCopy (bm->mins, mod->mins);
- mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
+ // LordHavoc: calculate bmodel bounding box rather than trusting what it says
+ for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
+ {
+ for (k = 0;k < surf->numedges;k++)
+ {
+ l = mod->surfedges[k + surf->firstedge];
+ if (l > 0)
+ vec = mod->vertexes[mod->edges[l].v[0]].position;
+ else
+ vec = mod->vertexes[mod->edges[-l].v[1]].position;
+ if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0];
+ if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1];
+ if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2];
+ if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0];
+ if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1];
+ if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2];
+ dist = vec[0]*vec[0]+vec[1]*vec[1];
+ if (modelyawradius < dist)
+ modelyawradius = dist;
+ dist += vec[2]*vec[2];
+ if (modelradius < dist)
+ modelradius = dist;
+ }
+ }
+ modelyawradius = sqrt(modelyawradius);
+ modelradius = sqrt(modelradius);
+ mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius);
+ mod->yawmins[2] = mod->normalmins[2];
+ mod->yawmaxs[2] = mod->normalmaxs[2];
+ mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
+ mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
+// mod->modelradius = modelradius;
+
+// VectorCopy (bm->maxs, mod->maxs);
+// VectorCopy (bm->mins, mod->mins);
+
+// mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
mod->numleafs = bm->visleafs;
+ mod->SERAddEntity = Mod_Brush_SERAddEntity;
+ mod->DrawEarly = R_DrawBrushModel;
+ mod->DrawLate = NULL;
+ mod->DrawShadow = NULL;
+
if (isworldmodel && i < (mod->numsubmodels - 1)) // LordHavoc: only register submodels if it is the world (prevents bsp models from replacing world submodels)
{ // duplicate the basic information
char name[10];