local p={}p.__index=p local X=Vector3.new local S=math.pi local n=S*2 local D=tick local function H(p,X)return p==p and p or X end local function t(p,X)local D=(X-p)%n return D>S and D-n or D end local function r(p,S)return X(t(p.X,S.X),t(p.Y,S.Y),t(p.Z,S.Z))end function p.new()local S=setmetatable({P=5;D=.1,Position=X(),Velocity=X();Goal=X(),Last=D()},p)return S end function p.CheckNAN(p)p.Velocity=X(H(p.Velocity.X,0),H(p.Velocity.Y,0),H(p.Velocity.Z,0))p.Position=X(H(p.Position.X,p.Goal.X),H(p.Position.Y,p.Goal.Y),H(p.Position.Z,p.Goal.Z))end function p.Update(p)local X=D()local S=X-p.Last p.Last=X p.Velocity=p.Velocity+p.P*((p.Goal-p.Position)+-p.Velocity*p.D)p.Position=p.Position+p.Velocity*S p:CheckNAN()return p.Position end function p.UpdateAngle(p)p.Goal=p.Position+r(p.Position,p.Goal)return p:Update()end return p



local Damping = {}
Damping.__index = Damping

local V3 = Vector3.new
local PI = math.pi
local TAU = PI * 2
local tick = tick


local function CheckNAN(value, returnIfNan)
	return (value == value and value or returnIfNan)
end


local function DeltaAngle(current, target)
	local num = (target - current) % TAU
	return (num > PI and (num - TAU) or num)
end


local function DeltaAngleV3(pos1, pos2)
	return V3(
		DeltaAngle(pos1.X, pos2.X),
		DeltaAngle(pos1.Y, pos2.Y),
		DeltaAngle(pos1.Z, pos2.Z)
	)
end


function Damping.new()
	
	local damping = setmetatable({
		P = 5;
		D = 0.1;
		Position = V3();
		Velocity = V3();
		Goal = V3();
		Last = tick();
	}, Damping)
	
	return damping
	
end


function Damping:CheckNAN()
	self.Velocity = V3(CheckNAN(self.Velocity.X, 0), CheckNAN(self.Velocity.Y, 0), CheckNAN(self.Velocity.Z, 0))
	self.Position = V3(CheckNAN(self.Position.X, self.Goal.X), CheckNAN(self.Position.Y, self.Goal.Y), CheckNAN(self.Position.Z, self.Goal.Z))
end


function Damping:Update()
	local t = tick()
	local dt = (t - self.Last)
	self.Last = t
	self.Velocity = (self.Velocity + (self.P * ((self.Goal - self.Position) + (-self.Velocity * self.D))))
	self.Position = (self.Position + (self.Velocity * dt))
	self:CheckNAN()
	return self.Position
end


function Damping:UpdateAngle()
	self.Goal = (self.Position + DeltaAngleV3(self.Position, self.Goal))
	return self:Update()
end


return Damping
