Advertisement
okpalan

vacuum.lua

Nov 9th, 2023 (edited)
499
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.59 KB | Source Code | 0 0
  1. // https://github.com/codewithnnamdi/vacuum
  2. // vacuum-1.lua - A numerica computation library for building games.
  3. // TODO:handle inputs as well
  4.  
  5. local matrix = {}
  6.  
  7. function matrix:new(n,m)
  8.     -- Create a new matrix
  9.     local matt = {}
  10.     for i = 1, n do
  11.         matt[i] = {}
  12.         for j = 1, m do
  13.             matt[i][j] = 0
  14.         end
  15.     end
  16.     setmetatable(matt, self)
  17.     self.__index = self
  18.     return matt
  19. end
  20.  
  21. function matrix:__tostring()
  22.     -- Print a matrix
  23.     local str = ""
  24.     for i = 1, #self do
  25.         for j = 1, #self[i] do
  26.             str = str .. self[i][j] .. " "
  27.         end
  28.         str = str .. "" .. "" .. ""
  29.     end
  30.     return str
  31. end
  32.  
  33. function matrix:__add(other)
  34.     -- Add two matrices
  35.     local matt = matrix:new(#self, #self[1])
  36.     for i = 1, #self do
  37.         for j = 1, #self[i] do
  38.             matt[i][j] = self[i][j] + other[i][j]
  39.         end
  40.     end
  41.     return matt
  42. end
  43.  
  44. function matrix:__sub(other)
  45.     -- Subtract two matrices
  46.     local matt = matrix:new(#self, #self[1])
  47.     for i = 1, #self do
  48.         for j = 1, #self[i] do
  49.             matt[i][j] = self[i][j] - other[i][j]
  50.         end
  51.     end
  52.     return matt
  53. end
  54.  
  55. function matrix:__mul(other)
  56.     -- Multiply two matrices
  57.     local matt = matrix:new(#self, #self[1])
  58.     for i = 1, #self do
  59.         for j = 1, #self[i] do
  60.             matt[i][j] = self[i][j] * other[i][j]
  61.         end
  62.     end
  63.     return matt
  64. end
  65.  
  66. function matrix:__div(other)
  67.     -- Divide two matrices
  68.     local matt = matrix:new(#self, #self[1])
  69.     for i = 1, #self do
  70.         for j = 1, #self[i] do
  71.             matt[i][j] = self[i][j] / other[i][j]
  72.         end
  73.     end
  74.     return matt
  75. end
  76.  
  77. function matrix:__unm()
  78.     -- Unary minus
  79.     local matt = matrix:new(#self, #self[1])
  80.     for i = 1, #self do
  81.         for j = 1, #self[i] do
  82.             matt[i][j] = -self[i][j]
  83.         end
  84.     end
  85.     return matt
  86. end
  87.  
  88. function matrix:__eq(other)
  89.     -- Check if two matrices are equal
  90.     for i = 1, #self do
  91.         for j = 1, #self[i] do
  92.             if self[i][j] ~= other[i][j] then
  93.                 return false
  94.             end
  95.         end
  96.     end
  97.     return true
  98. end
  99.  
  100. function matrix:__lt(other)
  101.     -- Check if one matrix is less than another
  102.     for i = 1, #self do
  103.         for j = 1, #self[i] do
  104.             if self[i][j] >= other[i][j] then
  105.                 return false
  106.             end
  107.         end
  108.     end
  109.     return true
  110. end
  111.  
  112. function matrix:__le(other)
  113.     -- Check if one matrix is less than or equal to another
  114.     for i = 1, #self do
  115.         for j = 1, #self[i] do
  116.             if self[i][j] > other[i][j] then
  117.                 return false
  118.             end
  119.         end
  120.     end
  121.     return true
  122. end
  123.  
  124. function matrix:__pow(other)
  125.     -- Raise a matrix to a power
  126.     local matt = matrix:new(#self, #self[1])
  127.     for i = 1, #self do
  128.         for j = 1, #self[i] do
  129.             matt[i][j] = self[i][j] ^ other[i][j]
  130.         end
  131.     end
  132.     return matt
  133. end
  134.  
  135. function matrix:__mod(other)
  136.     -- Modulo a matrix
  137.     local matt = matrix:new(#self, #self[1])
  138.     for i = 1, #self do
  139.         for j = 1, #self[i] do
  140.             matt[i][j] = self[i][j] % other[i][j]
  141.         end
  142.     end
  143.     return matt
  144. end
  145.  
  146. function matrix:__concat(other)
  147.     -- Concatenate two matrices
  148.     local matt = matrix:new(#self, #self[1])
  149.     for i = 1, #self do
  150.         for j = 1, #self[i] do
  151.             matt[i][j] = self[i][j] .. other[i][j]
  152.         end
  153.     end
  154.     return matt
  155. end
  156.  
  157. function matrix:__len()
  158.     -- Get the length of a matrix
  159.     return #self * #self[1]
  160. end
  161.  
  162. function matrix:__call(...)
  163.     -- Call a matrix
  164.     local matt = matrix:new(#self, #self[1])
  165.     for i = 1, #self do
  166.         for j = 1, #self[i] do
  167.             matt[i][j] = self[i][j](...)
  168.         end
  169.     end
  170.     return matt
  171. end
  172.  
  173. function matrix:__index(key)
  174.     -- Get a matrix element
  175.     return self[key[1]][key[2]]
  176. end
  177.  
  178. function matrix:__newindex(key, value)
  179.     -- Set a matrix element
  180.     self[key[1]][key[2]] = value
  181. end
  182.  
  183. function matrix:__pairs()
  184.     -- Iterate over a matrix
  185.     local i = 0
  186.     local j = 0
  187.     return function()
  188.         i = i + 1
  189.         if i > #self then
  190.             i = 1
  191.             j = j + 1
  192.         end
  193.         if j > #self[1] then
  194.             return nil
  195.         end
  196.         return {i, j}, self[i][j]
  197.     end
  198. end
  199.  
  200. local vec2 = {}
  201.  
  202. function vec2:new(x, y)
  203.     local o = {x = x or 0, y = y or 0}
  204.     setmetatable(o, self)
  205.     self.__index = self
  206.     return o
  207. end
  208.  
  209. function vec2:__tostring()
  210.     return "(" .. self.x .. ", " .. self.y .. ")"
  211. end
  212.  
  213. function vec2:__add(other)
  214.     return vec2:new(self.x + other.x, self.y + other.y)
  215. end
  216.  
  217. function vec2:__sub(other)
  218.     return vec2:new(self.x - other.x, self.y - other.y)
  219. end
  220.  
  221. function vec2:__mul(other)
  222.     return vec2:new(self.x * other, self.y * other)
  223. end
  224.  
  225. function vec2:__div(other)
  226.     return vec2:new(self.x / other, self.y / other)
  227. end
  228.  
  229. -- unary minus
  230. function vec2:__unm()
  231.     return vec2:new(-self.x, -self.y)
  232. end
  233.  
  234. function vec2:__eq(other)
  235.     return self.x == other.x and self.y == other.y
  236. end
  237.  
  238. function vec2:__lt(other)
  239.     return self.x < other.x and self.y < other.y
  240. end
  241.  
  242. function vec2:__le(other)
  243.     return self.x <= other.x and self.y <= other.y
  244. end
  245.  
  246. function vec2:__len()
  247.     return math.sqrt(self.x * self.x + self.y * self.y)
  248. end
  249.  
  250. function vec2:__call(x, y)
  251.     self.x = x
  252.     self.y = y
  253. end
  254.  
  255. function vec2:clone()
  256.     return vec2:new(self.x, self.y)
  257. end
  258.  
  259. function vec2:unpack()
  260.     return self.x, self.y
  261. end
  262.  
  263. function vec2:rotate(angle)
  264.     local c = math.cos(angle)
  265.     local s = math.sin(angle)
  266.     self.x, self.y = self.x * c - self.y * s, self.x * s + self.y * c
  267. end
  268.  
  269. function vec2:normalized()
  270.     local len = #self
  271.     return vec2:new(self.x / len, self.y / len)
  272. end
  273.  
  274. function vec2:normalize_inplace()
  275.     local len = #self
  276.     self.x = self.x / len
  277.     self.y = self.y / len
  278. end
  279.  
  280. function vec2:perpendicular()
  281.     return vec2:new(-self.y, self.x)
  282. end
  283.  
  284. function vec2:dot(other)
  285.     return self.x * other.x + self.y * other.y
  286. end
  287.  
  288. function vec2:cross(other)
  289.     return self.x * other.y - self.y * other.x
  290. end
  291.  
  292. function vec2:project_on(other)
  293.     local k = self:dot(other) / other:dot(other)
  294.     return vec2:new(other.x * k, other.y * k)
  295. end
  296.  
  297.  
  298. local vec3 = {}
  299.  
  300. function vec3:new(x, y, z)
  301.     local o = {x = x or 0, y = y or 0, z = z or 0}
  302.     setmetatable(o, self)
  303.     self.__index = self
  304.     return o
  305. end
  306.  
  307. function vec3:__tostring()
  308.     return "(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")"
  309. end
  310.  
  311. function vec3:__add(other)
  312.     return vec3:new(self.x + other.x, self.y + other.y, self.z + other.z)
  313. end
  314.  
  315. function vec3:__sub(other)
  316.     return vec3:new(self.x - other.x, self.y - other.y, self.z - other.z)
  317. end
  318.  
  319. function vec3:__mul(other)
  320.     return vec3:new(self.x * other, self.y * other, self.z * other)
  321. end
  322.  
  323. function vec3:__div(other)
  324.     return vec3:new(self.x / other, self.y / other, self.z / other)
  325. end
  326.  
  327. -- unary minus
  328. function vec3:__unm()
  329.     return vec3:new(-self.x, -self.y, -self.z)
  330. end
  331.  
  332. function vec3:__eq(other)
  333.     return self.x == other.x and self.y == other.y and self.z == other.z
  334. end
  335.  
  336. function vec3:__lt(other)
  337.     return self.x < other.x and self.y < other.y and self.z < other.z
  338. end
  339.  
  340. -- less than or equal
  341. function vec3:__le(other)
  342.     return self.x <= other.x and self.y <= other.y and self.z <= other.z
  343. end
  344.  
  345. function vec3:__len()
  346.     return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
  347. end
  348.  
  349.  
  350.  
  351. function vec3:__call(x, y, z)
  352.     self.x = x
  353.     self.y = y
  354.     self.z = z
  355. end
  356.  
  357. function vec3:clone()
  358.     return vec3:new(self.x, self.y, self.z)
  359. end
  360.  
  361. function vec3:unpack()
  362.     return self.x, self.y, self.z
  363. end
  364.  
  365. function  vec3:rotatex(theta)    
  366.     local c = math.cos(theta)
  367.     local s = math.sin(theta)
  368.     self.y, self.z = self.y * c - self.z * s, self.y * s + self.z * c
  369. end
  370.  
  371. function  vec3:rotatey(theta)    
  372.     local c = math.cos(theta)
  373.     local s = math.sin(theta)
  374.     self.x, self.z = self.x * c - self.z * s, self.x * s + self.z * c
  375. end
  376.  
  377. function  vec3:rotatez(theta)    
  378.     local c = math.cos(theta)
  379.     local s = math.sin(theta)
  380.     self.x, self.y = self.x * c - self.y * s, self.x * s + self.y * c
  381. end
  382.  
  383. function vec3:normalized()
  384.     local len = #self
  385.     return vec3:new(self.x / len, self.y / len, self.z / len)
  386. end
  387.  
  388. function vec3:normalize_inplace()
  389.     local len = #self
  390.     self.x = self.x / len
  391.     self.y = self.y / len
  392.     self.z = self.z / len
  393. end
  394.  
  395. local vec4 = {}
  396.  
  397. function vec4:new(x, y, z, w)
  398.     -- use a vec3 as a base
  399.     local o = vec3:new(x, y, z)
  400.     o.w = w or 0
  401.     setmetatable(o, self)
  402.     self.__index = self
  403.     return o
  404. end
  405.  
  406.  
  407.  
  408. local vector = { vec2 = vec2, vec3 = vec3, vec4 = vec4 }
  409. local mt = {
  410.     -- abstract call method in a metatable
  411.     __call = function(_, ...)
  412.         local n = select("#", ...)
  413.         return vmt[n](...)
  414.     end
  415. }
  416.  
  417. setmetatable(vector, mt)
  418.  
  419. return vector
  420. -- destructuring assignment for namespace
  421. local vec2, vec3, vec4 = vector.vec2, vector.vec3, vector.vec4
  422. -- Quaternion class
  423.  
  424.  
  425. local Quaternion = {};
  426.  
  427.  
  428. function Quaternion:new(x, y, z, w)
  429.     -- a Quaternion is a 4D vector
  430.     -- - inherits from vec4
  431.     local o = vec4:new(x, y, z,w)
  432.     setmetatable(o, self)
  433.     self.__index = self
  434.     return o
  435. end
  436.  
  437. function Quaternion:__tostring()
  438.     return "(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ", " .. self.w .. ")"
  439. end
  440.  
  441.  
  442. function Quaternion:__mul(other)
  443.     -- Quaternion multiplication
  444.     -- is not commutative
  445.     -- (a * b) != (b * a)
  446.     return Quaternion:new(
  447.         self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
  448.         self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.x,
  449.         self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w,
  450.         self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z
  451.     )
  452. end
  453.  
  454. function Quaternion:__div(other)
  455.     -- Quaternion division
  456.     -- is not commutative
  457.     -- (a / b) != (b / a)
  458.     return Quaternion:new(
  459.         self.w * other.x - self.x * other.w - self.y * other.z + self.z * other.y,
  460.         self.w * other.y + self.x * other.z - self.y * other.w - self.z * other.x,
  461.         self.w * other.z - self.x * other.y + self.y * other.x - self.z * other.w,
  462.         self.w * other.w + self.x * other.x + self.y * other.y + self.z * other.z
  463.     )
  464. end
  465.  
  466. function Quaternion:__unm()
  467.     -- Quaternion negation
  468.     return Quaternion:new(-self.x, -self.y, -self.z, -self.w)
  469. end
  470.  
  471. function Quaternion:__eq(other)
  472.     return self.x == other.x and self.y == other.y and self.z == other.z and self.w == other.w
  473. end
  474.  
  475. function Quaternion:conjugate()
  476.     -- Quaternion conjugate
  477.     return Quaternion:new(-self.x, -self.y, -self.z, self.w)
  478. end
  479.  
  480. function Quaternion:inverse()
  481.     -- Quaternion inverse
  482.     return self:conjugate() / self:dot(self)
  483. end
  484.  
  485. function Quaternion:dot(other)
  486.     -- Quaternion dot product
  487.     return self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w
  488. end
  489.  
  490. function Quaternion:normalize()
  491.     -- Quaternion normalization
  492.     local len = self:dot(self)
  493.     self.x = self.x / len
  494.     self.y = self.y / len
  495.     self.z = self.z / len
  496.     self.w = self.w / len
  497. end
  498.  
  499.  
  500. function Quaternion:rotate_vector(vector)
  501.     -- Rotate a vector by a quaternion
  502.     -- (q * v * q^-1)
  503.     return (self * Quaternion:new(vector.x, vector.y, vector.z, 0) * self:inverse()).xyz
  504. end
  505.  
  506. function Quaternion:rotate_point(point)
  507.     -- Rotate a point by a quaternion
  508.     -- (q * p * q^-1)
  509.     return (self * Quaternion:new(point.x, point.y, point.z, 0) * self:inverse()).xyz
  510. end
  511.  
  512. function Quaternion:rotate_quaternion(quaternion)
  513.     -- Rotate a quaternion by a quaternion
  514.     -- (q * r * q^-1)
  515.     return self * quaternion * self:inverse()
  516. end
  517.  
  518. function Quaternion:from_axis_angle(axis, angle)
  519.     -- Create a quaternion from an axis and an angle
  520.     local half_angle = angle / 2
  521.     local sin = math.sin(half_angle)
  522.     self.x = axis.x * sin
  523.     self.y = axis.y * sin
  524.     self.z = axis.z * sin
  525.     self.w = math.cos(half_angle)
  526. end
  527.  
  528. function Quaternion:from_euler_angles(roll, pitch, yaw)
  529.     -- Create a quaternion from euler angles
  530.     local cr = math.cos(roll / 2)
  531.     local cp = math.cos(pitch / 2)
  532.     local cy = math.cos(yaw / 2)
  533.     local sr = math.sin(roll / 2)
  534.     local sp = math.sin(pitch / 2)
  535.     local sy = math.sin(yaw / 2)
  536.     self.x = sr * cp * cy - cr * sp * sy
  537.     self.y = cr * sp * cy + sr * cp * sy
  538.     self.z = cr * cp * sy - sr * sp * cy
  539.     self.w = cr * cp * cy + sr * sp * sy
  540. end
  541.  
  542. function Quaternion:to_axis_angle()
  543.     -- Convert a quaternion to an axis and an angle
  544.     local axis = vec3:new(self.x, self.y, self.z)
  545.     local angle = 2 * math.acos(self.w)
  546.     axis:normalize()
  547.     return axis, angle
  548. end
  549.  
  550. function Quaternion:to_euler_angles()
  551.     -- Convert a quaternion to euler angles
  552.     local roll = math.atan2(2 * (self.w * self.x + self.y * self.z), 1 - 2 * (self.x * self.x + self.y * self.y))
  553.     local pitch = math.asin(2 * (self.w * self.y - self.z * self.x))
  554.     local yaw = math.atan2(2 * (self.w * self.z + self.x * self.y), 1 - 2 * (self.y * self.y + self.z * self.z))
  555.     return roll, pitch, yaw
  556. end
  557.  
  558. function Quaternion:to_matrix()
  559.     -- Convert a quaternion to a matrix
  560.     local matrix = Matrix:new()
  561.     matrix[1][1] = 1 - 2 * (self.y * self.y + self.z * self.z)
  562.     matrix[1][2] = 2 * (self.x * self.y + self.z * self.w)
  563.     matrix[1][3] = 2 * (self.x * self.z - self.y * self.w)
  564.     matrix[2][1] = 2 * (self.x * self.y - self.z * self.w)
  565.     matrix[2][2] = 1 - 2 * (self.x * self.x + self.z * self.z)
  566.     matrix[2][3] = 2 * (self.y * self.z + self.x * self.w)
  567.     matrix[3][1] = 2 * (self.x * self.z + self.y * self.w)
  568.     matrix[3][2] = 2 * (self.y * self.z - self.x * self.w)
  569.     matrix[3][3] = 1 - 2 * (self.x * self.x + self.y * self.y)
  570.     return matrix
  571. end
  572.  
  573. function Quaternion:to_string()
  574.     -- Convert a quaternion to a string
  575.     return string.format("Quaternion(%f, %f, %f, %f)", self.x, self.y, self.z, self.w)
  576. end
  577.  
  578. function Quaternion:to_table()
  579.     -- Convert a quaternion to a table
  580.     return {self.x, self.y, self.z, self.w}
  581. end
  582.  
  583.  
  584.  
  585. function Quaternion:to_vec3()
  586.     -- Convert a quaternion to a vec3
  587.     return vec3:new(self.x, self.y, self.z)
  588. end
  589.  
  590. function Quaternion:to_vec2()
  591.     -- Convert a quaternion to a vec2
  592.     return vec2:new(self.x, self.y)
  593. end
  594.  
  595. function Quaternion:to_vec4()
  596.     -- Convert a quaternion to a vec4
  597.     return vec4:new(self.x, self.y, self.z, self.w)
  598. end
  599.  
  600. return Quaternion
  601.  
Tags: vacuum
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement