Skip to content

Instantly share code, notes, and snippets.

@Bambofy
Created September 14, 2017 18:39
Show Gist options
  • Save Bambofy/31a465ceb8a4edc72850c95724081964 to your computer and use it in GitHub Desktop.
Save Bambofy/31a465ceb8a4edc72850c95724081964 to your computer and use it in GitHub Desktop.
local path = ... .. "."
local loader = {}
loader.version = "0.0.2"
function loader.load(path, filename)
loader.object = {
v = {}, -- List of vertices - x, y, z, [w]=1.0
vt = {}, -- Texture coordinates - u, v, [w]=0
vn = {}, -- Normals - x, y, z
vp = {}, -- Parameter space vertices - u, [v], [w]
f = {}, -- Faces
materials = {}
}
assert(file_exists(path .. "/" .. filename), "File not found: " .. path .. "/" .. filename)
local get_lines
if love then
get_lines = love.filesystem.lines
else
get_lines = io.lines
end
local lines = {}
for line in get_lines(path .. "/" .. filename) do
table.insert(lines, line)
end
loader.parse(path, filename, lines)
return loader.object
end
function loader.parse(path, filename, lines)
for _, line in ipairs(lines) do
local l = string_split(line, "%s+")
if l[1] == "mtllib" then
local mtllibfilename = l[2]
loader.parseMaterial(path, mtllibfilename)
elseif l[1] == "v" then
local v = {
x = tonumber(l[2]),
y = tonumber(l[3]),
z = tonumber(l[4]),
w = tonumber(l[5]) or 1.0
}
table.insert(loader.object.v, v)
elseif l[1] == "vt" then
local vt = {
u = tonumber(l[2]),
v = tonumber(l[3]),
w = tonumber(l[4]) or 0
}
table.insert(loader.object.vt, vt)
elseif l[1] == "vn" then
local vn = {
x = tonumber(l[2]),
y = tonumber(l[3]),
z = tonumber(l[4]),
}
table.insert(loader.object.vn, vn)
elseif l[1] == "vp" then
local vp = {
u = tonumber(l[2]),
v = tonumber(l[3]),
w = tonumber(l[4]),
}
table.insert(loader.object.vp, vp)
elseif l[1] == "f" then
local f = {}
for i=2, #l do
local line = string.gsub(l[i], "//", "/")
local split = string_split(line, "/")
local v = {}
if #split == 1 then
v.v = tonumber(split[1])
elseif #split == 2 then
v.v = tonumber(split[1])
v.vn = tonumber(split[2])
elseif #split == 3 then
v.v = tonumber(split[1])
v.vt = tonumber(split[2])
v.vn = tonumber(split[3])
end
table.insert(f, v)
end
table.insert(loader.object.f, f)
end
end
end
function loader.parseMaterial(path, mtllibfilename)
assert(file_exists(path .. "/" .. mtllibfilename), "File not found: " .. path .. "/" .. mtllibfilename)
local lines = {}
for line in love.filesystem.lines(path .. "/" .. mtllibfilename) do
table.insert(lines, line)
end
local materials = {}
local currentMaterialIndex = 0
for k,v in pairs(lines) do
local parts = string_split(v, "%s+")
if parts[1] == "newmtl" then
currentMaterialIndex = currentMaterialIndex + 1
materials[currentMaterialIndex] = {
Name = parts[2]
}
elseif parts[1] == "Ka" then
materials[currentMaterialIndex].Ambient = {
R = tonumber(parts[2]),
G = tonumber(parts[3]),
B = tonumber(parts[4])
}
elseif parts[1] == "Kd" then
materials[currentMaterialIndex].Diffuse = {
R = tonumber(parts[2]),
G = tonumber(parts[3]),
B = tonumber(parts[4])
}
elseif parts[1] == "Ks" then
materials[currentMaterialIndex].Specular = {
R = tonumber(parts[2]),
G = tonumber(parts[3]),
B = tonumber(parts[4])
}
elseif parts[1] == "Ns" then
materials[currentMaterialIndex].Shininess = tonumber(parts[2])
elseif parts[1] == "map_Kd" then
materials[currentMaterialIndex].DiffuseTexture = path .. "/" .. parts[2]
end
end
loader.object.materials = materials
end
function file_exists(file)
if love then return love.filesystem.exists(file) end
local f = io.open(file, "r")
if f then f:close() end
return f ~= nil
end
-- http://wiki.interfaceware.com/534.html
function string_split(s, d)
local t = {}
local i = 0
local f
local match = '(.-)' .. d .. '()'
if string.find(s, d) == nil then
return {s}
end
for sub, j in string.gmatch(s, match) do
i = i + 1
t[i] = sub
f = j
end
if i ~= 0 then
t[i+1] = string.sub(s, f)
end
return t
end
return loader
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment