the new demo player now has smoother animations at low time scales

This commit is contained in:
myT 2022-11-04 05:06:38 +01:00
parent f401f742ee
commit 0be40a60a7
6 changed files with 114 additions and 136 deletions

View file

@ -319,7 +319,7 @@ static void RB_RenderDrawSurfList( const drawSurf_t* drawSurfs, int numDrawSurfs
if ( entityNum != ENTITYNUM_WORLD ) {
backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
if (backEnd.currentEntity->intShaderTime)
backEnd.refdef.floatTime = originalTime - (double)(backEnd.currentEntity->e.shaderTime.iShaderTime) / 1000.0;
backEnd.refdef.floatTime = originalTime - (double)backEnd.currentEntity->e.shaderTime.iShaderTime / 1000.0;
else
backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime.fShaderTime;
// we have to reset the shaderTime as well otherwise image animations start
@ -446,7 +446,7 @@ static void RB_RenderLitSurfList( dlight_t* dl, qbool opaque )
if ( entityNum != ENTITYNUM_WORLD ) {
backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
if (backEnd.currentEntity->intShaderTime)
backEnd.refdef.floatTime = originalTime - (double)backEnd.currentEntity->e.shaderTime.iShaderTime;
backEnd.refdef.floatTime = originalTime - (double)backEnd.currentEntity->e.shaderTime.iShaderTime / 1000.0;
else
backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime.fShaderTime;
// we have to reset the shaderTime as well otherwise image animations start

View file

@ -565,23 +565,6 @@ void R_Init()
if ((intptr_t)tess.xyz & 15)
Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" );
// init function tables
//
for (int i = 0; i < FUNCTABLE_SIZE; ++i)
{
tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) );
tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f;
tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE;
tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i];
if ( i < FUNCTABLE_SIZE / 4 )
tr.triangleTable[i] = (float)i / (FUNCTABLE_SIZE / 4);
else if ( i < FUNCTABLE_SIZE / 2 )
tr.triangleTable[i] = 1.0f - tr.triangleTable[i - FUNCTABLE_SIZE / 4];
else
tr.triangleTable[i] = -tr.triangleTable[i - FUNCTABLE_SIZE / 2];
}
R_InitFogTable();
R_NoiseInit();

View file

@ -111,7 +111,6 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
for ( i = 0 ; i < 8 ; i++ ) {
float factor;
byte *data;
int lat, lng;
vec3_t normal;
#if idppc
float d0, d1, d2, d3, d4, d5;
@ -151,18 +150,16 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
ent->directedLight[1] += factor * data[4];
ent->directedLight[2] += factor * data[5];
#endif
lat = data[7];
lng = data[6];
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
const float lat = (float)data[7] * (2.0f * M_PI / 256.0f);
const float lon = (float)data[6] * (2.0f * M_PI / 256.0f);
const float cosLat = cos( lat );
const float sinLat = sin( lat );
const float cosLon = cos( lon );
const float sinLon = sin( lon );
normal[0] = cosLat * sinLon;
normal[1] = sinLat * sinLon;
normal[2] = cosLon;
VectorMA( direction, factor, normal, direction );
}

View file

