Use sub-tic accuracy for smooth sine quakes

- Converting the wave speed back to floats, since I'm using sin() instead
  of the finesine table now.
- Pre-shift the quake intensities to avoid extra shifting in GetModIntensity.
- Loading old saves will shift the intensities to fixed point but will not
  convert the fixed wave speeds to floats. The chances of this
  being in a savegame where the speeds are non-zero is pretty much nil,
  and int and floating point 0 are bitwise identical (not counting -0.0).
This commit is contained in:
Randy Heit 2015-03-02 19:17:24 -06:00
parent f941fa9e40
commit 156d1e61fd
4 changed files with 26 additions and 28 deletions

View file

@ -35,23 +35,23 @@ DEarthquake::DEarthquake()
DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int intensityZ, int duration, DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int intensityZ, int duration,
int damrad, int tremrad, FSoundID quakesound, int flags, int damrad, int tremrad, FSoundID quakesound, int flags,
fixed_t waveSpeedX, fixed_t waveSpeedY, fixed_t waveSpeedZ) double waveSpeedX, double waveSpeedY, double waveSpeedZ)
: DThinker(STAT_EARTHQUAKE) : DThinker(STAT_EARTHQUAKE)
{ {
m_QuakeSFX = quakesound; m_QuakeSFX = quakesound;
m_Spot = center; m_Spot = center;
// Radii are specified in tile units (64 pixels) // Radii are specified in tile units (64 pixels)
m_DamageRadius = damrad << (FRACBITS); m_DamageRadius = damrad << FRACBITS;
m_TremorRadius = tremrad << (FRACBITS); m_TremorRadius = tremrad << FRACBITS;
m_IntensityX = intensityX; m_IntensityX = intensityX << FRACBITS;
m_IntensityY = intensityY; m_IntensityY = intensityY << FRACBITS;
m_IntensityZ = intensityZ; m_IntensityZ = intensityZ << FRACBITS;
m_CountdownStart = duration; m_CountdownStart = duration;
m_Countdown = duration; m_Countdown = duration;
m_Flags = flags; m_Flags = flags;
m_WaveSpeedX = waveSpeedX; m_WaveSpeedX = (float)waveSpeedX;
m_WaveSpeedY = waveSpeedY; m_WaveSpeedY = (float)waveSpeedY;
m_WaveSpeedZ = waveSpeedZ; m_WaveSpeedZ = (float)waveSpeedZ;
} }
//========================================================================== //==========================================================================
@ -87,6 +87,9 @@ void DEarthquake::Serialize (FArchive &arc)
if (SaveVersion < 4521) if (SaveVersion < 4521)
{ {
m_WaveSpeedX = m_WaveSpeedY = m_WaveSpeedZ = 0; m_WaveSpeedX = m_WaveSpeedY = m_WaveSpeedZ = 0;
m_IntensityX <<= FRACBITS;
m_IntensityY <<= FRACBITS;
m_IntensityZ <<= FRACBITS;
} }
else else
{ {
@ -163,15 +166,14 @@ void DEarthquake::Tick ()
} }
} }
fixed_t DEarthquake::GetModWave(fixed_t waveMultiplier) const fixed_t DEarthquake::GetModWave(double waveMultiplier) const
{ {
//QF_WAVE converts intensity into amplitude and unlocks a new property, the wave length. //QF_WAVE converts intensity into amplitude and unlocks a new property, the wave length.
//This is, in short, waves per second (full cycles, mind you, from 0 to 360.) //This is, in short, waves per second (full cycles, mind you, from 0 to 360.)
//Named waveMultiplier because that's as the name implies: adds more waves per second. //Named waveMultiplier because that's as the name implies: adds more waves per second.
fixed_t wavesPerSecond = (waveMultiplier >> 15) * m_Countdown % (TICRATE * 2); double time = m_Countdown - FIXED2DBL(r_TicFrac);
fixed_t index = ((wavesPerSecond * (FINEANGLES / 2)) / (TICRATE)); return FLOAT2FIXED(sin(waveMultiplier * time * (M_PI * 2 / TICRATE)));
return finesine[index & FINEMASK];
} }
//========================================================================== //==========================================================================
@ -182,7 +184,7 @@ fixed_t DEarthquake::GetModWave(fixed_t waveMultiplier) const
// //
//========================================================================== //==========================================================================
fixed_t DEarthquake::GetModIntensity(int intensity) const fixed_t DEarthquake::GetModIntensity(fixed_t intensity) const
{ {
assert(m_CountdownStart >= m_Countdown); assert(m_CountdownStart >= m_Countdown);
intensity += intensity; // always doubled intensity += intensity; // always doubled
@ -209,11 +211,7 @@ fixed_t DEarthquake::GetModIntensity(int intensity) const
scalar = m_CountdownStart - m_Countdown; scalar = m_CountdownStart - m_Countdown;
} }
assert(m_CountdownStart > 0); assert(m_CountdownStart > 0);
intensity = intensity * (scalar << FRACBITS) / m_CountdownStart; intensity = Scale(intensity, scalar, m_CountdownStart);
}
else
{
intensity <<= FRACBITS;
} }
return intensity; return intensity;
} }
@ -305,7 +303,7 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration,
int damrad, int tremrad, FSoundID quakesfx, int flags, int damrad, int tremrad, FSoundID quakesfx, int flags,
fixed_t waveSpeedX, fixed_t waveSpeedY, fixed_t waveSpeedZ) double waveSpeedX, double waveSpeedY, double waveSpeedZ)
{ {
AActor *center; AActor *center;
bool res = false; bool res = false;

View file

@ -156,7 +156,7 @@ class DEarthquake : public DThinker
public: public:
DEarthquake(AActor *center, int intensityX, int intensityY, int intensityZ, int duration, DEarthquake(AActor *center, int intensityX, int intensityY, int intensityZ, int duration,
int damrad, int tremrad, FSoundID quakesfx, int flags, int damrad, int tremrad, FSoundID quakesfx, int flags,
fixed_t waveSpeedX, fixed_t waveSpeedY, fixed_t waveSpeedZ); double waveSpeedX, double waveSpeedY, double waveSpeedZ);
void Serialize (FArchive &arc); void Serialize (FArchive &arc);
void Tick (); void Tick ();
@ -166,11 +166,11 @@ public:
int m_CountdownStart; int m_CountdownStart;
FSoundID m_QuakeSFX; FSoundID m_QuakeSFX;
int m_Flags; int m_Flags;
int m_IntensityX, m_IntensityY, m_IntensityZ; fixed_t m_IntensityX, m_IntensityY, m_IntensityZ;
fixed_t m_WaveSpeedX, m_WaveSpeedY, m_WaveSpeedZ; float m_WaveSpeedX, m_WaveSpeedY, m_WaveSpeedZ;
fixed_t GetModIntensity(int intensity) const; fixed_t GetModIntensity(int intensity) const;
fixed_t GetModWave(fixed_t waveMultiplier) const; fixed_t GetModWave(double waveMultiplier) const;
static int StaticGetQuakeIntensities(AActor *viewer, FQuakeJiggers &jiggers); static int StaticGetQuakeIntensities(AActor *viewer, FQuakeJiggers &jiggers);

View file

@ -929,7 +929,7 @@ void P_DoDeferedScripts (void);
// //
// [RH] p_quake.c // [RH] p_quake.c
// //
bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, fixed_t waveSpeedX, fixed_t waveSpeedY, fixed_t waveSpeedZ); bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ);
bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx);
#endif #endif

View file

@ -4428,9 +4428,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_QuakeEx)
ACTION_PARAM_INT(tremrad, 5); ACTION_PARAM_INT(tremrad, 5);
ACTION_PARAM_SOUND(sound, 6); ACTION_PARAM_SOUND(sound, 6);
ACTION_PARAM_INT(flags, 7); ACTION_PARAM_INT(flags, 7);
ACTION_PARAM_FIXED(mulWaveX, 8); ACTION_PARAM_DOUBLE(mulWaveX, 8);
ACTION_PARAM_FIXED(mulWaveY, 9); ACTION_PARAM_DOUBLE(mulWaveY, 9);
ACTION_PARAM_FIXED(mulWaveZ, 10); ACTION_PARAM_DOUBLE(mulWaveZ, 10);
P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ); P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ);
} }