diff options
-rw-r--r-- | src/cgame/cg_draw.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_ents.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 14 | ||||
-rw-r--r-- | src/cgame/cg_main.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_particles.c | 5 | ||||
-rw-r--r-- | src/cgame/cg_view.c | 110 | ||||
-rw-r--r-- | src/game/bg_lib.c | 472 | ||||
-rw-r--r-- | src/game/bg_lib.h | 1 | ||||
-rw-r--r-- | src/game/bg_local.h | 25 | ||||
-rw-r--r-- | src/game/bg_misc.c | 4 | ||||
-rw-r--r-- | src/game/bg_pmove.c | 233 | ||||
-rw-r--r-- | src/game/bg_public.h | 6 | ||||
-rw-r--r-- | src/game/q_shared.h | 2 |
13 files changed, 633 insertions, 245 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index c004c3d5..0617580b 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -345,7 +345,7 @@ static void CG_DrawLighting( void ) VectorCopy( cent->lerpOrigin, point ); - AngleVectors( cg.predictedPlayerState.viewangles, direction, NULL, NULL ); + AngleVectors( cg.refdefViewAngles, direction, NULL, NULL ); currentLum = CG_LightFromDirection( point, direction ); //CG_Printf( "%d\n", lum ); diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c index 57b89fc6..62920756 100644 --- a/src/cgame/cg_ents.c +++ b/src/cgame/cg_ents.c @@ -655,7 +655,7 @@ static void CG_TorchLight( centity_t *cent ) if( cent->currentState.clientNum == cg.predictedPlayerState.clientNum ) { VectorCopy( cg.predictedPlayerState.origin, from ); - VectorCopy( cg.predictedPlayerState.viewangles, angles ); + VectorCopy( cg.refdefViewAngles, angles ); } else { diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 38bc3d26..77c8ec13 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -438,6 +438,16 @@ typedef struct { int numpositions; } skulltrail_t; +//TA: smoothing of view for WW transitions +#define MAXSMOOTHS 32 + +typedef struct +{ + float time; + + vec3_t rotAxis; + float rotAngle; +} smooth_t; #define MAX_REWARDSTACK 10 #define MAX_SOUNDBUFFER 20 @@ -645,6 +655,9 @@ typedef struct { int weapon2Time; //TA: time when BUTTON_ATTACK2 went t->f f->t qboolean weapon1Firing; qboolean weapon2Firing; + + vec3_t lastNormal; //TA: view smoothage + smooth_t sList[ MAXSMOOTHS ]; //TA: WW smoothing } cg_t; @@ -1183,6 +1196,7 @@ extern vmCvar_t cg_trueLightning; extern vmCvar_t cg_creepRes; extern vmCvar_t cg_drawSurfNormal; extern vmCvar_t cg_debugAlloc; +extern vmCvar_t cg_smoothTime; // // cg_main.c diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index e9717faf..2cdc9149 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -186,6 +186,7 @@ vmCvar_t cg_trueLightning; vmCvar_t cg_creepRes; vmCvar_t cg_drawSurfNormal; vmCvar_t cg_debugAlloc; +vmCvar_t cg_smoothTime; typedef struct { @@ -266,6 +267,7 @@ static cvarTable_t cvarTable[] = { { &cg_creepRes, "cg_creepRes", "16", CVAR_ARCHIVE }, { &cg_drawSurfNormal, "cg_drawSurfNormal", "0", CVAR_CHEAT }, { &cg_debugAlloc, "cg_debugAlloc", "0", 0 }, + { &cg_smoothTime, "cg_smoothTime", "300", 0 }, // the following variables are created in other parts of the system, // but we also reference them here diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c index ac709a1b..9b216ceb 100644 --- a/src/cgame/cg_particles.c +++ b/src/cgame/cg_particles.c @@ -136,7 +136,10 @@ void CG_ClearParticles (void) oldtime = cg.time; // Ridah, init the shaderAnims - for (i=0; shaderAnimNames[i]; i++) { + //for (i=0; shaderAnimNames[i]; i++) { + //TA: figure out this thing works... + i = 0; + { int j; for (j=0; j<shaderAnimCounts[i]; j++) { diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c index 90a2a5e9..6608b21e 100644 --- a/src/cgame/cg_view.c +++ b/src/cgame/cg_view.c @@ -753,6 +753,106 @@ static void CG_DrawSurfNormal( void ) trap_R_AddPolyToScene( cgs.media.whiteShader, 4, normal ); } +/* +=============== +CG_addSmoothOp +=============== +*/ +static void CG_addSmoothOp( vec3_t rotAxis, float rotAngle ) +{ + int i; + + //iterate through smooth array + for( i = 0; i < MAXSMOOTHS; i++ ) + { + //found an unused index in the smooth array + if( cg.sList[ i ].time + cg_smoothTime.integer < cg.time ) + { + //copy to array and stop + VectorCopy( rotAxis, cg.sList[ i ].rotAxis ); + cg.sList[ i ].rotAngle = rotAngle; + cg.sList[ i ].time = cg.time; + return; + } + } + + //no free indices in the smooth array +} + +/* +=============== +CG_smoothWWTransitions +=============== +*/ +static void CG_smoothWWTransitions( playerState_t *ps, const vec3_t in, vec3_t out ) +{ + vec3_t rotAxis, surfNormal; + vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; + vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; + float rotAngle; + vec3_t inAxis[ 3 ], outAxis[ 3 ]; + int i; + float stLocal, sFraction; + qboolean performed = qfalse; + + //set surfNormal + if( !( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) ) + VectorCopy( ps->grapplePoint, surfNormal ); + else + VectorCopy( ceilingNormal, surfNormal ); + + AnglesToAxis( in, inAxis ); + + //if we are moving from one surface to another smooth the transition + if( !VectorCompare( surfNormal, cg.lastNormal ) ) + { + //if we moving from the ceiling to the floor special case + //( x product of colinear vectors is undefined) + if( VectorCompare( ceilingNormal, cg.lastNormal ) && + VectorCompare( refNormal, surfNormal ) ) + { + AngleVectors( in, NULL, rotAxis, NULL ); + rotAngle = 180.0f; + } + else + { + CrossProduct( cg.lastNormal, surfNormal, rotAxis ); + VectorNormalize( rotAxis ); + rotAngle = abs( RAD2DEG( acos( DotProduct( cg.lastNormal, surfNormal ) ) ) ); + } + + //add the op + CG_addSmoothOp( rotAxis, rotAngle ); + } + + //iterate through ops + for( i = 0; i < MAXSMOOTHS; i++ ) + { + //if this op has time remaining, perform it + if( ( cg.time < cg.sList[ i ].time + cg_smoothTime.integer ) && VectorLength( cg.sList[ i ].rotAxis ) ) + { + stLocal = 1.0 - ( ( ( cg.sList[ i ].time + cg_smoothTime.integer ) - cg.time ) / cg_smoothTime.integer ); + sFraction = -( cos( stLocal * M_PI ) + 1 ) / 2; + + RotatePointAroundVector( outAxis[ 0 ], cg.sList[ i ].rotAxis, inAxis[ 0 ], sFraction * cg.sList[ i ].rotAngle ); + RotatePointAroundVector( outAxis[ 1 ], cg.sList[ i ].rotAxis, inAxis[ 1 ], sFraction * cg.sList[ i ].rotAngle ); + RotatePointAroundVector( outAxis[ 2 ], cg.sList[ i ].rotAxis, inAxis[ 2 ], sFraction * cg.sList[ i ].rotAngle ); + + AxisCopy( outAxis, inAxis ); + performed = qtrue; + } + } + + //if we performed any ops then return the smoothed angles + //otherwise simply return the in angles + if( performed ) + AxisToAngles( outAxis, out ); + else + VectorCopy( in, out ); + + //copy the current normal to the lastNormal + VectorCopy( surfNormal, cg.lastNormal ); +} /* =============== @@ -788,9 +888,15 @@ static int CG_CalcViewValues( void ) { cg.xyspeed = sqrt( ps->velocity[0] * ps->velocity[0] + ps->velocity[1] * ps->velocity[1] ); - VectorCopy( ps->origin, cg.refdef.vieworg ); - VectorCopy( ps->viewangles, cg.refdefViewAngles ); + + if( BG_ClassHasAbility( ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) ) + CG_smoothWWTransitions( ps, ps->viewangles, cg.refdefViewAngles ); + else + VectorCopy( ps->viewangles, cg.refdefViewAngles ); + + if( !( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) ) + VectorSet( cg.lastNormal, 0.0f, 0.0f, 1.0f ); if (cg_cameraOrbit.integer) { if (cg.time > cg.nextOrbitTime) { diff --git a/src/game/bg_lib.c b/src/game/bg_lib.c index 55c1e4f2..ca634ac6 100644 --- a/src/game/bg_lib.c +++ b/src/game/bg_lib.c @@ -796,7 +796,7 @@ double tan( double x ) { return sin(x) / cos(x); } -float acostable[] = { +/*float acostable[] = { 3.14159265,3.07908248,3.05317551,3.03328655,3.01651113,3.00172442,2.98834964,2.97604422, 2.96458497,2.95381690,2.94362719,2.93393068,2.92466119,2.91576615,2.90720289,2.89893629, 2.89093699,2.88318015,2.87564455,2.86831188,2.86116621,2.85419358,2.84738169,2.84071962, @@ -936,7 +936,477 @@ double acos( double x ) { x = 1; index = (float) (1.0 + x) * 511.9; return acostable[index]; +}*/ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* A union which permits us to convert between a float and a 32 bit + int. */ + +typedef union +{ + float value; + unsigned int word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +//acos +static const float +pi = 3.1415925026e+00, /* 0x40490fda */ +pio2_hi = 1.5707962513e+00, /* 0x3fc90fda */ +pio2_lo = 7.5497894159e-08, /* 0x33a22168 */ +pS0 = 1.6666667163e-01, /* 0x3e2aaaab */ +pS1 = -3.2556581497e-01, /* 0xbea6b090 */ +pS2 = 2.0121252537e-01, /* 0x3e4e0aa8 */ +pS3 = -4.0055535734e-02, /* 0xbd241146 */ +pS4 = 7.9153501429e-04, /* 0x3a4f7f04 */ +pS5 = 3.4793309169e-05, /* 0x3811ef08 */ +qS1 = -2.4033949375e+00, /* 0xc019d139 */ +qS2 = 2.0209457874e+00, /* 0x4001572d */ +qS3 = -6.8828397989e-01, /* 0xbf303361 */ +qS4 = 7.7038154006e-02; /* 0x3d9dc62e */ + +/* +================== +acos +================== +*/ +double acos( double x ) +{ + float z, p, q, r, w, s, c, df; + int hx, ix; + + GET_FLOAT_WORD( hx, x ); + ix = hx & 0x7fffffff; + + if( ix == 0x3f800000 ) + { /* |x|==1 */ + if( hx > 0 ) + return 0.0; /* acos(1) = 0 */ + else + return pi + (float)2.0 * pio2_lo; /* acos(-1)= pi */ + } + else if( ix > 0x3f800000 ) + { /* |x| >= 1 */ + return (x-x)/(x-x); /* acos(|x|>1) is NaN */ + } + + if( ix < 0x3f000000 ) + { /* |x| < 0.5 */ + if( ix <= 0x23000000 ) + return pio2_hi + pio2_lo;/*if|x|<2**-57*/ + + z = x * x; + p = z * ( pS0 + z * ( pS1 + z * ( pS2 + z * ( pS3 + z * ( pS4 + z * pS5 ) ) ) ) ); + q = 1.0 + z * ( qS1 + z * ( qS2 + z * ( qS3 + z * qS4 ) ) ); + r = p / q; + return pio2_hi - ( x - ( pio2_lo - x * r ) ); + } + else if( hx < 0 ) + { /* x < -0.5 */ + z = ( 1.0 + x ) * (float)0.5; + p = z * ( pS0 + z * ( pS1 + z * ( pS2 + z * ( pS3 + z * ( pS4 + z * pS5 ) ) ) ) ); + q = 1.0 + z * ( qS1 + z * ( qS2 + z * ( qS3 + z * qS4 ) ) ); + s = sqrt( z ); + r = p / q; + w = r * s - pio2_lo; + return pi - (float)2.0 * ( s + w ); + } + else + { /* x > 0.5 */ + int idf; + z = ( 1.0 - x ) * (float)0.5; + s = sqrt( z ); + df = s; + GET_FLOAT_WORD( idf, df ); + SET_FLOAT_WORD( df, idf & 0xfffff000 ); + c = ( z - df * df ) / ( s + df ); + p = z * ( pS0 + z * ( pS1 + z * ( pS2 + z * ( pS3 + z * ( pS4 + z * pS5 ) ) ) ) ); + q = 1.0 + z * ( qS1 + z * ( qS2 + z * ( qS3 + z * qS4 ) ) ); + r = p / q; + w = r * s + c; + return (double)( 2.0 * ( df + w ) ); + } } + +//pow +static const float +bp[ ] = { 1.0, 1.5, }, +dp_h[ ] = { 0.0, 5.84960938e-01, }, /* 0x3f15c000 */ +dp_l[ ] = { 0.0, 1.56322085e-06, }, /* 0x35d1cfdc */ +huge = 1.0e+30, +tiny = 1.0e-30, +zero = 0.0, +one = 1.0, +two = 2.0, +two24 = 16777216.0, /* 0x4b800000 */ +two25 = 3.355443200e+07, /* 0x4c000000 */ +twom25 = 2.9802322388e-08, /* 0x33000000 */ + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 6.0000002384e-01, /* 0x3f19999a */ +L2 = 4.2857143283e-01, /* 0x3edb6db7 */ +L3 = 3.3333334327e-01, /* 0x3eaaaaab */ +L4 = 2.7272811532e-01, /* 0x3e8ba305 */ +L5 = 2.3066075146e-01, /* 0x3e6c3255 */ +L6 = 2.0697501302e-01, /* 0x3e53f142 */ +P1 = 1.6666667163e-01, /* 0x3e2aaaab */ +P2 = -2.7777778450e-03, /* 0xbb360b61 */ +P3 = 6.6137559770e-05, /* 0x388ab355 */ +P4 = -1.6533901999e-06, /* 0xb5ddea0e */ +P5 = 4.1381369442e-08, /* 0x3331bb4c */ +lg2 = 6.9314718246e-01, /* 0x3f317218 */ +lg2_h = 6.93145752e-01, /* 0x3f317200 */ +lg2_l = 1.42860654e-06, /* 0x35bfbe8c */ +ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */ +cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */ +cp_h = 9.6179199219e-01, /* 0x3f763800 =head of cp */ +cp_l = 4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */ +ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */ +ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/ +ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ + +/* +================== +copysignf +================== +*/ +static float copysignf( float x, float y ) +{ + unsigned int ix, iy; + + GET_FLOAT_WORD( ix, x ); + GET_FLOAT_WORD( iy, y ); + SET_FLOAT_WORD( x, ( ix & 0x7fffffff ) | ( iy & 0x80000000 ) ); + return x; +} + +/* +================== +__scalbnf +================== +*/ +static float __scalbnf( float x, int n ) +{ + int k, ix; + + GET_FLOAT_WORD( ix, x ); + + k = ( ix & 0x7f800000 ) >> 23; /* extract exponent */ + + if( k == 0 ) + { /* 0 or subnormal x */ + if( ( ix & 0x7fffffff ) == 0 ) + return x; /* +-0 */ + + x *= two25; + GET_FLOAT_WORD( ix, x ); + k = ( ( ix & 0x7f800000 ) >> 23 ) - 25; + } + if( k == 0xff ) + return x+x; /* NaN or Inf */ + + k = k + n; + + if( n > 50000 || k > 0xfe ) + return huge * copysignf( huge, x ); /* overflow */ + if ( n < -50000 ) + return tiny * copysignf( tiny, x ); /*underflow*/ + if( k > 0 ) /* normal result */ + { + SET_FLOAT_WORD( x, ( ix & 0x807fffff ) | ( k << 23 ) ); + return x; + } + if( k <= -25 ) + return tiny * copysignf( tiny, x ); /*underflow*/ + + k += 25; /* subnormal result */ + SET_FLOAT_WORD( x, ( ix & 0x807fffff ) | ( k << 23 ) ); + return x * twom25; +} + +/* +================== +pow +================== +*/ +float pow( float x, float y ) +{ + float z, ax, z_h, z_l, p_h, p_l; + float y1, t1, t2, r, s, t, u, v, w; + int i, j, k, yisint, n; + int hx, hy, ix, iy, is; + + /*TA: for some reason the Q3 VM goes apeshit when x = 1.0 + and y > 1.0. Curiously this doesn't happen with gcc + hence this hack*/ + if( x == 1.0 ) + return x; + + GET_FLOAT_WORD( hx, x ); + GET_FLOAT_WORD( hy, y ); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + + /* y==zero: x**0 = 1 */ + if( iy == 0 ) + return one; + + /* +-NaN return x+y */ + if( ix > 0x7f800000 || iy > 0x7f800000 ) + return x + y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if( hx < 0 ) + { + if( iy >= 0x4b800000 ) + yisint = 2; /* even integer y */ + else if( iy >= 0x3f800000 ) + { + k = ( iy >> 23 ) - 0x7f; /* exponent */ + j = iy >> ( 23 - k ); + if( ( j << ( 23 - k ) ) == iy ) + yisint = 2 - ( j & 1 ); + } + } + + /* special value of y */ + if( iy == 0x7f800000 ) + { /* y is +-inf */ + if( ix == 0x3f800000 ) + return y - y; /* inf**+-1 is NaN */ + else if( ix > 0x3f800000 )/* (|x|>1)**+-inf = inf,0 */ + return ( hy >= 0 ) ? y : zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return ( hy < 0 ) ? -y : zero; + } + + if( iy == 0x3f800000 ) + { /* y is +-1 */ + if( hy < 0 ) + return one / x; + else + return x; + } + + if( hy == 0x40000000 ) + return x * x; /* y is 2 */ + + if( hy == 0x3f000000 ) + { /* y is 0.5 */ + if( hx >= 0 ) /* x >= +0 */ + return sqrt( x ); + } + + ax = fabs( x ); + + /* special value of x */ + if( ix == 0x7f800000 || ix == 0 || ix == 0x3f800000 ) + { + z = ax; /*x is +-0,+-inf,+-1*/ + if( hy < 0 ) + z = one / z; /* z = (1/|x|) */ + if( hx < 0 ) + { + if( ( ( ix - 0x3f800000 ) | yisint ) == 0 ) + z = ( z - z ) / ( z - z ); /* (-1)**non-int is NaN */ + else if( yisint == 1 ) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + + return z; + } + + /* (x<0)**(non-int) is NaN */ + if( ( ( ( (unsigned int)hx >> 31 ) - 1 ) | yisint ) == 0 ) + return ( x - x ) / ( x - x ); + + /* |y| is huge */ + if( iy > 0x4d000000 ) + { /* if |y| > 2**27 */ + /* over/underflow if x is not close to one */ + if( ix < 0x3f7ffff8 ) + return ( hy < 0 ) ? huge * huge : tiny * tiny; + + if( ix > 0x3f800007 ) + return ( hy > 0 ) ? huge * huge : tiny * tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x - 1; /* t has 20 trailing zeros */ + w = ( t * t ) * ( (float)0.5 - t * ( (float)0.333333333333 - t * (float)0.25 ) ); + u = ivln2_h * t; /* ivln2_h has 16 sig. bits */ + v = t * ivln2_l - w * ivln2; + t1 = u + v; + GET_FLOAT_WORD( is, t1 ); + SET_FLOAT_WORD( t1, is & 0xfffff000 ); + t2 = v - ( t1 - u ); + } + else + { + float s2, s_h, s_l, t_h, t_l; + n = 0; + /* take care subnormal number */ + if( ix < 0x00800000 ) + { + ax *= two24; + n -= 24; + GET_FLOAT_WORD( ix, ax ); + } + + n += ( ( ix ) >> 23 ) - 0x7f; + j = ix & 0x007fffff; + + /* determine interval */ + ix = j | 0x3f800000; /* normalize ix */ + if( j <= 0x1cc471 ) + k = 0; /* |x|<sqrt(3/2) */ + else if( j < 0x5db3d7 ) + k = 1; /* |x|<sqrt(3) */ + else + { + k = 0; + n += 1; + ix -= 0x00800000; + } + SET_FLOAT_WORD( ax, ix ); + + /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ + u = ax - bp[ k ]; /* bp[0]=1.0, bp[1]=1.5 */ + v = one / ( ax + bp[ k ] ); + s = u * v; + s_h = s; + GET_FLOAT_WORD( is, s_h ); + SET_FLOAT_WORD( s_h, is & 0xfffff000 ); + /* t_h=ax+bp[k] High */ + SET_FLOAT_WORD( t_h, ( ( ix >> 1 ) | 0x20000000 ) + 0x0040000 + ( k << 21 ) ); + t_l = ax - ( t_h - bp[ k ] ); + s_l = v * ( ( u - s_h * t_h ) - s_h * t_l ); + /* compute log(ax) */ + s2 = s * s; + r = s2 * s2 * ( L1 + s2 * ( L2 + s2 * ( L3 + s2 * ( L4 + s2 * ( L5 + s2 * L6 ) ) ) ) ); + r += s_l * ( s_h + s ); + s2 = s_h * s_h; + t_h = (float)3.0 + s2 + r; + GET_FLOAT_WORD( is, t_h ); + SET_FLOAT_WORD( t_h, is & 0xfffff000 ); + t_l = r - ( ( t_h - (float)3.0 ) - s2 ); + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = s_l * t_h + t_l * s; + /* 2/(3log2)*(s+...) */ + p_h = u + v; + GET_FLOAT_WORD( is, p_h ); + SET_FLOAT_WORD( p_h, is & 0xfffff000 ); + p_l = v - ( p_h - u ); + z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l * p_h + p_l * cp + dp_l[ k ]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (float)n; + t1 = ( ( ( z_h + z_l ) + dp_h[ k ] ) + t ); + GET_FLOAT_WORD( is, t1 ); + SET_FLOAT_WORD( t1, is & 0xfffff000 ); + t2 = z_l - ( ( ( t1 - t ) - dp_h[ k ] ) - z_h ); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if( ( ( ( (unsigned int)hx >> 31 ) - 1 ) | ( yisint - 1 ) ) == 0 ) + s = -one; /* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + GET_FLOAT_WORD( is, y ); + SET_FLOAT_WORD( y1, is & 0xfffff000 ); + p_l = ( y - y1 ) * t1 + y * t2; + p_h = y1 * t1; + z = p_l + p_h; + GET_FLOAT_WORD( j, z ); + + if( j > 0x43000000 ) /* if z > 128 */ + return s * huge * huge; /* overflow */ + else if( j == 0x43000000 ) + { /* if z == 128 */ + if( p_l + ovt > z - p_h ) + return s * huge * huge; /* overflow */ + } + else if( ( j & 0x7fffffff ) > 0x43160000 ) /* z <= -150 */ + return s * tiny * tiny; /* underflow */ + else if( (unsigned int)j == 0xc3160000 ) + { /* z == -150 */ + if( p_l <= z - p_h ) + return s * tiny * tiny; /* underflow */ + } + + /* + * compute 2**(p_h+p_l) + */ + i = j & 0x7fffffff; + k = ( i >> 23 ) - 0x7f; + n = 0; + + if( i > 0x3f000000 ) + { /* if |z| > 0.5, set n = [z+0.5] */ + n = j + ( 0x00800000 >> ( k + 1 ) ); + k = ( ( n & 0x7fffffff ) >> 23 ) - 0x7f; /* new k for n */ + SET_FLOAT_WORD( t, n & ~( 0x007fffff >> k ) ); + n = ( ( n & 0x007fffff ) | 0x00800000 ) >> ( 23 - k ); + + if( j < 0 ) + n = -n; + + p_h -= t; + } + + t = p_l + p_h; + GET_FLOAT_WORD( is, t ); + SET_FLOAT_WORD( t, is & 0xfffff000 ); + u = t * lg2_h; + v = ( p_l - ( t - p_h ) ) * lg2 + t * lg2_l; + z = u + v; + w = v - ( z - u ); + t = z * z; + t1 = z - t * ( P1 + t * ( P2 + t * ( P3 + t * ( P4 + t * P5 ) ) ) ); + r = ( z * t1 ) / ( t1 - two ) - ( w + z * w ); + z = one - ( r - z ); + GET_FLOAT_WORD( j, z ); + j += (n << 23 ); + + if( ( j >> 23 ) <= 0 ) + z = __scalbnf( z, n ); /* subnormal output */ + else + SET_FLOAT_WORD( z, j ); + + return s * z; +} + #endif diff --git a/src/game/bg_lib.h b/src/game/bg_lib.h index df86a340..99efe089 100644 --- a/src/game/bg_lib.h +++ b/src/game/bg_lib.h @@ -91,4 +91,5 @@ double tan( double x ); int abs( int n ); double fabs( double x ); double acos( double x ); +float pow( float x, float y ); diff --git a/src/game/bg_local.h b/src/game/bg_local.h index 28d5e511..43ac67fd 100644 --- a/src/game/bg_local.h +++ b/src/game/bg_local.h @@ -57,31 +57,6 @@ typedef struct { int previous_waterlevel; } pml_t; -//TA: struct that stores smooth ops -// there is an array of these in bg_pmove.c -typedef struct -{ - float time; - - vec3_t rotAxis; - float rotAngle; -} smooth_t; - -//TA: make this into a cvar later.... -#define SMOOTHTIME 300 -#define MAXSMOOTHS 16 - -//TA: wall climbing local -typedef struct -{ - smooth_t sList[ MAXSMOOTHS ]; - - qboolean justFallen; - vec3_t lastNormal; - vec3_t nonSvangles; - int lastUpmove; //for toggleable walling -} wcl_t; - extern pmove_t *pm; extern pml_t pml; diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 89a8d6ba..1ca5734c 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -3640,7 +3640,7 @@ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); //TA: have to get the surfNormal thru somehow... - if( ps->stats[ STAT_STATE ] & SS_GPISROTVEC ) + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) { VectorCopy( ceilingNormal, s->angles2 ); } @@ -3737,7 +3737,7 @@ void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); //TA: have to get the surfNormal thru somehow... - if( ps->stats[ STAT_STATE ] & SS_GPISROTVEC ) + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) { VectorCopy( ceilingNormal, s->angles2 ); } diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c index 5c0764d7..620ef21a 100644 --- a/src/game/bg_pmove.c +++ b/src/game/bg_pmove.c @@ -34,10 +34,6 @@ pmove_t *pm; pml_t pml; -//TA: wall climbing struct for EVERY client. Not c/s communicated so -// size isn't that important -wcl_t wcl[ MAX_CLIENTS ]; - // movement parameters float pm_stopspeed = 100.0f; float pm_duckScale = 0.25f; @@ -57,97 +53,6 @@ float pm_spectatorfriction = 5.0f; int c_pmove = 0; /* -================ -PM_AddSmoothOp - -Add a smoothing operation to the smoothing queue -================ -*/ -static void PM_AddSmoothOp( vec3_t rotAxis, float rotAngle ) -{ - int i; - - //hack to prevent multiple identical rotations being added to the queue - //this happens often because groundtrace is called twice a frame - for( i = 0; i < MAXSMOOTHS; i++ ) - { - if( wcl[ pm->ps->clientNum ].sList[ i ].time >= pm->cmd.serverTime - 50 ) - return; - - /*if( VectorCompare( sList[ i ].rotAxis, rotAxis ) ) - return;*/ - - } - - //iterate through smoothing array - for( i = 0; i < MAXSMOOTHS; i++ ) - { - //if a smooth has been performed it can be overwritten - if( wcl[ pm->ps->clientNum ].sList[ i ].time + SMOOTHTIME < pm->cmd.serverTime ) - { - //copy the new smooth into the array and stop - VectorCopy( rotAxis, wcl[ pm->ps->clientNum ].sList[ i ].rotAxis ); - wcl[ pm->ps->clientNum ].sList[ i ].rotAngle = rotAngle; - wcl[ pm->ps->clientNum ].sList[ i ].time = pm->cmd.serverTime; - return; - } - } - - //there are no free smooth slots -} - - -/* -================ -PM_PerformSmoothOps - -Perform all the smoothing operations in the smoothing queue -================ -*/ -static qboolean PM_PerformSmoothOps( vec3_t in[3], vec3_t out[3] ) -{ - int i; - float stLocal, sFraction; - vec3_t localIn[3], localOut[3]; - qboolean performed = qfalse; - - AxisCopy( in, localIn ); - - //iterate through smoothing array - for( i = 0; i < MAXSMOOTHS; i++ ) - { - //perform smooth - if( ( pm->cmd.serverTime < wcl[ pm->ps->clientNum ].sList[ i ].time + SMOOTHTIME ) && - ( VectorLength( wcl[ pm->ps->clientNum ].sList[ i ].rotAxis ) != 0 ) ) - { - //the rotAxis /should/ never be of zero length but q3 *will* crash if it is... - //better to be safe than sorry :) - - stLocal = 1.0 - ( ( ( wcl[ pm->ps->clientNum ].sList[ i ].time + SMOOTHTIME ) - pm->cmd.serverTime ) / SMOOTHTIME ); - - //some ppl might prefer this smoothing function: - //sFraction = -( 1.0 - sin( stLocal * M_PI / 2 ) ); - sFraction = -( cos( stLocal * M_PI ) + 1 ) / 2; - - RotatePointAroundVector( localOut[0], wcl[ pm->ps->clientNum ].sList[ i ].rotAxis, - localIn[0], sFraction * wcl[ pm->ps->clientNum ].sList[ i ].rotAngle ); - RotatePointAroundVector( localOut[1], wcl[ pm->ps->clientNum ].sList[ i ].rotAxis, - localIn[1], sFraction * wcl[ pm->ps->clientNum ].sList[ i ].rotAngle ); - RotatePointAroundVector( localOut[2], wcl[ pm->ps->clientNum ].sList[ i ].rotAxis, - localIn[2], sFraction * wcl[ pm->ps->clientNum ].sList[ i ].rotAngle ); - - AxisCopy( localOut, localIn ); - performed = qtrue; - } - } - - AxisCopy( localOut, out ); - - return performed; -} - - -/* =============== PM_AddEvent @@ -583,7 +488,7 @@ static qboolean PM_CheckJump( void ) { vec3_t normal = { 0, 0, -1 }; - if( !( pm->ps->stats[ STAT_STATE ] & SS_GPISROTVEC ) ) + if( !( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) ) VectorCopy( pm->ps->grapplePoint, normal ); VectorMA( pm->ps->velocity, JUMP_VELOCITY, normal, pm->ps->velocity ); @@ -1408,17 +1313,16 @@ PM_GroundClimbTrace */ static void PM_GroundClimbTrace( void ) { - vec3_t surfNormal, movedir, forward, right, point, srotAxis; + vec3_t surfNormal, movedir, forward, right, point; vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; - float toAngles[3], surfAngles[3], srotAngle; + float toAngles[3], surfAngles[3]; trace_t trace; int i; - qboolean smoothed = qtrue; //TA: If we're on the ceiling then grapplePoint is a rotation normal.. otherwise its a surface normal. // would have been nice if Carmack had left a few random variables in the ps struct for mod makers - if( pm->ps->stats[ STAT_STATE ] & SS_GPISROTVEC ) + if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) { VectorCopy( ceilingNormal, surfNormal ); } @@ -1428,7 +1332,7 @@ static void PM_GroundClimbTrace( void ) } //construct a vector which reflects the direction the player is looking wrt the surface normal - AngleVectors( wcl[ pm->ps->clientNum ].nonSvangles, forward, NULL, NULL ); + AngleVectors( pm->ps->viewangles, forward, NULL, NULL ); CrossProduct( forward, surfNormal, right ); VectorNormalize( right ); CrossProduct( surfNormal, right, movedir ); @@ -1475,9 +1379,6 @@ static void PM_GroundClimbTrace( void ) break; } - //experimental: slow down speed around transitions - pm->ps->stats[ STAT_STATE ] &= ~SS_WALLTRANSIDING; - //if we hit something if( trace.fraction < 1.0 && !( trace.surfaceFlags & ( SURF_SKY | SURF_NOIMPACT ) ) && !( trace.entityNum != ENTITYNUM_WORLD && i != 3 ) ) @@ -1489,9 +1390,6 @@ static void PM_GroundClimbTrace( void ) //surface... do some stuff... if( !VectorCompare( trace.plane.normal, surfNormal ) ) { - //experimental: slow down speed around transitions - pm->ps->stats[ STAT_STATE ] |= SS_WALLTRANSIDING; - //if the trace result or the old vector is not the floor or ceiling correct the YAW angle if( !VectorCompare( trace.plane.normal, refNormal ) && !VectorCompare( surfNormal, refNormal ) && !VectorCompare( trace.plane.normal, ceilingNormal ) && !VectorCompare( surfNormal, ceilingNormal ) ) @@ -1563,7 +1461,7 @@ static void PM_GroundClimbTrace( void ) { CrossProduct( surfNormal, trace.plane.normal, pm->ps->grapplePoint ); VectorNormalize( pm->ps->grapplePoint ); - pm->ps->stats[ STAT_STATE ] |= SS_GPISROTVEC; + pm->ps->stats[ STAT_STATE ] |= SS_WALLCLIMBINGCEILING; } //transition from ceiling to wall @@ -1575,14 +1473,6 @@ static void PM_GroundClimbTrace( void ) pm->ps->delta_angles[1] -= ANGLE2SHORT( ( ( surfAngles[1] - toAngles[1] ) * 2 ) - 180 ); } - - //smooth transitions - CrossProduct( surfNormal, trace.plane.normal, srotAxis ); - VectorNormalize( srotAxis ); - srotAngle = abs( RAD2DEG( acos( DotProduct( surfNormal, trace.plane.normal ) ) ) ); - - PM_AddSmoothOp( srotAxis, srotAngle ); - smoothed = qfalse; } pml.groundTrace = trace; @@ -1595,13 +1485,9 @@ static void PM_GroundClimbTrace( void ) { //so we know what surface we're stuck to VectorCopy( trace.plane.normal, pm->ps->grapplePoint ); - pm->ps->stats[ STAT_STATE ] &= ~SS_GPISROTVEC; + pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBINGCEILING; } - //so that surf -> empty space is smoothed - wcl[ pm->ps->clientNum ].justFallen = qtrue; - VectorCopy( pm->ps->grapplePoint, wcl[ pm->ps->clientNum ].lastNormal ); - //IMPORTANT: break out of the for loop if we've hit something break; } @@ -1616,42 +1502,16 @@ static void PM_GroundClimbTrace( void ) if ( trace.fraction >= 1.0 ) { - //mild hack to get smoothing when jumping off walls - if( pm->cmd.upmove > 0 ) - smoothed = qfalse; - // if the trace didn't hit anything, we are in free fall - //Com_Printf( "trace missed justFallen:%d\n", wcl[ pm->ps->clientNum ].justFallen ); PM_GroundTraceMissed(); pml.groundPlane = qfalse; pml.walking = qfalse; pm->ps->legsAnim &= ~ANIM_WALLCLIMBING; - if( wcl[ pm->ps->clientNum ].justFallen && !smoothed ) - { - if( pm->ps->stats[ STAT_STATE ] & SS_GPISROTVEC ) - { - //FIXME: need some delta-correction here - //pm->ps->delta_angles[1] -= ANGLE2SHORT( ( ( nonSvangles[1] - pm->ps->grapplePoint[1] ) * 2) ); - AngleVectors( pm->ps->viewangles, NULL, srotAxis, NULL ); - - srotAngle = 180; - } - else - { - CrossProduct( wcl[ pm->ps->clientNum ].lastNormal, refNormal, srotAxis ); - VectorNormalize( srotAxis ); - srotAngle = abs( RAD2DEG( acos( DotProduct( refNormal, wcl[ pm->ps->clientNum ].lastNormal ) ) ) ); - } - - PM_AddSmoothOp( srotAxis, srotAngle ); - } - - pm->ps->stats[ STAT_STATE ] &= ~SS_GPISROTVEC; + pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBINGCEILING; //we get very bizarre effects if we don't do this :0 VectorCopy( refNormal, pm->ps->grapplePoint ); - wcl[ pm->ps->clientNum ].justFallen = qfalse; return; } @@ -1689,19 +1549,21 @@ static void PM_GroundTrace( void ) { if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) ) { //toggle wall climbing if holding crouch - if( pm->cmd.upmove < 0 && wcl[ pm->ps->clientNum ].lastUpmove >= 0 ) + if( pm->cmd.upmove < 0 && !( pm->ps->pm_flags & PMF_CROUCH_HELD ) ) { if( !( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) ) pm->ps->stats[ STAT_STATE ] |= SS_WALLCLIMBING; else if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBING; + + pm->ps->pm_flags |= PMF_CROUCH_HELD; } + else if( pm->cmd.upmove >= 0 ) + pm->ps->pm_flags &= ~PMF_CROUCH_HELD; if( pm->ps->pm_type == PM_DEAD ) pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBING; - wcl[ pm->ps->clientNum ].lastUpmove = pm->cmd.upmove; - if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) { PM_GroundClimbTrace( ); @@ -1732,37 +1594,13 @@ static void PM_GroundTrace( void ) { return; } - if( wcl[ pm->ps->clientNum ].justFallen ) - { - if( pm->ps->stats[ STAT_STATE ] & SS_GPISROTVEC ) - { - //FIXME: need some delta-correction here - //pm->ps->delta_angles[1] -= ANGLE2SHORT( ( ( nonSvangles[1] - pm->ps->grapplePoint[1] ) * 2) ); - AngleVectors( wcl[ pm->ps->clientNum ].nonSvangles, NULL, srotAxis, NULL ); - - srotAngle = 180; - } - else - { - CrossProduct( wcl[ pm->ps->clientNum ].lastNormal, refNormal, srotAxis ); - VectorNormalize( srotAxis ); - - srotAngle = abs( RAD2DEG( acos( DotProduct( refNormal, wcl[ pm->ps->clientNum ].lastNormal ) ) ) ); - } - - PM_AddSmoothOp( srotAxis, srotAngle ); - } - - //things have already been smoothed.. - wcl[ pm->ps->clientNum ].justFallen = qfalse; - // if the trace didn't hit anything, we are in free fall if ( trace.fraction == 1.0 ) { PM_GroundTraceMissed(); pml.groundPlane = qfalse; pml.walking = qfalse; - pm->ps->stats[ STAT_STATE ] &= ~SS_GPISROTVEC; + pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBINGCEILING; //we get very bizarre effects if we don't do this :0 VectorCopy( refNormal, pm->ps->grapplePoint ); @@ -2574,11 +2412,11 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) { short temp[3]; int i; vec3_t surfNormal, xNormal; - vec3_t axis[3], rotaxis[3], smoothaxis[3]; + vec3_t axis[3], rotaxis[3]; vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; float rotAngle; - vec3_t tempang, tempang2; + vec3_t tempang; if( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPINTERMISSION ) return; // no view changes at all @@ -2612,7 +2450,7 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) { AnglesToAxis( tempang, axis ); //the grapplePoint being a surfNormal rotation Normal hack... see above :) - if( ps->stats[ STAT_STATE ] & SS_GPISROTVEC ) + if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) { VectorCopy( ceilingNormal, surfNormal ); VectorCopy( ps->grapplePoint, xNormal ); @@ -2648,40 +2486,23 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) { AxisCopy( axis, rotaxis ); } - AxisToAngles( rotaxis, wcl[ pm->ps->clientNum ].nonSvangles ); - - //force angles to -180 <= x <= 180 - for( i = 0; i < 3; i++ ) - { - while( wcl[ pm->ps->clientNum ].nonSvangles[ i ] > 180 ) - wcl[ pm->ps->clientNum ].nonSvangles[ i ] -= 360; - - while( wcl[ pm->ps->clientNum ].nonSvangles[ i ] < 180 ) - wcl[ pm->ps->clientNum ].nonSvangles[ i ] += 360; - } - - //smooth transitions - if( !PM_PerformSmoothOps( rotaxis, smoothaxis ) ) - AxisCopy( rotaxis, smoothaxis ); - //convert the new axis back to angles - AxisToAngles( smoothaxis, tempang2 ); + AxisToAngles( rotaxis, tempang ); //force angles to -180 <= x <= 180 //AnglesSubtract( tempang2, 0, tempang2 ); for( i = 0; i < 3; i++ ) { - while( tempang2[ i ] > 180 ) - tempang2[ i ] -= 360; + while( tempang[ i ] > 180 ) + tempang[ i ] -= 360; - while( tempang2[ i ] < 180 ) - tempang2[ i ] += 360; + while( tempang[ i ] < 180 ) + tempang[ i ] += 360; } //actually set the viewangles - for (i=0 ; i<3 ; i++) { - ps->viewangles[i] = tempang2[i]; - } + for ( i = 0; i < 3; i++ ) + ps->viewangles[ i ] = tempang[ i ]; } @@ -2783,11 +2604,7 @@ void PmoveSingle (pmove_t *pmove) // is moved to the client side PM_UpdateViewAngles( pm->ps, &pm->cmd ); - if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) && - ( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) ) - AngleVectors( wcl[ pm->ps->clientNum ].nonSvangles, pml.forward, pml.right, pml.up ); - else - AngleVectors( pm->ps->viewangles, pml.forward, pml.right, pml.up ); + AngleVectors( pm->ps->viewangles, pml.forward, pml.right, pml.up ); if ( pm->cmd.upmove < 10 ) { // not holding jump diff --git a/src/game/bg_public.h b/src/game/bg_public.h index d0d9399c..0e864bc5 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -160,6 +160,7 @@ typedef enum { // pmove->pm_flags #define PMF_DUCKED 1 #define PMF_JUMP_HELD 2 +#define PMF_CROUCH_HELD 4 #define PMF_BACKWARDS_JUMP 8 // go into backwards land #define PMF_BACKWARDS_RUN 16 // coast down to backwards run #define PMF_TIME_LAND 32 // pm_time is time before rejump @@ -247,9 +248,8 @@ typedef enum { #define SCA_FOVWARPS 32 #define SS_WALLCLIMBING 1 -#define SS_GPISROTVEC 2 -#define SS_CREEPSLOWED 4 -#define SS_WALLTRANSIDING 8 +#define SS_WALLCLIMBINGCEILING 2 +#define SS_CREEPSLOWED 8 #define SS_SPEEDBOOST 16 #define SS_INFESTING 32 #define SS_GRABBED 64 diff --git a/src/game/q_shared.h b/src/game/q_shared.h index 8814b664..b5fd5889 100644 --- a/src/game/q_shared.h +++ b/src/game/q_shared.h @@ -630,7 +630,7 @@ void ByteToDir( int b, vec3_t dir ); typedef struct { float v[3]; } vec3struct_t; -#define VectorCopy(a,b) *(vec3struct_t *)b=*(vec3struct_t *)a; +#define VectorCopy(a,b) *(vec3struct_t *)b=*(vec3struct_t *)a #define ID_INLINE static #endif #endif |