Skip to content

Instantly share code, notes, and snippets.

@bit-hack
Created April 19, 2018 23:17
Show Gist options
  • Save bit-hack/222b0b79d710de637db3afcbccc3dac7 to your computer and use it in GitHub Desktop.
Save bit-hack/222b0b79d710de637db3afcbccc3dac7 to your computer and use it in GitHub Desktop.
.obj to .c file converter
import sys
class ObjGroup(object):
def __init__(self, name, v_base, vt_base):
self._name = name
self._mtl = ''
self._vertex = []
self._uv = []
self._face = []
self._v_base = v_base
self._vt_base = vt_base
def name(self):
return self._name
def set_mtl(self, name):
self._mtl = name
def add_vertex(self, vertex):
self._vertex += [vertex]
def add_uv(self, uv):
self._uv += [uv]
def add_face(self, face):
f = []
for p in face:
if type(p) is tuple:
f.append((p[0] - 1 - self._v_base,
p[1] - 1 - self._vt_base))
else:
f.append((p - 1 - self._v_base))
self._face += [f]
def uvs(self):
return self._uv
def vertices(self):
return self._vertex
def faces(self):
return self._face
class ObjFile(object):
def __init__(self):
self.groups = [ObjGroup('undef', 0, 0)]
class ObjVertex(object):
def __init__(self, v, t):
self._v = v
self._t = t or tuple((0.0, 0.0))
def x(self):
return self._v[0]
def y(self):
return self._v[1]
def z(self):
return self._v[2]
def u(self):
return self._t[0]
def v(self):
return self._t[1]
def __eq__(self, other):
for index, v in enumerate(self._v):
if abs(v - other._v[index]) > 0.001:
return False
for index, t in enumerate(self._t):
if abs(t - other._t[index]) > 0.001:
return False
return True
def __hash__(self):
o = []
o += [int(c * 100) for c in self._v]
o += [int(c * 100) for c in self._t]
return ''.join(o).__hash__()
class ObjGroupExt(object):
def _cache_vertex(self, v):
try:
return self._vert.index(v)
except ValueError:
self._vert.append(v)
return self._vert.index(v)
def _add_face(self, v0, v1, v2):
iv0 = self._cache_vertex(v0)
iv1 = self._cache_vertex(v1)
iv2 = self._cache_vertex(v2)
self._face.append((iv0, iv1, iv2))
def name(self):
return self._name
def vertices(self):
return self._vert
def faces(self):
return self._face
def serial_save(self, out):
if self.name() == 'undef':
return
# write out vertices
out.write('const float vert_{}[] = {{\n'.format(self.name()))
for v in self._vert:
out.write(' {:>10}f, {:>10}f, {:>10}f, {:>10}f, {:>10}f,\n'.format(
v.x(), v.y(), v.z(), v.u(), v.v()))
out.write('};\n')
# write out faces
out.write('const int face_{}[] = {{\n'.format(self.name()))
for f in self._face:
out.write('{:4}, {:4}, {:4},\n'.format(f[0], f[1], f[2]))
out.write('};\n')
def __init__(self, group):
self._name = group.name()
self._vert = []
self._face = []
v = group.vertices()
t = group.uvs() or [tuple((0.0, 0.))]
for face in group.faces():
assert(len(face) == 3)
try:
v0 = ObjVertex(v[face[0][0]], t[face[0][1]])
v1 = ObjVertex(v[face[1][0]], t[face[1][1]])
v2 = ObjVertex(v[face[2][0]], t[face[2][1]])
except IndexError:
continue
self._add_face(v0, v1, v2)
class ObjFileExt(object):
def __init__(self, obj_file):
self.groups = [ObjGroupExt(g) for g in obj_file.groups]
def serial_save(self, out):
for g in self.groups:
g.serial_save(out)
class ObjToC(object):
def __init__(self):
self._obj = ObjFile()
self._v_count = 0
self._vt_count = 0
def _cmd_g(self, token):
group = ObjGroup(token[0], self._v_count, self._vt_count)
self._obj.groups += [group]
def _cmd_usemtl(self, token):
self._obj.groups[-1].set_mtl(token[0])
def _cmd_v(self, token):
vertex = [float(x) for x in token]
self._obj.groups[-1].add_vertex(vertex)
self._v_count += 1
def _cmd_vt(self, token):
coord = [float(x) for x in token]
self._obj.groups[-1].add_uv(coord)
self._vt_count += 1
def _cmd_f(self, token):
face = []
for t in token:
if '/' in t:
c = t.split('/')
face.append((int(c[0]), int(c[1])))
else:
face.append((int(t), 0))
self._obj.groups[-1].add_face(face)
def _cmd_null(self, token):
pass
def _dispatch(self, line):
if line.startswith('#'):
return
token = line.split()
if not token:
return
method = getattr(ObjToC, '_cmd_' + token[0], ObjToC._cmd_null)
method(self, token[1:])
def load(self, fd):
for line in fd.readlines():
self._dispatch(line.strip())
return self._obj
if __name__ == '__main__':
if len(sys.argv) < 3:
raise Exception("usage: [.obj] [.c]")
with open(sys.argv[1], 'r') as fd:
obj = ObjToC().load(fd)
obj_ext = ObjFileExt(obj)
with open(sys.argv[2], 'w') as fd:
obj_ext.serial_save(fd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment