Skip to content

Instantly share code, notes, and snippets.

@SeijiEmery
Created August 22, 2017 15:30
Show Gist options
  • Save SeijiEmery/89f65890bfc815839e5459aab416b205 to your computer and use it in GitHub Desktop.
Save SeijiEmery/89f65890bfc815839e5459aab416b205 to your computer and use it in GitHub Desktop.
Obj-file loader (python)
#
# Scaffold, can be trivially extended to do useful things.
# Currently, just loads a file + prints # of tris, verts, normals, and uvs.
#
def load_obj (path):
class Parser:
def __init__ (self):
self.has_tris, self.has_verts, self.has_textures, self.has_normals = False, False, False, False
self.tris, self.verts, self.textures, self.normals = [], [], [], []
def mtllib (self, name):
pass
def usemtl (self, name):
pass
def g (self, name):
pass
def v (self, x, y, z = "0", w = "0"):
# print("Vertex: %s"%(map(float, (x, y, z, w))))
self.verts += map(float, (x, y, z, w))
self.has_verts = True
def vn (self, x, y, z):
# print("Vertex normal: %s"%(map(float, (x, y, z, w))))
self.normals += map(float, (x, y, z))
self.has_normals = True
def vt (self, u, v, w = "0"):
# print("Vertex uv: %s"%(map(float, (u, v, w))))
self.textures += map(float, (u, v, w))
self.has_textures = True
def f (self, *args):
indices = [0] * 12
mapv = lambda i: i-1 if i > 0 else len(self.verts) + i
mapt = lambda i: i-1 if i > 0 else len(self.textures) + i
mapn = lambda i: i-1 if i > 0 else len(self.normals) + i
for i, elem in enumerate(args):
xs = elem.split("/")
if len(xs) >= 1 and xs[0]: indices[i * 3 + 0] = mapv(int(xs[0]))
if len(xs) >= 2 and xs[1]: indices[i * 3 + 1] = mapt(int(xs[1]))
if len(xs) >= 3 and xs[2]: indices[i * 3 + 2] = mapn(int(xs[2]))
self.tris += indices[:9]
if len(args) >= 4:
self.tris += indices[6:9]
self.tris += indices[9:12]
self.tris += indices[0:3]
self.has_tris = True
parser = Parser()
with open(path, 'r') as f:
for linenum, line in enumerate(f):
toks = line.split('#')[0].strip().split()
if not toks:
continue
try:
parser.__class__.__dict__[toks[0]](parser, *toks[1:])
except KeyError:
print("Unrecognized command: '%s' on line %d: '%s'"%(toks[0], linenum, line.rstrip()))
print("%d triangles"%(len(parser.tris) / 9))
print("%d vertices"%(len(parser.verts) / 4))
print("%d normals"%(len(parser.verts) / 3))
print("%d uvs"%(len(parser.verts) / 3))
if __name__ == '__main__':
import sys
if len(sys.argv) != 2:
print("usage: %s <path-to-obj-file>", sys.argv[0])
else:
load_obj(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment