X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_brush.c;h=b005563b02b4630bdd9d04c91a5c7e9c5de5c697;hb=018a70ec5e58fead3ddcbd1a4cf63ad2abc3d8f1;hp=f1f87b8c27e3fa301a8fcc09fbc7bd243e1019f7;hpb=d7035ef4229a2462ad59a67160494593fbd8f2e0;p=xonotic%2Fdarkplaces.git diff --git a/model_brush.c b/model_brush.c index f1f87b8c..b005563b 100644 --- a/model_brush.c +++ b/model_brush.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. 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. @@ -20,12 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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 gl_subdivide_size = {CVAR_SAVE, "gl_subdivide_size", "128"}; +cvar_t halflifebsp = {0, "halflifebsp", "0"}; +cvar_t r_novis = {0, "r_novis", "0"}; /* =============== @@ -36,7 +37,13 @@ void Mod_BrushInit (void) { Cvar_RegisterVariable (&gl_subdivide_size); Cvar_RegisterVariable (&halflifebsp); - memset (mod_novis, 0xff, sizeof(mod_novis)); + Cvar_RegisterVariable (&r_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); } /* @@ -47,21 +54,16 @@ Mod_PointInLeaf mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) { mnode_t *node; - + // if (!model || !model->nodes) // 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) @@ -69,7 +71,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) mnode_t *node; float d; mplane_t *plane; - + if (!model || !model->nodes) Sys_Error ("Mod_PointInLeaf: bad model"); @@ -85,7 +87,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) else node = node->children[1]; } - + return NULL; // never reached } */ @@ -95,16 +97,17 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) 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; 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) @@ -112,8 +115,9 @@ byte *Mod_DecompressVis (byte *in, model_t *model) *out++ = 0xff; row--; } - return decompressed; + return decompressed; } + */ do { @@ -122,7 +126,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model) *out++ = *in++; continue; } - + c = in[1]; in += 2; while (c) @@ -131,25 +135,21 @@ byte *Mod_DecompressVis (byte *in, model_t *model) c--; } } while (out - decompressed < row); - + return decompressed; } 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]; @@ -192,7 +192,7 @@ void Mod_SetupNoTexture() 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; @@ -209,7 +209,7 @@ void Mod_LoadTextures (lump_t *l) 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)); @@ -232,11 +232,14 @@ void Mod_LoadTextures (lump_t *l) 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 @@ -250,6 +253,12 @@ void Mod_LoadTextures (lump_t *l) 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) @@ -393,53 +402,31 @@ void Mod_LoadTextures (lump_t *l) // 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++) { @@ -447,21 +434,20 @@ void Mod_LoadTextures (lump_t *l) 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]; } } } @@ -471,7 +457,7 @@ void Mod_LoadTextures (lump_t *l) Mod_LoadLighting ================= */ -void Mod_LoadLighting (lump_t *l) +static void Mod_LoadLighting (lump_t *l) { int i; byte *in, *out, *data; @@ -530,7 +516,7 @@ void Mod_LoadLighting (lump_t *l) Mod_LoadVisibility ================= */ -void Mod_LoadVisibility (lump_t *l) +static void Mod_LoadVisibility (lump_t *l) { if (!l->filelen) { @@ -541,16 +527,12 @@ void Mod_LoadVisibility (lump_t *l) memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen); } -void CL_ParseEntityLump(char *entdata); - -extern qboolean isworldmodel; - /* ================= Mod_LoadEntities ================= */ -void Mod_LoadEntities (lump_t *l) +static void Mod_LoadEntities (lump_t *l) { if (!l->filelen) { @@ -570,7 +552,7 @@ void Mod_LoadEntities (lump_t *l) Mod_LoadVertexes ================= */ -void Mod_LoadVertexes (lump_t *l) +static void Mod_LoadVertexes (lump_t *l) { dvertex_t *in; mvertex_t *out; @@ -598,7 +580,7 @@ void Mod_LoadVertexes (lump_t *l) Mod_LoadSubmodels ================= */ -void Mod_LoadSubmodels (lump_t *l) +static void Mod_LoadSubmodels (lump_t *l) { dmodel_t *in; dmodel_t *out; @@ -616,7 +598,8 @@ void Mod_LoadSubmodels (lump_t *l) for ( i=0 ; imins[j] = LittleFloat (in->mins[j]) - 1; out->maxs[j] = LittleFloat (in->maxs[j]) + 1; out->origin[j] = LittleFloat (in->origin[j]); @@ -634,7 +617,7 @@ void Mod_LoadSubmodels (lump_t *l) Mod_LoadEdges ================= */ -void Mod_LoadEdges (lump_t *l) +static void Mod_LoadEdges (lump_t *l) { dedge_t *in; medge_t *out; @@ -661,7 +644,7 @@ void Mod_LoadEdges (lump_t *l) Mod_LoadTexinfo ================= */ -void Mod_LoadTexinfo (lump_t *l) +static void Mod_LoadTexinfo (lump_t *l) { texinfo_t *in; mtexinfo_t *out; @@ -685,7 +668,7 @@ void Mod_LoadTexinfo (lump_t *l) miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); - + if (!loadmodel->textures) { out->texture = &r_notexture_mip; // checkerboard texture @@ -712,7 +695,7 @@ CalcSurfaceExtents 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; @@ -724,7 +707,7 @@ void CalcSurfaceExtents (msurface_t *s) maxs[0] = maxs[1] = -99999; tex = s->texinfo; - + for (i=0 ; inumedges ; i++) { e = loadmodel->surfedges[s->firstedge+i]; @@ -761,14 +744,12 @@ void CalcSurfaceExtents (msurface_t *s) void GL_SubdivideSurface (msurface_t *fa); -extern char skyname[]; - /* ================= Mod_LoadFaces ================= */ -void Mod_LoadFaces (lump_t *l) +static void Mod_LoadFaces (lump_t *l) { dface_t *in; msurface_t *out; @@ -787,20 +768,20 @@ void Mod_LoadFaces (lump_t *l) for ( surfnum=0 ; surfnumfirstedge = 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 ; isamples = 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') @@ -822,11 +803,11 @@ void Mod_LoadFaces (lump_t *l) && (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; } - + // if (!strncmp(out->texinfo->texture->name,"*",1)) // turbulent if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check { @@ -835,7 +816,7 @@ void Mod_LoadFaces (lump_t *l) 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; @@ -845,6 +826,8 @@ void Mod_LoadFaces (lump_t *l) continue; } + if (!out->texinfo->texture->transparent) + out->flags |= SURF_CLIPSOLID; } } @@ -854,7 +837,7 @@ void Mod_LoadFaces (lump_t *l) 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) @@ -868,7 +851,7 @@ void Mod_SetParent (mnode_t *node, mnode_t *parent) Mod_LoadNodes ================= */ -void Mod_LoadNodes (lump_t *l) +static void Mod_LoadNodes (lump_t *l) { int i, j, count, p; dnode_t *in; @@ -915,7 +898,7 @@ void Mod_LoadNodes (lump_t *l) Mod_LoadLeafs ================= */ -void Mod_LoadLeafs (lump_t *l) +static void Mod_LoadLeafs (lump_t *l) { dleaf_t *in; mleaf_t *out; @@ -944,13 +927,12 @@ void Mod_LoadLeafs (lump_t *l) out->firstmarksurface = loadmodel->marksurfaces + LittleShort(in->firstmarksurface); out->nummarksurfaces = LittleShort(in->nummarksurfaces); - + p = LittleLong(in->visofs); if (p == -1) 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]; @@ -972,7 +954,7 @@ void Mod_LoadLeafs (lump_t *l) Mod_LoadClipnodes ================= */ -void Mod_LoadClipnodes (lump_t *l) +static void Mod_LoadClipnodes (lump_t *l) { dclipnode_t *in, *out; int i, count; @@ -1069,7 +1051,7 @@ Mod_MakeHull0 Duplicate the drawing hull structure as a clipping hull ================= */ -void Mod_MakeHull0 (void) +static void Mod_MakeHull0 (void) { mnode_t *in; dclipnode_t *out; @@ -1077,7 +1059,7 @@ void Mod_MakeHull0 (void) hull_t *hull; hull = &loadmodel->hulls[0]; - + in = loadmodel->nodes; count = loadmodel->numnodes; out = Hunk_AllocName ( count*sizeof(*out), va("%s hull0", loadname)); @@ -1100,12 +1082,12 @@ void Mod_MakeHull0 (void) 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); @@ -1129,8 +1111,8 @@ void Mod_LoadMarksurfaces (lump_t *l) Mod_LoadSurfedges ================= */ -void Mod_LoadSurfedges (lump_t *l) -{ +static void Mod_LoadSurfedges (lump_t *l) +{ int i, count; int *in, *out; @@ -1153,14 +1135,13 @@ void Mod_LoadSurfedges (lump_t *l) 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; - int bits; - + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); @@ -1172,18 +1153,13 @@ void Mod_LoadPlanes (lump_t *l) for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); -// if (out->normal[j] < 0) -// bits |= 1<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); } } @@ -1201,7 +1177,7 @@ winding_t; NewWinding ================== */ -winding_t *NewWinding (int points) +static winding_t *NewWinding (int points) { winding_t *w; int size; @@ -1210,15 +1186,15 @@ winding_t *NewWinding (int points) 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); } /* @@ -1226,7 +1202,7 @@ void FreeWinding (winding_t *w) BaseWindingForPlane ================= */ -winding_t *BaseWindingForPlane (mplane_t *p) +static winding_t *BaseWindingForPlane (mplane_t *p) { vec3_t org, vright, vup; winding_t *w; @@ -1268,7 +1244,7 @@ If keepon is true, an exactly on-plane winding will be saved, otherwise 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]; @@ -1369,7 +1345,7 @@ returned winding will be the input winding. If on both sides, two 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]; @@ -1483,28 +1459,90 @@ static portal_t *portalchain; 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() +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; 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; @@ -1529,8 +1567,11 @@ void Mod_FinalizePortals() 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; @@ -1545,6 +1586,7 @@ void Mod_FinalizePortals() VectorCopy(p->winding->points[j], point->position); point++; } + PlaneClassify(&portal->plane); // link into leaf's portal chain portal->next = portal->here->portals; @@ -1566,6 +1608,7 @@ void Mod_FinalizePortals() VectorCopy(p->winding->points[j], point->position); point++; } + PlaneClassify(&portal->plane); // link into leaf's portal chain portal->next = portal->here->portals; @@ -1576,7 +1619,7 @@ void Mod_FinalizePortals() } FreeWinding(p->winding); } - free(p); + qfree(p); p = pnext; } } @@ -1586,7 +1629,7 @@ void Mod_FinalizePortals() 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"); @@ -1610,7 +1653,7 @@ void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back) RemovePortalFromNode ============= */ -void RemovePortalFromNodes(portal_t *portal) +static void RemovePortalFromNodes(portal_t *portal) { int i; mnode_t *node; @@ -1620,7 +1663,7 @@ void RemovePortalFromNodes(portal_t *portal) { node = portal->nodes[i]; - portalpointer = &node->portals; + portalpointer = (void **) &node->portals; while (1) { t = *portalpointer; @@ -1636,7 +1679,7 @@ void RemovePortalFromNodes(portal_t *portal) } else if (portal->nodes[1] == node) { - *portalpointer = portal->next[1]; + *portalpointer = portal->next[1]; portal->nodes[1] = NULL; } else @@ -1645,16 +1688,16 @@ void RemovePortalFromNodes(portal_t *portal) } 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_RecursiveNodePortals (mnode_t *node) +static void Mod_RecursiveNodePortals (mnode_t *node) { int side; mnode_t *front, *back, *other_node; @@ -1815,7 +1858,7 @@ void Mod_MakeOutsidePortals(mnode_t *node) } */ -void Mod_MakePortals() +static void Mod_MakePortals(void) { // Con_Printf("building portals for %s\n", loadmodel->name); @@ -1835,9 +1878,9 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) int i, j; dheader_t *header; dmodel_t *bm; - + loadmodel->type = mod_brush; - + header = (dheader_t *)buffer; i = LittleLong (header->version); @@ -1853,7 +1896,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) ((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]); @@ -1876,14 +1919,23 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) 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]; @@ -1892,17 +1944,55 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) 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];