parameters: (path, with_materials=False, with_normals=False,
                  error_handler=None)
return_statement: return return_type(vertices, faces, uvs, face_uvs_idx, materials,
                         materials_order, vertex_normals, face_normals)
docstring: r"""Load data from an obj file as a single mesh.
  
      With limited materials support to Kd, Ka, Ks, map_Kd, map_Ka and map_Ks.
      Followed format described in: http://paulbourke.net/dataformats/obj/
  
      Args:
          path (str): path to the obj file (with extension).
          with_materials (bool): if True, load materials. Default: False.
          with_normals (bool): if True, load vertex normals. Default: False.
          error_handler (Callable, optional):
              function that handle errors that may happen during file processing,
              with following signature:
              ``error_handler(error: Exception, material_name: Optional[str],
              materials: Optional[list[dict]], materials_order: Optional[list])``.
              Default: raise all errors.
  
      Returns:
          (obj.return_type):
              nametuple of:
  
              - **vertices** (torch.Tensor): of shape :math:`(\text{num_vertices}, 3)`.
              - **faces** (torch.LongTensor):
                of shape :math:`(\text{num_faces}, \text{face_size})`.
              - **uvs** (torch.Tensor): of shape :math:`(\text{num_uvs}, 2)`.
              - **face_uvs_idx** (torch.LongTensor):
                of shape :math:`(\text{num_faces}, \text{face_size})`.
              - **materials** (list of dict):
                a list of materials (see return values of :func:`load_mtl`).
              - **materials_order** (torch.LongTensor):
                of shape :math:`(\text{num_same_material_groups}, 2)`.
                showing the order in which materials are used over **face_uvs_idx**
                and the first indices in which they start to be used.
                A material can be used multiple times.
              - **vertex_normals** (torch.Tensor): of shape :math:`(\text{num_vertices}, 3)`.
              - **face_normals** (torch.LongTensor):
                of shape :math:`(\text{num_faces}, \text{face_size})`.
  
      Raises:
          MaterialNotFoundError:
              The .obj is using a material that haven't be found in the material files
          MaterialLoadError:
              From :func:`load_mtl`: Failed to load material,
              very often due to path to map_Kd/map_Ka/map_ks being invalid.
docstring_summary: r"""Load data from an obj file as a single mesh.
docstring_tokens: r Load data from an obj file as a single mesh .
function: def import_mesh(path, with_materials=False, with_normals=False,
                  error_handler=None):
      r"""Load data from an obj file as a single mesh.
  
      With limited materials support to Kd, Ka, Ks, map_Kd, map_Ka and map_Ks.
      Followed format described in: http://paulbourke.net/dataformats/obj/
  
      Args:
          path (str): path to the obj file (with extension).
          with_materials (bool): if True, load materials. Default: False.
          with_normals (bool): if True, load vertex normals. Default: False.
          error_handler (Callable, optional):
              function that handle errors that may happen during file processing,
              with following signature:
              ``error_handler(error: Exception, material_name: Optional[str],
              materials: Optional[list[dict]], materials_order: Optional[list])``.
              Default: raise all errors.
  
      Returns:
          (obj.return_type):
              nametuple of:
  
              - **vertices** (torch.Tensor): of shape :math:`(\text{num_vertices}, 3)`.
              - **faces** (torch.LongTensor):
                of shape :math:`(\text{num_faces}, \text{face_size})`.
              - **uvs** (torch.Tensor): of shape :math:`(\text{num_uvs}, 2)`.
              - **face_uvs_idx** (torch.LongTensor):
                of shape :math:`(\text{num_faces}, \text{face_size})`.
              - **materials** (list of dict):
                a list of materials (see return values of :func:`load_mtl`).
              - **materials_order** (torch.LongTensor):
                of shape :math:`(\text{num_same_material_groups}, 2)`.
                showing the order in which materials are used over **face_uvs_idx**
                and the first indices in which they start to be used.
                A material can be used multiple times.
              - **vertex_normals** (torch.Tensor): of shape :math:`(\text{num_vertices}, 3)`.
              - **face_normals** (torch.LongTensor):
                of shape :math:`(\text{num_faces}, \text{face_size})`.
  
      Raises:
          MaterialNotFoundError:
              The .obj is using a material that haven't be found in the material files
          MaterialLoadError:
              From :func:`load_mtl`: Failed to load material,
              very often due to path to map_Kd/map_Ka/map_ks being invalid.
      """
      if error_handler is None:
          error_handler = default_error_handler
      vertices = []
      faces = []
      uvs = []
      # 3 values per face
      face_uvs_idx = []
      vertex_normals = []
      # 3 values per face
      face_normals = []
      # textures = []
      mtl_path = None
      materials_order = []
      materials_dict = {}
      materials_idx = {}
  
      with open(path, 'r', encoding='utf-8') as f:
          for line in f:
              data = line.split()
              if len(data) == 0:
                  continue
              if data[0] == 'v':
                  vertices.append(data[1:])
              elif with_materials and data[0] == 'vt':
                  uvs.append(data[1:3])
              elif with_normals and data[0] == 'vn':
                  vertex_normals.append(data[1:])
              elif data[0] == 'f':
                  data = [da.split('/') for da in data[1:]]
                  faces.append([int(d[0]) for d in data])
                  if with_materials:
                      if len(data[1]) > 1 and data[1][1] != '':
                          face_uvs_idx.append([int(d[1]) for d in data])
                      else:
                          face_uvs_idx.append([0, 0, 0])
                  if with_normals:
                      if len(data[1]) > 2:
                          face_normals.append([int(d[2]) for d in data])
                      else:
                          face_normals.append([0, 0, 0])
              elif with_materials and data[0] == 'usemtl':
                  material_name = data[1]
                  if material_name not in materials_idx:
                      materials_idx[material_name] = len(materials_idx)
                  materials_order.append([materials_idx[material_name], len(face_uvs_idx)])
              elif with_materials and data[0] == 'mtllib':
                  mtl_path = os.path.join(os.path.dirname(path), data[1])
                  materials_dict.update(load_mtl(mtl_path, error_handler))
  
      # building materials in right order
      materials = [{} for i in materials_idx]
      for material_name, idx in materials_idx.items():
          if material_name not in materials_dict:
              error_handler(
                  MaterialNotFoundError(f"'{material_name}' not found."),
                  material_name=material_name, idx=idx,
                  materials=materials, materials_order=materials_order)
          else:
              materials[idx] = materials_dict[material_name]
  
      vertices = torch.FloatTensor([float(el) for sublist in vertices
                                    for el in sublist]).view(-1, 3)
      faces = torch.LongTensor(faces) - 1
  
      if with_materials:
          uvs = torch.FloatTensor([float(el) for sublist in uvs
                                   for el in sublist]).view(-1, 2)
          face_uvs_idx = torch.LongTensor(face_uvs_idx) - 1
          materials_order = torch.LongTensor(materials_order)
      else:
          uvs = None
          face_uvs_idx = None
          materials = None
          materials_order = None
  
      if with_normals:
          vertex_normals = torch.FloatTensor(
              [float(el) for sublist in vertex_normals
               for el in sublist]).view(-1, 3)
          face_normals = torch.LongTensor(face_normals) - 1
      else:
          vertex_normals = None
          face_normals = None
  
      return return_type(vertices, faces, uvs, face_uvs_idx, materials,
                         materials_order, vertex_normals, face_normals)
