diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index ebb91f491..cade071e8 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -4973,8 +4973,6 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole { // load into heap noerrors = noerrors && Mod_LoadVertexes (mod, mod_base, &header.lumps[Q2LUMP_VERTEXES]); - if (header.version == BSPVERSION_Q2W) - /*noerrors = noerrors &&*/ Mod_LoadVertexNormals(mod, bspx, mod_base, &header.lumps[19]); noerrors = noerrors && Mod_LoadEdges (mod, mod_base, &header.lumps[Q2LUMP_EDGES], false); noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[Q2LUMP_SURFEDGES]); noerrors = noerrors && CModQ2_LoadSurfaces (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO]); @@ -4983,6 +4981,8 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole if (noerrors) Mod_LoadEntities (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); noerrors = noerrors && CModQ2_LoadFaces (mod, mod_base, &header.lumps[Q2LUMP_FACES], &header.lumps[Q2LUMP_LIGHTING], header.version == BSPVERSION_Q2W, bspx); + if (header.version == BSPVERSION_Q2W) + /*noerrors = noerrors &&*/ Mod_LoadVertexNormals(mod, bspx, mod_base, &header.lumps[19]); noerrors = noerrors && Mod_LoadMarksurfaces (mod, mod_base, &header.lumps[Q2LUMP_LEAFFACES], false); noerrors = noerrors && CModQ2_LoadVisibility (mod, mod_base, &header.lumps[Q2LUMP_VISIBILITY]); noerrors = noerrors && CModQ2_LoadBrushSides (mod, mod_base, &header.lumps[Q2LUMP_BRUSHSIDES]); diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 6123c869a..4e812aae8 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -2922,6 +2922,7 @@ qboolean Mod_BSPXRW_Read(struct bspxrw *ctx, const char *fname) #endif }; #endif + static const char *q1corelumpnames[HEADER_LUMPS] = {"entities","planes","textures","vertexes","visibility","nodes","texinfo","faces","lighting","clipnodes","leafs","marksurfaces","edges","surfedges","models"}; ctx->fname = fname; ctx->origfile = FS_MallocFile(ctx->fname, FS_GAME, &ctx->origsize); if (!ctx->origfile) @@ -2936,9 +2937,10 @@ qboolean Mod_BSPXRW_Read(struct bspxrw *ctx, const char *fname) case 30: ctx->fg = ((i==30)?fg_halflife:fg_quake); ctx->lumpofs = 4; - ctx->corelumps = 0; + ctx->corelumps = HEADER_LUMPS; + corelumpnames = q1corelumpnames; break; - case ('I'<<0)+('B'<<8)+('S'<<16)+('P'<<24): + case ('I'<<0)+('B'<<8)+('S'<<16)+('P'<<24): //starting with q2. i = LittleLong(*(int*)(ctx->origfile+4)); ctx->lumpofs = 8; switch(i) @@ -3172,14 +3174,11 @@ void Mod_BSPX_List_f(void) fname = cl.worldmodel->name; if (Mod_BSPXRW_Read(&ctx, fname)) { + Con_Printf("%s:\n", fname); for (i = 0; i < ctx.corelumps; i++) - { - Con_Printf("%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen); - } + Con_Printf("\t%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen); for ( ; i < ctx.totallumps; i++) - { - Con_Printf("%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen); - } + Con_Printf("\t%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen); Mod_BSPXRW_Free(&ctx); } } diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 12dc24e1f..88f6420a0 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -2422,18 +2422,48 @@ qboolean Mod_LoadVertexNormals (model_t *loadmodel, bspx_header_t *bspx, qbyte * Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); return false; } + + if (count != loadmodel->numvertexes) + return false; //invalid number of verts there, can't use this. } else - { - in = BSPX_FindLump(bspx, mod_base, "VERTEXNORMALS", &count); - if (in) - count /= sizeof(vec3_t); + { //ericw's thing + unsigned int size; + quint32_t t; + int *normcount; + struct surfedgenormals_s *sen; + normcount = BSPX_FindLump(bspx, mod_base, "FACENORMALS", &size); + if (normcount && size >= sizeof(*normcount)) + { + count = LittleLong(*normcount); + if (count < 1) + return false; + in = (void*)(normcount+1); //now the normals table. + sen = (void*)(in + count*3); + if ((qbyte*)(sen + loadmodel->numsurfedges)-(qbyte*)normcount != size) + return false; //bad size. + + loadmodel->surfedgenormals = ZG_Malloc(&loadmodel->memgroup, loadmodel->numsurfedges*sizeof(*loadmodel->surfedgenormals)); + for ( i=0 ; inumsurfedges ; i++, sen++) + { + t = LittleLong(sen->n); loadmodel->surfedgenormals[i].n = bound(0, t, count-1); + t = LittleLong(sen->s); loadmodel->surfedgenormals[i].s = bound(0, t, count-1); + t = LittleLong(sen->t); loadmodel->surfedgenormals[i].t = bound(0, t, count-1); + } + } else - count = 0; + { + //quake2world's thing + in = BSPX_FindLump(bspx, mod_base, "VERTEXNORMALS", &count); + if (in) + count /= sizeof(vec3_t); + else + count = 0; + if (count != loadmodel->numvertexes) + return false; //invalid number of verts there, can't use this. + } } - if (count != loadmodel->numvertexes) - return false; //invalid number of verts there, can't use this. out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(vec3_t)); loadmodel->normals = (vec3_t*)out; for ( i=0 ; inormals && (surf->texinfo->flags & 0x800) && (mod->normals[vertidx][0] || mod->normals[vertidx][1] || mod->normals[vertidx][2])) + if (mod->surfedgenormals) { - //per-vertex normals - used for smoothing groups and stuff. - VectorCopy(mod->normals[vertidx], mesh->normals_array[i]); + struct surfedgenormals_s *pv = mod->surfedgenormals + surf->firstedge + i; + VectorCopy(mod->normals[pv->n], mesh->normals_array[i]); + VectorCopy(mod->normals[pv->s], mesh->snormals_array[i]); + VectorCopy(mod->normals[pv->t], mesh->tnormals_array[i]); } else { - if (surf->flags & SURF_PLANEBACK) - VectorNegate(surf->plane->normal, mesh->normals_array[i]); + //figure out the texture directions, for bumpmapping and stuff + if (mod->normals && (surf->texinfo->flags & 0x800) && (mod->normals[vertidx][0] || mod->normals[vertidx][1] || mod->normals[vertidx][2])) + { + //per-vertex normals - used for smoothing groups and stuff. + VectorCopy(mod->normals[vertidx], mesh->normals_array[i]); + } else - VectorCopy(surf->plane->normal, mesh->normals_array[i]); + { + if (surf->flags & SURF_PLANEBACK) + VectorNegate(surf->plane->normal, mesh->normals_array[i]); + else + VectorCopy(surf->plane->normal, mesh->normals_array[i]); + } + VectorCopy(surf->texinfo->vecs[0], mesh->snormals_array[i]); + VectorNegate(surf->texinfo->vecs[1], mesh->tnormals_array[i]); + //for q1bsp the s+t vectors are usually axis-aligned, so fiddle them so they're normal aligned instead + d = -DotProduct(mesh->normals_array[i], mesh->snormals_array[i]); + VectorMA(mesh->snormals_array[i], d, mesh->normals_array[i], mesh->snormals_array[i]); + d = -DotProduct(mesh->normals_array[i], mesh->tnormals_array[i]); + VectorMA(mesh->tnormals_array[i], d, mesh->normals_array[i], mesh->tnormals_array[i]); + VectorNormalize(mesh->snormals_array[i]); + VectorNormalize(mesh->tnormals_array[i]); } - VectorCopy(surf->texinfo->vecs[0], mesh->snormals_array[i]); - VectorNegate(surf->texinfo->vecs[1], mesh->tnormals_array[i]); - //the s+t vectors are axis-aligned, so fiddle them so they're normal aligned instead - d = -DotProduct(mesh->normals_array[i], mesh->snormals_array[i]); - VectorMA(mesh->snormals_array[i], d, mesh->normals_array[i], mesh->snormals_array[i]); - d = -DotProduct(mesh->normals_array[i], mesh->tnormals_array[i]); - VectorMA(mesh->tnormals_array[i], d, mesh->normals_array[i], mesh->tnormals_array[i]); - VectorNormalize(mesh->snormals_array[i]); - VectorNormalize(mesh->tnormals_array[i]); //q1bsp has no colour information (fixme: sample from the lightmap?) for (sty = 0; sty < 1; sty++) @@ -4228,6 +4268,7 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, bspx_header_t *bspx, qbyte *m loadmodel->surfaces = out; loadmodel->numsurfaces = count; + Mod_LoadVertexNormals(loadmodel, bspx, mod_base, NULL); Mod_LoadLighting (loadmodel, bspx, mod_base, lightlump, false, &overrides, subbsp); switch(loadmodel->lightmaps.fmt) diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 18edb368d..534946dee 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -942,6 +942,12 @@ typedef struct vec4_t *points; } portal_t; +struct surfedgenormals_s { + quint32_t n; + quint32_t s; + quint32_t t; +}; + enum { MLS_NOTLOADED, @@ -1007,6 +1013,7 @@ typedef struct model_s int numvertexes; mvertex_t *vertexes; vec3_t *normals; + struct surfedgenormals_s *surfedgenormals; //for per-vertex normals int numedges; medge_t *edges;