Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Polygonal Animated Model library
- -- by Xytabich
- -- types 0-31 is reserved, please, don't use their
- local fs = require("filesystem")
- local function grab_byte(v)
- return math.floor(v / 256), string.char(math.floor(v) % 256)
- end
- pam = {}
- pam.float2str = function(x)
- local sign = 0
- if x < 0 then
- sign = 1
- x = -x
- end
- local mantissa, exponent = math.frexp(x)
- if x == 0 then
- mantissa = 0
- exponent = 0
- else
- mantissa = (mantissa * 2 - 1) * 8388608
- exponent = exponent + 126
- end
- local v, byte = ""
- x, byte = grab_byte(mantissa); v = v..byte
- x, byte = grab_byte(x); v = v..byte
- x, byte = grab_byte(exponent * 128 + x); v = v..byte
- x, byte = grab_byte(sign * 128 + x); v = v..byte
- return v
- end
- pam.str2float = function(x)
- local sign = 1
- local mantissa = string.byte(x, 3) % 128
- for i = 2, 1, -1 do mantissa = mantissa * 256 + string.byte(x, i) end
- if string.byte(x, 4) > 127 then sign = -1 end
- local exponent = (string.byte(x, 4) % 128) * 2 + math.floor(string.byte(x, 3) / 128)
- if exponent == 0 then return 0 end
- mantissa = (math.ldexp(mantissa, -23) + 1) * sign
- return math.ldexp(mantissa, exponent - 127)
- end
- pam.int2str = function(n)
- n = (n < 0) and (4294967296 + n) or n
- return string.char((math.modf(n/16777216))%256, (math.modf(n/65536))%256, (math.modf(n/256))%256, n%256)
- end
- pam.str2int = function(x)
- b1, b2, b3, b4 = string.byte(x, 1, 4)
- local n = b1*16777216 + b2*65536 + b3*256 + b4
- n = (n > 2147483647) and (n - 4294967296) or n
- return n
- end
- pam.type = 0
- pam.vertexes = {}
- pam.triangles = {} -- x,y,z, string color(use string.byte() to decode)
- pam.vertexFrames = {}
- pam.paletteFrames = {}
- -- modules
- pam.additionalModules = {}
- pam.modulesData = {}
- pam.addModule = function(m)
- if (m == nil) or (m.name == nil) or ((m.pack == nil) and (m.unpack == nil)) then
- return false
- end
- table.insert(pam.additionalModules, m)
- return true
- end
- pam.removeModule = function(name)
- if (name == nil) then return false end
- for n, m in pairs(pam.additionalModules) do
- if m.name == name then
- table.remove(pam.additionalModules, n)
- return true
- end
- end
- return false
- end
- pam.removeAllModules = function()
- pam.additionalModules = {}
- end
- -- pam
- pam.load = function(fileName)
- if (fileName ~= nil) and fs.exists(fileName) then
- local fileSize = fs.size(fileName)
- if fileSize < 12 then
- return false, "File size is too small" end
- local file = fs.open(fileName,"rb")
- local data = file:read(3)
- if data == "PAM" then
- pam.vertexes = {}
- pam.triangles = {}
- pam.vertexFrames = {}
- pam.paletteFrames = {}
- pam.type = file:read(1):byte()
- local vertsCount = pam.str2int(file:read(4))
- local trisCount = pam.str2int(file:read(4))
- for i = 1, vertsCount do -- vertexes
- if pam.type < 4 then
- table.insert(pam.vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 3D vertexes
- elseif pam.type < 8 then
- table.insert(pam.vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 2D vertexes
- end
- end
- os.sleep(0.001)
- for i = 1, trisCount do -- triangles
- table.insert(pam.triangles, {pam.str2int(file:read(4)), pam.str2int(file:read(4)), pam.str2int(file:read(4)), file:read(4)})
- end
- os.sleep(0.001)
- if (pam.type == 1) or (pam.type == 3) then -- 3D vertex animation
- local framesCount = pam.str2int(file:read(4))
- for i = 1, framesCount do
- local frameVertexes = {}
- for j = 1, vertsCount do
- table.insert(frameVertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4)), pam.str2float(file:read(4))})
- end
- table.insert(pam.vertexFrames, frameVertexes)
- os.sleep(0.001)
- end
- end
- if (pam.type == 5) or (pam.type == 7) then -- 2D vertex animation
- local framesCount = pam.str2int(file:read(4))
- for i = 1, framesCount do
- local frameVertexes = {}
- for j = 1, vertsCount do
- table.insert(frameVertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4))})
- end
- table.insert(pam.vertexFrames, frameVertexes)
- os.sleep(0.001)
- end
- end
- if (pam.type == 2) or (pam.type == 3) or
- (pam.type == 6) or (pam.type == 7) then -- palette animation
- local framesCount = pam.str2int(file:read(4))
- for i = 1, framesCount do
- local framePalette = {}
- for j = 1, trisCount do
- table.insert(framePalette, file:read(4))
- end
- table.insert(pam.paletteFrames, framePalette)
- os.sleep(0.001)
- end
- end
- for n, m in pairs(pam.additionalModules) do
- if (m ~= nil) and (m.unpack ~= nil) then
- local md = m.unpack(file, fileSize, pam)
- if md ~= nil then pam.modulesData[m.name] = md end
- os.sleep(0.001)
- end
- end
- file:close()
- return true
- else
- file:close()
- return false, "File has invalid format"
- end
- else
- return false, "File does not exists"
- end
- end
- pam.save = function(fileName)
- if fileName == nil then return false end
- if (#pam.vertexes < 3) and (#pam.triangles < 1) then return false end
- if #pam.additionalModules < 1 then
- if #pam.vertexes[1] == 3 then pam.type = 0
- else pam.type = 4 end
- if #pam.vertexFrames > 0 then
- pam.type = pam.type + 1
- if #pam.paletteFrames > 0 then
- pam.type = pam.type + 2
- end
- elseif #pam.paletteFrames > 0 then
- pam.type = pam.type + 1
- end
- end
- local data = "PAM"..string.char(pam.type)..pam.int2str(#pam.vertexes)..pam.int2str(#pam.triangles)
- for n, vert in pairs(pam.vertexes) do -- pack mesh
- local x,y,z = table.unpack(vert)
- data = data..pam.float2str(x)..pam.float2str(y)
- if pam.type < 4 then data = data..pam.float2str(z) end
- end
- os.sleep(0.001)
- for n, tri in pairs(pam.triangles) do
- local a,b,c,d = table.unpack(tri)
- data = data..pam.int2str(a)..pam.int2str(b)..pam.int2str(c)..d
- end
- os.sleep(0.001)
- if #pam.additionalModules < 1 then
- if #pam.vertexFrames > 0 then -- pack vertex animation
- data = data..pam.int2str(#pam.vertexFrames)
- for n, frame in pairs(pam.vertexFrames) do
- for n, vert in pairs(frame) do
- local x,y,z = table.unpack(vert)
- data = data..pam.float2str(x)..pam.float2str(y)
- if pam.type < 4 then data = data..pam.float2str(z) end
- end
- end
- end
- if #pam.paletteFrames > 0 then -- pack palette animation
- data = data..pam.int2str(#pam.paletteFrames)
- for n, frame in pairs(pam.paletteFrames) do
- for n, color in pairs(frame) do
- data = data..color
- end
- end
- end
- os.sleep(0.001)
- else
- for n, m in pairs(pam.additionalModules) do
- if (m ~= nil) and (m.pack ~= nil) and (pam.modulesData[m.name] ~= nil) then
- data = data..m.pack(pam.modulesData[m.name], pam)
- os.sleep(0.001)
- end
- end
- end
- local file = fs.open(fileName, "wb")
- file:write(data)
- file:close()
- return true
- end
- pam.loadMesh = function(fileName)
- if (fileName ~= nil) and fs.exists(fileName) then
- if fs.size(fileName) < 12 then
- return false, "File size is too small" end
- local file = fs.open(fileName,"rb")
- local data = file:read(3)
- if data == "PAM" then
- local vertexes = {}
- local triangles = {}
- local type = file:read(1):byte()
- local vertsCount = pam.str2int(file:read(4))
- local trisCount = pam.str2int(file:read(4))
- for i = 1, vertsCount do -- vertexes
- if pam.type < 4 then
- table.insert(vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 3D vertexes
- elseif pam.type < 8 then
- table.insert(vertexes, {pam.str2float(file:read(4)), pam.str2float(file:read(4))}) -- 2D vertexes
- end
- end
- for i = 1, trisCount do -- triangles
- table.insert(triangles, {pam.str2int(file:read(4)), pam.str2int(file:read(4)), pam.str2int(file:read(4)), file:read(4)})
- end
- file:close()
- return true, type, vertexes, triangles
- else
- file:close()
- return false, "File has invalid format"
- end
- else
- return false, "File does not exists"
- end
- end
- local function lerpVertex(v1, v2, t)
- if #v1 == 3 then
- local v = {0,0,0}
- v[1] = (1-t)*v1[1] + t*v2[1];
- v[2] = (1-t)*v1[2] + t*v2[2];
- v[3] = (1-t)*v1[3] + t*v2[3];
- return v
- else
- local v = {0,0}
- v[1] = (1-t)*v1[1] + t*v2[1];
- v[2] = (1-t)*v1[2] + t*v2[2];
- return v
- end
- end
- local function lerpColor(c1, c2, t)
- local c = {0,0,0,0}
- c[1] = math.floor((1-t)*c1[1] + t*c2[1]);
- c[2] = math.floor((1-t)*c1[2] + t*c2[2]);
- c[3] = math.floor((1-t)*c1[3] + t*c2[3]);
- c[4] = math.floor((1-t)*c1[4] + t*c2[4]);
- return c
- end
- pam.lerpVertexFrames = function(f1, f2, t)
- if f1 == f2 then
- return nil, "Frames must be different"
- end
- local firstFrame
- local secondFrame
- local outputFrame = {}
- if f1 == 0 then
- firstFrame = pam.vertexes
- elseif (f1 < 1) or (f1 > #pam.vertexFrames) then
- return nil, "Invalid first frame"
- else
- firstFrame = pam.vertexFrames[f1]
- end
- if f2 == 0 then
- secondFrame = pam.vertexes
- elseif (f2 < 1) or (f2 > #pam.vertexFrames) then
- return nil, "Invalid second frame"
- else
- secondFrame = pam.vertexFrames[f2]
- end
- for i=1, #firstFrame do
- table.insert(outputFrame, lerpVertex(firstFrame[i], secondFrame[i], t))
- end
- return outputFrame
- end
- pam.lerpPaletteFrames = function(f1, f2, t)
- if f1 == f2 then
- return nil, "Frames must be different"
- end
- local firstFrame
- local secondFrame
- local outputFrame = {}
- if (f1 < 0) or (f1 > #pam.paletteFrames) then
- return nil, "Invalid first frame"
- elseif f1 ~= 0 then
- firstFrame = pam.paletteFrames[f1];
- end
- if (f2 < 0) or (f2 > #pam.paletteFrames) then
- return nil, "Invalid second frame"
- elseif f2 ~= 0 then
- secondFrame = pam.paletteFrames[f2]
- end
- for i=1, #pam.triangles do
- local c1
- local c2
- if f1 == 0 then
- c1 = table.pack(pam.triangles[i][4]:byte(1,4))
- else
- c1 = table.pack(firstFrame[i]:byte(1,4))
- end
- if f2 == 0 then
- c2 = table.pack(pam.triangles[i][4]:byte(1,4))
- else
- c2 = table.pack(secondFrame[i]:byte(1,4))
- end
- table.insert(outputFrame, lerpColor(c1, c2, t))
- end
- return outputFrame
- end
- return pam
Advertisement
Add Comment
Please, Sign In to add comment