utils.lua 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. --- Various utility functions
  2. -- @module utils
  3. local modules = (...): gsub('%.[^%.]+$', '') .. "."
  4. local vec2 = require(modules .. "vec2")
  5. local vec3 = require(modules .. "vec3")
  6. local sqrt = math.sqrt
  7. local abs = math.abs
  8. local ceil = math.ceil
  9. local floor = math.floor
  10. local log = math.log
  11. local utils = {}
  12. -- reimplementation of math.frexp, due to its removal from Lua 5.3 :(
  13. -- courtesy of airstruck
  14. local log2 = log(2)
  15. local frexp = math.frexp or function(x)
  16. if x == 0 then return 0, 0 end
  17. local e = floor(log(abs(x)) / log2 + 1)
  18. return x / 2 ^ e, e
  19. end
  20. --- Clamps a value within the specified range.
  21. -- @param value Input value
  22. -- @param min Minimum output value
  23. -- @param max Maximum output value
  24. -- @return number
  25. function utils.clamp(value, min, max)
  26. return math.max(math.min(value, max), min)
  27. end
  28. --- Returns `value` if it is equal or greater than |`size`|, or 0.
  29. -- @param value
  30. -- @param size
  31. -- @return number
  32. function utils.deadzone(value, size)
  33. return abs(value) >= size and value or 0
  34. end
  35. --- Check if value is equal or greater than threshold.
  36. -- @param value
  37. -- @param threshold
  38. -- @return boolean
  39. function utils.threshold(value, threshold)
  40. -- I know, it barely saves any typing at all.
  41. return abs(value) >= threshold
  42. end
  43. --- Check if value is equal or less than threshold.
  44. -- @param value
  45. -- @param threshold
  46. -- @return boolean
  47. function utils.tolerance(value, threshold)
  48. -- I know, it barely saves any typing at all.
  49. return abs(value) <= threshold
  50. end
  51. --- Scales a value from one range to another.
  52. -- @param value Input value
  53. -- @param min_in Minimum input value
  54. -- @param max_in Maximum input value
  55. -- @param min_out Minimum output value
  56. -- @param max_out Maximum output value
  57. -- @return number
  58. function utils.map(value, min_in, max_in, min_out, max_out)
  59. return ((value) - (min_in)) * ((max_out) - (min_out)) / ((max_in) - (min_in)) + (min_out)
  60. end
  61. --- Linear interpolation.
  62. -- Performs linear interpolation between 0 and 1 when `low` < `progress` < `high`.
  63. -- @param progress (0-1)
  64. -- @param low value to return when `progress` is 0
  65. -- @param high value to return when `progress` is 1
  66. -- @return number
  67. function utils.lerp(progress, low, high)
  68. return progress * (high - low) + low
  69. end
  70. --- Hermite interpolation.
  71. -- Performs smooth Hermite interpolation between 0 and 1 when `low` < `progress` < `high`.
  72. -- @param progress (0-1)
  73. -- @param low value to return when `progress` is 0
  74. -- @param high value to return when `progress` is 1
  75. -- @return number
  76. function utils.smoothstep(progress, low, high)
  77. local t = utils.clamp((progress - low) / (high - low), 0.0, 1.0)
  78. return t * t * (3.0 - 2.0 * t)
  79. end
  80. --- Round number at a given precision.
  81. -- Truncates `value` at `precision` points after the decimal (whole number if
  82. -- left unspecified).
  83. -- @param value
  84. -- @param precision
  85. -- @return number
  86. function utils.round(value, precision)
  87. if precision then return utils.round(value / precision) * precision end
  88. return value >= 0 and floor(value+0.5) or ceil(value-0.5)
  89. end
  90. --- Wrap `value` around if it exceeds `limit`.
  91. -- @param value
  92. -- @param limit
  93. -- @return number
  94. function utils.wrap(value, limit)
  95. if value < 0 then
  96. value = value + utils.round(((-value/limit)+1))*limit
  97. end
  98. return value % limit
  99. end
  100. --- Check if a value is a power-of-two.
  101. -- Returns true if a number is a valid power-of-two, otherwise false.
  102. -- @author undef
  103. -- @param value
  104. -- @return boolean
  105. function utils.is_pot(value)
  106. -- found here: https://love2d.org/forums/viewtopic.php?p=182219#p182219
  107. -- check if a number is a power-of-two
  108. return (frexp(value)) == 0.5
  109. end
  110. -- Originally from vec3
  111. function utils.project_on(a, b)
  112. local s =
  113. (a.x * b.x + a.y * b.y + a.z or 0 * b.z or 0) /
  114. (b.x * b.x + b.y * b.y + b.z or 0 * b.z or 0)
  115. if a.z and b.z then
  116. return vec3(
  117. b.x * s,
  118. b.y * s,
  119. b.z * s
  120. )
  121. end
  122. return vec2(
  123. b.x * s,
  124. b.y * s
  125. )
  126. end
  127. -- Originally from vec3
  128. function utils.project_from(a, b)
  129. local s =
  130. (b.x * b.x + b.y * b.y + b.z or 0 * b.z or 0) /
  131. (a.x * b.x + a.y * b.y + a.z or 0 * b.z or 0)
  132. if a.z and b.z then
  133. return vec3(
  134. b.x * s,
  135. b.y * s,
  136. b.z * s
  137. )
  138. end
  139. return vec2(
  140. b.x * s,
  141. b.y * s
  142. )
  143. end
  144. -- Originally from vec3
  145. function utils.mirror_on(a, b)
  146. local s =
  147. (a.x * b.x + a.y * b.y + a.z or 0 * b.z or 0) /
  148. (b.x * b.x + b.y * b.y + b.z or 0 * b.z or 0) * 2
  149. if a.z and b.z then
  150. return vec3(
  151. b.x * s - a.x,
  152. b.y * s - a.y,
  153. b.z * s - a.z
  154. )
  155. end
  156. return vec2(
  157. b.x * s - a.x,
  158. b.y * s - a.y
  159. )
  160. end
  161. -- Originally from vec3
  162. function utils.reflect(i, n)
  163. return i - (n * (2 * n:dot(i)))
  164. end
  165. -- Originally from vec3
  166. function utils.refract(i, n, ior)
  167. local d = n:dot(i)
  168. local k = 1 - ior * ior * (1 - d * d)
  169. if k >= 0 then
  170. return (i * ior) - (n * (ior * d + sqrt(k)))
  171. end
  172. return vec3()
  173. end
  174. return utils