Light/radiance (#5252)

* Cam fix, Sun Fix, import-export as json

* Ran black formatting
This commit is contained in:
Chirag Singh
2024-08-30 04:02:45 +05:30
committed by GitHub
parent afd5a5b23e
commit 9633d92c17
6 changed files with 319 additions and 108 deletions
@@ -39,6 +39,10 @@ classes = (
operator.ViewFromSun, operator.ViewFromSun,
operator.RefreshIFCMaterials, operator.RefreshIFCMaterials,
operator.UnmapMaterial, operator.UnmapMaterial,
operator.RADIANCE_OT_select_camera,
operator.RADIANCE_OT_export_material_mappings,
operator.RADIANCE_OT_import_material_mappings,
operator.RADIANCE_OT_open_spectraldb,
prop.RadianceMaterial, prop.RadianceMaterial,
prop.BIMSolarProperties, prop.BIMSolarProperties,
prop.RadianceExporterProperties, prop.RadianceExporterProperties,
@@ -1,3 +1,22 @@
# Bonsai - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of Bonsai.
#
# Bonsai is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Bonsai is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
import json import json
import os import os
@@ -10,6 +29,15 @@ class MATERIAL_UL_radiance_materials(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
if self.layout_type in {"DEFAULT", "COMPACT"}: if self.layout_type in {"DEFAULT", "COMPACT"}:
row = layout.row(align=True) row = layout.row(align=True)
# Adding color preview or glass icon
if item.category == "Glass":
row.label(icon="SHADING_TEXTURE")
else:
color_rect = row.row()
color_rect.prop(item, "color", text="")
color_rect.scale_x = 0.3
row.prop(item, "name", text="", emboss=False, icon_value=icon) row.prop(item, "name", text="", emboss=False, icon_value=icon)
if item.is_mapped: if item.is_mapped:
row.label(text=f"{item.category} - {item.subcategory}") row.label(text=f"{item.category} - {item.subcategory}")
+197 -55
View File
@@ -30,11 +30,17 @@ import bonsai.tool as tool
from pathlib import Path from pathlib import Path
from typing import Union, Optional, Sequence from typing import Union, Optional, Sequence
import json import json
import math
import time
import sun_position
import ifcopenshell import ifcopenshell
import webbrowser
import ifcopenshell.geom import ifcopenshell.geom
import multiprocessing import multiprocessing
from mathutils import Vector from mathutils import Vector
from bonsai.bim.module.light.data import SolarData from bonsai.bim.module.light.data import SolarData
from bpy_extras.io_utils import ExportHelper
from bpy_extras.io_utils import ImportHelper
ifc_materials = [] ifc_materials = []
@@ -95,14 +101,10 @@ class ExportOBJ(bpy.types.Operator):
while True: while True:
shape = iterator.get() shape = iterator.get()
materials = shape.geometry.materials materials = shape.geometry.materials
# print(shape.geometry)
material_ids = shape.geometry.material_ids material_ids = shape.geometry.material_ids
# material_names = shape.geometry.material_names # material_names = shape.geometry.material_names
# print(material_ids)
for material in materials: for material in materials:
# print(material, dir(material))
# print(material.name)
ifc_materials.append(material.name) ifc_materials.append(material.name)
serialiser.write(shape) serialiser.write(shape)
@@ -129,10 +131,15 @@ class RadianceRender(bpy.types.Operator):
self.report({"ERROR"}, "PyRadiance is not available. Cannot perform rendering.") self.report({"ERROR"}, "PyRadiance is not available. Cannot perform rendering.")
return {"CANCELLED"} return {"CANCELLED"}
# Get the resolution from the user input print("Starting Radiance rendering process...")
props = context.scene.radiance_exporter_properties props = context.scene.radiance_exporter_properties
resolution_x, resolution_y = props.radiance_resolution_x, props.radiance_resolution_y 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
aspect_ratio = resolution_x / resolution_y
quality = props.radiance_quality.upper() quality = props.radiance_quality.upper()
detail = props.radiance_detail.upper() detail = props.radiance_detail.upper()
variability = props.radiance_variability.upper() variability = props.radiance_variability.upper()
@@ -141,6 +148,11 @@ class RadianceRender(bpy.types.Operator):
output_file_format = props.output_file_format output_file_format = props.output_file_format
use_hdr = props.use_hdr use_hdr = props.use_hdr
choose_hdr_image = props.choose_hdr_image choose_hdr_image = props.choose_hdr_image
print(f"Resolution: {resolution_x}x{resolution_y}")
print(f"Quality: {quality}, Detail: {detail}, Variability: {variability}")
print(f"Output directory: {output_dir}")
if use_hdr: if use_hdr:
hdr_image = "noon_grass_2k.hdr" hdr_image = "noon_grass_2k.hdr"
hdr_mask = "noon_grass_2k_mask.hdr" hdr_mask = "noon_grass_2k_mask.hdr"
@@ -148,30 +160,34 @@ class RadianceRender(bpy.types.Operator):
hdr_image_path = os.path.join(os.path.dirname(__file__), "HDRs", hdr_image) hdr_image_path = os.path.join(os.path.dirname(__file__), "HDRs", hdr_image)
hdr_mask_path = os.path.join(os.path.dirname(__file__), "HDRs", hdr_mask) hdr_mask_path = os.path.join(os.path.dirname(__file__), "HDRs", hdr_mask)
sky_map_cal_path = os.path.join(os.path.dirname(__file__), "HDRs", sky_map_cal) sky_map_cal_path = os.path.join(os.path.dirname(__file__), "HDRs", sky_map_cal)
# os.chdir(output_dir)
obj_file_path = os.path.join(output_dir, "model.obj") obj_file_path = os.path.join(output_dir, "model.obj")
sun_props = context.scene.BIMSolarProperties sun_props = context.scene.BIMSolarProperties
sun_pos_props = context.scene.sun_pos_properties
sky_file_path = os.path.join(output_dir, "sky.rad") sky_file_path = os.path.join(output_dir, "sky.rad")
latitude = sun_props.latitude # latitude = sun_props.latitude
longitude = sun_props.longitude # longitude = sun_props.longitude
timezone = sun_props.timezone # month = sun_props.month
month = sun_props.month # day = sun_props.day
day = sun_props.day # hour = sun_props.hour
hour = sun_props.hour # minute = sun_props.minute
minute = sun_props.minute
print("Sun Properties:") # print("Sun Properties:")
print("Latitude: ", latitude) # print("Latitude: ", latitude)
print("Longitude: ", longitude) # print("Longitude: ", longitude)
print("Timezone: ", timezone) # print("Timezone: ", timezone)
print("Month: ", month) # print("Month: ", month)
print("Day: ", day) # print("Day: ", day)
print("Hour: ", hour) # print("Hour: ", hour)
print("Minute: ", minute) # print("Minute: ", minute)
print("Setting up camera...")
if props.use_active_camera:
camera = context.scene.camera
else:
camera = props.selected_camera
camera = self.get_active_camera(context)
if camera is None: if camera is None:
self.report({"ERROR"}, "No active camera found in the scene. Please add a camera and set it as active.") self.report({"ERROR"}, "No active camera found in the scene. Please add a camera and set it as active.")
return {"CANCELLED"} return {"CANCELLED"}
@@ -179,19 +195,34 @@ class RadianceRender(bpy.types.Operator):
# Get camera position and direction # Get camera position and direction
camera_position, camera_direction = self.get_camera_data(camera) camera_position, camera_direction = self.get_camera_data(camera)
dt = datetime(2024, month, day, hour, minute) print(f"Camera position: {camera_position}")
print(f"Camera direction: {camera_direction}")
# azimuth, elevation = sun_position.sun_calc.get_sun_coordinates(
# sun_pos_props.time,
# sun_pos_props.latitude,
# sun_pos_props.longitude,
# -sun_pos_props.UTC_zone,
# sun_pos_props.month,
# sun_pos_props.day,
# sun_pos_props.year,
# )
dt = datetime(sun_pos_props.year, sun_props.month, sun_props.day, sun_props.hour, sun_props.minute)
sky_description = pr.gensky( sky_description = pr.gensky(
dt=dt, dt=dt,
latitude=latitude, # azimuth=64.1,
longitude=longitude, # altitude=-26.6,
timezone=timezone, latitude=sun_props.latitude,
year=2024, longitude=sun_props.longitude,
sunny_with_sun=True, year=sun_pos_props.year,
sunny_without_sun=False, timezone=-int(sun_props.UTC_zone),
cloudy=False, # sunny_with_sun=False,
ground_reflectance=0.2, # sunny_without_sun=False,
turbidity=3.0, # cloudy=False,
# ground_reflectance=0.2,
# turbidity=3.0,
) )
sky_description_str = sky_description.decode("utf-8") sky_description_str = sky_description.decode("utf-8")
@@ -292,11 +323,7 @@ ground_glow source ground
props = context.scene.radiance_exporter_properties props = context.scene.radiance_exporter_properties
if props.use_json_file: data = props.get_mappings_dict()
with open(props.json_file, "r") as file:
data = json.load(file)
else:
data = props.get_mappings_dict()
materials_file = os.path.join(output_dir, "materials.rad") materials_file = os.path.join(output_dir, "materials.rad")
written_materials = set() written_materials = set()
@@ -318,9 +345,6 @@ ground_glow source ground
file.write(material) file.write(material)
written_materials.add(material.split()[2]) # Add material name to written set written_materials.add(material.split()[2]) # Add material name to written set
print(data)
print(default_materials)
for style_id in all_materials: for style_id in all_materials:
material = next((m for m in props.materials if m.style_id == style_id), None) material = next((m for m in props.materials if m.style_id == style_id), None)
if material and material.is_mapped: if material and material.is_mapped:
@@ -351,7 +375,7 @@ ground_glow source ground
self.report({"INFO"}, "Exported Scene file to: {}".format(scene_file)) self.report({"INFO"}, "Exported Scene file to: {}".format(scene_file))
# Py Radiance Rendering code print("Setting up Radiance scene...")
scene = pr.Scene("ascene") scene = pr.Scene("ascene")
material_path = os.path.join(output_dir, "materials.rad") material_path = os.path.join(output_dir, "materials.rad")
@@ -360,10 +384,39 @@ ground_glow source ground
scene.add_material(material_path) scene.add_material(material_path)
scene.add_surface(scene_path) scene.add_surface(scene_path)
scene.add_source(sky_file_path) scene.add_source(sky_file_path)
print("Setting up view...")
if camera.data.type == "PERSP":
# Perspective camera
camera_fov = camera.data.angle
# Calculate vertical FOV based on the desired aspect ratio
vertical_fov = 2 * math.atan(math.tan(camera_fov / 2) / aspect_ratio)
aview = pr.View(position=camera_position, direction=camera_direction) aview = pr.View(
vtype="v", # Perspective view
position=camera_position,
direction=camera_direction,
vup=(0, 0, 1), # Assuming Z is up
horiz=math.degrees(camera_fov),
vert=math.degrees(vertical_fov),
)
else: # 'ORTHO'
# Orthographic camera
# Calculate the view size based on the camera's orthographic scale
ortho_scale = camera.data.ortho_scale
view_width = ortho_scale
view_height = ortho_scale / aspect_ratio
aview = pr.View(
vtype="l", # Parallel projection (orthographic)
position=camera_position,
direction=camera_direction,
vup=(0, 0, 1), # Assuming Z is up
horiz=view_width,
vert=view_height,
)
scene.add_view(aview) scene.add_view(aview)
print("Starting render...")
start_time = time.time()
image = pr.render( image = pr.render(
scene, scene,
ambbounce=1, ambbounce=1,
@@ -371,32 +424,34 @@ ground_glow source ground
quality=quality, quality=quality,
detail=detail, detail=detail,
variability=variability, variability=variability,
nproc=multiprocessing.cpu_count(),
) )
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}.{output_file_format.lower()}")
print(f"Saving HDR output to: {output_hdr_path}")
if output_file_format == "HDR": if output_file_format == "HDR":
with open(output_hdr_path, "wb") as wtr: with open(output_hdr_path, "wb") as wtr:
wtr.write(image) wtr.write(image)
else: else:
pass pass
print("Applying tone mapping...")
pcond_image = pr.pcond(hdr=output_hdr_path, human=True) pcond_image = pr.pcond(hdr=output_hdr_path, human=True)
tiff_path = os.path.join(output_dir, f"{output_file_name}.tiff") 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) 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"}, "Radiance rendering completed. Output: {}".format(tiff_path))
return {"FINISHED"} return {"FINISHED"}
def get_active_camera(self, context): def get_active_camera(self, context):
if context.scene.camera: props = context.scene.radiance_exporter_properties
if props.use_active_camera:
return context.scene.camera return context.scene.camera
for obj in context.scene.objects: else:
if obj.type == "CAMERA": return props.selected_camera
return obj
return None
def get_camera_data(self, camera): def get_camera_data(self, camera):
# Get camera position # Get camera position
@@ -509,9 +564,29 @@ class RefreshIFCMaterials(bpy.types.Operator):
for render_item in style.Styles: for render_item in style.Styles:
if render_item.is_a("IfcSurfaceStyleRendering"): if render_item.is_a("IfcSurfaceStyleRendering"):
style_id = f"IfcSurfaceStyleRendering-{render_item.id()}" style_id = f"IfcSurfaceStyleRendering-{render_item.id()}"
ifc_materials.append(style_id)
style_name = style.Name or f"Unnamed Style {render_item.id()}" style_name = style.Name or f"Unnamed Style {render_item.id()}"
props.add_material_mapping(style_id, style_name)
# Extract color and transparency
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
props.active_material_index = 0 if props.materials else -1 props.active_material_index = 0 if props.materials else -1
@@ -531,3 +606,70 @@ class UnmapMaterial(bpy.types.Operator):
material = props.materials[self.material_index] material = props.materials[self.material_index]
props.unmap_material(material.name) props.unmap_material(material.name)
return {"FINISHED"} return {"FINISHED"}
class RADIANCE_OT_select_camera(bpy.types.Operator):
bl_idname = "radiance.select_camera"
bl_label = "Select Camera"
bl_description = "Select a camera from the viewport"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.object is not None and context.object.type == "CAMERA"
def execute(self, context):
props = context.scene.radiance_exporter_properties
props.selected_camera = context.object
props.use_active_camera = False
return {"FINISHED"}
class RADIANCE_OT_export_material_mappings(bpy.types.Operator, ExportHelper):
bl_idname = "radiance.export_material_mappings"
bl_label = "Export Material Mappings"
bl_description = "Export material mappings to a JSON file"
filename_ext = ".json"
def execute(self, context):
props = context.scene.radiance_exporter_properties
mappings = {}
for material in props.materials:
if material.is_mapped:
mappings[material.style_id] = {
"name": material.name,
"category": material.category,
"subcategory": material.subcategory,
}
with open(self.filepath, "w") as f:
json.dump(mappings, f, indent=4)
self.report({"INFO"}, f"Material mappings exported to {self.filepath}")
return {"FINISHED"}
class RADIANCE_OT_import_material_mappings(bpy.types.Operator, ImportHelper):
bl_idname = "radiance.import_material_mappings"
bl_label = "Import Material Mappings"
bl_description = "Import material mappings from a JSON file"
filename_ext = ".json"
def execute(self, context):
props = context.scene.radiance_exporter_properties
props.import_mappings(self.filepath)
self.report({"INFO"}, f"Material mappings imported from {self.filepath}")
return {"FINISHED"}
class RADIANCE_OT_open_spectraldb(bpy.types.Operator):
bl_idname = "radiance.open_spectraldb"
bl_label = "Open SpectralDB"
bl_description = "Open the SpectralDB website for reference"
def execute(self, context):
webbrowser.open("https://spectraldb.com")
return {"FINISHED"}
+46 -20
View File
@@ -32,6 +32,7 @@ from bpy.props import (
FloatVectorProperty, FloatVectorProperty,
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
PointerProperty,
) )
import os import os
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -107,6 +108,11 @@ def update_display_sun_path(self, context):
SolarDecorator.uninstall() SolarDecorator.uninstall()
def update_resolution(self, context):
context.scene.render.resolution_x = self.radiance_resolution_x
context.scene.render.resolution_y = self.radiance_resolution_y
def update_sun_path(): def update_sun_path():
if not SolarData.is_loaded: if not SolarData.is_loaded:
SolarData.load() SolarData.load()
@@ -142,6 +148,10 @@ def update_sun_path():
rotation_euler = Euler((elevation - pi / 2, 0, -azimuth)) rotation_euler = Euler((elevation - pi / 2, 0, -azimuth))
rotation_quaternion = rotation_euler.to_quaternion() rotation_quaternion = rotation_euler.to_quaternion()
props.azimuth = azimuth
props.elevation = elevation
props.UTC_zone = zone
if sun_vector.z < 0: if sun_vector.z < 0:
bpy.context.scene.display.light_direction = mat @ Vector((0, 0, 1)) bpy.context.scene.display.light_direction = mat @ Vector((0, 0, 1))
else: else:
@@ -162,14 +172,11 @@ class RadianceMaterial(PropertyGroup):
category: StringProperty(name="Category") category: StringProperty(name="Category")
subcategory: StringProperty(name="Subcategory") subcategory: StringProperty(name="Subcategory")
is_mapped: BoolProperty(name="Is Mapped", default=False) is_mapped: BoolProperty(name="Is Mapped", default=False)
color: FloatVectorProperty(name="Color", subtype="COLOR", default=(1.0, 1.0, 1.0), min=0.0, max=1.0, size=3)
class RadianceExporterProperties(PropertyGroup): class RadianceExporterProperties(PropertyGroup):
def update_json_file(self, context):
if self.json_file:
self.json_file = bpy.path.abspath(self.json_file)
def update_output_dir(self, context): def update_output_dir(self, context):
if self.output_dir: if self.output_dir:
self.output_dir = bpy.path.abspath(self.output_dir) self.output_dir = bpy.path.abspath(self.output_dir)
@@ -184,8 +191,26 @@ class RadianceExporterProperties(PropertyGroup):
item.style_id = style_id item.style_id = style_id
item.category = "" item.category = ""
item.subcategory = "" item.subcategory = ""
item.color = (1.0, 1.0, 1.0) # Default white
return item return item
def import_mappings(self, filepath):
with open(filepath, "r") as f:
mappings = json.load(f)
for style_id, mapping in mappings.items():
material = self.get_material_mapping(mapping["name"])
if material:
material.style_id = style_id
material.category = mapping["category"]
material.subcategory = mapping["subcategory"]
material.is_mapped = True
else:
new_material = self.add_material_mapping(style_id, mapping["name"])
new_material.category = mapping["category"]
new_material.subcategory = mapping["subcategory"]
new_material.is_mapped = True
def get_material_mapping(self, style_name): def get_material_mapping(self, style_name):
return next((item for item in self.materials if item.name == style_name), None) return next((item for item in self.materials if item.name == style_name), None)
@@ -213,12 +238,6 @@ class RadianceExporterProperties(PropertyGroup):
item.subcategory = "" item.subcategory = ""
item.is_mapped = False item.is_mapped = False
use_json_file: BoolProperty(
name="Upload JSON",
description="Toggle between uploading a JSON file and using in-UI material mapping",
default=False,
)
is_exporting: bpy.props.BoolProperty( is_exporting: bpy.props.BoolProperty(
name="Is Exporting", description="Whether the OBJ export is in progress", default=False name="Is Exporting", description="Whether the OBJ export is in progress", default=False
) )
@@ -237,6 +256,7 @@ class RadianceExporterProperties(PropertyGroup):
("Plant", "Plant", ""), ("Plant", "Plant", ""),
("Exterior", "Exterior", ""), ("Exterior", "Exterior", ""),
("Color Swatch", "Color Swatch", ""), ("Color Swatch", "Color Swatch", ""),
("Glass", "Glass", ""),
] ]
def update_material_mapping(self, context): def update_material_mapping(self, context):
@@ -269,14 +289,13 @@ class RadianceExporterProperties(PropertyGroup):
should_load_from_memory: BoolProperty( should_load_from_memory: BoolProperty(
name="Load from Memory", name="Load from Memory",
default=False, default=False,
description="Use IFC file currently loaded in Bonsai",
) )
radiance_resolution_x: IntProperty( radiance_resolution_x: IntProperty(
name="X", description="Horizontal resolution of the output image", default=1920, min=1 name="X", description="Horizontal resolution of the output image", default=1920, min=1, update=update_resolution
) )
radiance_resolution_y: IntProperty( radiance_resolution_y: IntProperty(
name="Y", description="Vertical resolution of the output image", default=1080, min=1 name="Y", description="Vertical resolution of the output image", default=1080, min=1, update=update_resolution
) )
output_dir: StringProperty( output_dir: StringProperty(
name="Output Directory", name="Output Directory",
@@ -292,13 +311,6 @@ class RadianceExporterProperties(PropertyGroup):
subtype="FILE_PATH", subtype="FILE_PATH",
update=lambda self, context: self.update_ifc_file(context), update=lambda self, context: self.update_ifc_file(context),
) )
json_file: StringProperty(
name="JSON File",
description="Path to the JSON file",
default="",
subtype="FILE_PATH",
update=lambda self, context: self.update_json_file(context),
)
radiance_quality: EnumProperty( radiance_quality: EnumProperty(
name="Quality", name="Quality",
@@ -350,6 +362,17 @@ class RadianceExporterProperties(PropertyGroup):
default="Noon", default="Noon",
) )
use_active_camera: BoolProperty(
name="Use Active Camera", description="Use the active camera in the scene", default=True
)
selected_camera: PointerProperty(
type=bpy.types.Object,
name="Camera",
description="Select a camera to use for rendering",
poll=lambda self, object: object.type == "CAMERA",
)
class BIMSolarProperties(PropertyGroup): class BIMSolarProperties(PropertyGroup):
sites: EnumProperty(items=get_sites, name="Sites") sites: EnumProperty(items=get_sites, name="Sites")
@@ -364,6 +387,9 @@ class BIMSolarProperties(PropertyGroup):
sun_position: FloatVectorProperty(name="Sun Position", subtype="XYZ", default=(0, 0, 0)) sun_position: FloatVectorProperty(name="Sun Position", subtype="XYZ", default=(0, 0, 0))
sun_path_origin: FloatVectorProperty(name="Sun Path Origin", subtype="XYZ", default=(0, 0, 0)) sun_path_origin: FloatVectorProperty(name="Sun Path Origin", subtype="XYZ", default=(0, 0, 0))
sun_path_size: FloatProperty(name="Sun Path Size", min=0.1, default=50, update=update_sun_path_size) sun_path_size: FloatProperty(name="Sun Path Size", min=0.1, default=50, update=update_sun_path_size)
azimuth: FloatProperty(name="Azimuth")
elevation: FloatProperty(name="Elevation")
UTC_zone: FloatProperty(name="UTC Zone")
display_shadows: BoolProperty( display_shadows: BoolProperty(
name="Display Shadows", name="Display Shadows",
default=False, default=False,
@@ -1,4 +1,7 @@
{ {
"Glass": {
"Clear Glass": "void BRTDfunc clear_glass\n10\n sr_clear_r sr_clear_g sr_clear_b\n st_clear_r st_clear_g st_clear_b\n 0 0 0\n glaze1.cal\n0\n19\n 0 0 0\n 0 0 0\n 0 0 0\n 1\n 0.074 0.077 0.079\n 0.074 0.077 0.079\n 0.862 0.890 0.886\n"
},
"Wall": { "Wall": {
"White Painted Room Walls": "void plastic white_painted_room_walls \n0\n0\n5 0.8316 0.8116 0.7226 0.0036 0.2", "White Painted Room Walls": "void plastic white_painted_room_walls \n0\n0\n5 0.8316 0.8116 0.7226 0.0036 0.2",
"White Painted Corridor Walls": "void plastic white_painted_corridor_walls \n0\n0\n5 0.8143 0.7984 0.715 0.0039 0.2", "White Painted Corridor Walls": "void plastic white_painted_corridor_walls \n0\n0\n5 0.8143 0.7984 0.715 0.0039 0.2",
+41 -33
View File
@@ -50,43 +50,52 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
row.prop(props, "output_dir") row.prop(props, "output_dir")
row = layout.row() row = layout.row()
layout.prop(props, "use_json_file") layout.label(text="Info: Unmapped materials default to white")
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
if len(props.materials) > 0:
col = layout.column(align=True)
col.prop(props, "category")
if props.category:
col.prop(props, "subcategory")
if props.use_json_file: if props.active_material_index >= 0 and props.active_material_index < len(props.materials):
row = layout.row() active_material = props.materials[props.active_material_index]
row.prop(props, "json_file") if active_material.category and active_material.subcategory:
layout.label(
text=f"Mapped: {active_material.name} to {active_material.category} - {active_material.subcategory}"
)
else:
layout.label(text=f"Select category and subcategory for: {active_material.name}")
if not props.use_json_file: row = layout.row()
row = layout.row() row.operator("radiance.import_material_mappings", text="Import Mappings", icon="IMPORT")
layout.label(text="Info: Unmapped materials default to white") row.operator("radiance.export_material_mappings", text="Export Mappings", icon="EXPORT")
row = layout.row() row = layout.row()
row.template_list("MATERIAL_UL_radiance_materials", "", props, "materials", props, "active_material_index") row.operator("bim.refresh_ifc_materials", text="Refresh IFC Materials")
if len(props.materials) > 0:
col = layout.column(align=True)
col.prop(props, "category")
if props.category:
col.prop(props, "subcategory")
if props.active_material_index >= 0 and props.active_material_index < len(props.materials):
active_material = props.materials[props.active_material_index]
if active_material.category and active_material.subcategory:
layout.label(
text=f"Mapped: {active_material.name} to {active_material.category} - {active_material.subcategory}"
)
else:
layout.label(text=f"Select category and subcategory for: {active_material.name}")
row = layout.row()
row.operator("bim.refresh_ifc_materials", text="Refresh IFC Materials")
layout.separator() layout.separator()
row = layout.row()
row.label(text="Resolution")
row.prop(props, "radiance_resolution_x", text="X")
row = layout.row() row = layout.row()
row.label(text="") 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()
row.prop(props, "use_active_camera")
if not props.use_active_camera:
row = box.row()
row.prop(props, "selected_camera")
row.operator("radiance.select_camera", text="", icon="EYEDROPPER")
row = box.row(align=True)
row.label(text="Resolution")
row.prop(props, "radiance_resolution_x", text="X")
row.prop(props, "radiance_resolution_y", text="Y") row.prop(props, "radiance_resolution_y", text="Y")
row = layout.row() row = layout.row()
@@ -115,8 +124,7 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
row.prop(props, "choose_hdr_image") row.prop(props, "choose_hdr_image")
row = layout.row() row = layout.row()
row.operator("export_scene.radiance", text="Export Geometry for Simulation") layout.label(text="Step 2: Run the simulation")
row = layout.row() row = layout.row()
row.operator("render_scene.radiance", text="Radiance Render") row.operator("render_scene.radiance", text="Radiance Render")
row.enabled = not props.is_exporting row.enabled = not props.is_exporting