Repository: mikedh/trimesh

Issue:
List Index out of Range when loading .obj
Hi, I am trying to load .obj model that I created with blender but I am having issues. It seems to work fine with .ply or .stl format. The error I keep getting is "Indexerror: list index out of range"

Traceback (most recent call last):
  File ".\pyrenderTest.py", line 14, in <module>
    road = trimesh.load('C:/Users/walit/Downloads/Surface/surface.obj', file_type='OBJ')
  File "C:\Program Files\Python37\lib\site-packages\trimesh\exchange\load.py", line 136, in load
    **kwargs)
  File "C:\Program Files\Python37\lib\site-packages\trimesh\constants.py", line 136, in timed
    result = method(*args, **kwargs)
  File "C:\Program Files\Python37\lib\site-packages\trimesh\exchange\load.py", line 212, in load_mesh
    **kwargs)
  File "C:\Program Files\Python37\lib\site-packages\trimesh\exchange\obj.py", line 80, in load_obj
    v, vn, vt, vc = _parse_vertices(text=text)
  File "C:\Program Files\Python37\lib\site-packages\trimesh\exchange\obj.py", line 513, in _parse_vertices
    per_row = {k: len(v[1].split()) for k, v in data.items()}
  File "C:\Program Files\Python37\lib\site-packages\trimesh\exchange\obj.py", line 513, in <dictcomp>
    per_row = {k: len(v[1].split()) for k, v in data.items()}
IndexError: list index out of range


Here is my .obj

# Blender v2.80 (sub 75) OBJ File: ''
# www.blender.org
mtllib surface.mtl

o textureSurface
v -500.000000 0.000000 500.000000
v 500.000000 0.000000 500.000000
v 500.000000 0.000000 -500.000000
v -500.000000 0.000000 -500.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 0.0000 1.0000 0.0000
usemtl Material
s 1
f 1/1/1 2/2/1 3/3/1
f 1/1/1 3/3/1 4/4/1

Thank you in advance for you help!


Discussion:

Patch:
diff --git a/models/singlevn.obj b/models/singlevn.obj
new file mode 100644
index 00000000..e95807d3
--- /dev/null
+++ b/models/singlevn.obj
@@ -0,0 +1,16 @@
+mtllib surface.mtl
+
+o textureSurface
+v -500.000000 0.000000 500.000000
+v 500.000000 0.000000 500.000000
+v 500.000000 0.000000 -500.000000
+v -500.000000 0.000000 -500.000000
+vt 0.000000 0.000000
+vt 1.000000 0.000000
+vt 1.000000 1.000000
+vt 0.000000 1.000000
+vn 0.0000 1.0000 0.0000
+usemtl Material
+s 1
+f 1/1/1 2/2/1 3/3/1
+f 1/1/1 3/3/1 4/4/1
diff --git a/trimesh/exchange/load.py b/trimesh/exchange/load.py
index e84aec9e..2d38f240 100644
--- a/trimesh/exchange/load.py
+++ b/trimesh/exchange/load.py
@@ -575,6 +575,7 @@ def parse_file_args(file_obj,
     # if we still have no resolver try using file_obj name
     if (resolver is None and
         hasattr(file_obj, 'name') and
+        file_obj.name is not None and
             len(file_obj.name) > 0):
         resolver = visual.resolvers.FilePathResolver(file_obj.name)
 
diff --git a/trimesh/exchange/obj.py b/trimesh/exchange/obj.py
index 978c9060..ea6491fd 100644
--- a/trimesh/exchange/obj.py
+++ b/trimesh/exchange/obj.py
@@ -510,7 +510,7 @@ def _parse_vertices(text):
             for k, v in starts.items() if v >= 0}
 
     # count the number of data values per row on a sample row
-    per_row = {k: len(v[1].split()) for k, v in data.items()}
+    per_row = {k: len(v[0].split()) for k, v in data.items()}
 
     # convert data values into numpy arrays
     result = collections.defaultdict(lambda: None)
diff --git a/trimesh/path/path.py b/trimesh/path/path.py
index f515ee17..8e41c6df 100644
--- a/trimesh/path/path.py
+++ b/trimesh/path/path.py
@@ -102,11 +102,10 @@ class Path(object):
         """
         Print a quick summary of the number of vertices and entities.
         """
-        r = '<trimesh.{}(vertices.shape={}, len(entities)={})>'.format(
+        return '<trimesh.{}(vertices.shape={}, len(entities)={})>'.format(
             type(self).__name__,
             self.vertices.shape,
             len(self.entities))
-        return r
 
     def process(self):
         """
@@ -124,7 +123,8 @@ class Path(object):
 
     @vertices.setter
     def vertices(self, values):
-        self._vertices = caching.tracked_array(values, dtype=np.float64)
+        self._vertices = caching.tracked_array(
+            values, dtype=np.float64)
 
     @property
     def entities(self):
diff --git a/trimesh/version.py b/trimesh/version.py
index ec0a0cc4..257e0a57 100644
--- a/trimesh/version.py
+++ b/trimesh/version.py
@@ -1,1 +1,1 @@
-__version__ = '3.4.6'
+__version__ = '3.4.7'


Test patch:
diff --git a/tests/test_obj.py b/tests/test_obj.py
index 2c0c24b9..cbd6aa66 100644
--- a/tests/test_obj.py
+++ b/tests/test_obj.py
@@ -119,6 +119,14 @@ class OBJTest(g.unittest.TestCase):
         # assert colors have survived the export cycle
         assert (mesh.visual.vertex_colors == rec.visual.vertex_colors).all()
 
+    def test_single_vn(self):
+        """
+        Make sure files with a single VN load.
+        """
+        m = g.get_mesh('singlevn.obj')
+        assert len(m.vertices) > 0
+        assert len(m.faces) > 0
+
 
 if __name__ == '__main__':
     g.trimesh.util.attach_to_log()