mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 07:21:58 +00:00
Fix md3 skins not loading properly (since colormap change). Throw in support for eg foo.md3_0.skin files too, so armour model replacements can be handled properly.
This commit is contained in:
parent
09b9a76bb4
commit
cf2a1421bd
2 changed files with 90 additions and 21 deletions
|
@ -461,6 +461,7 @@ void GLMesh_DeleteVertexBuffers (void)
|
||||||
|
|
||||||
//from gl_model.c
|
//from gl_model.c
|
||||||
extern char loadname[]; // for hunk tags
|
extern char loadname[]; // for hunk tags
|
||||||
|
extern char diskname[]; // for skin files/etc.
|
||||||
void Mod_CalcAliasBounds (aliashdr_t *a);
|
void Mod_CalcAliasBounds (aliashdr_t *a);
|
||||||
|
|
||||||
|
|
||||||
|
@ -538,7 +539,44 @@ typedef struct {
|
||||||
int shaderIndex;
|
int shaderIndex;
|
||||||
} md3Shader_t;
|
} md3Shader_t;
|
||||||
|
|
||||||
|
qboolean Mod_GetShaderNameForSurface(const char *skinfile, const char *surfacename, char *texturename, size_t texturenamesize)
|
||||||
|
{
|
||||||
|
const char *linestart = skinfile;
|
||||||
|
//lots of `surfacename,shadername` pair lines.
|
||||||
|
while (*skinfile)
|
||||||
|
{
|
||||||
|
if (*skinfile == ',')
|
||||||
|
{
|
||||||
|
while (*linestart == ' ' || *linestart == '\t')
|
||||||
|
linestart++;
|
||||||
|
if (skinfile - linestart == strlen(surfacename))
|
||||||
|
if (!strncmp(linestart, surfacename, skinfile-linestart))
|
||||||
|
{ //okay, this is the one we're after.
|
||||||
|
skinfile++;
|
||||||
|
while(*skinfile == ' ' || *skinfile == '\t')
|
||||||
|
skinfile++;
|
||||||
|
linestart = skinfile;
|
||||||
|
while (*skinfile && *skinfile != '\n')
|
||||||
|
skinfile++;
|
||||||
|
while (skinfile > linestart && (skinfile[-1] == '\r' || skinfile[-1] == ' ' || skinfile[-1] == '\t'))
|
||||||
|
skinfile--;
|
||||||
|
|
||||||
|
if (skinfile-linestart >= texturenamesize)
|
||||||
|
return false; //too long.
|
||||||
|
memcpy(texturename, linestart, skinfile-linestart);
|
||||||
|
texturename[skinfile-linestart] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//walk to the end of the line.
|
||||||
|
while (*skinfile && *skinfile != '\n')
|
||||||
|
skinfile++;
|
||||||
|
}
|
||||||
|
else if (*skinfile++ == '\n')
|
||||||
|
linestart = skinfile;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
||||||
{
|
{
|
||||||
|
@ -559,6 +597,9 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
||||||
int numframes;
|
int numframes;
|
||||||
aliashdr_t *outhdr;
|
aliashdr_t *outhdr;
|
||||||
|
|
||||||
|
char *skinfile[countof(outhdr->textures)];
|
||||||
|
unsigned int numskinfiles;
|
||||||
|
|
||||||
start = Hunk_LowMark ();
|
start = Hunk_LowMark ();
|
||||||
|
|
||||||
pinheader = (md3Header_t *)buffer;
|
pinheader = (md3Header_t *)buffer;
|
||||||
|
@ -566,16 +607,16 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
||||||
ival = LittleLong (pinheader->version);
|
ival = LittleLong (pinheader->version);
|
||||||
if (ival != MD3_VERSION)
|
if (ival != MD3_VERSION)
|
||||||
Sys_Error ("%s has wrong version number (%i should be %i)",
|
Sys_Error ("%s has wrong version number (%i should be %i)",
|
||||||
mod->name, ival, MD3_VERSION);
|
diskname, ival, MD3_VERSION);
|
||||||
|
|
||||||
numsurfs = LittleLong (pinheader->numSurfaces);
|
numsurfs = LittleLong (pinheader->numSurfaces);
|
||||||
numframes = LittleLong(pinheader->numFrames);
|
numframes = LittleLong(pinheader->numFrames);
|
||||||
|
|
||||||
if (numframes > MAXALIASFRAMES)
|
if (numframes > MAXALIASFRAMES)
|
||||||
Sys_Error ("%s has too many frames (%i vs %i)",
|
Sys_Error ("%s has too many frames (%i vs %i)",
|
||||||
mod->name, numframes, MAXALIASFRAMES);
|
diskname, numframes, MAXALIASFRAMES);
|
||||||
if (!numsurfs)
|
if (!numsurfs)
|
||||||
Sys_Error ("%s has nosurfaces", mod->name);
|
Sys_Error ("%s has nosurfaces", diskname);
|
||||||
|
|
||||||
pinframes = (md3Frame_t*)((byte*)buffer + LittleLong(pinheader->ofsFrames));
|
pinframes = (md3Frame_t*)((byte*)buffer + LittleLong(pinheader->ofsFrames));
|
||||||
//
|
//
|
||||||
|
@ -585,13 +626,20 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
||||||
size = sizeof(aliashdr_t) + (numframes-1) * sizeof (outhdr->frames[0]);
|
size = sizeof(aliashdr_t) + (numframes-1) * sizeof (outhdr->frames[0]);
|
||||||
outhdr = (aliashdr_t *) Hunk_AllocName (size * numsurfs, loadname);
|
outhdr = (aliashdr_t *) Hunk_AllocName (size * numsurfs, loadname);
|
||||||
|
|
||||||
|
for (numskinfiles = 0; numskinfiles < countof(skinfile); numskinfiles++)
|
||||||
|
{ //q3 doesn't really support multiple skins any other way. plus this lets us fix up some texture paths...
|
||||||
|
skinfile[numskinfiles] = COM_LoadMallocFile(va("%s_%i.skin", diskname, numskinfiles), NULL);
|
||||||
|
if (!skinfile[numskinfiles])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (surf = 0, pinsurface = (md3Surface_t*)((byte*)buffer + LittleLong(pinheader->ofsSurfaces)); surf < numsurfs; surf++, pinsurface = (md3Surface_t*)((byte*)pinsurface + LittleLong(pinsurface->ofsEnd)))
|
for (surf = 0, pinsurface = (md3Surface_t*)((byte*)buffer + LittleLong(pinheader->ofsSurfaces)); surf < numsurfs; surf++, pinsurface = (md3Surface_t*)((byte*)pinsurface + LittleLong(pinsurface->ofsEnd)))
|
||||||
{
|
{
|
||||||
aliashdr_t *osurf = (aliashdr_t*)((byte*)outhdr + size*surf);
|
aliashdr_t *osurf = (aliashdr_t*)((byte*)outhdr + size*surf);
|
||||||
if (LittleLong(pinsurface->ident) != (('I'<<0)|('D'<<8)|('P'<<16)|('3'<<24)))
|
if (LittleLong(pinsurface->ident) != (('I'<<0)|('D'<<8)|('P'<<16)|('3'<<24)))
|
||||||
Sys_Error ("%s corrupt surface ident", mod->name);
|
Sys_Error ("%s corrupt surface ident", diskname);
|
||||||
if (LittleLong(pinsurface->numFrames) != numframes)
|
if (LittleLong(pinsurface->numFrames) != numframes)
|
||||||
Sys_Error ("%s mismatched framecounts", mod->name);
|
Sys_Error ("%s mismatched framecounts", diskname);
|
||||||
|
|
||||||
if (surf+1 < numsurfs)
|
if (surf+1 < numsurfs)
|
||||||
osurf->nextsurface = size;
|
osurf->nextsurface = size;
|
||||||
|
@ -647,8 +695,12 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
||||||
//load the textures
|
//load the textures
|
||||||
if (!isDedicated)
|
if (!isDedicated)
|
||||||
{
|
{
|
||||||
|
int numshaders = pinsurface->numShaders;
|
||||||
pinshader = (md3Shader_t*)((byte*)pinsurface + LittleLong(pinsurface->ofsShaders));
|
pinshader = (md3Shader_t*)((byte*)pinsurface + LittleLong(pinsurface->ofsShaders));
|
||||||
osurf->numskins = LittleLong(pinsurface->numShaders);
|
if (numskinfiles)
|
||||||
|
osurf->numskins = numskinfiles;
|
||||||
|
else
|
||||||
|
osurf->numskins = q_max(1, q_min(countof(osurf->textures), numshaders));
|
||||||
for (j = 0; j < osurf->numskins; j++, pinshader++)
|
for (j = 0; j < osurf->numskins; j++, pinshader++)
|
||||||
{
|
{
|
||||||
char texturename[MAX_QPATH];
|
char texturename[MAX_QPATH];
|
||||||
|
@ -656,6 +708,15 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
||||||
char uppername[MAX_QPATH];
|
char uppername[MAX_QPATH];
|
||||||
char lowername[MAX_QPATH];
|
char lowername[MAX_QPATH];
|
||||||
char *ext;
|
char *ext;
|
||||||
|
if (j >= numshaders)
|
||||||
|
{ //invalid skin index for the model... not a major issue I guess
|
||||||
|
q_strlcpy(texturename, diskname, sizeof(texturename));
|
||||||
|
*(char*)COM_SkipPath(texturename) = 0;
|
||||||
|
//and concat the specified name
|
||||||
|
q_strlcat(texturename, pinsurface->name, sizeof(texturename));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
//texture names in md3s are kinda fucked. they could be just names relative to the mdl, or full paths, or just simple shader names.
|
//texture names in md3s are kinda fucked. they could be just names relative to the mdl, or full paths, or just simple shader names.
|
||||||
//our texture manager is too lame to scan all 1000 possibilities
|
//our texture manager is too lame to scan all 1000 possibilities
|
||||||
if (strchr(pinshader->name, '/') || strchr(pinshader->name, '\\'))
|
if (strchr(pinshader->name, '/') || strchr(pinshader->name, '\\'))
|
||||||
|
@ -664,23 +725,26 @@ void Mod_LoadMD3Model (qmodel_t *mod, void *buffer)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //and if there's no path then we want to prefix it with our own.
|
{ //and if there's no path then we want to prefix it with our own.
|
||||||
q_strlcpy(texturename, mod->name, sizeof(texturename));
|
q_strlcpy(texturename, diskname, sizeof(texturename));
|
||||||
*(char*)COM_SkipPath(texturename) = 0;
|
*(char*)COM_SkipPath(texturename) = 0;
|
||||||
//and concat the specified name
|
//and concat the specified name
|
||||||
q_strlcat(texturename, pinshader->name, sizeof(texturename));
|
q_strlcat(texturename, pinshader->name, sizeof(texturename));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (j < numskinfiles)
|
||||||
|
Mod_GetShaderNameForSurface(skinfile[j], pinsurface->name, texturename, sizeof(texturename)); //swap it out for the skinned texture..
|
||||||
//and make sure there's no extensions. these get ignored in q3, which is kinda annoying, but this is an md3 and standards are standards (and it makes luma easier).
|
//and make sure there's no extensions. these get ignored in q3, which is kinda annoying, but this is an md3 and standards are standards (and it makes luma easier).
|
||||||
ext = (char*)COM_FileGetExtension(texturename);
|
ext = (char*)COM_FileGetExtension(texturename);
|
||||||
if (*ext)
|
if (*ext)
|
||||||
*--ext = 0;
|
*--ext = 0;
|
||||||
//luma has an extra postfix.
|
//luma has an extra postfix.
|
||||||
q_snprintf(uppername, sizeof(fullbrightname), "%s_shirt", texturename);
|
q_snprintf(uppername, sizeof(uppername), "%s_shirt", texturename);
|
||||||
q_snprintf(lowername, sizeof(fullbrightname), "%s_pants", texturename);
|
q_snprintf(lowername, sizeof(lowername), "%s_pants", texturename);
|
||||||
q_snprintf(fullbrightname, sizeof(fullbrightname), "%s_luma", texturename);
|
q_snprintf(fullbrightname, sizeof(fullbrightname), "%s_luma", texturename);
|
||||||
osurf->textures[j][0].base = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, texturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
|
osurf->textures[j][0].base = TexMgr_LoadImage(mod, texturename, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, texturename, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
|
||||||
osurf->textures[j][0].lower = TexMgr_LoadImage(mod, lowername, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, lowername, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
|
osurf->textures[j][0].lower = TexMgr_LoadImage(mod, lowername, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, lowername, 0, TEXPREF_ALLOWMISSING|TEXPREF_PAD|TEXPREF_MIPMAP);
|
||||||
osurf->textures[j][0].upper = TexMgr_LoadImage(mod, uppername, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, uppername, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_NOBRIGHT|TEXPREF_MIPMAP);
|
osurf->textures[j][0].upper = TexMgr_LoadImage(mod, uppername, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, uppername, 0, TEXPREF_ALLOWMISSING|TEXPREF_PAD|TEXPREF_MIPMAP);
|
||||||
osurf->textures[j][0].luma = TexMgr_LoadImage(mod, fullbrightname, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, fullbrightname, 0, TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP);
|
osurf->textures[j][0].luma = TexMgr_LoadImage(mod, fullbrightname, osurf->skinwidth, osurf->skinheight, SRC_EXTERNAL, NULL, fullbrightname, 0, TEXPREF_ALLOWMISSING|TEXPREF_PAD|TEXPREF_ALPHA|TEXPREF_FULLBRIGHT|TEXPREF_MIPMAP);
|
||||||
osurf->textures[j][3] = osurf->textures[j][2] = osurf->textures[j][1] = osurf->textures[j][0];
|
osurf->textures[j][3] = osurf->textures[j][2] = osurf->textures[j][1] = osurf->textures[j][0];
|
||||||
}
|
}
|
||||||
if (osurf->numskins)
|
if (osurf->numskins)
|
||||||
|
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
qmodel_t *loadmodel;
|
qmodel_t *loadmodel;
|
||||||
char loadname[32]; // for hunk tags
|
char loadname[32]; // for hunk tags
|
||||||
|
char diskname[MAX_QPATH]; // for loading related name-based files.
|
||||||
|
|
||||||
static void Mod_LoadSpriteModel (qmodel_t *mod, void *buffer);
|
static void Mod_LoadSpriteModel (qmodel_t *mod, void *buffer);
|
||||||
static void Mod_LoadBrushModel (qmodel_t *mod, void *buffer);
|
static void Mod_LoadBrushModel (qmodel_t *mod, void *buffer);
|
||||||
|
@ -381,12 +382,16 @@ static qmodel_t *Mod_LoadModel (qmodel_t *mod, qboolean crash)
|
||||||
Con_DPrintf("Ignoring %s from lower priority path\n", newname);
|
Con_DPrintf("Ignoring %s from lower priority path\n", newname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
memcpy(diskname, newname, sizeof(newname));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!buf)
|
if (!buf)
|
||||||
|
{
|
||||||
|
memcpy(diskname, mod->name, sizeof(mod->name));
|
||||||
buf = COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), & mod->path_id);
|
buf = COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), & mod->path_id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
if (crash)
|
if (crash)
|
||||||
|
|
Loading…
Reference in a new issue