Vector Maths

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:

LerpAngle( progress, a, b )
LerpVector( progress, a, b )

Those seem to cover your base approach needs.



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 )


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.


GAMEMODE:'CalcView' Failed: weapons/dfsjfs_base/shared.lua:91: attempt to call method 'Right' (a nil value)


[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).