gzdoom/wadsrc/static/zscript/actors/shared/camera.zs
dileepvr 95b264bdb6
Isometric Mode and Robin (#2618)
* Feature-complete isometric mode fork.

* Dithered transparency condition tweaks.

* Dithered transparency for non-corpse monsters only (and missiles).

* SpectatorCamera vertical shift.

* Including math.h in hw_sprites.cpp to keep visual studio happy (it couldn't find M_SQRT2 definition).

* Defining MY_SQRT2 in hw_sprites.cpp to keep visual studio happy (it couldn't find M_SQRT2 definition).

* Defining MY_SQRT2 in r_utility.cpp also to keep visual studio happy.

* retrigger checks

* Have correct sprite angle-frame face the camera with orthographic projection enabled.

* Dithered Transparency now works properly on 3D floors. Moved that dither-trans flag setting code within hw_bsp.cpp to handle double-processing of linedefs. Added helper functions to FRenderViewpoint class 'bool IsOrtho()' and 'bool IsAllowedOoB()' to clean up checks everywhere in the code.

* Fixed indents. Added bbox property to subsector struct and use it instead of BSP nodes and Clippers (creating a bbox around viewpoint and checking for overlap) in orthographic mode when no fog of war is active. Turns out to be much faster. Though you need really big maps (Winter's Fury MAP01) to see a difference in fps.

* Non-linux checks don't like uint. Changed to unsigned int.

* Small change of a float to camera.zs. Ignore for testing. Should make no difference.

* Update actor.h to remain mergeable

RF2_NOMIPMAP was introduced, so I had to displace RF_ISOMETRICSPRITES to next bit.
2024-08-11 10:04:40 -04:00

214 lines
4.3 KiB
Text

class DoomBuilderCamera : Actor
{
States
{
Spawn:
TNT1 A 1;
Stop;
}
}
class SecurityCamera : Actor
{
default
{
+NOBLOCKMAP
+NOGRAVITY
+DONTSPLASH
RenderStyle "None";
CameraHeight 0;
}
double Center;
double Acc;
double Delta;
double Range;
override void PostBeginPlay ()
{
Super.PostBeginPlay ();
Center = Angle;
if (args[2])
Delta = 360. / (args[2] * TICRATE / 8);
else
Delta = 0.;
if (args[1])
Delta /= 2;
Acc = 0.;
int arg = (args[0] << 24) >> 24; // make sure the value has the intended sign.
Pitch = clamp(arg, -89, 89);
Range = args[1];
}
override void Tick ()
{
Acc += Delta;
if (Range != 0)
Angle = Center + Range * sin(Acc);
else if (Delta != 0)
Angle = Acc;
}
}
class AimingCamera : SecurityCamera
{
double MaxPitchChange;
override void PostBeginPlay ()
{
int changepitch = args[2];
args[2] = 0;
Super.PostBeginPlay ();
MaxPitchChange = double(changepitch) / TICRATE;
Range /= TICRATE;
ActorIterator it = Level.CreateActorIterator(args[3]);
tracer = it.Next ();
if (tracer == NULL)
{
if (args[3] != 0)
{
console.Printf ("AimingCamera %d: Can't find TID %d\n", tid, args[3]);
}
}
else
{ // Don't try for a new target upon losing this one.
args[3] = 0;
}
}
override void Tick ()
{
if (tracer == NULL && args[3] != 0)
{ // Recheck, in case something with this TID was created since the last time.
ActorIterator it = Level.CreateActorIterator(args[3]);
tracer = it.Next ();
}
if (tracer != NULL)
{
double dir = deltaangle(angle, AngleTo(tracer));
double delta = abs(dir);
if (delta > Range)
{
delta = Range;
}
if (dir > 0)
{
Angle += delta;
}
else
{
Angle -= delta;
}
if (MaxPitchChange != 0)
{ // Aim camera's pitch; use floats for precision
Vector2 vect = tracer.Vec2To(self);
double dz = pos.z - tracer.pos.z - tracer.Height/2;
double dist = vect.Length();
double desiredPitch = dist != 0.f ? VectorAngle(dist, dz) : 0.;
double diff = deltaangle(pitch, desiredPitch);
if (abs (diff) < MaxPitchChange)
{
pitch = desiredPitch;
}
else if (diff < 0)
{
pitch -= MaxPitchChange;
}
else
{
pitch += MaxPitchChange;
}
}
}
}
}
class SpectatorCamera : Actor
{
bool chasingtracer;
double lagdistance; // camera gives chase (lazy follow) if tracer gets > lagdistance away from camera.pos
int chasemode; // 0: chase until tracer centered, 1: same but only when tracer is moving, 2: stop chase if tracer within lagdistance
property lagdistance : lagdistance;
property chasingtracer : chasingtracer;
property chasemode : chasemode;
default
{
+NOBLOCKMAP
+NOGRAVITY
+NOINTERACTION
RenderStyle "None";
CameraHeight 0;
SpectatorCamera.chasingtracer false;
SpectatorCamera.lagdistance 0.0;
SpectatorCamera.chasemode 0;
}
void Init(double dist, double yaw, double inpitch, int inflags)
{
double zshift = 0.0;
if(tracer != NULL)
{
if(player != NULL) zshift = -0.25*tracer.height;
else zshift = 0.5*tracer.height;
}
else if (player != NULL && player.mo != NULL) zshift = -0.5*player.mo.height;
SetViewPos((-dist*Cos(yaw)*Cos(inpitch), -dist*Sin(yaw)*Cos(inpitch), dist*Sin(inpitch)+zshift), inflags);
LookAtSelf(inpitch);
}
void LookAtSelf(double inpitch)
{
if(ViewPos.Offset.length() > 0.)
{
Vector3 negviewpos = (-1.0) * ViewPos.Offset;
angle = negviewpos.Angle();
pitch = inpitch;
}
}
override void Tick()
{
if(tracer != NULL)
{
Vector3 distvec = tracer.pos - pos;
double dist = distvec.length();
if((dist <= 4 && chasingtracer) || lagdistance <= 0.0) // Keep tracer centered on screen
{
SetOrigin(tracer.pos, true);
chasingtracer = false;
}
else // Lazy follow tracer
{
if(dist >= 2*lagdistance)
{
SetOrigin(tracer.pos, true);
chasingtracer = false;
}
else if(dist > lagdistance && !chasingtracer) chasingtracer = true;
if(chasingtracer)
{
speed = tracer.vel.xy.length()/dist;
if((speed == 0.0) && (chasemode == 0)) speed = tracer.speed/dist;
SetOrigin(pos + 2*distvec*speed, true);
if(chasemode > 1) chasingtracer = false;
}
}
}
else if(player != NULL && player.mo != NULL)
{
cameraFOV = player.FOV;
SetOrigin(player.mo.pos, true);
}
}
}