X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_brush.c;h=edcb60930aff8f03c1e89c331adf28e83ddcf751;hp=da5809be7158132911bbc56b2fa3c95d0ab1fdf7;hb=ada6778a14d4ccecf7d2de73aa7816865d297399;hpb=6474fce0b19926a8f531ce83f4c127920b1dc8cc diff --git a/model_brush.c b/model_brush.c index da5809be..edcb6093 100644 --- a/model_brush.c +++ b/model_brush.c @@ -20,14 +20,22 @@ 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"}; + +#define NUM_DETAILTEXTURES 1 +static rtexture_t *detailtextures[NUM_DETAILTEXTURES]; +static rtexturepool_t *detailtexturepool; /* =============== @@ -36,18 +44,64 @@ 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) +void Mod_BrushStartup (void) +{ + int i, x, y, light; + float vc[3], vx[3], vy[3], vn[3], lightdir[3]; +#define DETAILRESOLUTION 256 + qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION]; + detailtexturepool = R_AllocTexturePool(); + lightdir[0] = 0.5; + lightdir[1] = 1; + lightdir[2] = -0.25; + VectorNormalize(lightdir); + for (i = 0;i < NUM_DETAILTEXTURES;i++) + { + fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4); + for (y = 0;y < DETAILRESOLUTION;y++) + { + for (x = 0;x < DETAILRESOLUTION;x++) + { + vc[0] = x; + vc[1] = y; + vc[2] = noise[y][x] * (1.0f / 32.0f); + vx[0] = x + 1; + vx[1] = y; + vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f); + vy[0] = x; + vy[1] = y + 1; + vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f); + VectorSubtract(vx, vc, vx); + VectorSubtract(vy, vc, vy); + CrossProduct(vx, vy, vn); + VectorNormalize(vn); + light = 128 - DotProduct(vn, lightdir) * 128; + light = bound(0, light, 255); + data[y][x][0] = data[y][x][1] = data[y][x][2] = light; + data[y][x][3] = 255; + } + } + detailtextures[i] = R_LoadTexture(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE); + } +} + +void Mod_BrushShutdown (void) { - R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL); + int i; + for (i = 0;i < NUM_DETAILTEXTURES;i++) + R_FreeTexture(detailtextures[i]); + R_FreeTexturePool(&detailtexturepool); } /* @@ -55,13 +109,14 @@ void Mod_Brush_SERAddEntity(void) Mod_PointInLeaf =============== */ -mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) +mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) { - mnode_t *node; + mnode_t *node; + + if (model == NULL) + return NULL; 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 @@ -72,74 +127,54 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) return (mleaf_t *)node; } +int Mod_PointContents (const vec3_t p, model_t *model) +{ + mnode_t *node; + + if (model == NULL) + return CONTENTS_EMPTY; + + Mod_CheckLoaded(model); + + // LordHavoc: modified to start at first clip node, + // in other words: first node of the (sub)model + node = model->nodes + model->hulls[0].firstclipnode; + while (node->contents == 0) + node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist]; + + return ((mleaf_t *)node)->contents; +} + void Mod_FindNonSolidLocation(vec3_t pos, model_t *mod) { - if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[0]-=1;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[0]+=2;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; + if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[0]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[0]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; pos[0]-=1; - pos[1]-=1;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[1]+=2;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; + pos[1]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[1]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; pos[1]-=1; - pos[2]-=1;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; - pos[2]+=2;if (Mod_PointInLeaf(pos, mod)->contents != CONTENTS_SOLID) return; + pos[2]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; + pos[2]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return; 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 +195,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 +209,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 +263,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]) + { + 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) { - data = loadimagepixels(tx->name, false, 0, 0); - if (data) + 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 +364,7 @@ static void Mod_LoadTextures (lump_t *l) { tx->width = 16; tx->height = 16; - tx->texture = loadmodel->notexture.texture; + tx->texture = r_notexture; } } else @@ -390,7 +405,7 @@ static void Mod_LoadTextures (lump_t *l) { tx->width = 16; tx->height = 16; - tx->texture = loadmodel->notexture.texture; + tx->texture = r_notexture; } } } @@ -412,23 +427,22 @@ static void Mod_LoadTextures (lump_t *l) if (!R_TextureHasAlpha(tx->texture)) tx->flags |= SURF_CLIPSOLID; } + + tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES]; } -// -// 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 +456,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 +541,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 +555,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 +601,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 +669,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 +746,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 +857,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 +877,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; } } @@ -855,6 +968,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) @@ -962,32 +1076,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++) { @@ -996,93 +1104,53 @@ void Mod_GenerateWarpMesh (msurface_t *surf) v->st[1] = DotProduct (v->v, surf->texinfo->vecs[1]); } } +#endif -void Mod_GenerateVertexLitMesh (msurface_t *surf) +void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly) { - int i, is, it, *index, smax, tmax; - float *in, s, t; - surfvertex_t *out; - surfmesh_t *mesh; + int i, iu, iv, *index, smax, tmax; + float *in, s, t, u, v, ubase, vbase, uscale, vscale; + 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; - 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])); - memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); - - index = mesh->index; - for (i = 0;i < mesh->numtriangles;i++) + if (vertexonly) { - *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); - - s = DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; - t = DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; - - out->st[0] = s / surf->texinfo->texture->width; - out->st[1] = t / surf->texinfo->texture->height; - - s = (s + 8 - surf->texturemins[0]) * (1.0 / 16.0); - t = (t + 8 - surf->texturemins[1]) * (1.0 / 16.0); - - // lightmap coordinates - out->uv[0] = 0; - out->uv[1] = 0; - - // LordHavoc: calc lightmap data offset for vertex lighting to use - is = (int) s; - it = (int) t; - is = bound(0, is, smax); - it = bound(0, it, tmax); - out->lightmapoffset = ((it * (smax+1) + is) * 3); - } -} - -void Mod_GenerateLightmappedMesh (msurface_t *surf) -{ - int i, is, it, *index, smax, tmax; - float *in, s, t, xbase, ybase, xscale, yscale; - surfvertex_t *out; - surfmesh_t *mesh; - - surf->flags |= SURF_LIGHTMAP; - smax = surf->extents[0] >> 4; - tmax = surf->extents[1] >> 4; - 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->lightmaptexturestride = 0; + surf->lightmaptexture = NULL; + uscale = 0; + vscale = 0; + ubase = 0; + vbase = 0; } 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->flags |= SURF_LIGHTMAP; + if (r_miplightmaps.integer) + { + surf->lightmaptexturestride = (surf->extents[0]>>4)+1; + 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_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE); + } + R_FragmentLocation(surf->lightmaptexture, NULL, NULL, &ubase, &vbase, &uscale, &vscale); + uscale = (uscale - ubase) * 16.0 / ((surf->extents[0] & ~15) + 16); + vscale = (vscale - vbase) * 16.0 / ((surf->extents[1] & ~15) + 16); } -// 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); - 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 * (4 + 2 + 2 + 2 + 1) * sizeof(float)); 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])); - memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); + mesh->verts = (float *)(mesh + 1); + mesh->st = mesh->verts + mesh->numverts * 4; + mesh->uv = mesh->st + mesh->numverts * 2; + mesh->ab = mesh->uv + mesh->numverts * 2; + mesh->lightmapoffsets = (int *)(mesh->ab + mesh->numverts * 2); + mesh->index = mesh->lightmapoffsets + mesh->numverts; index = mesh->index; for (i = 0;i < mesh->numtriangles;i++) @@ -1092,48 +1160,47 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf) *index++ = i + 2; } - for (i = 0, in = surf->poly_verts, out = mesh->vertex;i < mesh->numverts;i++, in += 3, out++) + for (i = 0, in = surf->poly_verts;i < mesh->numverts;i++, in += 3) { - VectorCopy (in, out->v); - - s = DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; - t = DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; - - out->st[0] = s / surf->texinfo->texture->width; - out->st[1] = t / surf->texinfo->texture->height; - - s = (s + 8 - surf->texturemins[0]) * (1.0 / 16.0); - t = (t + 8 - surf->texturemins[1]) * (1.0 / 16.0); - - // lightmap coordinates - out->uv[0] = s * xscale + xbase; - out->uv[1] = t * yscale + ybase; - + s = DotProduct (in, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; + t = DotProduct (in, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; + u = (s + 8 - surf->texturemins[0]) * (1.0 / 16.0) * uscale + ubase; + v = (t + 8 - surf->texturemins[1]) * (1.0 / 16.0) * vscale + vbase; // LordHavoc: calc lightmap data offset for vertex lighting to use - is = (int) s; - it = (int) t; - is = bound(0, is, smax); - it = bound(0, it, tmax); - out->lightmapoffset = ((it * (smax+1) + is) * 3); + iu = (int) u; + iv = (int) v; + iu = bound(0, iu, smax); + iv = bound(0, iv, tmax); + + mesh->verts[i * 4 + 0] = in[0]; + mesh->verts[i * 4 + 1] = in[1]; + mesh->verts[i * 4 + 2] = in[2]; + mesh->st[i * 2 + 0] = s / surf->texinfo->texture->width; + mesh->st[i * 2 + 1] = t / surf->texinfo->texture->height; + mesh->uv[i * 2 + 0] = u; + mesh->uv[i * 2 + 1] = v; + mesh->ab[i * 2 + 0] = s * (1.0f / 16.0f); + mesh->ab[i * 2 + 1] = t * (1.0f / 16.0f); + mesh->lightmapoffsets[i] = ((iv * (smax+1) + iu) * 3); } } void Mod_GenerateVertexMesh (msurface_t *surf) { - int i, *index; - float *in; - surfvertex_t *out; - surfmesh_t *mesh; + int i, *index; + float *in, s, t; + surfmesh_t *mesh; 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 * (4 + 2 + 2) * sizeof(float)); 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])); - memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); + mesh->verts = (float *)(mesh + 1); + mesh->st = mesh->verts + mesh->numverts * 4; + mesh->ab = mesh->st + mesh->numverts * 2; + mesh->index = (int *)(mesh->ab + mesh->numverts * 2); index = mesh->index; for (i = 0;i < mesh->numtriangles;i++) @@ -1143,20 +1210,24 @@ void Mod_GenerateVertexMesh (msurface_t *surf) *index++ = i + 2; } - for (i = 0, in = surf->poly_verts, out = mesh->vertex;i < mesh->numverts;i++, in += 3, out++) + for (i = 0, in = surf->poly_verts;i < mesh->numverts;i++, in += 3) { - 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; + s = (DotProduct (in, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]); + t = (DotProduct (in, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]); + mesh->verts[i * 4 + 0] = in[0]; + mesh->verts[i * 4 + 1] = in[1]; + mesh->verts[i * 4 + 2] = in[2]; + mesh->st[i * 2 + 0] = s / surf->texinfo->texture->width; + mesh->st[i * 2 + 1] = t / surf->texinfo->texture->height; + mesh->ab[i * 2 + 0] = s * (1.0f / 16.0f); + mesh->ab[i * 2 + 1] = t * (1.0f / 16.0f); } } void Mod_GenerateSurfacePolygon (msurface_t *surf) { - float *vert; - int i; - int lindex; - float *vec; + int i, lindex; + float *vec, *vert, mins[3], maxs[3]; // convert edges back to a normal polygon surf->poly_numverts = surf->numedges; @@ -1171,6 +1242,22 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf) VectorCopy (vec, vert); vert += 3; } + vert = surf->poly_verts; + VectorCopy(vert, mins); + VectorCopy(vert, maxs); + vert += 3; + for (i = 1;i < surf->poly_numverts;i++) + { + if (mins[0] > vert[0]) mins[0] = vert[0];if (maxs[0] < vert[0]) maxs[0] = vert[0]; + if (mins[1] > vert[1]) mins[1] = vert[1];if (maxs[1] < vert[1]) maxs[1] = vert[1]; + if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2]; + vert += 3; + } + VectorCopy(mins, surf->poly_mins); + VectorCopy(maxs, surf->poly_maxs); + surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f; + surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f; + surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f; } /* @@ -1180,10 +1267,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)) @@ -1199,13 +1285,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; @@ -1217,13 +1310,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]; @@ -1241,80 +1333,54 @@ static void Mod_LoadFaces (lump_t *l) { out->shader = &Cshader_sky; out->samples = NULL; - 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; - } - */ - out->samples = NULL; - Mod_GenerateWarpMesh (out); - continue; + 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; out->samples = NULL; - Mod_GenerateWarpMesh (out); - } - else if ((out->extents[0]+1) > (256*16) || (out->extents[1]+1) > (256*16)) - { - Con_Printf ("Bad surface extents, converting to fullbright polygon"); - out->shader = &Cshader_wall_fullbright; - out->samples = NULL; - Mod_GenerateVertexMesh(out); - } - else if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer) - { - out->shader = &Cshader_wall_vertex; - Mod_GenerateVertexLitMesh(out); + 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_GenerateWallMesh (out, true); + } + else + { + out->shader = &Cshader_wall_lightmap; + Mod_GenerateWallMesh (out, false); + } + } } } } -static model_t *sortmodel; - -static int Mod_SurfaceQSortCompare(const void *voida, const void *voidb) -{ - const msurface_t *a, *b; - a = *((const msurface_t **)voida); - b = *((const msurface_t **)voidb); - if (a->shader != b->shader) - return (long) a->shader - (long) b->shader; - if (a->texinfo->texture != b->texinfo->texture); - return a->texinfo->texture - b->texinfo->texture; - return 0; -} - -static void Mod_BrushSortedSurfaces(model_t *model, mempool_t *pool) -{ - int surfnum; - sortmodel = model; - sortmodel->modelsortedsurfaces = Mem_Alloc(pool, sortmodel->nummodelsurfaces * sizeof(msurface_t *)); - 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); -} - - /* ================= Mod_SetParent @@ -1420,15 +1486,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 } } @@ -1465,6 +1523,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; @@ -1477,6 +1536,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; @@ -1489,6 +1549,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 { @@ -1503,6 +1564,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; @@ -1515,6 +1577,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); } } @@ -1731,9 +1792,6 @@ static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) winding_t *neww; int maxpts; - // debugging - Mem_CheckSentinels(in); - counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0; // determine sides for each point @@ -1773,15 +1831,12 @@ static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) if (neww->numpoints >= maxpts) Sys_Error ("ClipWinding: points exceeded estimate"); - Mem_CheckSentinels(neww); - p1 = in->points[i]; if (sides[i] == SIDE_ON) { VectorCopy (p1, neww->points[neww->numpoints]); neww->numpoints++; - Mem_CheckSentinels(neww); continue; } @@ -1789,7 +1844,6 @@ static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) { VectorCopy (p1, neww->points[neww->numpoints]); neww->numpoints++; - Mem_CheckSentinels(neww); } if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) @@ -1811,15 +1865,11 @@ static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) VectorCopy (mid, neww->points[neww->numpoints]); neww->numpoints++; - Mem_CheckSentinels(neww); } // free the original winding FreeWinding (in); - // debugging - Mem_CheckSentinels(neww); - return neww; } @@ -1846,9 +1896,6 @@ static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, wi winding_t *f, *b; int maxpts; - // debugging - Mem_CheckSentinels(in); - counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0; // determine sides for each point @@ -1897,10 +1944,8 @@ static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, wi { VectorCopy (p1, f->points[f->numpoints]); f->numpoints++; - Mem_CheckSentinels(f); VectorCopy (p1, b->points[b->numpoints]); b->numpoints++; - Mem_CheckSentinels(b); continue; } @@ -1908,13 +1953,11 @@ static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, wi { VectorCopy (p1, f->points[f->numpoints]); f->numpoints++; - Mem_CheckSentinels(f); } else if (sides[i] == SIDE_BACK) { VectorCopy (p1, b->points[b->numpoints]); b->numpoints++; - Mem_CheckSentinels(b); } if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) @@ -1936,15 +1979,9 @@ static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, wi VectorCopy (mid, f->points[f->numpoints]); f->numpoints++; - Mem_CheckSentinels(f); VectorCopy (mid, b->points[b->numpoints]); b->numpoints++; - Mem_CheckSentinels(b); } - - // debugging - Mem_CheckSentinels(front); - Mem_CheckSentinels(back); } typedef struct portal_s @@ -1968,7 +2005,6 @@ static portal_t *AllocPortal (void) { portal_t *p; p = Mem_Alloc(loadmodel->mempool, sizeof(portal_t)); - //memset(p, 0, sizeof(portal_t)); p->chain = portalchain; portalchain = p; return p; @@ -2005,15 +2041,13 @@ static void Mod_FinalizePortals(void) mleaf_t *leaf, *endleaf; winding_t *w; - Mem_CheckSentinelsGlobal(); - // 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); + VectorSet(leaf->mins, 2000000000, 2000000000, 2000000000); + VectorSet(leaf->maxs, -2000000000, -2000000000, -2000000000); } p = portalchain; while(p) @@ -2040,8 +2074,6 @@ static void Mod_FinalizePortals(void) Mod_RecursiveRecalcNodeBBox(loadmodel->nodes); - Mem_CheckSentinelsGlobal(); - // tally up portal and point counts p = portalchain; numportals = 0; @@ -2061,7 +2093,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++) @@ -2132,8 +2164,6 @@ static void Mod_FinalizePortals(void) FreePortal(p); p = pnext; } - - Mem_CheckSentinelsGlobal(); } /* @@ -2217,8 +2247,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; @@ -2236,7 +2264,6 @@ static void Mod_RecursiveNodePortals (mnode_t *node) nodeportal->plane = *node->plane; nodeportalwinding = BaseWindingForPlane (node->plane); - Mem_CheckSentinels(nodeportalwinding); side = 0; // shut up compiler warning for (portal = (portal_t *)node->portals;portal;portal = portal->next[side]) { @@ -2331,52 +2358,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(); } @@ -2392,6 +2377,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) dheader_t *header; dmodel_t *bm; mempool_t *mainmempool; + char *loadname; mod->type = mod_brush; @@ -2399,13 +2385,17 @@ 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); + // until we get a texture for it... + R_ResetQuakeSky(); + } // 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) @@ -2519,21 +2492,23 @@ 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; - Mod_BrushSortedSurfaces(mod, mainmempool); - // LordHavoc: only register submodels if it is the world // (prevents bsp models from replacing world submodels) if (loadmodel->isworldmodel && i < (mod->numsubmodels - 1)) @@ -2550,5 +2525,5 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod = loadmodel; } } -// Mem_CheckSentinelsGlobal(); } +