Blender V4.3
usd_reader_light.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Tangent Animation. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "usd_reader_light.hh"
6
7#include "BLI_math_rotation.h"
8
9#include "BKE_light.h"
10#include "BKE_object.hh"
11
12#include "DNA_light_types.h"
13#include "DNA_object_types.h"
14
15#include <pxr/usd/usdLux/diskLight.h>
16#include <pxr/usd/usdLux/distantLight.h>
17#include <pxr/usd/usdLux/rectLight.h>
18#include <pxr/usd/usdLux/shapingAPI.h>
19#include <pxr/usd/usdLux/sphereLight.h>
20
21namespace blender::io::usd {
22
23void USDLightReader::create_object(Main *bmain, const double /*motionSampleTime*/)
24{
25 Light *blight = BKE_light_add(bmain, name_.c_str());
26
28 object_->data = blight;
29}
30
31void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime)
32{
33 Light *blight = (Light *)object_->data;
34
35 if (blight == nullptr) {
36 return;
37 }
38
39 if (!prim_) {
40 return;
41 }
42
43 pxr::UsdLuxLightAPI light_api(prim_);
44 if (!light_api) {
45 return;
46 }
47
48 float light_surface_area = 1.0f;
49
50 if (prim_.IsA<pxr::UsdLuxDiskLight>()) {
51 /* Disk area light. */
52 blight->type = LA_AREA;
53 blight->area_shape = LA_AREA_DISK;
54
55 pxr::UsdLuxDiskLight disk_light(prim_);
56 if (disk_light) {
57 if (pxr::UsdAttribute radius_attr = disk_light.GetRadiusAttr()) {
58 float radius = 0.0f;
59 if (radius_attr.Get(&radius, motionSampleTime)) {
60 blight->area_size = radius * 2.0f;
61 }
62 }
63 }
64
65 const float radius = 0.5f * blight->area_size;
66 light_surface_area = radius * radius * M_PI;
67 }
68 else if (prim_.IsA<pxr::UsdLuxRectLight>()) {
69 /* Rectangular area light. */
70 blight->type = LA_AREA;
71 blight->area_shape = LA_AREA_RECT;
72
73 pxr::UsdLuxRectLight rect_light(prim_);
74 if (rect_light) {
75 if (pxr::UsdAttribute width_attr = rect_light.GetWidthAttr()) {
76 float width = 0.0f;
77 if (width_attr.Get(&width, motionSampleTime)) {
78 blight->area_size = width;
79 }
80 }
81
82 if (pxr::UsdAttribute height_attr = rect_light.GetHeightAttr()) {
83 float height = 0.0f;
84 if (height_attr.Get(&height, motionSampleTime)) {
85 blight->area_sizey = height;
86 }
87 }
88 }
89
90 light_surface_area = blight->area_size * blight->area_sizey;
91 }
92 else if (prim_.IsA<pxr::UsdLuxSphereLight>()) {
93 /* Point and spot light. */
94 blight->type = LA_LOCAL;
95
96 pxr::UsdLuxSphereLight sphere_light(prim_);
97 if (sphere_light) {
98 pxr::UsdAttribute treatAsPoint_attr = sphere_light.GetTreatAsPointAttr();
99 bool treatAsPoint;
100 if (treatAsPoint_attr && treatAsPoint_attr.Get(&treatAsPoint, motionSampleTime) &&
101 treatAsPoint)
102 {
103 blight->radius = 0.0f;
104 }
105 else if (pxr::UsdAttribute radius_attr = sphere_light.GetRadiusAttr()) {
106 float radius = 0.0f;
107 if (radius_attr.Get(&radius, motionSampleTime)) {
108 blight->radius = radius;
109 }
110 }
111 }
112
113 light_surface_area = 4.0f * M_PI * blight->radius * blight->radius;
114
115 pxr::UsdLuxShapingAPI shaping_api = pxr::UsdLuxShapingAPI(prim_);
116 if (shaping_api && shaping_api.GetShapingConeAngleAttr().IsAuthored()) {
117 blight->type = LA_SPOT;
118
119 if (pxr::UsdAttribute cone_angle_attr = shaping_api.GetShapingConeAngleAttr()) {
120 float cone_angle = 0.0f;
121 if (cone_angle_attr.Get(&cone_angle, motionSampleTime)) {
122 blight->spotsize = DEG2RADF(cone_angle) * 2.0f;
123 }
124 }
125
126 if (pxr::UsdAttribute cone_softness_attr = shaping_api.GetShapingConeSoftnessAttr()) {
127 float cone_softness = 0.0f;
128 if (cone_softness_attr.Get(&cone_softness, motionSampleTime)) {
129 blight->spotblend = cone_softness;
130 }
131 }
132 }
133 }
134 else if (prim_.IsA<pxr::UsdLuxDistantLight>()) {
135 blight->type = LA_SUN;
136
137 pxr::UsdLuxDistantLight distant_light(prim_);
138 if (distant_light) {
139 if (pxr::UsdAttribute angle_attr = distant_light.GetAngleAttr()) {
140 float angle = 0.0f;
141 if (angle_attr.Get(&angle, motionSampleTime)) {
142 blight->sun_angle = DEG2RADF(angle * 2.0f);
143 }
144 }
145 }
146 }
147
148 /* Intensity */
149 if (pxr::UsdAttribute intensity_attr = light_api.GetIntensityAttr()) {
150 float intensity = 0.0f;
151 if (intensity_attr.Get(&intensity, motionSampleTime)) {
152 if (blight->type == LA_SUN) {
153 /* Unclear why, but approximately matches Karma. */
154 blight->energy = intensity * 4.0f;
155 }
156 else {
157 /* Convert from intensity to radiant flux. */
158 blight->energy = intensity * M_PI;
159 }
161 }
162 }
163
164 /* Exposure. */
165 if (pxr::UsdAttribute exposure_attr = light_api.GetExposureAttr()) {
166 float exposure = 0.0f;
167 if (exposure_attr.Get(&exposure, motionSampleTime)) {
168 blight->energy *= pow(2.0f, exposure);
169 }
170 }
171
172 /* Color. */
173 if (pxr::UsdAttribute color_attr = light_api.GetColorAttr()) {
174 pxr::GfVec3f color;
175 if (color_attr.Get(&color, motionSampleTime)) {
176 blight->r = color[0];
177 blight->g = color[1];
178 blight->b = color[2];
179 }
180 }
181
182 /* Diffuse and Specular. */
183 if (pxr::UsdAttribute diff_attr = light_api.GetDiffuseAttr()) {
184 float diff_fac = 1.0f;
185 if (diff_attr.Get(&diff_fac, motionSampleTime)) {
186 blight->diff_fac = diff_fac;
187 }
188 }
189 if (pxr::UsdAttribute spec_attr = light_api.GetSpecularAttr()) {
190 float spec_fac = 1.0f;
191 if (spec_attr.Get(&spec_fac, motionSampleTime)) {
192 blight->spec_fac = spec_fac;
193 }
194 }
195
196 /* Normalize: Blender lights are always normalized, so inverse correct for it
197 * TODO: take into account object transform, or natively support this as a
198 * setting on lights in Blender. */
199 bool normalize = false;
200 if (pxr::UsdAttribute normalize_attr = light_api.GetNormalizeAttr()) {
201 normalize_attr.Get(&normalize, motionSampleTime);
202 }
203 if (!normalize) {
204 blight->energy *= light_surface_area;
205 }
206
207 /* TODO:
208 * bool GetEnableColorTemperatureAttr
209 * float GetColorTemperatureAttr
210 */
211
212 USDXformReader::read_object_data(bmain, motionSampleTime);
213}
214
215} // namespace blender::io::usd
General operations, lookup, etc. for blender lights.
struct Light * BKE_light_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT
General operations, lookup, etc. for blender objects.
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
#define M_PI
#define DEG2RADF(_deg)
@ LA_AREA
@ LA_LOCAL
@ LA_SPOT
@ LA_SUN
@ LA_AREA_RECT
@ LA_AREA_DISK
Object is a sort of wrapper for general info.
@ OB_LAMP
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
void create_object(Main *bmain, double motionSampleTime) override
void read_object_data(Main *bmain, double motionSampleTime) override
const USDImportParams & import_params_
void read_object_data(Main *bmain, double motionSampleTime) override
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
float sun_angle
float energy
float spec_fac
float area_sizey
short area_shape
float spotblend
float spotsize
float radius
float area_size
short type
float diff_fac