math.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. -- love.math
  2. --------------------------------------------------------------------------------
  3. --------------------------------------------------------------------------------
  4. ------------------------------------OBJECTS-------------------------------------
  5. --------------------------------------------------------------------------------
  6. --------------------------------------------------------------------------------
  7. -- BezierCurve (love.math.newBezierCurve)
  8. love.test.math.BezierCurve = function(test)
  9. -- create obj
  10. local curve = love.math.newBezierCurve(1, 1, 2, 2, 3, 1)
  11. local px, py = curve:getControlPoint(2)
  12. test:assertObject(curve)
  13. -- check initial properties
  14. test:assertCoords({2, 2}, {px, py}, 'check point x/y')
  15. test:assertEquals(3, curve:getControlPointCount(), 'check 3 points')
  16. test:assertEquals(2, curve:getDegree(), 'check degree is points-1')
  17. -- check some values on the curve
  18. test:assertEquals(1, curve:evaluate(0), 'check curve evaluation 0')
  19. test:assertRange(curve:evaluate(0.1), 1.2, 1.3, 'check curve evaluation 0.1')
  20. test:assertRange(curve:evaluate(0.2), 1.4, 1.5, 'check curve evaluation 0.2')
  21. test:assertRange(curve:evaluate(0.5), 2, 2.1, 'check curve evaluation 0.5')
  22. test:assertEquals(3, curve:evaluate(1), 'check curve evaluation 1')
  23. -- check derivative
  24. local deriv = curve:getDerivative()
  25. test:assertObject(deriv)
  26. test:assertEquals(2, deriv:getControlPointCount(), 'check deriv points')
  27. test:assertRange(deriv:evaluate(0.1), 2, 2.1, 'check deriv evaluation 0.1')
  28. -- check segment
  29. local segment = curve:getSegment(0, 0.5)
  30. test:assertObject(segment)
  31. test:assertEquals(3, segment:getControlPointCount(), 'check segment points')
  32. test:assertRange(segment:evaluate(0.1), 1, 1.1, 'check segment evaluation 0.1')
  33. -- mess with control points
  34. curve:removeControlPoint(2)
  35. curve:insertControlPoint(4, 1, -1)
  36. curve:insertControlPoint(5, 3, -1)
  37. curve:insertControlPoint(6, 2, -1)
  38. curve:setControlPoint(2, 3, 2)
  39. test:assertEquals(5, curve:getControlPointCount(), 'check 3 points still')
  40. local px1, py1 = curve:getControlPoint(1)
  41. local px2, py2 = curve:getControlPoint(3)
  42. local px3, py3 = curve:getControlPoint(5)
  43. test:assertCoords({1, 1}, {px1, py1}, 'check modified point 1')
  44. test:assertCoords({5, 3}, {px2, py2}, 'check modified point 1')
  45. test:assertCoords({3, 1}, {px3, py3}, 'check modified point 1')
  46. -- check render lists
  47. local coords1 = curve:render(5)
  48. local coords2 = curve:renderSegment(0, 0.1, 5)
  49. test:assertEquals(196, #coords1, 'check coords')
  50. test:assertEquals(20, #coords2, 'check segment coords')
  51. -- check translation values
  52. px, py = curve:getControlPoint(2)
  53. test:assertCoords({3, 2}, {px, py}, 'check pretransform x/y')
  54. curve:rotate(90 * (math.pi/180), 0, 0)
  55. px, py = curve:getControlPoint(2)
  56. test:assertCoords({-2, 3}, {px, py}, 'check rotated x/y')
  57. curve:scale(2, 0, 0)
  58. px, py = curve:getControlPoint(2)
  59. test:assertCoords({-4, 6}, {px, py}, 'check scaled x/y')
  60. curve:translate(5, -5)
  61. px, py = curve:getControlPoint(2)
  62. test:assertCoords({1, 1}, {px, py}, 'check translated x/y')
  63. end
  64. -- RandomGenerator (love.math.RandomGenerator)
  65. -- @NOTE as this checks random numbers the chances this fails is very unlikely, but not 0...
  66. -- if you've managed to proc it congrats! your prize is to rerun the testsuite again
  67. love.test.math.RandomGenerator = function(test)
  68. -- create object
  69. local rng1 = love.math.newRandomGenerator(3418323524, 20529293)
  70. test:assertObject(rng1)
  71. -- check set properties
  72. local low, high = rng1:getSeed()
  73. test:assertEquals(3418323524, low, 'check seed low')
  74. test:assertEquals(20529293, high, 'check seed high')
  75. -- check states
  76. local rng2 = love.math.newRandomGenerator(1448323524, 10329293)
  77. test:assertNotEquals(rng1:random(), rng2:random(), 'check not matching states')
  78. test:assertNotEquals(rng1:randomNormal(), rng2:randomNormal(), 'check not matching states')
  79. -- check setting state works
  80. rng2:setState(rng1:getState())
  81. test:assertEquals(rng1:random(), rng2:random(), 'check now matching')
  82. -- check overwriting seed works, should change output
  83. rng1:setSeed(os.time())
  84. test:assertNotEquals(rng1:random(), rng2:random(), 'check not matching states')
  85. test:assertNotEquals(rng1:randomNormal(), rng2:randomNormal(), 'check not matching states')
  86. end
  87. -- Transform (love.math.Transform)
  88. love.test.math.Transform = function(test)
  89. -- create obj
  90. local transform = love.math.newTransform(0, 0, 0, 1, 1, 0, 0, 0, 0)
  91. test:assertObject(transform)
  92. -- set some values and check the matrix and transformPoint values
  93. transform:translate(10, 8)
  94. transform:scale(2, 3)
  95. transform:rotate(90*(math.pi/180))
  96. transform:shear(1, 2)
  97. local px, py = transform:transformPoint(1, 1)
  98. test:assertCoords({4, 14}, {px, py}, 'check transformation methods')
  99. transform:reset()
  100. px, py = transform:transformPoint(1, 1)
  101. test:assertCoords({1, 1}, {px, py}, 'check reset')
  102. -- apply a transform to another transform
  103. local transform2 = love.math.newTransform()
  104. transform2:translate(5, 3)
  105. transform:apply(transform2)
  106. px, py = transform:transformPoint(1, 1)
  107. test:assertCoords({6, 4}, {px, py}, 'check apply other transform')
  108. -- check cloning a transform
  109. local transform3 = transform:clone()
  110. px, py = transform3:transformPoint(1, 1)
  111. test:assertCoords({6, 4}, {px, py}, 'check clone transform')
  112. -- check inverse and inverseTransform
  113. transform:reset()
  114. transform:translate(-14, 6)
  115. local ipx, ipy = transform:inverseTransformPoint(0, 0)
  116. transform:inverse()
  117. px, py = transform:transformPoint(0, 0)
  118. test:assertCoords({-px, -py}, {ipx, ipy}, 'check inverse points transform')
  119. -- check matrix manipulation
  120. transform:setTransformation(0, 0, 0, 1, 1, 0, 0, 0, 0)
  121. transform:translate(4, 4)
  122. local m1, m2, m3, m4, m5, m6, m7, m8,
  123. m9, m10, m11, m12, m13, m14, m15, m16 = transform:getMatrix()
  124. test:assertEquals(4, m4, 'check translate matrix x')
  125. test:assertEquals(4, m8, 'check translate matrix y')
  126. transform:setMatrix(m1, m2, m3, 3, m5, m6, m7, 1, m9, m10, m11, m12, m13, m14, m15, m16)
  127. px, py = transform:transformPoint(1, 1)
  128. test:assertCoords({4, 2}, {px, py}, 'check set matrix')
  129. -- check affine vs non affine
  130. transform:reset()
  131. test:assertTrue(transform:isAffine2DTransform(), 'check affine 1')
  132. transform:translate(4, 3)
  133. test:assertTrue(transform:isAffine2DTransform(), 'check affine 2')
  134. transform:setMatrix(1, 3, 4, 5.5, 1, 4.5, 2, 1, 3.4, 5.1, 4.1, 13, 1, 1, 2, 3)
  135. test:assertFalse(transform:isAffine2DTransform(), 'check not affine')
  136. end
  137. --------------------------------------------------------------------------------
  138. --------------------------------------------------------------------------------
  139. ------------------------------------METHODS-------------------------------------
  140. --------------------------------------------------------------------------------
  141. --------------------------------------------------------------------------------
  142. -- love.math.colorFromBytes
  143. love.test.math.colorFromBytes = function(test)
  144. -- check random value
  145. local r1, g1, b1, a1 = love.math.colorFromBytes(51, 51, 51, 51)
  146. test:assertEquals(r1, 0.2, 'check r from bytes')
  147. test:assertEquals(g1, 0.2, 'check g from bytes')
  148. test:assertEquals(b1, 0.2, 'check b from bytes')
  149. test:assertEquals(a1, 0.2, 'check a from bytes')
  150. -- check "max" value
  151. local r2, g2, b2, a2 = love.math.colorFromBytes(255, 255, 255, 255)
  152. test:assertEquals(r2, 1, 'check r from bytes')
  153. test:assertEquals(g2, 1, 'check g from bytes')
  154. test:assertEquals(b2, 1, 'check b from bytes')
  155. test:assertEquals(a2, 1, 'check a from bytes')
  156. -- check "min" value
  157. local r3, g3, b3, a3 = love.math.colorFromBytes(0, 0, 0, 0)
  158. test:assertEquals(r3, 0, 'check r from bytes')
  159. test:assertEquals(g3, 0, 'check g from bytes')
  160. test:assertEquals(b3, 0, 'check b from bytes')
  161. test:assertEquals(a3, 0, 'check a from bytes')
  162. end
  163. -- love.math.colorToBytes
  164. love.test.math.colorToBytes = function(test)
  165. -- check random value
  166. local r1, g1, b1, a1 = love.math.colorToBytes(0.2, 0.2, 0.2, 0.2)
  167. test:assertEquals(r1, 51, 'check bytes from r')
  168. test:assertEquals(g1, 51, 'check bytes from g')
  169. test:assertEquals(b1, 51, 'check bytes from b')
  170. test:assertEquals(a1, 51, 'check bytes from a')
  171. -- check "max" value
  172. local r2, g2, b2, a2 = love.math.colorToBytes(1, 1, 1, 1)
  173. test:assertEquals(r2, 255, 'check bytes from r')
  174. test:assertEquals(g2, 255, 'check bytes from g')
  175. test:assertEquals(b2, 255, 'check bytes from b')
  176. test:assertEquals(a2, 255, 'check bytes from a')
  177. -- check "min" value
  178. local r3, g3, b3, a3 = love.math.colorToBytes(0, 0, 0, 0)
  179. test:assertEquals(r3, 0, 'check bytes from r')
  180. test:assertEquals(g3, 0, 'check bytes from g')
  181. test:assertEquals(b3, 0, 'check bytes from b')
  182. test:assertEquals(a3, 0, 'check bytes from a')
  183. end
  184. -- love.math.gammaToLinear
  185. -- @NOTE I tried doing the same formula as the source from MathModule.cpp
  186. -- but get test failues due to slight differences
  187. love.test.math.gammaToLinear = function(test)
  188. local lr, lg, lb = love.math.gammaToLinear(1, 0.8, 0.02)
  189. --local eg = ((0.8 + 0.055) / 1.055)^2.4
  190. --local eb = 0.02 / 12.92
  191. test:assertGreaterEqual(0, lr, 'check gamma r to linear')
  192. test:assertGreaterEqual(0, lg, 'check gamma g to linear')
  193. test:assertGreaterEqual(0, lb, 'check gamma b to linear')
  194. end
  195. -- love.math.getRandomSeed
  196. -- @NOTE whenever i run this high is always 0, is that intended?
  197. love.test.math.getRandomSeed = function(test)
  198. local low, high = love.math.getRandomSeed()
  199. test:assertGreaterEqual(0, low, 'check random seed low')
  200. test:assertGreaterEqual(0, high, 'check random seed high')
  201. end
  202. -- love.math.getRandomState
  203. love.test.math.getRandomState = function(test)
  204. test:assertNotNil(love.math.getRandomState())
  205. end
  206. -- love.math.isConvex
  207. love.test.math.isConvex = function(test)
  208. local isconvex = love.math.isConvex({0, 0, 1, 0, 1, 1, 1, 0, 0, 0}) -- square
  209. local notconvex = love.math.isConvex({1, 2, 2, 4, 3, 4, 2, 1, 3, 1}) -- weird shape
  210. test:assertTrue(isconvex, 'check polygon convex')
  211. test:assertFalse(notconvex, 'check polygon not convex')
  212. end
  213. -- love.math.linearToGammer
  214. -- @NOTE I tried doing the same formula as the source from MathModule.cpp
  215. -- but get test failues due to slight differences
  216. love.test.math.linearToGamma = function(test)
  217. local gr, gg, gb = love.math.linearToGamma(1, 0.8, 0.001)
  218. --local eg = 1.055 * (0.8^1/2.4) - 0.055
  219. --local eb = 0.001 * 12.92
  220. test:assertGreaterEqual(0, gr, 'check linear r to gamme')
  221. test:assertGreaterEqual(0, gg, 'check linear g to gamme')
  222. test:assertGreaterEqual(0, gb, 'check linear b to gamme')
  223. end
  224. -- love.math.newBezierCurve
  225. -- @NOTE this is just basic nil checking, objs have their own test method
  226. love.test.math.newBezierCurve = function(test)
  227. test:assertObject(love.math.newBezierCurve({0, 0, 0, 1, 1, 1, 2, 1}))
  228. end
  229. -- love.math.newRandomGenerator
  230. -- @NOTE this is just basic nil checking, objs have their own test method
  231. love.test.math.newRandomGenerator = function(test)
  232. test:assertObject(love.math.newRandomGenerator())
  233. end
  234. -- love.math.newTransform
  235. -- @NOTE this is just basic nil checking, objs have their own test method
  236. love.test.math.newTransform = function(test)
  237. test:assertObject(love.math.newTransform())
  238. end
  239. -- love.math.perlinNoise
  240. love.test.math.perlinNoise = function(test)
  241. -- check some noise values
  242. -- output should be consistent if given the same input
  243. local noise1 = love.math.perlinNoise(100)
  244. local noise2 = love.math.perlinNoise(1, 10)
  245. local noise3 = love.math.perlinNoise(1043, 31.123, 999)
  246. local noise4 = love.math.perlinNoise(99.222, 10067, 8, 1843)
  247. test:assertRange(noise1, 0.5, 0.51, 'check noise 1 dimension')
  248. test:assertRange(noise2, 0.5, 0.51, 'check noise 2 dimensions')
  249. test:assertRange(noise3, 0.56, 0.57, 'check noise 3 dimensions')
  250. test:assertRange(noise4, 0.52, 0.53, 'check noise 4 dimensions')
  251. end
  252. -- love.math.simplexNoise
  253. love.test.math.simplexNoise = function(test)
  254. -- check some noise values
  255. -- output should be consistent if given the same input
  256. local noise1 = love.math.simplexNoise(100)
  257. local noise2 = love.math.simplexNoise(1, 10)
  258. local noise3 = love.math.simplexNoise(1043, 31.123, 999)
  259. local noise4 = love.math.simplexNoise(99.222, 10067, 8, 1843)
  260. -- rounded to avoid floating point issues
  261. test:assertRange(noise1, 0.5, 0.51, 'check noise 1 dimension')
  262. test:assertRange(noise2, 0.47, 0.48, 'check noise 2 dimensions')
  263. test:assertRange(noise3, 0.26, 0.27, 'check noise 3 dimensions')
  264. test:assertRange(noise4, 0.53, 0.54, 'check noise 4 dimensions')
  265. end
  266. -- love.math.random
  267. love.test.math.random = function(test)
  268. -- check some random ranges
  269. love.math.setRandomSeed(123)
  270. test:assertRange(love.math.random(), 0.37068322251462, 0.37068322251464, "check random algorithm")
  271. test:assertEquals(love.math.random(10), 4, "check single random param")
  272. test:assertEquals(love.math.random(15, 100), 92, "check two random params")
  273. end
  274. -- love.math.randomNormal
  275. love.test.math.randomNormal = function(test)
  276. love.math.setRandomSeed(1234)
  277. test:assertRange(love.math.randomNormal(1, 2), 1.0813614997253, 1.0813614997255, 'check randomNormal two params')
  278. end
  279. -- love.math.setRandomSeed
  280. -- @NOTE same with getRandomSeed, high is always 0 when I tested it?
  281. love.test.math.setRandomSeed = function(test)
  282. love.math.setRandomSeed(9001)
  283. local low, high = love.math.getRandomSeed()
  284. test:assertEquals(9001, low, 'check seed low set')
  285. test:assertEquals(0, high, 'check seed high set')
  286. end
  287. -- love.math.setRandomState
  288. love.test.math.setRandomState = function(test)
  289. -- check setting state matches value returned
  290. local rs1 = love.math.getRandomState()
  291. love.math.setRandomState(rs1)
  292. local rs2 = love.math.getRandomState()
  293. test:assertEquals(rs1, rs2, 'check random state set')
  294. end
  295. -- love.math.triangulate
  296. love.test.math.triangulate = function(test)
  297. local triangles1 = love.math.triangulate({0, 0, 1, 0, 1, 1, 1, 0, 0, 0}) -- square
  298. local triangles2 = love.math.triangulate({1, 2, 2, 4, 3, 4, 2, 1, 3, 1}) -- weird shape
  299. test:assertEquals(3, #triangles1, 'check polygon triangles')
  300. test:assertEquals(3, #triangles2, 'check polygon triangles')
  301. end