Skip to content

Commit

Permalink
Reworked view offsetting
Browse files Browse the repository at this point in the history
View offsets are now added after the base position and angles (accounting for interpolation) are calculated. Behavior was centralized into a singular tracer that all view offsets now use to prevent clipping out of the map. Cleaned up camera rendering behavior. Angles are now properly normalized after all offsetting is accounted for. The chase cam can now update in real-time instead of forcing interpolation.
  • Loading branch information
Boondorl authored and madame-rachelle committed Mar 1, 2024
1 parent 08a093f commit b469770
Show file tree
Hide file tree
Showing 7 changed files with 341 additions and 464 deletions.
10 changes: 5 additions & 5 deletions src/playsim/a_sharedglobal.h
Expand Up @@ -125,11 +125,11 @@ enum

struct FQuakeJiggers
{
DVector3 Intensity;
DVector3 RelIntensity;
DVector3 Offset;
DVector3 RelOffset;
double RollIntensity, RollWave;
DVector3 Intensity = {};
DVector3 RelIntensity = {};
DVector3 Offset = {};
DVector3 RelOffset = {};
double RollIntensity = 0.0, RollWave = 0.0;
};

class DEarthquake : public DThinker
Expand Down
2 changes: 1 addition & 1 deletion src/playsim/actor.h
Expand Up @@ -770,7 +770,7 @@ class DViewPosition : public DObject
Flags = f;
}

bool isZero()
bool isZero() const
{
return Offset.isZero();
}
Expand Down
7 changes: 2 additions & 5 deletions src/playsim/p_local.h
Expand Up @@ -393,11 +393,8 @@ bool P_CheckMissileSpawn(AActor *missile, double maxdist);

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, FRenderViewpoint *view);
// [RH] Position the cam's view offsets.
void R_OffsetView(FRenderViewpoint& viewPoint, const DVector3& dir, const double distance);


// [RH] Means of death
Expand Down
82 changes: 22 additions & 60 deletions src/playsim/p_map.cpp
Expand Up @@ -5573,77 +5573,39 @@ void P_RailAttack(FRailParams *p)
CVAR(Float, chase_height, -8.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, chase_dist, 90.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)

void P_AimCamera(AActor *t1, DVector3 &campos, DAngle &camangle, sector_t *&CameraSector, bool &unlinked)
void R_OffsetView(FRenderViewpoint& viewPoint, const DVector3& dir, const double distance)
{
double distance = clamp<double>(chase_dist, 0, 30000);
DAngle angle = t1->Angles.Yaw - DAngle::fromDeg(180);
DAngle pitch = t1->Angles.Pitch;
FTraceResults trace;
DVector3 vvec;
double sz;

double pc = pitch.Cos();

vvec = { pc * angle.Cos(), pc * angle.Sin(), pitch.Sin() };
sz = t1->Top() - t1->Floorclip + clamp<double>(chase_height, -1000, 1000);

if (Trace(t1->PosAtZ(sz), t1->Sector, vvec, distance, 0, 0, NULL, trace) &&
trace.Distance > 10)
const DAngle baseYaw = dir.Angle();
FTraceResults trace = {};
if (Trace(viewPoint.Pos, viewPoint.sector, dir, distance, 0u, 0u, nullptr, trace))
{
// Position camera slightly in front of hit thing
campos = t1->PosAtZ(sz) + vvec *(trace.Distance - 5);
viewPoint.Pos = trace.HitPos - trace.HitVector * min<double>(5.0, trace.Distance);
viewPoint.sector = viewPoint.ViewLevel->PointInRenderSubsector(viewPoint.Pos)->sector;
}
else
{
campos = trace.HitPos - trace.HitVector * 1/256.;
viewPoint.Pos = trace.HitPos;
viewPoint.sector = trace.Sector;
}
CameraSector = trace.Sector;
unlinked = trace.unlinked;
camangle = trace.SrcAngleFromTarget - DAngle::fromDeg(180.);
}

struct ViewPosPortal
{
int counter;
};

static ETraceStatus VPos_CheckPortal(FTraceResults &res, void *userdata)
{
//[MC] Mirror how third person works.
ViewPosPortal *pc = (ViewPosPortal *)userdata;

if (res.HitType == TRACE_CrossingPortal)
viewPoint.Angles.Yaw += deltaangle(baseYaw, trace.SrcAngleFromTarget);
// TODO: Why does this even need to be done? Please fix tracers already.
if (dir.Z < 0.0)
{
res.HitType = TRACE_HitNone; // Needed to force the trace to continue appropriately.
pc->counter++;
return TRACE_Skip;
while (!viewPoint.sector->PortalBlocksMovement(sector_t::floor) && viewPoint.Pos.Z < viewPoint.sector->GetPortalPlaneZ(sector_t::floor))
{
viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::floor);
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::floor)->mDestination;
}
}
if (res.HitType == TRACE_HitActor)
else if (dir.Z > 0.0)
{
return TRACE_Skip;
while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling) && viewPoint.Pos.Z > viewPoint.sector->GetPortalPlaneZ(sector_t::ceiling))
{
viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::ceiling);
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::ceiling)->mDestination;
}
}
return TRACE_Stop;
}

// [MC] Used for ViewPos. Uses code borrowed from P_AimCamera.
void P_AdjustViewPos(AActor *t1, DVector3 orig, DVector3 &campos, sector_t *&CameraSector, bool &unlinked, FRenderViewpoint *view)
{
FTraceResults trace;
ViewPosPortal pc;
pc.counter = 0;
const DVector3 vvec = campos - orig;
const 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, CameraSector, vvec.Unit(), distance, 0, 0, t1, trace, TRACE_ReportPortals, VPos_CheckPortal, &pc) &&
trace.Distance > 5)
campos = orig + vvec.Unit() * (trace.Distance - 5);
else
campos = trace.HitPos - trace.HitVector * 1 / 256.;


CameraSector = trace.Sector;
unlinked = trace.unlinked;
}

//==========================================================================
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/hwrenderer/scene/hw_sprites.cpp
Expand Up @@ -800,7 +800,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
// Some added checks if the camera actor is not supposed to be seen. It can happen that some portal setup has this actor in view in which case it may not be skipped here
if (viewmaster == camera && !vp.showviewer)
{
if (vp.noviewer || (viewmaster->player && viewmaster->player->crossingPortal)) return;
if (vp.bForceNoViewer || (viewmaster->player && viewmaster->player->crossingPortal)) return;
DVector3 vieworigin = viewmaster->Pos();
if (thruportal == 1) vieworigin += di->Level->Displacements.getOffset(viewmaster->Sector->PortalGroup, sector->PortalGroup);
if (fabs(vieworigin.X - vp.ActorPos.X) < 2 && fabs(vieworigin.Y - vp.ActorPos.Y) < 2) return;
Expand Down

0 comments on commit b469770

Please sign in to comment.