forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			174 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Using IES profiles from http://www.derekjenson.com/3d-blog/ies-light-profiles
 | |
| # IES parser based on:
 | |
| # https://github.com/tobspr/RenderPipeline
 | |
| # Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
 | |
| # Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| # of this software and associated documentation files (the "Software"), to deal
 | |
| # in the Software without restriction, including without limitation the rights
 | |
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| # copies of the Software, and to permit persons to whom the Software is
 | |
| # furnished to do so, subject to the following conditions:
 | |
| 
 | |
| # The above copyright notice and this permission notice shall be included in
 | |
| # all copies or substantial portions of the Software.
 | |
| 
 | |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | |
| # THE SOFTWARE.
 | |
| 
 | |
| import re
 | |
| import os
 | |
| import math
 | |
| import bpy
 | |
| import random
 | |
| 
 | |
| def load(filepath):
 | |
|     global _vertical_angles
 | |
|     global _horizontal_angles
 | |
|     global _candela_values
 | |
|     KEYWORD_REGEX = re.compile(r"\[([A-Za-z0-8_-]+)\](.*)")
 | |
| 
 | |
|     PROFILES = [
 | |
|         "IESNA:LM-63-1986",
 | |
|         "IESNA:LM-63-1991",
 | |
|         "IESNA91",
 | |
|         "IESNA:LM-63-1995",
 | |
|         "IESNA:LM-63-2002",
 | |
|         "ERCO Leuchten GmbH  BY: ERCO/LUM650/8701",
 | |
|         "ERCO Leuchten GmbH"
 | |
|     ]
 | |
| 
 | |
|     with open(filepath, "r") as handle:
 | |
|         lines = handle.readlines()
 | |
| 
 | |
|     lines = [i.strip() for i in lines]
 | |
| 
 | |
|     # Parse version header
 | |
|     first_line = lines.pop(0)
 | |
|     if first_line not in PROFILES:
 | |
|         raise "Unsupported Profile: " + first_line
 | |
| 
 | |
|     # Extracts the keywords
 | |
|     keywords = {}
 | |
|     while lines:
 | |
|         line = lines.pop(0)
 | |
|         if not line.startswith("["):
 | |
|             if line != "TILT=NONE":
 | |
|                 continue
 | |
|             lines.insert(0, line)
 | |
|             break
 | |
|         else:
 | |
|             match = KEYWORD_REGEX.match(line)
 | |
|             if match:
 | |
|                 key, val = match.group(1, 2)
 | |
|                 keywords[key.strip()] = val.strip()
 | |
|             else:
 | |
|                 raise "Invalid keyword line: " + line
 | |
| 
 | |
|     # Next line should be TILT=NONE according to the spec
 | |
|     if lines.pop(0) != "TILT=NONE":
 | |
|         raise "Expected TILT=NONE line, but none found!"
 | |
| 
 | |
|     # From now on, lines do not matter anymore, instead everything is space seperated
 | |
|     new_parts = (' '.join(lines)).replace(",", " ").split()
 | |
| 
 | |
|     def read_int():
 | |
|         return int(new_parts.pop(0))
 | |
| 
 | |
|     def read_float():
 | |
|         return float(new_parts.pop(0))
 | |
| 
 | |
|     # Amount of Lamps
 | |
|     if read_int() != 1:
 | |
|         raise "Only 1 Lamp supported!"
 | |
| 
 | |
|     # Extract various properties
 | |
|     lumen_per_lamp = read_float()
 | |
|     candela_multiplier = read_float()
 | |
|     num_vertical_angles = read_int()
 | |
|     num_horizontal_angles = read_int()
 | |
| 
 | |
|     if num_vertical_angles < 1 or num_horizontal_angles < 1:
 | |
|         raise "Invalid of vertical/horizontal angles!"
 | |
| 
 | |
|     photometric_type = read_int()
 | |
|     unit_type = read_int()
 | |
| 
 | |
