qsenko1

damn

Jul 29th, 2021
1,036
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --By xXxMoNkEyMaNxXx elsez
  2. --Roblox Lua
  3. local type=type
  4. local getmetatable=getmetatable
  5. local setmetatable=setmetatable
  6.  
  7. local pi=math.pi
  8. local tau=2*pi
  9. local sqrt=math.sqrt
  10. local atan2=math.atan2
  11. local exp,log=math.exp,math.log
  12. local cos,sin=math.cos,math.sin
  13. local acos,asin=math.acos,math.asin
  14.  
  15. local function TYPE(x)
  16.     local xMet=getmetatable(x)
  17.     if type(xMet)=="table" and xMet.__type~=nil then
  18.         return xMet.__type
  19.     else
  20.         return type(x)
  21.     end
  22. end
  23.  
  24. local Q={}
  25. local metatable={__type="quaternion"}
  26. local alt={"w","x","y","z"}
  27. function metatable.__index(q,i)
  28.     return q[alt[i]]
  29. end
  30. local function new(w,x,y,z)
  31.     return setmetatable({w=w or 1,x=x or 0,y=y or 0,z=z or 0},metatable)
  32. end
  33. Q.new=new
  34. local function inv(q)
  35.     local w,x,y,z=q.w,q.x,q.y,q.z
  36.     local m=w*w+x*x+y*y+z*z
  37.     if m>0 then
  38.         return new(w/m,-x/m,-y/m,-z/m)
  39.     else
  40.         return new(0)
  41.     end
  42. end
  43. Q.inv=inv
  44.  
  45. --Unary minus; -q
  46. local function unm(q)
  47.     return new(-q.w,-q.x,-q.y,-q.z)
  48. end
  49. metatable.__unm=unm
  50. Q.unm=unm
  51. local function add(q0,q1)
  52.     local t0,t1=TYPE(q0),TYPE(q1)
  53.     if t0=="quaternion" and t1=="quaternion" then
  54.         return new(q0.w+q1.w,q0.x+q1.x,q0.y+q1.y,q0.z+q1.z)
  55.     elseif t0=="quaternion" and t1=="number" then
  56.         return new(q0.w+q1,q0.x,q0.y,q0.z)
  57.     elseif t0=="number" and t1=="quaternion" then
  58.         return new(q0+q1.w,q1.x,q1.y,q1.z)
  59.     end
  60. end
  61. metatable.__add=add
  62. Q.add=add
  63. local function sub(q0,q1)
  64.     local t0,t1=TYPE(q0),TYPE(q1)
  65.     if t0=="quaternion" and t1=="quaternion" then
  66.         return new(q0.w-q1.w,q0.x-q1.x,q0.y-q1.y,q0.z-q1.z)
  67.     elseif t0=="quaternion" and t1=="number" then
  68.         return new(q0.w-q1,q0.x,q0.y,q0.z)
  69.     elseif t0=="number" and t1=="quaternion" then
  70.         return new(q0-q1.w,-q1.x,-q1.y,-q1.z)
  71.     end
  72. end
  73. metatable.__sub=sub
  74. Q.sub=sub
  75. local function mul(q0,q1)
  76.     local t0,t1=TYPE(q0),TYPE(q1)
  77.     if t0=="quaternion" and t1=="quaternion" then
  78.         local w0,x0,y0,z0,w1,x1,y1,z1=q0.w,q0.x,q0.y,q0.z,q1.w,q1.x,q1.y,q1.z
  79.         return new(w0*w1-x0*x1-y0*y1-z0*z1,w0*x1+x0*w1+y0*z1-z0*y1,w0*y1-x0*z1+y0*w1+z0*x1,w0*z1+x0*y1-y0*x1+z0*w1)
  80.     elseif t0=="quaternion" and t1=="number" then
  81.         return new(q0.w*q1,q0.x*q1,q0.y*q1,q0.z*q1)
  82.     elseif t0=="number" and t1=="quaternion" then
  83.         return new(q0*q1.w,q0*q1.x,q0*q1.y,q0*q1.z)
  84.     end
  85. end
  86. metatable.__mul=mul
  87. Q.mul=mul
  88. local function div(q0,q1)
  89.     local t0,t1=TYPE(q0),TYPE(q1)
  90.     if t0=="quaternion" and t1=="quaternion" then
  91.         local w0,x0,y0,z0,w1,x1,y1,z1=q0.w,q0.x,q0.y,q0.z,q1.w,q1.x,q1.y,q1.z
  92.         local m1=w1*w1+x1*x1+y1*y1+z1*z1
  93.         if m1>0 then--This is the quaternion that gets you from q1 to q0 from q1: mul(inv(q1),q0).  (quaternion division is actually ambiguous)
  94.             return new((w1*w0+x1*x0+y1*y0+z1*z0)/m1,(w1*x0-x1*w0-y1*z0+z1*y0)/m1,(w1*y0+x1*z0-y1*w0-z1*x0)/m1,(w1*z0-x1*y0+y1*x0-z1*w0)/m1)
  95.         else
  96.             return new(0)
  97.         end
  98.     elseif t0=="quaternion" and t1=="number" then
  99.         return new(q0.w/q1,q0.x/q1,q0.y/q1,q0.z/q1)
  100.     elseif t0=="number" and t1=="quaternion" then
  101.         local w1,x1,y1,z1=q1.w,q1.x,q1.y,q1.z
  102.         local m1=w1*w1+x1*x1+y1*y1+z1*z1
  103.         if m1>0 then
  104.             local m=q0/m1
  105.             return new(m*w1,-m*x1,-m*y1,-m*z1)
  106.         else
  107.             return new(0)
  108.         end
  109.     end
  110. end
  111. metatable.__div=div
  112. Q.div=div
  113. local function pow(q0,q1)
  114.     local t0,t1=TYPE(q0),TYPE(q1)
  115.     if t0=="quaternion" and t1=="quaternion" then
  116.         local w0,x0,y0,z0=q0.w,q0.x,q0.y,q0.z
  117.         local vv=x0*x0+y0*y0+z0*z0
  118.         local mm=w0*w0+vv
  119.         if mm>0 then
  120.             if vv>0 then
  121.                 local m=sqrt(mm)
  122.                 local s=acos(w0/m)/sqrt(vv)
  123.                 w0,x0,y0,z0=log(m),x0*s,y0*s,z0*s
  124.             else
  125.                 w0,x0,y0,z0=0.5*log(mm),0,0,0
  126.             end
  127.         else
  128.             w0,x0,y0,z0=-math.huge,0,0,0
  129.         end
  130.         local w1,x1,y1,z1=q1.w,q1.x,q1.y,q1.z
  131.         local m=exp(w0*w1-x0*x1-y0*y1-z0*z1)
  132.         local x,y,z=w0*x1+x0*w1+y0*z1-z0*y1,w0*y1-x0*z1+y0*w1+z0*x1,w0*z1+x0*y1-y0*x1+z0*w1
  133.         local vv=x*x+y*y+z*z
  134.         if vv>0 then
  135.             local v=sqrt(vv)
  136.             local s=m*sin(v)/v
  137.             return new(m*cos(v),x*s,y*s,z*s)
  138.         else
  139.             return new(m)
  140.         end
  141.     elseif t0=="quaternion" and t1=="number" then
  142.         local w,x,y,z=q0.w,q0.x,q0.y,q0.z
  143.         local vv=x*x+y*y+z*z
  144.         if vv>0 then
  145.             local v=sqrt(vv)
  146.             local m=(w*w+vv)^(0.5*q1)
  147.             local theta=q1*atan2(v,w)
  148.             local s=m*sin(theta)/v
  149.             return new(m*cos(theta),x*s,y*s,z*s)
  150.         else
  151.             if w<0 then
  152.                 local m=(-w)^q1
  153.                 local s=m*sin(pi*q1)*0.57735026918962576450914878050196--3^-0.5
  154.                 return new(m*cos(pi*q1),s,s,s)
  155.             else
  156.                 return new(w^q1)
  157.             end
  158.         end
  159.     elseif t0=="number" and t1=="quaternion" then
  160.         local w,x,y,z=q1.w,q1.x,q1.y,q1.z
  161.         if q0>0 then
  162.             local m=q0^w
  163.             local vv=x*x+y*y+z*z
  164.             if vv>0 then
  165.                 local v=sqrt(vv)
  166.                 local s=m*sin(v)/v
  167.                 return new(m*cos(v),x*s,y*s,z*s)
  168.             else
  169.                 return new(m)
  170.             end
  171.         elseif q0<0 then--Not a good idea to use this.
  172.             local m=(-q0)^w
  173.             local mc,ms=m*cos(pi*w),m*sin(pi*w)
  174.             local vv=x*x+y*y+z*z
  175.             if vv>0 then
  176.                 local v=sqrt(vv)
  177.                 local c,s=cos(v),sin(v)/v
  178.                 local vc,vs=mc*s,ms*c*0.57735026918962576450914878050196
  179.                 return new(mc*c-ms*s,vc*x+vs,vc*y+vs,vc*z+vs)--This is probably TERRIBLY wrong, but raising a negative number to the power of a quaternion is ill-defined in the first place.
  180.             else
  181.                 return new(c,s,s,s)
  182.             end
  183.         elseif w*w+x*x+y*y+z*z>0 then
  184.             return new(0)
  185.         else
  186.             return new()--anyeting to da powa of 0 is 1 dud
  187.         end
  188.     end
  189. end
  190. metatable.__pow=pow
  191. Q.pow=pow
  192. local function length(q)
  193.     local w,x,y,z=q.w,q.x,q.y,q.z
  194.     return sqrt(w*w+x*x+y*y+z*z)
  195. end
  196. metatable.__len=length
  197. Q.length=length
  198. Q.magnitude=length
  199. local function Qtostring(q,precision)
  200.     precision=precision or 3
  201.     return (", %."..precision.."f"):rep(4):sub(3):format(q.w,q.x,q.y,q.z)
  202. end
  203. metatable.__tostring=Qtostring
  204. Q.tostring=Qtostring
  205.  
  206. local function Qlog(q)
  207.     local w,x,y,z=q.w,q.x,q.y,q.z
  208.     local vv=x*x+y*y+z*z
  209.     local mm=w*w+vv
  210.     if mm>0 then
  211.         if vv>0 then
  212.             local m=sqrt(mm)
  213.             local s=acos(w/m)/sqrt(vv)
  214.             return new(log(m),x*s,y*s,z*s)
  215.         else
  216.             return new(0.5*log(mm))--lim v->0 x/v*acos(a/sqrt(a*a+v*v))=0 when a is positive
  217.         end
  218.     else
  219.         return new(-math.huge)
  220.     end
  221. end
  222. Q.log=Qlog
  223.  
  224. local function Qexp(q)
  225.     local m=exp(q.w)
  226.     local x,y,z=q.x,q.y,q.z
  227.     local vv=x*x+y*y+z*z
  228.     if vv>0 then
  229.         local v=sqrt(vv)
  230.         local s=m*sin(v)/v
  231.         return new(m*cos(v),x*s,y*s,z*s)
  232.     else
  233.         return new(m)
  234.     end
  235. end
  236. Q.exp=Qexp
  237.  
  238. local function Qnormalize(q)
  239.     local w,x,y,z=q.w,q.x,q.y,q.z
  240.     local mm=w*w+x*x+y*y+z*z
  241.     if mm>0 then
  242.         local m=sqrt(mm)
  243.         return new(w/m,x/m,y/m,z/m)
  244.     else
  245.         return new()
  246.     end
  247. end
  248. Q.normalize=Qnormalize
  249. Q.unit=Qnormalize
  250.  
  251. return Q
  252.  
RAW Paste Data