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.
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 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));
}
// Sys_Error ("Mod_PointInLeaf: bad model");
node = model->nodes;
- if (node->contents < 0)
- return (mleaf_t *)node;
- while (1)
- {
+ do
node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist];
- if (node->contents < 0)
- return (mleaf_t *)node;
- }
-
- return NULL; // never reached
+ while (node->contents == 0);
+
+ return (mleaf_t *)node;
}
/*
mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
else
node = node->children[1];
}
-
+
return NULL; // never reached
}
*/
byte *out;
int row;
- row = (model->numleafs+7)>>3;
+ row = (model->numleafs+7)>>3;
out = decompressed;
+ /*
if (!in)
{ // no vis info, so make all visible
while (row)
}
return decompressed;
}
+ */
do
{
byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
{
- if (leaf == model->leafs)
+ if (r_novis.value || leaf == model->leafs || leaf->compressed_vis == NULL)
return mod_novis;
return Mod_DecompressVis (leaf->compressed_vis, model);
}
-extern byte *mod_base;
-
-extern cvar_t r_fullbrights;
-
rtexture_t *r_notexture;
texture_t r_notexture_mip;
-void Mod_SetupNoTexture()
+void Mod_SetupNoTexture(void)
{
int x, y;
byte pix[16][16][4];
for (;j < 16;j++)
tx->name[j] = 0;
+ if (!tx->name[0])
+ {
+ Con_Printf("warning: unnamed texture in %s\n", loadname);
+ sprintf(tx->name, "unnamed%i", i);
+ }
+
tx->transparent = false;
data = loadimagepixels(tx->name, false, 0, 0);
if (data)
memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
}
-void CL_ParseEntityLump(char *entdata);
-
-extern qboolean isworldmodel;
-
/*
=================
Mod_LoadEntities
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]);
void GL_SubdivideSurface (msurface_t *fa);
-extern char skyname[];
-
/*
=================
Mod_LoadFaces
out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
CalcSurfaceExtents (out);
-
+
// lighting info
for (i=0 ; i<MAXLIGHTMAPS ; i++)
&& (out->texinfo->texture->name[2] == 'y' || out->texinfo->texture->name[2] == 'Y'))
{
// LordHavoc: for consistency reasons, mark sky as fullbright and solid as well
- out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
+ out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID);
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
-
+
+ out->flags |= SURF_CLIPSOLID;
}
}
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
-// out->efrags = NULL;
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
mplane_t *out;
dplane_t *in;
int count;
- int bits;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
for ( i=0 ; i<count ; i++, in++, out++)
{
- bits = 0;
for (j=0 ; j<3 ; j++)
- {
out->normal[j] = LittleFloat (in->normal[j]);
-// if (out->normal[j] < 0)
-// bits |= 1<<j;
- }
out->dist = LittleFloat (in->dist);
- out->type = LittleLong (in->type);
-// out->signbits = bits;
- BoxOnPlaneSideClassify(out);
+ // LordHavoc: recalculated by PlaneClassify, FIXME: validate type and report error if type does not match normal?
+// out->type = LittleLong (in->type);
+ PlaneClassify(out);
}
}
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)
{
- free (w);
+ qfree (w);
}
/*
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 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]);
+}
+
+void Mod_FinalizePortals(void)
{
int i, j, numportals, numpoints;
portal_t *p, *pnext;
mportal_t *portal;
mvertex_t *point;
+ mleaf_t *leaf, *endleaf;
+ winding_t *w;
+
+ // recalculate bounding boxes for all leafs (because qbsp is very sloppy)
+ leaf = loadmodel->leafs;
+ endleaf = leaf + loadmodel->numleafs;
+ for (;leaf < endleaf;leaf++)
+ {
+ VectorSet( 2000000000, 2000000000, 2000000000, leaf->mins);
+ VectorSet(-2000000000, -2000000000, -2000000000, leaf->maxs);
+ }
+ p = portalchain;
+ while(p)
+ {
+ if (p->winding)
+ {
+ for (i = 0;i < 2;i++)
+ {
+ leaf = (mleaf_t *)p->nodes[i];
+ w = p->winding;
+ for (j = 0;j < w->numpoints;j++)
+ {
+ if (leaf->mins[0] > w->points[j][0]) leaf->mins[0] = w->points[j][0];
+ if (leaf->mins[1] > w->points[j][1]) leaf->mins[1] = w->points[j][1];
+ if (leaf->mins[2] > w->points[j][2]) leaf->mins[2] = w->points[j][2];
+ if (leaf->maxs[0] < w->points[j][0]) leaf->maxs[0] = w->points[j][0];
+ if (leaf->maxs[1] < w->points[j][1]) leaf->maxs[1] = w->points[j][1];
+ if (leaf->maxs[2] < w->points[j][2]) leaf->maxs[2] = w->points[j][2];
+ }
+ }
+ }
+ 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;
VectorCopy(p->winding->points[j], point->position);
point++;
}
+ PlaneClassify(&portal->plane);
// link into leaf's portal chain
portal->next = portal->here->portals;
VectorCopy(p->winding->points[j], point->position);
point++;
}
+ PlaneClassify(&portal->plane);
// link into leaf's portal chain
portal->next = portal->here->portals;
}
FreeWinding(p->winding);
}
- free(p);
+ qfree(p);
p = pnext;
}
}
{
node = portal->nodes[i];
- portalpointer = &node->portals;
+ portalpointer = (void **) &node->portals;
while (1)
{
t = *portalpointer;
}
else if (portal->nodes[1] == node)
{
- *portalpointer = portal->next[1];
+ *portalpointer = portal->next[1];
portal->nodes[1] = NULL;
}
else
}
if (t->nodes[0] == node)
- portalpointer = &t->next[0];
+ portalpointer = (void **) &t->next[0];
else if (t->nodes[1] == node)
- portalpointer = &t->next[1];
+ portalpointer = (void **) &t->next[1];
else
Host_Error ("RemovePortalFromNodes: portal not bounding leaf");
}
}
*/
-void Mod_MakePortals()
+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)
//
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);