X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=model_brush.c;h=9c0cf4e8328752cb6d43b27a51e2a3aac80cc065;hb=03e1a41d3cb44dad41bb271bc94e0b09606626b1;hp=3c248fe258ee06fa2948ee422affcd0c920cec1e;hpb=2b77a4b0d8f8283a5dcaa86642d46f8ad114f189;p=xonotic%2Fdarkplaces.git diff --git a/model_brush.c b/model_brush.c index 3c248fe2..9c0cf4e8 100644 --- a/model_brush.c +++ b/model_brush.c @@ -24,15 +24,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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; + /* =============== Mod_BrushInit @@ -40,25 +43,76 @@ 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_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) +{ + int i; + for (i = 0;i < NUM_DETAILTEXTURES;i++) + R_FreeTexture(detailtextures[i]); + R_FreeTexturePool(&detailtexturepool); +} + /* =============== 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); @@ -71,17 +125,35 @@ 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; } @@ -153,17 +225,20 @@ static void Mod_LoadTextures (lump_t *l) // 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)); + loadmodel->textures = Mem_Alloc(loadmodel->mempool, loadmodel->numtextures * sizeof(texture_t)); // fill out all slots with notexture - for (i = 0;i < loadmodel->numtextures;i++) + for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++) { - loadmodel->textures[i] = tx = Mem_Alloc(loadmodel->mempool, sizeof(texture_t)); tx->width = 16; tx->height = 16; tx->texture = r_notexture; + tx->shader = &Cshader_wall_lightmap; if (i == loadmodel->numtextures - 1) - tx->flags = SURF_DRAWTURB | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID; + { + tx->flags = SURF_DRAWTURB | SURF_LIGHTBOTHSIDES; + tx->shader = &Cshader_water; + } } // just to work around bounds checking when debugging with it (array index out of bounds error thing) @@ -204,13 +279,10 @@ static void Mod_LoadTextures (lump_t *l) if (name[j] >= 'A' && name[j] <= 'Z') name[j] += 'a' - 'A'; - tx = loadmodel->textures[i]; + tx = loadmodel->textures + i; strcpy(tx->name, name); tx->width = mtwidth; tx->height = mtheight; - tx->texture = NULL; - tx->glowtexture = NULL; - tx->fogtexture = NULL; if (!tx->name[0]) { @@ -338,27 +410,32 @@ static void Mod_LoadTextures (lump_t *l) if (tx->name[0] == '*') { - tx->flags |= (SURF_DRAWTURB | SURF_LIGHTBOTHSIDES); + tx->flags |= SURF_DRAWTURB | SURF_LIGHTBOTHSIDES; // LordHavoc: some turbulent textures should be fullbright and solid if (!strncmp(tx->name,"*lava",5) || !strncmp(tx->name,"*teleport",9) || !strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture - tx->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID); + tx->flags |= SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA; + tx->shader = &Cshader_water; } else if (tx->name[0] == 's' && tx->name[1] == 'k' && tx->name[2] == 'y') - tx->flags |= (SURF_DRAWSKY | SURF_CLIPSOLID); + { + tx->flags |= SURF_DRAWSKY; + tx->shader = &Cshader_sky; + } else { tx->flags |= SURF_LIGHTMAP; - if (!R_TextureHasAlpha(tx->texture)) - tx->flags |= SURF_CLIPSOLID; + tx->shader = &Cshader_wall_lightmap; } + + tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES]; } // sequence the animations for (i = 0;i < m->nummiptex;i++) { - tx = loadmodel->textures[i]; + tx = loadmodel->textures + i; if (!tx || tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0) continue; if (tx->anim_total[0] || tx->anim_total[1]) @@ -370,7 +447,7 @@ static void Mod_LoadTextures (lump_t *l) for (j = i;j < m->nummiptex;j++) { - tx2 = loadmodel->textures[j]; + tx2 = loadmodel->textures + j; if (!tx2 || tx2->name[0] != '+' || strcmp (tx2->name+2, tx->name+2)) continue; @@ -570,7 +647,7 @@ void Mod_LoadLightList(void) 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); + Host_Error("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1); } s++; n++; @@ -601,22 +678,20 @@ static void Mod_LoadVisibility (lump_t *l) } // used only for HalfLife maps -void Mod_ParseWadsFromEntityLump(char *data) +void Mod_ParseWadsFromEntityLump(const char *data) { char key[128], value[4096]; char wadname[128]; int i, j, k; if (!data) return; - data = COM_Parse(data); - if (!data) + if (!COM_ParseToken(&data)) return; // error if (com_token[0] != '{') return; // error while (1) { - data = COM_Parse(data); - if (!data) + if (!COM_ParseToken(&data)) return; // error if (com_token[0] == '}') break; // end of worldspawn @@ -626,8 +701,7 @@ void Mod_ParseWadsFromEntityLump(char *data) strcpy(key, com_token); while (key[strlen(key)-1] == ' ') // remove trailing spaces key[strlen(key)-1] = 0; - data = COM_Parse(data); - if (!data) + if (!COM_ParseToken(&data)) return; // error strcpy(value, com_token); if (!strcmp("wad", key)) // for HalfLife maps @@ -807,15 +881,20 @@ static void Mod_LoadTexinfo (lump_t *l) 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]; + out->texture = loadmodel->textures + miptex; } - if (out->texture == NULL) + if (out->flags & TEX_SPECIAL) { - // 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 texture chosen is NULL or the shader needs a lightmap, + // force to notexture water shader + if (out->texture == NULL || out->texture->shader->flags & SHADERFLAGS_NEEDLIGHTMAP) + out->texture = loadmodel->textures + (loadmodel->numtextures - 1); + } + else + { + // if texture chosen is NULL, force to notexture + if (out->texture == NULL) + out->texture = loadmodel->textures + (loadmodel->numtextures - 2); } } } @@ -892,6 +971,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) @@ -1027,90 +1107,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; smax = surf->extents[0] >> 4; tmax = surf->extents[1] >> 4; - surf->lightmaptexturestride = 0; - surf->lightmaptexture = NULL; - - surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t)); - mesh->numverts = surf->poly_numverts; - mesh->numtriangles = surf->poly_numverts - 2; - mesh->vertex = (surfvertex_t *)(mesh + 1); - mesh->index = (int *)(mesh->vertex + mesh->numverts); - memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); - index = mesh->index; - for (i = 0;i < mesh->numtriangles;i++) - { - *index++ = 0; - *index++ = i + 1; - *index++ = i + 2; - } - - for (i = 0, in = surf->poly_verts, out = mesh->vertex;i < mesh->numverts;i++, in += 3, out++) + if (vertexonly) { - 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_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_PRECACHE); + 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_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE); + 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); } - 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); - surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t)); + 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->vertex = (surfvertex_t *)(mesh + 1); - mesh->index = (int *)(mesh->vertex + mesh->numverts); - 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++) @@ -1120,48 +1163,49 @@ 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); + v = (t + 8 - surf->texturemins[1]) * (1.0 / 16.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); + iu = (int) u; + iv = (int) v; + iu = bound(0, iu, smax); + iv = bound(0, iv, tmax); + u = u * uscale + ubase; + v = v * vscale + vbase; + + 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; - surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t)); + 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->vertex = (surfvertex_t *)(mesh + 1); - mesh->index = (int *)(mesh->vertex + mesh->numverts); - 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++) @@ -1171,20 +1215,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; @@ -1199,55 +1247,22 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf) VectorCopy (vec, vert); vert += 3; } -} - -static void Mod_SplitSurfMeshIfTooBig(msurface_t *s) -{ - int j, base, tricount, newvertexcount, *index, *vertexremap; - surfmesh_t *newmesh, *oldmesh, *firstmesh; - if (s->mesh->numtriangles > 1000) + vert = surf->poly_verts; + VectorCopy(vert, mins); + VectorCopy(vert, maxs); + vert += 3; + for (i = 1;i < surf->poly_numverts;i++) { - vertexremap = Mem_Alloc(tempmempool, s->mesh->numverts * sizeof(int)); - base = 0; - oldmesh = NULL; - firstmesh = NULL; - newmesh = NULL; - while (base < s->mesh->numtriangles) - { - tricount = s->mesh->numtriangles - base; - if (tricount > 1000) - tricount = 1000; - index = s->mesh->index + base * 3; - base += tricount; - - newvertexcount = 0; - memset(vertexremap, -1, s->mesh->numverts * sizeof(int)); - for (j = 0;j < tricount * 3;j++) - if (vertexremap[index[j]] < 0) - vertexremap[index[j]] = newvertexcount++; - - newmesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + newvertexcount * sizeof(surfvertex_t) + tricount * sizeof(int[3])); - newmesh->chain = NULL; - newmesh->numverts = newvertexcount; - newmesh->numtriangles = tricount; - newmesh->vertex = (surfvertex_t *)(newmesh + 1); - newmesh->index = (int *)(newmesh->vertex + newvertexcount); - for (j = 0;j < tricount * 3;j++) - { - newmesh->index[j] = vertexremap[index[j]]; - // yes this copies the same vertex multiple times in many cases... but that's ok... - memcpy(&newmesh->vertex[newmesh->index[j]], &s->mesh->vertex[index[j]], sizeof(surfvertex_t)); - } - if (oldmesh) - oldmesh->chain = newmesh; - else - firstmesh = newmesh; - oldmesh = newmesh; - } - Mem_Free(vertexremap); - Mem_Free(s->mesh); - s->mesh = firstmesh; + 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; } /* @@ -1269,9 +1284,12 @@ static void Mod_LoadFaces (lump_t *l) loadmodel->surfaces = out; loadmodel->numsurfaces = count; + loadmodel->surfacevisframes = Mem_Alloc(loadmodel->mempool, count * sizeof(int)); + loadmodel->surfacepvsframes = Mem_Alloc(loadmodel->mempool, count * sizeof(int)); for (surfnum = 0;surfnum < count;surfnum++, in++, out++) { + out->number = surfnum; // FIXME: validate edges, texinfo, etc? out->firstedge = LittleLong(in->firstedge); out->numedges = LittleShort(in->numedges); @@ -1298,8 +1316,6 @@ static void Mod_LoadFaces (lump_t *l) // force lightmap upload on first time seeing the surface out->cached_dlight = true; - out->cached_ambient = -1000; - out->cached_lightscalebit = -1000; CalcSurfaceExtents (out); @@ -1318,87 +1334,21 @@ static void Mod_LoadFaces (lump_t *l) out->samples = loadmodel->lightdata + (i * 3); Mod_GenerateSurfacePolygon(out); - - if (out->texinfo->texture->flags & SURF_DRAWSKY) - { - out->shader = &Cshader_sky; - out->samples = NULL; - Mod_GenerateWarpMesh (out); - } - else if (out->texinfo->texture->flags & SURF_DRAWTURB) + if (out->texinfo->texture->shader == &Cshader_wall_lightmap) { - out->shader = &Cshader_water; - out->samples = NULL; - Mod_GenerateWarpMesh (out); + if ((out->extents[0] >> 4) + 1 > (256) || (out->extents[1] >> 4) + 1 > (256)) + Host_Error ("Bad surface extents"); + Mod_GenerateWallMesh (out, false); + // 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); } else - { - 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_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 - { - // stainmap for permanent marks on walls - out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3); - // clear to white - memset(out->stainsamples, 255, ssize * tsize * 3); - if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer) - { - out->shader = &Cshader_wall_vertex; - Mod_GenerateVertexLitMesh(out); - } - else - { - out->shader = &Cshader_wall_lightmap; - Mod_GenerateLightmappedMesh(out); - } - } - } - Mod_SplitSurfMeshIfTooBig(out); + Mod_GenerateVertexMesh (out); } } -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 (qbyte *) a->shader - (qbyte *) 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]; - - if (r_sortsurfaces.integer) - qsort(sortmodel->modelsortedsurfaces, sortmodel->nummodelsurfaces, sizeof(msurface_t *), Mod_SurfaceQSortCompare); -} - - /* ================= Mod_SetParent @@ -1647,21 +1597,21 @@ Mod_LoadMarksurfaces */ static void Mod_LoadMarksurfaces (lump_t *l) { - int i, j; - short *in; + int i, j; + short *in; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); loadmodel->nummarksurfaces = l->filelen / sizeof(*in); - loadmodel->marksurfaces = Mem_Alloc(loadmodel->mempool, loadmodel->nummarksurfaces * sizeof(msurface_t *)); + loadmodel->marksurfaces = Mem_Alloc(loadmodel->mempool, loadmodel->nummarksurfaces * sizeof(int)); for (i = 0;i < loadmodel->nummarksurfaces;i++) { j = (unsigned) LittleShort(in[i]); if (j >= loadmodel->numsurfaces) Host_Error ("Mod_ParseMarksurfaces: bad surface number"); - loadmodel->marksurfaces[i] = loadmodel->surfaces + j; + loadmodel->marksurfaces[i] = j; } } @@ -2406,7 +2356,11 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) 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 = (qbyte *)header; @@ -2476,7 +2430,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) 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->shader == &Cshader_sky) + if (surf->texinfo->texture->shader == &Cshader_sky) mod->DrawSky = R_DrawBrushModelSky; for (k = 0;k < surf->numedges;k++) { @@ -2523,8 +2477,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) 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))