mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-03-09 01:50:58 +00:00
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)
|
if (!inf || num >= inf->numanimations)
|
||||||
return false;
|
return false;
|
||||||
group = inf->ofsanimations;
|
group = inf->ofsanimations;
|
||||||
|
group += num;
|
||||||
|
|
||||||
*name = group[num].name;
|
*name = group->name;
|
||||||
*numframes = group[num].numposes;
|
*numframes = group->numposes;
|
||||||
*loop = group[num].loop;
|
*loop = group->loop;
|
||||||
*duration = group->numposes/group->rate;
|
*duration = group->numposes/group->rate;
|
||||||
*act = group[num].action;
|
*act = group->action;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#ifdef HALFLIFEMODELS
|
#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);
|
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)
|
static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsize)
|
||||||
{
|
{
|
||||||
const struct iqmheader *h = (const struct iqmheader *)buffer;
|
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 iqmanim *anim;
|
||||||
const struct iqmext_fte_mesh *ftemesh;
|
const struct iqmext_fte_mesh *ftemesh;
|
||||||
const struct iqmext_fte_event *fteevents;
|
const struct iqmext_fte_event *fteevents;
|
||||||
const char *strings;
|
struct iqmstrings_s strings;
|
||||||
|
|
||||||
const unsigned int *fteskincount;
|
const unsigned int *fteskincount;
|
||||||
const struct iqmext_fte_skin_meshskin *fteskins;
|
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;
|
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...*/
|
/*try to completely disregard all the info the creator carefully added to their model...*/
|
||||||
numgroups = 0;
|
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].loop = !!(LittleLong(anim[i].flags) & IQM_LOOP);
|
||||||
framegroups[i].action = -1;
|
framegroups[i].action = -1;
|
||||||
framegroups[i].actionweight = 0;
|
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
|
else
|
||||||
|
@ -8467,7 +8480,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
//joint info (mesh)
|
//joint info (mesh)
|
||||||
for (i = 0; i < h->num_joints; i++)
|
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;
|
bones[i].parent = ijoint[i].parent;
|
||||||
|
|
||||||
GenMatrixPosQuat3Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, mat);
|
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]);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -8508,22 +8524,38 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
vec4_t quat;
|
vec4_t quat;
|
||||||
vec3_t scale;
|
vec3_t scale;
|
||||||
float mat[12];
|
float mat[12];
|
||||||
|
int fc;
|
||||||
|
|
||||||
//joint info (mesh)
|
//joint info (mesh)
|
||||||
for (i = 0; i < h->num_joints; i++)
|
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;
|
|
||||||
|
|
||||||
GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, mat);
|
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]);
|
Matrix3x4_Multiply(mat, &oposebase[ijoint[i].parent*12], &oposebase[i*12]);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
memcpy(&oposebase[i*12], mat, sizeof(mat));
|
memcpy(&oposebase[i*12], mat, sizeof(mat));
|
||||||
|
bones[i].parent = -1;
|
||||||
|
}
|
||||||
Matrix3x4_Invert_Simple(&oposebase[i*12], bones[i].inverse);
|
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)
|
//pose info (anim)
|
||||||
for (i = 0; i < h->num_frames; i++)
|
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->timestamp = fteevents->timestamp;
|
||||||
oevent->code = fteevents->evcode;
|
oevent->code = fteevents->evcode;
|
||||||
oevent->data = ZG_Malloc(&mod->memgroup, strlen(strings+fteevents->evdata_str)+1);
|
oevent->data = ZG_Malloc(&mod->memgroup, strlen(Mod_IQMString(&strings, fteevents->evdata_str))+1);
|
||||||
strcpy(oevent->data, strings+fteevents->evdata_str);
|
strcpy(oevent->data, Mod_IQMString(&strings, fteevents->evdata_str));
|
||||||
link = &fgroup[fteevents->anim].events;
|
link = &fgroup[fteevents->anim].events;
|
||||||
while (*link && (*link)->timestamp <= oevent->timestamp)
|
while (*link && (*link)->timestamp <= oevent->timestamp)
|
||||||
link = &(*link)->next;
|
link = &(*link)->next;
|
||||||
|
@ -8641,7 +8673,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
{
|
{
|
||||||
if (h->num_meshes)
|
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);
|
firstvert = LittleLong(mesh[i].first_vertex);
|
||||||
numverts = LittleLong(mesh[i].num_vertexes);
|
numverts = LittleLong(mesh[i].num_vertexes);
|
||||||
numtris = LittleLong(mesh[i].num_triangles);
|
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);
|
skin->frame = ZG_Malloc(&mod->memgroup, sizeof(*skin->frame)*skin->numframes);
|
||||||
for (t = 0; t < skin->numframes; t++, sf++)
|
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)
|
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);
|
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->numframes = 1; //non-sequenced skins.
|
||||||
|
|
||||||
skin->frame = skinframe = ZG_Malloc(&mod->memgroup, sizeof(*skin->frame)*skin->numframes);
|
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;
|
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;
|
gai[i].numindexes = idx - gai[i].ofs_indexes;
|
||||||
if (gai[i].numindexes != numtris*3)
|
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*/
|
/*verts*/
|
||||||
gai[i].shares_verts = i;
|
gai[i].shares_verts = i;
|
||||||
|
|
Loading…
Reference in a new issue