Guest User

pam.lua

a guest
Dec 9th, 2016
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.91 KB | None | 0 0
  1. -- Polygonal Animated Model library
  2. -- by Xytabich
  3. -- types 0-31 is reserved, please, don't use their
  4.  
  5. local fs = require("filesystem")
  6.  
  7. local function grab_byte(v)
  8.       return math.floor(v / 256), string.char(math.floor(v) % 256)
  9. end
  10.  
  11. pam = {}
  12.  
  13. pam.float2str = function(x)
  14.    local sign = 0
  15.    if x < 0 then
  16.      sign = 1
  17.      x = -x
  18.    end
  19.    local mantissa, exponent = math.frexp(x)
  20.    if x == 0 then
  21.       mantissa = 0
  22.       exponent = 0
  23.    else
  24.       mantissa = (mantissa * 2 - 1) * 8388608
  25.       exponent = exponent + 126
  26.    end
  27.    local v, byte = ""
  28.    x, byte = grab_byte(mantissa); v = v..byte
  29.    x, byte = grab_byte(x); v = v..byte
  30.    x, byte = grab_byte(exponent * 128 + x); v = v..byte
  31.    x, byte = grab_byte(sign * 128 + x); v = v..byte
  32.    return v
  33. end
  34.  
  35. pam.str2float = function(x)
  36.   local sign = 1
  37.   local mantissa = string.byte(x, 3) % 128
  38.  
  39.   for i = 2, 1, -1 do mantissa = mantissa * 256 + string.byte(x, i) end
  40.   if string.byte(x, 4) > 127 then sign = -1 end
  41.   local exponent = (string.byte(x, 4) % 128) * 2 + math.floor(string.byte(x, 3) / 128)
  42.   if exponent == 0 then return 0 end
  43.   mantissa = (math.ldexp(mantissa, -23) + 1) * sign
  44.   return math.ldexp(mantissa, exponent - 127)
  45. end
  46.  
  47. pam.int2str = function(n)
  48.   n = (n < 0) and (4294967296 + n) or n
  49.   return string.char((math.modf(n/16777216))%256, (math.modf(n/65536))%256, (math.modf(n/256))%256, n%256)
  50. end
  51.  
  52. pam.str2int = function(x)
  53.   b1, b2, b3, b4 = string.byte(x, 1, 4)
  54.   local n = b1*16777216 + b2*65536 + b3*256 + b4
  55.   n = (n > 2147483647) and (n - 4294967296) or n
  56.   return n
  57. end
  58.  
  59. pam.type = 0
  60. pam.vertexes = {}
  61. pam.triangles = {} -- x,y,z, string color(use string.byte() to decode)
  62. pam.vertexFrames = {}
  63. pam.paletteFrames = {}
  64.  
  65. -- modules
  66. pam.additionalModules = {}
  67. pam.modulesData = {}
  68.  
  69. pam.addModule = function(m)
  70.   if (m == nil) or (m.name == nil) or ((m.pack == nil) and (m.unpack == nil)) then
  71.     return false
  72.   end
  73.  
  74.   table.insert(pam.additionalModules, m)
  75.  
  76.   return true
  77. end
  78.  
  79. pam.removeModule = function(name)
  80.   if (name == nil) then return false end
  81.  
  82.   for n, m in pairs(pam.additionalModules) do
  83.     if m.name == name then
  84.       table.remove(pam.additionalModules, n)
  85.       return true
  86.     end
  87.   end
  88.  
  89.   return false
  90. end
  91.  
  92. pam.removeAllModules = function()
  93.   pam.additionalModules = {}
  94. end
  95.  
  96. -- pam
  97.  
  98. pam.load = function(fileName)
  99.   if (fileName ~= nil) and fs.exists(fileName) then
  100.     local fileSize = fs.size(fileName)
  101.     if fileSize < 12 then
  102.       return false, "File size is too small" end
  103.    
  104.     local file = fs.open(fileName,"rb")
  105.     local data = file:read(3)
  106.     if data == "PAM" then
  107.       pam.vertexes = {}
  108.       pam.triangles = {}
  109.       pam.vertexFrames = {}
  110.       pam.paletteFrames = {}
  111.    
  112.       pam.type = file:read(1):byte()
  113.       local vertsCount = pam.str2int(file:read(4))
  114.       local trisCount = pam.str2int(file:read(4))
  115.      
  116.       for i = 1, vertsCount do -- vertexes
  117.         if pam.type < 4 then
  118.           table.insert(pam.vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 3D vertexes
  119.         elseif pam.type < 8 then
  120.           table.insert(pam.vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 2D vertexes
  121.         end
  122.       end
  123.       os.sleep(0.001)
  124.      
  125.       for i = 1, trisCount do -- triangles
  126.         table.insert(pam.triangles, {pam.str2int(file:read(4)), pam.str2int(file:read(4)), pam.str2int(file:read(4)), file:read(4)})
  127.       end
  128.       os.sleep(0.001)
  129.      
  130.       if (pam.type == 1) or (pam.type == 3) then -- 3D vertex animation
  131.         local framesCount = pam.str2int(file:read(4))
  132.         for i = 1, framesCount do
  133.           local frameVertexes = {}
  134.           for j = 1, vertsCount do
  135.             table.insert(frameVertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4)), pam.str2float(file:read(4))})
  136.           end
  137.           table.insert(pam.vertexFrames, frameVertexes)
  138.           os.sleep(0.001)
  139.         end
  140.       end
  141.  
  142.       if (pam.type == 5) or (pam.type == 7) then -- 2D vertex animation
  143.         local framesCount = pam.str2int(file:read(4))
  144.         for i = 1, framesCount do
  145.           local frameVertexes = {}
  146.           for j = 1, vertsCount do
  147.             table.insert(frameVertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4))})
  148.           end
  149.           table.insert(pam.vertexFrames, frameVertexes)
  150.           os.sleep(0.001)
  151.         end
  152.       end
  153.      
  154.       if (pam.type == 2) or (pam.type == 3) or
  155.           (pam.type == 6) or (pam.type == 7) then -- palette animation
  156.         local framesCount = pam.str2int(file:read(4))
  157.         for i = 1, framesCount do
  158.           local framePalette = {}
  159.           for j = 1, trisCount do
  160.             table.insert(framePalette, file:read(4))
  161.           end
  162.           table.insert(pam.paletteFrames, framePalette)
  163.           os.sleep(0.001)
  164.         end
  165.       end
  166.      
  167.       for n, m in pairs(pam.additionalModules) do
  168.         if (m ~= nil) and (m.unpack ~= nil) then
  169.           local md = m.unpack(file, fileSize, pam)
  170.           if md ~= nil then pam.modulesData[m.name] = md end
  171.           os.sleep(0.001)
  172.         end
  173.       end
  174.      
  175.       file:close()
  176.       return true
  177.     else
  178.       file:close()
  179.       return false, "File has invalid format"
  180.     end
  181.   else
  182.     return false, "File does not exists"
  183.   end
  184. end
  185.  
  186. pam.save = function(fileName)
  187.   if fileName == nil then return false end
  188.  
  189.   if (#pam.vertexes < 3) and (#pam.triangles < 1) then return false end
  190.  
  191.   if #pam.additionalModules < 1 then
  192.     if #pam.vertexes[1] == 3 then pam.type = 0
  193.     else pam.type = 4 end
  194.    
  195.     if #pam.vertexFrames > 0 then
  196.       pam.type = pam.type + 1
  197.       if #pam.paletteFrames > 0 then
  198.         pam.type = pam.type + 2
  199.       end
  200.     elseif #pam.paletteFrames > 0 then
  201.       pam.type = pam.type + 1
  202.     end
  203.   end
  204.  
  205.   local data = "PAM"..string.char(pam.type)..pam.int2str(#pam.vertexes)..pam.int2str(#pam.triangles)
  206.  
  207.   for n, vert in pairs(pam.vertexes) do -- pack mesh
  208.     local x,y,z = table.unpack(vert)
  209.     data = data..pam.float2str(x)..pam.float2str(y)
  210.     if pam.type < 4 then data = data..pam.float2str(z) end
  211.   end
  212.   os.sleep(0.001)
  213.  
  214.   for n, tri in pairs(pam.triangles) do
  215.     local a,b,c,d = table.unpack(tri)
  216.     data = data..pam.int2str(a)..pam.int2str(b)..pam.int2str(c)..d
  217.   end
  218.   os.sleep(0.001)
  219.  
  220.   if #pam.additionalModules < 1 then
  221.     if #pam.vertexFrames > 0 then -- pack vertex animation
  222.       data = data..pam.int2str(#pam.vertexFrames)
  223.       for n, frame in pairs(pam.vertexFrames) do
  224.         for n, vert in pairs(frame) do
  225.           local x,y,z = table.unpack(vert)
  226.           data = data..pam.float2str(x)..pam.float2str(y)
  227.           if pam.type < 4 then data = data..pam.float2str(z) end
  228.         end
  229.       end
  230.     end
  231.    
  232.     if #pam.paletteFrames > 0 then -- pack palette animation
  233.       data = data..pam.int2str(#pam.paletteFrames)
  234.       for n, frame in pairs(pam.paletteFrames) do
  235.         for n, color in pairs(frame) do
  236.           data = data..color
  237.         end
  238.       end
  239.     end
  240.     os.sleep(0.001)
  241.   else
  242.     for n, m in pairs(pam.additionalModules) do
  243.       if (m ~= nil) and (m.pack ~= nil) and (pam.modulesData[m.name] ~= nil) then
  244.         data = data..m.pack(pam.modulesData[m.name], pam)
  245.         os.sleep(0.001)
  246.       end
  247.     end
  248.   end
  249.  
  250.   local file = fs.open(fileName, "wb")
  251.   file:write(data)
  252.   file:close()
  253.  
  254.   return true
  255. end
  256.  
  257. pam.loadMesh = function(fileName)
  258.   if (fileName ~= nil) and fs.exists(fileName) then
  259.     if fs.size(fileName) < 12 then
  260.     return false, "File size is too small" end
  261.    
  262.     local file = fs.open(fileName,"rb")
  263.     local data = file:read(3)
  264.     if data == "PAM" then
  265.       local vertexes = {}
  266.       local triangles = {}
  267.    
  268.       local type = file:read(1):byte()
  269.       local vertsCount = pam.str2int(file:read(4))
  270.       local trisCount = pam.str2int(file:read(4))
  271.      
  272.       for i = 1, vertsCount do -- vertexes
  273.         if pam.type < 4 then
  274.           table.insert(vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 3D vertexes
  275.         elseif pam.type < 8 then
  276.           table.insert(vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 2D vertexes
  277.         end
  278.       end
  279.      
  280.       for i = 1, trisCount do -- triangles
  281.         table.insert(triangles, {pam.str2int(file:read(4)), pam.str2int(file:read(4)), pam.str2int(file:read(4)), file:read(4)})
  282.       end
  283.      
  284.       file:close()
  285.       return true, type, vertexes, triangles
  286.     else
  287.       file:close()
  288.       return false, "File has invalid format"
  289.     end
  290.   else
  291.     return false, "File does not exists"
  292.   end
  293. end
  294.  
  295. local function lerpVertex(v1, v2, t)
  296.   if #v1 == 3 then
  297.     local v = {0,0,0}
  298.     v[1] = (1-t)*v1[1] + t*v2[1];
  299.     v[2] = (1-t)*v1[2] + t*v2[2];
  300.     v[3] = (1-t)*v1[3] + t*v2[3];
  301.     return v
  302.   else
  303.     local v = {0,0}
  304.     v[1] = (1-t)*v1[1] + t*v2[1];
  305.     v[2] = (1-t)*v1[2] + t*v2[2];
  306.     return v
  307.   end
  308. end
  309.  
  310. local function lerpColor(c1, c2, t)
  311.   local c = {0,0,0,0}
  312.   c[1] = math.floor((1-t)*c1[1] + t*c2[1]);
  313.   c[2] = math.floor((1-t)*c1[2] + t*c2[2]);
  314.   c[3] = math.floor((1-t)*c1[3] + t*c2[3]);
  315.   c[4] = math.floor((1-t)*c1[4] + t*c2[4]);
  316.   return c
  317. end
  318.  
  319. pam.lerpVertexFrames = function(f1, f2, t)
  320.   if f1 == f2 then
  321.     return nil, "Frames must be different"
  322.   end
  323.  
  324.   local firstFrame
  325.   local secondFrame
  326.   local outputFrame = {}
  327.  
  328.   if f1 == 0 then
  329.     firstFrame = pam.vertexes
  330.   elseif (f1 < 1) or (f1 > #pam.vertexFrames) then
  331.     return nil, "Invalid first frame"
  332.   else
  333.     firstFrame = pam.vertexFrames[f1]
  334.   end
  335.   if f2 == 0 then
  336.     secondFrame = pam.vertexes
  337.   elseif (f2 < 1) or (f2 > #pam.vertexFrames) then
  338.     return nil, "Invalid second frame"
  339.   else
  340.     secondFrame = pam.vertexFrames[f2]
  341.   end
  342.  
  343.   for i=1, #firstFrame do
  344.     table.insert(outputFrame, lerpVertex(firstFrame[i], secondFrame[i], t))
  345.   end
  346.  
  347.   return outputFrame
  348. end
  349.  
  350. pam.lerpPaletteFrames = function(f1, f2, t)
  351.   if f1 == f2 then
  352.     return nil, "Frames must be different"
  353.   end
  354.  
  355.   local firstFrame
  356.   local secondFrame
  357.   local outputFrame = {}
  358.  
  359.   if (f1 < 0) or (f1 > #pam.paletteFrames) then
  360.     return nil, "Invalid first frame"
  361.   elseif f1 ~= 0 then
  362.     firstFrame = pam.paletteFrames[f1];
  363.   end
  364.   if (f2 < 0) or (f2 > #pam.paletteFrames) then
  365.     return nil, "Invalid second frame"
  366.   elseif f2 ~= 0 then
  367.     secondFrame = pam.paletteFrames[f2]
  368.   end
  369.  
  370.   for i=1, #pam.triangles do
  371.     local c1
  372.     local c2
  373.     if f1 == 0 then
  374.       c1 = table.pack(pam.triangles[i][4]:byte(1,4))
  375.     else
  376.       c1 = table.pack(firstFrame[i]:byte(1,4))
  377.     end
  378.     if f2 == 0 then
  379.       c2 = table.pack(pam.triangles[i][4]:byte(1,4))
  380.     else
  381.       c2 = table.pack(secondFrame[i]:byte(1,4))
  382.     end
  383.     table.insert(outputFrame, lerpColor(c1, c2, t))
  384.   end
  385.  
  386.   return outputFrame
  387. end
  388.  
  389. return pam
Advertisement
Add Comment
Please, Sign In to add comment