* 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.
This commit is contained in:
toasterbabe 2017-08-26 18:56:23 +01:00
parent 4da6169892
commit 76300026f8
5 changed files with 133 additions and 43 deletions

View File

@ -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])

View File

@ -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);

View File

@ -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)

View File

@ -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,

View File

@ -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];