Fix up our shoddy md5 format support.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6027 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-08-20 04:53:39 +00:00
parent 34f55c05e6
commit 4426a286d2
2 changed files with 57 additions and 2 deletions

View File

@ -239,7 +239,7 @@ cvar_t r_telealpha = CVARF ("r_telealpha", "",
cvar_t r_waterwarp = CVARFD ("r_waterwarp", "1", cvar_t r_waterwarp = CVARFD ("r_waterwarp", "1",
CVAR_ARCHIVE, "Enables fullscreen warp, preferably via glsl. -1 specifies to force the fov warp fallback instead which can give a smidge more performance."); CVAR_ARCHIVE, "Enables fullscreen warp, preferably via glsl. -1 specifies to force the fov warp fallback instead which can give a smidge more performance.");
cvar_t r_replacemodels = CVARFD ("r_replacemodels", IFMINIMAL("","md3 md2"), cvar_t r_replacemodels = CVARFD ("r_replacemodels", IFMINIMAL("","md3 md2 md5mesh"),
CVAR_ARCHIVE, "A list of filename extensions to attempt to use instead of mdl."); CVAR_ARCHIVE, "A list of filename extensions to attempt to use instead of mdl.");
cvar_t r_lightmap_nearest = CVARFD ("gl_lightmap_nearest", "0", CVAR_ARCHIVE, "Use nearest sampling for lightmaps. This will give a more blocky look. Meaningless when gl_lightmap_average is enabled."); cvar_t r_lightmap_nearest = CVARFD ("gl_lightmap_nearest", "0", CVAR_ARCHIVE, "Use nearest sampling for lightmaps. This will give a more blocky look. Meaningless when gl_lightmap_average is enabled.");

View File

@ -29,6 +29,9 @@ cvar_t mod_nomipmap = CVARD ("mod_nomipmap", "0", "Disables the use of mip
#ifdef MODELFMT_OBJ #ifdef MODELFMT_OBJ
cvar_t mod_obj_orientation = CVARD("mod_obj_orientation", "1", "Controls how the model's axis are interpreted.\n0: x=forward, z=up (Quake)\n1: x=forward, y=up\n2: z=forward, y=up"); cvar_t mod_obj_orientation = CVARD("mod_obj_orientation", "1", "Controls how the model's axis are interpreted.\n0: x=forward, z=up (Quake)\n1: x=forward, y=up\n2: z=forward, y=up");
#endif #endif
#ifdef MD5MODELS
cvar_t mod_md5_singleanimation = CVARD("mod_md5_singleanimation", "1", "When loading an md5mesh file, also attempt to load an .md5anim file, and unpack it into individual poses. Use 0 for mods that will be precaching their own md5anims for use with skeletal objects.");
#endif
static void QDECL r_meshpitch_callback(cvar_t *var, char *oldvalue) static void QDECL r_meshpitch_callback(cvar_t *var, char *oldvalue)
{ {
if (!strcmp(var->string, "-1") || !strcmp(var->string, "1")) if (!strcmp(var->string, "-1") || !strcmp(var->string, "1"))
@ -8720,6 +8723,9 @@ static qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *proto
*poseofs = posedata = ZG_Malloc(&mod->memgroup, sizeof(float)*12*numjoints*numframes); *poseofs = posedata = ZG_Malloc(&mod->memgroup, sizeof(float)*12*numjoints*numframes);
if (!prototype->baseframeofs)
prototype->baseframeofs = posedata;
if (prototype->numbones) if (prototype->numbones)
{ {
if (prototype->numbones != numjoints) if (prototype->numbones != numjoints)
@ -8813,7 +8819,9 @@ static qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *proto
for (i = 0; i < numframes; i++) for (i = 0; i < numframes; i++)
{ {
EXPECT("frame"); EXPECT("frame");
EXPECT(va("%i", i)); buffer = COM_ParseOut(buffer, token, sizeof(token));
if (atoi(token) != i)
MD5ERROR1PARAM("MD5ANIM: expected frame %i", i);
EXPECT("{"); EXPECT("{");
for (j = 0; j < numanimatedparts; j++) for (j = 0; j < numanimatedparts; j++)
{ {
@ -8861,11 +8869,13 @@ static qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *proto
BZ_Free(boneflags); BZ_Free(boneflags);
BZ_Free(baseframe); BZ_Free(baseframe);
memset(&grp, 0, sizeof(grp));
Q_strncpyz(grp.name, "", sizeof(grp.name)); Q_strncpyz(grp.name, "", sizeof(grp.name));
grp.skeltype = SKEL_RELATIVE; grp.skeltype = SKEL_RELATIVE;
grp.numposes = numframes; grp.numposes = numframes;
grp.rate = framespersecond; grp.rate = framespersecond;
grp.loop = true; grp.loop = true;
grp.boneofs = *poseofs;
*gat = grp; *gat = grp;
return true; return true;
@ -8965,6 +8975,8 @@ static galiasinfo_t *Mod_ParseMD5MeshModel(model_t *mod, char *buffer, char *mod
pose->numposes = 1; pose->numposes = 1;
pose->boneofs = posedata; pose->boneofs = posedata;
root->baseframeofs = posedata;
Q_strncpyz(pose->name, "base", sizeof(pose->name)); Q_strncpyz(pose->name, "base", sizeof(pose->name));
EXPECT("{"); EXPECT("{");
@ -9045,6 +9057,7 @@ static galiasinfo_t *Mod_ParseMD5MeshModel(model_t *mod, char *buffer, char *mod
} }
Mod_DefaultMesh(inf, COM_SkipPath(mod->name), 0); Mod_DefaultMesh(inf, COM_SkipPath(mod->name), 0);
inf->shares_bones = 0;
inf->ofsbones = bones; inf->ofsbones = bones;
inf->numbones = numjoints; inf->numbones = numjoints;
inf->numanimations = 1; inf->numanimations = 1;
@ -9238,6 +9251,8 @@ static galiasinfo_t *Mod_ParseMD5MeshModel(model_t *mod, char *buffer, char *mod
static qboolean QDECL Mod_LoadMD5MeshModel(model_t *mod, void *buffer, size_t fsize) static qboolean QDECL Mod_LoadMD5MeshModel(model_t *mod, void *buffer, size_t fsize)
{ {
galiasinfo_t *root; galiasinfo_t *root;
char animname[MAX_QPATH];
void *animfile;
root = Mod_ParseMD5MeshModel(mod, buffer, mod->name); root = Mod_ParseMD5MeshModel(mod, buffer, mod->name);
if (root == NULL) if (root == NULL)
@ -9245,6 +9260,45 @@ static qboolean QDECL Mod_LoadMD5MeshModel(model_t *mod, void *buffer, size_t fs
return false; return false;
} }
if (mod_md5_singleanimation.ival && root->numanimations==1 && root->ofsanimations[0].skeltype==SKEL_ABSOLUTE) //make sure there's only the base pose...
{
COM_StripAllExtensions(mod->name, animname, sizeof(animname));
Q_strncatz(animname, ".md5anim", sizeof(animname));
animfile = FS_LoadMallocFile(animname, NULL);
if (animfile) //FIXME: make non fatal somehow..
{
galiasinfo_t *surf;
void *np = NULL;
galiasanimation_t ng;
if (Mod_ParseMD5Anim(mod, animfile, root, &np, &ng) && ng.numposes>0)
{
galiasanimation_t *a;
int i;
root->numanimations = ng.numposes;
root->ofsanimations = ZG_Malloc(&mod->memgroup, ng.numposes*sizeof(*root->ofsanimations));
//pull out each frame individually
for (i = 0; i < ng.numposes; i++)
{
a = &root->ofsanimations[i];
a->skeltype = ng.skeltype;
a->loop = false;
a->numposes = 1;
a->rate = 10;
a->boneofs = (float*)np + i*12*root->numbones;
Q_snprintfz(a->name, sizeof(a->name), "%s_%i", animname, i);
}
for(surf = root;(surf = surf->nextsurf);)
{
surf->ofsanimations = root->ofsanimations;
surf->numanimations = root->numanimations;
}
}
Z_Free(animfile);
}
}
mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files.
@ -9835,6 +9889,7 @@ void Alias_Register(void)
Mod_RegisterModelFormatMagic(NULL, "Inter-Quake Model (iqm)", ('I'<<0)+('N'<<8)+('T'<<16)+('E'<<24), Mod_LoadInterQuakeModel); Mod_RegisterModelFormatMagic(NULL, "Inter-Quake Model (iqm)", ('I'<<0)+('N'<<8)+('T'<<16)+('E'<<24), Mod_LoadInterQuakeModel);
#endif #endif
#ifdef MD5MODELS #ifdef MD5MODELS
Cvar_Register(&mod_md5_singleanimation, NULL);
Mod_RegisterModelFormatText(NULL, "MD5 Mesh/Anim (md5mesh)", "MD5Version", Mod_LoadMD5MeshModel); Mod_RegisterModelFormatText(NULL, "MD5 Mesh/Anim (md5mesh)", "MD5Version", Mod_LoadMD5MeshModel);
Mod_RegisterModelFormatText(NULL, "External Anim", "EXTERNALANIM", Mod_LoadCompositeAnim); Mod_RegisterModelFormatText(NULL, "External Anim", "EXTERNALANIM", Mod_LoadCompositeAnim);
#endif #endif