diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index c66de8cfc..fc24205b0 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -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 ""; + 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<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_idxnum_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;