//----------------------------------------------------------------------------- // Purpose: Blend view angles. //----------------------------------------------------------------------------- void C_PropJeep::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd ) { if ( r_JeepViewBlendTo.GetInt() ) { // Check to see if the mouse has been touched in a bit or that we are not throttling. if ( ( pCmd->mousedx != 0 || pCmd->mousedy != 0 ) || ( fabsf( m_flThrottle ) < 0.01f ) ) { m_flViewAngleDeltaTime = 0.0f; } else { m_flViewAngleDeltaTime += gpGlobals->frametime; } if ( m_flViewAngleDeltaTime > r_JeepViewBlendToTime.GetFloat() ) { // Blend the view angles. int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" ); Vector vehicleEyeOrigin; QAngle vehicleEyeAngles; GetAttachmentLocal( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles ); QAngle outAngles; InterpolateAngles( pCmd->viewangles, vehicleEyeAngles, outAngles, r_JeepViewBlendToScale.GetFloat() ); pCmd->viewangles = outAngles; } } BaseClass::UpdateViewAngles( pLocalPlayer, pCmd ); }
bool evolve::Geometry::IsAngleInRange(float angle, float lower, float upper) { float centerAngle = InterpolateAngles(lower,upper,.5f); float disFromCenter = DistanceBetweenAngles(centerAngle,angle); float range = DistanceBetweenAngles(lower,upper); return (disFromCenter < (range/2.f)); }
void C_HLTVCamera::SmoothCameraAngle( QAngle& targetAngle ) { if ( m_flLastAngleUpdateTime > 0 ) { float deltaTime = gpGlobals->realtime - m_flLastAngleUpdateTime; deltaTime = clamp( deltaTime*m_flInertia, 0.01, 1); InterpolateAngles( m_aCamAngle, targetAngle, m_aCamAngle, deltaTime ); } else { m_aCamAngle = targetAngle; } m_flLastAngleUpdateTime = gpGlobals->realtime; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_PlayerClassCommando::InterpolateBullRushViewAngles( void ) { // Determine the fraction. if ( m_ClassData.m_flBullRushTime < COMMANDO_BULLRUSH_VIEWDELTA_TEST ) { m_ClassData.m_vecBullRushViewDir = m_ClassData.m_vecBullRushViewGoalDir; return; } float flFraction = 1.0f - ( ( m_ClassData.m_flBullRushTime - COMMANDO_BULLRUSH_VIEWDELTA_TEST ) / COMMANDO_BULLRUSH_VIEWDELTA_TIME ); QAngle angCurrent; InterpolateAngles( m_ClassData.m_vecBullRushViewDir, m_ClassData.m_vecBullRushViewGoalDir, angCurrent, flFraction ); NormalizeAngles( angCurrent ); m_ClassData.m_vecBullRushViewDir = angCurrent; }
//========================== // V_CalcCameraRefdef //========================== void V_CalcCameraRefdef( struct ref_params_s *pparams ) { static float lasttime, oldz = 0; // get viewentity and monster eyeposition cl_entity_t *view = GET_ENTITY( pparams->viewentity ); if( view ) { pparams->vieworg = view->origin; pparams->viewangles = view->angles; // interpolate position for monsters if( view->curstate.movetype == MOVETYPE_STEP ) { float f; // don't do it if the goalstarttime hasn't updated in a while. // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit // was increased to 1.0 s., which is 2x the max lag we are accounting for. if(( GET_CLIENT_TIME() < view->curstate.animtime + 1.0f ) && ( view->curstate.animtime != view->latched.prevanimtime )) { f = (GET_CLIENT_TIME() - view->curstate.animtime) / (view->curstate.animtime - view->latched.prevanimtime); } if( !( view->curstate.effects & EF_NOINTERP )) { // ugly hack to interpolate angle, position. // current is reached 0.1 seconds after being set f = f - 1.0f; } else { f = 0.0f; } InterpolateOrigin( view->latched.prevorigin, view->origin, pparams->vieworg, f, true ); InterpolateAngles( view->latched.prevangles, view->angles, pparams->viewangles, f, true ); } studiohdr_t *viewmonster = (studiohdr_t *)IEngineStudio.Mod_Extradata( view->model ); if( viewmonster && view->curstate.eflags & EFLAG_SLERP ) { Vector forward; AngleVectors( pparams->viewangles, forward, NULL, NULL ); Vector viewpos = viewmonster->eyeposition; if( viewpos == g_vecZero ) viewpos = Vector( 0, 0, 8 ); // monster_cockroach pparams->vieworg += viewpos + forward * 8; // best value for humans pparams->fov_x = 100; // adjust fov for monster view pparams->fov_y = V_CalcFov( pparams->fov_x, pparams->viewport[2], pparams->viewport[3] ); } // this is smooth stair climbing in thirdperson mode but not affected for client model :( if( !pparams->smoothing && pparams->onground && view->origin[2] - oldz > 0.0f ) { float steptime; steptime = pparams->time - lasttime; if( steptime < 0 ) steptime = 0; oldz += steptime * 150.0f; if( oldz > view->origin[2] ) oldz = view->origin[2]; if( view->origin[2] - oldz > pparams->movevars->stepsize ) oldz = view->origin[2] - pparams->movevars->stepsize; pparams->vieworg[2] += oldz - view->origin[2]; } else { oldz = view->origin[2]; } lasttime = pparams->time; if( view->curstate.effects & EF_NUKE_ROCKET ) pparams->viewangles.x = -pparams->viewangles.x; // stupid quake bug! // g-cont. apply shake to camera gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0f ); } }
void V_GetDirectedChasePosition(cl_entity_t * ent1, cl_entity_t * ent2,float * angle, float * origin) { float newAngle[3]; float newOrigin[3]; float tempVec[3]; int flags = gHUD.m_Spectator.m_iObserverFlags; qboolean deadPlayer = ent1->player && (ent1->curstate.solid == SOLID_NOT); float dfactor = ( flags & DRC_FLAG_DRAMATIC )? -1.0f : 1.0f; if ( ent1->player && (ent1->curstate.solid == SOLID_NOT) ) dfactor = 1.5f; // zoom away if player dies float distance = 112.0f + ( 16.0f * dfactor ); // get close if dramatic; // go away in final scenes if (flags & DRC_FLAG_FINAL ) distance*=2.0f; // let v_lastDistance float smoothly away v_lastDistance+= v_frametime * 24.0f; // move unit per seconds back if ( distance > v_lastDistance ) distance = v_lastDistance; VectorCopy(ent1->origin, newOrigin); if ( ent1->player ) { if ( deadPlayer ) newOrigin[2]+= 2; //laying on ground else newOrigin[2]+= 28; // head level of living player } else newOrigin[2]+= 8; // object, tricky, must be above bomb in CS if ( ( ent2 == (cl_entity_t*)0xFFFFFFFF ) || deadPlayer ) // we have no second target or player just died { // we have no second target, choose view direction based on // show front of primary target VectorCopy(ent1->angles, newAngle); newAngle[1]+= 180.0f; newAngle[0]+= 12.5f * dfactor; // lower angle if dramatic // if final scene (bomb), show from real high pos if ( flags & DRC_FLAG_FINAL ) newAngle[0] = 22.5f; // choose side of object/player if ( flags & DRC_FLAG_SIDE ) newAngle[1]+=22.5f; else newAngle[1]-=22.5f; // if ( AngleBetweenVectors( tempVec, newAngle ) > 1.0f ) V_SmoothInterpolateAngles( v_lastAngles, newAngle, angle, 120.0f ); // HACK, if player is dead don't clip against his dead body, can't check this V_GetChaseOrigin( angle, newOrigin, distance, deadPlayer, origin ); } else if ( ent2 ) { // get new angle towards second target VectorSubtract( ent2->origin, ent1->origin, newAngle ); VectorAngles( newAngle, newAngle ); newAngle[0] = -newAngle[0]; // set angle diffrent in Dramtaic scenes newAngle[0]+= 12.5f * dfactor; // lower angle if dramatic if ( flags & DRC_FLAG_SIDE ) newAngle[1]+=22.5f; else newAngle[1]-=22.5f; V_GetChaseOrigin( newAngle, newOrigin, distance, false, origin ); origin[2]+= 16.0f*( 1.0f - (v_lastDistance / distance) ); // calculate angle to second target VectorSubtract( ent2->origin, origin, tempVec ); VectorAngles( tempVec, tempVec ); tempVec[0] = -tempVec[0]; // take middle between two viewangles InterpolateAngles( newAngle, tempVec, angle, 0.5f); } else { // second target disappeard somehow (dead) // keep last good viewangle V_GetChaseOrigin( angle, newOrigin, distance, false, origin ); } VectorCopy(angle, v_lastAngles); }
/* ================== V_CalcSpectatorRefdef ================== */ void V_CalcSpectatorRefdef ( struct ref_params_s * pparams ) { vec3_t angles; static viewinterp_t ViewInterp; static float bob = 0.0f; static vec3_t velocity ( 0.0f, 0.0f, 0.0f); static int lastWeaponModelIndex = 0; static int lastViewModelIndex = 0; cl_entity_t * ent = gEngfuncs.GetEntityByIndex( g_iUser2 ); cl_entity_t * gunModel = gEngfuncs.GetViewModel(); static float lasttime; static float lastang[3]; static float lastorg[3]; vec3_t delta; pparams->onlyClientDraw = false; // refresh position VectorCopy ( pparams->simorg, v_sim_org ); // get old values VectorCopy ( pparams->cl_viewangles, v_cl_angles ); VectorCopy ( pparams->viewangles, v_angles ); VectorCopy ( pparams->vieworg, v_origin ); v_frametime = pparams->frametime; if ( pparams->nextView == 0 ) { // first renderer cycle, full screen switch ( g_iUser1 ) { case OBS_CHASE_LOCKED: V_GetChasePos( g_iUser2, NULL, v_origin, v_angles ); break; case OBS_CHASE_FREE: V_GetChasePos( g_iUser2, v_cl_angles, v_origin, v_angles ); break; case OBS_ROAMING : VectorCopy (v_cl_angles, v_angles); VectorCopy (v_sim_org, v_origin); break; case OBS_IN_EYE : V_GetInEyePos( g_iUser2, v_origin, v_angles ); break; case OBS_MAP_FREE : pparams->onlyClientDraw = true; V_GetMapFreePosition( v_cl_angles, v_origin, v_angles ); break; case OBS_MAP_CHASE : pparams->onlyClientDraw = true; V_GetMapChasePosition( g_iUser2, v_cl_angles, v_origin, v_angles ); break; } if ( gHUD.m_Spectator.m_pip->value ) pparams->nextView = 1; // force a second renderer view gHUD.m_Spectator.m_iDrawCycle = 0; } else { // second renderer cycle, inset window // set inset parameters pparams->viewport[0] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowX); // change viewport to inset window pparams->viewport[1] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowY); pparams->viewport[2] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowWidth); pparams->viewport[3] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowHeight); pparams->nextView = 0; // on further view pparams->onlyClientDraw = false; // override some settings in certain modes switch ( (int)gHUD.m_Spectator.m_pip->value ) { case INSET_CHASE_FREE : V_GetChasePos( g_iUser2, v_cl_angles, v_origin, v_angles ); break; case INSET_IN_EYE : V_GetInEyePos( g_iUser2, v_origin, v_angles ); break; case INSET_MAP_FREE : pparams->onlyClientDraw = true; V_GetMapFreePosition( v_cl_angles, v_origin, v_angles ); break; case INSET_MAP_CHASE : pparams->onlyClientDraw = true; if ( g_iUser1 == OBS_ROAMING ) V_GetMapChasePosition( 0, v_cl_angles, v_origin, v_angles ); else V_GetMapChasePosition( g_iUser2, v_cl_angles, v_origin, v_angles ); break; } gHUD.m_Spectator.m_iDrawCycle = 1; } // do the smoothing only once per frame, not in roaming or map mode if ( (gHUD.m_Spectator.m_iDrawCycle == 0) && (g_iUser1 == OBS_IN_EYE) ) { // smooth angles VectorSubtract( v_angles, lastang, delta ); if ( Length( delta ) != 0.0f ) { VectorCopy( v_angles, ViewInterp.Angles[ ViewInterp.CurrentAngle & ORIGIN_MASK ] ); ViewInterp.AngleTime[ ViewInterp.CurrentAngle & ORIGIN_MASK ] = pparams->time; ViewInterp.CurrentAngle++; VectorCopy( v_angles, lastang ); } if ( cl_vsmoothing && cl_vsmoothing->value ) { int foundidx; int i; float t; t = pparams->time - cl_vsmoothing->value; for ( i = 1; i < ORIGIN_MASK; i++ ) { foundidx = ViewInterp.CurrentAngle - 1 - i; if ( ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ] <= t ) break; } if ( i < ORIGIN_MASK && ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ] != 0.0 ) { // Interpolate double dt; float da; vec3_t v1,v2; AngleVectors( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], v1, NULL, NULL ); AngleVectors( ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], v2, NULL, NULL ); da = AngleBetweenVectors( v1, v2 ); dt = ViewInterp.AngleTime[ (foundidx + 1) & ORIGIN_MASK ] - ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ]; if ( dt > 0.0 && ( da < 22.5f) ) { double frac; frac = ( t - ViewInterp.AngleTime[ foundidx & ORIGIN_MASK] ) / dt; frac = min( 1.0, frac ); // interpolate angles InterpolateAngles( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], v_angles, frac ); } } } // smooth origin VectorSubtract( v_origin, lastorg, delta ); if ( Length( delta ) != 0.0 ) { VectorCopy( v_origin, ViewInterp.Origins[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] ); ViewInterp.OriginTime[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->time; ViewInterp.CurrentOrigin++; VectorCopy( v_origin, lastorg ); } // don't smooth in roaming (already smoothd), if ( cl_vsmoothing && cl_vsmoothing->value ) { int foundidx; int i; float t; t = pparams->time - cl_vsmoothing->value; for ( i = 1; i < ORIGIN_MASK; i++ ) { foundidx = ViewInterp.CurrentOrigin - 1 - i; if ( ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] <= t ) break; } if ( i < ORIGIN_MASK && ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] != 0.0 ) { // Interpolate vec3_t delta; double frac; double dt; vec3_t neworg; dt = ViewInterp.OriginTime[ (foundidx + 1) & ORIGIN_MASK ] - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ]; if ( dt > 0.0 ) { frac = ( t - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK] ) / dt; frac = min( 1.0, frac ); VectorSubtract( ViewInterp.Origins[ ( foundidx + 1 ) & ORIGIN_MASK ], ViewInterp.Origins[ foundidx & ORIGIN_MASK ], delta ); VectorMA( ViewInterp.Origins[ foundidx & ORIGIN_MASK ], frac, delta, neworg ); // Dont interpolate large changes if ( Length( delta ) < 64 ) { VectorCopy( neworg, v_origin ); } } } } } // Hack in weapon model: if ( (g_iUser1 == OBS_IN_EYE || gHUD.m_Spectator.m_pip->value == INSET_IN_EYE) && ent && g_iUser2 ) { // get position for weapon model VectorCopy( v_origin, gunModel->origin); VectorCopy( v_angles, gunModel->angles); // add idle tremble gunModel->angles[PITCH]*=-1; // calculate player velocity float timeDiff = ent->curstate.msg_time - ent->prevstate.msg_time; if ( timeDiff > 0 ) { vec3_t distance; VectorSubtract(ent->prevstate.origin, ent->curstate.origin, distance); VectorScale(distance, 1/timeDiff, distance ); velocity[0] = velocity[0]*0.66f + distance[0]*0.33f; velocity[1] = velocity[1]*0.66f + distance[1]*0.33f; velocity[2] = velocity[2]*0.66f + distance[2]*0.33f; VectorCopy(velocity, pparams->simvel); pparams->onground = 1; bob = V_CalcBob( pparams ); } vec3_t forward; AngleVectors(v_angles, forward, NULL, NULL ); for ( int i = 0; i < 3; i++ ) { gunModel->origin[ i ] += bob * 0.4 * forward[ i ]; } // throw in a little tilt. gunModel->angles[YAW] -= bob * 0.5; gunModel->angles[ROLL] -= bob * 1; gunModel->angles[PITCH] -= bob * 0.3; VectorCopy( gunModel->angles, gunModel->curstate.angles ); VectorCopy( gunModel->angles, gunModel->latched.prevangles ); if ( lastWeaponModelIndex != ent->curstate.weaponmodel ) { // weapon model changed lastWeaponModelIndex = ent->curstate.weaponmodel; lastViewModelIndex = V_FindViewModelByWeaponModel( lastWeaponModelIndex ); if ( lastViewModelIndex ) { gEngfuncs.pfnWeaponAnim(0,0); // reset weapon animation } else { // model not found gunModel->model = NULL; // disable weaopn model lastWeaponModelIndex = lastViewModelIndex = 0; } } if ( lastViewModelIndex ) { gunModel->model = IEngineStudio.GetModelByIndex( lastViewModelIndex ); gunModel->curstate.modelindex = lastViewModelIndex; gunModel->curstate.frame = 0; gunModel->curstate.colormap = 0; gunModel->index = g_iUser2; } else { gunModel->model = NULL; // disable weaopn model } } else { gunModel->model = NULL; // disable weaopn model lastWeaponModelIndex = lastViewModelIndex = 0; } lasttime = pparams->time; // write back new values into pparams VectorCopy ( v_angles, pparams->viewangles ) VectorCopy ( v_origin, pparams->vieworg ); }