Created
April 19, 2018 23:17
-
-
Save bit-hack/222b0b79d710de637db3afcbccc3dac7 to your computer and use it in GitHub Desktop.
.obj to .c file converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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