Source code for photonmap.Reader.ReadRADGeo
from photonmap.Common.Math import *
from openalea.plantgl.all import *
import re
#Objectif of this module is read the geometry of each object of fichier RAD
[docs]
def cylinder_vertices(start, end, rayon):
"""
Generate the geometry of a cylinder
Parameters
----------
start: Vec3
The center of the first circle of cylinder
end: Vec3
The center of the second circle of cylinder
rayon: float
The radius of these two circles
Returns
-------
A array of vertices of an cylinder
"""
vert = []
direction = end - start
direction.normalize()
horizontal = crossVector(direction, Vector3(0,0,1))
v1 = end + rayon * horizontal
v2 = start + rayon * horizontal
v3 = start - rayon * horizontal
v4 = end - rayon * horizontal
vert.append((v1[0], v1[1], v1[2]))
vert.append((v2[0], v2[1], v2[2]))
vert.append((v3[0], v3[1], v3[2]))
vert.append((v4[0], v4[1], v4[2]))
return vert
[docs]
def read_rad(file: str, scale_factor: int, invert_normals: bool):
"""
Parse a radiance file (https://radsite.lbl.gov/radiance/framed.html) to a make a plantGL Scene
Parameters
----------
file: str
the rad filename
scale_factor: int
The size of geometries. The vertices of geometries is recalculated by dividing their coordinates by this value
invert_normals: bool
whether to invert the normals or not.
Returns
-------
A plantGL Scene.
"""
with open(file, "r") as f:
lines = f.readlines()
materials = {}
shapes = {}
sc = Scene()
i = 0
for _ in range(len(lines)):
i += 1
if i >= len(lines):
break
elif lines[i].startswith("#"):
continue
elif lines[i].startswith("void"): # material
li = lines[i].split(None)
type = li[1]
name = li[2].strip("\n")
# print("material name: " + str(name))
if materials.get(name) is None:
if type == "plastic":
li = lines[i + 4].split(None)
color = Color3(
denormalize(float(li[0])),
denormalize(float(li[1])),
denormalize(float(li[2])),
)
spec = Color3(
denormalize(float(li[3])),
denormalize(float(li[3])),
denormalize(float(li[3])),
)
roughness = float(li[4])
mat = {
"name": name,
"type": type,
"color": color,
"spec": spec,
"roughness": roughness,
}
materials[name] = mat
i += 5
elif type == "metal":
li = lines[i + 4].split(None)
color = Color3(
denormalize(float(li[0])),
denormalize(float(li[1])),
denormalize(float(li[2])),
)
spec = Color3(
denormalize(float(li[3])),
denormalize(float(li[3])),
denormalize(float(li[3])),
)
roughness = float(li[4])
mat = {
"name": name,
"type": type,
"color": color,
"spec": spec,
"roughness": roughness,
}
materials[name] = mat
i += 5
elif type == "trans":
li = lines[i + 4].split(None)
color = Color3(
denormalize(float(li[0])),
denormalize(float(li[1])),
denormalize(float(li[2])),
)
spec = Color3(
denormalize(float(li[3])),
denormalize(float(li[3])),
denormalize(float(li[3])),
)
roughness = float(li[4])
trans = float(li[5])
tspec = float(li[6])
mat = {
"name": name,
"type": type,
"color": color,
"spec": spec,
"roughness": roughness,
"trans": trans,
"tspec": tspec,
}
materials[name] = mat
i += 5
elif type == "light":
li = lines[i + 4].split(None)
color = Color3(
denormalize(float(li[0])),
denormalize(float(li[1])),
denormalize(float(li[2])),
)
mat = {"name": name, "type": type, "color": color}
materials[name] = mat
i += 5
else:
keys = materials.keys()
for k in keys:
if lines[i].startswith(k):
li = lines[i].split(None)
material = li[0]
type = li[1]
name = li[2].strip("\n")
if type == "point_light" or type == "point":
i += 1
vert = []
l = re.split(r"\s+|;+", lines[i])
vert.append(
(
float(l[0]) / scale_factor,
float(l[1]) / scale_factor,
float(l[2]) / scale_factor,
)
)
shapes[name] = {
"vertices": vert,
"type": type,
"size": 1,
"material": material,
}
else:
i += 3
vert = []
size = int(lines[i])
tmp = i + 1
nbCoords = int(size / 3)
if type == "cylinder":
l = re.split(r"\s+|;+", lines[i + 1])
l2 = re.split(r"\s+|;+", lines[i + 2])
l3 = re.split(r"\s+|;+", lines[i + 3])
r = float(l3[0]) / scale_factor
x, y, z = (
float(l[0]) / scale_factor,
float(l[1]) / scale_factor,
float(l[2]) / scale_factor,
)
x2, y2, z2 = (
float(l2[0]) / scale_factor,
float(l2[1]) / scale_factor,
float(l2[2]) / scale_factor,
)
vert = cylinder_vertices(Vector3(x,y,z), Vector3(x2,y2,z2), 0)
# vert.append((x + r, y + r, z + r))
# vert.append((x - r, y - r, z - r))
# vert.append((x2 + r, y2 + r, z2 + r))
# vert.append((x2 - r, y2 - r, z2 - r))
shapes[name] = {
"vertices": vert,
"type": type,
"size": len(vert),
"material": material,
}
i += 3
elif type == "cone":
l = re.split(r"\s+|;+", lines[i + 1])
l2 = re.split(r"\s+|;+", lines[i + 2])
l3 = re.split(r"\s+|;+", lines[i + 3])
r = float(l3[0]) / scale_factor
r2 = float(l3[1]) / scale_factor
x, y, z = (
float(l[0]) / scale_factor,
float(l[1]) / scale_factor,
float(l[2]) / scale_factor,
)
x2, y2, z2 = (
float(l2[0]) / scale_factor,
float(l2[1]) / scale_factor,
float(l2[2]) / scale_factor,
)
ratio = r / r2
pos = [x, y, z]
newCone = Frustum()
newCone.taper = 1.0 + ratio
newCone.height = z2 * 10 - z * 10
ts = Tesselator()
newCone.apply(ts)
mesh = ts.result
maxi = 0
for i in range(0, mesh.indexListSize()):
index = mesh.indexAt(i)
typeF = mesh.faceSize(i)
for j in range(0, typeF):
if index[j] > maxi:
maxi = index[j]
for u in range(0, maxi + 1):
mvector = mesh.pointAt(u)
mesh.pointList[u] = (
mvector[0] / 10 + pos[0],
mvector[1] / 10 + pos[1],
mvector[2] / 10 + pos[2],
)
shapes[name] = {
"vertices": vert,
"type": type,
"size": len(vert),
"material": material,
"mesh": mesh,
}
i += 3
else:
for j in range(tmp, tmp + nbCoords):
l = re.split(r"\s+|;+", lines[j])
vert.append(
(
float(l[0]) / scale_factor,
float(l[1]) / scale_factor,
float(l[2]) / scale_factor,
)
)
i = j
shapes[name] = {
"vertices": vert,
"type": type,
"size": size,
"material": material,
}
for sh, val in shapes.items():
mat_key = val["material"]
mat = materials[mat_key]
vert = val["vertices"]
s = Shape()
nbCoords = int(val["size"] / 3)
if val.get("mesh") is not None:
print("mesh detected")
s.name = sh
s.geometry = val["mesh"]
if mat["type"] == "light":
s.name += str(vert[0])
s.appearance = Material(
name=name,
ambient=Color3(mat["color"]),
emission=Color3(mat["color"]),
)
elif mat["type"] == "trans":
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
specular=Color3(mat["spec"]),
shininess=1 - mat["roughness"],
transparency=mat["trans"],
)
else:
if Color3(mat["spec"]) == Color3(0, 0, 0):
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
shininess=1 - mat["roughness"],
)
else:
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
specular=Color3(mat["spec"]),
shininess=1 - mat["roughness"],
)
s.appearance.name = mat["name"]
sc.add(s)
elif nbCoords % 3 == 0:
ts = TriangleSet(vert)
i = 0
indList = []
if nbCoords == 9:
ind = Index3(i, i + 1, i + 2)
indList.append(ind)
ind = Index3(i, i + 2, i + 3)
indList.append(ind)
ind = Index3(i, i + 3, i + 4)
indList.append(ind)
ind = Index3(i, i + 4, i + 5)
indList.append(ind)
ind = Index3(i, i + 5, i + 6)
indList.append(ind)
ind = Index3(i, i + 6, i + 7)
indList.append(ind)
ind = Index3(i, i + 7, i + 8)
indList.append(ind)
else:
while i < nbCoords:
if invert_normals:
ind = Index3(i, i + 2, i + 1)
else:
ind = Index3(i, i + 1, i + 2)
indList.append(ind)
i += 3
ts.indexList = Index3Array(indList)
ts.computeNormalList()
s.geometry = ts
s.name = sh
if mat["type"] == "light":
s.name += str(vert[0])
s.appearance = Material(
name=name,
ambient=Color3(mat["color"]),
emission=Color3(mat["color"]),
)
elif mat["type"] == "trans":
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
specular=Color3(mat["spec"]),
shininess=1 - mat["roughness"],
transparency=mat["trans"],
)
else:
if Color3(mat["spec"]) == Color3(0, 0, 0):
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
shininess=1 - mat["roughness"],
)
else:
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
specular=Color3(mat["spec"]),
shininess=1 - mat["roughness"],
)
s.appearance.name = mat["name"]
sc.add(s)
else:
#triangulate quad
ts = TriangleSet(vert)
i = 0
indList = []
while i < nbCoords:
if invert_normals:
ind = Index3(i, i + 2, i + 1)
ind2 = Index3(i, i + 3, i + 2)
else:
ind = Index3(i, i + 1, i + 2)
ind2 = Index3(i, i + 2, i + 3)
indList.append(ind)
indList.append(ind2)
i += 4
ts.indexList = Index3Array(indList)
ts.computeNormalList()
s.geometry = ts
s.name = sh
if mat["type"] == "light":
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
emission=Color3(mat["color"]),
)
elif mat["type"] == "trans":
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
specular=Color3(mat["spec"]),
shininess=1 - mat["roughness"],
transparency=mat["trans"],
)
else:
if Color3(mat["spec"]) == Color3(0, 0, 0):
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
shininess=1 - mat["roughness"],
)
else:
s.appearance = Material(
name=mat["name"],
ambient=Color3(mat["color"]),
specular=Color3(mat["spec"]),
shininess=1 - mat["roughness"],
)
s.appearance.name = mat["name"]
sc.add(s)
save_name = file.split(".")[0] + ".obj"
sc.save(save_name)
return sc