This commit is contained in:
Major Cooke 2020-10-10 10:27:44 -05:00
parent 474e09e265
commit 1e8f3fe329
10 changed files with 131 additions and 25 deletions

View file

@ -414,7 +414,8 @@ enum ActorFlag8
MF8_STOPRAILS = 0x00000200, // [MC] Prevent rails from going further if an actor has this flag.
MF8_ABSVIEWANGLES = 0x00000400, // [MC] By default view angle/pitch/roll is an offset. This will make it absolute instead.
MF8_FALLDAMAGE = 0x00000800, // Monster will take fall damage regardless of map settings.
MF8_VIEWPOSNOANGLES = 0x00001000, // [MC] View position takes no angles into account
MF8_ABSVIEWPOS = 0x00002000, // [MC] Absolute position, so the actor must update it manually.
};
// --- mobj.renderflags ---
@ -968,7 +969,8 @@ public:
DAngle SpriteAngle;
DAngle SpriteRotation;
DRotator Angles;
DRotator ViewAngles; // Offsets for cameras
DRotator ViewAngles; // Angle offsets for cameras
DVector3 ViewPos; // Position offsets for cameras
DVector2 Scale; // Scaling values; 1 is normal size
double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double.

View file

@ -394,6 +394,9 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner);
// [RH] Position the chasecam
void P_AimCamera (AActor *t1, DVector3 &, DAngle &, sector_t *&sec, bool &unlinked);
// [MC] Aiming for viewpos.
void P_AdjustViewPos(AActor *t1, DVector3 orig, DVector3 &, sector_t *&sec, bool &unlinked);
// [RH] Means of death
enum
{

View file

@ -5384,6 +5384,27 @@ void P_AimCamera(AActor *t1, DVector3 &campos, DAngle &camangle, sector_t *&Came
camangle = trace.SrcAngleFromTarget - 180.;
}
void P_AdjustViewPos(AActor *t1, DVector3 orig, DVector3 &campos, sector_t *&CameraSector, bool &unlinked)
{
FTraceResults trace;
DVector3 vvec = campos - orig;
double distance = vvec.Length();
// Trace handles all of the portal crossing, which is why there is no usage of Vec#Offset(Z).
if (Trace(orig, t1->Sector, vvec.Unit(), distance, 0, 0, t1, trace) &&
trace.Distance > 5)
{
// Position camera slightly in front of hit thing
campos = orig + vvec.Unit() * (trace.Distance - 5);
}
else
{
campos = trace.HitPos - trace.HitVector * 1 / 256.;
}
CameraSector = trace.Sector;
unlinked = trace.unlinked;
}
//==========================================================================
//

View file

@ -368,7 +368,8 @@ void AActor::Serialize(FSerializer &arc)
A("spawnorder", SpawnOrder)
A("friction", Friction)
A("SpriteOffset", SpriteOffset)
A("userlights", UserLights);
A("userlights", UserLights)
A("viewpos", ViewPos);
SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain);
SerializeArgs(arc, "args", args, def->args, special);

View file

@ -725,7 +725,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
if (thing == camera && !vp.showviewer)
{
DVector3 thingorigin = thing->Pos();
if (thruportal == 1) thingorigin += di->Level->Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
if (thruportal == 1) thingorigin += di->Level->Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
if (fabs(thingorigin.X - vp.ActorPos.X) < 2 && fabs(thingorigin.Y - vp.ActorPos.Y) < 2) return;
}
// Thing is invisible if close to the camera.

View file

