vec3_t CTriMenu::MakePointOrtho( vec2_t vOrg ) { vec3_t vForward, vRight, vUp, vTotalOrg, vFRight, vFUp; if(CL_IsThirdPerson()) { extern vec3_t g_vecCamAngles; AngleVectors( g_vecCamAngles, vForward, vRight, vUp ); } // Use first person angles else { AngleVectors( g_vPlayerAngles , vForward, vRight, vUp ); } vTotalOrg = g_vViewOrg + vForward*5; float flTmp[3] = {1, 1, 0}; flTmp[0] = ( 2* vOrg.x ) - 1; flTmp[1] = ( 2 *vOrg.y) - 1; /*vFRight = */gEngfuncs.pTriAPI->ScreenToWorld( flTmp, vFRight ); // software mode fallback casue screentoworld doesnt work there if( !IEngineStudio.IsHardware( ) ) { vFRight = vRight+(vRight*( 6.5* vOrg.x - 3.75 )/.5 ); vFUp = vUp+(vUp*( 4.9*vOrg.y - 2.95 )/.5); vFRight = vFRight + vTotalOrg + vFUp + ( vForward * 1.5 ); } // add forward so it doesnt clip the view return vFRight;//vTotalOrg + vFRight + vFUp + ( vForward * 1.5 ); }
void DLLEXPORT V_CalcRefdef( struct ref_params_s *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 ( CL_IsThirdPerson() ) { V_CalcThirdPersonRefdef ( pparams ); } else { V_CalcNormalRefdef ( pparams ); } }
/* ================== 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_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; }