- handle display of player sprite during portal transition properly.

This checks if the current viewpoint lies on the interpolation path, translated by all active portals.
This commit is contained in:
Christoph Oelckers 2016-04-07 19:35:01 +02:00
parent 47e20aead4
commit 0cbdb9ab72
3 changed files with 83 additions and 48 deletions

View file

@ -692,6 +692,8 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
fixed_t startx = viewx; fixed_t startx = viewx;
fixed_t starty = viewy; fixed_t starty = viewy;
fixed_t startz = viewz; fixed_t startz = viewz;
DVector3 savedpath[2] = { ViewPath[0], ViewPath[1] };
int savedvisibility = camera->renderflags & RF_INVISIBLE;
CurrentPortalUniq++; CurrentPortalUniq++;
@ -738,10 +740,27 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
P_TranslatePortalXY(pds->src, view.X, view.Y); P_TranslatePortalXY(pds->src, view.X, view.Y);
P_TranslatePortalZ(pds->src, view.Z); P_TranslatePortalZ(pds->src, view.Z);
P_TranslatePortalAngle(pds->src, va); P_TranslatePortalAngle(pds->src, va);
P_TranslatePortalXY(pds->src, ViewPath[0].X, ViewPath[0].Y);
P_TranslatePortalXY(pds->src, ViewPath[1].X, ViewPath[1].Y);
viewx = FLOAT2FIXED(view.X); viewx = FLOAT2FIXED(view.X);
viewy = FLOAT2FIXED(view.Y); viewy = FLOAT2FIXED(view.Y);
viewz = FLOAT2FIXED(view.Z); viewz = FLOAT2FIXED(view.Z);
viewangle = va.BAMs(); viewangle = va.BAMs();
if (!r_showviewer)
{
double distp = (ViewPath[0] - ViewPath[1]).Length();
if (distp > EQUAL_EPSILON)
{
double dist1 = (view - ViewPath[0]).Length();
double dist2 = (view - ViewPath[1]).Length();
if (dist1 + dist2 < distp + 1)
{
camera->renderflags |= RF_INVISIBLE;
}
}
}
} }
ViewAngle = AngleToFloat(viewangle); ViewAngle = AngleToFloat(viewangle);
@ -783,6 +802,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
InSubsector = NULL; InSubsector = NULL;
R_RenderBSPNode (nodes + numnodes - 1); R_RenderBSPNode (nodes + numnodes - 1);
R_3D_ResetClip(); // reset clips (floor/ceiling) R_3D_ResetClip(); // reset clips (floor/ceiling)
if (!savedvisibility) camera->renderflags &= ~RF_INVISIBLE;
PlaneCycles.Clock(); PlaneCycles.Clock();
R_DrawPlanes (); R_DrawPlanes ();
@ -822,6 +842,8 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
viewx = startx; viewx = startx;
viewy = starty; viewy = starty;
viewz = startz; viewz = startz;
ViewPath[0] = savedpath[0];
ViewPath[1] = savedpath[1];
ViewAngle = AngleToFloat(viewangle); ViewAngle = AngleToFloat(viewangle);
} }

View file

