Advertisement
mrsimb

Vector library for Lua

Feb 10th, 2017
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.21 KB | None | 0 0
  1. -- Vector library by mrsimb
  2. Vector = {}           -- Vector namespace
  3. Vector.protomt = {}   -- Vector base metatable
  4. Vector.mt = {}        -- Vector derived objects metatable
  5.  
  6. -- to create new vectors by calling Vector object like self: a = Vector(1, 2, 3)
  7. function Vector.protomt.__call(t, x, y, z)
  8.   return Vector.new(x, y, z)
  9. end
  10.  
  11. -- [] operator (get)
  12. function Vector.mt:__index(k)
  13.   if (type(k) == 'number') then
  14.     if (k == 1) then return self.x
  15.     elseif (k == 2) then return self.y
  16.     elseif (k == 3) then return self.z
  17.     end
  18.   end
  19.   rawget(self, k)
  20. end
  21.  
  22. -- [] operator (set)
  23. function Vector.mt:__newindex(k, v)
  24.   if (type(k) == 'number') then
  25.     if (k == 1) then self.x = v
  26.     elseif (k == 2) then self.y = v
  27.     elseif (k == 3) then self.z = v
  28.     end
  29.   else
  30.     rawset(self, k, v)
  31.   end
  32. end
  33.  
  34. -- + operator
  35. function Vector.mt:__add(v)
  36.   return Vector.add(Vector.copy(self), v)
  37. end
  38.  
  39. -- - operator (binary)
  40. function Vector.mt:__sub(v)
  41.   return Vector.sub(Vector.copy(self), v)
  42. end
  43.  
  44. -- - operator (unary)
  45. function Vector.mt:__unm()
  46.   return Vector.new(-self.x, -self.y, -self.z)
  47. end
  48.  
  49. -- * operator
  50. function Vector.mt:__mul(n)
  51.   return Vector.mul(Vector.copy(self), n)
  52. end
  53.  
  54. -- / operator
  55. function Vector.mt:__div(n)
  56.   return Vector.div(Vector.copy(self), n)
  57. end
  58.  
  59. -- ^ operator
  60. function Vector.mt:__pow(n)
  61.   return Vector.pow(Vector.copy(self), n)
  62. end
  63.  
  64. -- == operator
  65. function Vector.mt:__eq(v)
  66.   return Vector.eq(self, v)
  67. end
  68.  
  69. -- < operator (compare magnitude)
  70. function Vector.mt:__lt(v)
  71.   return Vector.lt(self, v)
  72. end
  73.  
  74. -- <= operator (compare magnitude)
  75. function Vector.mt:__le(v)
  76.   return Vector.le(self, v)
  77. end
  78.  
  79. -- tostring()
  80. function Vector.mt:__tostring()
  81.   return Vector.toString(self)
  82. end
  83.  
  84. -- sets components of self vector to the given values
  85. -- you can pass array or another Vector
  86. function Vector:set(x, y, z)
  87.   if (type(x) == 'table') then
  88.     if (Vector.isVector(x)) then
  89.       self.x = x.x or 0
  90.       self.y = x.y or 0
  91.       self.y = x.z or 0
  92.       return self
  93.     end
  94.     self.x = x[1] or 0
  95.     self.y = x[2] or 0
  96.     self.z = x[3] or 0
  97.     return self
  98.   end
  99.   self.x = x or 0
  100.   self.y = y or 0
  101.   self.z = z or 0
  102.   return self
  103. end
  104.  
  105. -- returns copy of self vector
  106. function Vector:copy()
  107.   return Vector.new(self.x, self.y, self.z)
  108. end
  109.  
  110. -- returns string representation of self vector
  111. function Vector:toString()
  112.   return self.x .. ', ' .. self.y .. ', ' .. self.z
  113. end
  114. -- returns array with components of self vector
  115. function Vector:toArray()
  116.   return {self.x or 0, self.y or 0, self.z or 0}
  117. end
  118.  
  119. -- adds values to self vector and returns it
  120. -- you can pass array or another Vector
  121. function Vector:add(x, y, z)
  122.   if (type(x) == 'table') then
  123.     if (Vector.isVector(x)) then
  124.       self.x = self.x + (x.x or 0)
  125.       self.y = self.y + (x.y or 0)
  126.       self.y = self.y + (x.z or 0)
  127.       return self
  128.     end
  129.     self.x = self.x + (x[1] or 0)
  130.     self.y = self.y + (x[2] or 0)
  131.     self.z = self.z + (x[3] or 0)
  132.     return self
  133.   end
  134.   self.x = self.x + (x or 0)
  135.   self.y = self.y + (y or 0)
  136.   self.z = self.z + (z or 0)
  137.   return self
  138. end
  139.  
  140. -- substracts values from self vector and returns it
  141. -- you can pass array or another Vector
  142. function Vector:sub(x, y, z)
  143.   if (type(x) == 'table') then
  144.     if (Vector.isVector(x)) then
  145.       self.x = self.x - (x.x or 0)
  146.       self.y = self.y - (x.y or 0)
  147.       self.z = self.z - (x.z or 0)
  148.       return self
  149.     end
  150.     self.x = self.x - (x[1] or 0)
  151.     self.y = self.y - (x[2] or 0)
  152.     self.z = self.z - (x[3] or 0)
  153.     return self
  154.   end
  155.   self.x = self.x - (x or 0)
  156.   self.y = self.y - (y or 0)
  157.   self.z = self.z - (z or 0)
  158.   return self
  159. end
  160.  
  161. -- multiplicates self vector by given value and returns it
  162. function Vector:mul(n)
  163.   self.x = self.x * (n or 0)
  164.   self.y = self.y * (n or 0)
  165.   self.z = self.z * (n or 0)
  166.   return self
  167. end
  168.  
  169. -- divides self vector by given value and returns it
  170. function Vector:div(n)
  171.   self.x = self.x / (n or 0)
  172.   self.y = self.y / (n or 0)
  173.   self.z = self.z / (n or 0)
  174.   return self
  175. end
  176.  
  177. -- powers self vector by given value and returns it
  178. function Vector:pow(n)
  179.   self.x = self.x ^ (n or 0)
  180.   self.y = self.y ^ (n or 0)
  181.   self.z = self.z ^ (n or 0)
  182.   return self
  183. end
  184.  
  185. -- equality check againist self vector
  186. -- you can pass array or another Vector
  187. function Vector:eq(x, y, z)
  188.   local a, b, c
  189.   if (type(x) == 'table') then
  190.     if (Vector.isVector(x)) then
  191.       a = x.x or 0
  192.       b = x.y or 0
  193.       c = x.z or 0
  194.     else
  195.       a = x[1] or 0
  196.       b = x[2] or 0
  197.       c = x[3] or 0
  198.     end
  199.   else
  200.     a = x or 0
  201.     b = y or 0
  202.     c = z or 0
  203.   end
  204.   return self.x == a and self.y == b and self.z == c
  205. end
  206.  
  207. -- self vector's magnitude is less than value or another vector magnitude
  208. function Vector:lt(x, y, z)
  209.   if (type(x) == 'table') then
  210.     return Vector.mag(self) < Vector.mag(x)
  211.   end
  212.   return Vector.mag(self) < x
  213. end
  214.  
  215. -- self vector's magnitude is less or equals value or another vector magnitude
  216. function Vector:le(x, y, z)
  217.   if (type(x) == 'table') then
  218.     return Vector.mag(self) <= Vector.mag(x)
  219.   end
  220.   return Vector.mag(self) <= x
  221. end
  222.  
  223. -- returns magnitude (length) of self vector
  224. function Vector:mag()
  225.   return math.sqrt(Vector.magSq(self))
  226. end
  227.  
  228. -- returns squared magnitude (length) of self vector (faster)
  229. function Vector:magSq()
  230.   return self.x ^ 2 + self.y ^ 2 + self.z ^ 2
  231. end
  232.  
  233. -- returns distance beetween v and self vector
  234. function Vector:dist(v)
  235.   local d = Vector.distSq(self, v)
  236.   return math.sqrt(d)
  237. end
  238.  
  239. -- returns squared distance beetween v and self vector (faster)
  240. function Vector:distSq(v)
  241.   local d = Vector.sub(Vector.copy(self), v)
  242.   return Vector.magSq(d)
  243. end
  244.  
  245. -- returns cross product of v and self vector
  246. function Vector:cross(v)
  247.   return Vector.new(self.y * v.z - self.z * v.y, self.z * v.x - self.x * v.z, self.x * v.y - self.y * v.x)
  248. end
  249.  
  250. -- returns dot product of v and self vector
  251. function Vector:dot(v)
  252.   return self.x * v.x + self.y * v.y + self.z * v.z
  253. end
  254.  
  255. -- normalizes self vector and returns it
  256. function Vector:norm()
  257.   local m = Vector.mag(self)
  258.   if (m == 0) then
  259.     return self
  260.   end
  261.   return Vector.div(self, m)
  262. end
  263.  
  264. -- limits magnitude of self vector to max value and returns it
  265. function Vector:limit(max)
  266.   return Vector.mul(Vector.norm(self), max)
  267. end
  268.  
  269. -- returns angle of rotation for self vector (only 2D vectors)
  270. function Vector:angle()
  271.   return math.atan2(self.y, self.x)
  272. end
  273.  
  274. -- calculates and returns angle between two vectors
  275. function Vector:angleBetween(v)
  276.   return math.acos(Vector.dot(self, v) / (Vector.mag(self) * Vector.mag(v)))
  277. end
  278.  
  279. -- rotates self vector by angle (only 2D vectors) and returns it
  280. function Vector:rotate(a)
  281.   local na = Vector.angle(self) + a
  282.   local m = Vector.mag(self)
  283.   self.x = math.cos(na) * m
  284.   self.y = math.sin(na) * m
  285.   return self
  286. end
  287.  
  288. -- linear interpolation of self vector
  289. -- you can pass array or another Vector
  290. function Vector:lerp(x, y, z, n)
  291.   if (type(x) == 'table') then
  292.     if (Vector.isVector(x)) then
  293.       return self.lerp(self, x.x, x.y, x.z, y)
  294.     end
  295.     return self.lerp(self, x[1], x[2], x[3], y)
  296.   end
  297.   self.x = self.x + (x - self.x) * n
  298.   self.y = self.y + (y - self.y) * n
  299.   self.z = self.z + (z - self.z) * n
  300.   return self
  301. end
  302.  
  303. -- Static methods
  304.  
  305. -- returns new vector from given angle
  306. function Vector.fromAngle(a)
  307.   return Vector.new(math.cos(a), math.sin(a))
  308. end
  309.  
  310. -- returns 2D vector from random angle
  311. function Vector.random2d()
  312.   local a = math.random() * math.pi * 2;
  313.   return Vector.fromAngle(a)
  314. end
  315.  
  316. -- returns 3D vector from random angle
  317. function Vector.random3d()
  318.   local a = math.random() * math.pi * 2;
  319.   local vx = math.sqrt(1 - vz ^ 2) * math.cos(a);
  320.   local vy = math.sqrt(1 - vz ^ 2) * math.sin(a);
  321.   local vz = math.random() * 2 - 1;
  322.   return Vector.new(vx, vy, vz)
  323. end
  324.  
  325. -- checks if self is vector
  326. function Vector.isVector(self)
  327.   return getmetatable(self) == getmetatable(Vector)
  328. end
  329.  
  330. -- returns new vector from given values
  331. -- you can pass array or another Vector
  332. function Vector.new(x, y, z)
  333.   local this = {}
  334.  
  335.   if (type(x) == 'table') then
  336.     if (Vector.isVector(x)) then
  337.       this.x = x.x or 0
  338.       this.y = x.y or 0
  339.       this.y = x.z or 0
  340.     else
  341.       this.x = x[1] or 0
  342.       this.y = x[2] or 0
  343.       this.z = x[3] or 0
  344.     end
  345.   else
  346.     this.x = x or 0
  347.     this.y = y or 0
  348.     this.z = z or 0
  349.   end
  350.  
  351.   this.set = Vector.set
  352.   this.copy = Vector.copy
  353.   this.toString = Vector.toString
  354.   this.toArray = Vector.toArray
  355.   this.add = Vector.add
  356.   this.sub = Vector.sub
  357.   this.mul = Vector.mul
  358.   this.div = Vector.div
  359.   this.eq = Vector.eq
  360.   this.lt = Vector.lt
  361.   this.le = Vector.le
  362.   this.mag = Vector.mag
  363.   this.magSq = Vector.magSq
  364.   this.dist = Vector.dist
  365.   this.distSq = Vector.distSq
  366.   this.cross = Vector.cross
  367.   this.dot = Vector.dot
  368.   this.norm = Vector.norm
  369.   this.limit = Vector.limit
  370.   this.angle = Vector.angle
  371.   this.angleBetween = Vector.angleBetween
  372.   this.rotate = Vector.rotate
  373.   this.lerp = Vector.lerp
  374.  
  375.   -- set Vector childrens metatable
  376.   setmetatable(this, Vector.mt)
  377.  
  378.   return this
  379. end
  380.  
  381. -- set base Vector parent metatable
  382. setmetatable(Vector, Vector.protomt)
  383. -- Vector library by mrsimb
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement