Finally added support for ericw-tools' FACENORMALS bspx lump.

This commit is contained in:
Shpoike 2023-07-12 18:05:21 +01:00
parent b5705e4d7e
commit 6fc3d57c76
4 changed files with 80 additions and 33 deletions

View File

@ -4973,8 +4973,6 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
{ {
// load into heap // load into heap
noerrors = noerrors && Mod_LoadVertexes (mod, mod_base, &header.lumps[Q2LUMP_VERTEXES]); 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_LoadEdges (mod, mod_base, &header.lumps[Q2LUMP_EDGES], false);
noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[Q2LUMP_SURFEDGES]); noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[Q2LUMP_SURFEDGES]);
noerrors = noerrors && CModQ2_LoadSurfaces (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO]); 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) if (noerrors)
Mod_LoadEntities (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); 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); 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 && Mod_LoadMarksurfaces (mod, mod_base, &header.lumps[Q2LUMP_LEAFFACES], false);
noerrors = noerrors && CModQ2_LoadVisibility (mod, mod_base, &header.lumps[Q2LUMP_VISIBILITY]); noerrors = noerrors && CModQ2_LoadVisibility (mod, mod_base, &header.lumps[Q2LUMP_VISIBILITY]);
noerrors = noerrors && CModQ2_LoadBrushSides (mod, mod_base, &header.lumps[Q2LUMP_BRUSHSIDES]); noerrors = noerrors && CModQ2_LoadBrushSides (mod, mod_base, &header.lumps[Q2LUMP_BRUSHSIDES]);

View File

@ -2922,6 +2922,7 @@ qboolean Mod_BSPXRW_Read(struct bspxrw *ctx, const char *fname)
#endif #endif
}; };
#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->fname = fname;
ctx->origfile = FS_MallocFile(ctx->fname, FS_GAME, &ctx->origsize); ctx->origfile = FS_MallocFile(ctx->fname, FS_GAME, &ctx->origsize);
if (!ctx->origfile) if (!ctx->origfile)
@ -2936,9 +2937,10 @@ qboolean Mod_BSPXRW_Read(struct bspxrw *ctx, const char *fname)
case 30: case 30:
ctx->fg = ((i==30)?fg_halflife:fg_quake); ctx->fg = ((i==30)?fg_halflife:fg_quake);
ctx->lumpofs = 4; ctx->lumpofs = 4;
ctx->corelumps = 0; ctx->corelumps = HEADER_LUMPS;
corelumpnames = q1corelumpnames;
break; 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)); i = LittleLong(*(int*)(ctx->origfile+4));
ctx->lumpofs = 8; ctx->lumpofs = 8;
switch(i) switch(i)
@ -3172,14 +3174,11 @@ void Mod_BSPX_List_f(void)
fname = cl.worldmodel->name; fname = cl.worldmodel->name;
if (Mod_BSPXRW_Read(&ctx, fname)) if (Mod_BSPXRW_Read(&ctx, fname))
{ {
Con_Printf("%s:\n", fname);
for (i = 0; i < ctx.corelumps; i++) for (i = 0; i < ctx.corelumps; i++)
{ Con_Printf("\t%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen);
Con_Printf("%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen);
}
for ( ; i < ctx.totallumps; i++) for ( ; i < ctx.totallumps; i++)
{ Con_Printf("\t%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen);
Con_Printf("%s: %u\n", ctx.lumps[i].lumpname, (unsigned int)ctx.lumps[i].filelen);
}
Mod_BSPXRW_Free(&ctx); Mod_BSPXRW_Free(&ctx);
} }
} }

View File

@ -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); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name);
return false; return false;
} }
if (count != loadmodel->numvertexes)
return false; //invalid number of verts there, can't use this.
} }
else else
{ { //ericw's thing
in = BSPX_FindLump(bspx, mod_base, "VERTEXNORMALS", &count); unsigned int size;
if (in) quint32_t t;
count /= sizeof(vec3_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 ; i<loadmodel->numsurfedges ; 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 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)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(vec3_t));
loadmodel->normals = (vec3_t*)out; loadmodel->normals = (vec3_t*)out;
for ( i=0 ; i<count ; i++, in+=3, out+=3) for ( i=0 ; i<count ; i++, in+=3, out+=3)
@ -2532,28 +2562,38 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
} }
} }
//figure out the texture directions, for bumpmapping and stuff if (mod->surfedgenormals)
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. struct surfedgenormals_s *pv = mod->surfedgenormals + surf->firstedge + i;
VectorCopy(mod->normals[vertidx], mesh->normals_array[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 else
{ {
if (surf->flags & SURF_PLANEBACK) //figure out the texture directions, for bumpmapping and stuff
VectorNegate(surf->plane->normal, mesh->normals_array[i]); 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 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?) //q1bsp has no colour information (fixme: sample from the lightmap?)
for (sty = 0; sty < 1; sty++) 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->surfaces = out;
loadmodel->numsurfaces = count; loadmodel->numsurfaces = count;
Mod_LoadVertexNormals(loadmodel, bspx, mod_base, NULL);
Mod_LoadLighting (loadmodel, bspx, mod_base, lightlump, false, &overrides, subbsp); Mod_LoadLighting (loadmodel, bspx, mod_base, lightlump, false, &overrides, subbsp);
switch(loadmodel->lightmaps.fmt) switch(loadmodel->lightmaps.fmt)

View File

@ -942,6 +942,12 @@ typedef struct
vec4_t *points; vec4_t *points;
} portal_t; } portal_t;
struct surfedgenormals_s {
quint32_t n;
quint32_t s;
quint32_t t;
};
enum enum
{ {
MLS_NOTLOADED, MLS_NOTLOADED,
@ -1007,6 +1013,7 @@ typedef struct model_s
int numvertexes; int numvertexes;
mvertex_t *vertexes; mvertex_t *vertexes;
vec3_t *normals; vec3_t *normals;
struct surfedgenormals_s *surfedgenormals; //for per-vertex normals
int numedges; int numedges;
medge_t *edges; medge_t *edges;