From 76300026f823291ac1d5f1457c7a8c739d4373a1 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 26 Aug 2017 18:56:23 +0100 Subject: [PATCH] * Added support for sprite2s to MD2s! - Name each frame either SPR2_**** or SUPER**** (where **** is the 4-character name) - If the name is 3 characters, '.' is accepted as a substitute for the '_', but a space/absent isn't (for tool-related reasons). - Adds a big sprite2 index array to all models, even non-player ones. Sorry! * Made MD2 frame interpoleration only work across the same spriteset (and sprite2set). * Made MD2 frame interpoleration happen when there's less than a quarter of a second between frames, as opposed to the hardcoded specific animation disabling. * Fixed sprite2-related typo in dehacked.c. --- src/dehacked.c | 2 +- src/hardware/hw_md2.c | 141 ++++++++++++++++++++++++++++++++++++------ src/hardware/hw_md2.h | 4 +- src/info.c | 8 +-- src/r_things.c | 21 +------ 5 files changed, 133 insertions(+), 43 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index cdfbc5e22..385411748 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7982,7 +7982,7 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word); return 0; } - else if (fastncmp("SPR2_",word,4)) { + else if (fastncmp("SPR2_",word,5)) { p = word+5; for (i = 0; i < (fixed_t)free_spr2; i++) if (!spr2names[i][4]) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index df2c9f59a..14879b2b7 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -28,6 +28,7 @@ #include "../doomdef.h" #include "../doomstat.h" +#include "../fastcmp.h" #ifdef HWRENDER #include "hw_drv.h" @@ -395,6 +396,29 @@ static md2_model_t *md2_readModel(const char *filename) } strcpy(model->frames[i].name, frame->name); + if (frame->name[0] == 'S') + { + boolean super; + if ((super = (fastncmp("UPER", frame->name+1, 4))) // SUPER + || fastncmp("PR2_", frame->name+1, 4)) // SPR2_ + { + UINT8 spr2; + for (spr2 = 0; spr2 < free_spr2; spr2++) + if (fastncmp(frame->name+5,spr2names[spr2],3) + && ((frame->name[8] == spr2names[spr2][3]) + || (frame->name[8] == '.' && spr2names[spr2][3] == '_'))) + break; + + if (spr2 < free_spr2) + { + if (super) + spr2 |= FF_SPR2SUPER; + if (model->spr2frames[spr2][1]++ == 0) // numspr2frames + model->spr2frames[spr2][0] = i; // starting frame + CONS_Debug(DBG_RENDER, "frame %s, sprite2 %s - starting frame %d, number of frames %d\n", frame->name, spr2names[spr2 & ~FF_SPR2SUPER], model->spr2frames[spr2][0], model->spr2frames[spr2][1]); + } + } + } for (j = 0; j < model->header.numVertices; j++) { model->frames[i].vertices[j].vertex[0] = (float) ((INT32) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0]; @@ -1078,6 +1102,51 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, con res? run? */ + +static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player) +{ + UINT8 super = 0, i = 0; + + if (!md2 || !skin) + return 0; + + while (!(md2->model->spr2frames[spr2][1]) + && spr2 != SPR2_STND + && ++i != 32) // recursion limiter + { + if (spr2 & FF_SPR2SUPER) + { + super = FF_SPR2SUPER; + spr2 &= ~FF_SPR2SUPER; + continue; + } + + switch(spr2) + { + + // Normal special cases. + case SPR2_JUMP: + spr2 = ((player + ? player->charflags + : skin->flags) + & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; + break; + case SPR2_TIRE: + spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; + break; + + // Use the handy list, that's what it's there for! + default: + spr2 = spr2defaults[spr2]; + break; + } + + spr2 |= super; + } + + return spr2; +} + #define NORMALFOG 0x00000000 #define FADEFOG 0x19000000 void HWR_DrawMD2(gr_vissprite_t *spr) @@ -1225,31 +1294,67 @@ void HWR_DrawMD2(gr_vissprite_t *spr) tics = spr->mobj->anim_duration; } - //FIXME: this is not yet correct - frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames; - buff = md2->model->glCommandBuffer; - curr = &md2->model->frames[frame]; - if (cv_grmd2.value == 1) +#define INTERPOLERATION_LIMIT TICRATE/4 + + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation - if (spr->mobj->frame & FF_ANIMATE) + UINT8 spr2 = P_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); + UINT8 mod = md2->model->spr2frames[spr2][1] ? md2->model->spr2frames[spr2][1] : md2->model->header.numFrames; + //FIXME: this is not yet correct + frame = md2->model->spr2frames[spr2][0] + ((spr->mobj->frame & FF_FRAMEMASK) % mod); + buff = md2->model->glCommandBuffer; + curr = &md2->model->frames[frame]; + if (cv_grmd2.value == 1 && tics <= INTERPOLERATION_LIMIT) { - UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; - if (nextframe >= (UINT32)spr->mobj->state->var1) - nextframe = (spr->mobj->state->frame & FF_FRAMEMASK); - nextframe %= md2->model->header.numFrames; - next = &md2->model->frames[nextframe]; - } - else - { - if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL - && !(spr->mobj->player && spr->mobj->state->nextstate == S_PLAY_WAIT && spr->mobj->state == &states[S_PLAY_STND])) + if (durs > INTERPOLERATION_LIMIT) + durs = INTERPOLERATION_LIMIT; + + if (spr->mobj->frame & FF_ANIMATE + || (spr->mobj->state->nextstate != S_NULL + && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite + && (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) == spr->mobj->sprite2)) { - const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; + UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextframe >= (UINT32)((skin_t*)spr->mobj->skin)->sprites[spr->mobj->sprite2].numframes) + nextframe = 0; + nextframe = md2->model->spr2frames[spr2][0] + (nextframe % md2->model->spr2frames[spr2][1]); next = &md2->model->frames[nextframe]; } } } + else + { + //FIXME: this is not yet correct + frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames; + buff = md2->model->glCommandBuffer; + curr = &md2->model->frames[frame]; + if (cv_grmd2.value == 1 && tics <= INTERPOLERATION_LIMIT) + { + if (durs > INTERPOLERATION_LIMIT) + durs = INTERPOLERATION_LIMIT; + + // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation + if (spr->mobj->frame & FF_ANIMATE) + { + UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextframe >= (UINT32)spr->mobj->state->var1) + nextframe = (spr->mobj->state->frame & FF_FRAMEMASK); + nextframe %= md2->model->header.numFrames; + next = &md2->model->frames[nextframe]; + } + else + { + if (spr->mobj->state->nextstate != S_NULL + && states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite) + { + const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; + next = &md2->model->frames[nextframe]; + } + } + } + } + +#undef INTERPOLERATION_LIMIT //Hurdler: it seems there is still a small problem with mobj angle p.x = FIXED_TO_FLOAT(spr->mobj->x); diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 299d12400..b183e4367 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -22,6 +22,7 @@ #define _HW_MD2_H_ #include "hw_glob.h" +#include "../info.h" // magic number "IDP2" or 844121161 #define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I') @@ -111,7 +112,8 @@ typedef struct md2_textureCoordinate_t *texCoords; md2_triangle_t *triangles; md2_frame_t *frames; - INT32 *glCommandBuffer; + size_t spr2frames[2*NUMPLAYERSPRITES][2]; + INT32 *glCommandBuffer; } ATTRPACK md2_model_t; #if defined(_MSC_VER) diff --git a/src/info.c b/src/info.c index dc774bb9c..c8bea7803 100644 --- a/src/info.c +++ b/src/info.c @@ -526,11 +526,11 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_TRNS, - 0, // SPR2_NSTD, - 0, // SPR2_NFLT, - 0, // SPR2_NSTN, + FF_SPR2SUPER|SPR2_STND, // SPR2_NSTD, + FF_SPR2SUPER|SPR2_FLT , // SPR2_NFLT, + FF_SPR2SUPER|SPR2_STUN, // SPR2_NSTN, SPR2_NSTN, // SPR2_NPUL, - 0, // SPR2_NATK, + FF_SPR2SUPER|SPR2_ROLL, // SPR2_NATK, 0, // SPR2_NGT0, (should never be referenced) SPR2_NGT0, // SPR2_NGT1, diff --git a/src/r_things.c b/src/r_things.c index ebec4a14a..67aa4e585 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2431,7 +2431,7 @@ CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) { - UINT8 super = (spr2 & FF_SPR2SUPER), i = 0; + UINT8 super = 0, i = 0; if (!skin) return 0; @@ -2442,6 +2442,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) { if (spr2 & FF_SPR2SUPER) { + super = FF_SPR2SUPER; spr2 &= ~FF_SPR2SUPER; continue; } @@ -2460,24 +2461,6 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; break; - // NiGHTS sprites. - case SPR2_NSTD: - spr2 = SPR2_STND; - super = FF_SPR2SUPER; - break; - case SPR2_NFLT: - spr2 = SPR2_FLT ; - super = FF_SPR2SUPER; - break; - case SPR2_NSTN: - spr2 = SPR2_STUN; - super = FF_SPR2SUPER; - break; - case SPR2_NATK: - spr2 = SPR2_ROLL; - super = FF_SPR2SUPER; - break; - // Use the handy list, that's what it's there for! default: spr2 = spr2defaults[spr2];