import re
import numpy as np
import ddg
def _read_obj(filename):
data = {
"filetype": None,
"indexedfs": None,
"halfedgeds": None,
"v": [],
"f": [],
"vt": [],
"vn": [],
"vt_face_idx": [],
"vn_face_idx": [],
}
f = open(filename, "r", encoding="utf8", errors="ignore")
for line in f:
if line.startswith(("v", "vt", "vn")):
data[line.split()[0]].append(
[
float(s)
for s in re.findall(
r"[-+]?\d*\.\d+(?:[eE][-+]?\d+)?|[-+]?\d+(?:[eE][-+]?\d+)?",
line,
)
]
)
if line.startswith("f"):
data["f"].append(line[1:])
f.close()
if not data["vt"] and not data["vn"]:
data["filetype"] = "0"
if data["vt"] and not data["vn"]:
data["filetype"] = "T"
if not data["vt"] and data["vn"]:
data["filetype"] = "N"
if data["vt"] and data["vn"]:
data["filetype"] = "TN"
for face in data["f"]:
if data["filetype"] == "T":
data["vt_face_idx"].append(
[int(s[1:]) - 1 for s in re.findall(r"/\d+", face)]
)
if data["filetype"] == "N":
data["vn_face_idx"].append(
[int(s[1:]) - 1 for s in re.findall(r"/\d+", face)]
)
if data["filetype"] == "TN":
data["vt_face_idx"].append(
[int(s[1:-1]) - 1 for s in re.findall(r"/\d+/", face)]
)
data["vn_face_idx"].append(
[int(s.split("/")[-1]) - 1 for s in re.findall(r"/\d+/\d+", face)]
)
if not data["f"]:
raise ValueError(
"Faces in the input file do not have any of the specified forms"
)
data["f"] = [
[int(s[1:]) - 1 for s in re.findall(r" \d+", face)] for face in data["f"]
]
return data
def _set_vt_and_vn(data):
if data["filetype"] == "T":
data["halfedgeds"].edges.add_attribute("vt")
data["halfedgeds"].edges.add_attribute("vt_index")
if data["filetype"] == "N":
data["halfedgeds"].edges.add_attribute("vn")
data["halfedgeds"].edges.add_attribute("vn_index")
if data["filetype"] == "TN":
data["halfedgeds"].edges.add_attribute("vt")
data["halfedgeds"].edges.add_attribute("vn")
data["halfedgeds"].edges.add_attribute("vt_index")
data["halfedgeds"].edges.add_attribute("vn_index")
for face in data["halfedgeds"].faces:
edge = face.edge
dataface = data["f"][face.ifs_face_index]
while edge.head.ifs_index != dataface[0]:
edge = edge.nex
for i, edg in enumerate(ddg.halfedge.edge_loop(edge)):
j = i
if (
edge.nex.head.ifs_index != dataface[1]
): # edgeloop is reverse orientation to the given
# vertex order
j = -i
if data["filetype"] == "T":
edg.vt_index = data["vt_face_idx"][face.ifs_face_index][j]
edg.vt = data["vt"][edg.vt_index]
if data["filetype"] == "N":
edg.vn_index = data["vn_face_idx"][face.ifs_face_index][j]
edg.vn = data["vn"][edg.vn_index]
if data["filetype"] == "TN":
edg.vt_index = data["vt_face_idx"][face.ifs_face_index][j]
edg.vt = data["vt"][edg.vt_index]
edg.vn_index = data["vn_face_idx"][face.ifs_face_index][j]
edg.vn = data["vn"][edg.vn_index]
def _initialize_indexedfs(data):
"""
Creates an IndexedFaceSet as self.indexedfs of the given obj file.
"""
faceSet = ddg.indexedfaceset.GeneralizedIndexedFaceSet(data["f"])
data["indexedfs"] = faceSet
return data
def _initialize_halfedgeds(filename):
"""
Creates a halfedge surface of the given obj file.
Sets attributes "vn" and "vt" to edges pointing to the corresponding
vertex if given.
"""
data = _read_obj(filename)
if not data["indexedfs"]:
_initialize_indexedfs(data)
hds = ddg.indexedfaceset.indexed_face_set_to_surface(data["indexedfs"])
hds.verts.add_attribute("co")
for vert in hds.verts:
vert.co = np.array(data["v"][vert.ifs_index])
data["halfedgeds"] = hds
if data["filetype"] != "0":
_set_vt_and_vn(data)
return data
[docs]def obj_to_hds(filename):
"""
| Converts an obj file to a ddg.halfedge.Surface with vertex attribute
| "co", and edge attributes "vt" and "vn", if given.
| Reads an obj file with given v and faces of the form f 1 2 3
| or given v,vt and faces of the form f 1/1 2/1 3/1
| or given v,vn and faces of the form f 1//1 2//1 3//1
| or given v,vt,vn and faces of the form f 1/1/2 2/1/2 3/1/2.
Parameters
----------
filename : str
(path and) name of the obj file, like "path/file.obj"
Returns
-------
ddg.halfedge.Surface
"""
encoder = _initialize_halfedgeds(filename)
return encoder["halfedgeds"]