Exemplo n.º 1
0
/*
==================
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;
}
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;
	}
}
Exemplo n.º 3
0
//==========================
// 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 );
}
Exemplo n.º 4
0
/*
==================
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;
}