-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobj2lbeam.lua
90 lines (80 loc) · 2.38 KB
/
obj2lbeam.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
-- convert .obj files to LBeam structures
local opts = {}
for i=1, #arg do
if arg[i]:sub(1,1) == "-" then
local k,v = arg[i]:match("%-([^=]+)=(.+)")
opts[k]=tonumber(v) or v
end
end
if opts.help then
print("usage: obj2lbeam OBJFILE [opts]")
print("converts a .obj file to an LBeam structure.\n")
print("options:")
print(" -mass=N set node mass")
print(" -stiff=N set beam stiffness")
print(" -damp=N set beam damping")
print(" -color=C set triangle color")
print(" -bounce=N set triangle bounciness")
end
if #arg == 0 then
error("expected a .obj file", 0)
end
local nodes, beams, tris =
{{mass=tonumber(opts.mass)or 15}},
{{stiffness=tonumber(opts.stiff)or 5000,damping=tonumber(opts.damp)or 10}},
{{color=opts.color or "red",collide=true,
draw=true,bounce=tonumber(opts.bounce)or 0.5}}
local function addBeam(na, nb)
for i=1, #beams do
if (beams[i][1] == na and beams[i][2] == nb) or
(beams[i][2] == na and beams[i][1] == nb) then
return
end
end
beams[#beams+1] = {na, nb}
end
for line in io.lines(arg[1]) do
local cmd = line:match("^[^ ]+")
if cmd == "v" then
local x, y, z = line:match("v (%-?[%d%.]+) (%-?[%d%.]+) (%-?[%d%.]+)")
nodes[#nodes+1] = {tonumber(x),tonumber(y),tonumber(z),tostring(#nodes)}
elseif cmd == "f" then
local a, b, c, e = line:match("f (%d+)/%d+/%d+ (%d+)/%d+/%d+ (%d+)/%d+/%d+(.*)")
if e and #e > 0 then
error("only triangular faces are supported!")
end
addBeam(a,b)
addBeam(b,c)
addBeam(c,a)
-- TODO; might need extra logic here?
tris[#tris+1] = {a,b,c}
elseif cmd == "l" then
local a, b = line:match("l (%d+) (%d+)")
addBeam(a, b)
end
end
local function serialize(t)
local ret = ""
if type(t) == "table" then
ret = "{"
for k, v in pairs(t) do
if type(k) == "number" then
ret = ret .. string.format("%s,", serialize(v))
else
ret = ret .. string.format("%s = %s,", k,
serialize(v))
end
end
ret = ret .. "}\n"
elseif type(t) == "function" or type(t) == "thread" or
type(t) == "userdata" then
error("cannot serialize type " .. type(t), 2)
else
return string.format("%q", t)
end
return ret
end
local outname = arg[1]:match("([^/]+)$"):gsub("%.obj$", ".lbeam")
local out = io.open(outname, "w")
out:write(serialize({nodes=nodes,beams=beams,triangles=tris}, {}))
out:close()