/* ================== V_CalcRefdef ================== */ 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; static float lastang[3]; vec3_t angdelta; vec3_t camAngles, camForward, camRight, camUp; cl_entity_t *pwater; // don't allow cheats in multiplayer if(pparams->maxclients > 1) { scr_ofsx->value = 0.0; scr_ofsy->value = 0.0; scr_ofsz->value = 0.0; } V_DriftPitch(pparams); // ent is the player model ( visible when out of body ) ent = gEngfuncs.GetLocalPlayer(); // view is the weapon model (only visible from inside body ) view = gEngfuncs.GetViewModel(); // transform the view offset by the model's matrix to get the offset from // model origin for the view bob = V_CalcBob(pparams); // Observer angle capturing and smoothing if(iHasNewViewOrigin) { // Get the angles from the physics code VectorCopy(vecNewViewOrigin, pparams->vieworg); VectorCopy(vecNewViewOrigin, pparams->simorg); } // refresh position VectorCopy(pparams->simorg, pparams->vieworg); pparams->vieworg[2] += (bob); VectorAdd(pparams->vieworg, pparams->viewheight, pparams->vieworg); // Observer angle capturing and smoothing if(iHasNewViewAngles) { // Get the angles from the physics code VectorCopy(vecNewViewAngles, pparams->cl_viewangles); } else if(pparams->health == -5) { CAM_ToThirdPerson(); // Lock mouse movement iMouseInUse = 1; pparams->cl_viewangles[0] = 89; // Spin the view float flTimeDelta = (pparams->time - g_flStartScaleTime); if(flTimeDelta > 0) { float flROFSpin = 1.0 + (flTimeDelta * 2.0); float flSpin = flTimeDelta * 45; pparams->cl_viewangles[1] = flSpin * flROFSpin; } } else { CAM_ToFirstPerson(); // Unlock mouse movement iMouseInUse = 0; } VectorSubtract(pparams->cl_viewangles, lastang, angdelta); if(Length(angdelta) != 0.0) { VectorCopy(pparams->cl_viewangles, ViewInterp.Angles[ViewInterp.CurrentAngle & ORIGIN_MASK]); ViewInterp.AngleTime[ViewInterp.CurrentAngle & ORIGIN_MASK] = pparams->time; ViewInterp.CurrentAngle++; VectorCopy(pparams->cl_viewangles, lastang); } if(cl_vsmoothing && cl_vsmoothing->value && (iIsSpectator & SPEC_SMOOTH_ANGLES)) { int foundidx; int i; float t; if(cl_vsmoothing->value < 0.0) { gEngfuncs.Cvar_SetValue("cl_vsmoothing", 0.0); } 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; dt = ViewInterp.AngleTime[(foundidx + 1) & ORIGIN_MASK] - ViewInterp.AngleTime[foundidx & ORIGIN_MASK]; if(dt > 0.0) { double frac; frac = (t - ViewInterp.AngleTime[foundidx & ORIGIN_MASK]) / dt; frac = min(1.0, frac); // interpolate angles V_InterpolateAngles(ViewInterp.Angles[foundidx & ORIGIN_MASK], ViewInterp.Angles[(foundidx + 1) & ORIGIN_MASK], pparams->cl_viewangles, frac); VectorCopy(pparams->cl_viewangles, vecNewViewAngles); } } } VectorCopy(pparams->cl_viewangles, pparams->viewangles); gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake(pparams->vieworg, pparams->viewangles, 1.0); // never let view origin sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // FIXME, we send origin at 1/128 now, change this? // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis pparams->vieworg[0] += 1.0 / 32; pparams->vieworg[1] += 1.0 / 32; pparams->vieworg[2] += 1.0 / 32; // Check for problems around water, move the viewer artificially if necessary // -- this prevents drawing errors in GL due to waves waterOffset = 0; if(pparams->waterlevel >= 2) { int i, contents, waterDist, waterEntity; vec3_t point; waterDist = cl_waterdist->value; if(pparams->hardware) { waterEntity = gEngfuncs.PM_WaterEntity(pparams->simorg); if(waterEntity >= 0 && waterEntity < pparams->max_entities) { pwater = gEngfuncs.GetEntityByIndex(waterEntity); if(pwater && (pwater->model != NULL)) { waterDist += (pwater->curstate.scale * 16); // Add in wave height } } } else { waterEntity = 0; // Don't need this in software } VectorCopy(pparams->vieworg, point); // Eyes are above water, make sure we're above the waves if(pparams->waterlevel == 2) { point[2] -= waterDist; for(i = 0; i < waterDist; i++) { contents = gEngfuncs.PM_PointContents(point, NULL); if(contents > CONTENTS_WATER) break; point[2] += 1; } waterOffset = (point[2] + waterDist) - pparams->vieworg[2]; } else { // eyes are under water. Make sure we're far enough under point[2] += waterDist; for(i = 0; i < waterDist; i++) { contents = gEngfuncs.PM_PointContents(point, NULL); if(contents <= CONTENTS_WATER) break; point[2] -= 1; } waterOffset = (point[2] - waterDist) - pparams->vieworg[2]; } } pparams->vieworg[2] += waterOffset; V_CalcViewRoll(pparams); V_AddIdle(pparams); // offsets VectorCopy(pparams->cl_viewangles, angles); AngleVectors(angles, pparams->forward, pparams->right, pparams->up); for(i = 0; i < 3; i++) { pparams->vieworg[i] += scr_ofsx->value * pparams->forward[i] + scr_ofsy->value * pparams->right[i] + scr_ofsz->value * pparams->up[i]; } // Treating cam_ofs[2] as the distance if(CL_IsThirdPerson()) { vec3_t ofs; ofs[0] = ofs[1] = ofs[2] = 0.0; CL_CameraOffset((float *)&ofs); VectorCopy(ofs, camAngles); camAngles[ROLL] = 0; AngleVectors(camAngles, camForward, camRight, camUp); // Is the player in a falling anim? If so, raise camera above and look down if(pparams->health == -5) { pparams->vieworg[2] += 92; } else { for(i = 0; i < 3; i++) { pparams->vieworg[i] += -ofs[2] * camForward[i]; } pparams->vieworg[2] += 20; } } // Give gun our viewangles VectorCopy(pparams->cl_viewangles, view->angles); // set up gun position V_CalcGunAngle(pparams); // Use predicted origin as view origin. VectorCopy(pparams->simorg, view->origin); view->origin[2] += (waterOffset); VectorAdd(view->origin, pparams->viewheight, view->origin); // Let the viewmodel shake at about 10% of the amplitude gEngfuncs.V_ApplyShake(view->origin, view->angles, 0.9); 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; // 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; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if(pparams->viewsize == 110) { view->origin[2] += 1; } else if(pparams->viewsize == 100) { view->origin[2] += 2; } else if(pparams->viewsize == 90) { view->origin[2] += 1; } else if(pparams->viewsize == 80) { view->origin[2] += 0.5; } // Add in the punchangle, if any VectorAdd(pparams->viewangles, pparams->punchangle, pparams->viewangles); // Include client side punch, too VectorAdd(pparams->viewangles, (float *)&ev_punchangle, pparams->viewangles); V_DropPunchAngle(pparams->frametime, (float *)&ev_punchangle); // smooth out stair step ups #if 1 if(!pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0) { float steptime; steptime = pparams->time - lasttime; if(steptime < 0) //FIXME I_Error ("steptime < 0"); steptime = 0; oldz += steptime * 150; if(oldz > pparams->simorg[2]) oldz = pparams->simorg[2]; if(pparams->simorg[2] - oldz > 18) oldz = pparams->simorg[2] - 18; pparams->vieworg[2] += oldz - pparams->simorg[2]; view->origin[2] += oldz - pparams->simorg[2]; } else { oldz = pparams->simorg[2]; } #endif { static float lastorg[3]; vec3_t delta; VectorSubtract(pparams->simorg, lastorg, delta); if(Length(delta) != 0.0) { VectorCopy(pparams->simorg, ViewInterp.Origins[ViewInterp.CurrentOrigin & ORIGIN_MASK]); ViewInterp.OriginTime[ViewInterp.CurrentOrigin & ORIGIN_MASK] = pparams->time; ViewInterp.CurrentOrigin++; VectorCopy(pparams->simorg, lastorg); } } // Smooth out whole view in multiplayer when on trains, lifts if(cl_vsmoothing && cl_vsmoothing->value && ((iIsSpectator & SPEC_SMOOTH_ORIGIN) || (pparams->smoothing && (pparams->maxclients > 1)))) { int foundidx; int i; float t; if(cl_vsmoothing->value < 0.0) { gEngfuncs.Cvar_SetValue("cl_vsmoothing", 0.0); } 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) { VectorSubtract(neworg, pparams->simorg, delta); VectorAdd(pparams->simorg, delta, pparams->simorg); VectorAdd(pparams->vieworg, delta, pparams->vieworg); VectorAdd(view->origin, delta, view->origin); VectorCopy(pparams->simorg, vecNewViewOrigin); } } } } // Store off v_angles before munging for third person v_angles = pparams->viewangles; if(CL_IsThirdPerson()) { VectorCopy(camAngles, pparams->viewangles); } // override all previous settings if the viewent isn't the client if(pparams->viewentity > pparams->maxclients) { cl_entity_t *viewentity; viewentity = gEngfuncs.GetEntityByIndex(pparams->viewentity); if(viewentity) { VectorCopy(viewentity->origin, pparams->vieworg); VectorCopy(viewentity->angles, pparams->viewangles); // Store off overridden viewangles v_angles = pparams->viewangles; } } lasttime = pparams->time; v_origin = pparams->vieworg; }
/* ================== V_CalcRefdef ================== */ void V_CalcRefdef(void) { entity_t *ent, *view; int i; vec3_t forward, right, up; vec3_t angles; float bob; static float oldz = 0; V_DriftPitch(); // ent is the player model (visible when out of body) ent = &cl_entities[cl.viewentity]; // view is the weapon model (only visible from inside body) view = &cl.viewent; // transform the view offset by the model's matrix to get the offset from // model origin for the view ent->angles[YAW] = cl.viewangles[YAW]; // the model should face // the view dir ent->angles[PITCH] = -cl.viewangles[PITCH]; // the model should face // the view dir bob = V_CalcBob(); // refresh position VectorCopy(ent->origin, r_refdef.vieworg); r_refdef.vieworg[2] += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis r_refdef.vieworg[0] += 1.0 / 32; r_refdef.vieworg[1] += 1.0 / 32; r_refdef.vieworg[2] += 1.0 / 32; VectorCopy(cl.viewangles, r_refdef.viewangles); V_CalcViewRoll(); V_AddIdle(); // offsets angles[PITCH] = -ent->angles[PITCH]; // because entity pitches are // actually backward angles[YAW] = ent->angles[YAW]; angles[ROLL] = ent->angles[ROLL]; AngleVectors(angles, forward, right, up); for (i = 0; i < 3; i++) r_refdef.vieworg[i] += scr_ofsx.value * forward[i] + scr_ofsy.value * right[i] + scr_ofsz.value * up[i]; V_BoundOffsets(); // set up gun position VectorCopy(cl.viewangles, view->angles); CalcGunAngle(); VectorCopy(ent->origin, view->origin); view->origin[2] += cl.viewheight; for (i = 0; i < 3; i++) { view->origin[i] += forward[i] * bob * 0.4; // view->origin[i] += right[i]*bob*0.4; // view->origin[i] += up[i]*bob*0.8; } view->origin[2] += bob; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if (scr_viewsize.value == 110) view->origin[2] += 1; else if (scr_viewsize.value == 100) view->origin[2] += 2; else if (scr_viewsize.value == 90) view->origin[2] += 1; else if (scr_viewsize.value == 80) view->origin[2] += 0.5; view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->frame = cl.stats[STAT_WEAPONFRAME]; view->colormap = vid.colormap; // set up the refresh position VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); // smooth out stair step ups if (cl.onground && ent->origin[2] - oldz > 0) { float steptime; steptime = cl.time - cl.oldtime; if (steptime < 0) //FIXME I_Error ("steptime < 0"); steptime = 0; oldz += steptime * 80; if (oldz > ent->origin[2]) oldz = ent->origin[2]; if (ent->origin[2] - oldz > 12) oldz = ent->origin[2] - 12; r_refdef.vieworg[2] += oldz - ent->origin[2]; view->origin[2] += oldz - ent->origin[2]; } else oldz = ent->origin[2]; if (chase_active.value) Chase_Update(); }
//========================== // V_CalcFirstPersonRefdef //========================== void V_CalcFirstPersonRefdef( struct ref_params_s *pparams ) { V_DriftPitch( pparams ); float bob = V_CalcBob( pparams ); pparams->vieworg = pparams->simorg; pparams->vieworg += pparams->viewheight; pparams->vieworg.z += bob; pparams->viewangles = pparams->cl_viewangles; gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0f ); V_CalcSendOrigin( pparams ); float waterOffset = V_CalcWaterLevel( pparams ); pparams->vieworg[2] += waterOffset; V_CalcViewRoll( pparams ); V_AddIdle( pparams ); // offsets AngleVectors( pparams->cl_viewangles, pparams->forward, pparams->right, pparams->up ); cl_entity_t *view = GET_VIEWMODEL(); Vector lastAngles = view->angles = pparams->cl_viewangles; V_CalcGunAngle( pparams ); // use predicted origin as view origin. view->origin = pparams->simorg; view->origin += pparams->viewheight; view->origin.z += waterOffset; // Let the viewmodel shake at about 10% of the amplitude gEngfuncs.V_ApplyShake( view->origin, view->angles, 0.9f ); view->origin += pparams->forward * bob * 0.4f; view->origin.z += bob; view->angles[PITCH] -= bob * 0.3f; view->angles[YAW] -= bob * 0.5f; view->angles[ROLL] -= bob * 1.0f; view->origin.z -= 1; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if( pparams->viewsize == 110 ) { view->origin[2] += 1; } else if( pparams->viewsize == 100 ) { view->origin[2] += 2; } else if( pparams->viewsize == 90 ) { view->origin[2] += 1; } else if( pparams->viewsize == 80 ) { view->origin[2] += 0.5; } V_CalcViewModelLag( pparams, view->origin, view->angles, lastAngles ); pparams->viewangles += pparams->punchangle; pparams->viewangles += ev_punchangle; V_DropPunchAngle(pparams->frametime,ev_punchangle); static float lasttime, oldz = 0; if( !pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0.0f ) { float steptime; steptime = pparams->time - lasttime; if( steptime < 0 ) steptime = 0; oldz += steptime * 150.0f; if( oldz > pparams->simorg[2] ) oldz = pparams->simorg[2]; if( pparams->simorg[2] - oldz > pparams->movevars->stepsize ) oldz = pparams->simorg[2] - pparams->movevars->stepsize; pparams->vieworg[2] += oldz - pparams->simorg[2]; view->origin.z += oldz - pparams->simorg[2]; } else { oldz = pparams->simorg[2]; } lasttime = pparams->time; // smooth player view in multiplayer V_InterpolatePos( pparams ); }
void V_CalcRefdef (void) { vec3_t forward; float bob; float height_adjustment; V_DriftPitch (); bob = V_CalcBob (); height_adjustment = v_viewheight.value ? bound (-7, v_viewheight.value, 4) : V_CalcBob (); // set up the refresh position VectorCopy (cl.simorg, r_refdef.vieworg); // never let it sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis r_refdef.vieworg[0] += 1.0/16; r_refdef.vieworg[1] += 1.0/16; r_refdef.vieworg[2] += 1.0/16; // add view height if (view_message.flags & PF_GIB) { r_refdef.vieworg[2] += 8; // gib view height } else if (view_message.flags & PF_DEAD && (cl.stats[STAT_HEALTH] <= 0)) { r_refdef.vieworg[2] -= 16; // corpse view height } else { // normal view height // Use STAT_VIEWHEIGHT in case of server support it or NQ demoplayback, if not then use default viewheight. r_refdef.vieworg[2] += ((cl.z_ext & Z_EXT_VIEWHEIGHT) || cls.nqdemoplayback) ? cl.stats[STAT_VIEWHEIGHT] : DEFAULT_VIEWHEIGHT; r_refdef.vieworg[2] += height_adjustment; r_refdef.vieworg[2] += bob; // smooth out stair step ups r_refdef.vieworg[2] += cl.crouch; } // set up refresh view angles VectorCopy (cl.simangles, r_refdef.viewangles); V_CalcViewRoll (); V_AddIdle (); if (v_gunkick.value) { // add weapon kick offset AngleVectors (r_refdef.viewangles, forward, NULL, NULL); VectorMA (r_refdef.vieworg, cl.punchangle, forward, r_refdef.vieworg); // add weapon kick angle r_refdef.viewangles[PITCH] += cl.punchangle * 0.5; } if (view_message.flags & PF_DEAD && (cl.stats[STAT_HEALTH] <= 0)) r_refdef.viewangles[ROLL] = 80; // dead view angle //VULT CAMERAS CameraUpdate(view_message.flags & PF_DEAD); V_AddViewWeapon (height_adjustment); }
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; vec3_t camAngles, camForward, camRight, camUp; cl_entity_t *pwater; static struct model_s *savedviewmodel; //LRC - if this is the second pass through, then we've just drawn the sky, and now we're setting up the normal view. if (pparams->nextView == 1) { gHUD.m_iSkyMode = SKY_ON; //This means that an env_sky is in the level but we are drawing the normal view this time. view = gEngfuncs.GetViewModel(); view->model = savedviewmodel; pparams->viewangles[0] = v_angles.x; pparams->viewangles[1] = v_angles.y; pparams->viewangles[2] = v_angles.z; pparams->vieworg[0] = v_origin.x; pparams->vieworg[1] = v_origin.y; pparams->vieworg[2] = v_origin.z; pparams->nextView = 0; if (gHUD.viewFlags & 1 ) // custom view active (trigger_viewset) //AJH (copied function from below) { cl_entity_t *viewentity; viewentity = gEngfuncs.GetEntityByIndex( gHUD.viewEntityIndex ); if (viewentity) { pparams->vieworg[0] = viewentity->origin[0]; pparams->vieworg[1] = viewentity->origin[1]; pparams->vieworg[2] = viewentity->origin[2]; pparams->vieworg[2] = viewentity->origin[2]; pparams->viewangles[0] = viewentity->angles[0]; pparams->viewangles[1] = viewentity->angles[1]; pparams->viewangles[2] = viewentity->angles[2]; pparams->crosshairangle[PITCH] = 100; // test // ugly method to remove crosshair from screen if(gHUD.viewFlags & 8 ) //AJH Do we draw the player in the camera? { gHUD.m_iCameraMode=2; } if(gHUD.viewFlags & 4 ) //AJH Invert the x view angle again if we are using an item camera? { pparams->viewangles[0] = -viewentity->angles[0]; } } else { gEngfuncs.Con_DPrintf( "Warning : invalid view ent index: %i\n", gHUD.viewEntityIndex ); } } else { pparams->crosshairangle[PITCH] = 0; // test } return; } V_DriftPitch ( pparams ); if ( gEngfuncs.IsSpectateOnly() ) { ent = gEngfuncs.GetEntityByIndex( g_iUser2 ); } else { // ent is the player model ( visible when out of body ) ent = gEngfuncs.GetLocalPlayer(); } // view is the weapon model (only visible from inside body ) view = gEngfuncs.GetViewModel(); // trigger_viewset - dont show weapon model when custom view is enabled if (gHUD.viewFlags & 1) view->model = NULL; //LRC - don't show weapon models when we're drawing the sky. if (gHUD.m_iSkyMode == SKY_ON) { savedviewmodel = view->model; view->model = NULL; } // transform the view offset by the model's matrix to get the offset from // model origin for the view bob = V_CalcBob ( pparams ); // refresh position VectorCopy ( pparams->simorg, pparams->vieworg ); pparams->vieworg[2] += ( bob ); VectorAdd( pparams->vieworg, pparams->viewheight, pparams->vieworg ); VectorCopy ( pparams->cl_viewangles, pparams->viewangles ); gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0 ); // never let view origin sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // FIXME, we send origin at 1/128 now, change this? // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis pparams->vieworg[0] += 1.0/32; pparams->vieworg[1] += 1.0/32; pparams->vieworg[2] += 1.0/32; // Check for problems around water, move the viewer artificially if necessary // -- this prevents drawing errors in GL due to waves waterOffset = 0; if ( pparams->waterlevel >= 2 ) { int i, contents, waterDist, waterEntity; vec3_t point; waterDist = cl_waterdist->value; if ( pparams->hardware ) { waterEntity = gEngfuncs.PM_WaterEntity( pparams->simorg ); if ( waterEntity >= 0 && waterEntity < pparams->max_entities ) { pwater = gEngfuncs.GetEntityByIndex( waterEntity ); if ( pwater && ( pwater->model != NULL ) ) { waterDist += ( pwater->curstate.scale * 16 ); // Add in wave height } } } else { waterEntity = 0; // Don't need this in software } VectorCopy( pparams->vieworg, point ); // Eyes are above water, make sure we're above the waves if ( pparams->waterlevel == 2 ) { point[2] -= waterDist; for ( i = 0; i < waterDist; i++ ) { contents = gEngfuncs.PM_PointContents( point, NULL ); if ( contents > CONTENTS_WATER ) break; point[2] += 1; } waterOffset = (point[2] + waterDist) - pparams->vieworg[2]; } else { // eyes are under water. Make sure we're far enough under point[2] += waterDist; for ( i = 0; i < waterDist; i++ ) { contents = gEngfuncs.PM_PointContents( point, NULL ); if ( contents <= CONTENTS_WATER ) break; point[2] -= 1; } waterOffset = (point[2] - waterDist) - pparams->vieworg[2]; } } pparams->vieworg[2] += waterOffset; V_CalcViewRoll ( pparams ); V_AddIdle ( pparams ); // offsets VectorCopy( pparams->cl_viewangles, angles ); AngleVectors ( angles, pparams->forward, pparams->right, pparams->up ); // don't allow cheats in multiplayer if ( pparams->maxclients <= 1 ) { for ( i=0 ; i<3 ; i++ ) { pparams->vieworg[i] += scr_ofsx->value*pparams->forward[i] + scr_ofsy->value*pparams->right[i] + scr_ofsz->value*pparams->up[i]; } } // Give gun our viewangles VectorCopy ( pparams->cl_viewangles, view->angles ); // set up gun position V_CalcGunAngle ( pparams ); // Use predicted origin as view origin. VectorCopy ( pparams->simorg, view->origin ); view->origin[2] += ( waterOffset ); VectorAdd( view->origin, pparams->viewheight, view->origin ); // Let the viewmodel shake at about 10% of the amplitude gEngfuncs.V_ApplyShake( view->origin, view->angles, 0.9 ); 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; // 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; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if (pparams->viewsize == 110) { view->origin[2] += 1; } else if (pparams->viewsize == 100) { view->origin[2] += 2; } else if (pparams->viewsize == 90) { view->origin[2] += 1; } else if (pparams->viewsize == 80) { view->origin[2] += 0.5; } // Add in the punchangle, if any VectorAdd ( pparams->viewangles, pparams->punchangle, pparams->viewangles ); // Include client side punch, too VectorAdd ( pparams->viewangles, (float *)&ev_punchangle, pparams->viewangles); V_DropPunchAngle ( pparams->frametime, (float *)&ev_punchangle ); // smooth out stair step ups #if 1 if ( !pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0) { float steptime; steptime = pparams->time - lasttime; if (steptime < 0) //FIXME I_Error ("steptime < 0"); steptime = 0; oldz += steptime * 150; if (oldz > pparams->simorg[2]) oldz = pparams->simorg[2]; if (pparams->simorg[2] - oldz > 18) oldz = pparams->simorg[2]- 18; pparams->vieworg[2] += oldz - pparams->simorg[2]; view->origin[2] += oldz - pparams->simorg[2]; } else { oldz = pparams->simorg[2]; } #endif { static float lastorg[3]; vec3_t delta; VectorSubtract( pparams->simorg, lastorg, delta ); if ( Length( delta ) != 0.0 ) { VectorCopy( pparams->simorg, ViewInterp.Origins[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] ); ViewInterp.OriginTime[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->time; ViewInterp.CurrentOrigin++; VectorCopy( pparams->simorg, lastorg ); } } // Smooth out whole view in multiplayer when on trains, lifts if ( cl_vsmoothing && cl_vsmoothing->value && ( pparams->smoothing && ( pparams->maxclients > 1 ) ) ) { int foundidx; int i; float t; if ( cl_vsmoothing->value < 0.0 ) { gEngfuncs.Cvar_SetValue( "cl_vsmoothing", 0.0 ); } 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 ) { VectorSubtract( neworg, pparams->simorg, delta ); VectorAdd( pparams->simorg, delta, pparams->simorg ); VectorAdd( pparams->vieworg, delta, pparams->vieworg ); VectorAdd( view->origin, delta, view->origin ); } } } } // Store off v_angles before munging for third person v_angles = pparams->viewangles; v_lastAngles = pparams->viewangles; // v_cl_angles = pparams->cl_viewangles; // keep old user mouse angles ! // override all previous settings if the viewent isn't the client if ( pparams->viewentity > pparams->maxclients ) { cl_entity_t *viewentity; viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity ); if ( viewentity ) { VectorCopy( viewentity->origin, pparams->vieworg ); VectorCopy( viewentity->angles, pparams->viewangles ); // Store off overridden viewangles v_angles = pparams->viewangles; } } lasttime = pparams->time; v_origin = pparams->vieworg; //LRC 1.8 - clear to the fog color (if any) on the first pass if ( pparams->nextView == 0 ) { ClearToFogColor(); } //LRC 1.8 - no fog in the env_sky if ( gHUD.m_iSkyMode != SKY_ON_DRAWING ) { RenderFog(); } if (gHUD.viewFlags & 1 && gHUD.m_iSkyMode == SKY_OFF) // custom view active (trigger_viewset) //AJH (added skymode check and copied function to above) { cl_entity_t *viewentity; viewentity = gEngfuncs.GetEntityByIndex( gHUD.viewEntityIndex ); if (viewentity) { pparams->vieworg[0] = viewentity->origin[0]; pparams->vieworg[1] = viewentity->origin[1]; pparams->vieworg[2] = viewentity->origin[2]; pparams->vieworg[2] = viewentity->origin[2]; pparams->viewangles[0] = viewentity->angles[0]; pparams->viewangles[1] = viewentity->angles[1]; pparams->viewangles[2] = viewentity->angles[2]; pparams->crosshairangle[PITCH] = 100; // test // ugly method to remove crosshair from screen if(gHUD.viewFlags & 8 ) //AJH Do we draw the player in the camera? { gHUD.m_iCameraMode=2; } if(gHUD.viewFlags & 4 ) //AJH Invert the x view angle again if we are using an item camera? { pparams->viewangles[0] = -viewentity->angles[0]; } } else gEngfuncs.Con_Printf( "Warning : invalid view ent index: %i\n", gHUD.viewEntityIndex ); } else pparams->crosshairangle[PITCH] = 0; // test // LRC - override the view position if we're drawing a sky, rather than the player's view if (gHUD.m_iSkyMode >= SKY_ON && pparams->nextView == 0) { gHUD.m_iSkyMode = SKY_ON_DRAWING; if (gHUD.m_iSkyScale == 0) //AJH No parallax (old behaviour) { pparams->vieworg[0] = gHUD.m_vecSkyPos.x; pparams->vieworg[1] = gHUD.m_vecSkyPos.y; pparams->vieworg[2] = gHUD.m_vecSkyPos.z; } else { VectorCopy(gHUD.m_vecSkyPos + v_origin/gHUD.m_iSkyScale,pparams->vieworg); } if (gHUD.viewFlags & 1)//AJH (to allow skys and cameras to coexist) { cl_entity_t *viewentity; viewentity = gEngfuncs.GetEntityByIndex( gHUD.viewEntityIndex ); if (viewentity) { pparams->viewangles[0] = viewentity->angles[0]; pparams->viewangles[1] = viewentity->angles[1]; pparams->viewangles[2] = viewentity->angles[2]; } else gEngfuncs.Con_Printf( "Warning : invalid view ent index: %i\n", gHUD.viewEntityIndex ); } pparams->nextView = 1; } }
/* ================== V_CalcRefdef ================== */ void V_CalcRefdef (void) { vec3_t forward; float height_adjustment; height_adjustment = v_viewheight.value ? bound (-7, v_viewheight.value, 4) : V_CalcBob (); // set up the refresh position VectorCopy (cl.simorg, r_refdef2.vieworg); // never let it sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis r_refdef2.vieworg[0] += 1.0/16; r_refdef2.vieworg[1] += 1.0/16; r_refdef2.vieworg[2] += 1.0/16; // add view height if (view_message.flags & PF_GIB) r_refdef2.vieworg[2] += 8; // gib view height else if (view_message.flags & PF_DEAD) r_refdef2.vieworg[2] -= 16; // corpse view height else { r_refdef2.vieworg[2] += cl.viewheight; // normal view height r_refdef2.vieworg[2] += height_adjustment; // smooth out stair step ups r_refdef2.vieworg[2] += cl.crouch; } if (cl.landtime) { const float tt = 350; const float lt = 90; const float lh = 6; float _landtime = 350 - (cl.time - cl.landtime) * 1000; if (_landtime <= 0) cl.landtime = 0; else { if (_landtime >= (tt - lt)) r_refdef2.vieworg[2] -= ((tt - _landtime) / lt) * lh; else r_refdef2.vieworg[2] -= _landtime / (tt - lt) * lh; } } // set up refresh view angles VectorCopy (cl.simangles, r_refdef2.viewangles); V_CalcViewRoll (); V_AddIdle (); if (v_kickback.value) { if (cls.nqprotocol) r_refdef2.viewangles[PITCH] += cl.punchangle; else { // add weapon kick offset AngleVectors (r_refdef2.viewangles, forward, NULL, NULL); VectorMA (r_refdef2.vieworg, cl.punchangle, forward, r_refdef2.vieworg); // add weapon kick angle r_refdef2.viewangles[PITCH] += cl.punchangle * 0.5; } } if (view_message.flags & PF_DEAD) // PF_GIB will also set PF_DEAD r_refdef2.viewangles[ROLL] = 80; // dead view angle V_AddViewWeapon (height_adjustment); }
static void V_CalcRefdef (void) { // view is the weapon model (visible only from inside body) entity_t *view = &cl.viewent; float bob; static float oldz = 0; int i; vec3_t forward, right, up; vec_t *origin = cl.simorg; vec_t *viewangles = cl.simangles; V_DriftPitch (); bob = V_CalcBob (); // refresh position VectorCopy (origin, r_data->refdef->vieworg); r_data->refdef->vieworg[2] += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis r_data->refdef->vieworg[0] += 1.0 / 16; r_data->refdef->vieworg[1] += 1.0 / 16; r_data->refdef->vieworg[2] += 1.0 / 16; VectorCopy (viewangles, r_data->refdef->viewangles); V_CalcViewRoll (); V_AddIdle (); // offsets AngleVectors (viewangles, forward, right, up); // don't allow cheats in multiplayer // FIXME check for dead if (cl.maxclients == 1) { for (i = 0; i < 3; i++) { r_data->refdef->vieworg[i] += scr_ofsx->value * forward[i] + scr_ofsy->value * right[i] + scr_ofsz->value * up[i]; } } V_BoundOffsets (); // set up gun position VectorCopy (viewangles, view->angles); CalcGunAngle (); VectorCopy (origin, view->origin); view->origin[2] += cl.viewheight; for (i = 0; i < 3; i++) { view->origin[i] += forward[i] * bob * 0.4; // view->origin[i] += right[i] * bob * 0.4; // view->origin[i] += up[i] * bob * 0.8; } view->origin[2] += bob; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) ; else if (r_data->scr_viewsize->int_val == 110) view->origin[2] += 1; else if (r_data->scr_viewsize->int_val == 100) view->origin[2] += 2; else if (r_data->scr_viewsize->int_val == 90) view->origin[2] += 1; else if (r_data->scr_viewsize->int_val == 80) view->origin[2] += 0.5; if (view_message->pls.flags & (PF_GIB | PF_DEAD)) view->model = NULL; else view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->frame = view_message->pls.weaponframe; view->skin = 0; // set up the refresh position VectorAdd (r_data->refdef->viewangles, cl.punchangle, r_data->refdef->viewangles); // smooth out stair step ups if ((cl.onground != -1) && (origin[2] - oldz > 0)) { float steptime; steptime = host_frametime; oldz += steptime * 80; if (oldz > origin[2]) oldz = origin[2]; if (origin[2] - oldz > 12) oldz = origin[2] - 12; r_data->refdef->vieworg[2] += oldz - origin[2]; view->origin[2] += oldz - origin[2]; } else oldz = origin[2]; if (cl.chase && chase_active->int_val) Chase_Update (); CL_TransformEntity (view, view->angles, true); }
/* ================== V_CalcRefdef ================== */ void V_CalcNormalRefdef ( ref_params_t *pparams ) { cl_entity_t *ent, *view; int i; Vector angles; float bob, waterOffset; static viewinterp_t ViewInterp; static float oldz = 0; static float lasttime; Vector camAngles, camForward, camRight, camUp; cl_entity_t *pwater; V_DriftPitch ( pparams ); if ( gEngfuncs.IsSpectateOnly() ) { ent = gEngfuncs.GetEntityByIndex( g_iUser2 ); } else { // ent is the player model ( visible when out of body ) ent = gEngfuncs.GetLocalPlayer(); } // view is the weapon model (only visible from inside body ) view = gEngfuncs.GetViewModel(); // transform the view offset by the model's matrix to get the offset from // model origin for the view bob = V_CalcBob ( pparams ); // refresh position pparams->vieworg = pparams->simorg; pparams->vieworg[2] += ( bob ); pparams->vieworg = pparams->vieworg + pparams->viewheight; pparams->viewangles = pparams->cl_viewangles; gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0 ); // never let view origin sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // FIXME, we send origin at 1/128 now, change this? // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis pparams->vieworg[0] += 1.0/32; pparams->vieworg[1] += 1.0/32; pparams->vieworg[2] += 1.0/32; // Check for problems around water, move the viewer artificially if necessary // -- this prevents drawing errors in GL due to waves waterOffset = 0; if ( pparams->waterlevel >= WATERLEVEL_WAIST ) { int i, contents, waterDist, waterEntity; Vector point; waterDist = cl_waterdist->value; if ( pparams->hardware ) { waterEntity = gEngfuncs.PM_WaterEntity( pparams->simorg ); if ( waterEntity >= 0 && waterEntity < pparams->max_entities ) { pwater = gEngfuncs.GetEntityByIndex( waterEntity ); if ( pwater && ( pwater->model != NULL ) ) { waterDist += ( pwater->curstate.scale * 16 ); // Add in wave height } } } else { waterEntity = 0; // Don't need this in software } point = pparams->vieworg; // Eyes are above water, make sure we're above the waves if ( pparams->waterlevel == WATERLEVEL_WAIST ) { point[2] -= waterDist; for ( i = 0; i < waterDist; i++ ) { contents = gEngfuncs.PM_PointContents( point, NULL ); if ( contents > CONTENTS_WATER ) break; point[2] += 1; } waterOffset = (point[2] + waterDist) - pparams->vieworg[2]; } else { // eyes are under water. Make sure we're far enough under point[2] += waterDist; for ( i = 0; i < waterDist; i++ ) { contents = gEngfuncs.PM_PointContents( point, NULL ); if ( contents <= CONTENTS_WATER ) break; point[2] -= 1; } waterOffset = (point[2] - waterDist) - pparams->vieworg[2]; } } pparams->vieworg[2] += waterOffset; V_CalcViewRoll ( pparams ); V_AddIdle ( pparams ); // offsets angles = pparams->cl_viewangles; AngleVectors ( angles, pparams->forward, pparams->right, pparams->up ); // don't allow cheats in multiplayer if ( pparams->maxclients <= 1 ) { for ( i=0 ; i<3 ; i++ ) { pparams->vieworg[i] += scr_ofsx->value*pparams->forward[i] + scr_ofsy->value*pparams->right[i] + scr_ofsz->value*pparams->up[i]; } } // Treating cam_ofs[2] as the distance if( CL_IsThirdPerson() ) { Vector ofs; ofs[0] = ofs[1] = ofs[2] = 0.0; CL_CameraOffset( ofs ); camAngles = ofs; camAngles[ ROLL ] = 0; AngleVectors( camAngles, camForward, camRight, camUp ); for ( i = 0; i < 3; i++ ) { pparams->vieworg[ i ] += -ofs[2] * camForward[ i ]; } } // Give gun our viewangles view->angles = pparams->cl_viewangles; // set up gun position V_CalcGunAngle ( pparams ); // Use predicted origin as view origin. view->origin = pparams->simorg; view->origin[2] += ( waterOffset ); view->origin = view->origin + pparams->viewheight; // Let the viewmodel shake at about 10% of the amplitude gEngfuncs.V_ApplyShake( view->origin, view->angles, 0.9 ); 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; // 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; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if (pparams->viewsize == 110) { view->origin[2] += 1; } else if (pparams->viewsize == 100) { view->origin[2] += 2; } else if (pparams->viewsize == 90) { view->origin[2] += 1; } else if (pparams->viewsize == 80) { view->origin[2] += 0.5; } // Add in the punchangle, if any pparams->viewangles = pparams->viewangles + pparams->punchangle; // Include client side punch, too pparams->viewangles = pparams->viewangles + ev_punchangle; V_DropPunchAngle ( pparams->frametime, ev_punchangle ); // smooth out stair step ups #if 1 if ( !pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0) { float steptime; steptime = pparams->time - lasttime; if (steptime < 0) //FIXME I_Error ("steptime < 0"); steptime = 0; oldz += steptime * 150; if (oldz > pparams->simorg[2]) oldz = pparams->simorg[2]; if (pparams->simorg[2] - oldz > 18) oldz = pparams->simorg[2]- 18; pparams->vieworg[2] += oldz - pparams->simorg[2]; view->origin[2] += oldz - pparams->simorg[2]; } else { oldz = pparams->simorg[2]; } #endif { static Vector lastorg; const Vector delta = pparams->simorg - lastorg; if ( delta.Length() != 0.0 ) { ViewInterp.Origins[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->simorg; ViewInterp.OriginTime[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->time; ViewInterp.CurrentOrigin++; lastorg = pparams->simorg; } } // Smooth out whole view in multiplayer when on trains, lifts if ( cl_vsmoothing && cl_vsmoothing->value && ( pparams->smoothing && ( pparams->maxclients > 1 ) ) ) { int foundidx; int i; float t; if ( cl_vsmoothing->value < 0.0 ) { gEngfuncs.Cvar_SetValue( "cl_vsmoothing", 0.0 ); } 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 Vector delta; double frac; double dt; Vector 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 ); delta = ViewInterp.Origins[ ( foundidx + 1 ) & ORIGIN_MASK ] - ViewInterp.Origins[ foundidx & ORIGIN_MASK ]; VectorMA( ViewInterp.Origins[ foundidx & ORIGIN_MASK ], frac, delta, neworg ); // Dont interpolate large changes if ( delta.Length() < 64 ) { delta = neworg - pparams->simorg; pparams->simorg = pparams->simorg + delta; pparams->vieworg = pparams->vieworg + delta; view->origin = view->origin + delta; } } } } // Store off v_angles before munging for third person v_angles = pparams->viewangles; v_client_aimangles = pparams->cl_viewangles; v_lastAngles = pparams->viewangles; // v_cl_angles = pparams->cl_viewangles; // keep old user mouse angles ! if ( CL_IsThirdPerson() ) { pparams->viewangles = camAngles; float pitch = camAngles[ 0 ]; // Normalize angles if ( pitch > 180 ) pitch -= 360.0; else if ( pitch < -180 ) pitch += 360; // Player pitch is inverted pitch /= -3.0; // Slam local player's pitch value ent->angles[ 0 ] = pitch; ent->curstate.angles[ 0 ] = pitch; ent->prevstate.angles[ 0 ] = pitch; ent->latched.prevangles[ 0 ] = pitch; } // override all previous settings if the viewent isn't the client if ( pparams->viewentity > pparams->maxclients ) { cl_entity_t *viewentity; viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity ); if ( viewentity ) { pparams->vieworg = viewentity->origin; pparams->viewangles = viewentity->angles; // Store off overridden viewangles v_angles = pparams->viewangles; } } lasttime = pparams->time; v_origin = pparams->vieworg; }
/* ================== V_CalcRefdef ================== */ void V_CalcRefdef (void) { entity_t *ent, *view; int i; vec3_t forward, right, up; vec3_t angles; float bob; static float oldz = 0; static vec3_t punch = {0,0,0}; //johnfitz -- v_gunkick float delta; //johnfitz -- v_gunkick V_DriftPitch (); // ent is the player model (visible when out of body) ent = &cl_entities[cl.viewentity]; // view is the weapon model (only visible from inside body) view = &cl.viewent; // transform the view offset by the model's matrix to get the offset from // model origin for the view ent->angles[YAW] = cl.viewangles[YAW]; // the model should face the view dir ent->angles[PITCH] = -cl.viewangles[PITCH]; // the model should face the view dir bob = V_CalcBob (); // refresh position VectorCopy (ent->origin, r_refdef.vieworg); r_refdef.vieworg[2] += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis r_refdef.vieworg[0] += 1.0/32; r_refdef.vieworg[1] += 1.0/32; r_refdef.vieworg[2] += 1.0/32; VectorCopy (cl.viewangles, r_refdef.viewangles); V_CalcViewRoll (); V_AddIdle (); // offsets angles[PITCH] = -ent->angles[PITCH]; // because entity pitches are actually backward angles[YAW] = ent->angles[YAW]; angles[ROLL] = ent->angles[ROLL]; AngleVectors (angles, forward, right, up); if (cl.maxclients <= 1) //johnfitz -- moved cheat-protection here from V_RenderView for (i=0 ; i<3 ; i++) r_refdef.vieworg[i] += scr_ofsx.value*forward[i] + scr_ofsy.value*right[i] + scr_ofsz.value*up[i]; V_BoundOffsets (); // set up gun position VectorCopy (cl.viewangles, view->angles); CalcGunAngle (); VectorCopy (ent->origin, view->origin); view->origin[2] += cl.viewheight; for (i=0 ; i<3 ; i++) view->origin[i] += forward[i]*bob*0.4; view->origin[2] += bob; //johnfitz -- removed all gun position fudging code (was used to keep gun from getting covered by sbar) //MarkV -- restored this with r_viewmodel_quake cvar if (r_viewmodel_quake.value) { if (scr_viewsize.value == 110) view->origin[2] += 1; else if (scr_viewsize.value == 100) view->origin[2] += 2; else if (scr_viewsize.value == 90) view->origin[2] += 1; else if (scr_viewsize.value == 80) view->origin[2] += 0.5; } view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->frame = cl.stats[STAT_WEAPONFRAME]; view->colormap = vid.colormap; //johnfitz -- v_gunkick if (v_gunkick.value == 1) //original quake kick VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); if (v_gunkick.value == 2) //lerped kick { for (i=0; i<3; i++) if (punch[i] != v_punchangles[0][i]) { //speed determined by how far we need to lerp in 1/10th of a second delta = (v_punchangles[0][i]-v_punchangles[1][i]) * host_frametime * 10; if (delta > 0) punch[i] = q_min(punch[i]+delta, v_punchangles[0][i]); else if (delta < 0) punch[i] = q_max(punch[i]+delta, v_punchangles[0][i]); } VectorAdd (r_refdef.viewangles, punch, r_refdef.viewangles); } //johnfitz // smooth out stair step ups if (!noclip_anglehack && cl.onground && ent->origin[2] - oldz > 0) //johnfitz -- added exception for noclip //FIXME: noclip_anglehack is set on the server, so in a nonlocal game this won't work. { float steptime; steptime = cl.time - cl.oldtime; if (steptime < 0) //FIXME I_Error ("steptime < 0"); steptime = 0; oldz += steptime * 80; if (oldz > ent->origin[2]) oldz = ent->origin[2]; if (ent->origin[2] - oldz > 12) oldz = ent->origin[2] - 12; r_refdef.vieworg[2] += oldz - ent->origin[2]; view->origin[2] += oldz - ent->origin[2]; } else oldz = ent->origin[2]; if (chase_active.value) Chase_UpdateForDrawing (); //johnfitz }