view.cpp
.V_CalcBob
- calculates the number that is used to 'push' the viewmodel forward in Half-LifeV_CalcRoll
- only in DMC, it is used to calculate the roll that depends on the player's side movementV_CalcGunAngle
- sets up the viewmodel angles, also applies TFC concussion grenade effect (albeit it's unused in vanilla HL)V_AddIdle
- applies TFC concussion grenade effect, used by the view when a game of deathmatch is over and a level change is coming upV_CalcViewRoll
- "chooses" the amount of view roll depending on if the player is alive or dead - if the player is dead, then 80° for the rollV_CalcNormalRefdef
- the big function that calls most of the above and applies the view bobbingvoid DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams )
{
// RecClCalcRefdef(pparams);
// intermission / finale rendering
if ( pparams->intermission )
{
V_CalcIntermissionRefdef ( pparams );
}
else if ( pparams->spectator || g_iUser1 ) // g_iUser true if in spectator mode
{
V_CalcSpectatorRefdef ( pparams );
}
else if ( !pparams->paused )
{
V_CalcNormalRefdef ( pparams );
}
}
From the engine, we also get a pparams
, or in other words, some variables about the player's state.typedef struct ref_params_s
{
// Output
float vieworg[3]; // view origin, position of our "eyes"
float viewangles[3]; // view angles
float forward[3]; // forward vector, direction forward relative to our view angles
float right[3]; // right vector
float up[3]; // up vector
// Client frametime;
float frametime;
...
int onground;
int waterlevel;
float simvel[3]; // player velocity
float simorg[3]; // player origin
...
float cl_viewangles[3]; // client view angles, taken into account when firing a weapon
...
float punchangle[3]; // punchangle from server
...
We won't modify any of these yet in this tutorial, as we'll be modifying the weapon position & angles instead.
// throw in a little tilt.
view->angles[YAW] -= bob * 0.5;
view->angles[ROLL] -= bob * 1;
view->angles[PITCH] -= bob * 0.3;
// pushing the view origin down off of the same X/Z plane as the ent's origin will give the
// gun a very nice 'shifting' effect when the player looks up/down. If there is a problem
// with view model distortion, this may be a cause. (SJB).
view->origin[2] -= 1;
view->angles
does not actually affect the angles of the viewmodel.// Enables old HL WON view bobbing
VectorCopy( view->angles, view->curstate.angles );
That's all. The one line that brings back HL WON view bobbing.offset_forward = sin( time )
1: X = 0.0, Y = 0.0
2: X = 0.5, Y = 1.0
3: X = 1.0, Y = 0.0
4: X = 0.5, Y = -1.0
5: X = 0.0, Y = 0.0
6: X = -0.5, Y = 1.0
7: X = -1.0, Y = 0.0
8: X = -0.5, Y = -1.0
Now, tell me if you notice a pattern there. X = sin(cycle)
Y = sin(2cycle)
Let's define a point called viewmodel
and assign it the coordinates sin(cycle) and sin(2cycle).viewmodel = ( sin(cycle), sin(2cycle) )
Now, the only thing left to do should be to apply this to the viewmodel.
model->origin += right * sin(cycle);
model->origin += up * sin(2*cycle);
However, it doesn't quite work that way in HL SDK. Instead, that's what V_CalcBob is for.
float bob = V_CalcBob( pparams );
// bob is proportional to simulated velocity in the xy plane
// (don't count Z, or jumping messes it up)
VectorCopy( pparams->simvel, vel );
vel[2] = 0;
bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value;
bob = bob * 0.3 + bob * 0.7 * sin(cycle);
bob = V_min( bob, 4 );
bob = V_max( bob, -7 );
return bob;
A*0.3 + B*0.7
is a whole other topic that I'll cover in part 2 of this tutorial. It's a form of linear interpolation.sin(cycle)
is the heart of this very algorithm.
static double bobtime;
static float bob;
static float lasttime;
We will get rid of those. Delete those 3 lines and change the function's parameters, so that your V_CalcBob will look like this:
void V_CalcBob ( struct ref_params_s *pparams, double &bobtime, float &bob, float &lasttime )
{
float cycle;
vec3_t vel;
I've also changed float V_CalcBob to void V_CalcBob.V_CalcBob( pparams, bobtime, bob, lasttime );
bob
by reference, there's no need to return it any more, hence the function is a void one.enum calcBobMode_t
{
VB_COS,
VB_SIN,
VB_COS2,
VB_SIN2
};
And then modify V_CalcBob's parameters again:
void V_CalcBob ( struct ref_params_s *pparams, float freqmod, calcBobMode_t mode, double &bobtime, float &bob, float &lasttime )
In there, I snuck in a variable called freqmod
. This is actually gonna be the 'frequency modifier`. If the frequency is higher, then the cycle, and thus bob, will be faster.if ( pparams->onground == -1 ||
pparams->time == lasttime )
{
// just use old value
return bob;
}
lasttime = pparams->time;
bobtime += pparams->frametime;
if ( pparams->onground == -1 ||
pparams->time == lasttime )
{
// just use old value
return;// bob;
}
lasttime = pparams->time;
bobtime += pparams->frametime * freqmod;
bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value;
bob = bob * 0.3 + bob * 0.7 * sin(cycle);
bob = V_min( bob, 4 );
bob = V_max( bob, -7 );
return bob;
}
bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value;
if ( mode == VB_SIN )
bob = bob*0.3 + bob*0.7*sin(cycle);
else if ( mode == VB_COS )
bob = bob*0.3 + bob*0.7*cos(cycle);
else if ( mode == VB_SIN2 )
bob = bob*0.3 + bob*0.7*sin(cycle)*sin(cycle);
else if ( mode == VB_COS2 )
bob = bob*0.3 + bob*0.7*cos(cycle)*cos(cycle);
bob = V_min( bob, 4 );
bob = V_max( bob, -7 );
//return bob;
}
void V_CalcNormalRefdef ( struct ref_params_s *pparams )
{
cl_entity_t *ent, *view;
int i;
vec3_t angles;
float bob, waterOffset;
static viewinterp_t ViewInterp;
static float oldz = 0;
static float lasttime;
void V_CalcNormalRefdef ( struct ref_params_s *pparams )
{
cl_entity_t *ent, *view;
int i;
vec3_t angles;
float bobRight = 0, bobUp = 0, bobForward = 0, waterOffset;
static viewinterp_t ViewInterp;
static float oldz = 0;
static float lasttime;
static double bobtimes[ 3 ] = { 0,0,0 };
static float lasttimes[ 3 ] = { 0,0,0 };
// transform the view offset by the model's matrix to get the offset from
// model origin for the view
bob = V_CalcBob ( pparams );
// transform the view offset by the model's matrix to get the offset from
// model origin for the view
V_CalcBob( pparams, 0.75f, VB_SIN, bobtimes[0], bobRight, lasttimes[0] ); // right
V_CalcBob( pparams, 1.50f, VB_SIN, bobtimes[1], bobUp, lasttimes[1] ); // up
V_CalcBob( pparams, 1.00f, VB_SIN, bobtimes[2], bobForward, lasttimes[2] ); // forward
V_CalcBob( pparams, 0.75f, VB_SIN
is essentially sin( 0.75 * cycle)
for ( i = 0; i < 3; i++ )
{
view->origin[ i ] += bob * 0.4 * pparams->forward[ i ];
}
view->origin[2] += bob;
// throw in a little tilt.
view->angles[YAW] -= bob * 0.5;
view->angles[ROLL] -= bob * 1;
view->angles[PITCH] -= bob * 0.3;
for ( i = 0; i < 3; i++ )
{
view->origin[i] += bobRight * 0.33 * pparams->right[i];
view->origin[i] += bobUp * 0.17 * pparams->up[i];
view->origin[i] += bobForward * 0.4 * pparams->forward[i];
}
view->origin[2] += bobRight;
// throw in a little tilt.
//view->angles[YAW] -= bobForward * 0.5;
//view->angles[ROLL] -= bobForward * 1.0;
//view->angles[PITCH] -= bobForward * 0.3;
You must log in to post a comment. You can login or register a new account.