Make certain sprites in rotating sectors impervious against diverging from their initial position due to roundoff error accumulation. The sprites affected are those with statnums 0, STANDABLE, FX, and FALLER (also SE lights, but that shouldn't be considered permanent) contained in sectors with SE 0, 6 or 14. Fix some interpolation issues with such sprites in passing, though they still jitter on occasion. For usage examples, take a look at the updated trueror1.map.

Implementation note: the so instrumented sprites use actor[].t_data[7] to hold a magic number (0x18190000 + pivot spr idx), and t_data[8] and [9] for the initial coords relative to the pivot point.

git-svn-id: https://svn.eduke32.com/eduke32@1913 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2011-06-22 19:12:47 +00:00
parent ffde01b0ca
commit 5cb1132d56
4 changed files with 95 additions and 7 deletions

Binary file not shown.

View file

@ -648,6 +648,20 @@ void Sect_ClearInterpolation(int32_t i)
} }
} }
static int32_t move_fixed_sprite(int32_t j, int32_t pivotspr, int32_t daang)
{
if ((FIXSPR_STATNUMP(sprite[j].statnum) || (sprite[j].picnum==SECTOREFFECTOR && (sprite[j].lotag==49||sprite[j].lotag==50)))
&& actor[j].t_data[7]==(0x18190000|pivotspr))
{
rotatepoint(0,0, actor[j].t_data[8],actor[j].t_data[9], daang&2047, &sprite[j].x,&sprite[j].y);
sprite[j].x += sprite[pivotspr].x;
sprite[j].y += sprite[pivotspr].y;
return 0;
}
return 1;
}
static void A_MoveSector(int32_t i) static void A_MoveSector(int32_t i)
{ {
//T1,T2 and T3 are used for all the sector moving stuff!!! //T1,T2 and T3 are used for all the sector moving stuff!!!
@ -1390,7 +1404,9 @@ ACTOR_STATIC void G_MoveStandables(void)
if (sect < 0) KILLIT(i); if (sect < 0) KILLIT(i);
Bmemcpy(&actor[i].bposx, s, sizeof(vec3_t)); // 'fixed' sprites in rotating sectors already have bpos* updated
if ((t[7]&(0xffff0000))!=0x18190000)
Bmemcpy(&actor[i].bposx, s, sizeof(vec3_t));
IFWITHIN(CRANE,CRANE+3) IFWITHIN(CRANE,CRANE+3)
{ {
@ -3301,6 +3317,7 @@ ACTOR_STATIC void G_MoveTransports(void)
break; break;
case STAT_PROJECTILE: case STAT_PROJECTILE:
// comment out to make RPGs pass through water:
if (sectlotag != 0) goto JBOLT; if (sectlotag != 0) goto JBOLT;
case STAT_ACTOR: case STAT_ACTOR:
if ((sprite[j].picnum == SHARK) || (sprite[j].picnum == COMMANDER) || (sprite[j].picnum == OCTABRAIN) if ((sprite[j].picnum == SHARK) || (sprite[j].picnum == COMMANDER) || (sprite[j].picnum == OCTABRAIN)
@ -5537,7 +5554,11 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3
p = headspritesect[s->sectnum]; p = headspritesect[s->sectnum];
while (p >= 0) while (p >= 0)
{ {
if (sprite[p].statnum != STAT_EFFECTOR && sprite[p].statnum != STAT_PROJECTILE) // that hardcoded SE light behavior here should be considered temporary at best...
// really need some more general system for handling them!
// Are SE0's broken or what?
if ((sprite[p].statnum != STAT_EFFECTOR || (sprite[p].lotag==49||sprite[p].lotag==50))
&& sprite[p].statnum != STAT_PROJECTILE)
if (sprite[p].picnum != LASERLINE) if (sprite[p].picnum != LASERLINE)
{ {
if (sprite[p].picnum == APLAYER && sprite[p].owner >= 0) if (sprite[p].picnum == APLAYER && sprite[p].owner >= 0)
@ -5551,7 +5572,12 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3
sprite[p].z += zchange; sprite[p].z += zchange;
rotatepoint(sprite[j].x,sprite[j].y,sprite[p].x,sprite[p].y,(q*l),&sprite[p].x,&sprite[p].y); // interpolation fix
actor[p].bposx = sprite[p].x;
actor[p].bposy = sprite[p].y;
if (move_fixed_sprite(p, j, t[2]))
rotatepoint(sprite[j].x,sprite[j].y,sprite[p].x,sprite[p].y,(q*l),&sprite[p].x,&sprite[p].y);
} }
p = nextspritesect[p]; p = nextspritesect[p];
} }
@ -5746,7 +5772,15 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3
(sprite[j].picnum == SECTOREFFECTOR && (sprite[j].lotag == 49||sprite[j].lotag == 50))) (sprite[j].picnum == SECTOREFFECTOR && (sprite[j].lotag == 49||sprite[j].lotag == 50)))
&& sprite[j].picnum != LOCATORS) && sprite[j].picnum != LOCATORS)
{ {
rotatepoint(s->x,s->y,sprite[j].x,sprite[j].y,q,&sprite[j].x,&sprite[j].y); if (move_fixed_sprite(j, s-sprite, t[2]))
rotatepoint(s->x,s->y,sprite[j].x,sprite[j].y,q,&sprite[j].x,&sprite[j].y);
// fix interpolation
if (numplayers < 2 && !g_netServer)
{
actor[j].bposx = sprite[j].x;
actor[j].bposy = sprite[j].y;
}
sprite[j].x+= m; sprite[j].x+= m;
sprite[j].y+= x; sprite[j].y+= x;
@ -5804,6 +5838,22 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3
} }
} }
} }
else
{
// fix for jittering of sprites in halted subways
for (j=headspritesect[s->sectnum]; j >= 0; j=nextspritesect[j])
{
// keep this conditional in sync with above!
if (sprite[j].statnum != STAT_PLAYER && sector[sprite[j].sectnum].lotag != 2 &&
(sprite[j].picnum != SECTOREFFECTOR ||
(sprite[j].picnum == SECTOREFFECTOR && (sprite[j].lotag == 49||sprite[j].lotag == 50)))
&& sprite[j].picnum != LOCATORS)
{
actor[j].bposx = sprite[j].x;
actor[j].bposy = sprite[j].y;
}
}
}
break; break;

