Radiance Support added

This commit is contained in:
Chirag Singh
2024-07-09 11:50:36 +05:30
committed by Dion Moult
parent 220fb13eec
commit a2dead2dd7
4 changed files with 212 additions and 13 deletions
@@ -21,17 +21,14 @@ from . import ui, prop, operator
classes = (
operator.ExportRadiance,
operator.ExportOBJ,
operator.RadianceRender,
prop.RadianceExporterProperties,
ui.BIM_PT_radiance_exporter,
)
def register():
# for cls in classes:
# bpy.utils.register_class(cls)
bpy.types.Scene.radiance_exporter_properties = bpy.props.PointerProperty(type=prop.RadianceExporterProperties)
def unregister():
# for cls in reversed(classes):
# bpy.utils.unregister_class(cls)
del bpy.types.Scene.radiance_exporter_properties
@@ -26,16 +26,193 @@ import json
import ifcopenshell
import ifcopenshell.geom
import multiprocessing
import shutil
class ExportRadiance(bpy.types.Operator):
"""Exports and renders the scene with Radiance using rad"""
class ExportOBJ(bpy.types.Operator):
"""Exports the IFC File to OBJ"""
bl_idname = "export_scene.radiance"
bl_label = "Export and Render"
bl_description = "Export the scene to Radiance and render it"
bl_label = "Export"
bl_description = "Export the IFC to OBJ"
def execute(self, context):
return {'FINISHED'}
# Get the resolution from the user input
resolution_x, resolution_y = self.getResolution(context)
quality = context.scene.radiance_exporter_properties.radiance_quality.upper()
detail = context.scene.radiance_exporter_properties.radiance_detail.upper()
variability = context.scene.radiance_exporter_properties.radiance_variability.upper()
# Calculate the aspect ratio
aspect_ratio = resolution_x / resolution_y
# Get the blend file path and create the "Radiance Rendering" directory
self.report({'INFO'}, "Exporting Radiance files...")
blend_file_path = bpy.data.filepath
if not blend_file_path:
self.report({'ERROR'}, "Please save the Blender file before exporting.")
return {'CANCELLED'}
blend_file_dir = os.path.dirname(blend_file_path)
radiance_dir = os.path.join(blend_file_dir, "RadianceRendering")
self.report({'INFO'}, "Radiance directory: {}".format(radiance_dir))
if not os.path.exists(radiance_dir):
os.makedirs(radiance_dir)
# IFC file export and processing
settings = ifcopenshell.geom.settings()
# Settings for obj
serializer_settings = ifcopenshell.geom.serializer_settings()
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.SURFACES_AND_SOLIDS)
settings.set("apply-default-materials", True)
serializer_settings.set("use-element-guids", True)
settings.set("use-world-coords", True)
ifc_file_name = context.scene.radiance_exporter_properties.ifc_file_name
ifc_file_path = os.path.join(blend_file_dir, f"{ifc_file_name}.ifc")
if not os.path.exists(ifc_file_path):
self.report({'ERROR'}, f"IFC file not found: {ifc_file_path}")
return {'CANCELLED'}
ifc_file = ifcopenshell.open(ifc_file_path)
for material in ifc_file.by_type("IfcMaterial"):
self.report({'INFO'}, f"Material: {material.Name}, ID: {material.id()}")
obj_file_path = os.path.join(radiance_dir, "model.obj")
mtl_file_path = os.path.join(radiance_dir, "model.mtl")
# serialiser = ifcopenshell.geom.serializers.obj(obj_file_path, mtl_file_path, settings, ifcopenshell.geom.serializer_settings())
serialiser = ifcopenshell.geom.serializers.obj(obj_file_path, mtl_file_path, settings, serializer_settings)
serialiser.setFile(ifc_file)
serialiser.setUnitNameAndMagnitude("METER", 1.0)
serialiser.writeHeader()
iterator = ifcopenshell.geom.iterator(settings, ifc_file, multiprocessing.cpu_count())
if iterator.initialize():
while True:
serialiser.write(iterator.get())
if not iterator.next():
break
serialiser.finalize()
return {'FINISHED'}
def getResolution(self, context):
scene = context.scene
props = scene.radiance_exporter_properties
resolution_x = props.radiance_resolution_x
resolution_y = props.radiance_resolution_y
return resolution_x, resolution_y
class RadianceRender(bpy.types.Operator):
"""Radiance Rendering"""
bl_idname = "render_scene.radiance"
bl_label = "Render"
bl_description = "Renders the scene using Radiance"
def execute(self, context):
# Get the resolution from the user input
resolution_x, resolution_y = self.getResolution(context)
quality = context.scene.radiance_exporter_properties.radiance_quality.upper()
detail = context.scene.radiance_exporter_properties.radiance_detail.upper()
variability = context.scene.radiance_exporter_properties.radiance_variability.upper()
# Get the blend file path and create the "Radiance Rendering" directory
blend_file_path = bpy.data.filepath
if not blend_file_path:
self.report({'ERROR'}, "Please save the Blender file before rendering.")
return {'CANCELLED'}
blend_file_dir = os.path.dirname(blend_file_path)
radiance_dir = os.path.join(blend_file_dir, "RadianceRendering")
# Material processing
style = []
obj_file_path = os.path.join(radiance_dir, "model.obj")
with open(obj_file_path, "r") as obj_file:
# Iterate through each line in the file
for line in obj_file:
# Check if the line starts with "usemtl"
if line.startswith("usemtl"):
l = line.strip().split(" ")
style.append(l[1])
# json_file_path = os.path.join(blend_file_dir, "material_mapping.json")
json_file_path = context.scene.radiance_exporter_properties.json_file_path
self.report({'INFO'}, f"Selected JSON file: {json_file_path}")
if json_file_path:
# self.report({'INFO'}, f"Selected JSON file: {json_file_name}")
json_dest_path = os.path.join(blend_file_dir, json_file_path.split("\\")[-1])
shutil.copy(json_file_path, json_dest_path)
self.report({'INFO'}, f"JSON file saved to: {json_dest_path}")
else:
self.report({'WARNING'}, "No JSON file selected")
with open(json_file_path, 'r') as file:
data = json.load(file)
# Create materials.rad file
materials_file = os.path.join(radiance_dir, "materials.rad")
with open(materials_file, "w") as file:
file.write("void plastic white\n0\n0\n5 1 1 1 0 0\n")
file.write("void plastic blue_plastic\n0\n0\n5 0.1 0.2 0.8 0.05 0.1\n")
file.write("void plastic red_plastic\n0\n0\n5 0.8 0.1 0.2 0.05 0.1\n")
file.write("void metal silver_metal\n0\n0\n5 0.8 0.8 0.8 0.9 0.1\n")
file.write("void glass clear_glass\n0\n0\n3 0.96 0.96 0.96\n")
file.write("void light white_light\n0\n0\n3 1.0 1.0 1.0\n")
file.write("void trans olive_trans\n0\n0\n7 0.6 0.7 0.4 0.05 0.05 0.7 0.2\n")
for i in set(style):
file.write("inherit alias " + i + " " + data.get(i, "white") + "\n")
self.report({'INFO'}, "Exported Materials Rad file to: {}".format(materials_file))
# Run obj2mesh
rtm_file_path = os.path.join(radiance_dir, "model.rtm")
mesh_file_path = save_obj2mesh_output(obj_file_path, rtm_file_path, matfiles=[materials_file])
# subprocess.run(["obj2mesh", "-a", materials_file, obj_file_path, rtm_file_path])
self.report({'INFO'}, "obj2mesh output: {}".format(mesh_file_path))
scene_file = os.path.join(radiance_dir, "scene.rad")
with open(scene_file, "w") as file:
file.write("void mesh model\n1 " + rtm_file_path + "\n0\n0\n")
self.report({'INFO'}, "Exported Scene file to: {}".format(scene_file))
# Py Radiance Rendering code
scene = pr.Scene("ascene")
material_path = os.path.join(radiance_dir, "materials.rad")
scene_path = os.path.join(radiance_dir, "scene.rad")
scene.add_material(material_path)
scene.add_surface(scene_path)
aview = pr.View(position=(1, 1.5, 1), direction=(1, 0, 0))
scene.add_view(aview)
octpath = os.path.join(blend_file_dir, "ascene.oct")
print("Reached here")
image = pr.render(scene, ambbounce=1, resolution=(resolution_x, resolution_y),
quality=quality, detail=detail, variability=variability)
raw_hdr_path = os.path.join(radiance_dir, "raw.hdr")
with open(raw_hdr_path, "wb") as wtr:
wtr.write(image)
self.report({'INFO'}, "Radiance rendering completed. Output: {}".format(raw_hdr_path))
return {'FINISHED'}
def getResolution(self, context):
scene = context.scene
@@ -46,5 +223,7 @@ class ExportRadiance(bpy.types.Operator):
def save_obj2mesh_output(inp: Union[bytes, str, Path], output_file: str, **kwargs):
output_bytes = pr.obj2mesh(inp, **kwargs)
with open(output_file, 'wb') as f:
f.write(output_bytes)
f.write(output_bytes)
return output_file
@@ -21,6 +21,14 @@ from bpy.props import IntProperty, StringProperty, EnumProperty
from bpy.types import PropertyGroup
class RadianceExporterProperties(PropertyGroup):
def update_json_file_path(self, context):
if self.json_file_path:
self.json_file_path = bpy.path.abspath(self.json_file_path)
radiance_resolution_x: IntProperty(
name="X",
description="Horizontal resolution of the output image",
@@ -36,8 +44,17 @@ class RadianceExporterProperties(PropertyGroup):
ifc_file_name: StringProperty(
name="IFC File Name",
description="Name of the IFC file to use (without .ifc extension)",
default="AC20-FZK-Haus"
default=""
)
json_file_path: StringProperty(
name="JSON File",
description="Path to the JSON file",
default="",
subtype="FILE_PATH",
update=lambda self, context: self.update_json_file_path(context)
)
radiance_quality: EnumProperty(
name="Quality",
description="Radiance rendering quality",
@@ -36,6 +36,9 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
row = layout.row()
row.prop(props, "ifc_file_name")
row = layout.row()
row.prop(props, "json_file_path")
row = layout.row()
row.label(text="Resolution")
@@ -55,4 +58,7 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
row.prop(props, "radiance_variability")
row = layout.row()
row.operator("export_scene.radiance", text="Export and Render")
row.operator("export_scene.radiance", text="Export to OBJ")
row = layout.row()
row.operator("render_scene.radiance", text="Radiance Render")