|     # Check for a correct unit type, should be 1 for meters and 2 for feet
 | |
|     if unit_type not in [1, 2]:
 | |
|         raise "Invalid unit type"
 | |
| 
 | |
|     width = read_float()
 | |
|     length = read_float()
 | |
|     height = read_float()
 | |
|     ballast_factor = read_float()
 | |
|     future_use = read_float()
 | |
|     input_watts = read_float()
 | |
| 
 | |
|     _vertical_angles = [read_float() for i in range(num_vertical_angles)]
 | |
|     _horizontal_angles = [read_float() for i in range(num_horizontal_angles)]
 | |
| 
 | |
|     _candela_values = []
 | |
|     candela_scale = 0.0
 | |
| 
 | |
|     for i in range(num_horizontal_angles):
 | |
|         vertical_data = [read_float() for i in range(num_vertical_angles)]
 | |
|         candela_scale = max(candela_scale, max(vertical_data))
 | |
|         _candela_values += vertical_data
 | |
| 
 | |
|     # Rescale values, divide by maximum
 | |
|     _candela_values = [i / candela_scale for i in _candela_values]
 | |
|     generate_texture()
 | |
| 
 | |
| def generate_texture():
 | |
|     tex = bpy.data.images.new("iestexture", width=128, height=128, float_buffer=True) # R16
 | |
|     resolution_vertical = 128
 | |
|     resolution_horizontal = 128
 | |
| 
 | |
|     for vert in range(resolution_vertical):
 | |
|         for horiz in range(resolution_horizontal):
 | |
|             vert_angle = vert / (resolution_vertical - 1.0)
 | |
|             vert_angle = math.cos(vert_angle * math.pi) * 90.0 + 90.0
 | |
|             horiz_angle = horiz / (resolution_horizontal - 1.0) * 360.0
 | |
|             candela = get_candela_value(vert_angle, horiz_angle)
 | |
|             x = vert
 | |
|             y = horiz
 | |
|             i = x + y * resolution_horizontal
 | |
|             tex.pixels[i * 4] = candela
 | |
|             tex.pixels[i * 4 + 1] = candela
 | |
|             tex.pixels[i * 4 + 2] = candela
 | |
|             tex.pixels[i * 4 + 3] = 1.0
 | |
| 
 | |
| def get_candela_value(vertical_angle, horizontal_angle):
 | |
|     # Assume a dataset without horizontal angles
 | |
|     return get_vertical_candela_value(0, vertical_angle)
 | |
| 
 | |
| def get_vertical_candela_value(horizontal_angle_idx, vertical_angle):
 | |
|     if vertical_angle < 0.0:
 | |
|         return 0.0
 | |
| 
 | |
|     if vertical_angle > _vertical_angles[len(_vertical_angles) - 1]:
 | |
|         return 0.0
 | |
| 
 | |
|     for vertical_index in range(1, len(_vertical_angles)):
 | |
|         curr_angle = _vertical_angles[vertical_index]
 | |
|         if curr_angle > vertical_angle:
 | |
|             prev_angle = _vertical_angles[vertical_index - 1]
 | |
|             prev_value = get_candela_value_from_index(vertical_index - 1, horizontal_angle_idx)
 | |
|             curr_value = get_candela_value_from_index(vertical_index, horizontal_angle_idx)
 | |
|             lerp = (vertical_angle - prev_angle) / (curr_angle - prev_angle)
 | |
|             assert lerp >= 0.0 and lerp <= 1.0
 | |
|             return curr_value * lerp + prev_value * (1.0 - lerp)
 | |
|     return 0.0
 | |
| 
 | |
| def get_candela_value_from_index(vertical_angle_idx, horizontal_angle_idx):
 | |
|     index = vertical_angle_idx + horizontal_angle_idx * len(_vertical_angles)
 | |
|     return _candela_values[index]
 | |
| 
 | |
| filepath = "/Users/onek8/Desktop/ies/JellyFish.ies"
 | |
| load(filepath)
 |