Exemplo n.º 1
0
//
// CL_PredictPlayers
//
void CL_PredictPlayer (player_t *p)
{
	if (p->playerstate == PST_DEAD)
	{
		P_DeathThink (p);
		p->mo->RunThink();
		P_CalcHeight(p);
	}
	else
	{
		P_MovePlayer(p);
		P_CalcHeight(p);
		p->mo->RunThink();
	}
}
Exemplo n.º 2
0
//
// CL_PredictSpying
//
// Handles calling the thinker routines for the player being spied with spynext.
//
static void CL_PredictSpying()
{
	player_t *player = &displayplayer();
	if (consoleplayer_id == displayplayer_id)
		return;

	predicting = false;
	
	P_PlayerThink(player);
	P_CalcHeight(player);
}
Exemplo n.º 3
0
//
// CL_PredictSpectator
//
//
static void CL_PredictSpectator()
{
	player_t *player = &consoleplayer();
	if (!player->spectator)
		return;
		
	predicting = true;
	
	P_PlayerThink(player);
	P_CalcHeight(player);
	
	predicting = false;
}
Exemplo n.º 4
0
//
// CL_PredicMove
//
void CL_PredictMove (void)
{
	if (noservermsgs)
		return;

	player_t *p = &consoleplayer();

	if (!p->tic || !p->mo)
		return;

	// Save player angle, viewheight,deltaviewheight and jumpTics.
	// Will use it later to predict movements
	cl_angle[gametic%MAXSAVETICS] = p->mo->angle;
	cl_pitch[gametic%MAXSAVETICS] = p->mo->pitch;
	cl_viewheight[gametic%MAXSAVETICS] = p->viewheight;
	cl_deltaviewheight[gametic%MAXSAVETICS] = p->deltaviewheight;
	cl_jumpTics[gametic%MAXSAVETICS] = p->jumpTics;
	reactiontime[gametic%MAXSAVETICS] = p->mo->reactiontime;

	// Disable sounds, etc, during prediction
	predicting = true;

	// Set predictable items to their last received positions
	CL_ResetPlayers();
	CL_ResetSectors();

	int predtic = gametic - MAXSAVETICS;

	if(predtic < 0)
		predtic = 0;

	// Predict each tic
	while(++predtic < gametic)
	{
		CL_PredictPlayers(predtic);
		CL_PredictSectors(predtic);
	}

	predicting = false;

	CL_PredictPlayers(predtic);
	CL_PredictSectors(predtic);

	P_PlayerThink (p);
	P_CalcHeight(p);
}
Exemplo n.º 5
0
void P_Ticker (void)
{
  int i;

  // pause if in menu and at least one tic has been run
  //
  // killough 9/29/98: note that this ties in with basetic,
  // since G_Ticker does the pausing during recording or
  // playback, and compensates by incrementing basetic.
  // 
  // All of this complicated mess is used to preserve demo sync.

  if (paused || (menuactive && !demoplayback && !netgame &&
		 players[consoleplayer].viewz != 1))
    return;

               // not if this is an intermission screen
  if(gamestate==GS_LEVEL)
    for (i=0; i<MAXPLAYERS; i++)
      if (playeringame[i])
	{
	  players[i].predicted = NULL; // sf: nothing predicted yet
	  P_PlayerThink(&players[i]);
	}
  
  reset_viewz = false;  // sf

  P_RunThinkers();
  P_UpdateSpecials();
  P_RespawnSpecials();
  leveltime++;                       // for par times

  // sf: on original doom, sometimes if you activated a hyperlift
  // while standing on it, your viewz was left behind and appeared
  // to "jump". code in p_floor.c detects if a hyperlift has been
  // activated and viewz is reset appropriately here.

  if(reset_viewz && gamestate == GS_LEVEL)
      P_CalcHeight (&players[displayplayer]); // Determines view height and bobbing

  T_DelayedScripts();
}
Exemplo n.º 6
0
// [RH] Modified to support different source and destination ids.
// [RH] Modified some more to be accurate.
bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBOOL reverse)
{
	int i;
	line_t *l;

	if (side || thing->flags2 & MF2_NOTELEPORT || !line || line->sidedef[1] == NULL)
		return false;

	FLineIdIterator itr(id);
	while ((i = itr.Next()) >= 0)
	{
		if (line->Index() == i)
			continue;

		if ((l=&level.lines[i]) != line && l->backsector)
		{
			// Get the thing's position along the source linedef
			double pos;
			DVector2 npos;			// offsets from line
			double den;

			den = line->Delta().LengthSquared();
			if (den == 0)
			{
				pos = 0;
				npos.Zero();
			}
			else
			{
				double num = (thing->Pos().XY() - line->v1->fPos()) | line->Delta();
				if (num <= 0)
				{
					pos = 0;
				}
				else if (num >= den)
				{
					pos = 1;
				}
				else
				{
					pos = num / den;
				}
				npos = thing->Pos().XY() - line->v1->fPos() - line->Delta() * pos;
			}

			// Get the angle between the two linedefs, for rotating
			// orientation and velocity. Rotate 180 degrees, and flip
			// the position across the exit linedef, if reversed.
			DAngle angle = l->Delta().Angle() - line->Delta().Angle();

			if (!reverse)
			{
				angle += 180.;
				pos = 1 - pos;
			}

			// Sine, cosine of angle adjustment
			double s = angle.Sin();
			double c = angle.Cos();

			DVector2 p;

			// Rotate position along normal to match exit linedef
			p.X = npos.X*c - npos.Y*s;
			p.Y = npos.Y*c + npos.X*s;

			// Interpolate position across the exit linedef
			p += l->v1->fPos() + pos*l->Delta();

			// Whether this is a player, and if so, a pointer to its player_t.
			// Voodoo dolls are excluded by making sure thing->player->mo==thing.
			player_t *player = thing->player && thing->player->mo == thing ?
				thing->player : NULL;

			// Whether walking towards first side of exit linedef steps down
			bool stepdown = l->frontsector->floorplane.ZatPoint(p) < l->backsector->floorplane.ZatPoint(p);

			// Height of thing above ground
			double z = thing->Z() - thing->floorz;

			// Side to exit the linedef on positionally.
			//
			// Notes:
			//
			// This flag concerns exit position, not momentum. Due to
			// roundoff error, the thing can land on either the left or
			// the right side of the exit linedef, and steps must be
			// taken to make sure it does not end up on the wrong side.
			//
			// Exit momentum is always towards side 1 in a reversed
			// teleporter, and always towards side 0 otherwise.
			//
			// Exiting positionally on side 1 is always safe, as far
			// as avoiding oscillations and stuck-in-wall problems,
			// but may not be optimum for non-reversed teleporters.
			//
			// Exiting on side 0 can cause oscillations if momentum
			// is towards side 1, as it is with reversed teleporters.
			//
			// Exiting on side 1 slightly improves player viewing
			// when going down a step on a non-reversed teleporter.

			// Is this really still necessary with real math instead of imprecise trig tables?
#if 1
			int side = reverse || (player && stepdown);
			int fudge = FUDGEFACTOR;

			double dx = line->Delta().X;
			double dy = line->Delta().Y;
			// Make sure we are on correct side of exit linedef.
			while (P_PointOnLineSidePrecise(p, l) != side && --fudge >= 0)
			{
				if (fabs(dx) > fabs(dy))
					p.Y -= (dx < 0) != side ? -1 : 1;
				else
					p.X += (dy < 0) != side ? -1 : 1;
			}
#endif

			// Adjust z position to be same height above ground as before.
			// Ground level at the exit is measured as the higher of the
			// two floor heights at the exit linedef.
			z = z + l->sidedef[stepdown]->sector->floorplane.ZatPoint(p);

			// Attempt to teleport, aborting if blocked
			if (!P_TeleportMove (thing, DVector3(p, z), false))
			{
				return false;
			}

			if (thing == players[consoleplayer].camera)
			{
				R_ResetViewInterpolation ();
			}

			// Rotate thing's orientation according to difference in linedef angles
			thing->Angles.Yaw += angle;

			// Rotate thing's velocity to come out of exit just like it entered
			p = thing->Vel.XY();
			thing->Vel.X = p.X*c - p.Y*s;
			thing->Vel.Y = p.Y*c + p.X*s;

			// Adjust a player's view, in case there has been a height change
			if (player && player->mo == thing)
			{
				// Adjust player's local copy of velocity
				p = player->Vel;
				player->Vel.X = p.X*c - p.Y*s;
				player->Vel.Y = p.Y*c + p.X*s;

				// Save the current deltaviewheight, used in stepping
				double deltaviewheight = player->deltaviewheight;

				// Clear deltaviewheight, since we don't want any changes now
				player->deltaviewheight = 0;

				// Set player's view according to the newly set parameters
				P_CalcHeight(player);

				// Reset the delta to have the same dynamics as before
				player->deltaviewheight = deltaviewheight;
			}

			return true;
		}
	}
	return false;
}
Exemplo n.º 7
0
void Stereo3D::render(FGLRenderer& renderer, GL_IRECT * bounds, float fov0, float ratio0, float fovratio0, bool toscreen, sector_t * viewsector, player_t * player) 
{
	if (doBufferHud)
		LocalHudRenderer::unbind();

	// Reset pitch and roll when leaving Rift mode
	if ( (mode == OCULUS_RIFT) && ((int)mode != vr_mode) ) {
		renderer.mAngles.Roll = 0;
		renderer.mAngles.Pitch = 0;
	}
	setMode(vr_mode);

	// Restore actual screen, instead of offscreen single-eye buffer,
	// in case we just exited Rift mode.
	adaptScreenSize = false;

	GLboolean supportsStereo = false;
	GLboolean supportsBuffered = false;
	// Task: manually calibrate oculusFov by slowly yawing view. 
	// If subjects approach center of view too fast, oculusFov is too small.
	// If subjects approach center of view too slowly, oculusFov is too large.
	// If subjects approach correctly , oculusFov is just right.
	// 90 is too large, 80 is too small.
	// float oculusFov = 85 * fovratio; // Hard code probably wider fov for oculus // use vr_rift_fov

	if (mode == OCULUS_RIFT) {
	// if (false) {
		renderer.mCurrentFoV = vr_rift_fov; // needed for Frustum angle calculation
		// Adjust player eye height, but only in oculus rift mode...
		if (player != NULL) { // null check to avoid aliens crash
			if (savedPlayerViewHeight == 0) {
				savedPlayerViewHeight = player->mo->ViewHeight;
			}
			fixed_t testHeight = savedPlayerViewHeight + FLOAT2FIXED(vr_view_yoffset);
			if (player->mo->ViewHeight != testHeight) {
				player->mo->ViewHeight = testHeight;
				P_CalcHeight(player);
			}
		}
	} else {
		// Revert player eye height when leaving Rift mode
		if ( (savedPlayerViewHeight != 0) && (player->mo->ViewHeight != savedPlayerViewHeight) ) {
			player->mo->ViewHeight = savedPlayerViewHeight;
			savedPlayerViewHeight = 0;
			P_CalcHeight(player);
		}
	}

	angle_t a1 = renderer.FrustumAngle();

	switch(mode) 
	{

	case MONO:
		setViewportFull(renderer, bounds);
		setMonoView(renderer, fov0, ratio0, fovratio0, player);
		renderer.RenderOneEye(a1, toscreen, true);
		renderer.EndDrawScene(viewsector);
		break;

	case GREEN_MAGENTA:
		setViewportFull(renderer, bounds);
		{ // Local scope for color mask
			// Left eye green
			LocalScopeGLColorMask colorMask(0,1,0,1); // green
			setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}

			// Right eye magenta
			colorMask.setColorMask(1,0,1,1); // magenta
			setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
		} // close scope to auto-revert glColorMask
		renderer.EndDrawScene(viewsector);
		break;

	case RED_CYAN:
		setViewportFull(renderer, bounds);
		{ // Local scope for color mask
			// Left eye red
			LocalScopeGLColorMask colorMask(1,0,0,1); // red
			setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}

			// Right eye cyan
			colorMask.setColorMask(0,1,1,1); // cyan
			setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
		} // close scope to auto-revert glColorMask
		renderer.EndDrawScene(viewsector);
		break;

	case SIDE_BY_SIDE:
		{
			// FIRST PASS - 3D
			// Temporarily modify global variables, so HUD could draw correctly
			// each view is half width
			int oldViewwidth = viewwidth;
			viewwidth = viewwidth/2;
			// left
			setViewportLeft(renderer, bounds);
			setLeftEyeView(renderer, fov0, ratio0/2, fovratio0, player); // TODO is that fovratio?
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, false, false); // False, to not swap yet
			}
			// right
			// right view is offset to right
			int oldViewwindowx = viewwindowx;
			viewwindowx += viewwidth;
			setViewportRight(renderer, bounds);
			setRightEyeView(renderer, fov0, ratio0/2, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
			//
			// SECOND PASS weapon sprite
			renderer.EndDrawScene(viewsector); // right view
			viewwindowx -= viewwidth;
			renderer.EndDrawScene(viewsector); // left view
			//
			// restore global state
			viewwidth = oldViewwidth;
			viewwindowx = oldViewwindowx;
			break;
		}

	case SIDE_BY_SIDE_SQUISHED:
		{
			// FIRST PASS - 3D
			// Temporarily modify global variables, so HUD could draw correctly
			// each view is half width
			int oldViewwidth = viewwidth;
			viewwidth = viewwidth/2;
			// left
			setViewportLeft(renderer, bounds);
			setLeftEyeView(renderer, fov0, ratio0, fovratio0*2, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}
			// right
			// right view is offset to right
			int oldViewwindowx = viewwindowx;
			viewwindowx += viewwidth;
			setViewportRight(renderer, bounds);
			setRightEyeView(renderer, fov0, ratio0, fovratio0*2, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, false, true);
			}
			//
			// SECOND PASS weapon sprite
			renderer.EndDrawScene(viewsector); // right view
			viewwindowx -= viewwidth;
			renderer.EndDrawScene(viewsector); // left view
			//
			// restore global state
			viewwidth = oldViewwidth;
			viewwindowx = oldViewwindowx;
			break;
		}

	case OCULUS_RIFT:
		{
			if ( (oculusTexture == NULL) || (! oculusTexture->checkSize(SCREENWIDTH, SCREENHEIGHT)) ) {
				if (oculusTexture)
					delete(oculusTexture);
				oculusTexture = new OculusTexture(SCREENWIDTH, SCREENHEIGHT);
			}
			if ( (hudTexture == NULL) || (! hudTexture->checkSize(SCREENWIDTH/2, SCREENHEIGHT)) ) {
				if (hudTexture)
					delete(hudTexture);
				hudTexture = new HudTexture(SCREENWIDTH/2, SCREENHEIGHT);
				hudTexture->bindToFrameBuffer();
				glClearColor(0, 0, 0, 0);
				glClear(GL_COLOR_BUFFER_BIT);
				hudTexture->unbind();
			}
			// Render unwarped image to offscreen frame buffer
			if (doBufferOculus) {
				oculusTexture->bindToFrameBuffer();
			}
			// FIRST PASS - 3D
			// Temporarily modify global variables, so HUD could draw correctly
			// each view is half width
			int oldViewwidth = viewwidth;
			viewwidth = viewwidth/2;
			int oldScreenBlocks = screenblocks;
			screenblocks = 12; // full screen
			//
			// TODO correct geometry for oculus
			//
			float ratio = vr_rift_aspect;
			float fovy = 2.0*atan(tan(0.5*vr_rift_fov*3.14159/180.0)/ratio) * 180.0/3.14159;
			float fovratio = vr_rift_fov/fovy;
			//
			// left
			GL_IRECT riftBounds; // Always use full screen with Oculus Rift
			riftBounds.width = SCREENWIDTH;
			riftBounds.height = SCREENHEIGHT;
			riftBounds.left = 0;
			riftBounds.top = 0;
			setViewportLeft(renderer, &riftBounds);
			setLeftEyeView(renderer, vr_rift_fov, ratio, fovratio, player, false);
			glEnable(GL_DEPTH_TEST);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, false, false);
			}
			// right
			// right view is offset to right
			int oldViewwindowx = viewwindowx;
			viewwindowx += viewwidth;
			setViewportRight(renderer, &riftBounds);
			setRightEyeView(renderer, vr_rift_fov, ratio, fovratio, player, false);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, false, true);
			}

			// Second pass sprites (especially weapon)
			int oldViewwindowy = viewwindowy;
			const bool showSprites = true;
			if (showSprites) {
				// SECOND PASS weapon sprite
				glEnable(GL_TEXTURE_2D);
				screenblocks = 12;
				float fullWidth = SCREENWIDTH / 2.0;
				viewwidth = RIFT_HUDSCALE * fullWidth;
				float left = (1.0 - RIFT_HUDSCALE) * fullWidth * 0.5; // left edge of scaled viewport
				// TODO Sprite needs some offset to appear at correct distance, rather than at infinity.
				int spriteOffsetX = (int)(0.021*fullWidth); // kludge to set weapon distance
				viewwindowx = left + fullWidth - spriteOffsetX;
				int spriteOffsetY = (int)(-0.01 * vr_weapon_height * viewheight); // nudge gun up/down
				// Counteract effect of status bar on weapon position
				if (oldScreenBlocks <= 10) { // lower weapon in status mode
					spriteOffsetY += 0.227 * viewwidth; // empirical - lines up brutal doom down sight in 1920x1080 Rift mode
				}
				viewwindowy += spriteOffsetY;
				renderer.EndDrawScene(viewsector); // right view
				setViewportLeft(renderer, &riftBounds);
				viewwindowx = left + spriteOffsetX;
				renderer.EndDrawScene(viewsector); // left view
			}

			// Third pass HUD
			if (doBufferHud) {
				screenblocks = max(oldScreenBlocks, 10); // Don't vignette main 3D view
				// Draw HUD again, to avoid flashing? - and render to screen
				blitHudTextureToScreen(true); // HUD pass now occurs in main doom loop! Since I delegated screen->Update to stereo3d.updateScreen().
			}

			//
			// restore global state
			viewwidth = oldViewwidth;
			viewwindowx = oldViewwindowx;
			viewwindowy = oldViewwindowy;
			// Update orientation for NEXT frame, after expensive render has occurred this frame
			setViewDirection(renderer);
			// Set up 2D rendering to write to our hud renderbuffer
			if (doBufferHud) {
				bindHudTexture(true);
				glClearColor(0, 0, 0, 0);
				glClear(GL_COLOR_BUFFER_BIT);
				bindHudTexture(false);
				LocalHudRenderer::bind();
			}
			break;
		}

	case LEFT_EYE_VIEW:
		setViewportFull(renderer, bounds);
		setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
		{
			ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
			renderer.RenderOneEye(a1, toscreen, true);
		}
		renderer.EndDrawScene(viewsector);
		break;

	case RIGHT_EYE_VIEW:
		setViewportFull(renderer, bounds);
		setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
		{
			ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
			renderer.RenderOneEye(a1, toscreen, true);
		}
		renderer.EndDrawScene(viewsector);
		break;

	case QUAD_BUFFERED:
		setViewportFull(renderer, bounds);
		glGetBooleanv(GL_STEREO, &supportsStereo);
		glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
		if (supportsStereo && supportsBuffered && toscreen)
		{ 
			// Right first this time, so more generic GL_BACK_LEFT will remain for other modes
			glDrawBuffer(GL_BACK_RIGHT);
			setRightEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_RIGHT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, false);
			}
			// Left
			glDrawBuffer(GL_BACK_LEFT);
			setLeftEyeView(renderer, fov0, ratio0, fovratio0, player);
			{
				ViewShifter vs(EYE_VIEW_LEFT, player, renderer);
				renderer.RenderOneEye(a1, toscreen, true);
			}
			// Want HUD in both views
			glDrawBuffer(GL_BACK);
		} else { // mono view, in case hardware stereo is not supported
			setMonoView(renderer, fov0, ratio0, fovratio0, player);
			renderer.RenderOneEye(a1, toscreen, true);			
		}
		renderer.EndDrawScene(viewsector);
		break;

	default:
		setViewportFull(renderer, bounds);
		setMonoView(renderer, fov0, ratio0, fovratio0, player);
		renderer.RenderOneEye(a1, toscreen, true);			
		renderer.EndDrawScene(viewsector);
		break;

	}
}