function_tokens: def import_mesh ( path , with_materials = False , with_normals = False , error_handler = None ) : if error_handler is None : error_handler = default_error_handler vertices = [ ] faces = [ ] uvs = [ ] # 3 values per face face_uvs_idx = [ ] vertex_normals = [ ] # 3 values per face face_normals = [ ] # textures = [] mtl_path = None materials_order = [ ] materials_dict = { } materials_idx = { } with open ( path , 'r' , encoding = 'utf-8' ) as f : for line in f : data = line . split ( ) if len ( data ) == 0 : continue if data [ 0 ] == 'v' : vertices . append ( data [ 1 : ] ) elif with_materials and data [ 0 ] == 'vt' : uvs . append ( data [ 1 : 3 ] ) elif with_normals and data [ 0 ] == 'vn' : vertex_normals . append ( data [ 1 : ] ) elif data [ 0 ] == 'f' : data = [ da . split ( '/' ) for da in data [ 1 : ] ] faces . append ( [ int ( d [ 0 ] ) for d in data ] ) if with_materials : if len ( data [ 1 ] ) > 1 and data [ 1 ] [ 1 ] != '' : face_uvs_idx . append ( [ int ( d [ 1 ] ) for d in data ] ) else : face_uvs_idx . append ( [ 0 , 0 , 0 ] ) if with_normals : if len ( data [ 1 ] ) > 2 : face_normals . append ( [ int ( d [ 2 ] ) for d in data ] ) else : face_normals . append ( [ 0 , 0 , 0 ] ) elif with_materials and data [ 0 ] == 'usemtl' : material_name = data [ 1 ] if material_name not in materials_idx : materials_idx [ material_name ] = len ( materials_idx ) materials_order . append ( [ materials_idx [ material_name ] , len ( face_uvs_idx ) ] ) elif with_materials and data [ 0 ] == 'mtllib' : mtl_path = os . path . join ( os . path . dirname ( path ) , data [ 1 ] ) materials_dict . update ( load_mtl ( mtl_path , error_handler ) ) # building materials in right order materials = [ { } for i in materials_idx ] for material_name , idx in materials_idx . items ( ) : if material_name not in materials_dict : error_handler ( MaterialNotFoundError ( f"'{material_name}' not found." ) , material_name = material_name , idx = idx , materials = materials , materials_order = materials_order ) else : materials [ idx ] = materials_dict [ material_name ] vertices = torch . FloatTensor ( [ float ( el ) for sublist in vertices for el in sublist ] ) . view ( - 1 , 3 ) faces = torch . LongTensor ( faces ) - 1 if with_materials : uvs = torch . FloatTensor ( [ float ( el ) for sublist in uvs for el in sublist ] ) . view ( - 1 , 2 ) face_uvs_idx = torch . LongTensor ( face_uvs_idx ) - 1 materials_order = torch . LongTensor ( materials_order ) else : uvs = None face_uvs_idx = None materials = None materials_order = None if with_normals : vertex_normals = torch . FloatTensor ( [ float ( el ) for sublist in vertex_normals for el in sublist ] ) . view ( - 1 , 3 ) face_normals = torch . LongTensor ( face_normals ) - 1 else : vertex_normals = None face_normals = None return return_type ( vertices , faces , uvs , face_uvs_idx , materials , materials_order , vertex_normals , face_normals )