Stl To Obj

lua-users home
wiki

STL to OBJ

Convert ASCII STL to OBJ (Wavefront) format with optional coloring

--[[
	Convert ASCII STL file to OBJ (wavefront file) with optional coloring
	V 1.0
	Date: 2014-09-25
	Author: Michael Lutz
	Licensed under the same terms as Lua itself
--]]

local version = "1.0"

print("Usage:")
print("stl_to_obj.lua <stl_file> [<color>]")
print("-----------")
print("<color>: can be a color: red,green,blue,cyan,magenta,yellow")
print("<color>: can be and RGB value R,G,B: 255,70,80")

--/////////////////////////////////////////////////////////////////
-- input stl filename
local stl_filename = arg[1]
local filename = string.sub(stl_filename,1,-5)

print()
print("Input file: "..stl_filename)

local color_rgb = {
	["red"] = {1.0,0,0},
	["green"] = {0,1.0,0},
	["blue"] = {0,0,1.0},
	["cyan"] = {0,1.0,1.0},
	["magenta"] = {1.0,0,1.0},
	["yellow"] = {1.0,1.0,0},
}

local color = {}
if arg and arg[2] then
	if color_rgb[arg[2]] then
		color = color_rgb[arg[2]]
	else
		local r,g,b = string.match(arg[2],"(%d+),(%d+),(%d+)")
		color = {tonumber(r)/255,tonumber(g)/255,tonumber(b)/255}
	end
	print("Input color: "..arg[2])
end




-- obj filename
local obj_filename = filename..".obj"
print("Output file: "..obj_filename)

local t_vertices = {}
local t_normals = {}
local t_faces = {}

--/////////////////////////////////////////////////////////////////
-- parse stl file
local file_stl = io.open(stl_filename, "r")

local cur_face = {}
local count = 0
for line in file_stl:lines() do
	if string.find(line, "^%s*facet normal") then
		local x,y,z = string.match(line, "(%S+)%s(%S+)%s(%S+)$")
		table.insert(cur_face, {tonumber(x),tonumber(y),tonumber(z)})
	end
	if string.find(line, "^%s*vertex") then
		local x,y,z = string.match(line, "(%S+)%s(%S+)%s(%S+)$")
		table.insert(cur_face, {tonumber(x),tonumber(y),tonumber(z)})
		count = count + 1
		if count == 3 then
			table.insert(t_faces,cur_face)
			cur_face = {}
			count = 0
		end
	end
end
file_stl:close()

--/////////////////////////////////////////////////////////////////
-- write mtl
local mtl_filename = filename..".mtl"
if #color ~= 0 then
	print("Output mtl: "..mtl_filename)
	local file = io.open(mtl_filename, "w")
	file:write(
		"# Color: "..arg[2].."\n"..
		"newmtl color_"..arg[2].."\n"..
		"Ka "..string.format("%f",color[1]).." "..string.format("%f",color[2]).." "..string.format("%f",color[3]).."\n"..
		"Kd "..string.format("%f",color[1]).." "..string.format("%f",color[2]).." "..string.format("%f",color[3]).."\n"..
		"Ks 0.000 0.000 0.000\n")
	file:close()
end

print()

--/////////////////////////////////////////////////////////////////
-- write obj
local file = io.open(obj_filename, "w")

file:write("#########################################\n")
file:write("# Wavefront .obj file\n")
file:write("# Created by: stl_to_obj.lua (v "..version..") / Author: Michael Lutz\n")
file:write("# Date: "..os.date().."\n")
file:write("#########################################\n\n")

if #color ~= 0 then
	file:write("#########################################\n")
	file:write("# MTL lib:\n\n")
	file:write("mtllib "..mtl_filename.."\n\n")
end

--/////////////////////////////////////////////////////////////////
-- # List of Vertices
file:write("#########################################\n")
file:write("# List of vertices:\n\n")

for i,v in ipairs(t_faces) do
	for i2=2,4 do
		file:write("v "..string.format("%f",v[i2][1]).." "..string.format("%f",v[i2][2]).." "..string.format("%f",v[i2][3]).."\n")
	end
end
file:write("\n")

--/////////////////////////////////////////////////////////////////
--# Normals in (x,y,z) form; normals might not be unit.
-- Normals are not needed since stl saves the triangles in counter clock anyways
--file:write("\n# List of Normals\n\n")
--for i,v in ipairs(t_faces) do
--	file:write("vn "..string.format("%f",v[1][1]).." "..string.format("%f",v[1][2]).." "..string.format("%f",v[1][3]).."\n")
--end

--/////////////////////////////////////////////////////////////////
-- # Face Definitions (see below)
file:write("#########################################\n")
file:write("# Face definitions:\n\n")

if #color ~= 0 then
	file:write("usemtl color_"..arg[2].."\n\n")
end

for i,v in ipairs(t_faces) do
	local i2 = (i-1)*3
	--file:write("f "..(i2+1).."//"..i.." "..(i2+2).."//"..i.." "..(i2+3).."//"..i.."\n")
	file:write("f "..(i2+1).." "..(i2+2).." "..(i2+3).."\n")
end

file:close()

RecentChanges · preferences
edit · history
Last edited September 26, 2014 9:14 am GMT (diff)