X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_brush.c;h=d7825c7a0c9ac7b7bdf9a7cb6ed7b03d877a0e51;hp=3296a68da26c9597559b9167b8e4f3a6a0946751;hb=817897f7c12e5603ab6b7daf550e1abf27512781;hpb=6fb3daf04a26ac42b15c02c2276f6820ffe795a8 diff --git a/model_brush.c b/model_brush.c index 3296a68d..d7825c7a 100644 --- a/model_brush.c +++ b/model_brush.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "image.h" +#include "r_shadow.h" // note: model_shared.c sets up r_notexture, and r_surf_notexture @@ -33,10 +34,6 @@ cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1"}; 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; - /* =============== Mod_BrushInit @@ -54,55 +51,6 @@ void Mod_BrushInit (void) memset(mod_novis, 0xff, sizeof(mod_novis)); } -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_LoadTexture2D(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL); - } -} - -void Mod_BrushShutdown (void) -{ - int i; - for (i = 0;i < NUM_DETAILTEXTURES;i++) - R_FreeTexture(detailtextures[i]); - R_FreeTexturePool(&detailtexturepool); -} - /* =============== Mod_PointInLeaf @@ -214,11 +162,6 @@ static void Mod_LoadTextures (lump_t *l) dmiptexlump_t *m; qbyte *data, *mtdata; char name[256]; - qbyte *basepixels, *bumppixels, *nmappixels, *glosspixels, *glowpixels, *maskpixels; - int basepixels_width, basepixels_height, bumppixels_width, bumppixels_height; - int nmappixels_width, nmappixels_height, glosspixels_width, glosspixels_height; - int glowpixels_width, glowpixels_height, maskpixels_width, maskpixels_height; - rtexture_t *detailtexture; loadmodel->textures = NULL; @@ -236,15 +179,19 @@ static void Mod_LoadTextures (lump_t *l) // fill out all slots with notexture for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++) { + tx->number = i; + strcpy(tx->name, "NO TEXTURE FOUND"); tx->width = 16; tx->height = 16; - tx->texture = r_notexture; + tx->skin.base = r_notexture; tx->shader = &Cshader_wall_lightmap; + tx->flags = SURF_SOLIDCLIP; if (i == loadmodel->numtextures - 1) { - tx->flags = SURF_DRAWTURB | SURF_LIGHTBOTHSIDES; + tx->flags |= SURF_DRAWTURB | SURF_LIGHTBOTHSIDES; tx->shader = &Cshader_water; } + tx->currentframe = tx; } // just to work around bounds checking when debugging with it (array index out of bounds error thing) @@ -296,14 +243,6 @@ static void Mod_LoadTextures (lump_t *l) Con_Printf("warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name); } - basepixels = NULL;basepixels_width = 0;basepixels_height = 0; - bumppixels = NULL;bumppixels_width = 0;bumppixels_height = 0; - nmappixels = NULL;nmappixels_width = 0;nmappixels_height = 0; - glosspixels = NULL;glosspixels_width = 0;glosspixels_height = 0; - glowpixels = NULL;glowpixels_width = 0;glowpixels_height = 0; - maskpixels = NULL;maskpixels_width = 0;maskpixels_height = 0; - detailtexture = NULL; - // LordHavoc: HL sky textures are entirely different than quake if (!loadmodel->ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128) { @@ -331,162 +270,43 @@ static void Mod_LoadTextures (lump_t *l) } else { - if ((basepixels = loadimagepixels(tx->name, false, 0, 0)) != NULL) - { - basepixels_width = image_width; - basepixels_height = image_height; - } - // _luma is supported for tenebrae compatibility - // (I think it's a very stupid name, but oh well) - if ((glowpixels = loadimagepixels(va("%s_glow", tx->name), false, 0, 0)) != NULL - || (glowpixels = loadimagepixels(va("%s_luma", tx->name), false, 0, 0)) != NULL) - { - glowpixels_width = image_width; - glowpixels_height = image_height; - } - if ((bumppixels = loadimagepixels(va("%s_bump", tx->name), false, 0, 0)) != NULL) - { - bumppixels_width = image_width; - bumppixels_height = image_height; - } - if ((glosspixels = loadimagepixels(va("%s_gloss", tx->name), false, 0, 0)) != NULL) - { - glosspixels_width = image_width; - glosspixels_height = image_height; - } - if (!basepixels) + if (!Mod_LoadSkinFrame(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true)) { + // did not find external texture, load it from the bsp or wad3 if (loadmodel->ishlbsp) { // internal texture overrides wad - if (mtdata && (basepixels = W_ConvertWAD3Texture(dmiptex)) != NULL) - { - basepixels_width = image_width; - basepixels_height = image_height; - } - else if ((basepixels = W_GetTexture(tx->name)) != NULL) + qbyte *pixels, *freepixels; + pixels = freepixels = NULL; + if (mtdata) + pixels = W_ConvertWAD3Texture(dmiptex); + if (pixels == NULL) + pixels = freepixels = W_GetTexture(tx->name); + if (pixels != NULL) { - // get the size from the wad texture - tx->width = basepixels_width = image_width; - tx->height = basepixels_height = image_height; + tx->width = image_width; + tx->height = image_height; + tx->skin.base = tx->skin.merged = R_LoadTexture2D(loadmodel->texturepool, tx->name, image_width, image_height, pixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); } + if (freepixels) + Mem_Free(freepixels); } - else - { - if (mtdata) // texture included - { - if (r_fullbrights.integer && tx->name[0] != '*') - { - basepixels_width = tx->width; - basepixels_height = tx->height; - basepixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4); - Image_Copy8bitRGBA(mtdata, basepixels, basepixels_width * basepixels_height, palette_nofullbrights); - if (!glowpixels) - { - for (j = 0;j < (int)(tx->width*tx->height);j++) - if (((qbyte *)&palette_onlyfullbrights[mtdata[j]])[3] > 0) // fullbright - break; - if (j < (int)(tx->width * tx->height)) - { - glowpixels_width = tx->width; - glowpixels_height = tx->height; - glowpixels = Mem_Alloc(loadmodel->mempool, glowpixels_width * glowpixels_height * 4); - Image_Copy8bitRGBA(mtdata, glowpixels, glowpixels_width * glowpixels_height, palette_onlyfullbrights); - } - } - } - else - { - basepixels_width = tx->width; - basepixels_height = tx->height; - basepixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4); - Image_Copy8bitRGBA(mtdata, basepixels, tx->width * tx->height, palette_complete); - } - } - } - } - } - - if (basepixels) - { - for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4) - if (basepixels[j] < 255) - break; - if (j < basepixels_width * basepixels_height * 4) - { - maskpixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4); - maskpixels_width = basepixels_width; - maskpixels_height = basepixels_height; - for (j = 0;j < basepixels_width * basepixels_height * 4;j += 4) - { - maskpixels[j+0] = 255; - maskpixels[j+1] = 255; - maskpixels[j+2] = 255; - maskpixels[j+3] = basepixels[j+3]; - } + else if (mtdata) // texture included + Mod_LoadSkinFrame_Internal(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, tx->name[0] != '*' && r_fullbrights.integer, mtdata, tx->width, tx->height); } - - if (!bumppixels) - { - bumppixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4); - bumppixels_width = basepixels_width; - bumppixels_height = basepixels_height; - memcpy(bumppixels, basepixels, bumppixels_width * bumppixels_height * 4); - } - - if (!nmappixels && bumppixels) - { - nmappixels = Mem_Alloc(loadmodel->mempool, bumppixels_width * bumppixels_height * 4); - nmappixels_width = bumppixels_width; - nmappixels_height = bumppixels_height; - Image_HeightmapToNormalmap(bumppixels, nmappixels, nmappixels_width, nmappixels_height, false, 1); - } - } - - if (!detailtexture) - detailtexture = detailtextures[i % NUM_DETAILTEXTURES]; - - if (basepixels) - { - tx->texture = R_LoadTexture2D (loadmodel->texturepool, tx->name, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); - if (nmappixels) - tx->nmaptexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", tx->name), basepixels_width, basepixels_height, nmappixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); - if (glosspixels) - tx->glosstexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_gloss", tx->name), glosspixels_width, glosspixels_height, glosspixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); - if (glowpixels) - tx->glowtexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_glow", tx->name), glowpixels_width, glowpixels_height, glowpixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); - if (maskpixels) - tx->fogtexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_mask", tx->name), maskpixels_width, maskpixels_height, maskpixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); - tx->detailtexture = detailtexture; } - else + if (tx->skin.base == NULL) { // no texture found tx->width = 16; tx->height = 16; - tx->texture = r_notexture; - tx->nmaptexture = NULL; - tx->glosstexture = NULL; - tx->glowtexture = NULL; - tx->fogtexture = NULL; - tx->detailtexture = NULL; - } - - if (basepixels) - Mem_Free(basepixels); - if (bumppixels) - Mem_Free(bumppixels); - if (nmappixels) - Mem_Free(nmappixels); - if (glosspixels) - Mem_Free(glosspixels); - if (glowpixels) - Mem_Free(glowpixels); - if (maskpixels) - Mem_Free(maskpixels); + tx->skin.base = r_notexture; + } if (tx->name[0] == '*') { + // turb does not block movement + tx->flags &= ~SURF_SOLIDCLIP; tx->flags |= SURF_DRAWTURB | SURF_LIGHTBOTHSIDES; // LordHavoc: some turbulent textures should be fullbright and solid if (!strncmp(tx->name,"*lava",5) @@ -505,7 +325,7 @@ static void Mod_LoadTextures (lump_t *l) else { tx->flags |= SURF_LIGHTMAP; - if (!tx->fogtexture) + if (!tx->skin.fog) tx->flags |= SURF_SHADOWCAST | SURF_SHADOWLIGHT; tx->shader = &Cshader_wall_lightmap; } @@ -646,7 +466,7 @@ static void Mod_LoadLighting (lump_t *l) i = LittleLong(((int *)data)[1]); if (i == 1) { - Con_DPrintf("%s loaded", litfilename); + Con_DPrintf("loaded %s\n", litfilename); loadmodel->lightdata = Mem_Alloc(loadmodel->mempool, loadsize - 8); memcpy(loadmodel->lightdata, data + 8, loadsize - 8); Mem_Free(data); @@ -783,8 +603,10 @@ void Mod_ProcessLightList(void) dist = -dist; if (dist > 0 && dist < e->cullradius) { - VectorSubtract(e->origin, surf->poly_center, temp); - if (DotProduct(temp, temp) - surf->poly_radius2 < e->cullradius2) + temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0]; + temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1]; + temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2]; + if (DotProduct(temp, temp) < lightradius2) loadmodel->surfacevisframes[*mark] = -2; } } @@ -1237,58 +1059,6 @@ static void Mod_LoadTexinfo (lump_t *l) } } -/* -================ -CalcSurfaceExtents - -Fills in s->texturemins[] and s->extents[] -================ -*/ -static void CalcSurfaceExtents (msurface_t *s) -{ - float mins[2], maxs[2], val; - int i,j, e; - mvertex_t *v; - mtexinfo_t *tex; - int bmins[2], bmaxs[2]; - - mins[0] = mins[1] = 999999999; - maxs[0] = maxs[1] = -999999999; - - tex = s->texinfo; - - for (i=0 ; inumedges ; i++) - { - e = loadmodel->surfedges[s->firstedge+i]; - if (e >= 0) - v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; - else - v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; - - for (j=0 ; j<2 ; j++) - { - val = v->position[0] * tex->vecs[j][0] + - v->position[1] * tex->vecs[j][1] + - v->position[2] * tex->vecs[j][2] + - tex->vecs[j][3]; - if (val < mins[j]) - mins[j] = val; - if (val > maxs[j]) - maxs[j] = val; - } - } - - for (i=0 ; i<2 ; i++) - { - bmins[i] = floor(mins[i]/16); - bmaxs[i] = ceil(maxs[i]/16); - - s->texturemins[i] = bmins[i] * 16; - s->extents[i] = (bmaxs[i] - bmins[i]) * 16; - } -} - - void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) { int i, j; @@ -1584,17 +1354,18 @@ void Mod_GenerateVertexMesh (msurface_t *surf) Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->verts, mesh->str, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals); } -void Mod_GenerateSurfacePolygon (msurface_t *surf) +void Mod_GenerateSurfacePolygon (msurface_t *surf, int firstedge, int numedges) { - int i, lindex; - float *vec, *vert, mins[3], maxs[3], temp[3], dist; + int i, lindex, j; + float *vec, *vert, mins[3], maxs[3], val, *v; + mtexinfo_t *tex; // convert edges back to a normal polygon - surf->poly_numverts = surf->numedges; - vert = surf->poly_verts = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * surf->numedges); - for (i = 0;i < surf->numedges;i++) + surf->poly_numverts = numedges; + vert = surf->poly_verts = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * numedges); + for (i = 0;i < numedges;i++) { - lindex = loadmodel->surfedges[surf->firstedge + i]; + lindex = loadmodel->surfedges[firstedge + i]; if (lindex > 0) vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; else @@ -1602,33 +1373,44 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf) VectorCopy (vec, vert); vert += 3; } + + // calculate polygon bounding box and center vert = surf->poly_verts; VectorCopy(vert, mins); VectorCopy(vert, maxs); vert += 3; - for (i = 1;i < surf->poly_numverts;i++) + for (i = 1;i < surf->poly_numverts;i++, vert += 3) { 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; - surf->poly_radius2 = 0; - vert = surf->poly_verts; - for (i = 0;i < surf->poly_numverts;i++) + + // generate surface extents information + tex = surf->texinfo; + mins[0] = maxs[0] = DotProduct(surf->poly_verts, tex->vecs[0]) + tex->vecs[0][3]; + mins[1] = maxs[1] = DotProduct(surf->poly_verts, tex->vecs[1]) + tex->vecs[1][3]; + for (i = 1, v = surf->poly_verts + 3;i < surf->poly_numverts;i++, v += 3) { - VectorSubtract(vert, surf->poly_center, temp); - dist = DotProduct(temp, temp); - if (surf->poly_radius2 < dist) - surf->poly_radius2 = dist; - vert += 3; + for (j = 0;j < 2;j++) + { + val = DotProduct(v, tex->vecs[j]) + tex->vecs[j][3]; + if (mins[j] > val) + mins[j] = val; + if (maxs[j] < val) + maxs[j] = val; + } + } + for (i = 0;i < 2;i++) + { + surf->texturemins[i] = (int) floor(mins[i] / 16) * 16; + surf->extents[i] = (int) ceil(maxs[i] / 16) * 16 - surf->texturemins[i]; } - surf->poly_radius = sqrt(surf->poly_radius2); } /* @@ -1640,7 +1422,7 @@ static void Mod_LoadFaces (lump_t *l) { dface_t *in; msurface_t *out; - int i, count, surfnum, planenum, ssize, tsize; + int i, count, surfnum, planenum, ssize, tsize, firstedge, numedges; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -1658,10 +1440,10 @@ static void Mod_LoadFaces (lump_t *l) { out->number = surfnum; // 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); + firstedge = LittleLong(in->firstedge); + numedges = LittleShort(in->numedges); + if ((unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->numsurfedges) + Host_Error("Mod_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)\n", firstedge, numedges, loadmodel->numsurfedges); i = LittleShort (in->texinfo); if ((unsigned int) i >= (unsigned int) loadmodel->numtexinfo) @@ -1684,7 +1466,7 @@ static void Mod_LoadFaces (lump_t *l) // force lightmap upload on first time seeing the surface out->cached_dlight = true; - CalcSurfaceExtents (out); + Mod_GenerateSurfacePolygon(out, firstedge, numedges); ssize = (out->extents[0] >> 4) + 1; tsize = (out->extents[1] >> 4) + 1; @@ -1700,7 +1482,6 @@ static void Mod_LoadFaces (lump_t *l) else // LordHavoc: white lighting (bsp version 29) out->samples = loadmodel->lightdata + (i * 3); - Mod_GenerateSurfacePolygon(out); if (out->texinfo->texture->shader == &Cshader_wall_lightmap) { if ((out->extents[0] >> 4) + 1 > (256) || (out->extents[1] >> 4) + 1 > (256)) @@ -2747,6 +2528,95 @@ static void Mod_BuildSurfaceNeighbors (msurface_t *surfaces, int numsurfaces, me #endif } +void Mod_BuildLightmapUpdateChains(mempool_t *mempool, model_t *model) +{ + int i, j, stylecounts[256], totalcount, remapstyles[256]; + msurface_t *surf; + memset(stylecounts, 0, sizeof(stylecounts)); + for (i = 0;i < model->nummodelsurfaces;i++) + { + surf = model->surfaces + model->firstmodelsurface + i; + for (j = 0;j < MAXLIGHTMAPS;j++) + stylecounts[surf->styles[j]]++; + } + totalcount = 0; + model->light_styles = 0; + for (i = 0;i < 255;i++) + { + if (stylecounts[i]) + { + remapstyles[i] = model->light_styles++; + totalcount += stylecounts[i] + 1; + } + } + if (!totalcount) + return; + model->light_style = Mem_Alloc(mempool, model->light_styles * sizeof(qbyte)); + model->light_stylevalue = Mem_Alloc(mempool, model->light_styles * sizeof(int)); + model->light_styleupdatechains = Mem_Alloc(mempool, model->light_styles * sizeof(msurface_t **)); + model->light_styleupdatechainsbuffer = Mem_Alloc(mempool, totalcount * sizeof(msurface_t *)); + model->light_styles = 0; + for (i = 0;i < 255;i++) + if (stylecounts[i]) + model->light_style[model->light_styles++] = i; + j = 0; + for (i = 0;i < model->light_styles;i++) + { + model->light_styleupdatechains[i] = model->light_styleupdatechainsbuffer + j; + j += stylecounts[model->light_style[i]] + 1; + } + for (i = 0;i < model->nummodelsurfaces;i++) + { + surf = model->surfaces + model->firstmodelsurface + i; + for (j = 0;j < MAXLIGHTMAPS;j++) + if (surf->styles[j] != 255) + *model->light_styleupdatechains[remapstyles[surf->styles[j]]]++ = surf; + } + j = 0; + for (i = 0;i < model->light_styles;i++) + { + *model->light_styleupdatechains[i] = NULL; + model->light_styleupdatechains[i] = model->light_styleupdatechainsbuffer + j; + j += stylecounts[model->light_style[i]] + 1; + } +} + +void Mod_BuildPVSTextureChains(model_t *model) +{ + int i, j; + for (i = 0;i < model->numtextures;i++) + model->pvstexturechainslength[i] = 0; + for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++) + { + if (model->surfacepvsframes[j] == model->pvsframecount) + { + model->pvssurflist[model->pvssurflistlength++] = j; + model->pvstexturechainslength[model->surfaces[j].texinfo->texture->number]++; + } + } + for (i = 0, j = 0;i < model->numtextures;i++) + { + if (model->pvstexturechainslength[i]) + { + model->pvstexturechains[i] = model->pvstexturechainsbuffer + j; + j += model->pvstexturechainslength[i] + 1; + } + else + model->pvstexturechains[i] = NULL; + } + for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++) + if (model->surfacepvsframes[j] == model->pvsframecount) + *model->pvstexturechains[model->surfaces[j].texinfo->texture->number]++ = model->surfaces + j; + for (i = 0;i < model->numtextures;i++) + { + if (model->pvstexturechainslength[i]) + { + *model->pvstexturechains[i] = NULL; + model->pvstexturechains[i] -= model->pvstexturechainslength[i]; + } + } +} + /* ================= Mod_LoadBrushModel @@ -2758,12 +2628,15 @@ extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relative extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor); void Mod_LoadBrushModel (model_t *mod, void *buffer) { - int i, j; - dheader_t *header; - dmodel_t *bm; - mempool_t *mainmempool; - char *loadname; - model_t *originalloadmodel; + int i, j, k; + dheader_t *header; + dmodel_t *bm; + mempool_t *mainmempool; + char *loadname; + model_t *originalloadmodel; + float dist, modelyawradius, modelradius, *vec; + msurface_t *surf; + surfmesh_t *mesh; mod->type = mod_brush; @@ -2823,15 +2696,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) // for (i = 0;i < mod->numsubmodels;i++) { - int k, l; - float dist, modelyawradius, modelradius, *vec; - msurface_t *surf; - - mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f; - mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f; - modelyawradius = 0; - modelradius = 0; - bm = &mod->submodels[i]; mod->hulls[0].firstclipnode = bm->headnode[0]; @@ -2850,38 +2714,44 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod->DrawFakeShadow = NULL; mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume; mod->DrawLight = R_Model_Brush_DrawLight; - mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *)); + mod->pvstexturechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t **)); + mod->pvstexturechainsbuffer = Mem_Alloc(originalloadmodel->mempool, (mod->nummodelsurfaces + mod->numtextures) * sizeof(msurface_t *)); + mod->pvstexturechainslength = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(int)); + Mod_BuildPVSTextureChains(mod); + Mod_BuildLightmapUpdateChains(originalloadmodel->mempool, mod); if (mod->nummodelsurfaces) { // LordHavoc: calculate bmodel bounding box rather than trusting what it says + mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f; + mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f; + modelyawradius = 0; + modelradius = 0; for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++) { // we only need to have a drawsky function if it is used (usually only on world model) if (surf->texinfo->texture->shader == &Cshader_sky) mod->DrawSky = R_Model_Brush_DrawSky; - // link into texture chain - surf->texturechain = mod->texturesurfacechains[surf->texinfo->texture - mod->textures]; - mod->texturesurfacechains[surf->texinfo->texture - mod->textures] = surf; + // LordHavoc: submodels always clip, even if water + if (mod->numsubmodels - 1) + surf->flags |= SURF_SOLIDCLIP; // calculate bounding shapes - for (k = 0;k < surf->numedges;k++) + for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - l = mod->surfedges[k + surf->firstedge]; - if (l > 0) - vec = mod->vertexes[mod->edges[l].v[0]].position; - else - vec = mod->vertexes[mod->edges[-l].v[1]].position; - if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0]; - if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1]; - if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2]; - if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0]; - if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1]; - if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2]; - dist = vec[0]*vec[0]+vec[1]*vec[1]; - if (modelyawradius < dist) - modelyawradius = dist; - dist += vec[2]*vec[2]; - if (modelradius < dist) - modelradius = dist; + for (k = 0, vec = mesh->verts;k < mesh->numverts;k++, vec += 4) + { + if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0]; + if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1]; + if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2]; + if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0]; + if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1]; + if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2]; + dist = vec[0]*vec[0]+vec[1]*vec[1]; + if (modelyawradius < dist) + modelyawradius = dist; + dist += vec[2]*vec[2]; + if (modelradius < dist) + modelradius = dist; + } } } modelyawradius = sqrt(modelyawradius); @@ -2893,28 +2763,11 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius; mod->radius = modelradius; mod->radius2 = modelradius * modelradius; - // LordHavoc: build triangle meshs for entire model's geometry - // (only used for shadow volumes) - mod->shadowmesh = Mod_ShadowMesh_Begin(originalloadmodel->mempool, 1024); - for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++) - if (surf->flags & SURF_SHADOWCAST) - Mod_ShadowMesh_AddPolygon(originalloadmodel->mempool, mod->shadowmesh, surf->poly_numverts, surf->poly_verts); - mod->shadowmesh = Mod_ShadowMesh_Finish(originalloadmodel->mempool, mod->shadowmesh); - Mod_ShadowMesh_CalcBBox(mod->shadowmesh, mod->shadowmesh_mins, mod->shadowmesh_maxs, mod->shadowmesh_center, &mod->shadowmesh_radius); } else { // LordHavoc: empty submodel (lacrima.bsp has such a glitch) 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->radius = 0; - mod->radius2 = 0; - mod->shadowmesh = NULL; } Mod_BuildSurfaceNeighbors(mod->surfaces + mod->firstmodelsurface, mod->nummodelsurfaces, originalloadmodel->mempool);