X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=model_brush.c;h=79be4373212982d91f523c03ce38bdab4431824e;hb=1fdb85e19b37eb797e3b1118b844c7071e9cdefb;hp=5aecaa77587a1d5203d0a2fed89a23e94b5be4d9;hpb=ae9ed9b6acd2b4f0052ae163904b13506a1199a0;p=xonotic%2Fdarkplaces.git diff --git a/model_brush.c b/model_brush.c index 5aecaa77..79be4373 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" +// note: model_shared.c sets up r_notexture, and r_surf_notexture + qbyte mod_novis[(MAX_MAP_LEAFS + 7)/ 8]; -cvar_t r_subdivide_size = {CVAR_SAVE, "r_subdivide_size", "128"}; +//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", "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) { - R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL); + 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) +{ + int i; + for (i = 0;i < NUM_DETAILTEXTURES;i++) + R_FreeTexture(detailtextures[i]); + R_FreeTexturePool(&detailtexturepool); } /* @@ -60,8 +114,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,32 +138,6 @@ 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 -} -*/ /* =================== @@ -128,18 +154,6 @@ static qbyte *Mod_DecompressVis (qbyte *in, model_t *model) 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) @@ -167,40 +181,6 @@ qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) return Mod_DecompressVis (leaf->compressed_vis, model); } -void Mod_SetupNoTexture(void) -{ - int x, y; - qbyte 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 +188,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; - qbyte *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 *)((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 +242,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); + { + 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 +343,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 +384,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 +406,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 +435,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]; + } + } } } } @@ -614,11 +648,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); } @@ -693,11 +725,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) @@ -806,8 +836,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)) @@ -827,18 +856,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; } } @@ -914,6 +947,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) @@ -1021,9 +1055,9 @@ 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; @@ -1039,14 +1073,8 @@ void Mod_GenerateWarpMesh (msurface_t *surf) 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++) { @@ -1055,6 +1083,7 @@ void Mod_GenerateWarpMesh (msurface_t *surf) v->st[1] = DotProduct (v->v, surf->texinfo->vecs[1]); } } +#endif void Mod_GenerateVertexLitMesh (msurface_t *surf) { @@ -1063,7 +1092,6 @@ 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; @@ -1091,6 +1119,9 @@ void Mod_GenerateVertexLitMesh (msurface_t *surf) 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->ab[0] = s * (1.0f / 16.0f); + out->ab[1] = t * (1.0f / 16.0f); + out->st[0] = s / surf->texinfo->texture->width; out->st[1] = t / surf->texinfo->texture->height; @@ -1123,15 +1154,13 @@ 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_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); @@ -1158,6 +1187,9 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf) 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->ab[0] = s * (1.0f / 16.0f); + out->ab[1] = t * (1.0f / 16.0f); + out->st[0] = s / surf->texinfo->texture->width; out->st[1] = t / surf->texinfo->texture->height; @@ -1180,7 +1212,7 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf) void Mod_GenerateVertexMesh (msurface_t *surf) { int i, *index; - float *in; + float *in, s, t; surfvertex_t *out; surfmesh_t *mesh; @@ -1205,17 +1237,19 @@ void Mod_GenerateVertexMesh (msurface_t *surf) 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; + 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; + out->ab[0] = s * (1.0f / 16.0f); + out->ab[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; @@ -1230,6 +1264,20 @@ 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; + } + 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; } static void Mod_SplitSurfMeshIfTooBig(msurface_t *s) @@ -1239,7 +1287,6 @@ static void Mod_SplitSurfMeshIfTooBig(msurface_t *s) if (s->mesh->numtriangles > 1000) { vertexremap = Mem_Alloc(tempmempool, s->mesh->numverts * sizeof(int)); - memset(vertexremap, -1, s->mesh->numverts * sizeof(int)); base = 0; oldmesh = NULL; firstmesh = NULL; @@ -1253,6 +1300,7 @@ static void Mod_SplitSurfMeshIfTooBig(msurface_t *s) 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++; @@ -1288,9 +1336,9 @@ Mod_LoadFaces */ static void Mod_LoadFaces (lump_t *l) { - dface_t *in; + dface_t *in; msurface_t *out; - int i, count, surfnum, planenum, side, ssize, tsize; + int i, count, surfnum, planenum, ssize, tsize; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -1306,13 +1354,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; @@ -1347,20 +1402,13 @@ static void Mod_LoadFaces (lump_t *l) { out->shader = &Cshader_sky; out->samples = NULL; - Mod_GenerateWarpMesh (out); + Mod_GenerateVertexMesh (out); } else 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); + Mod_GenerateVertexMesh (out); } else { @@ -1372,9 +1420,9 @@ static void Mod_LoadFaces (lump_t *l) out->shader = &Cshader_water; out->shader = &Cshader_water; out->samples = NULL; - Mod_GenerateWarpMesh (out); + Mod_GenerateVertexMesh (out); } - else if ((out->extents[0]+1) > (256*16) || (out->extents[1]+1) > (256*16)) + 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; @@ -1425,7 +1473,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); } @@ -1534,15 +1583,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 } } @@ -1749,8 +1790,6 @@ static void Mod_LoadPlanes (lump_t *l) out->normal[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); } } @@ -1928,9 +1967,6 @@ static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) // free the original winding FreeWinding (in); - // debugging - //Mem_CheckSentinels(neww); - return neww; } @@ -2043,10 +2079,6 @@ static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, wi VectorCopy (mid, b->points[b->numpoints]); b->numpoints++; } - - // debugging - //Mem_CheckSentinels(f); - //Mem_CheckSentinels(b); } typedef struct portal_s @@ -2070,7 +2102,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; @@ -2107,8 +2138,6 @@ 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; @@ -2142,8 +2171,6 @@ static void Mod_FinalizePortals(void) Mod_RecursiveRecalcNodeBBox(loadmodel->nodes); - //Mem_CheckSentinelsGlobal(); - // tally up portal and point counts p = portalchain; numportals = 0; @@ -2234,8 +2261,6 @@ static void Mod_FinalizePortals(void) FreePortal(p); p = pnext; } - - //Mem_CheckSentinelsGlobal(); } /* @@ -2319,8 +2344,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; @@ -2338,7 +2361,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]) { @@ -2433,52 +2455,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(); } @@ -2502,7 +2482,7 @@ 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); @@ -2518,44 +2498,24 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) // store which lightmap format to use mod->lightmaprgba = 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 @@ -2625,7 +2585,6 @@ 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; // 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]) { @@ -2636,17 +2595,10 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) VectorClear(mod->yawmaxs); VectorClear(mod->rotatedmins); VectorClear(mod->rotatedmaxs); - //mod->modelradius = 0; } -// VectorCopy (bm->maxs, mod->maxs); -// VectorCopy (bm->mins, mod->mins); - -// mod->radius = RadiusFromBounds (mod->mins, mod->maxs); - mod->numleafs = bm->visleafs; - mod->SERAddEntity = Mod_Brush_SERAddEntity; mod->Draw = R_DrawBrushModelNormal; mod->DrawShadow = NULL; @@ -2668,5 +2620,5 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod = loadmodel; } } -// Mem_CheckSentinelsGlobal(); } +