View file

@ -103,6 +103,9 @@ extern "C" {
#define TILE_ANIM (MAXTILES-4) #define TILE_ANIM (MAXTILES-4)
#define TILE_VIEWSCR (MAXTILES-5) #define TILE_VIEWSCR (MAXTILES-5)
// sprites with these statnums should be considered for fixing (bitmap)
#define FIXSPR_STATNUMP(k) ((k)==STAT_DEFAULT || (k)==STAT_STANDABLE || ((k)==STAT_FX) || ((k)==STAT_FALLER))
// JBF 20040604: sync is a function on some platforms // JBF 20040604: sync is a function on some platforms
#define sync dsync #define sync dsync

View file

@ -1016,6 +1016,42 @@ static inline void G_SetupBackdrop(int16_t sky)
pskybits=3; pskybits=3;
} }
// tweak moving sectors with these SE lotags (bitmap)
#define FIXSPR_SELOTAGP(k) ((k==0) || (k==6) || (k==14))
// setup sprites in moving sectors that are to be fixed wrt a certain pivot
// position and should not diverge from it due to roundoff error in the future.
// has to be after the spawning stuff.
static void premap_setup_fixed_sprites(void)
{
int32_t i, j, pivot;
for (i=headspritestat[STAT_EFFECTOR]; i>=0; i=nextspritestat[i])
{
if (FIXSPR_SELOTAGP(sprite[i].lotag))
{
for (j=headspritesect[sprite[i].sectnum]; j>=0; j=nextspritesect[j])
{
// TRIPBOMB uses t_data[7] for its own purposes. Wouldn't be
// too useful with moving sectors anyway
if ((FIXSPR_STATNUMP(sprite[j].statnum) && sprite[j].picnum!=TRIPBOMB) ||
(sprite[j].picnum==SECTOREFFECTOR && (sprite[j].lotag==49||sprite[j].lotag==50)))
{
pivot = i;
if (sprite[i].lotag==0)
pivot = sprite[i].owner;
if (pivot < 0 || pivot>=MAXSPRITES)
continue;
// let's hope we don't step on anyone's toes here
actor[j].t_data[7] = 0x18190000 | pivot; // 'rs' magic + pivot SE sprite index
actor[j].t_data[8] = sprite[j].x - sprite[pivot].x;
actor[j].t_data[9] = sprite[j].y - sprite[pivot].y;
}
}
}
}
}
static inline void prelevel(char g) static inline void prelevel(char g)
{ {
int32_t i, nexti, j, startwall, endwall, lotaglist; int32_t i, nexti, j, startwall, endwall, lotaglist;
@ -1140,11 +1176,10 @@ static inline void prelevel(char g)
{ {
if (PN == SECTOREFFECTOR && SLT == 14) if (PN == SECTOREFFECTOR && SLT == 14)
A_Spawn(-1,i); A_Spawn(-1,i);
// if (sprite[i].cstat&2048)
// actor[i].flags |= SPRITE_NOSHADE;
} }
premap_setup_fixed_sprites();
lotaglist = 0; lotaglist = 0;
i = headspritestat[STAT_DEFAULT]; i = headspritestat[STAT_DEFAULT];