From b24ee842ba296e99d089b951a18b3b03f756e5fa Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Tue, 14 Aug 2018 02:57:44 +0200 Subject: [PATCH] Implemented "six degrees of freedom" movement for guided redeemer missiles (reload/zoom for manual tilt control). Made part of the guided redeemer reticle rotate according to the missile's roll just to show off Shape2D. --- graphics/GuidedX1.png | Bin 0 -> 5079 bytes graphics/GuidedX2.png | Bin 0 -> 4029 bytes zscript.txt | 1 + zscript/mk_quaternion.zsc | 97 ++++++++++++++++++++++++++++++++++++ zscript/warheadlauncher.zsc | 67 +++++++++++++++++-------- 5 files changed, 144 insertions(+), 21 deletions(-) create mode 100644 graphics/GuidedX1.png create mode 100644 graphics/GuidedX2.png create mode 100644 zscript/mk_quaternion.zsc diff --git a/graphics/GuidedX1.png b/graphics/GuidedX1.png new file mode 100644 index 0000000000000000000000000000000000000000..c330d1679d860802719f0c9a9b1645edb499d71e GIT binary patch literal 5079 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 literal 0 HcmV?d00001 diff --git a/zscript.txt b/zscript.txt index 436f0c5..77c0177 100644 --- a/zscript.txt +++ b/zscript.txt @@ -2,6 +2,7 @@ version "3.4" #include "zscript/mk_matrix.zsc" #include "zscript/mk_coordutil.zsc" +#include "zscript/mk_quaternion.zsc" #include "zscript/utcommon.zsc" #include "zscript/impacthammer.zsc" #include "zscript/chainsaw.zsc" diff --git a/zscript/mk_quaternion.zsc b/zscript/mk_quaternion.zsc new file mode 100644 index 0000000..24631a5 --- /dev/null +++ b/zscript/mk_quaternion.zsc @@ -0,0 +1,97 @@ +/* + Quaternion math helper class. + (C)2018 Marisa Kirisame, UnSX Team. + Released under the GNU Lesser General Public License version 3 (or later). + See https://www.gnu.org/licenses/lgpl-3.0.txt for its terms. +*/ + +Class Quat +{ + protected double W, X, Y, Z; + + Quat init( double w, double x, double y, double z ) + { + self.W = w; + self.X = x; + self.Y = y; + self.Z = z; + return self; + } + + void copy( Quat q ) + { + W = q.W; + X = q.X; + Y = q.Y; + Z = q.Z; + } + + static Quat create( double w, double x, double y, double z ) + { + return new("Quat").init(w,x,y,z); + } + + static Quat create_axis( Vector3 axis, double theta ) + { + double scale = axis dot axis; + if ( scale < double.epsilon ) return Quat.create(1,0,0,0); + theta *= 0.5; + double f = sin(theta)/sqrt(scale); + return Quat.create(cos(theta),axis.x*f,axis.y*f,axis.z*f); + } + + static Quat create_euler( double pitch, double yaw, double roll ) + { + Quat zrot = Quat.create_axis((0,0,1),yaw); + Quat yrot = Quat.create_axis((0,1,0),pitch); + Quat xrot = Quat.create_axis((1,0,0),roll); + Quat sum = zrot.qmul(yrot); + sum = sum.qmul(xrot); + return sum; + } + + // copied here since Actor.Normalize180 is not (yet) clearscope + static double Normalize180( double ang ) + { + ang = ang%360; + ang = (ang+360)%360; + if ( ang > 180 ) ang -= 360; + return ang; + } + + double, double, double to_euler() + { + double stest = z*x-w*y; + double yawY = 2*(w*z+x*y); + double yawX = 1-2*(y*y+z*z); + double st = 0.4999995; + double pitch = 0; + double yaw = 0; + double roll = 0; + if ( stest <= -st ) + { + pitch = 90; + yaw = atan2(yawY,yawX); + roll = Normalize180(yaw+(2*atan2(x,w))); + } + else if ( stest > st ) + { + pitch = -90; + yaw = atan2(yawY,yawX); + roll = Normalize180(yaw+(2*atan2(x,w))); + } + else + { + pitch = -asin(2*stest); + yaw = atan2(yawY,yawX); + roll = atan2(2*(w*x+y*z),(1-2*(x*x+y*y))); + } + return pitch, yaw, roll; + } + + Quat qmul( Quat q ) + { + return Quat.create(w*q.w-x*q.x-y*q.y-z*q.z,w*q.x+x*q.w+y*q.z-z + *q.y,w*q.y+y*q.w+z*q.x-x*q.z,w*q.z+z*q.w+x*q.y-y*q.x); + } +} diff --git a/zscript/warheadlauncher.zsc b/zscript/warheadlauncher.zsc index 0fa59e4..4e793b7 100644 --- a/zscript/warheadlauncher.zsc +++ b/zscript/warheadlauncher.zsc @@ -355,15 +355,13 @@ Class WarShell : Actor Class GuidedWarShell : WarShell { - double lagangle, lagpitch, lagangle2, lagpitch2; - double guideangle, guidepitch, lastguideroll; + double lagangle, lagpitch, lagroll, lagangle2, lagpitch2, lagroll2, + guideangle, guidepitch, guideroll; override void PostBeginPlay() { Super.PostBeginPlay(); if ( target && target.player ) target.player.camera = self; - guideangle = angle; - guidepitch = pitch; } override void Tick() { @@ -385,22 +383,25 @@ Class GuidedWarShell : WarShell { lagangle = target.player.cmd.yaw/128.; lagpitch = -target.player.cmd.pitch/128.; - guideangle += lagangle2*0.95+lagangle*0.05; - guidepitch += lagpitch2*0.95+lagpitch*0.05; - guidepitch = Clamp(guidepitch,-89,89); - double guideroll = -lagangle2*15; - Vector3 dir = (cos(guideangle)*cos(guidepitch),sin(guideangle)*cos(guidepitch),-sin(guidepitch)); - destangle = atan2(dir.y,dir.x); - destpitch = asin(-dir.z); - double destroll = lastguideroll*0.9+guideroll*0.1; - A_SetAngle(destangle,SPF_INTERPOLATE); - A_SetPitch(destpitch,SPF_INTERPOLATE); - A_SetRoll(destroll,SPF_INTERPOLATE); + if ( target.player.cmd.buttons&BT_RELOAD ) lagroll = 5; + else if ( target.player.cmd.buttons&BT_ZOOM ) lagroll = -5; + else lagroll = 0; + guideangle = lagangle2*0.95+lagangle*0.05; + guidepitch = lagpitch2*0.95+lagpitch*0.05; + guideroll = lagroll2*0.95+lagroll*0.05; + Quat orient = Quat.create_euler(pitch,angle,roll); + Quat angles = Quat.create_euler(guidepitch,guideangle,guideroll); + orient = orient.qmul(angles); + double npitch, nangle, nroll; + [npitch, nangle, nroll] = orient.to_euler(); + A_SetAngle(nangle,SPF_INTERPOLATE); + A_SetPitch(npitch,SPF_INTERPOLATE); + A_SetRoll(nroll,SPF_INTERPOLATE); vel = (vel+(cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch))*0.8).unit()*11; } lagangle2 = lagangle2*0.95+lagangle*0.05; lagpitch2 = lagpitch2*0.95+lagpitch*0.05; - lastguideroll = roll*0.98; + lagroll2 = lagroll2*0.95+lagroll*0.05; } States { @@ -439,25 +440,36 @@ Class RedeemerHUD : HUDMessageBase { Actor Camera; Vector3 ViewPos; - double ViewAngle, ViewPitch, ViewRoll; - TextureID reticle, mark, readout; + double ViewAngle, ViewPitch, ViewRoll, LagRoll, LagRoll2; + TextureID reticle1, reticle2, mark, readout; Font whfont; ThinkerIterator t; MidTracer tr; Array ta; + Shape2D rreticle; RedeemerHUD Init() { - reticle = TexMan.CheckForTexture("GuidedX",TexMan.Type_Any); + reticle1 = TexMan.CheckForTexture("GuidedX1",TexMan.Type_Any); + reticle2 = TexMan.CheckForTexture("GuidedX2",TexMan.Type_Any); mark = TexMan.CheckForTexture("Crosshr6",TexMan.Type_Any); readout = TexMan.CheckForTexture("Readout",TexMan.Type_Any); whfont = Font.GetFont('WHFONT'); t = ThinkerIterator.Create("Actor"); tr = new("MidTracer"); + rreticle = new("Shape2D"); + rreticle.PushCoord((0,0)); + rreticle.PushCoord((1,0)); + rreticle.PushCoord((0,1)); + rreticle.PushCoord((1,1)); + rreticle.PushTriangle(0,3,1); + rreticle.PushTriangle(0,2,3); return self; } override bool Tick() { + LagRoll = Quat.Normalize180(ViewRoll-LagRoll2); + LagRoll2 += Quat.Normalize180(LagRoll-LagRoll2)*0.1; // shootable targetting if ( CVar.GetCVar('flak_redeemerreadout',players[consoleplayer]).GetBool() ) { @@ -494,8 +506,21 @@ Class RedeemerHUD : HUDMessageBase Screen.DrawText(whfont,Font.CR_UNTRANSLATED,(ta[i].vpos.x-whfont.StringWidth(ta[i].diststr)/2)-12,ta[i].vpos.y+8,ta[i].diststr,DTA_RenderStyle,(1|2<<8|1<<16)); } } - // other stuff - Screen.DrawTexture(reticle,false,320,240,DTA_VirtualWidth,640,DTA_VirtualHeight,480,DTA_RenderStyle,(1|2<<8|1<<16)); + // reticle + Vector2 vs = (640,640/Screen.GetAspectRatio()); + Vector2 mid, siz; + [mid, siz] = Screen.VirtualToRealCoords(vs*0.5,(128,128),vs,false,false); + Vector2 verts[4]; + verts[0] = (-siz.x,-siz.y); + verts[1] = (siz.x,-siz.y); + verts[2] = (-siz.x,siz.y); + verts[3] = (siz.x,siz.y); + rreticle.Clear(Shape2D.C_Verts); + for ( int i=0; i<4; i++ ) + rreticle.PushVertex(mid+(verts[i].x*cos(LagRoll2)-verts[i].y*sin(LagRoll2),verts[i].x*sin(LagRoll2)+verts[i].y*cos(LagRoll2))); + Screen.DrawShape(reticle1,false,rreticle,DTA_RenderStyle,(1|2<<8|1<<16)); + Screen.DrawTexture(reticle2,false,vs.x*0.5,vs.y*0.5,DTA_VirtualWidthF,vs.x,DTA_VirtualHeightF,vs.y,DTA_KeepRatio,true,DTA_RenderStyle,(1|2<<8|1<<16)); + // faux assembly readout int numreadouts = Screen.GetHeight()/128+2; for ( int i=0; i