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:
parent
74e9015f9d
commit
130d758077
1 changed files with 50 additions and 18 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue