Skip to content

Commit 878236a

Browse files
committed
Missing material properties + tests
1 parent d624aae commit 878236a

File tree

5 files changed

+117
-30
lines changed

5 files changed

+117
-30
lines changed

pywavefront/material.py

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,15 @@ def __init__(self, name, is_default=False):
5252
self.ambient = [.2, .2, .2, 1.]
5353
self.specular = [0., 0., 0., 1.]
5454
self.emissive = [0., 0., 0., 1.]
55+
self.transparency = 1.0
5556
self.shininess = 0.
56-
self.texture = None
57+
self.texture = None # diffuse
58+
self.texture_ambient = None
59+
self.texture_specular_color = None
60+
self.texture_specular_highlight = None
61+
self.texture_alpha = None
62+
self.texture_bump = None
63+
5764
self.is_default = is_default
5865

5966
# Interleaved array of floats in GL_T2F_N3F_V3F format
@@ -62,11 +69,6 @@ def __init__(self, name, is_default=False):
6269

6370
self.gl_floats = None
6471

65-
@property
66-
def file(self):
67-
"""File with full path"""
68-
return os.path.join(self.path, self.name)
69-
7072
@property
7173
def has_normals(self):
7274
return "N3F" in self.vertex_format
@@ -95,7 +97,7 @@ def pad_light(self, values):
9597

9698
def set_alpha(self, alpha):
9799
"""Set alpha/last value on all four lighting attributes."""
98-
alpha = float(alpha)
100+
self.transparency = alpha
99101
self.diffuse[3] = alpha
100102
self.ambient[3] = alpha
101103
self.specular[3] = alpha
@@ -116,6 +118,21 @@ def set_emissive(self, values=None):
116118
def set_texture(self, path):
117119
self.texture = Texture(path)
118120

121+
def set_texture_ambient(self, path):
122+
self.texture_ambient = Texture(path)
123+
124+
def set_texture_specular_color(self, path):
125+
self.texture_specular_color = Texture(path)
126+
127+
def set_texture_specular_highlight(self, path):
128+
self.texture_specular_highlight = Texture(path)
129+
130+
def set_texture_alpha(self, path):
131+
self.texture_alpha = Texture(path)
132+
133+
def set_texture_bump(self, path):
134+
self.texture_bump = Texture(path)
135+
119136
def unset_texture(self):
120137
self.texture = None
121138

@@ -166,24 +183,57 @@ def parse_Ns(self):
166183

167184
@auto_consume
168185
def parse_d(self):
169-
self.this_material.set_alpha(self.values[1])
186+
"""Transparency"""
187+
self.this_material.set_alpha(float(self.values[1]))
188+
189+
@auto_consume
190+
def parse_Tr(self):
191+
"""Transparency (alternative)"""
192+
self.this_material.set_alpha(1.0 - float(self.values[1]))
170193

171194
@auto_consume
172195
def parse_map_Kd(self):
196+
"""Diffuse map"""
173197
Kd = os.path.join(self.dir, " ".join(self.values[1:]))
174198
self.this_material.set_texture(Kd)
175199

176200
@auto_consume
177-
def parse_Ni(self):
178-
# unimplemented
179-
pass
201+
def parse_map_Ka(self):
202+
"""Ambient map"""
203+
Kd = os.path.join(self.dir, " ".join(self.values[1:]))
204+
self.this_material.set_texture_ambient(Kd)
180205

181206
@auto_consume
182-
def parse_Tr(self):
183-
# unimplemented
207+
def parse_map_Ks(self):
208+
"""Specular color map"""
209+
Kd = os.path.join(self.dir, " ".join(self.values[1:]))
210+
self.this_material.set_texture_specular_color(Kd)
211+
212+
@auto_consume
213+
def parse_map_Ns(self):
214+
"""Specular color map"""
215+
Kd = os.path.join(self.dir, " ".join(self.values[1:]))
216+
self.this_material.set_texture_specular_highlight(Kd)
217+
218+
@auto_consume
219+
def parse_map_d(self):
220+
"""Aplha map"""
221+
Kd = os.path.join(self.dir, " ".join(self.values[1:]))
222+
self.this_material.set_texture_alpha(Kd)
223+
224+
@auto_consume
225+
def parse_map_bump(self):
226+
"""Bump map"""
227+
Kd = os.path.join(self.dir, " ".join(self.values[1:]))
228+
self.this_material.set_texture_bump(Kd)
229+
230+
def parse_bump(self):
231+
self.parse_map_bump()
232+
233+
@auto_consume
234+
def parse_Ni(self):
184235
pass
185236

186237
@auto_consume
187238
def parse_illum(self):
188-
# unimplemented
189239
pass

pywavefront/visualization.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ def draw_material(material, face=GL_FRONT_AND_BACK):
8787
glEnable(GL_CULL_FACE)
8888
glCullFace(GL_BACK)
8989

