code: def load_obj(fn):
      """Load 3d mesh form .obj' file.
  
      Args:
        fn: Input file name or file-like object.
  
      Returns:
        dictionary with the following keys (some of which may be missing):
          position: np.float32, (n, 3) array, vertex positions
          uv: np.float32, (n, 2) array, vertex uv coordinates
          normal: np.float32, (n, 3) array, vertex uv normals
          face: np.int32, (k*3,) traingular face indices
      """
      position = [np.zeros(3, dtype=np.float32)]
      normal = [np.zeros(3, dtype=np.float32)]
      uv = [np.zeros(2, dtype=np.float32)]
  
      tuple2idx = OrderedDict()
      trinagle_indices = []
  
      input_file = open(fn) if isinstance(fn, str) else fn
      for line in input_file:
          line = line.strip()
          if not line or line[0] == "#":
              continue
          line = line.split(" ", 1)
          tag = line[0]
          if len(line) > 1:
              line = line[1]
          else:
              line = ""
          if tag == "v":
              position.append(np.fromstring(line, sep=" "))
          elif tag == "vt":
              uv.append(np.fromstring(line, sep=" "))
          elif tag == "vn":
              normal.append(np.fromstring(line, sep=" "))
          elif tag == "f":
              output_face_indices = []
              for chunk in line.split():
                  # tuple order: pos_idx, uv_idx, normal_idx
                  vt = _parse_vertex_tuple(chunk)
                  if vt not in tuple2idx:  # create a new output vertex?
                      tuple2idx[vt] = len(tuple2idx)
                  output_face_indices.append(tuple2idx[vt])
              # generate face triangles
              for i in range(1, len(output_face_indices) - 1):
                  for vi in [0, i, i + 1]:
                      trinagle_indices.append(output_face_indices[vi])
  
      outputs = {}
      outputs["face"] = np.int32(trinagle_indices)
      pos_idx, uv_idx, normal_idx = np.int32(list(tuple2idx)).T
      if np.any(pos_idx):
          outputs["position"] = _unify_rows(position)[pos_idx]
      if np.any(uv_idx):
          outputs["uv"] = _unify_rows(uv)[uv_idx]
      if np.any(normal_idx):
          outputs["normal"] = _unify_rows(normal)[normal_idx]
      return outputs
  
file_path: lucid/lucid/misc/gl/meshutil.py
imports: from builtins import str
  from collections import OrderedDict
  import numpy
label_desc: Use image node_id 10 for calling a global function with example usage: load_obj(fn) and returns: outputs