mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-30 07:41:45 +00:00
the new demo player now has smoother animations at low time scales
This commit is contained in:
parent
f401f742ee
commit
0be40a60a7
6 changed files with 114 additions and 136 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
// 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;
|
||||
// input's in the [0;1] range
|
||||
typedef double (*waveGenFunc_t)( double );
|
||||
|
||||
return r;
|
||||
|
||||
static double WaveGenSine( double x )
|
||||
{
|
||||
return sin(x * 2.0 * M_PI);
|
||||
}
|
||||
|
||||
|
||||
static const float* TableForFunc( genFunc_t func )
|
||||
static double WaveGenSquare( double x )
|
||||
{
|
||||
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;
|
||||
}
|
||||
return x < 0.5 ? 1.0 : -1.0;
|
||||
}
|
||||
|
||||
ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'\n", func, tess.shader->name );
|
||||
return NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// Evaluates a given waveForm_t, referencing backEnd.refdef.time directly
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue