270 lines
7.2 KiB
Lua
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
|