python - 我应该在 OBJFileLoader 的“文件名”中放置什么?
问题描述
在https://www.pygame.org/wiki/OBJFileLoader找到的 OBJFileLoader 中,我应该用什么代替“文件名”。
在 Class OBJ 的行中: def init (self, filename, swapyz=False): 当我将完整路径放入 .obj 文件时,它说语法不正确。
新的错误信息:
Traceback (most recent call last):
File "C:/Users/Winter/PycharmProjects/Plane/Plane.py", line 26, in <module>
obj = OBJ('C:/Users/Winter/Desktop/TAL16OBJ.obj')
File "C:\Users\Winter\PycharmProjects\Plane\Main.py", line 86, in __init__
mtl = self.mtl[material]
AttributeError: 'OBJ' object has no attribute 'mtl'
这是当前代码:
import pygame
from OpenGL.GL import *
def MTL(filename):
contents = {}
mtl = None
for line in open("C:/Users/Winter/Desktop/TAL16OBJ.mtl", "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]] = list(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 = []
material = None
for line in open("C:/Users/Winter/Desktop/TAL16OBJ.obj", "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
v = list(map(float, values[1:4]))
if swapyz:
v = v[0], v[2], v[1]
self.vertices.append(v)
elif values[0] == 'vn':
v = list(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(list(map(float, values[1:3])))
elif values[0] in ('usemtl', 'usemat'):
material = values[1]
elif values[0] == 'mtllib':
self.mtl = MTL(values[1])
elif values[0] == 'f':
face = []
texcoords = []
norms = []
for v in values[1:]:
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))
self.gl_list = glGenLists(1)
glNewList(self.gl_list, GL_COMPILE)
glEnable(GL_TEXTURE_2D)
glFrontFace(GL_CCW)
for face in self.faces:
vertices, normals, texture_coords, material = face
mtl = self.mtl[material]
if 'texture_Kd' in mtl:
# use diffuse texmap
glBindTexture(GL_TEXTURE_2D, mtl['texture_Kd'])
else:
# just use diffuse colour
glColor(*mtl['Kd'])
glBegin(GL_POLYGON)
for i in range(len(vertices)):
if normals[i] > 0:
glNormal3fv(self.normals[normals[i] - 1])
if texture_coords[i] > 0:
glTexCoord2fv(self.texcoords[texture_coords[i] - 1])
glVertex3fv(self.vertices[vertices[i] - 1])
glEnd()
glDisable(GL_TEXTURE_2D)
glEndList()
from Main import *
import sys
import pygame
from pygame.locals import *
from pygame.constants import *
from OpenGL.GL import *
from OpenGL.GLU import *
pygame.init()
viewport = (800,600)
hx = viewport[0]/2
hy = viewport[1]/2
srf = pygame.display.set_mode(viewport, OPENGL | DOUBLEBUF)
glLightfv(GL_LIGHT0, GL_POSITION, (-40, 200, 100, 0.0))
glLightfv(GL_LIGHT0, GL_AMBIENT, (0.2, 0.2, 0.2, 1.0))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.5, 0.5, 0.5, 1.0))
glEnable(GL_LIGHT0)
glEnable(GL_LIGHTING)
glEnable(GL_COLOR_MATERIAL)
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH) # most obj files expect to be smooth-shaded
# LOAD OBJECT AFTER PYGAME INIT
obj = OBJ("C:/Users/Winter/Desktop/TAL16OBJ.obj")
clock = pygame.time.Clock()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
width, height = viewport
gluPerspective(90.0, width/float(height), 1, 100.0)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_MODELVIEW)
rx, ry = (0,0)
tx, ty = (0,0)
zpos = 5
rotate = move = False
while 1:
clock.tick(30)
for e in pygame.event.get():
if e.type == QUIT:
sys.exit()
elif e.type == KEYDOWN and e.key == K_ESCAPE:
sys.exit()
elif e.type == MOUSEBUTTONDOWN:
if e.button == 4: zpos = max(1, zpos-1)
elif e.button == 5: zpos += 1
elif e.button == 1: rotate = True
elif e.button == 3: move = True
elif e.type == MOUSEBUTTONUP:
if e.button == 1: rotate = False
elif e.button == 3: move = False
elif e.type == MOUSEMOTION:
i, j = e.rel
if rotate:
rx += i
ry += j
if move:
tx += i
ty -= j
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
# RENDER OBJECT
glTranslate(tx/20., ty/20., - zpos)
glRotate(ry, 1, 0, 0)
glRotate(rx, 0, 1, 0)
glCallList(obj.gl_list)
解决方案
由于AttributeError: 'OBJ' object has no attribute 'mtl'
.obj 文件中缺少材料,因此引发了 。在 .obj 文件的顶部应该有这样一行
mtllib NameOfYourMTLfile.mtl
指示应该为模型使用哪个材料/.mtl 文件。该模型可能未正确导出。
您必须pygame.display.flip()
在 while 循环的底部调用才能更新 pygame 窗口。
while 1:
# ... other code omitted.
# Call this at the bottom of the loop.
pygame.display.flip()
此外,在MTL
函数和OBJ
类中,您应该将filename
变量/参数传递给open
而不是这个字符串字面量"C:/Users/Winter/Desktop/TAL16OBJ.mtl"
。
def MTL(filename):
contents = {}
mtl = None
for line in open(filename, "r"): # open(filename)
class OBJ:
def __init__(self, filename, swapyz=False):
"""Loads a Wavefront OBJ file. """
self.vertices = []
self.normals = []
self.texcoords = []
self.faces = []
material = None
for line in open(filename, "r"): # open(filename)
推荐阅读
- javascript - 当我应用条件跳过键为偶数的数组值时,为什么会得到空结果?
- php - php中的日期错误,我无法在图表中显示日期
- c# - 使用 Spire.Presentation 在 PowerPoint 中嵌入 YouTube 视频
- node.js - 如何在node.js中的amazon s3中获取存储桶中任何资源的最后访问日期?
- java - 无法写入核心转储 ulimit -c 尝试了一切都不起作用
- python - python 龙卷风应用程序中活动的进程数
- scala - Spark2 Scala Dataframe 列重命名需要很长时间
- java - Writing Unicode plane 1 characters with Apache POI
- sql-server - SQL Server: How to replace carriage return characters
- android - 我如何在 Google Exoplayer 中访问原始样本