Created
February 4, 2009 23:50
-
-
Save hdon/58433 to your computer and use it in GitHub Desktop.
This file contains 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
# code borrowed from here: | |
# http://www.pygame.org/wiki/OBJFileLoader | |
import pygame, re | |
from OpenGL.GL import * | |
def MTL(filename): | |
contents = {} | |
mtl = None | |
for line in open(filename, "r"): | |
if line.startswith('#'): continue | |
values = line.split() | |
if not values: continue | |
if values[0] == 'newmtl': | |
mtl = contents[values[1]] = {} | |
elif mtl is None: | |
raise ValueError, "mtl file doesn't start with newmtl stmt" | |
elif values[0] == 'map_Kd': | |
# load the texture referred to by this declaration | |
mtl[values[0]] = values[1] | |
surf = pygame.image.load(mtl['map_Kd']) | |
image = pygame.image.tostring(surf, 'RGBA', 1) | |
ix, iy = surf.get_rect().size | |
texid = mtl['texture_Kd'] = glGenTextures(1) | |
glBindTexture(GL_TEXTURE_2D, texid) | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | |
GL_LINEAR) | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, | |
GL_LINEAR) | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ix, iy, 0, GL_RGBA, | |
GL_UNSIGNED_BYTE, image) | |
else: | |
mtl[values[0]] = map(float, values[1:]) | |
return contents | |
class OBJ: | |
def __init__(self, filename, swapyz=False): | |
"""Loads a Wavefront OBJ file. """ | |
self.vertices = [] | |
self.normals = [] | |
self.texcoords = [] | |
self.faces = [] | |
VERTEX_COLOR_EXTENSION = False | |
material = None | |
for line in open(filename, "r"): | |
if line.startswith('#'): continue | |
values = line.split() | |
if not values: continue | |
if values[0] == 'v': | |
v = map(float, values[1:4]) | |
if swapyz: | |
v = v[0], v[2], v[1] | |
self.vertices.append(v) | |
elif values[0] == 'vn': | |
v = map(float, values[1:4]) | |
if swapyz: | |
v = v[0], v[2], v[1] | |
self.normals.append(v) | |
elif values[0] == 'vt': | |
self.texcoords.append(map(float, values[1:3])) | |
elif values[0] in ('usemtl', 'usemat'): | |
material = values[1] | |
elif values[0] == 'mtllib': | |
self.mtl = MTL(values[1]) | |
# Face | |
elif values[0] == 'f': | |
face = [] | |
texcoords = [] | |
norms = [] | |
colors = [] | |
for v in values[1:]: | |
v = v.split('#') | |
# OBJ extension for color: %f/%f/%f#%02x%02x%02x | |
if len(v) == 1: | |
colors.append((255,255,255)) | |
v = v[0] | |
elif len(v) == 2: | |
VERTEX_COLOR_EXTENSION = True | |
colors.append(tuple(int(s,16)for s in re.findall('..', v[1]))) | |
v = v[0] | |
w = v.split('/') | |
face.append(int(w[0])) | |
if len(w) >= 2 and len(w[1]) > 0: | |
texcoords.append(int(w[1])) | |
else: | |
texcoords.append(0) | |
if len(w) >= 3 and len(w[2]) > 0: | |
norms.append(int(w[2])) | |
else: | |
norms.append(0) | |
self.faces.append((face, norms, texcoords, material, colors)) | |
self.gl_list = glGenLists(1) | |
glNewList(self.gl_list, GL_COMPILE) | |
glFrontFace(GL_CCW) | |
for face in self.faces: | |
vertices, normals, texture_coords, material, colors = face | |
if material == '(null)': | |
glDisable(GL_TEXTURE_2D) | |
else: | |
mtl = self.mtl[material] | |
if 'texture_Kd' in mtl: | |
# use diffuse texmap | |
glEnable(GL_TEXTURE_2D) | |
glBindTexture(GL_TEXTURE_2D, mtl['texture_Kd']) | |
else: | |
# just use diffuse colour | |
glDisable(GL_TEXTURE_2D) | |
glColor(*mtl['Kd']) | |
glBegin(GL_POLYGON) | |
for i,v in enumerate(vertices): | |
if normals[i] > 0: | |
glNormal3fv(self.normals[normals[i] - 1]) | |
if texture_coords[i] > 0: | |
glTexCoord2fv(self.texcoords[texture_coords[i] - 1]) | |
if VERTEX_COLOR_EXTENSION: | |
glColor3ubv(colors[i]) | |
glVertex3fv(self.vertices[vertices[i] - 1]) | |
glEnd() | |
glDisable(GL_TEXTURE_2D) | |
glEndList() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment