X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_brush.c;h=5b7e7dd5979a918c5470921634123cdbf2fda7cf;hp=54324fabacbed2f224ccb97efaf3a41633def2f4;hb=bc8b80ee19f7a87e326fa765427d0c4e8dfe9940;hpb=d57be67cb00229acb8564b92c8b7c58eeed8a0cb diff --git a/model_brush.c b/model_brush.c index 54324fab..5b7e7dd5 100644 --- a/model_brush.c +++ b/model_brush.c @@ -20,14 +20,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -byte mod_novis[(MAX_MAP_LEAFS + 7)/ 8]; +// note: model_shared.c sets up r_notexture, and r_surf_notexture -cvar_t r_subdivide_size = {CVAR_SAVE, "r_subdivide_size", "128"}; +qbyte mod_novis[(MAX_MAP_LEAFS + 7)/ 8]; + +//cvar_t r_subdivide_size = {CVAR_SAVE, "r_subdivide_size", "128"}; cvar_t halflifebsp = {0, "halflifebsp", "0"}; cvar_t r_novis = {0, "r_novis", "0"}; cvar_t r_miplightmaps = {CVAR_SAVE, "r_miplightmaps", "0"}; cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1"}; -cvar_t r_vertexsurfacesthreshold = {CVAR_SAVE, "r_vertexsurfacesthreshold", "48"}; +cvar_t r_vertexsurfacesthreshold = {CVAR_SAVE, "r_vertexsurfacesthreshold", "0"}; +cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"}; +cvar_t r_sortsurfaces = {0, "r_sortsurfaces", "0"}; /* =============== @@ -36,20 +40,17 @@ Mod_BrushInit */ void Mod_BrushInit (void) { - Cvar_RegisterVariable(&r_subdivide_size); +// Cvar_RegisterVariable(&r_subdivide_size); Cvar_RegisterVariable(&halflifebsp); Cvar_RegisterVariable(&r_novis); Cvar_RegisterVariable(&r_miplightmaps); Cvar_RegisterVariable(&r_lightmaprgba); Cvar_RegisterVariable(&r_vertexsurfacesthreshold); + Cvar_RegisterVariable(&r_nosurftextures); + Cvar_RegisterVariable(&r_sortsurfaces); memset(mod_novis, 0xff, sizeof(mod_novis)); } -void Mod_Brush_SERAddEntity(void) -{ - R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL); -} - /* =============== Mod_PointInLeaf @@ -60,8 +61,6 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) mnode_t *node; Mod_CheckLoaded(model); -// if (!model || !model->nodes) -// Sys_Error ("Mod_PointInLeaf: bad model"); // LordHavoc: modified to start at first clip node, // in other words: first node of the (sub)model @@ -86,60 +85,22 @@ void Mod_FindNonSolidLocation(vec3_t pos, model_t *mod) pos[2]-=1; } -/* -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"); - - node = model->nodes; - while (1) - { - if (node->contents < 0) - return (mleaf_t *)node; - plane = node->plane; - d = DotProduct (p,plane->normal) - plane->dist; - if (d > 0) - node = node->children[0]; - else - node = node->children[1]; - } - - return NULL; // never reached -} -*/ /* =================== Mod_DecompressVis =================== */ -static byte *Mod_DecompressVis (byte *in, model_t *model) +static qbyte *Mod_DecompressVis (qbyte *in, model_t *model) { - static byte decompressed[MAX_MAP_LEAFS/8]; - int c; - byte *out; - int row; + static qbyte decompressed[MAX_MAP_LEAFS/8]; + int c; + qbyte *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) @@ -160,47 +121,13 @@ static byte *Mod_DecompressVis (byte *in, model_t *model) return decompressed; } -byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) +qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) { if (r_novis.integer || leaf == model->leafs || leaf->compressed_vis == NULL) return mod_novis; return Mod_DecompressVis (leaf->compressed_vis, model); } -void Mod_SetupNoTexture(void) -{ - int x, y; - byte pix[16][16][4]; - - for (y = 0;y < 16;y++) - { - for (x = 0;x < 16;x++) - { - if ((y < 8) ^ (x < 8)) - { - pix[y][x][0] = 128; - pix[y][x][1] = 128; - pix[y][x][2] = 128; - pix[y][x][3] = 255; - } - else - { - pix[y][x][0] = 64; - pix[y][x][1] = 64; - pix[y][x][2] = 64; - pix[y][x][3] = 255; - } - } - } - - memset(&loadmodel->notexture, 0, sizeof(texture_t)); - strcpy(loadmodel->notexture.name, "notexture"); - loadmodel->notexture.width = 16; - loadmodel->notexture.height = 16; - loadmodel->notexture.flags = 0; - loadmodel->notexture.texture = R_LoadTexture(loadmodel->texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP); -} - /* ================= Mod_LoadTextures @@ -208,36 +135,52 @@ Mod_LoadTextures */ static void Mod_LoadTextures (lump_t *l) { - int i, j, k, num, max, altmax, mtwidth, mtheight, *dofs; - miptex_t *dmiptex; - texture_t *tx, *tx2, *anims[10], *altanims[10]; - dmiptexlump_t *m; - byte *data, *mtdata, *data2; - char name[256]; + int i, j, k, num, max, altmax, mtwidth, mtheight, *dofs, incomplete; + miptex_t *dmiptex; + texture_t *tx, *tx2, *anims[10], *altanims[10]; + dmiptexlump_t *m; + qbyte *data, *mtdata, *data2; + char name[256]; - Mod_SetupNoTexture(); + loadmodel->textures = NULL; 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 = Mem_Alloc(loadmodel->mempool, m->nummiptex * sizeof(*loadmodel->textures)); + // add two slots for notexture walls and notexture liquids + loadmodel->numtextures = m->nummiptex + 2; + loadmodel->textures = Mem_Alloc(loadmodel->mempool, loadmodel->numtextures * sizeof(*loadmodel->textures)); + + // fill out all slots with notexture + for (i = 0;i < loadmodel->numtextures;i++) + { + loadmodel->textures[i] = tx = Mem_Alloc(loadmodel->mempool, sizeof(texture_t)); + tx->width = 16; + tx->height = 16; + tx->texture = r_notexture; + if (i == loadmodel->numtextures - 1) + tx->flags = SURF_DRAWTURB | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID; + } // just to work around bounds checking when debugging with it (array index out of bounds error thing) dofs = m->dataofs; + // LordHavoc: mostly rewritten map texture loader for (i = 0;i < m->nummiptex;i++) { dofs[i] = LittleLong(dofs[i]); - if (dofs[i] == -1) + if (dofs[i] == -1 || r_nosurftextures.integer) continue; - dmiptex = (miptex_t *)((byte *)m + dofs[i]); + dmiptex = (miptex_t *)((qbyte *)m + dofs[i]); + + // make sure name is no more than 15 characters + for (j = 0;dmiptex->name[j] && j < 15;j++) + name[j] = dmiptex->name[j]; + name[j] = 0; + mtwidth = LittleLong (dmiptex->width); mtheight = LittleLong (dmiptex->height); mtdata = NULL; @@ -246,61 +189,59 @@ static void Mod_LoadTextures (lump_t *l) { // texture included if (j < 40 || j + mtwidth * mtheight > l->filelen) - Host_Error ("Texture %s is corrupt or incomplete\n", dmiptex->name); - mtdata = (byte *)dmiptex + j; + { + Con_Printf ("Texture \"%s\" in \"%s\"is corrupt or incomplete\n", dmiptex->name, loadmodel->name); + continue; + } + mtdata = (qbyte *)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 = Mem_Alloc(loadmodel->mempool, sizeof(texture_t)); - 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 - for (j = 0;dmiptex->name[j] && j < 15;j++) - { - if (dmiptex->name[j] >= 'A' && dmiptex->name[j] <= 'Z') - tx->name[j] = dmiptex->name[j] + ('a' - 'A'); - else - tx->name[j] = dmiptex->name[j]; - } - for (;j < 16;j++) - tx->name[j] = 0; + Con_Printf ("warning: texture \"%s\" in \"%s\" is not 16 aligned", dmiptex->name, loadmodel->name); - if (!tx->name[0]) - { - Con_Printf("warning: unnamed texture in %s\n", loadmodel->name); - sprintf(tx->name, "unnamed%i", i); - } + // LordHavoc: force all names to lowercase + for (j = 0;name[j];j++) + if (name[j] >= 'A' && name[j] <= 'Z') + name[j] += 'a' - 'A'; + tx = loadmodel->textures[i]; + strcpy(tx->name, name); tx->width = mtwidth; tx->height = mtheight; tx->texture = NULL; tx->glowtexture = NULL; tx->fogtexture = NULL; - if (!loadmodel->ishlbsp && !strncmp(tx->name,"sky",3) && mtwidth == 256 && mtheight == 128) // LordHavoc: HL sky textures are entirely unrelated + if (!tx->name[0]) { - data = loadimagepixels(tx->name, false, 0, 0); - if (data) + sprintf(tx->name, "unnamed%i", i); + Con_Printf("warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name); + } + + // LordHavoc: HL sky textures are entirely different than quake + if (!loadmodel->ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128) + { + if (loadmodel->isworldmodel) { - if (image_width == 256 && image_height == 128) - { - if (loadmodel->isworldmodel) - R_InitSky (data, 4); - Mem_Free(data); - } - else + data = loadimagepixels(tx->name, false, 0, 0); + if (data) { - Mem_Free(data); - Host_Error("Mod_LoadTextures: replacement sky image must be 256x128 pixels\n"); + if (image_width == 256 && image_height == 128) + { + R_InitSky (data, 4); + Mem_Free(data); + } + else + { + Mem_Free(data); + Con_Printf ("Invalid replacement texture for sky \"%s\" in %\"%s\", must be 256x128 pixels\n", tx->name, loadmodel->name); + if (mtdata != NULL) + R_InitSky (mtdata, 1); + } } + else if (mtdata != NULL) + R_InitSky (mtdata, 1); } - else if (loadmodel->isworldmodel) - R_InitSky (mtdata, 1); } else if ((tx->texture = loadtextureimagewithmask(loadmodel->texturepool, tx->name, 0, 0, false, true, true))) { @@ -349,7 +290,7 @@ static void Mod_LoadTextures (lump_t *l) { tx->width = 16; tx->height = 16; - tx->texture = loadmodel->notexture.texture; + tx->texture = r_notexture; } } else @@ -372,7 +313,7 @@ static void Mod_LoadTextures (lump_t *l) } if (fullbrights) { - data2 = Mem_Alloc(tempmempool, tx->width*tx->height); + data2 = Mem_Alloc(loadmodel->mempool, tx->width*tx->height); for (j = 0;j < tx->width*tx->height;j++) data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights tx->texture = R_LoadTexture (loadmodel->texturepool, tx->name, tx->width, tx->height, data2, TEXTYPE_QPALETTE, TEXF_MIPMAP | TEXF_PRECACHE); @@ -390,7 +331,7 @@ static void Mod_LoadTextures (lump_t *l) { tx->width = 16; tx->height = 16; - tx->texture = loadmodel->notexture.texture; + tx->texture = r_notexture; } } } @@ -414,21 +355,18 @@ static void Mod_LoadTextures (lump_t *l) } } -// -// sequence the animations -// + // sequence the animations for (i = 0;i < m->nummiptex;i++) { tx = loadmodel->textures[i]; - if (!tx || tx->name[0] != '+') + if (!tx || tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0) continue; - if (tx->anim_total) + if (tx->anim_total[0] || tx->anim_total[1]) continue; // already sequenced // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); - max = altmax = 0; for (j = i;j < m->nummiptex;j++) { @@ -442,38 +380,79 @@ static void Mod_LoadTextures (lump_t *l) else if (num >= 'a' && num <= 'j') altanims[num - 'a'] = tx2; else - Host_Error ("Bad animating texture %s", tx->name); + Con_Printf ("Bad animating texture %s\n", tx->name); } + max = altmax = 0; for (j = 0;j < 10;j++) { - if (anims[j] != NULL) + if (anims[j]) max = j + 1; - if (altanims[j] != NULL) + if (altanims[j]) altmax = j + 1; } + //Con_Printf("linking animation %s (%i:%i frames)\n\n", tx->name, max, altmax); - // link them all together + incomplete = false; for (j = 0;j < max;j++) { - tx2 = anims[j]; - if (!tx2) - Host_Error ("Missing frame %i of %s", j, tx->name); - tx2->anim_total = max; - tx2->alternate_anims = altanims[0]; // NULL if there is no alternate + if (!anims[j]) + { + Con_Printf ("Missing frame %i of %s\n", j, tx->name); + incomplete = true; + } + } + for (j = 0;j < altmax;j++) + { + if (!altanims[j]) + { + Con_Printf ("Missing altframe %i of %s\n", j, tx->name); + incomplete = true; + } + } + if (incomplete) + continue; + + if (altmax < 1) + { + // if there is no alternate animation, duplicate the primary + // animation into the alternate + altmax = max; for (k = 0;k < 10;k++) - tx2->anim_frames[k] = anims[k]; + altanims[k] = anims[k]; } - for (j = 0;j < altmax;j++) + // link together the primary animation + for (j = 0;j < max;j++) { - tx2 = altanims[j]; - if (!tx2) - Host_Error ("Missing frame %i of %s", j, tx->name); - tx2->anim_total = altmax; - tx2->alternate_anims = anims[0]; // NULL if there is no alternate + tx2 = anims[j]; + tx2->animated = true; + tx2->anim_total[0] = max; + tx2->anim_total[1] = altmax; for (k = 0;k < 10;k++) - tx2->anim_frames[k] = altanims[k]; + { + tx2->anim_frames[0][k] = anims[k]; + tx2->anim_frames[1][k] = altanims[k]; + } + } + + // if there really is an alternate anim... + if (anims[0] != altanims[0]) + { + // link together the alternate animation + for (j = 0;j < altmax;j++) + { + tx2 = altanims[j]; + tx2->animated = true; + // the primary/alternate are reversed here + tx2->anim_total[0] = altmax; + tx2->anim_total[1] = max; + for (k = 0;k < 10;k++) + { + tx2->anim_frames[0][k] = altanims[k]; + tx2->anim_frames[1][k] = anims[k]; + } + } } } } @@ -486,8 +465,7 @@ Mod_LoadLighting static void Mod_LoadLighting (lump_t *l) { int i; - byte *in, *out, *data; - byte d; + qbyte *in, *out, *data, d; char litfilename[1024]; loadmodel->lightdata = NULL; if (loadmodel->ishlbsp) // LordHavoc: load the colored lighting data straight @@ -501,7 +479,7 @@ static void Mod_LoadLighting (lump_t *l) strcpy(litfilename, loadmodel->name); COM_StripExtension(litfilename, litfilename); strcat(litfilename, ".lit"); - data = (byte*) COM_LoadFile (litfilename, false); + data = (qbyte*) COM_LoadFile (litfilename, false); if (data) { if (loadsize > 8 && data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T') @@ -547,6 +525,66 @@ static void Mod_LoadLighting (lump_t *l) } } +void Mod_LoadLightList(void) +{ + int a, n, numlights; + char lightsfilename[1024], *s, *t, *lightsstring; + mlight_t *e; + + strcpy(lightsfilename, loadmodel->name); + COM_StripExtension(lightsfilename, lightsfilename); + strcat(lightsfilename, ".lights"); + s = lightsstring = (char *) COM_LoadFile (lightsfilename, false); + if (s) + { + numlights = 0; + while (*s) + { + while (*s && *s != '\n') + s++; + if (!*s) + { + Mem_Free(lightsstring); + Host_Error("lights file must end with a newline\n"); + } + s++; + numlights++; + } + loadmodel->lights = Mem_Alloc(loadmodel->mempool, numlights * sizeof(mlight_t)); + s = lightsstring; + n = 0; + while (*s && n < numlights) + { + t = s; + while (*s && *s != '\n') + s++; + if (!*s) + { + Mem_Free(lightsstring); + Host_Error("misparsed lights file!\n"); + } + e = loadmodel->lights + n; + *s = 0; + a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &e->origin[0], &e->origin[1], &e->origin[2], &e->falloff, &e->light[0], &e->light[1], &e->light[2], &e->subtract, &e->spotdir[0], &e->spotdir[1], &e->spotdir[2], &e->spotcone, &e->distbias, &e->style); + *s = '\n'; + if (a != 14) + { + Mem_Free(lightsstring); + Host_Error("invalid lights file, found %d parameters on line %i, should be 13 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone style)\n", a, n + 1); + } + s++; + n++; + } + if (*s) + { + Mem_Free(lightsstring); + Host_Error("misparsed lights file!\n"); + } + loadmodel->numlights = numlights; + Mem_Free(lightsstring); + } +} + /* ================= @@ -555,11 +593,9 @@ Mod_LoadVisibility */ static void Mod_LoadVisibility (lump_t *l) { + loadmodel->visdata = NULL; if (!l->filelen) - { - loadmodel->visdata = NULL; return; - } loadmodel->visdata = Mem_Alloc(loadmodel->mempool, l->filelen); memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen); } @@ -634,11 +670,9 @@ Mod_LoadEntities */ static void Mod_LoadEntities (lump_t *l) { + loadmodel->entities = NULL; if (!l->filelen) - { - loadmodel->entities = NULL; return; - } loadmodel->entities = Mem_Alloc(loadmodel->mempool, l->filelen); memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); if (loadmodel->ishlbsp) @@ -747,8 +781,7 @@ static void Mod_LoadTexinfo (lump_t *l) { texinfo_t *in; mtexinfo_t *out; - int i, j, k, count; - int miptex; + int i, j, k, count, miptex; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -768,18 +801,22 @@ static void Mod_LoadTexinfo (lump_t *l) miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); - if (!loadmodel->textures) - out->texture = &loadmodel->notexture; - else + out->texture = NULL; + if (loadmodel->textures) + { + if ((unsigned int) miptex >= (unsigned int) loadmodel->numtextures) + Con_Printf ("error in model \"%s\": invalid miptex index %i (of %i)\n", loadmodel->name, miptex, loadmodel->numtextures); + else + out->texture = loadmodel->textures[miptex]; + } + if (out->texture == NULL) { - if (miptex < 0) - Host_Error ("miptex < 0"); - if (miptex >= loadmodel->numtextures) - Host_Error ("miptex >= loadmodel->numtextures"); - out->texture = loadmodel->textures[miptex]; + // choose either the liquid notexture, or the normal notexture + if (out->flags & TEX_SPECIAL) + out->texture = loadmodel->textures[loadmodel->numtextures - 1]; + else + out->texture = loadmodel->textures[loadmodel->numtextures - 2]; } - if (!out->texture) - out->texture = &loadmodel->notexture; } } @@ -831,9 +868,6 @@ static void CalcSurfaceExtents (msurface_t *s) s->texturemins[i] = bmins[i] * 16; s->extents[i] = (bmaxs[i] - bmins[i]) * 16; -// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512) - if ((tex->flags & TEX_SPECIAL) == 0 && (s->extents[i]+1) > (256*16)) - Host_Error ("Bad surface extents"); } } @@ -858,6 +892,7 @@ void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) } } +#if 0 #define MAX_SUBDIVPOLYTRIANGLES 4096 #define MAX_SUBDIVPOLYVERTS (MAX_SUBDIVPOLYTRIANGLES * 3) @@ -965,32 +1000,26 @@ can be done reasonably. */ void Mod_GenerateWarpMesh (msurface_t *surf) { - int i, j; - surfvertex_t *v; - surfmesh_t *mesh; + int i, j; + surfvertex_t *v; + surfmesh_t *mesh; subdivpolytriangles = 0; subdivpolyverts = 0; SubdividePolygon (surf->poly_numverts, surf->poly_verts); + if (subdivpolytriangles < 1) + Host_Error("Mod_GenerateWarpMesh: no triangles?\n"); - mesh = &surf->mesh; + surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + subdivpolytriangles * sizeof(int[3]) + subdivpolyverts * sizeof(surfvertex_t)); mesh->numverts = subdivpolyverts; mesh->numtriangles = subdivpolytriangles; - if (mesh->numtriangles < 1) - Host_Error("Mod_GenerateWarpMesh: no triangles?\n"); - mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t)); - mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3])); + mesh->vertex = (surfvertex_t *)(mesh + 1); + mesh->index = (int *)(mesh->vertex + mesh->numverts); memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); for (i = 0;i < mesh->numtriangles;i++) - { for (j = 0;j < 3;j++) - { mesh->index[i*3+j] = subdivpolyindex[i][j]; - //if (mesh->index[i] < 0 || mesh->index[i] >= mesh->numverts) - // Host_Error("Mod_GenerateWarpMesh: invalid index generated\n"); - } - } for (i = 0, v = mesh->vertex;i < subdivpolyverts;i++, v++) { @@ -999,6 +1028,7 @@ void Mod_GenerateWarpMesh (msurface_t *surf) v->st[1] = DotProduct (v->v, surf->texinfo->vecs[1]); } } +#endif void Mod_GenerateVertexLitMesh (msurface_t *surf) { @@ -1007,17 +1037,16 @@ void Mod_GenerateVertexLitMesh (msurface_t *surf) surfvertex_t *out; surfmesh_t *mesh; - //surf->flags |= SURF_LIGHTMAP; smax = surf->extents[0] >> 4; tmax = surf->extents[1] >> 4; surf->lightmaptexturestride = 0; surf->lightmaptexture = NULL; - mesh = &surf->mesh; + surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t)); mesh->numverts = surf->poly_numverts; mesh->numtriangles = surf->poly_numverts - 2; - mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t)); - mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3])); + mesh->vertex = (surfvertex_t *)(mesh + 1); + mesh->index = (int *)(mesh->vertex + mesh->numverts); memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); index = mesh->index; @@ -1067,24 +1096,22 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf) if (r_miplightmaps.integer) { surf->lightmaptexturestride = (surf->extents[0]>>4)+1; - surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP/* | TEXF_PRECACHE*/, NULL, NULL, 0); + surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_PRECACHE); } else { surf->lightmaptexturestride = R_CompatibleFragmentWidth((surf->extents[0]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, 0); - surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT/* | TEXF_PRECACHE*/, NULL, NULL, 0); + surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE); } -// surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, va("lightmap%08x", lightmapnum), surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE); -// surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, va("lightmap%08x", lightmapnum), surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_PRECACHE); - R_GetFragmentLocation(surf->lightmaptexture, NULL, NULL, &xbase, &ybase, &xscale, &yscale); + R_FragmentLocation(surf->lightmaptexture, NULL, NULL, &xbase, &ybase, &xscale, &yscale); xscale = (xscale - xbase) * 16.0 / ((surf->extents[0] & ~15) + 16); yscale = (yscale - ybase) * 16.0 / ((surf->extents[1] & ~15) + 16); - mesh = &surf->mesh; + surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t)); mesh->numverts = surf->poly_numverts; mesh->numtriangles = surf->poly_numverts - 2; - mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t)); - mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3])); + mesh->vertex = (surfvertex_t *)(mesh + 1); + mesh->index = (int *)(mesh->vertex + mesh->numverts); memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); index = mesh->index; @@ -1121,6 +1148,39 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf) } } +void Mod_GenerateVertexMesh (msurface_t *surf) +{ + int i, *index; + float *in; + surfvertex_t *out; + surfmesh_t *mesh; + + surf->lightmaptexturestride = 0; + surf->lightmaptexture = NULL; + + surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t)); + mesh->numverts = surf->poly_numverts; + mesh->numtriangles = surf->poly_numverts - 2; + mesh->vertex = (surfvertex_t *)(mesh + 1); + mesh->index = (int *)(mesh->vertex + mesh->numverts); + memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); + + index = mesh->index; + for (i = 0;i < mesh->numtriangles;i++) + { + *index++ = 0; + *index++ = i + 1; + *index++ = i + 2; + } + + for (i = 0, in = surf->poly_verts, out = mesh->vertex;i < mesh->numverts;i++, in += 3, out++) + { + VectorCopy (in, out->v); + out->st[0] = (DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) / surf->texinfo->texture->width; + out->st[1] = (DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) / surf->texinfo->texture->height; + } +} + void Mod_GenerateSurfacePolygon (msurface_t *surf) { float *vert; @@ -1143,6 +1203,55 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf) } } +static void Mod_SplitSurfMeshIfTooBig(msurface_t *s) +{ + int j, base, tricount, newvertexcount, *index, *vertexremap; + surfmesh_t *newmesh, *oldmesh, *firstmesh; + if (s->mesh->numtriangles > 1000) + { + vertexremap = Mem_Alloc(tempmempool, s->mesh->numverts * sizeof(int)); + base = 0; + oldmesh = NULL; + firstmesh = NULL; + newmesh = NULL; + while (base < s->mesh->numtriangles) + { + tricount = s->mesh->numtriangles - base; + if (tricount > 1000) + tricount = 1000; + index = s->mesh->index + base * 3; + base += tricount; + + newvertexcount = 0; + memset(vertexremap, -1, s->mesh->numverts * sizeof(int)); + for (j = 0;j < tricount * 3;j++) + if (vertexremap[index[j]] < 0) + vertexremap[index[j]] = newvertexcount++; + + newmesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + newvertexcount * sizeof(surfvertex_t) + tricount * sizeof(int[3])); + newmesh->chain = NULL; + newmesh->numverts = newvertexcount; + newmesh->numtriangles = tricount; + newmesh->vertex = (surfvertex_t *)(newmesh + 1); + newmesh->index = (int *)(newmesh->vertex + newvertexcount); + for (j = 0;j < tricount * 3;j++) + { + newmesh->index[j] = vertexremap[index[j]]; + // yes this copies the same vertex multiple times in many cases... but that's ok... + memcpy(&newmesh->vertex[newmesh->index[j]], &s->mesh->vertex[index[j]], sizeof(surfvertex_t)); + } + if (oldmesh) + oldmesh->chain = newmesh; + else + firstmesh = newmesh; + oldmesh = newmesh; + } + Mem_Free(vertexremap); + Mem_Free(s->mesh); + s->mesh = firstmesh; + } +} + /* ================= Mod_LoadFaces @@ -1150,10 +1259,9 @@ Mod_LoadFaces */ static void Mod_LoadFaces (lump_t *l) { - dface_t *in; + dface_t *in; msurface_t *out; - int i, count, surfnum; - int planenum, side; + int i, count, surfnum, planenum, ssize, tsize; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -1169,13 +1277,20 @@ static void Mod_LoadFaces (lump_t *l) // FIXME: validate edges, texinfo, etc? out->firstedge = LittleLong(in->firstedge); out->numedges = LittleShort(in->numedges); + if ((unsigned int) out->firstedge + (unsigned int) out->numedges > (unsigned int) loadmodel->numsurfedges) + Host_Error("Mod_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)\n", out->firstedge, out->numedges, loadmodel->numsurfedges); - out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); + i = LittleShort (in->texinfo); + if ((unsigned int) i >= (unsigned int) loadmodel->numtexinfo) + Host_Error("Mod_LoadFaces: invalid texinfo index %i (model has %i texinfos)\n", i, loadmodel->numtexinfo); + out->texinfo = loadmodel->texinfo + i; out->flags = out->texinfo->texture->flags; planenum = LittleShort(in->planenum); - side = LittleShort(in->side); - if (side) + if ((unsigned int) planenum >= (unsigned int) loadmodel->numplanes) + Host_Error("Mod_LoadFaces: invalid plane index %i (model has %i planes)\n", planenum, loadmodel->numplanes); + + if (LittleShort(in->side)) out->flags |= SURF_PLANEBACK; out->plane = loadmodel->planes + planenum; @@ -1187,13 +1302,12 @@ static void Mod_LoadFaces (lump_t *l) out->cached_dlight = true; out->cached_ambient = -1000; out->cached_lightscalebit = -1000; - out->cached_light[0] = -1000; - out->cached_light[1] = -1000; - out->cached_light[2] = -1000; - out->cached_light[3] = -1000; CalcSurfaceExtents (out); + ssize = (out->extents[0] >> 4) + 1; + tsize = (out->extents[1] >> 4) + 1; + // lighting info for (i = 0;i < MAXLIGHTMAPS;i++) out->styles[i] = in->styles[i]; @@ -1210,42 +1324,53 @@ static void Mod_LoadFaces (lump_t *l) if (out->texinfo->texture->flags & SURF_DRAWSKY) { out->shader = &Cshader_sky; - Mod_GenerateWarpMesh (out); - continue; - } - - if (out->texinfo->texture->flags & SURF_DRAWTURB) - { - out->shader = &Cshader_water; - /* - for (i=0 ; i<2 ; i++) - { - out->extents[i] = 16384*1024; - out->texturemins[i] = -8192*1024; - } - */ - Mod_GenerateWarpMesh (out); - continue; + out->samples = NULL; + Mod_GenerateVertexMesh (out); } - - if (!R_TextureHasAlpha(out->texinfo->texture->texture)) - out->flags |= SURF_CLIPSOLID; - if (out->texinfo->flags & TEX_SPECIAL) + else if (out->texinfo->texture->flags & SURF_DRAWTURB) { - // qbsp couldn't find the texture for this surface, but it was either turb or sky... assume turb out->shader = &Cshader_water; - Mod_GenerateWarpMesh (out); - } - else if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer) - { - out->shader = &Cshader_wall_vertex; - Mod_GenerateVertexLitMesh(out); + out->samples = NULL; + Mod_GenerateVertexMesh (out); } else { - out->shader = &Cshader_wall_lightmap; - Mod_GenerateLightmappedMesh(out); + if (!R_TextureHasAlpha(out->texinfo->texture->texture)) + out->flags |= SURF_CLIPSOLID; + if (out->texinfo->flags & TEX_SPECIAL) + { + // qbsp couldn't find the texture for this surface, but it was either turb or sky... assume turb + out->shader = &Cshader_water; + out->shader = &Cshader_water; + out->samples = NULL; + Mod_GenerateVertexMesh (out); + } + else if ((out->extents[0] >> 4) + 1 > (256) || (out->extents[1] >> 4) + 1 > (256)) + { + Con_Printf ("Bad surface extents, converting to fullbright polygon"); + out->shader = &Cshader_wall_fullbright; + out->samples = NULL; + Mod_GenerateVertexMesh(out); + } + else + { + // stainmap for permanent marks on walls + out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3); + // clear to white + memset(out->stainsamples, 255, ssize * tsize * 3); + if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer) + { + out->shader = &Cshader_wall_vertex; + Mod_GenerateVertexLitMesh(out); + } + else + { + out->shader = &Cshader_wall_lightmap; + Mod_GenerateLightmappedMesh(out); + } + } } + Mod_SplitSurfMeshIfTooBig(out); } } @@ -1257,7 +1382,7 @@ static int Mod_SurfaceQSortCompare(const void *voida, const void *voidb) a = *((const msurface_t **)voida); b = *((const msurface_t **)voidb); if (a->shader != b->shader) - return (long) a->shader - (long) b->shader; + return (qbyte *) a->shader - (qbyte *) b->shader; if (a->texinfo->texture != b->texinfo->texture); return a->texinfo->texture - b->texinfo->texture; return 0; @@ -1271,7 +1396,8 @@ static void Mod_BrushSortedSurfaces(model_t *model, mempool_t *pool) for (surfnum = 0;surfnum < sortmodel->nummodelsurfaces;surfnum++) sortmodel->modelsortedsurfaces[surfnum] = &sortmodel->surfaces[surfnum + sortmodel->firstmodelsurface]; - qsort(sortmodel->modelsortedsurfaces, sortmodel->nummodelsurfaces, sizeof(msurface_t *), Mod_SurfaceQSortCompare); + if (r_sortsurfaces.integer) + qsort(sortmodel->modelsortedsurfaces, sortmodel->nummodelsurfaces, sizeof(msurface_t *), Mod_SurfaceQSortCompare); } @@ -1380,15 +1506,7 @@ static void Mod_LoadLeafs (lump_t *l) 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; - } - */ + // FIXME: Insert caustics here } } @@ -1425,6 +1543,7 @@ static void Mod_LoadClipnodes (lump_t *l) hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 36; + VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size); hull = &loadmodel->hulls[2]; hull->clipnodes = out; @@ -1437,6 +1556,7 @@ static void Mod_LoadClipnodes (lump_t *l) hull->clip_maxs[0] = 32; hull->clip_maxs[1] = 32; hull->clip_maxs[2] = 32; + VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size); hull = &loadmodel->hulls[3]; hull->clipnodes = out; @@ -1449,6 +1569,7 @@ static void Mod_LoadClipnodes (lump_t *l) hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 18; + VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size); } else { @@ -1463,6 +1584,7 @@ static void Mod_LoadClipnodes (lump_t *l) hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 32; + VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size); hull = &loadmodel->hulls[2]; hull->clipnodes = out; @@ -1475,6 +1597,7 @@ static void Mod_LoadClipnodes (lump_t *l) hull->clip_maxs[0] = 32; hull->clip_maxs[1] = 32; hull->clip_maxs[2] = 64; + VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size); } for (i=0 ; inormal[2] = LittleFloat (in->normal[2]); out->dist = LittleFloat (in->dist); - // LordHavoc: recalculated by PlaneClassify, FIXME: validate type and report error if type does not match normal? -// out->type = LittleLong (in->type); PlaneClassify(out); } } @@ -1601,16 +1722,11 @@ static void Mod_LoadPlanes (lump_t *l) typedef struct { int numpoints; + int padding; double points[8][3]; // variable sized } winding_t; -typedef struct -{ - int numpoints; -} -windingsizeof_t; - /* ================== NewWinding @@ -1622,10 +1738,10 @@ static winding_t *NewWinding (int points) int size; if (points > MAX_POINTS_ON_WINDING) - Host_Error("NewWinding: too many points\n"); + Sys_Error("NewWinding: too many points\n"); - size = sizeof(windingsizeof_t) + sizeof(double[3]) * points; - w = Mem_Alloc(tempmempool, size); + size = sizeof(winding_t) + sizeof(double[3]) * (points - 8); + w = Mem_Alloc(loadmodel->mempool, size); memset (w, 0, size); return w; @@ -1725,10 +1841,16 @@ static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) return in; maxpts = in->numpoints+4; // can't use counts[0]+2 because of fp grouping errors + if (maxpts > MAX_POINTS_ON_WINDING) + Sys_Error ("ClipWinding: maxpts > MAX_POINTS_ON_WINDING"); + neww = NewWinding (maxpts); for (i = 0;i < in->numpoints;i++) { + if (neww->numpoints >= maxpts) + Sys_Error ("ClipWinding: points exceeded estimate"); + p1 = in->points[i]; if (sides[i] == SIDE_ON) @@ -1765,9 +1887,6 @@ static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) neww->numpoints++; } - if (neww->numpoints > maxpts) - Host_Error ("ClipWinding: points exceeded estimate"); - // free the original winding FreeWinding (in); @@ -1828,11 +1947,17 @@ static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, wi maxpts = in->numpoints+4; // can't use counts[0]+2 because of fp grouping errors + if (maxpts > MAX_POINTS_ON_WINDING) + Sys_Error ("ClipWinding: maxpts > MAX_POINTS_ON_WINDING"); + *front = f = NewWinding (maxpts); *back = b = NewWinding (maxpts); for (i = 0;i < in->numpoints;i++) { + if (f->numpoints >= maxpts || b->numpoints >= maxpts) + Sys_Error ("DivideWinding: points exceeded estimate"); + p1 = in->points[i]; if (sides[i] == SIDE_ON) @@ -1877,9 +2002,6 @@ static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, wi VectorCopy (mid, b->points[b->numpoints]); b->numpoints++; } - - if (f->numpoints > maxpts || b->numpoints > maxpts) - Host_Error ("DivideWinding: points exceeded estimate"); } typedef struct portal_s @@ -1902,8 +2024,7 @@ AllocPortal static portal_t *AllocPortal (void) { portal_t *p; - p = Mem_Alloc(tempmempool, sizeof(portal_t)); - //memset(p, 0, sizeof(portal_t)); + p = Mem_Alloc(loadmodel->mempool, sizeof(portal_t)); p->chain = portalchain; portalchain = p; return p; @@ -1945,8 +2066,8 @@ static void Mod_FinalizePortals(void) endleaf = leaf + loadmodel->numleafs; for (;leaf < endleaf;leaf++) { - VectorSet( 2000000000, 2000000000, 2000000000, leaf->mins); - VectorSet(-2000000000, -2000000000, -2000000000, leaf->maxs); + VectorSet(leaf->mins, 2000000000, 2000000000, 2000000000); + VectorSet(leaf->maxs, -2000000000, -2000000000, -2000000000); } p = portalchain; while(p) @@ -1992,7 +2113,7 @@ static void Mod_FinalizePortals(void) } loadmodel->portals = Mem_Alloc(loadmodel->mempool, numportals * sizeof(mportal_t) + numpoints * sizeof(mvertex_t)); loadmodel->numportals = numportals; - loadmodel->portalpoints = (void *) ((long) loadmodel->portals + numportals * sizeof(mportal_t)); + loadmodel->portalpoints = (void *) ((qbyte *) loadmodel->portals + numportals * sizeof(mportal_t)); loadmodel->numportalpoints = numpoints; // clear all leaf portal chains for (i = 0;i < loadmodel->numleafs;i++) @@ -2146,8 +2267,6 @@ static void Mod_RecursiveNodePortals (mnode_t *node) portal_t *portal, *nextportal, *nodeportal, *splitportal, *temp; winding_t *nodeportalwinding, *frontwinding, *backwinding; - // CheckLeafPortalConsistancy (node); - // if a leaf, we're done if (node->contents) return; @@ -2259,52 +2378,10 @@ static void Mod_RecursiveNodePortals (mnode_t *node) Mod_RecursiveNodePortals(back); } -/* -void Mod_MakeOutsidePortals(mnode_t *node) -{ - int i, j; - portal_t *p, *portals[6]; - mnode_t *outside_node; - - outside_node = Mem_Alloc(loadmodel->mempool, sizeof(mnode_t)); - outside_node->contents = CONTENTS_SOLID; - outside_node->portals = NULL; - - for (i = 0;i < 3;i++) - { - for (j = 0;j < 2;j++) - { - portals[j*3 + i] = p = AllocPortal (); - memset (&p->plane, 0, sizeof(mplane_t)); - p->plane.normal[i] = j ? -1 : 1; - p->plane.dist = -65536; - p->winding = BaseWindingForPlane (&p->plane); - if (j) - AddPortalToNodes (p, outside_node, node); - else - AddPortalToNodes (p, node, outside_node); - } - } - - // clip the basewindings by all the other planes - for (i = 0;i < 6;i++) - { - for (j = 0;j < 6;j++) - { - if (j == i) - continue; - portals[i]->winding = ClipWinding (portals[i]->winding, &portals[j]->plane, true); - } - } -} -*/ static void Mod_MakePortals(void) { -// Con_Printf("building portals for %s\n", loadmodel->name); - portalchain = NULL; -// Mod_MakeOutsidePortals (loadmodel->nodes); Mod_RecursiveNodePortals (loadmodel->nodes); Mod_FinalizePortals(); } @@ -2320,6 +2397,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) dheader_t *header; dmodel_t *bm; mempool_t *mainmempool; + char *loadname; mod->type = mod_brush; @@ -2327,13 +2405,13 @@ void Mod_LoadBrushModel (model_t *mod, void *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); + Host_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i (Quake) or 30 (HalfLife))", mod->name, i, BSPVERSION); mod->ishlbsp = i == 30; if (loadmodel->isworldmodel) Cvar_SetValue("halflifebsp", mod->ishlbsp); // swap all the lumps - mod_base = (byte *)header; + mod_base = (qbyte *)header; for (i=0 ; ilightmaprgba = r_lightmaprgba.integer; -// Mem_CheckSentinelsGlobal(); - // LordHavoc: had to move entity loading above everything to allow parsing various settings from worldspawn Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadEdges (&header->lumps[LUMP_EDGES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); -// Mem_CheckSentinelsGlobal(); Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); -// Mem_CheckSentinelsGlobal(); Mod_LoadFaces (&header->lumps[LUMP_FACES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); -// Mem_CheckSentinelsGlobal(); Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); -// Mem_CheckSentinelsGlobal(); Mod_LoadNodes (&header->lumps[LUMP_NODES]); -// Mem_CheckSentinelsGlobal(); Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); -// Mem_CheckSentinelsGlobal(); -// Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); -// Mem_CheckSentinelsGlobal(); Mod_MakeHull0 (); -// Mem_CheckSentinelsGlobal(); Mod_MakePortals(); -// Mem_CheckSentinelsGlobal(); mod->numframes = 2; // regular and alternate animation mainmempool = mod->mempool; + loadname = mod->name; + + Mod_LoadLightList (); // // set up the submodels (FIXME: this is confusing) @@ -2447,16 +2508,20 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) 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); + // LordHavoc: check for empty submodels (lacrima.bsp has such a glitch) + if (mod->normalmins[0] > mod->normalmaxs[0] || mod->normalmins[1] > mod->normalmaxs[1] || mod->normalmins[2] > mod->normalmaxs[2]) + { + Con_Printf("warning: empty submodel *%i in %s\n", i+1, loadname); + VectorClear(mod->normalmins); + VectorClear(mod->normalmaxs); + VectorClear(mod->yawmins); + VectorClear(mod->yawmaxs); + VectorClear(mod->rotatedmins); + VectorClear(mod->rotatedmaxs); + } mod->numleafs = bm->visleafs; - mod->SERAddEntity = Mod_Brush_SERAddEntity; mod->Draw = R_DrawBrushModelNormal; mod->DrawShadow = NULL; @@ -2478,5 +2543,5 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod = loadmodel; } } -// Mem_CheckSentinelsGlobal(); } +