90-
if material.texture and material.has_uvs:
91-
bind_texture(material.texture)
90+
# Fall back to ambient texture if no diffuse
91+
texture = material.texture or material.texture_ambient
92+
if texture and material.has_uvs:
93+
bind_texture(texture)
9294
else:
9395
glDisable(GL_TEXTURE_2D)
9496

test/simple_parsetest.mtl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Comment
2+
newmtl Material.simple
3+
Ns 1.0
4+
Ka 0.0 0.0 0.0
5+
Kd 0.1 0.1 0.1
6+
Ks 0.2 0.2 0.2
7+
d 1.0
8+
Tr 0.0
9+
map_Kd kd.png
10+
map_Ka ka.png
11+
map_Ks ks.png
12+
map_Ns ns.png
13+
map_d d.png
14+
map_bump bump.png
15+
bump bump.png
16+
newmtl Material2.simple
17+
Ns 1.0
18+
Ka 0.0 0.0 0.0
19+
Kd 0.64 0.64 0.64
20+
Ks 0.5 0.5 0.5
21+
d 1.0
22+
map_Kd 4x4.png

test/test_material.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ def setUp(self):
1313
# Append current path to locate files
1414
self.material = pywavefront.material.Material(prepend_dir('material'))
1515
self.material.set_texture(prepend_dir('4x4.png'))
16+
self.material.set_texture_ambient(prepend_dir('4x4.png'))
1617

1718
def testSetTexture(self):
1819
"""Running set_texture should set a texture."""
19-
self.assertEqual(self.material.texture.__class__,
20-
pywavefront.texture.Texture)
20+
self.assertEqual(self.material.texture.__class__, pywavefront.texture.Texture)
21+
self.assertEqual(self.material.texture_ambient.__class__, pywavefront.texture.Texture)
22+
23+
self.assertEqual(self.material.texture.path, prepend_dir('4x4.png'))
24+
self.assertEqual(self.material.texture_ambient.path, prepend_dir('4x4.png'))
2125

2226
def testUnsetTexture(self):
2327
"""Running unset_texture should set texture to None."""
@@ -57,6 +61,9 @@ def testSetEmissive(self):
5761
self.material.set_emissive()
5862
self.assertEqual(self.material.emissive, [0., 0., 0., 0.])
5963

64+
def testTransparency(self):
65+
self.assertEqual(self.material.transparency, 1.0)
66+
6067

6168
class TestInvalidMaterial(unittest.TestCase):
6269

test/test_parser.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import pywavefront.parser
55
from pywavefront.exceptions import PywavefrontException
6-
6+
from pywavefront.material import MaterialParser
77

88
def prepend_dir(file):
99
return os.path.join(os.path.dirname(__file__), file)
@@ -151,15 +151,16 @@ def testObjColors(self):
151151

152152
class TestMtlParser(unittest.TestCase):
153153
def setUp(self):
154-
# Append current path to locate files
155-
meshes = pywavefront.Wavefront(prepend_dir('simple.obj'))
156-
self.material1 = meshes.mesh_list[0].materials[0]
157-
self.material2 = meshes.mesh_list[1].materials[0]
154+
parser = MaterialParser(prepend_dir('simple_parsetest.mtl'))
155+
self.materials = parser.materials
156+
self.material1 = self.materials['Material.simple']
157+
self.material2 = self.materials['Material2.simple']
158158

159159
def testMtlName(self):
160160
"""Parsing an obj file with known material names should set those names."""
161-
self.assertEqual(self.material1.name, 'Material.simple')
162-
self.assertEqual(self.material2.name, 'Material2.simple')
161+
print(self.materials)
162+
self.assertIn('Material.simple', self.materials.keys())
163+
self.assertIn('Material2.simple', self.materials.keys())
163164

164165
def testMtlShininess(self):
165166
"""Parsing an obj file with known material shininess should set it."""
@@ -180,11 +181,16 @@ def testMtlSpecular(self):
180181
# also tests d
181182
self.assertEqual(self.material1.specular, [0.2, 0.2, 0.2, 1.])
182183

183-
def testMtlTextureName(self):
184-
"""Parsing an obj file with known material texture should set its name."""
185-
# also tests d
186-
self.assertEqual(self.material1.texture.path,
187-
prepend_dir('4x4.png'))
184+
def testMtlTransparency(self):
185+
self.assertEqual(self.material1.transparency, 1.0)
186+
187+
def testTextures(self):
188+
self.assertEqual(self.material1.texture.path, prepend_dir('kd.png'))
189+
self.assertEqual(self.material1.texture_ambient.path, prepend_dir('ka.png'))
190+
self.assertEqual(self.material1.texture_specular_color.path, prepend_dir('ks.png'))
191+
self.assertEqual(self.material1.texture_specular_highlight.path, prepend_dir('ns.png'))
192+
self.assertEqual(self.material1.texture_alpha.path, prepend_dir('d.png'))
193+
self.assertEqual(self.material1.texture_bump.path, prepend_dir('bump.png'))
188194

189195

190196
class TestParserFailure(unittest.TestCase):

0 commit comments

Comments
 (0)