• Vector Maths
    4 replies, posted
Once again i am having a brainfart with some simple vector math. I'm trying to modify some old code and make it more modular. Here's some code from an old SWEP. It basically allows you to specify the sprint position for a weapon, using the GetViewModelPosition function. [lua] function SWEP:AngApproach( newang, ang, mul ) ang:RotateAroundAxis( ang:Right(), newang.x * mul ) ang:RotateAroundAxis( ang:Up(), newang.y * mul ) ang:RotateAroundAxis( ang:Forward(), newang.z * mul ) return ang end function SWEP:PosApproach( newpos, pos, ang, mul ) local right = ang:Right() local up = ang:Up() local forward = ang:Forward() pos = pos + newpos.x * right * mul pos = pos + newpos.y * forward * mul pos = pos + newpos.z * up * mul return pos end function SWEP:MoveViewModelTo( newpos, newang, pos, ang, mul ) ang = self:AngApproach( newang, ang, mul ) pos = self:PosApproach( newpos, pos, ang, mul ) return pos, ang end function SWEP:GetViewModelPosition( pos, ang ) // shortened for sake of brevity - imagine this is what gets returned if you sprint return self:MoveViewModelTo( SomeSprintPosition, SomeSprintAngle, pos, ang, timescale ) end[/lua] So basically it calculates the position/angle of the viewmodel based on a time scale for any amount of time (between 0 and 1) and an arbitrary sprint position/angle and adds it to the original position/angle. What i want to do is store a single position/angle which can change at any time, and calculate the position of the viewmodel based on that using math.Approach. This would mean smooth transitions between an infinite amount of viewmodel positions. I hope i explained that well enough. Here's the code i have currently. [lua] function SWEP:ApproachAngPos( pos, ang, basepos, baseang, speed ) // note that self.CurAng and self.CurPos are initialized to Vector(0,0,0) when the SWEP is created, which means the viewmodel is in the normal position. self.CurAng.x = math.Approach( self.CurAng.x, ang.x, FrameTime() * speed ) self.CurAng.y = math.Approach( self.CurAng.y, ang.y, FrameTime() * speed ) self.CurAng.z = math.Approach( self.CurAng.z, ang.z, FrameTime() * speed ) // this works self.CurPos.x = math.Approach( self.CurPos.x, pos.x, FrameTime() * speed ) self.CurPos.y = math.Approach( self.CurPos.y, pos.y, FrameTime() * speed ) self.CurPos.z = math.Approach( self.CurPos.z, pos.z, FrameTime() * speed ) // this shit is wrong return basepos + self.CurPos, baseang + self.CurAng end function SWEP:GetViewModelPosition( pos, ang ) return self.Weapon:ApproachAngPos( SomeDifferentTargetPos, SomeDifferentTargetAng, pos, ang, 25 ) end[/lua] If you compare the old code and the new code, you'll notice that i replicated the angle calculating properly. I tested it and it worked. But the position calculations are a little trickier since the original code requires some multiplication with the angles. Any insight would be appreciated, my brain isn't in the mood for this right now.
Some methods that may be of use to you: [b][url=wiki.garrysmod.com/?title=G.LerpAngle]LerpAngle( progress, a, b )[/url][/b] [b][url=wiki.garrysmod.com/?title=G.LerpVector]LerpVector( progress, a, b )[/url][/b] Those seem to cover your base approach needs. [code] self.Progress = math.Approach( self.Progress or 0, 1, FrameTime( ) * Speed ) self.CurAng = LerpAngle( self.Progress, self.CurAng, ang ) self.CurPos = LerpVector( self.Progress, self.CurPos, pos ) [/code] Untested, but should give an idea.
The only problem is that the angle part of the maths requires more than just approaching another number. Although that Lerp stuff will be handy for tidying the code up. I'm basically trying to convert PosApproach from the old SWEP to work with my new system.
and now i'm confused as fuck because the old SWEP code is apparently using angle functions on vectors. when i try to, it spits out errors. What the shitfuck. [code]GAMEMODE:'CalcView' Failed: weapons/dfsjfs_base/shared.lua:91: attempt to call method 'Right' (a nil value) [/code] [lua]ang:RotateAroundAxis( ang:Right(), newang.x * mul ) [/lua] ang is a vector, so how is this even possible? [editline]07:58PM[/editline] well if it works i won't question it. i'm getting close to a solution. [lua] local newpos = self.Weapon:GetNWVector( "ViewVector", pos ) local newang = self.Weapon:GetNWVector( "ViewAngle", ang ) if self.EndPos != newpos or self.EndAng != newang then print( "CHANGING POSITIONS " ) self.IronTime = CurTime() self.EndPos = newpos self.EndAng = newang self.StartPos, self.StartAng = self.Weapon:MoveViewModelTo( self.CurPos, self.CurAng, self.EndPos, self.EndAng, 1 ) end self.IronScale = math.Clamp( ( CurTime() - self.IronTime ) / self.Weapon:GetNWFloat( "ViewTime", 0.5 ), 0, 1 ) self.CurPos = LerpVector( self.IronScale, self.StartPos, self.EndPos ) self.CurAng = LerpVector( self.IronScale, self.StartAng, self.EndAng ) return self.CurPos, self.CurAng[/lua]
The first argument of RotateAroundAxis is a vector. Right() is a function of Angle, which is meant to return an axis vector. If ang is already a vector, you may want to look at what you are passing in your arguments. I guess I'm not entirely sure why your ang is turning out to be a vector (unless I misread your post).
Sorry, you need to Log In to post a reply to this thread.