@ -141,7 +141,8 @@ typedef enum {
GF_TRIANGLE,
GF_SAWTOOTH,
GF_INVERSE_SAWTOOTH,
GF_NOISE
GF_NOISE,
GF_COUNT
} genFunc_t;
typedef enum {
@ -913,11 +914,6 @@ typedef struct {
int numSkins;
skin_t* skins[MAX_SKINS];
float sinTable[FUNCTABLE_SIZE];
float squareTable[FUNCTABLE_SIZE];
float triangleTable[FUNCTABLE_SIZE];
float sawToothTable[FUNCTABLE_SIZE];
float inverseSawToothTable[FUNCTABLE_SIZE];
float fogTable[FOG_TABLE_SIZE];
float mipFilter[4]; // only used by the GPU generators

View file

@ -24,45 +24,81 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_local.h"
static double WaveValue( const float* table, double base, double amplitude, double phase, double freq )
// input's in the [0;1] range
typedef double (*waveGenFunc_t)( double );
static double WaveGenSine( double x )
{
// the original code did a double to 32-bit int conversion of x
const double x = (phase + tess.shaderTime * freq) * FUNCTABLE_SIZE;
const int i = (int)((int64_t)x & (int64_t)FUNCTABLE_MASK);
const double r = base + table[i] * amplitude;
return sin(x * 2.0 * M_PI);
}
static double WaveGenSquare( double x )
{
return x < 0.5 ? 1.0 : -1.0;
}
static double WaveGenTriangle( double xs )
{
// the original table shifts the triangle for whatever reason...
const double x = (xs < 0.75) ? (xs + 0.25) : (xs - 0.75);
const double l = x * 4.0 - 1.0;
const double r = 1.0 - (x - 0.5) * 4.0;
const double f = (x < 0.5) ? l : r;
return f;
}
static double WaveGenSawTooth( double x )
{
return x;
}
static double WaveGenInverseSawTooth( double x )
{
return 1.0 - x;
}
static double WaveGenInvalid( double x )
{
ri.Error( ERR_DROP, "WaveGenInvalid called in shader '%s'\n", tess.shader->name );
return 0.0;
}
static double WaveValue( genFunc_t func , double base, double amplitude, double phase, double freq )
{
static const waveGenFunc_t waveGenFunctions[GF_COUNT] =
{
WaveGenInvalid, // GF_NULL
WaveGenSine,
WaveGenSquare,
WaveGenTriangle,
WaveGenSawTooth,
WaveGenInverseSawTooth,
WaveGenInvalid // GF_NOISE
};
// fmod doesn't behave how we want with negative numerators
// fmod(-2.25, 1) returns -0.25 but we really want 0.75
const double xo = phase + tess.shaderTime * freq;
const double xr = (double)(int)xo; // rounded towards 0
const double x = xo >= 0.0 ? (xo - xr) : (xo - xr + 1.0);
const double r = base + (waveGenFunctions[func])(x) * amplitude;
return r;
}
static const float* TableForFunc( genFunc_t func )
{
switch ( func )
{
case GF_SIN:
return tr.sinTable;
case GF_TRIANGLE:
return tr.triangleTable;
case GF_SQUARE:
return tr.squareTable;
case GF_SAWTOOTH:
return tr.sawToothTable;
case GF_INVERSE_SAWTOOTH:
return tr.inverseSawToothTable;
case GF_NONE:
default:
break;
}
ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'\n", func, tess.shader->name );
return NULL;
}
// Evaluates a given waveForm_t, referencing backEnd.refdef.time directly
static float EvalWaveForm( const waveForm_t *wf )
static float EvalWaveForm( const waveForm_t *wf )
{
return WaveValue( TableForFunc( wf->func ), wf->base, wf->amplitude, wf->phase, wf->frequency );
return WaveValue( wf->func, wf->base, wf->amplitude, wf->phase, wf->frequency );
}
@ -139,12 +175,10 @@ static void RB_CalcDeformVertexes( const deformStage_t* ds, int firstVertex, int
}
else
{
const float* table = TableForFunc(ds->deformationWave.func);
for ( int i = 0; i < numVertexes; i++, xyz += 4, normal += 4 )
{
const float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
const float scale = WaveValue( table, ds->deformationWave.base,
const float scale = WaveValue( ds->deformationWave.func, ds->deformationWave.base,
ds->deformationWave.amplitude,
ds->deformationWave.phase + off,
ds->deformationWave.frequency );
@ -190,21 +224,14 @@ static void RB_CalcDeformNormals( const deformStage_t* ds, int firstVertex, int
static void RB_CalcBulgeVertexes( const deformStage_t* ds, int firstVertex, int numVertexes )
{
int i;
const float *st = ( const float * ) &tess.texCoords[firstVertex];
float *xyz = ( float * ) &tess.xyz[firstVertex];
float *normal = ( float * ) &tess.normal[firstVertex];
float now;
const float* st = (const float*)&tess.texCoords[firstVertex];
float* xyz = (float*)&tess.xyz[firstVertex];
float* normal = (float*)&tess.normal[firstVertex];
now = backEnd.refdef.time * ds->bulgeSpeed / 1000.0f;
const float now = (backEnd.refdef.time / 1000.0f) * ds->bulgeSpeed;
for ( i = 0; i < numVertexes; i++, xyz += 4, st += 2, normal += 4 ) {
int off;
float scale;
off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
scale = tr.sinTable[ off & FUNCTABLE_MASK ] * ds->bulgeHeight;
for ( int i = 0; i < numVertexes; i++, xyz += 4, st += 2, normal += 4 ) {
const float scale = ds->bulgeHeight * sin(st[0] * ds->bulgeWidth + now);
xyz[0] += normal[0] * scale;
xyz[1] += normal[1] * scale;
@ -216,8 +243,9 @@ static void RB_CalcBulgeVertexes( const deformStage_t* ds, int firstVertex, int
// a deformation that can move an entire surface along a wave path
static void RB_CalcMoveVertexes( const deformStage_t* ds, int firstVertex, int numVertexes )
{
const float* table = TableForFunc( ds->deformationWave.func );
const double scale = WaveValue( table, ds->deformationWave.base,
const double scale = WaveValue(
ds->deformationWave.func,
ds->deformationWave.base,
ds->deformationWave.amplitude,
ds->deformationWave.phase,
ds->deformationWave.frequency );
@ -832,19 +860,13 @@ static void RB_CalcEnvironmentTexCoords( float *st, int firstVertex, int numVert
static void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st, int firstVertex, int numVertexes )
{
int i;
double now;
vec4_t* const v = &tess.xyz[firstVertex];
const double now = ( wf->phase + tess.shaderTime * wf->frequency );
now = ( wf->phase + tess.shaderTime * wf->frequency );
for ( i = 0; i < numVertexes; i++, st += 2 )
for ( int i = 0; i < numVertexes; i++, st += 2 )
{
float s = st[0];
float t = st[1];
st[0] = s + tr.sinTable[ ( ( int ) ( ( ( v[i][0] + v[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
st[1] = t + tr.sinTable[ ( ( int ) ( ( v[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
st[0] += sin( ( ( v[i][0] + v[i][2] )* 1.0 / 128 * 0.125 + now ) * 2.0 * M_PI ) * wf->amplitude;
st[1] += sin( ( v[i][1] * 1.0 / 128 * 0.125 + now ) * 2.0 * M_PI ) * wf->amplitude;
}
}
@ -885,13 +907,9 @@ static void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st, int n
static void RB_CalcRotateTexCoords( float degsPerSecond, float *st, int numVertexes )
{
double timeScale = tess.shaderTime;
double degs = -degsPerSecond * timeScale;
int index = degs * ( FUNCTABLE_SIZE / 360.0f );
float sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
float cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
const double x = -degsPerSecond * (tess.shaderTime / 360.0) * 2.0 * M_PI;
const double sinValue = sin(x);
const double cosValue = cos(x);
texModInfo_t tmi;
tmi.matrix[0][0] = cosValue;

View file

@ -375,6 +375,20 @@ static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
}
static void DecompressNormalVector( vec3_t output, const short* input )
{
const float lat = ((input[0] >> 8) & 0xFF) * ((2.0f * M_PI) / 256.0f);
const float lon = ( input[0] & 0xFF) * ((2.0f * M_PI) / 256.0f);
const float cosLat = cos( lat );
const float sinLat = sin( lat );
const float cosLon = cos( lon );
const float sinLon = sin( lon );
output[0] = cosLat * sinLon;
output[1] = sinLat * sinLon;
output[2] = cosLon;
}
static void LerpMeshVertexes( md3Surface_t* surf, float backlerp )
{
short *oldXyz, *newXyz, *oldNormals, *newNormals;
@ -382,7 +396,6 @@ static void LerpMeshVertexes( md3Surface_t* surf, float backlerp )
float oldXyzScale, newXyzScale;
float oldNormalScale, newNormalScale;
int vertNum;
unsigned lat, lng;
int numVerts;
outXyz = tess.xyz[tess.numVertexes];
@ -405,23 +418,11 @@ static void LerpMeshVertexes( md3Surface_t* surf, float backlerp )
newXyz += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
outXyz[0] = newXyz[0] * newXyzScale;
outXyz[1] = newXyz[1] * newXyzScale;
outXyz[2] = newXyz[2] * newXyzScale;
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
DecompressNormalVector( outNormal, newNormals );
}
} else {
//
@ -446,28 +447,11 @@ static void LerpMeshVertexes( md3Surface_t* surf, float backlerp )
outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
// FIXME: interpolate lat/long instead?
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
lat = ( oldNormals[0] >> 8 ) & 0xff;
lng = ( oldNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
DecompressNormalVector( uncompressedNewNormal, newNormals );
DecompressNormalVector( uncompressedOldNormal, oldNormals );
outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
// VectorNormalize (outNormal);
}
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
}