Compare commits

...

5 Commits

Author SHA1 Message Date
Chirag Singh 6503d666ae Implemented Gensky 2024-08-01 19:37:49 +05:30
chiragsingh1711 7711e570a8 Updated IFC file input and choosing the output directory. 2024-07-16 11:02:59 +05:30
Chirag Singh a5a8e347c8 Wrapped import pyradiance in a try-except to accommodate mac intel 2024-07-09 18:37:02 +05:30
Chirag Singh c044675dcc Radiance Support added 2024-07-09 11:50:36 +05:30
Chirag Singh eeb079339e Created a UI for Radiance Rendering in the Services and System Panel 2024-07-04 18:55:36 +05:30
6 changed files with 288 additions and 0 deletions
@@ -167,6 +167,7 @@ classes = [
ui.BIM_PT_tab_references,
# Services and systems
ui.BIM_PT_tab_services,
ui.BIM_PT_tab_lighting,
ui.BIM_PT_tab_zones,
ui.BIM_PT_tab_solar_analysis,
ui.BIM_PT_tab_lighting,
@@ -19,6 +19,21 @@
import bpy
from . import ui, prop, operator
<<<<<<< HEAD
classes = (
operator.ExportOBJ,
operator.RadianceRender,
prop.RadianceExporterProperties,
ui.BIM_PT_radiance_exporter,
)
def register():
bpy.types.Scene.radiance_exporter_properties = bpy.props.PointerProperty(type=prop.RadianceExporterProperties)
def unregister():
del bpy.types.Scene.radiance_exporter_properties
=======
import stat
from pathlib import Path
@@ -58,3 +73,4 @@ def register():
def unregister():
del bpy.types.Scene.radiance_exporter_properties
del bpy.types.Scene.BIMSolarProperties
>>>>>>> v0.8.0
@@ -24,7 +24,10 @@ except ImportError:
print("PyRadiance is not available. Rendering functionality will be disabled.")
pr = None
<<<<<<< HEAD
=======
from datetime import datetime
>>>>>>> v0.8.0
import bpy
import blenderbim.tool as tool
from pathlib import Path
@@ -33,15 +36,22 @@ import json
import ifcopenshell
import ifcopenshell.geom
import multiprocessing
<<<<<<< HEAD
=======
from mathutils import Vector
from blenderbim.bim.module.light.data import SolarData
ifc_materials = []
>>>>>>> v0.8.0
class ExportOBJ(bpy.types.Operator):
"""Exports the IFC File to OBJ"""
<<<<<<< HEAD
=======
>>>>>>> v0.8.0
bl_idname = "export_scene.radiance"
bl_label = "Export"
bl_description = "Export the IFC to OBJ"
@@ -51,20 +61,43 @@ class ExportOBJ(bpy.types.Operator):
# Get the output directory
should_load_from_memory = context.scene.radiance_exporter_properties.should_load_from_memory
output_dir = context.scene.radiance_exporter_properties.output_dir
<<<<<<< HEAD
json_file = context.scene.radiance_exporter_properties.json_file
=======
context.scene.radiance_exporter_properties.is_exporting = True
>>>>>>> v0.8.0
# Conversion from IFC to OBJ
# Settings for obj
settings = ifcopenshell.geom.settings()
serializer_settings = ifcopenshell.geom.serializer_settings()
<<<<<<< HEAD
=======
>>>>>>> v0.8.0
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)
if should_load_from_memory:
<<<<<<< HEAD
ifc_file_path = tool.Ifc.get_path()
else:
ifc_file_path = context.scene.radiance_exporter_properties.ifc_file
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(output_dir, "model.obj")
mtl_file_path = os.path.join(output_dir, "model.mtl")
=======
ifc_file = tool.Ifc.get()
else:
@@ -74,11 +107,23 @@ class ExportOBJ(bpy.types.Operator):
obj_file_path = os.path.join(output_dir, "model.obj")
mtl_file_path = os.path.join(output_dir, "model.mtl")
>>>>>>> v0.8.0
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()
<<<<<<< HEAD
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'}
=======
if ifc_file.schema in ("IFC2X3", "IFC4"):
elements = ifc_file.by_type("IfcElement") + ifc_file.by_type("IfcProxy")
else:
@@ -112,17 +157,71 @@ class ExportOBJ(bpy.types.Operator):
self.report({"INFO"}, "Exported OBJ file to: {}".format(obj_file_path))
return {"FINISHED"}
>>>>>>> v0.8.0
class RadianceRender(bpy.types.Operator):
"""Radiance Rendering"""
<<<<<<< HEAD
=======
>>>>>>> v0.8.0
bl_idname = "render_scene.radiance"
bl_label = "Render"
bl_description = "Renders the scene using Radiance"
def execute(self, context):
if pr is None:
<<<<<<< HEAD
self.report({'ERROR'}, "PyRadiance is not available. Cannot perform rendering.")
return {'CANCELLED'}
# 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()
should_load_from_memory = context.scene.radiance_exporter_properties.should_load_from_memory
output_dir = context.scene.radiance_exporter_properties.output_dir
json_file = context.scene.radiance_exporter_properties.json_file
obj_file_path = os.path.join(output_dir, "model.obj")
if should_load_from_memory:
ifc_file_path = tool.Ifc.get_path()
else:
ifc_file_path = context.scene.radiance_exporter_properties.ifc_file
# style = []
# ifc_file = ifcopenshell.open(ifc_file_path)
# for material in ifc_file.by_type("IfcSurfaceStyle"):
# self.report({'INFO'}, f"Material: {material.Name}, ID: {material.id()}")
# if material.id() == 17449 or material.id() == 20871 or material.id() == 15008:
# continue
# else:
# style.append("surface-style-"+str(material.id())+"-"+material.Name)
# Material processing
style = []
with open(obj_file_path, "r") as obj_file:
for line in obj_file:
if line.startswith("usemtl"):
l = line.strip().split(" ")
style.append(l[1])
with open(json_file, 'r') as file:
data = json.load(file)
# Create materials.rad file
materials_file = os.path.join(output_dir, "materials.rad")
with open(materials_file, "w") as file:
file.write("void plastic white\n0\n0\n5 0.6 0.6 0.6 0 0\n")
=======
self.report({"ERROR"}, "PyRadiance is not available. Cannot perform rendering.")
return {"CANCELLED"}
@@ -262,6 +361,7 @@ ground_glow source ground
materials_file = os.path.join(output_dir, "materials.rad")
with open(materials_file, "w") as file:
file.write("void plastic white\n0\n0\n5 0.8 0.8 0.8 0 0\n")
>>>>>>> v0.8.0
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")
@@ -269,6 +369,23 @@ ground_glow source ground
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")
<<<<<<< HEAD
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(output_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(output_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))
=======
for style_id, radiance_material in data.items():
print(style_id, radiance_material)
file.write("inherit alias " + style_id + " " + data.get(style_id, "white") + "\n")
@@ -285,6 +402,7 @@ ground_glow source ground
file.write('void mesh model\n1 "' + rtm_file_path + '"\n0\n0\n')
self.report({"INFO"}, "Exported Scene file to: {}".format(scene_file))
>>>>>>> v0.8.0
# Py Radiance Rendering code
scene = pr.Scene("ascene")
@@ -294,6 +412,21 @@ ground_glow source ground
scene.add_material(material_path)
scene.add_surface(scene_path)
<<<<<<< HEAD
aview = pr.View(position=(1, 1.5, 1), direction=(1, 0, 0))
scene.add_view(aview)
image = pr.render(scene, ambbounce=1, resolution=(resolution_x, resolution_y),
quality=quality, detail=detail, variability=variability)
raw_hdr_path = os.path.join(output_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'}
=======
scene.add_source(sky_file_path)
aview = pr.View(position=camera_position, direction=camera_direction)
@@ -343,6 +476,7 @@ ground_glow source ground
direction.normalize()
return (position.x, position.y, position.z), (direction.x, direction.y, direction.z)
>>>>>>> v0.8.0
def getResolution(self, context):
scene = context.scene
@@ -351,6 +485,14 @@ ground_glow source ground
resolution_y = props.radiance_resolution_y
return resolution_x, resolution_y
<<<<<<< HEAD
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)
return output_file
=======
def save_obj2mesh_output(inp: Union[bytes, str, Path], output_file: str, **kwargs):
output_bytes = pr.obj2mesh(inp, **kwargs)
@@ -448,3 +590,4 @@ class RefreshIFCMaterials(bpy.types.Operator):
props.add_material_mapping(style_id, style_name)
return {"FINISHED"}
>>>>>>> v0.8.0
@@ -17,6 +17,10 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
<<<<<<< HEAD
from bpy.props import IntProperty, StringProperty, EnumProperty, BoolProperty
from bpy.types import PropertyGroup
=======
import pytz
import tzfpy
import datetime
@@ -136,6 +140,7 @@ def update_sun_path():
obj.rotation_quaternion = rotation_quaternion @ z180_quaternion
obj.data.ortho_scale = props.sun_path_size * 2
>>>>>>> v0.8.0
class RadianceExporterProperties(PropertyGroup):
@@ -151,6 +156,26 @@ class RadianceExporterProperties(PropertyGroup):
if self.ifc_file:
self.ifc_file = bpy.path.abspath(self.ifc_file)
<<<<<<< HEAD
should_load_from_memory: BoolProperty(
name="Load from Memory",
default=False,
name="Load from Memory"
)
radiance_resolution_x: IntProperty(
name="X",
description="Horizontal resolution of the output image",
default=1920,
min=1
)
radiance_resolution_y: IntProperty(
name="Y",
description="Vertical resolution of the output image",
default=1080,
min=1
=======
def add_material_mapping(self, style_id, style_name):
item = self.material_mappings.add()
item.name = style_name
@@ -194,26 +219,49 @@ class RadianceExporterProperties(PropertyGroup):
)
radiance_resolution_y: IntProperty(
name="Y", description="Vertical resolution of the output image", default=1080, min=1
>>>>>>> v0.8.0
)
output_dir: StringProperty(
name="Output Directory",
description="Directory to output Radiance files",
default="",
subtype="DIR_PATH",
<<<<<<< HEAD
update=lambda self, context: self.update_output_dir(context)
=======
update=lambda self, context: self.update_output_dir(context),
>>>>>>> v0.8.0
)
ifc_file: StringProperty(
name="IFC File",
description="Path to the IFC file",
default="",
subtype="FILE_PATH",
<<<<<<< HEAD
update=lambda self, context: self.update_ifc_file(context)
=======
update=lambda self, context: self.update_ifc_file(context),
>>>>>>> v0.8.0
)
json_file: StringProperty(
name="JSON File",
description="Path to the JSON file",
default="",
subtype="FILE_PATH",
<<<<<<< HEAD
update=lambda self, context: self.update_json_file(context)
)
radiance_quality: EnumProperty(
name="Quality",
description="Radiance rendering quality",
items=[
('LOW', "Low", "Low quality"),
('MEDIUM', "Medium", "Medium quality"),
('HIGH', "High", "High quality")
],
default='MEDIUM'
=======
update=lambda self, context: self.update_json_file(context),
)
@@ -222,17 +270,35 @@ class RadianceExporterProperties(PropertyGroup):
description="Radiance rendering quality",
items=[("LOW", "Low", "Low quality"), ("MEDIUM", "Medium", "Medium quality"), ("HIGH", "High", "High quality")],
default="MEDIUM",
>>>>>>> v0.8.0
)
radiance_detail: EnumProperty(
name="Detail",
description="Radiance rendering detail",
<<<<<<< HEAD
items=[
('LOW', "Low", "Low detail"),
('MEDIUM', "Medium", "Medium detail"),
('HIGH', "High", "High detail")
],
default='MEDIUM'
=======
items=[("LOW", "Low", "Low detail"), ("MEDIUM", "Medium", "Medium detail"), ("HIGH", "High", "High detail")],
default="MEDIUM",
>>>>>>> v0.8.0
)
radiance_variability: EnumProperty(
name="Variability",
description="Radiance rendering variability",
items=[
<<<<<<< HEAD
('LOW', "Low", "Low variability"),
('MEDIUM', "Medium", "Medium variability"),
('HIGH', "High", "High variability")
],
default='MEDIUM'
)
=======
("LOW", "Low", "Low variability"),
("MEDIUM", "Medium", "Medium variability"),
("HIGH", "High", "High variability"),
@@ -278,3 +344,4 @@ class BIMSolarProperties(PropertyGroup):
description="Displays analemmas and sun position",
update=update_display_sun_path,
)
>>>>>>> v0.8.0
@@ -18,6 +18,16 @@
import bpy
import blenderbim.tool as tool
<<<<<<< HEAD
class BIM_PT_radiance_exporter(bpy.types.Panel):
"""Creates a Panel in the render properties window"""
bl_label = "Radiance Exporter"
bl_idname = "BIM_PT_radiance_exporter"
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
=======
from blenderbim.bim.module.light.data import SolarData
@@ -32,6 +42,7 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
>>>>>>> v0.8.0
bl_context = "scene"
bl_parent_id = "BIM_PT_tab_lighting"
@@ -44,6 +55,42 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
if tool.Ifc.get():
row = self.layout.row()
row.prop(props, "should_load_from_memory")
<<<<<<< HEAD
if not tool.Ifc.get() or not props.should_load_from_memory:
row = self.layout.row(align=True)
row.prop(props, "ifc_file")
# row.operator("bim.select_ifctester_ifc_file", icon="FILE_FOLDER", text="")
row = layout.row()
row.prop(props, "output_dir")
row = layout.row()
row.prop(props, "json_file")
row = layout.row()
row.label(text="Resolution")
row.prop(props, "radiance_resolution_x", text="X")
row = layout.row()
row.label(text="")
row.prop(props, "radiance_resolution_y", text="Y")
row = layout.row()
row.prop(props, "radiance_quality")
row = layout.row()
row.prop(props, "radiance_detail")
row = layout.row()
row.prop(props, "radiance_variability")
row = layout.row()
row.operator("export_scene.radiance", text="Export to OBJ")
row = layout.row()
row.operator("render_scene.radiance", text="Radiance Render")
=======
if not tool.Ifc.get() or not props.should_load_from_memory:
row = self.layout.row(align=True)
@@ -212,3 +259,4 @@ class BIM_PT_solar(bpy.types.Panel):
row = self.layout.row(align=True)
row.operator("bim.view_from_sun", icon="LIGHT_HEMI")
>>>>>>> v0.8.0
+13
View File
@@ -702,6 +702,19 @@ class BIM_PT_tab_services(Panel):
def draw(self, context):
pass
class BIM_PT_tab_lighting(Panel):
bl_label = "Lighting"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
@classmethod
def poll(cls, context):
return tool.Blender.is_tab(context, "SERVICES") and tool.Ifc.get()
def draw(self, context):
pass
class BIM_PT_tab_lighting(Panel):
bl_label = "Lighting"