@ -85,7 +85,7 @@ struct InterpolationViewer
static TArray<InterpolationViewer> PastViewers; static TArray<InterpolationViewer> PastViewers;
static FRandom pr_torchflicker ("TorchFlicker"); static FRandom pr_torchflicker ("TorchFlicker");
static FRandom pr_hom; static FRandom pr_hom;
static bool NoInterpolateView; bool NoInterpolateView; // GL needs access to this.
static TArray<DVector3a> InterpolationPath; static TArray<DVector3a> InterpolationPath;
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -108,6 +108,7 @@ int viewwindowy;
DVector3 ViewPos; DVector3 ViewPos;
DAngle ViewAngle; DAngle ViewAngle;
DAngle ViewPitch; DAngle ViewPitch;
DVector3 ViewPath[2];
extern "C" extern "C"
{ {
@ -590,67 +591,78 @@ void R_InterpolateView (player_t *player, double Frac, InterpolationViewer *ivie
DAngle oviewangle = iview->Old.Angles.Yaw; DAngle oviewangle = iview->Old.Angles.Yaw;
DAngle nviewangle = iview->New.Angles.Yaw; DAngle nviewangle = iview->New.Angles.Yaw;
if ((iview->Old.Pos.X != iview->New.Pos.X || iview->Old.Pos.Y != iview->New.Pos.Y) && InterpolationPath.Size() > 0) if (!cl_capfps)
{ {
DVector3 view = iview->New.Pos; if ((iview->Old.Pos.X != iview->New.Pos.X || iview->Old.Pos.Y != iview->New.Pos.Y) && InterpolationPath.Size() > 0)
// Interpolating through line portals is a messy affair.
// What needs be done is to store the portal transitions of the camera actor as waypoints
// and then find out on which part of the path the current view lies.
// Needless to say, this doesn't work for chasecam mode.
if (!r_showviewer)
{ {
double pathlen = 0; DVector3 view = iview->New.Pos;
double zdiff = 0;
double totalzdiff = 0;
DAngle adiff = 0.;
DAngle totaladiff = 0.;
double oviewz = iview->Old.Pos.Z;
double nviewz = iview->New.Pos.Z;
DVector3a oldpos = { { iview->Old.Pos.X, iview->Old.Pos.Y, 0 }, 0. };
DVector3a newpos = { { iview->New.Pos.X, iview->New.Pos.Y, 0 }, 0. };
InterpolationPath.Push(newpos); // add this to the array to simplify the loops below
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) // Interpolating through line portals is a messy affair.
// What needs be done is to store the portal transitions of the camera actor as waypoints
// and then find out on which part of the path the current view lies.
// Needless to say, this doesn't work for chasecam mode.
if (!r_showviewer)
{ {
DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1]; double pathlen = 0;
DVector3a &end = InterpolationPath[i]; double zdiff = 0;
pathlen += (end.pos-start.pos).Length(); double totalzdiff = 0;
totalzdiff += start.pos.Z; DAngle adiff = 0.;
totaladiff += start.angle; DAngle totaladiff = 0.;
} double oviewz = iview->Old.Pos.Z;
double interpolatedlen = Frac * pathlen; double nviewz = iview->New.Pos.Z;
DVector3a oldpos = { { iview->Old.Pos.X, iview->Old.Pos.Y, 0 }, 0. };
DVector3a newpos = { { iview->New.Pos.X, iview->New.Pos.Y, 0 }, 0. };
InterpolationPath.Push(newpos); // add this to the array to simplify the loops below
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
{
DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1];
DVector3a &end = InterpolationPath[i];
double fraglen = (end.pos - start.pos).Length();
zdiff += start.pos.Z;
adiff += start.angle;
if (fraglen <= interpolatedlen)
{ {
interpolatedlen -= fraglen; DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1];
DVector3a &end = InterpolationPath[i];
pathlen += (end.pos - start.pos).Length();
totalzdiff += start.pos.Z;
totaladiff += start.angle;
} }
else double interpolatedlen = Frac * pathlen;
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
{ {
double fragfrac = interpolatedlen / fraglen; DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1];
oviewz += zdiff; DVector3a &end = InterpolationPath[i];
nviewz -= totalzdiff - zdiff; double fraglen = (end.pos - start.pos).Length();
oviewangle += adiff; zdiff += start.pos.Z;
nviewangle -= totaladiff - adiff; adiff += start.angle;
DVector2 viewpos = start.pos + (fragfrac * (end.pos - start.pos)); if (fraglen <= interpolatedlen)
ViewPos = { viewpos, oviewz + Frac * (nviewz - oviewz) }; {
break; interpolatedlen -= fraglen;
}
else
{
double fragfrac = interpolatedlen / fraglen;
oviewz += zdiff;
nviewz -= totalzdiff - zdiff;
oviewangle += adiff;
nviewangle -= totaladiff - adiff;
DVector2 viewpos = start.pos + (fragfrac * (end.pos - start.pos));
ViewPos = { viewpos, oviewz + Frac * (nviewz - oviewz) };
break;
}
} }
InterpolationPath.Pop();
ViewPath[0] = iview->Old.Pos;
} }
InterpolationPath.Pop(); }
else
{
DVector2 disp = Displacements.getOffset(oldgroup, newgroup);
ViewPos = iview->Old.Pos + (iview->New.Pos - iview->Old.Pos - disp) * Frac;
ViewPath[1] = iview->New.Pos;
ViewPath[0] = iview->Old.Pos;
} }
} }
else else
{ {
DVector2 disp = Displacements.getOffset(oldgroup, newgroup); ViewPos = iview->New.Pos;
ViewPos = iview->Old.Pos + (iview->New.Pos - iview->Old.Pos - disp) * Frac; ViewPath[0] = ViewPath[1] = iview->New.Pos;
} }
if (player != NULL && if (player != NULL &&
!(player->cheats & CF_INTERPVIEW) && !(player->cheats & CF_INTERPVIEW) &&

View file

@ -15,6 +15,7 @@ extern DCanvas *RenderTarget;
extern DVector3 ViewPos; extern DVector3 ViewPos;
extern DAngle ViewAngle; extern DAngle ViewAngle;
extern DAngle ViewPitch; extern DAngle ViewPitch;
extern DVector3 ViewPath[2];
extern fixed_t viewx, viewy, viewz; extern fixed_t viewx, viewy, viewz;
extern angle_t viewangle; extern angle_t viewangle;