/* Copyright (C) 1996-1997 Id Software, Inc. This program 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. 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. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" byte mod_novis[MAX_MAP_LEAFS/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"}; /* =============== Mod_BrushInit =============== */ void Mod_BrushInit (void) { Cvar_RegisterVariable (&gl_subdivide_size); Cvar_RegisterVariable (&halflifebsp); memset (mod_novis, 0xff, sizeof(mod_novis)); } // Mod_PointInLeaf moved to cpu_noasm.c /* =================== Mod_DecompressVis =================== */ 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; out = decompressed; if (!in) { // no vis info, so make all visible while (row) { *out++ = 0xff; row--; } return decompressed; } do { if (*in) { *out++ = *in++; continue; } c = in[1]; in += 2; while (c) { *out++ = 0; c--; } } while (out - decompressed < row); return decompressed; } byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) { if (leaf == model->leafs) return mod_novis; return Mod_DecompressVis (leaf->compressed_vis, model); } extern byte *mod_base; extern cvar_t r_fullbrights; /* ================= Mod_LoadTextures ================= */ void Mod_LoadTextures (lump_t *l) { int i, j, num, max, altmax, bytesperpixel, freeimage, transparent, fullbrights; miptex_t *mt; texture_t *tx, *tx2; texture_t *anims[10]; texture_t *altanims[10]; dmiptexlump_t *m; byte *data; int *dofs; if (!l->filelen) { loadmodel->textures = NULL; return; } 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) , loadname); // just to work around bounds checking when debugging with it (array index out of bounds error thing) dofs = m->dataofs; for (i=0 ; inummiptex ; i++) { dofs[i] = LittleLong(dofs[i]); if (dofs[i] == -1) continue; mt = (miptex_t *)((byte *)m + dofs[i]); mt->width = LittleLong (mt->width); mt->height = LittleLong (mt->height); for (j=0 ; joffsets[j] = LittleLong (mt->offsets[j]); if ( (mt->width & 15) || (mt->height & 15) ) Host_Error ("Texture %s is not 16 aligned", mt->name); // LordHavoc: rewriting the map texture loader for GLQuake tx = Hunk_AllocName (sizeof(texture_t), loadname ); loadmodel->textures[i] = tx; // LordHavoc: force all names to lowercase and make sure they are terminated while copying for (j = 0;mt->name[j] && j < 15;j++) { if (mt->name[j] >= 'A' && mt->name[j] <= 'Z') tx->name[j] = mt->name[j] + ('a' - 'A'); else tx->name[j] = mt->name[j]; } for (;j < 16;j++) tx->name[j] = 0; tx->width = mt->width; tx->height = mt->height; for (j=0 ; joffsets[j] = 0; freeimage = TRUE; bytesperpixel = 4; fullbrights = FALSE; transparent = TRUE; data = loadimagepixels(tx->name, FALSE, 0, 0); //tx->width, tx->height); if (!data) // no external texture found { freeimage = FALSE; transparent = FALSE; bytesperpixel = 1; if (!hlbsp && mt->offsets[0]) // texture included { data = (byte *)((int) mt + mt->offsets[0]); if (r_fullbrights.value && tx->name[0] != '*') { for (j = 0;j < tx->width*tx->height;j++) if (data[j] >= 224) // fullbright { fullbrights = TRUE; break; } } } else // no texture, and no external replacement texture was found { tx->width = tx->height = 16; data = (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]); } } else { tx->width = image_width; tx->height = image_height; } if (!hlbsp && !strncmp(tx->name,"sky",3) && tx->width == 256 && tx->height == 128) // LordHavoc: HL sky textures are entirely unrelated { tx->transparent = FALSE; R_InitSky (data, bytesperpixel); } else { tx->transparent = transparent; if (fullbrights) { char name[64]; byte *data2; data2 = malloc(tx->width*tx->height); for (j = 0;j < tx->width*tx->height;j++) data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data2, true, transparent, 1); strcpy(name, tx->name); strcat(name, "_glow"); for (j = 0;j < tx->width*tx->height;j++) data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights tx->gl_glowtexturenum = GL_LoadTexture (name, tx->width, tx->height, data2, true, transparent, 1); free(data2); } else { tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data, true, transparent, bytesperpixel); tx->gl_glowtexturenum = 0; } } if (freeimage) free(data); } // // sequence the animations // for (i=0 ; inummiptex ; i++) { tx = loadmodel->textures[i]; if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) continue; // allready sequenced // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); max = tx->name[1]; altmax = 0; if (max >= 'a' && max <= 'z') max -= 'a' - 'A'; 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 ; jnummiptex ; j++) { tx2 = loadmodel->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; if (strcmp (tx2->name+2, tx->name+2)) continue; num = tx2->name[1]; if (num >= 'a' && num <= 'z') num -= 'a' - 'A'; if (num >= '0' && num <= '9') { num -= '0'; anims[num] = tx2; if (num+1 > max) max = num + 1; } else if (num >= 'A' && num <= 'J') { num = num - 'A'; altanims[num] = tx2; if (num+1 > altmax) altmax = num+1; } else Host_Error ("Bad animating texture %s", tx->name); } #define ANIM_CYCLE 2 // link them all together for (j=0 ; jname); tx2->anim_total = max * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = anims[ (j+1)%max ]; if (altmax) tx2->alternate_anims = altanims[0]; } for (j=0 ; jname); tx2->anim_total = altmax * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = altanims[ (j+1)%altmax ]; if (max) tx2->alternate_anims = anims[0]; } } } /* ================= Mod_LoadLighting ================= */ void Mod_LoadLighting (lump_t *l) { int i; byte *in, *out, *data; byte d; char litfilename[1024]; loadmodel->lightdata = NULL; if (hlbsp) // LordHavoc: load the colored lighting data straight { loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname); memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); } else // LordHavoc: bsp version 29 (normal white lighting) { // LordHavoc: hope is not lost yet, check for a .lit file to load strcpy(litfilename, loadmodel->name); COM_StripExtension(litfilename, litfilename); strcat(litfilename, ".lit"); data = (byte*) COM_LoadHunkFile (litfilename, false); if (data) { if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T') { i = LittleLong(((int *)data)[1]); if (i == 1) { Con_DPrintf("%s loaded", litfilename); loadmodel->lightdata = data + 8; return; } else Con_Printf("Unknown .lit file version (%d)\n", i); } else Con_Printf("Corrupt .lit file (old version?), ignoring\n"); } // LordHavoc: oh well, expand the white lighting data if (!l->filelen) return; loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, litfilename); in = loadmodel->lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write out = loadmodel->lightdata; memcpy (in, mod_base + l->fileofs, l->filelen); for (i = 0;i < l->filelen;i++) { d = *in++; *out++ = d; *out++ = d; *out++ = d; } } } /* ================= Mod_LoadVisibility ================= */ void Mod_LoadVisibility (lump_t *l) { if (!l->filelen) { loadmodel->visdata = NULL; return; } loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname); 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) { if (!l->filelen) { loadmodel->entities = NULL; return; } loadmodel->entities = Hunk_AllocName ( l->filelen, loadname); memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); if (isworldmodel) CL_ParseEntityLump(loadmodel->entities); } /* ================= Mod_LoadVertexes ================= */ void Mod_LoadVertexes (lump_t *l) { dvertex_t *in; mvertex_t *out; int i, count; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->vertexes = out; loadmodel->numvertexes = count; for ( i=0 ; iposition[0] = LittleFloat (in->point[0]); out->position[1] = LittleFloat (in->point[1]); out->position[2] = LittleFloat (in->point[2]); } } /* ================= Mod_LoadSubmodels ================= */ void Mod_LoadSubmodels (lump_t *l) { dmodel_t *in; dmodel_t *out; int i, j, count; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->submodels = out; loadmodel->numsubmodels = count; 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]); } for (j=0 ; jheadnode[j] = LittleLong (in->headnode[j]); out->visleafs = LittleLong (in->visleafs); out->firstface = LittleLong (in->firstface); out->numfaces = LittleLong (in->numfaces); } } /* ================= Mod_LoadEdges ================= */ void Mod_LoadEdges (lump_t *l) { dedge_t *in; medge_t *out; int i, count; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); loadmodel->edges = out; loadmodel->numedges = count; for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); out->v[1] = (unsigned short)LittleShort(in->v[1]); } } /* ================= Mod_LoadTexinfo ================= */ void Mod_LoadTexinfo (lump_t *l) { texinfo_t *in; mtexinfo_t *out; int i, j, k, count; int miptex; float len1, len2; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->texinfo = out; loadmodel->numtexinfo = count; for ( i=0 ; ivecs[k][j] = LittleFloat (in->vecs[k][j]); len1 = Length (out->vecs[0]); len2 = Length (out->vecs[1]); len1 = (len1 + len2)/2; if (len1 < 0.32) out->mipadjust = 4; else if (len1 < 0.49) out->mipadjust = 3; else if (len1 < 0.99) out->mipadjust = 2; else out->mipadjust = 1; #if 0 if (len1 + len2 < 0.001) out->mipadjust = 1; // don't crash else out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); #endif miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); if (!loadmodel->textures) { out->texture = r_notexture_mip; // checkerboard texture out->flags = 0; out->texture->transparent = FALSE; } else { if (miptex >= loadmodel->numtextures) Host_Error ("miptex >= loadmodel->numtextures"); out->texture = loadmodel->textures[miptex]; if (!out->texture) { out->texture = r_notexture_mip; // texture not found out->flags = 0; out->texture->transparent = FALSE; } } } } /* ================ CalcSurfaceExtents Fills in s->texturemins[] and s->extents[] ================ */ void CalcSurfaceExtents (msurface_t *s) { float mins[2], maxs[2], val; int i,j, e; mvertex_t *v; mtexinfo_t *tex; int bmins[2], bmaxs[2]; mins[0] = mins[1] = 999999; maxs[0] = maxs[1] = -99999; tex = s->texinfo; for (i=0 ; inumedges ; i++) { e = loadmodel->surfedges[s->firstedge+i]; if (e >= 0) v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; else v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; for (j=0 ; j<2 ; j++) { val = v->position[0] * tex->vecs[j][0] + v->position[1] * tex->vecs[j][1] + v->position[2] * tex->vecs[j][2] + tex->vecs[j][3]; if (val < mins[j]) mins[j] = val; if (val > maxs[j]) maxs[j] = val; } } for (i=0 ; i<2 ; i++) { bmins[i] = floor(mins[i]/16); bmaxs[i] = ceil(maxs[i]/16); s->texturemins[i] = bmins[i] * 16; s->extents[i] = (bmaxs[i] - bmins[i]) * 16; if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ ) Host_Error ("Bad surface extents"); } } void GL_SubdivideSurface (msurface_t *fa); extern char skyname[]; /* ================= Mod_LoadFaces ================= */ void Mod_LoadFaces (lump_t *l) { dface_t *in; msurface_t *out; int i, count, surfnum; int planenum, side; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->surfaces = out; loadmodel->numsurfaces = count; for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); out->numedges = LittleShort(in->numedges); out->flags = 0; planenum = LittleShort(in->planenum); side = LittleShort(in->side); if (side) out->flags |= SURF_PLANEBACK; out->plane = loadmodel->planes + planenum; out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); CalcSurfaceExtents (out); // lighting info for (i=0 ; istyles[i] = in->styles[i]; i = LittleLong(in->lightofs); if (i == -1) out->samples = NULL; 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); // 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') && (out->texinfo->texture->name[1] == 'k' || out->texinfo->texture->name[1] == 'K') && (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); 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 { out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); // LordHavoc: some turbulent textures should be fullbright and solid 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); for (i=0 ; i<2 ; i++) { out->extents[i] = 16384; out->texturemins[i] = -8192; } GL_SubdivideSurface (out); // cut up polygon for warps continue; } } } /* ================= Mod_SetParent ================= */ void Mod_SetParent (mnode_t *node, mnode_t *parent) { node->parent = parent; if (node->contents < 0) return; Mod_SetParent (node->children[0], node); Mod_SetParent (node->children[1], node); } /* ================= Mod_LoadNodes ================= */ void Mod_LoadNodes (lump_t *l) { int i, j, count, p; dnode_t *in; mnode_t *out; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->nodes = out; loadmodel->numnodes = count; for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); out->minmaxs[3+j] = LittleShort (in->maxs[j]); } p = LittleLong(in->planenum); out->plane = loadmodel->planes + p; out->firstsurface = LittleShort (in->firstface); out->numsurfaces = LittleShort (in->numfaces); for (j=0 ; j<2 ; j++) { p = LittleShort (in->children[j]); if (p >= 0) out->children[j] = loadmodel->nodes + p; else out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); } } Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs } /* ================= Mod_LoadLeafs ================= */ void Mod_LoadLeafs (lump_t *l) { dleaf_t *in; mleaf_t *out; int i, j, count, p; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->leafs = out; loadmodel->numleafs = count; for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); out->minmaxs[3+j] = LittleShort (in->maxs[j]); } p = LittleLong(in->contents); out->contents = p; 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]; // gl underwater warp // LordHavoc: disabled underwater warping /* if (out->contents != CONTENTS_EMPTY) { for (j=0 ; jnummarksurfaces ; j++) out->firstmarksurface[j]->flags |= SURF_UNDERWATER; } */ } } /* ================= Mod_LoadClipnodes ================= */ void Mod_LoadClipnodes (lump_t *l) { dclipnode_t *in, *out; int i, count; hull_t *hull; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->clipnodes = out; loadmodel->numclipnodes = count; if (hlbsp) { hull = &loadmodel->hulls[1]; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count-1; hull->planes = loadmodel->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; hull->clip_mins[2] = -36; hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 36; hull = &loadmodel->hulls[2]; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count-1; hull->planes = loadmodel->planes; hull->clip_mins[0] = -32; hull->clip_mins[1] = -32; hull->clip_mins[2] = -32; hull->clip_maxs[0] = 32; hull->clip_maxs[1] = 32; hull->clip_maxs[2] = 32; hull = &loadmodel->hulls[3]; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count-1; hull->planes = loadmodel->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; hull->clip_mins[2] = -18; hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 18; } else { hull = &loadmodel->hulls[1]; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count-1; hull->planes = loadmodel->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; hull->clip_mins[2] = -24; hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 32; hull = &loadmodel->hulls[2]; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count-1; hull->planes = loadmodel->planes; hull->clip_mins[0] = -32; hull->clip_mins[1] = -32; hull->clip_mins[2] = -24; hull->clip_maxs[0] = 32; hull->clip_maxs[1] = 32; hull->clip_maxs[2] = 64; } for (i=0 ; iplanenum = LittleLong(in->planenum); out->children[0] = LittleShort(in->children[0]); out->children[1] = LittleShort(in->children[1]); if (out->children[0] >= count || out->children[1] >= count) Host_Error("Corrupt clipping hull (out of range child)\n"); } } /* ================= Mod_MakeHull0 Duplicate the drawing hull structure as a clipping hull ================= */ void Mod_MakeHull0 (void) { mnode_t *in, *child; dclipnode_t *out; int i, j, count; hull_t *hull; hull = &loadmodel->hulls[0]; in = loadmodel->nodes; count = loadmodel->numnodes; out = Hunk_AllocName ( count*sizeof(*out), loadname); hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count-1; hull->planes = loadmodel->planes; for (i=0 ; iplanenum = in->plane - loadmodel->planes; for (j=0 ; j<2 ; j++) { child = in->children[j]; if (child->contents < 0) out->children[j] = child->contents; else out->children[j] = child - loadmodel->nodes; } } } /* ================= Mod_LoadMarksurfaces ================= */ 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); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->marksurfaces = out; loadmodel->nummarksurfaces = count; for ( i=0 ; i= loadmodel->numsurfaces) Host_Error ("Mod_ParseMarksurfaces: bad surface number"); out[i] = loadmodel->surfaces + j; } } /* ================= Mod_LoadSurfedges ================= */ void Mod_LoadSurfedges (lump_t *l) { int i, count; int *in, *out; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->surfedges = out; loadmodel->numsurfedges = count; for ( i=0 ; ifileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*2*sizeof(*out), loadname); loadmodel->planes = out; loadmodel->numplanes = count; 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); } } /* ================= Mod_LoadBrushModel ================= */ 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); if (i != BSPVERSION && i != 30) Host_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i or 30 (HalfLife))", mod->name, i, BSPVERSION); hlbsp = i == 30; halflifebsp.value = hlbsp; // swap all the lumps mod_base = (byte *)header; for (i=0 ; ilumps[LUMP_ENTITIES]); Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); Mod_LoadEdges (&header->lumps[LUMP_EDGES]); Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); Mod_LoadFaces (&header->lumps[LUMP_FACES]); Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); Mod_LoadNodes (&header->lumps[LUMP_NODES]); Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); // Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); Mod_MakeHull0 (); mod->numframes = 2; // regular and alternate animation // // set up the submodels (FIXME: this is confusing) // for (i=0 ; inumsubmodels ; i++) { bm = &mod->submodels[i]; mod->hulls[0].firstclipnode = bm->headnode[0]; for (j=1 ; jhulls[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); mod->numleafs = bm->visleafs; 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]; sprintf (name, "*%i", i+1); loadmodel = Mod_FindName (name); *loadmodel = *mod; strcpy (loadmodel->name, name); mod = loadmodel; } } }