@ -129,6 +129,7 @@ FRenderViewpoint::FRenderViewpoint()
FrameTime = 0;
extralight = 0;
showviewer = false;
NoPortalPath = false;
}
FRenderViewpoint r_viewpoint;
@ -435,7 +436,7 @@ void R_InterpolateView (FRenderViewpoint &viewpoint, player_t *player, double Fr
// 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 (!viewpoint.showviewer)
if (!viewpoint.showviewer && !viewpoint.NoPortalPath)
{
double pathlen = 0;
double zdiff = 0;
@ -775,34 +776,107 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor
iview->Old = iview->New;
}
if (player != NULL && gamestate != GS_TITLELEVEL &&
((player->cheats & CF_CHASECAM) || (r_deathcamera && viewpoint.camera->health <= 0)))
//==============================================================================================
// Handles offsetting the camera with ChaseCam and/or viewpos.
{
AActor *mo = viewpoint.camera;
const DVector3 orig = { mo->Pos().XY(), mo->player ? mo->player->viewz : mo->Z() + mo->GetCameraHeight() };
viewpoint.ActorPos = orig;
if (player && gamestate != GS_TITLELEVEL)
{
sector_t *oldsector = viewpoint.ViewLevel->PointInRenderSubsector(iview->Old.Pos)->sector;
// [RH] Use chasecam view
DVector3 campos;
DAngle camangle;
P_AimCamera (viewpoint.camera, campos, camangle, viewpoint.sector, unlinked); // fixme: This needs to translate the angle, too.
iview->New.Pos = campos;
iview->New.Angles.Yaw = camangle;
viewpoint.showviewer = true;
// Interpolating this is a very complicated thing because nothing keeps track of the aim camera's movement, so whenever we detect a portal transition
// it's probably best to just reset the interpolation for this move.
// Note that this can still cause problems with unusually linked portals
if (viewpoint.sector->PortalGroup != oldsector->PortalGroup || (unlinked && ((iview->New.Pos.XY() - iview->Old.Pos.XY()).LengthSquared()) > 256*256))
if ((player->cheats & CF_CHASECAM) || (r_deathcamera && viewpoint.camera->health <= 0))
{
iview->otic = nowtic;
iview->Old = iview->New;
r_NoInterpolate = true;
// [RH] Use chasecam view
DVector3 campos;
DAngle camangle;
P_AimCamera (viewpoint.camera, campos, camangle, viewpoint.sector, unlinked); // fixme: This needs to translate the angle, too.
iview->New.Pos = campos;
iview->New.Angles.Yaw = camangle;
viewpoint.showviewer = true;
// Interpolating this is a very complicated thing because nothing keeps track of the aim camera's movement, so whenever we detect a portal transition
// it's probably best to just reset the interpolation for this move.
// Note that this can still cause problems with unusually linked portals
if (viewpoint.sector->PortalGroup != oldsector->PortalGroup || (unlinked && ((iview->New.Pos.XY() - iview->Old.Pos.XY()).LengthSquared()) > 256*256))
{
iview->otic = nowtic;
iview->Old = iview->New;
r_NoInterpolate = true;
}
viewpoint.ActorPos = campos;
}
else // No chase/death cam and player is alive.
{
viewpoint.sector = viewpoint.ViewLevel->PointInRenderSubsector(iview->New.Pos.XY())->sector;
viewpoint.showviewer = false;
// [MC] Ignores all portal portal transitions since it's meant to be absolute.
// It'll be down to the modder to handle performing offsetting with the appropriate functions.
if (mo->flags8 & MF8_ABSVIEWPOS)
{
iview->New.Pos = mo->ViewPos;
}
else
{
DVector3 next = orig;
if (mo->ViewPos.isZero())
{
// Since viewpos isn't being used, it's safe to enable path interpolation
viewpoint.NoPortalPath = false;
}
else if ((mo->flags8 & MF8_VIEWPOSNOANGLES))
{
// No relativity added from angles.
next += mo->ViewPos;
}
else
{
// [MC] Do NOT handle portals here! Trace must have the unportaled (absolute) position to
// get the correct angle and distance. Trace automatically handles portals by itself.
// Also, viewpos must use the original angles, not the view angles to position the camera
DAngle yaw = mo->Angles.Yaw;
DAngle pitch = mo->Angles.Pitch;
DAngle roll = mo->Angles.Roll;
DVector3 relx, rely, relz, Off = mo->ViewPos;
DMatrix3x3 rot =
DMatrix3x3(DVector3(0., 0., 1.), yaw.Cos(), yaw.Sin()) *
DMatrix3x3(DVector3(0., 1., 0.), pitch.Cos(), pitch.Sin()) *
DMatrix3x3(DVector3(1., 0., 0.), roll.Cos(), roll.Sin());
relx = DVector3(1., 0., 0.)*rot;
rely = DVector3(0., 1., 0.)*rot;
relz = DVector3(0., 0., 1.)*rot;
next += relx * Off.X + rely * Off.Y + relz * Off.Z;
}
if (next != orig)
{
// [MC] Disable interpolation if the camera view is crossing through a portal.
// Also, disable the portal interpolation pathing entirely when using the viewpos feature.
// Interpolation still happens with everything else though and seems to work fine.
viewpoint.NoPortalPath = true;
P_AdjustViewPos(mo, orig, next, viewpoint.sector, unlinked);
if (viewpoint.sector->PortalGroup != oldsector->PortalGroup || (unlinked && ((iview->New.Pos.XY() - iview->Old.Pos.XY()).LengthSquared()) > 256 * 256))
{
iview->otic = nowtic;
iview->Old = iview->New;
r_NoInterpolate = true;
}
}
iview->New.Pos = next;
}
}
viewpoint.ActorPos = campos;
}
else
{
viewpoint.ActorPos = iview->New.Pos = { viewpoint.camera->Pos().XY(), viewpoint.camera->player ? viewpoint.camera->player->viewz : viewpoint.camera->Z() + viewpoint.camera->GetCameraHeight() };
iview->New.Pos = orig;
viewpoint.sector = viewpoint.camera->Sector;
viewpoint.showviewer = false;
viewpoint.showviewer = viewpoint.NoPortalPath = false;
}
}
// [MC] Apply the view angles first, which is the offsets. If the absolute isn't desired,

View file

@ -44,6 +44,7 @@ struct FRenderViewpoint
int extralight; // extralight to be added to this viewpoint
bool showviewer; // show the camera actor?
bool NoPortalPath; // Disable portal interpolation path for actor viewpos.
void SetViewAngle(const FViewWindow &viewwindow);

View file

@ -327,6 +327,8 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF8, STOPRAILS, AActor, flags8),
DEFINE_FLAG(MF8, FALLDAMAGE, AActor, flags8),
DEFINE_FLAG(MF8, ABSVIEWANGLES, AActor, flags8),
DEFINE_FLAG(MF8, VIEWPOSNOANGLES, AActor, flags8),
DEFINE_FLAG(MF8, ABSVIEWPOS, AActor, flags8),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -1948,6 +1948,7 @@ DEFINE_FIELD(AActor, InventoryID)
DEFINE_FIELD_NAMED(AActor, ViewAngles.Yaw, viewangle)
DEFINE_FIELD_NAMED(AActor, ViewAngles.Pitch, viewpitch)
DEFINE_FIELD_NAMED(AActor, ViewAngles.Roll, viewroll)
DEFINE_FIELD(AActor, ViewPos)
DEFINE_FIELD_X(FCheckPosition, FCheckPosition, thing);
DEFINE_FIELD_X(FCheckPosition, FCheckPosition, pos);

View file

@ -235,6 +235,7 @@ class Actor : Thinker native
native double CameraHeight; // Height of camera when used as such
native double CameraFOV;
native double ViewAngle, ViewPitch, ViewRoll;
native Vector3 ViewPos;
native double RadiusDamageFactor; // Radius damage factor
native double SelfDamageFactor;
native double StealthAlpha;