diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 158c07803..89a3c6c98 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -833,10 +833,14 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT run? */ -static boolean HWR_CanInterpolateModel(mobj_t *mobj) +static boolean HWR_CanInterpolateModel(mobj_t *mobj, model_t *model) { - return (!(mobj->state->nextstate == S_PLAY_WAIT && mobj->state == &states[S_PLAY_STND] && !(mobj->sprite2 & FF_SPR2SUPER))) - && (mobj->state != &states[S_PLAY_ROLL]); + return model->interpolate[(mobj->frame & FF_FRAMEMASK)]; +} + +static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame) +{ + return spr2frame->interpolate; } void HWR_DrawMD2(gr_vissprite_t *spr) @@ -1027,7 +1031,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) { if (spr->mobj->sprite2 && md2->model->spr2frames) { - if (HWR_CanInterpolateModel(spr->mobj)) + if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2])) { UINT32 framecount = (&((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2])->numframes; nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; @@ -1039,7 +1043,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; } } - else + else if (HWR_CanInterpolateModel(spr->mobj, md2->model)) { // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation if (spr->mobj->frame & FF_ANIMATE) diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 63c8b8f34..7e9c6cd57 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -199,6 +199,8 @@ model_t *LoadModel(const char *filename, int ztag) Optimize(model); GeneratePolygonNormals(model, ztag); LoadModelSprite2(model); + if (!model->spr2frames) + LoadModelInterpolationSettings(model); // Default material properties for (i = 0 ; i < model->numMaterials; i++) @@ -224,12 +226,59 @@ model_t *LoadModel(const char *filename, int ztag) void HWR_ReloadModels(void) { + size_t i; INT32 s; + for (s = 0; s < MAXSKINS; s++) { if (md2_playermodels[s].model) LoadModelSprite2(md2_playermodels[s].model); } + + for (i = 0; i < NUMSPRITES; i++) + { + if (md2_models[i].model) + LoadModelInterpolationSettings(md2_models[i].model); + } +} + +void LoadModelInterpolationSettings(model_t *model) +{ + INT32 i; + INT32 numframes = model->meshes[0].numFrames; + char *framename = model->framenames; + + if (!framename) + return; + + #define GET_OFFSET \ + memcpy(&interpolation_flag, framename + offset, 2); \ + model->interpolate[i] = (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)); + + for (i = 0; i < numframes; i++) + { + int offset = (strlen(framename) - 4); + char interpolation_flag[3]; + memset(&interpolation_flag, 0x00, 3); + + // find the +i on the frame name + // ANIM+i00 + // so the offset is (frame name length - 4) + GET_OFFSET; + + // maybe the frame had three digits? + // ANIM+i000 + // so the offset is (frame name length - 5) + if (!model->interpolate[i]) + { + offset--; + GET_OFFSET; + } + + framename += 16; + } + + #undef GET_OFFSET } void LoadModelSprite2(model_t *model) @@ -246,12 +295,15 @@ void LoadModelSprite2(model_t *model) { char prefix[6]; char name[5]; + char interpolation_flag[3]; char framechar[4]; UINT8 frame = 0; UINT8 spr2idx; + boolean interpolate = false; memset(&prefix, 0x00, 6); memset(&name, 0x00, 5); + memset(&interpolation_flag, 0x00, 3); memset(&framechar, 0x00, 4); if (strlen(framename) >= 9) @@ -261,6 +313,13 @@ void LoadModelSprite2(model_t *model) modelframename += 5; memcpy(&name, modelframename, 4); modelframename += 4; + // Oh look + memcpy(&interpolation_flag, modelframename, 2); + if (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)) + { + interpolate = true; + modelframename += 2; + } memcpy(&framechar, modelframename, 3); frame = atoi(framechar); @@ -277,6 +336,7 @@ void LoadModelSprite2(model_t *model) spr2frames[spr2idx].superframes[frame] = i; else spr2frames[spr2idx].frames[frame] = i; + spr2frames[spr2idx].interpolate = interpolate; break; } spr2idx++; diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index af9020ef9..75495c930 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -73,10 +73,13 @@ typedef struct tag_s // matrix_t transform; } tag_t; +#define MODEL_INTERPOLATION_FLAG "+i" + typedef struct { INT32 frames[256]; INT32 superframes[256]; + boolean interpolate; } modelspr2frames_t; typedef struct model_s @@ -93,8 +96,9 @@ typedef struct model_s char *mdlFilename; boolean unloaded; - modelspr2frames_t *spr2frames; char *framenames; + boolean interpolate[256]; + modelspr2frames_t *spr2frames; } model_t; extern int numModels; @@ -106,6 +110,7 @@ tag_t *GetTagByName(model_t *model, char *name, int frame); model_t *LoadModel(const char *filename, int ztag); void UnloadModel(model_t *model); void Optimize(model_t *model); +void LoadModelInterpolationSettings(model_t *model); void LoadModelSprite2(model_t *model); void GenerateVertexNormals(model_t *model); void GeneratePolygonNormals(model_t *model, int ztag);