Prevent IQM loader from crashing on bad models.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6250 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2022-05-28 17:59:45 +00:00
parent 74e9015f9d
commit 130d758077
1 changed files with 50 additions and 18 deletions

View File

@ -5673,12 +5673,13 @@ qboolean Mod_FrameInfoForNum(model_t *model, int surfaceidx, int num, char **nam
if (!inf || num >= inf->numanimations)
return false;
group = inf->ofsanimations;
group += num;
*name = group[num].name;
*numframes = group[num].numposes;
*loop = group[num].loop;
*name = group->name;
*numframes = group->numposes;
*loop = group->loop;
*duration = group->numposes/group->rate;
*act = group[num].action;
*act = group->action;
return true;
}
#ifdef HALFLIFEMODELS
@ -8218,6 +8219,17 @@ static void Mod_CleanWeights(const char *modelname, size_t numverts, vec4_t *owe
Con_DPrintf(CON_ERROR"%s has invalid vertex weights. Verticies will probably be attached to the wrong bones\n", modelname);
}
struct iqmstrings_s
{
const char *base;
size_t size;
};
static const char *Mod_IQMString(struct iqmstrings_s *strings, int offset)
{
if (offset < 0 || offset >= strings->size)
return "<BADSTRING>";
return strings->base + offset;
}
static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsize)
{
const struct iqmheader *h = (const struct iqmheader *)buffer;
@ -8227,7 +8239,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
const struct iqmanim *anim;
const struct iqmext_fte_mesh *ftemesh;
const struct iqmext_fte_event *fteevents;
const char *strings;
struct iqmstrings_s strings;
const unsigned int *fteskincount;
const struct iqmext_fte_skin_meshskin *fteskins;
@ -8363,7 +8375,8 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
return NULL;
}
strings = buffer + h->ofs_text;
strings.base = buffer + h->ofs_text;
strings.size = h->num_text;
/*try to completely disregard all the info the creator carefully added to their model...*/
numgroups = 0;
@ -8385,7 +8398,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
framegroups[i].loop = !!(LittleLong(anim[i].flags) & IQM_LOOP);
framegroups[i].action = -1;
framegroups[i].actionweight = 0;
Q_strncpyz(framegroups[i].name, strings+anim[i].name, sizeof(fgroup[i].name));
Q_strncpyz(framegroups[i].name, Mod_IQMString(&strings, anim[i].name), sizeof(fgroup[i].name));
}
}
else
@ -8467,7 +8480,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
//joint info (mesh)
for (i = 0; i < h->num_joints; i++)
{
Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(bones[i].name));
Q_strncpyz(bones[i].name, Mod_IQMString(&strings, ijoint[i].name), sizeof(bones[i].name));
bones[i].parent = ijoint[i].parent;
GenMatrixPosQuat3Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, mat);
@ -8499,6 +8512,9 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
GenMatrixPosQuat3Scale(pos, quat, scale, &opose[(i*h->num_poses+j)*12]);
}
}
if (framedata != (const unsigned short*)(buffer + h->ofs_frames) + h->num_framechannels*h->num_frames)
Con_Printf("%s: Incorrect number of framechannels found\n", mod->name);
}
else
{
@ -8508,22 +8524,38 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
vec4_t quat;
vec3_t scale;
float mat[12];
int fc;
//joint info (mesh)
for (i = 0; i < h->num_joints; i++)
{
Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(bones[i].name));
bones[i].parent = ijoint[i].parent;
Q_strncpyz(bones[i].name, Mod_IQMString(&strings, ijoint[i].name), sizeof(bones[i].name));
GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, mat);
if (ijoint[i].parent >= 0)
if (ijoint[i].parent >= 0 && ijoint[i].parent < i)
{
bones[i].parent = ijoint[i].parent;
Matrix3x4_Multiply(mat, &oposebase[ijoint[i].parent*12], &oposebase[i*12]);
}
else
{
memcpy(&oposebase[i*12], mat, sizeof(mat));
bones[i].parent = -1;
}
Matrix3x4_Invert_Simple(&oposebase[i*12], bones[i].inverse);
}
for (fc = 0, j = 0, p = ipose; j < h->num_poses; j++, p++)
{
for (i = 0; i < 10; i++)
if (p->mask & (1<<i))
fc++;
}
if (fc != h->num_framechannels)
Con_Printf("%s: Incorrect number of framechannels found (%i, expected %i)\n", mod->name, h->num_framechannels, fc);
else
//pose info (anim)
for (i = 0; i < h->num_frames; i++)
{
@ -8592,8 +8624,8 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
{
oevent->timestamp = fteevents->timestamp;
oevent->code = fteevents->evcode;
oevent->data = ZG_Malloc(&mod->memgroup, strlen(strings+fteevents->evdata_str)+1);
strcpy(oevent->data, strings+fteevents->evdata_str);
oevent->data = ZG_Malloc(&mod->memgroup, strlen(Mod_IQMString(&strings, fteevents->evdata_str))+1);
strcpy(oevent->data, Mod_IQMString(&strings, fteevents->evdata_str));
link = &fgroup[fteevents->anim].events;
while (*link && (*link)->timestamp <= oevent->timestamp)
link = &(*link)->next;
@ -8641,7 +8673,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
{
if (h->num_meshes)
{
Mod_DefaultMesh(&gai[i], strings+mesh[i].name, i);
Mod_DefaultMesh(&gai[i], Mod_IQMString(&strings, mesh[i].name), i);
firstvert = LittleLong(mesh[i].first_vertex);
numverts = LittleLong(mesh[i].num_vertexes);
numtris = LittleLong(mesh[i].num_triangles);
@ -8704,10 +8736,10 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
skin->frame = ZG_Malloc(&mod->memgroup, sizeof(*skin->frame)*skin->numframes);
for (t = 0; t < skin->numframes; t++, sf++)
{
Q_strncpyz(skin->frame[t].shadername, strings+sf->material_idx, sizeof(skin->frame[t].shadername));
Q_strncpyz(skin->frame[t].shadername, Mod_IQMString(&strings, sf->material_idx), sizeof(skin->frame[t].shadername));
if (sf->shadertext_idx && sf->shadertext_idx<h->num_text)
{
const char *stxt = strings+sf->shadertext_idx;
const char *stxt = Mod_IQMString(&strings, sf->shadertext_idx);
skin->frame[t].defaultshader = strcpy(ZG_Malloc(&mod->memgroup, strlen(stxt)+1), stxt);
}
}
@ -8718,7 +8750,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
skin->numframes = 1; //non-sequenced skins.
skin->frame = skinframe = ZG_Malloc(&mod->memgroup, sizeof(*skin->frame)*skin->numframes);
Q_strncpyz(skinframe->shadername, strings+mesh[i].material, sizeof(skinframe->shadername));
Q_strncpyz(skinframe->shadername, Mod_IQMString(&strings, mesh[i].material), sizeof(skinframe->shadername));
}
}
gai[i].numskins = skin-gai[i].ofsskins;
@ -8743,7 +8775,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
}
gai[i].numindexes = idx - gai[i].ofs_indexes;
if (gai[i].numindexes != numtris*3)
Con_Printf("%s(%s|%s): Dropped %u of %u triangles due to index size limit\n", mod->name, gai[i].surfacename,strings+mesh[i].material, numtris-gai[i].numindexes/3, numtris);
Con_Printf("%s(%s|%s): Dropped %u of %u triangles due to index size limit\n", mod->name, gai[i].surfacename,Mod_IQMString(&strings, mesh[i].material), numtris-gai[i].numindexes/3, numtris);
/*verts*/
gai[i].shares_verts = i;