mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-22 20:51:31 +00:00
models: reuse md2 skins in md5 models
This commit is contained in:
parent
ca0e150232
commit
ded6b9c858
4 changed files with 209 additions and 29 deletions
|
@ -774,9 +774,13 @@ Mod_LoadModel_MD2(const char *mod_name, const void *buffer, int modfilelen,
|
|||
|
||||
for (i = 0; i < pheader->num_skins; i++)
|
||||
{
|
||||
char *skin;
|
||||
|
||||
skin = (char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME;
|
||||
skin[MAX_SKINNAME - 1] = 0;
|
||||
|
||||
R_Printf(PRINT_DEVELOPER, "%s: %s #%d: Should load external '%s'\n",
|
||||
__func__, mod_name, i,
|
||||
(char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME);
|
||||
__func__, mod_name, i, skin);
|
||||
}
|
||||
|
||||
*type = mod_alias;
|
||||
|
@ -784,6 +788,48 @@ Mod_LoadModel_MD2(const char *mod_name, const void *buffer, int modfilelen,
|
|||
return extradata;
|
||||
}
|
||||
|
||||
static void
|
||||
Mod_LoadSkinList_MD2(const char *mod_name, const void *buffer, int modfilelen,
|
||||
char **skins, int *numskins)
|
||||
{
|
||||
dmdl_t pinmodel;
|
||||
int i;
|
||||
|
||||
if (modfilelen < sizeof(pinmodel))
|
||||
{
|
||||
R_Printf(PRINT_ALL, "%s: %s has incorrect header size (%i should be %ld)",
|
||||
__func__, mod_name, modfilelen, sizeof(pinmodel));
|
||||
}
|
||||
|
||||
for (i=0 ; i<sizeof(dmdl_t)/sizeof(int) ; i++)
|
||||
{
|
||||
((int *)&pinmodel)[i] = LittleLong(((int *)buffer)[i]);
|
||||
}
|
||||
|
||||
if (pinmodel.version != ALIAS_VERSION)
|
||||
{
|
||||
R_Printf(PRINT_ALL, "%s: %s has wrong version number (%i should be %i)",
|
||||
__func__, mod_name, pinmodel.version, ALIAS_VERSION);
|
||||
}
|
||||
|
||||
if (pinmodel.ofs_end < 0 || pinmodel.ofs_end > modfilelen)
|
||||
{
|
||||
R_Printf(PRINT_ALL, "%s: model %s file size(%d) too small, should be %d",
|
||||
__func__, mod_name, modfilelen, pinmodel.ofs_end);
|
||||
}
|
||||
|
||||
if (pinmodel.num_skins < 0)
|
||||
{
|
||||
R_Printf(PRINT_ALL, "%s: model %s file has incorrect skins count %d",
|
||||
__func__, mod_name, pinmodel.num_skins);
|
||||
}
|
||||
|
||||
*numskins = pinmodel.num_skins;
|
||||
*skins = malloc(pinmodel.num_skins * MAX_SKINNAME);
|
||||
|
||||
memcpy(*skins, (char *)buffer + pinmodel.ofs_skins,
|
||||
pinmodel.num_skins * MAX_SKINNAME);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
|
@ -1360,6 +1406,19 @@ Mod_LoadMinMaxUpdate(const char *mod_name, vec3_t mins, vec3_t maxs, void *extra
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Mod_LoadSkinList(const char *mod_name, const void *buffer, int modfilelen,
|
||||
char **skins, int *numskins)
|
||||
{
|
||||
switch (LittleLong(*(unsigned *)buffer))
|
||||
{
|
||||
case IDALIASHEADER:
|
||||
Mod_LoadSkinList_MD2(mod_name, buffer, modfilelen,
|
||||
skins, numskins);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadModel
|
||||
|
@ -1415,42 +1474,52 @@ Mod_LoadModel(const char *mod_name, const void *buffer, int modfilelen,
|
|||
return extradata;
|
||||
}
|
||||
|
||||
/* Add md5 to full file name */
|
||||
static void
|
||||
Mod_LoadFileInsertMD5(char *newname, const char *oldname, int size)
|
||||
{
|
||||
const char *filename;
|
||||
|
||||
filename = COM_SkipPath(oldname);
|
||||
memset(newname, 0, size);
|
||||
memcpy(newname, oldname, strlen(oldname) - strlen(filename));
|
||||
Q_strlcat(newname, "md5/", size);
|
||||
Q_strlcat(newname, filename, size);
|
||||
}
|
||||
|
||||
static int
|
||||
Mod_LoadFileMD5Merge(const char *namewe, void **buffer)
|
||||
{
|
||||
int fullsize, filesize_anim, filesize;
|
||||
char *final_buffer = NULL;
|
||||
void *anim_buffer = NULL;
|
||||
int fullsize, filesize_anim, filesize, filesize_skins;
|
||||
char *final_buffer = NULL, *skins_list = NULL;
|
||||
void *anim_buffer = NULL, *skins_buffer = NULL;
|
||||
qboolean md5path = false;
|
||||
char newname[256];
|
||||
|
||||
/* search mesh file */
|
||||
Q_strlcpy(newname, namewe, sizeof(newname));
|
||||
Q_strlcat(newname, ".md5mesh", sizeof(newname));
|
||||
filesize = ri.FS_LoadFile(newname, buffer);
|
||||
|
||||
#if 0
|
||||
/* check overwrite file */
|
||||
if (filesize <= 0)
|
||||
{
|
||||
const char *model_name;
|
||||
char model_path[256];
|
||||
char md5modelname[256];
|
||||
|
||||
model_name = COM_SkipPath(namewe);
|
||||
memset(model_path, 0, sizeof(model_path));
|
||||
memcpy(model_path, namewe, strlen(namewe) - strlen(model_name));
|
||||
Mod_LoadFileInsertMD5(md5modelname, newname, sizeof(md5modelname));
|
||||
|
||||
Q_strlcpy(newname, model_path, sizeof(newname));
|
||||
Q_strlcat(newname, "md5/", sizeof(newname));
|
||||
Q_strlcat(newname, model_name, sizeof(newname));
|
||||
Q_strlcat(newname, ".md5mesh", sizeof(newname));
|
||||
|
||||
filesize = ri.FS_LoadFile(newname, buffer);
|
||||
filesize = ri.FS_LoadFile(md5modelname, buffer);
|
||||
/* no replace file */
|
||||
if (filesize <= 0)
|
||||
{
|
||||
return filesize;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
md5path = true;
|
||||
strcpy(newname, md5modelname);
|
||||
}
|
||||
|
||||
/* search animation file */
|
||||
memcpy(newname + strlen(newname) - strlen("mesh"), "anim", strlen("anim"));
|
||||
filesize_anim = ri.FS_LoadFile(newname, &anim_buffer);
|
||||
if (filesize_anim <= 0)
|
||||
|
@ -1459,13 +1528,63 @@ Mod_LoadFileMD5Merge(const char *namewe, void **buffer)
|
|||
return filesize;
|
||||
}
|
||||
|
||||
/* search skins list */
|
||||
Q_strlcpy(newname, namewe, sizeof(newname));
|
||||
Q_strlcat(newname, ".md2", sizeof(newname));
|
||||
filesize_skins = ri.FS_LoadFile(newname, &skins_buffer);
|
||||
if (filesize_skins > 0)
|
||||
{
|
||||
char *skins = NULL;
|
||||
int numskins = 0, i;
|
||||
|
||||
Mod_LoadSkinList(newname, skins_buffer, filesize_skins,
|
||||
&skins, &numskins);
|
||||
ri.FS_FreeFile(skins_buffer);
|
||||
|
||||
/*
|
||||
* 20 -> numskins <num> | skin <num> "MAX_SKINNAME" + md5
|
||||
*/
|
||||
skins_list = malloc((numskins + 1) * (MAX_SKINNAME + 20));
|
||||
sprintf(skins_list, "\nnumskins %d\n", numskins);
|
||||
for(i = 0; i < numskins; i++)
|
||||
{
|
||||
char *skinname = skins + MAX_SKINNAME * i;
|
||||
|
||||
if (!md5path)
|
||||
{
|
||||
sprintf(skins_list + strlen(skins_list), "skin %d \"%s\"\n",
|
||||
i, skinname);
|
||||
}
|
||||
else
|
||||
{
|
||||
char md5skinname[256];
|
||||
|
||||
Mod_LoadFileInsertMD5(md5skinname, skinname, sizeof(md5skinname));
|
||||
|
||||
sprintf(skins_list + strlen(skins_list), "skin %d \"%s\"\n",
|
||||
i, md5skinname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare final file */
|
||||
fullsize = filesize + filesize_anim + 1;
|
||||
if (skins_list)
|
||||
{
|
||||
fullsize += strlen(skins_list);
|
||||
}
|
||||
|
||||
/* allocate new buffer, ERR_FATAL on alloc fail */
|
||||
final_buffer = ri.FS_AllocFile(fullsize);
|
||||
|
||||
/* copy combined information */
|
||||
memcpy(final_buffer, *buffer, filesize);
|
||||
if (skins_list)
|
||||
{
|
||||
memcpy(final_buffer + filesize, skins_list, strlen(skins_list));
|
||||
filesize += strlen(skins_list);
|
||||
free(skins_list);
|
||||
}
|
||||
final_buffer[filesize] = 0;
|
||||
memcpy(final_buffer + filesize + 1, anim_buffer, filesize_anim);
|
||||
|
||||
|
|
|
@ -103,12 +103,14 @@ typedef struct md5_model_s
|
|||
md5_frame_t *skelFrames;
|
||||
int *vertexIndices;
|
||||
vec2_t *st;
|
||||
char *skins;
|
||||
|
||||
int num_frames;
|
||||
int num_joints;
|
||||
int num_meshes;
|
||||
int num_verts;
|
||||
int num_tris;
|
||||
int num_skins;
|
||||
int frameRate;
|
||||
} md5_model_t;
|
||||
|
||||
|
@ -569,6 +571,58 @@ ReadMD5Model(const char *buffer, size_t size)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (sscanf(buff, "numskins %d", &mdl->num_skins) == 1)
|
||||
{
|
||||
if (mdl->num_skins > 0)
|
||||
{
|
||||
mdl->skins = malloc(mdl->num_skins * MAX_SKINNAME);
|
||||
memset(mdl->skins, 0, mdl->num_skins * MAX_SKINNAME);
|
||||
}
|
||||
}
|
||||
else if (strncmp (buff, "skin ", 5) == 0)
|
||||
{
|
||||
const char *token;
|
||||
char *line;
|
||||
int pos;
|
||||
|
||||
line = buff + 5;
|
||||
|
||||
token = COM_Parse(&line);
|
||||
pos = (int)strtol(token, (char **)NULL, 10);
|
||||
if (pos < mdl->num_skins)
|
||||
{
|
||||
int quote = 0, j = 0;
|
||||
char *skinname;
|
||||
|
||||
skinname = mdl->skins + pos * MAX_SKINNAME;
|
||||
|
||||
/* Copy the shader name whithout the quote marks */
|
||||
while (*line)
|
||||
{
|
||||
if (*line == '"')
|
||||
{
|
||||
quote++;
|
||||
|
||||
if (quote >= 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (quote == 1)
|
||||
{
|
||||
if ((j >= (MAX_SKINNAME - 1)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
skinname[j] = *line;
|
||||
j ++;
|
||||
}
|
||||
|
||||
line ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sscanf(buff, "numJoints %d", &mdl->num_joints) == 1)
|
||||
{
|
||||
if (mdl->num_joints > 0)
|
||||
|
@ -753,6 +807,12 @@ FreeModelMd5(md5_model_t *mdl)
|
|||
mdl->baseSkel = NULL;
|
||||
}
|
||||
|
||||
if (mdl->skins)
|
||||
{
|
||||
free(mdl->skins);
|
||||
mdl->skins = NULL;
|
||||
}
|
||||
|
||||
if (mdl->meshes)
|
||||
{
|
||||
/* Free mesh data */
|
||||
|
@ -1050,7 +1110,7 @@ Mod_LoadModel_MD5(const char *mod_name, const void *buffer, int modfilelen,
|
|||
|
||||
int framesize = sizeof(daliasxframe_t) + sizeof(dxtrivertx_t) * num_verts;
|
||||
int ofs_skins = sizeof(dmdx_t);
|
||||
int ofs_frames = ofs_skins + md5file->num_meshes * MAX_SKINNAME;
|
||||
int ofs_frames = ofs_skins + md5file->num_skins * MAX_SKINNAME;
|
||||
int ofs_glcmds = ofs_frames + framesize * md5file->num_frames;
|
||||
int ofs_meshes = ofs_glcmds + num_glcmds * sizeof(int);
|
||||
int ofs_tris = ofs_meshes + md5file->num_tris * sizeof(dtriangle_t);
|
||||
|
@ -1059,7 +1119,7 @@ Mod_LoadModel_MD5(const char *mod_name, const void *buffer, int modfilelen,
|
|||
|
||||
dmdx_t *pheader = NULL;
|
||||
|
||||
*numskins = md5file->num_meshes;
|
||||
*numskins = md5file->num_skins;
|
||||
extradata = Hunk_Begin(ofs_end + Q_max(*numskins, MAX_MD2SKINS) * sizeof(struct image_s *));
|
||||
pheader = Hunk_Alloc(ofs_end);
|
||||
*skins = Hunk_Alloc((*numskins) * sizeof(struct image_s *));
|
||||
|
@ -1139,18 +1199,19 @@ Mod_LoadModel_MD5(const char *mod_name, const void *buffer, int modfilelen,
|
|||
num_tris += md5file->meshes[i].num_tris; // vertexIndices
|
||||
}
|
||||
|
||||
memset((char *)pheader + pheader->ofs_skins, 0,
|
||||
/* register all skins */
|
||||
memcpy((char *)pheader + pheader->ofs_skins, md5file->skins,
|
||||
pheader->num_skins * MAX_SKINNAME);
|
||||
|
||||
/* use meshes names as replacement for skins */
|
||||
for (i = 0; i < pheader->num_skins; i++)
|
||||
{
|
||||
strncpy((char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME,
|
||||
md5file->meshes[i].shader, MAX_SKINNAME - 1);
|
||||
char *skin;
|
||||
|
||||
skin = (char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME;
|
||||
skin[MAX_SKINNAME - 1] = 0;
|
||||
|
||||
R_Printf(PRINT_DEVELOPER, "%s: %s #%d: Should load external '%s'\n",
|
||||
__func__, mod_name, i,
|
||||
(char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME);
|
||||
__func__, mod_name, i, skin);
|
||||
}
|
||||
|
||||
if (md5file)
|
||||
|
|
|
@ -143,7 +143,7 @@ LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *heigh
|
|||
|
||||
if (!raw || len < sizeof(pcx_t))
|
||||
{
|
||||
R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
|
||||
R_Printf(PRINT_DEVELOPER, "Bad pcx file %s, length %d\n", filename, len);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ FS_FOpenFile(const char *rawname, fileHandle_t *f, qboolean gamedir_only)
|
|||
// Evil hack for maps.lst and players/
|
||||
// TODO: A flag to ignore paks would be better
|
||||
if ((strcmp(fs_gamedirvar->string, "") == 0) && search->pack) {
|
||||
if ((strcmp(name, "maps.lst") == 0)|| (strncmp(name, "players/", 8) == 0)) {
|
||||
if ((strcmp(name, "maps.lst") == 0) || (strncmp(name, "players/", 8) == 0)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue