Files
mmkrp_2026/lua/includes/extensions/math.lua
2026-03-15 14:54:49 +03:00

270 lines
7.2 KiB
Lua

include( "math/ease.lua" )
math.tau = 2 * math.pi
--[[---------------------------------------------------------
Name: DistanceSqr( low, high )
Desc: Squared Distance between two 2d points, use this instead of math.Distance as it is more cpu efficient.
------------------------------------------------------------]]
function math.DistanceSqr( x1, y1, x2, y2 )
local xd = x2 - x1
local yd = y2 - y1
return xd * xd + yd * yd
end
--[[---------------------------------------------------------
Name: Distance( low, high )
Desc: Distance between two 2d points
------------------------------------------------------------]]
function math.Distance( x1, y1, x2, y2 )
local xd = x2 - x1
local yd = y2 - y1
return math.sqrt( xd * xd + yd * yd )
end
math.Dist = math.Distance -- Backwards compatibility
--[[---------------------------------------------------------
Name: BinToInt( bin )
Desc: Convert a binary string to an integer number
------------------------------------------------------------]]
function math.BinToInt( bin )
return tonumber( bin, 2 )
end
--[[---------------------------------------------------------
Name: IntToBin( int )
Desc: Convert an integer number to a binary string (the string len will be a multiple of three)
------------------------------------------------------------]]
local intbin = {
["0"] = "000", ["1"] = "001", ["2"] = "010", ["3"] = "011",
["4"] = "100", ["5"] = "101", ["6"] = "110", ["7"] = "111"
}
function math.IntToBin( int )
local str = string.gsub( string.format( "%o", int ), "(.)", function ( d ) return intbin[ d ] end )
return str
end
--[[---------------------------------------------------------
Name: Clamp( in, low, high )
Desc: Clamp value between 2 values
------------------------------------------------------------]]
function math.Clamp( _in, low, high )
return math.min( math.max( _in, low ), high )
end
--[[---------------------------------------------------------
Name: Rand( low, high )
Desc: Random number between low and high
-----------------------------------------------------------]]
function math.Rand( low, high )
return low + ( high - low ) * math.random()
end
math.Max = math.max
math.Min = math.min
--[[---------------------------------------------------------
Name: EaseInOut(fProgress, fEaseIn, fEaseOut)
Desc: Provided by garry from the facewound source and converted
to Lua by me :p
Usage: math.EaseInOut(0.1, 0.5, 0.5) - all parameters should be between 0 and 1
-----------------------------------------------------------]]
function math.EaseInOut( frac, easeIn, easeOut )
if ( frac == 0 or frac == 1 ) then return frac end
if ( easeIn == nil ) then easeIn = 0 end
if ( easeOut == nil ) then easeOut = 1 end
local fSumEase = easeIn + easeOut
if ( fSumEase == 0 ) then return frac end
if ( fSumEase > 1 ) then
easeIn = easeIn / fSumEase
easeOut = easeOut / fSumEase
end
local fProgressCalc = 1 / ( 2 - easeIn - easeOut )
if ( frac < easeIn ) then
return ( ( fProgressCalc / easeIn ) * frac * frac )
elseif ( frac < 1 - easeOut ) then
return ( fProgressCalc * ( 2 * frac - easeIn ) )
else
frac = 1 - frac
return ( 1 - ( fProgressCalc / easeOut ) * frac * frac )
end
end
function math.calcBSplineN( i, k, t, tInc )
local knot = ( i - 3 ) * tInc
if ( k <= 1 ) then
if ( knot <= t && t < knot + tInc ) then
return 1
end
return 0
end
local count = i + k - 4
local len = count * tInc
local knots = len - knot
local nknot = k - 1
local ret = 0
if ( knots > 0 ) then
ret = ( t - knot ) * math.calcBSplineN( i, nknot, t, tInc ) / knots
end
local sb = nknot * tInc
if ( sb > 0 ) then
ret = ret + ( len + tInc - t ) * math.calcBSplineN( i + 1, nknot, t, tInc ) / sb
end
return ret
end
function math.BSplinePoint( frac, points, frac_max )
local len = #points
local tInc = frac_max / ( len - 3 )
frac = frac + tInc
local ret = Vector()
for i = 1, len do
ret:Add( math.calcBSplineN( i, 4, frac, tInc ) * points[ i ] )
end
return ret
end
--[[---------------------------------------------------------
Cubic hermite spline
p0, p1 - points; m0, m1 - tangets; frac - fraction along the curve (0-1)
-----------------------------------------------------------]]
function math.CHSpline( frac, p0, m0, p1, m1 )
if ( frac >= 1 ) then return p1 end
if ( frac <= 0 ) then return p0 end
local t2 = frac * frac
local t3 = frac * t2
return p0 * ( 2 * t3 - 3 * t2 + 1 ) +
m0 * ( t3 - 2 * t2 + frac ) +
p1 * ( -2 * t3 + 3 * t2 ) +
m1 * ( t3 - t2 )
end
-- Round to the nearest integer
function math.Round( num, idp )
local mult = 10 ^ ( idp or 0 )
return math.floor( num * mult + 0.5 ) / mult
end
-- Rounds towards zero
function math.Truncate( num, idp )
local mult = 10 ^ ( idp or 0 )
return ( num < 0 and math.ceil or math.floor )( num * mult ) / mult
end
function math.Approach( cur, target, inc )
if ( cur < target ) then
return math.min( cur + math.abs( inc ), target )
end
if ( cur > target ) then
return math.max( cur - math.abs( inc ), target )
end
return target
end
function math.NormalizeAngle( a )
return ( a + 180 ) % 360 - 180
end
function math.AngleDifference( a, b )
local diff = math.NormalizeAngle( a - b )
if ( diff < 180 ) then
return diff
end
return diff - 360
end
function math.ApproachAngle( cur, target, inc )
return math.Approach( cur, cur + math.AngleDifference( target, cur ), inc )
end
function math.TimeFraction( Start, End, Current )
return ( Current - Start ) / ( End - Start )
end
function math.Remap( value, inMin, inMax, outMin, outMax )
return outMin + ( ( ( value - inMin ) / ( inMax - inMin ) ) * ( outMax - outMin ) )
end
-- Snaps the provided number to the nearest multiple
function math.SnapTo( num, multiple )
return math.floor( num / multiple + 0.5 ) * multiple
end
--[[---------------------------------------------------------
Name: CubicBezier( frac, p0, p1, p2, p3 )
Desc: Lerp point between points with cubic bezier
-----------------------------------------------------------]]
function math.CubicBezier( frac, p0, p1, p2, p3 )
local frac2 = frac * frac
local inv = 1 - frac
local inv2 = inv * inv
return inv2 * inv * p0 + 3 * inv2 * frac * p1 + 3 * inv * frac2 * p2 + frac2 * frac * p3
end
--[[---------------------------------------------------------
Name: QuadraticBezier( frac, p0, p1, p2 )
Desc: Lerp point between points with quadratic bezier
-----------------------------------------------------------]]
function math.QuadraticBezier( frac, p0, p1, p2 )
local frac2 = frac * frac
local inv = 1 - frac
local inv2 = inv * inv
return inv2 * p0 + 2 * inv * frac * p1 + frac2 * p2
end
--[[---------------------------------------------------------
Name: Factorial( num )
Desc: Calculate the factorial value of num
-----------------------------------------------------------]]
function math.Factorial( num )
if ( num < 0 ) then
return nil
elseif ( num < 2 ) then
return 1
end
local res = 1
for i = 2, num do
res = res * i
end
return res
end
--[[---------------------------------------------------------
Name: IsNearlyEqual( a, b, tolerance )
Desc: Checks if two floating point numbers are nearly equal
-----------------------------------------------------------]]
function math.IsNearlyEqual( a, b, tolerance )
if ( tolerance == nil ) then
tolerance = 1e-8
end
return math.abs( a - b ) <= tolerance
end