Export_3ds: Improved distance cue node search
[blender-addons.git] / io_scene_gltf2 / blender / imp / gltf2_blender_light.py
blob5de9d4ff17e363a222c65d7061d4e27af5cd7eab
1 # SPDX-FileCopyrightText: 2018-2021 The glTF-Blender-IO authors
3 # SPDX-License-Identifier: Apache-2.0
5 import bpy
6 from math import pi
8 from ...io.imp.gltf2_io_user_extensions import import_user_extensions
9 from ..com.gltf2_blender_conversion import PBR_WATTS_TO_LUMENS
10 from ..com.gltf2_blender_extras import set_extras
12 class BlenderLight():
13 """Blender Light."""
14 def __new__(cls, *args, **kwargs):
15 raise RuntimeError("%s should not be instantiated" % cls)
17 @staticmethod
18 def create(gltf, vnode, light_id):
19 """Light creation."""
20 pylight = gltf.data.extensions['KHR_lights_punctual']['lights'][light_id]
22 import_user_extensions('gather_import_light_before_hook', gltf, vnode, pylight)
24 if pylight['type'] == "directional":
25 light = BlenderLight.create_directional(gltf, light_id) # ...Why not pass the pylight?
26 elif pylight['type'] == "point":
27 light = BlenderLight.create_point(gltf, light_id)
28 elif pylight['type'] == "spot":
29 light = BlenderLight.create_spot(gltf, light_id)
31 if 'color' in pylight.keys():
32 light.color = pylight['color']
34 # TODO range
36 set_extras(light, pylight.get('extras'))
38 pylight['blender_object_data'] = light # Needed in case of KHR_animation_pointer
40 return light
42 @staticmethod
43 def create_directional(gltf, light_id):
44 pylight = gltf.data.extensions['KHR_lights_punctual']['lights'][light_id]
46 if 'name' not in pylight.keys():
47 pylight['name'] = "Sun" # Uh... Is it okay to mutate the import data?
49 sun = bpy.data.lights.new(name=pylight['name'], type="SUN")
51 if 'intensity' in pylight.keys():
52 sun.energy = BlenderLight.calc_energy_directional(gltf, pylight['intensity'])
54 return sun
56 @staticmethod
57 def calc_energy_directional(gltf, pylight_data):
58 if gltf.import_settings['export_import_convert_lighting_mode'] == 'SPEC':
59 return pylight_data / PBR_WATTS_TO_LUMENS
60 elif gltf.import_settings['export_import_convert_lighting_mode'] == 'COMPAT':
61 return pylight_data
62 elif gltf.import_settings['export_import_convert_lighting_mode'] == 'RAW':
63 return pylight_data
64 else:
65 raise ValueError(gltf.import_settings['export_import_convert_lighting_mode'])
67 @staticmethod
68 def calc_energy_pointlike(gltf, pylight_data):
69 if gltf.import_settings['export_import_convert_lighting_mode'] == 'SPEC':
70 return pylight_data / PBR_WATTS_TO_LUMENS * 4 * pi
71 elif gltf.import_settings['export_import_convert_lighting_mode'] == 'COMPAT':
72 return pylight_data * 4 * pi
73 elif gltf.import_settings['export_import_convert_lighting_mode'] == 'RAW':
74 return pylight_data
75 else:
76 raise ValueError(gltf.import_settings['export_import_convert_lighting_mode'])
78 @staticmethod
79 def create_point(gltf, light_id):
80 pylight = gltf.data.extensions['KHR_lights_punctual']['lights'][light_id]
82 if 'name' not in pylight.keys():
83 pylight['name'] = "Point"
85 point = bpy.data.lights.new(name=pylight['name'], type="POINT")
87 if 'intensity' in pylight.keys():
88 point.energy = BlenderLight.calc_energy_pointlike(gltf, pylight['intensity'])
90 return point
92 @staticmethod
93 def create_spot(gltf, light_id):
94 pylight = gltf.data.extensions['KHR_lights_punctual']['lights'][light_id]
96 if 'name' not in pylight.keys():
97 pylight['name'] = "Spot"
99 spot = bpy.data.lights.new(name=pylight['name'], type="SPOT")
101 # Angles
102 if 'spot' in pylight.keys() and 'outerConeAngle' in pylight['spot']:
103 spot.spot_size = BlenderLight.calc_spot_cone_outer(gltf, pylight['spot']['outerConeAngle'])
104 else:
105 spot.spot_size = pi / 2
107 if 'spot' in pylight.keys() and 'innerConeAngle' in pylight['spot']:
108 spot.spot_blend = BlenderLight.calc_spot_cone_inner(gltf, pylight['spot']['outerConeAngle'], pylight['spot']['innerConeAngle'])
109 else:
110 spot.spot_blend = 1.0
112 if 'intensity' in pylight.keys():
113 spot.energy = BlenderLight.calc_energy_pointlike(gltf, pylight['intensity'])
115 # Store multiple channel data, as we will need all channels to convert to blender data when animated by KHR_animation_pointer
116 if gltf.data.extensions_used is not None and "KHR_animation_pointer" in gltf.data.extensions_used:
117 if len(pylight['animations']) > 0:
118 for anim_idx in pylight['animations'].keys():
119 for channel_idx in pylight['animations'][anim_idx]:
120 channel = gltf.data.animations[anim_idx].channels[channel_idx]
121 pointer_tab = channel.target.extensions["KHR_animation_pointer"]["pointer"].split("/")
122 if len(pointer_tab) == 6 and pointer_tab[1] == "extensions" and \
123 pointer_tab[2] == "KHR_lights_punctual" and \
124 pointer_tab[3] == "lights" and \
125 pointer_tab[5] in ["spot.innerConeAngle", "spot.outerConeAngle"]:
126 # Store multiple channel data, as we will need all channels to convert to blender data when animated
127 if "multiple_channels" not in pylight.keys():
128 pylight['multiple_channels'] = {}
129 pylight['multiple_channels'][pointer_tab[5]] = (anim_idx, channel_idx)
131 return spot
133 @staticmethod
134 def calc_spot_cone_outer(gltf, outercone):
135 return outercone * 2
137 @staticmethod
138 def calc_spot_cone_inner(gltf, outercone, innercone):
139 return 1 - ( innercone / outercone )