in code/python/lib/obj_file_utils.py [0:0]
def load_obj_file(filename):
class obj_file:
def __init__(self, filename):
self._vertices = []
self._texcoords = []
self._normals = []
self._faces = []
self._material_files = []
self._material_names = []
self._object_names = []
self._group_names = []
object_name_curr = "_NULL_OBJECT"
group_name_curr = "_NULL_GROUP"
material_name_curr = "_NULL_MATERIAL"
print("[HYPERSIM: OBJ_FILE_UTILS] Begin load_obj_file...")
print("[HYPERSIM: OBJ_FILE_UTILS] Parsing " + filename + "...")
for line in open(filename, "r"):
line = line.strip()
# hack for OBJ files exported from Unreal
if line.startswith("#") or line.startswith("\xef\xbb\xbf#"):
continue
values = line.split()
if not values or len(values) == 0:
continue
if values[0] in ["mtllib", "matlib"]:
try:
material_file = values[1]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
material_file = "_ERROR_MATERIAL_FILE"
self._material_files.append(material_file)
elif values[0] == "v":
if len(values) == 4:
try:
vertex = [float(values[1]), float(values[2]), float(values[3])]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
vertex = [0.0,0.0,0.0]
else:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
vertex = [0.0,0.0,0.0]
self._vertices.append(vertex)
elif values[0] == "vn":
if len(values) == 4:
try:
vertex_normal = [float(values[1]), float(values[2]), float(values[3])]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + values)
vertex_normal = [0.0,0.0,0.0]
else:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
vertex_normal = [0.0,0.0,0.0]
self._normals.append(vertex_normal)
elif values[0] == "vt":
if len(values) == 3:
try:
vertex_texcoords = [float(values[1]), float(values[2])]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
vertex_texcoords = [0.0,0.0]
elif len(values) == 4:
try:
# HACK: in this case we assume 3 texture coordinates are exported in the obj file, but only the first 2 are stored
vertex_texcoords = [float(values[1]), float(values[2])]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
vertex_texcoords = [0.0,0.0]
else:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
vertex_texcoords = [0.0,0.0]
self._texcoords.append(vertex_texcoords)
elif values[0] == "o":
try:
object_name_curr = values[1]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
object_name_curr = "_ERROR_OBJECT"
self._object_names.append(object_name_curr)
elif values[0] == "g":
try:
group_name_curr = values[1]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
group_name_curr = "_ERROR_GROUP"
self._group_names.append(group_name_curr)
elif values[0] in ("usemtl", "usemat"):
try:
material_name_curr = values[1]
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
material_name_curr = "_ERROR_MATERIAL"
self._material_names.append(material_name_curr)
elif values[0] == "f":
face_vi = []
face_vti = []
face_vni = []
if len(values) == 4:
for v in values[1:4]:
w = v.split("/")
# v1
if len(w) == 1:
try:
f_vi = int(w[0])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vi = 0
face_vi.append(f_vi)
# v1/vt1
elif len(w) == 2:
try:
f_vi = int(w[0])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vi = 0
try:
f_vti = int(w[1])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vti = 0
face_vi.append(f_vi)
face_vti.append(f_vti)
# v1//vn1
elif len(w) == 3 and len(w[1]) == 0:
try:
f_vi = int(w[0])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vi = 0
try:
f_vni = int(w[2])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vni = 0
face_vi.append(f_vi)
face_vni.append(f_vni)
# v1/vt1/vn1
elif len(w) == 3 and len(w[1]) > 0:
try:
f_vi = int(w[0])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vi = 0
try:
f_vti = int(w[1])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vti = 0
try:
f_vni = int(w[2])
except ValueError:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
f_vni = 0
face_vi.append(f_vi)
face_vti.append(f_vti)
face_vni.append(f_vni)
else:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
else:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
if len(face_vi) != 3:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
face_vi = [0,0,0] # OBJ files are 1-indexed, so [0,0,0] is equivalent to assigning [null,null,null]
if len(face_vti) != 3:
if len(face_vti) != 0:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
face_vti = [0,0,0] # OBJ files are 1-indexed, so [0,0,0] is equivalent to assigning [null,null,null]
if len(face_vni) != 3:
if len(face_vni) != 0:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + " ".join(values))
face_vni = [0,0,0] # OBJ files are 1-indexed, so [0,0,0] is equivalent to assigning [null,null,null]
self._faces.append((object_name_curr, group_name_curr, material_name_curr, face_vi, face_vti, face_vni))
else:
print("[HYPERSIM: OBJ_FILE_UTILS] ERROR: Couldn't parse: " + line)
print("[HYPERSIM: OBJ_FILE_UTILS] Loading material files...")
self.material_file_data = {}
self.material_param_map = {}
for material_file in self._material_files:
material_file_data = load_mtl_file(os.path.dirname(os.path.abspath(filename)) + "/" + material_file)
self.material_file_data[material_file] = material_file_data
self.material_param_map.update(material_file_data.material_param_map)
print("[HYPERSIM: OBJ_FILE_UTILS] Uniquifying object names, group names, and material names...")
self.object_names = pd.Series(self._object_names).drop_duplicates().tolist()
self.group_names = pd.Series(self._group_names).drop_duplicates().tolist()
self.material_names = pd.Series(self._material_names).drop_duplicates().tolist()
print("[HYPERSIM: OBJ_FILE_UTILS] Constructing numpy arrays...")
self.vertices = array(self._vertices)
self.texcoords = array(self._texcoords)
self.normals = array(self._normals)
object_name_id_map = dict(zip(self.object_names, range(len(self.object_names))))
group_name_id_map = dict(zip(self.group_names, range(len(self.group_names))))
material_name_id_map = dict(zip(self.material_names, range(len(self.material_names))))
object_name_id_map["_NULL_OBJECT"] = -1
group_name_id_map["_NULL_GROUP"] = -1
material_name_id_map["_NULL_MATERIAL"] = -1
self.faces_oi = array([ object_name_id_map[f[0]] for f in self._faces ])
self.faces_gi = array([ group_name_id_map[f[1]] for f in self._faces ])
self.faces_mi = array([ material_name_id_map[f[2]] for f in self._faces ])
self.faces_vi = array([ f[3] for f in self._faces ]) - 1
self.faces_vti = array([ f[4] for f in self._faces ]) - 1
self.faces_vni = array([ f[5] for f in self._faces ]) - 1
print("[HYPERSIM: OBJ_FILE_UTILS] Finished.")
def __repr__(self):
_str = ""
_str = _str + "material_file_data\n" + str(self.material_file_data) + "\n"
_str = _str + "object_names\n" + str(self.object_names) + "\n"
_str = _str + "group_names\n" + str(self.group_names) + "\n"
_str = _str + "material_names\n" + str(self.material_names) + "\n"
_str = _str + "material_param_map\n" + str(self.material_param_map) + "\n"
_str = _str + "vertices\n" + str(self.vertices.dtype) + "\n" + str(self.vertices.shape) + "\n" + str(self.vertices) + "\n"
_str = _str + "texcoords\n" + str(self.texcoords.dtype) + "\n" + str(self.texcoords.shape) + "\n" + str(self.texcoords) + "\n"
_str = _str + "normals\n" + str(self.normals.dtype) + "\n" + str(self.normals.shape) + "\n" + str(self.normals) + "\n"
_str = _str + "faces_oi\n" + str(self.faces_oi.dtype) + "\n" + str(self.faces_oi.shape) + "\n" + str(self.faces_oi) + "\n"
_str = _str + "faces_gi\n" + str(self.faces_gi.dtype) + "\n" + str(self.faces_gi.shape) + "\n" + str(self.faces_gi) + "\n"
_str = _str + "faces_mi\n" + str(self.faces_mi.dtype) + "\n" + str(self.faces_mi.shape) + "\n" + str(self.faces_mi) + "\n"
_str = _str + "faces_vi\n" + str(self.faces_vi.dtype) + "\n" + str(self.faces_vi.shape) + "\n" + str(self.faces_vi) + "\n"
_str = _str + "faces_vti\n" + str(self.faces_vti.dtype) + "\n" + str(self.faces_vti.shape) + "\n" + str(self.faces_vti) + "\n"
_str = _str + "faces_vni\n" + str(self.faces_vni.dtype) + "\n" + str(self.faces_vni.shape) + "\n" + str(self.faces_vni) + "\n"
return _str
return obj_file(filename)