From 85759e3bd0437757d185c6856956ba1dd332ccbe Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Thu, 27 Aug 2020 11:43:09 -0500 Subject: [PATCH] Added A_SpriteOffset. (#895) - Coordinates work akin to A_OverlayOffset: +X shifts to the right, +Y shifts down. --- src/playsim/actor.h | 1 + src/playsim/p_mobj.cpp | 1 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 34 ++++++++++++------- .../swrenderer/scene/r_opaque_pass.cpp | 4 +-- src/rendering/swrenderer/things/r_sprite.cpp | 5 ++- src/scripting/vmthunks_actors.cpp | 1 + wadsrc/static/zscript/actors/actions.zs | 5 +++ wadsrc/static/zscript/actors/actor.zs | 1 + 8 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index a6aa1712d5..07fd9720ea 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -995,6 +995,7 @@ public: DVector3 OldRenderPos; DVector3 Vel; + DVector2 SpriteOffset; double Speed; double FloatSpeed; diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 233e4e7989..455866084f 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -365,6 +365,7 @@ void AActor::Serialize(FSerializer &arc) A("spawntime", SpawnTime) A("spawnorder", SpawnOrder) A("friction", Friction) + A("SpriteOffset", SpriteOffset) A("userlights", UserLights); SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 3e77ea06db..65fc4c5b84 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -898,12 +898,11 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t thing->renderflags ^= RF_XFLIP; r.Scale(sprscale.X, sprscale.Y); - - float rightfac = -r.left; + + float SpriteOffY = thing->SpriteOffset.Y; + float rightfac = -r.left - thing->SpriteOffset.X; float leftfac = rightfac - r.width; - float bottomfac = -r.top; - float topfac = bottomfac - r.height; - z1 = z - r.top; + z1 = z - r.top - SpriteOffY; z2 = z1 - r.height; float spriteheight = sprscale.Y * r.height; @@ -914,31 +913,39 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t PerformSpriteClipAdjustment(thing, thingpos, spriteheight); } - float viewvecX; - float viewvecY; switch (spritetype) { case RF_FACESPRITE: - viewvecX = vp.ViewVector.X; - viewvecY = vp.ViewVector.Y; + { + float viewvecX = vp.ViewVector.X; + float viewvecY = vp.ViewVector.Y; x1 = x - viewvecY*leftfac; x2 = x - viewvecY*rightfac; y1 = y + viewvecX*leftfac; y2 = y + viewvecX*rightfac; break; - + } case RF_FLATSPRITE: { + float bottomfac = -r.top - SpriteOffY; + float topfac = bottomfac - r.height; + x1 = x + leftfac; x2 = x + rightfac; y1 = y - topfac; y2 = y - bottomfac; + // [MC] Counteract in case of any potential problems. Tests so far haven't + // shown any outstanding issues but that doesn't mean they won't appear later + // when more features are added. + z1 += SpriteOffY; + z2 += SpriteOffY; + break; } - break; case RF_WALLSPRITE: - viewvecX = Angles.Yaw.Cos(); - viewvecY = Angles.Yaw.Sin(); + { + float viewvecX = Angles.Yaw.Cos(); + float viewvecY = Angles.Yaw.Sin(); x1 = x + viewvecY*leftfac; x2 = x + viewvecY*rightfac; @@ -946,6 +953,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t y2 = y - viewvecX*rightfac; break; } + } } else { diff --git a/src/rendering/swrenderer/scene/r_opaque_pass.cpp b/src/rendering/swrenderer/scene/r_opaque_pass.cpp index 6f6ef6bd1e..c30210ea96 100644 --- a/src/rendering/swrenderer/scene/r_opaque_pass.cpp +++ b/src/rendering/swrenderer/scene/r_opaque_pass.cpp @@ -1004,9 +1004,9 @@ namespace swrenderer bool RenderOpaquePass::GetThingSprite(AActor *thing, ThingSprite &sprite) { + // The X offsetting (SpriteOffset.X) is performed in r_sprite.cpp, in RenderSprite::Project(). sprite.pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); - sprite.pos.Z += thing->GetBobOffset(Thread->Viewport->viewpoint.TicFrac); - + sprite.pos.Z += thing->GetBobOffset(Thread->Viewport->viewpoint.TicFrac) - thing->SpriteOffset.Y; sprite.spritenum = thing->sprite; sprite.tex = nullptr; sprite.voxel = nullptr; diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index 1554379434..c3f4c0532f 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -81,8 +81,11 @@ namespace swrenderer const double thingxscalemul = spriteScale.X / tex->GetScale().X; // Calculate billboard line for the sprite + double SpriteOffX = (thing) ? thing->SpriteOffset.X : 0.; DVector2 dir = { viewport->viewpoint.Sin, -viewport->viewpoint.Cos }; - DVector2 pt1 = pos.XY() - viewport->viewpoint.Pos.XY() - dir * (((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->GetLeftOffsetSW() - 1) : tex->GetLeftOffsetSW()) * thingxscalemul); + DVector2 trs = pos.XY() - viewport->viewpoint.Pos.XY(); + trs = { trs.X + SpriteOffX * dir.X, trs.Y + SpriteOffX * dir.Y }; + DVector2 pt1 = trs - dir * (((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->GetLeftOffsetSW() - 1) : tex->GetLeftOffsetSW()) * thingxscalemul); DVector2 pt2 = pt1 + dir * (tex->GetWidth() * thingxscalemul); FWallCoords wallc; diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 9ada1dffb4..63fdcbbd86 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -1775,6 +1775,7 @@ DEFINE_FIELD_NAMED(AActor, __Pos, pos) DEFINE_FIELD_NAMED(AActor, __Pos.X, x) DEFINE_FIELD_NAMED(AActor, __Pos.Y, y) DEFINE_FIELD_NAMED(AActor, __Pos.Z, z) +DEFINE_FIELD(AActor, SpriteOffset) DEFINE_FIELD(AActor, Prev) DEFINE_FIELD(AActor, SpriteAngle) DEFINE_FIELD(AActor, SpriteRotation) diff --git a/wadsrc/static/zscript/actors/actions.zs b/wadsrc/static/zscript/actors/actions.zs index 8e27a46d20..69a6542ebe 100644 --- a/wadsrc/static/zscript/actors/actions.zs +++ b/wadsrc/static/zscript/actors/actions.zs @@ -95,4 +95,9 @@ extend class Actor } } + void A_SpriteOffset(double ox = 0.0, double oy = 0.0) + { + SpriteOffset.X = ox; + SpriteOffset.Y = oy; + } } diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 374c4867f5..a719376e3d 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -89,6 +89,7 @@ class Actor : Thinker native native PlayerInfo Player; native readonly vector3 Pos; native vector3 Prev; + native vector2 SpriteOffset; native double spriteAngle; native double spriteRotation; native double VisibleStartAngle;