Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- OBJ model library 1.0
- -- ---------------------
- -- by Totoro (computercraft.ru)
- -- ---
- -- texture support by Xytabich
- local png = require("PNGImage")
- tobj = {}
- local vertex = {}
- local faces = {}
- local image
- local texCoords = {}
- local palette = {}
- local color = {r = 1, g = 0, b = 0, a = 1}
- local position = {x = 0, y = 0, z = 0}
- local scale = 1.0
- local paletteColors = true
- local function getVT(data)
- local v, t = data:match("(-?%d+)/(-?%d+)")
- return tonumber(v), tonumber(t) or nil
- end
- local function round(v)
- local r = math.floor(v)
- if v-0.5 > r then return math.ceil(v)
- else return r end
- end
- local function inBounds(u, v) -- trim the number to the borders of 0-1
- if u > 1 then
- local a, b = math.modf(u)
- u = b
- elseif u < 0 then
- local a, b = math.modf(u)
- u = 1+b
- end
- if v > 1 then
- local a, b = math.modf(v)
- v = b
- elseif v < 0 then
- local a, b = math.modf(v)
- v = 1+b
- end
- return u, v
- end
- local function getFaceColor(t1, t2, t3)
- if (image == nil) or (t1 > #texCoords) or
- (t2 > #texCoords) or (t3 > #texCoords) then return nil
- else
- local u,v = table.unpack(texCoords[t1])
- local w,h = image:getSize()
- w=w-1 h=h-1
- if paletteColors then
- local r,g,b,a = image:getPixel(round(u*w), round((1-v)*h))
- if r == nil then return nil end
- return r/255, g/255, b/255, a/255
- else -- average color of 3 points - алгоритм для ленивых
- local r1,g1,b1,a1 = image:getPixel(round(u*w), round((1-v)*h))
- if r1 == nil then return nil end
- u,v = table.unpack(texCoords[t2])
- local r2,g2,b2,a2 = image:getPixel(round(u*w), round((1-v)*h))
- if r2 == nil then return nil end
- u,v = table.unpack(texCoords[t3])
- local r3,g3,b3,a3 = image:getPixel(round(u*w), round((1-v)*h))
- if r3 == nil then return nil end
- return ((r1+r2+r3)/3)/255, ((g1+g2+g3)/3)/255, ((b1+b2+b3)/3)/255, ((a1+a2+a3)/3)/255
- end
- end
- end
- local function getPaletteIndex(r,g,b,a)
- for i=1, #palette do
- local pr,pg,pb,pa = table.unpack(palette[i])
- if (r==pr) and (g==pg) and (b==pb) and (a==pa) then
- return i
- end
- end
- table.insert(palette, {r,g,b,a})
- return #palette
- end
- local function getPaletteColor(i)
- if (i < 1) or (i > #palette) then return 1,1,1,1
- else return table.unpack(palette[i]) end
- end
- tobj.loadTexture = function(filename)
- image = png.newFromFile(filename);
- end
- tobj.load = function(filename)
- file = io.open(filename, "r")
- if file ~= nil then
- vertex = {}
- for line in file:lines() do
- if line ~= nil and line ~= '' then
- local key, a, b, c, d = line:match("(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s*(%S*)")
- -- load vertex data / skip normals
- if key == 'v' then
- local x, y, z = tonumber(a), tonumber(b), tonumber(c)
- table.insert(vertex, {x,y,z})
- -- load texture data
- elseif key == "vt" then
- local u, v = tonumber(a), tonumber(b)
- table.insert(texCoords, table.pack(inBounds(u, v)))
- -- load faces data
- elseif key == 'f' then
- local v1, t1 = getVT(a)
- local v2, t2 = getVT(b)
- local v3, t3 = getVT(c)
- if v1 < 0 then
- local len = #vertex + 1
- v1, v2, v3 = len + v1, len + v2, len + v3
- end
- local p = 0
- if t1 ~= nil then
- r,g,b,a = getFaceColor(t1, t2, t3)
- if r ~= nil then
- p = getPaletteIndex(r,g,b,a)
- end
- end
- table.insert(faces, {vertex[v1], vertex[v2], vertex[v3], p})
- end
- end
- end
- file:close()
- else
- error("[OBJ.load] File not found!")
- end
- end
- tobj.setColor = function(r, g, b, a)
- color.r = r; color.g = g; color.b = b; color.a = a or 1;
- end
- tobj.setPosition = function(x, y, z)
- position.x = x; position.y = y; position.z = z
- end
- tobj.setScale = function(s)
- scale = s
- end
- tobj.getColor = function()
- return {color.r, color.g, color.b, color.a}
- end
- tobj.getPosition = function()
- return {position.x, position.y, position.z}
- end
- tobj.getScale = function()
- return scale
- end
- tobj.usePalette = function(use)
- if use ~= nil then paletteColors = use
- else return paletteColors end
- end
- tobj.draw = function(glasses)
- local count = 0
- for n, face in pairs(faces) do
- local triangle = glasses.addTriangle3D()
- triangle.setVertex(1, face[1][1]*scale + position.x, face[1][2]*scale + position.y, face[1][3]*scale + position.z)
- triangle.setVertex(2, face[2][1]*scale + position.x, face[2][2]*scale + position.y, face[2][3]*scale + position.z)
- triangle.setVertex(3, face[3][1]*scale + position.x, face[3][2]*scale + position.y, face[3][3]*scale + position.z)
- r,g,b,a = getPaletteColor(face[4])
- triangle.setColor(color.r*r, color.g*g, color.b*b)
- triangle.setAlpha(color.a*a)
- triangle.setVisibleThroughObjects(false)
- ---
- count = count + 1
- if count > 20 then count = 0; os.sleep(0.1) end
- end
- end
- tobj.getVertexNum = function()
- return #vertex
- end
- tobj.getPolyNum = function()
- return #faces
- end
- return tobj
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement