Compare commits

...

9 Commits

Author SHA1 Message Date
Chirag Singh 3613c4e059 Added HDR output file format 2024-09-01 14:07:52 +05:30
Chirag Singh 284ade69b4 Merge remote-tracking branch 'origin/v0.8.0' into light/radiance 2024-09-01 13:52:50 +05:30
Chirag Singh d8bc9af30f Merge remote-tracking branch 'origin/v0.8.0' into light/radiance 2024-09-01 12:42:50 +05:30
Chirag Singh b3531d8c9d Fixed blue sky when no hdri 2024-09-01 02:52:44 +05:30
Chirag Singh 72a95acfe4 Sorted the materials in cat and sub cat 2024-08-31 20:29:52 +05:30
Chirag Singh 79230b3341 Added prop with search, render in 3 steps 2024-08-31 20:20:08 +05:30
Chirag Singh 8a14707a09 Removed if transparent then glass and removed some comments 2024-08-31 20:00:10 +05:30
Chirag Singh 3ad41cfba6 Ran black formatting 2024-08-29 19:15:29 +05:30
Chirag Singh 50f21fe1b1 Cam fix, Sun Fix, import-export as json 2024-08-29 19:13:51 +05:30
4 changed files with 202 additions and 88 deletions
@@ -43,6 +43,9 @@ classes = (
operator.RADIANCE_OT_export_material_mappings,
operator.RADIANCE_OT_import_material_mappings,
operator.RADIANCE_OT_open_spectraldb,
operator.EnumPropertySearch,
operator.PrepareRadianceScene,
operator.SetEnumProperty,
prop.RadianceMaterial,
prop.BIMSolarProperties,
prop.RadianceExporterProperties,
+128 -59
View File
@@ -43,6 +43,8 @@ from bpy_extras.io_utils import ImportHelper
ifc_materials = []
scene = None
with open(os.path.join(os.path.dirname(__file__), "spectraldb.json"), "r") as f:
spectraldb = json.load(f)
@@ -118,12 +120,20 @@ class ExportOBJ(bpy.types.Operator):
return {"FINISHED"}
class RadianceRender(bpy.types.Operator):
"""Radiance Rendering"""
class PrepareRadianceScene(bpy.types.Operator):
bl_idname = "scene.prepare_radiance"
bl_label = "Prepare Radiance Scene"
bl_description = "Prepares the Radiance scene by creating necessary files and setting up the view"
bl_idname = "render_scene.radiance"
bl_label = "Render"
bl_description = "Renders the scene using Radiance"
def get_camera_data(self, camera):
# Get camera position
position = camera.matrix_world.to_translation()
# Get camera direction
direction = camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
direction.normalize()
return (position.x, position.y, position.z), (direction.x, direction.y, direction.z)
def execute(self, context):
if pr is None:
@@ -143,11 +153,12 @@ class RadianceRender(bpy.types.Operator):
detail = props.radiance_detail.upper()
variability = props.radiance_variability.upper()
output_dir = props.output_dir
output_file_name = props.output_file_name
output_file_format = props.output_file_format
use_hdr = props.use_hdr
choose_hdr_image = props.choose_hdr_image
global scene
scene = None
print(f"Resolution: {resolution_x}x{resolution_y}")
print(f"Quality: {quality}, Detail: {detail}, Variability: {variability}")
print(f"Output directory: {output_dir}")
@@ -197,7 +208,6 @@ class RadianceRender(bpy.types.Operator):
print(f"Camera position: {camera_position}")
print(f"Camera direction: {camera_direction}")
# sun_position = tool.Blender.get_sun_position_addon()
# azimuth, elevation = sun_position.sun_calc.get_sun_coordinates(
# sun_pos_props.time,
# sun_pos_props.latitude,
@@ -218,7 +228,7 @@ class RadianceRender(bpy.types.Operator):
longitude=sun_props.longitude,
year=sun_pos_props.year,
timezone=-int(sun_props.UTC_zone),
# sunny_with_sun=False,
# sunny_with_sun=True,
# sunny_without_sun=False,
# cloudy=False,
# ground_reflectance=0.2,
@@ -316,14 +326,14 @@ ground_glow source ground
with open(sky_file_path, "w") as f:
f.write(sky_description_str)
f.write("\n")
# f.write("skyfunc glow sky_glow\n0\n0\n4 .9 .9 1.15 0\n")
# f.write("sky_glow source sky\n0\n0\n4 0 0 1 180\n")
# f.write("skyfunc glow ground_glow\n0\n0\n4 1.4 .9 .6 0\n")
# f.write("ground_glow source ground\n0\n0\n4 0 0 -1 180\n")
f.write("skyfunc glow sky_glow\n0\n0\n4 .9 .9 1.15 0\n")
f.write("sky_glow source sky\n0\n0\n4 0 0 1 180\n")
f.write("skyfunc glow ground_glow\n0\n0\n4 1.4 .9 .6 0\n")
f.write("ground_glow source ground\n0\n0\n4 0 0 -1 180\n")
props = context.scene.radiance_exporter_properties
# props = context.scene.radiance_exporter_properties
data = props.get_mappings_dict()
# data = props.get_mappings_dict()
materials_file = os.path.join(output_dir, "materials.rad")
written_materials = set()
@@ -416,7 +426,36 @@ ground_glow source ground
)
scene.add_view(aview)
print("Starting render...")
self.report({"INFO"}, "Radiance scene prepared successfully.")
return {"FINISHED"}
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):
props = context.scene.radiance_exporter_properties
resolution_x, resolution_y = props.radiance_resolution_x, props.radiance_resolution_y
context.scene.render.resolution_x = resolution_x
context.scene.render.resolution_y = resolution_y
quality = props.radiance_quality.upper()
detail = props.radiance_detail.upper()
variability = props.radiance_variability.upper()
output_dir = props.output_dir
output_file_name = props.output_file_name
output_file_format = props.output_file_format
global scene
start_time = time.time()
image = pr.render(
scene,
ambbounce=1,
@@ -429,46 +468,38 @@ ground_glow source ground
end_time = time.time()
print(f"Render completed in {end_time - start_time:.2f} seconds")
output_hdr_path = os.path.join(output_dir, f"{output_file_name}.{output_file_format.lower()}")
output_hdr_path = os.path.join(output_dir, f"{output_file_name}.hdr")
print(f"Saving HDR output to: {output_hdr_path}")
if output_file_format == "HDR":
with open(output_hdr_path, "wb") as wtr:
wtr.write(image)
else:
pass
print("Applying tone mapping...")
pcond_image = pr.pcond(hdr=output_hdr_path, human=True)
with open(output_hdr_path, "wb") as wtr:
wtr.write(image)
if output_file_format == "HDR_TIFF":
print("Applying tone mapping...")
pcond_image = pr.pcond(hdr=output_hdr_path, human=True)
tiff_path = os.path.join(output_dir, f"{output_file_name}.tiff")
print(f"Saving TIFF output to: {tiff_path}")
pr.ra_tiff(inp=pcond_image, out=tiff_path, lzw=True)
tiff_path = os.path.join(output_dir, f"{output_file_name}.tiff")
print(f"Saving TIFF output to: {tiff_path}")
pr.ra_tiff(inp=pcond_image, out=tiff_path, lzw=True)
print("Radiance rendering process completed successfully.")
self.report({"INFO"}, "Radiance rendering completed. Output: {}".format(tiff_path))
self.report({"INFO"}, f"Radiance rendering completed. HDR Output: {output_hdr_path}")
if output_file_format == "HDR_TIFF":
self.report({"INFO"}, f"TIFF Output: {tiff_path}")
return {"FINISHED"}
def get_active_camera(self, context):
props = context.scene.radiance_exporter_properties
if props.use_active_camera:
return context.scene.camera
else:
return props.selected_camera
# def get_active_camera(self, context):
# props = context.scene.radiance_exporter_properties
# if props.use_active_camera:
# return context.scene.camera
# else:
# return props.selected_camera
def get_camera_data(self, camera):
# Get camera position
position = camera.matrix_world.to_translation()
# Get camera direction
direction = camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
direction.normalize()
return (position.x, position.y, position.z), (direction.x, direction.y, direction.z)
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
# 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
def save_obj2mesh_output(inp: Union[bytes, str, Path], output_file: str, **kwargs):
@@ -566,27 +597,21 @@ class RefreshIFCMaterials(bpy.types.Operator):
style_id = f"IfcSurfaceStyleRendering-{render_item.id()}"
style_name = style.Name or f"Unnamed Style {render_item.id()}"
# Extract color and transparency
# Extract color
color = (1.0, 1.0, 1.0) # Default white
transparency = 0.0 # Default opaque
if render_item.SurfaceColour:
color = (
render_item.SurfaceColour.Red,
render_item.SurfaceColour.Green,
render_item.SurfaceColour.Blue,
)
if hasattr(render_item, "Transparency") and render_item.Transparency is not None:
transparency = render_item.Transparency
# Add material with color
material = props.add_material_mapping(style_id, style_name)
material.color = color
# If transparency is high, consider it as glass
if transparency > 0.5:
material.category = "Glass"
material.subcategory = "Clear Glass"
material.is_mapped = True
material.category = ""
material.subcategory = ""
material.is_mapped = False
props.active_material_index = 0 if props.materials else -1
@@ -673,3 +698,47 @@ class RADIANCE_OT_open_spectraldb(bpy.types.Operator):
def execute(self, context):
webbrowser.open("https://spectraldb.com")
return {"FINISHED"}
class EnumPropertySearch(bpy.types.Operator):
bl_idname = "bim.enum_property_search"
bl_label = "Search Enum Property"
bl_options = {"REGISTER", "UNDO"}
prop_name: bpy.props.StringProperty()
search_term: bpy.props.StringProperty()
def execute(self, context):
data = context.space_data.context_pointer_get("data")
enum_items = get_enum_items(data, self.prop_name)
filtered_items = [item for item in enum_items if self.search_term.lower() in item[1].lower()]
def draw_menu(self, context):
layout = self.layout
for item in filtered_items:
props = layout.operator("bim.set_enum_property", text=item[1])
props.prop_name = self.prop_name
props.enum_value = item[0]
bpy.context.window_manager.popup_menu(draw_menu, title="Search Results", icon="VIEWZOOM")
return {"FINISHED"}
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
self.layout.prop(self, "search_term", text="Search")
class SetEnumProperty(bpy.types.Operator):
bl_idname = "bim.set_enum_property"
bl_label = "Set Enum Property"
bl_options = {"REGISTER", "UNDO"}
prop_name: bpy.props.StringProperty()
enum_value: bpy.props.StringProperty()
def execute(self, context):
data = context.space_data.context_pointer_get("data")
setattr(data, self.prop_name, self.enum_value)
return {"FINISHED"}
+8 -4
View File
@@ -182,6 +182,9 @@ class RadianceExporterProperties(PropertyGroup):
if self.ifc_file:
self.ifc_file = bpy.path.abspath(self.ifc_file)
def get_categories(self, context):
return sorted([(k, k, "") for k in spectraldb.keys()])
def add_material_mapping(self, style_id, style_name):
item = self.materials.add()
item.name = style_name
@@ -265,12 +268,12 @@ class RadianceExporterProperties(PropertyGroup):
print(f"Material '{active_material.name}' mapped to {self.category} - {self.subcategory}")
category: bpy.props.EnumProperty(
items=categories, name="Category", description="Material category", update=update_material_mapping
items=get_categories, name="Category", description="Material category", update=update_material_mapping
)
def get_subcategories(self, context):
if self.category in spectraldb:
return [(k, k, "") for k in spectraldb[self.category].keys()]
return sorted([(k, k, "") for k in spectraldb[self.category].keys()])
return []
subcategory: bpy.props.EnumProperty(
@@ -339,9 +342,10 @@ class RadianceExporterProperties(PropertyGroup):
name="Output File Format",
description="Format of the output image file",
items=[
("HDR", "HDR + Tiff", "High Dynamic Range"),
("HDR", "HDR", "High Dynamic Range (HDR) file only"),
("HDR_TIFF", "HDR + Tiff", "High Dynamic Range (HDR) and Tiff files"),
],
default="HDR",
default="HDR_TIFF",
)
use_hdr: BoolProperty(
+63 -25
View File
@@ -21,6 +21,28 @@ import bonsai.tool as tool
from bonsai.bim.module.light.data import SolarData
def get_enum_items(data, prop_name, context=None):
prop = data.__annotations__[prop_name]
items = prop.keywords.get("items")
if items is None:
return
if not isinstance(items, (list, tuple)):
items = items(data, context or bpy.context)
return items
def prop_with_search(layout, data, prop_name, **kwargs):
row = layout.row(align=True)
row.prop(data, prop_name, **kwargs)
try:
if len(get_enum_items(data, prop_name)) > 10:
row.context_pointer_set(name="data", data=data)
op = row.operator("bim.enum_property_search", text="", icon="VIEWZOOM")
op.prop_name = prop_name
except TypeError:
pass
class BIM_PT_radiance_exporter(bpy.types.Panel):
"""Creates a Panel in the render properties window"""
@@ -54,11 +76,14 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
row = layout.row()
row.template_list("MATERIAL_UL_radiance_materials", "", props, "materials", props, "active_material_index")
row.operator("radiance.open_spectraldb", text="", icon="WORLD") # Globe icon
# layout.use_property_split = True
# layout.use_property_decorate = False
# layout.width_hint = 350
if len(props.materials) > 0:
col = layout.column(align=True)
col.prop(props, "category")
prop_with_search(col, props, "category")
if props.category:
col.prop(props, "subcategory")
prop_with_search(col, props, "subcategory")
if props.active_material_index >= 0 and props.active_material_index < len(props.materials):
active_material = props.materials[props.active_material_index]
@@ -77,13 +102,6 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
layout.separator()
row = layout.row()
layout.label(text="Step 1: Export geometry for simulation")
row = layout.row()
row.operator("export_scene.radiance", text="Export Geometry for Simulation")
layout.separator()
box = layout.box()
box.label(text="Camera Settings")
row = box.row()
@@ -98,34 +116,54 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
row.prop(props, "radiance_resolution_x", text="X")
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")
layout.separator()
row = layout.row()
box = layout.box()
box.label(text="Render Settings")
row = box.row()
row.prop(props, "radiance_quality")
row = box.row()
row.prop(props, "radiance_detail")
row = box.row()
row.prop(props, "radiance_variability")
row = box.row()
row.prop(props, "output_file_name")
row = layout.row()
row = box.row()
row.prop(props, "output_file_format")
layout.separator()
row = layout.row()
row = box.row()
row.prop(props, "use_hdr")
if props.use_hdr:
row = layout.row()
row = box.row()
row.prop(props, "choose_hdr_image")
row = layout.row()
layout.label(text="Step 2: Run the simulation")
row = layout.row()
# Step 1: Export geometry for simulation
box = layout.box()
box.label(text="Step 1: Export geometry for simulation")
row = box.row()
row.operator("export_scene.radiance", text="Export Geometry for Simulation")
layout.separator()
# Step 2: Prepare Radiance scene
box = layout.box()
box.label(text="Step 2: Prepare Radiance scene")
row = box.row()
row.operator("scene.prepare_radiance", text="Prepare Scene")
layout.separator()
# Step 3: Run the simulation
box = layout.box()
box.label(text="Step 3: Run the simulation")
row = box.row()
row.operator("render_scene.radiance", text="Radiance Render")
row.enabled = not props.is_exporting