Blender V4.5
usd_writer_light.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4#include "usd_writer_light.hh"
7
8#include <pxr/usd/usdLux/diskLight.h>
9#include <pxr/usd/usdLux/distantLight.h>
10#include <pxr/usd/usdLux/rectLight.h>
11#include <pxr/usd/usdLux/shapingAPI.h>
12#include <pxr/usd/usdLux/sphereLight.h>
13
14#include "BLI_assert.h"
15#include "BLI_math_rotation.h"
16
17#include "DNA_light_types.h"
18
19namespace blender::io::usd {
20
22
23bool USDLightWriter::is_supported(const HierarchyContext * /*context*/) const
24{
25 return true;
26}
27
29{
30 pxr::UsdStageRefPtr stage = usd_export_context_.stage;
31 const pxr::SdfPath &usd_path = usd_export_context_.usd_path;
32 pxr::UsdTimeCode timecode = get_export_time_code();
33
34 const Light *light = static_cast<const Light *>(context.object->data);
35 pxr::UsdLuxLightAPI usd_light_api;
36
37 switch (light->type) {
38 case LA_AREA: {
39 switch (light->area_shape) {
40 case LA_AREA_RECT: {
41 pxr::UsdLuxRectLight rect_light = pxr::UsdLuxRectLight::Define(stage, usd_path);
42 set_attribute(rect_light.CreateWidthAttr(pxr::VtValue(), true),
43 light->area_size,
44 timecode,
46 set_attribute(rect_light.CreateHeightAttr(pxr::VtValue(), true),
47 light->area_sizey,
48 timecode,
50 usd_light_api = rect_light.LightAPI();
51 break;
52 }
53 case LA_AREA_SQUARE: {
54 pxr::UsdLuxRectLight rect_light = pxr::UsdLuxRectLight::Define(stage, usd_path);
55 set_attribute(rect_light.CreateWidthAttr(pxr::VtValue(), true),
56 light->area_size,
57 timecode,
59 set_attribute(rect_light.CreateHeightAttr(pxr::VtValue(), true),
60 light->area_size,
61 timecode,
63 usd_light_api = rect_light.LightAPI();
64 break;
65 }
66 case LA_AREA_DISK: {
67 pxr::UsdLuxDiskLight disk_light = pxr::UsdLuxDiskLight::Define(stage, usd_path);
68 set_attribute(disk_light.CreateRadiusAttr(pxr::VtValue(), true),
69 light->area_size / 2.0f,
70 timecode,
72 usd_light_api = disk_light.LightAPI();
73 break;
74 }
75 case LA_AREA_ELLIPSE: {
76 /* An ellipse light deteriorates into a disk light. */
77 pxr::UsdLuxDiskLight disk_light = pxr::UsdLuxDiskLight::Define(stage, usd_path);
78 set_attribute(disk_light.CreateRadiusAttr(pxr::VtValue(), true),
79 (light->area_size + light->area_sizey) / 4.0f,
80 timecode,
82 usd_light_api = disk_light.LightAPI();
83 break;
84 }
85 }
86 break;
87 }
88 case LA_LOCAL:
89 case LA_SPOT: {
90 pxr::UsdLuxSphereLight sphere_light = pxr::UsdLuxSphereLight::Define(stage, usd_path);
91 set_attribute(sphere_light.CreateRadiusAttr(pxr::VtValue(), true),
92 light->radius,
93 timecode,
95 set_attribute(sphere_light.CreateTreatAsPointAttr(pxr::VtValue(), true),
96 light->radius == 0.0f,
97 timecode,
99
100 if (light->type == LA_SPOT) {
101 pxr::UsdLuxShapingAPI shaping_api = pxr::UsdLuxShapingAPI::Apply(sphere_light.GetPrim());
102 if (shaping_api) {
103 set_attribute(shaping_api.CreateShapingConeAngleAttr(pxr::VtValue(), true),
104 RAD2DEGF(light->spotsize) / 2.0f,
105 timecode,
107 set_attribute(shaping_api.CreateShapingConeSoftnessAttr(pxr::VtValue(), true),
108 light->spotblend,
109 timecode,
111 }
112 }
113
114 usd_light_api = sphere_light.LightAPI();
115 break;
116 }
117 case LA_SUN: {
118 pxr::UsdLuxDistantLight distant_light = pxr::UsdLuxDistantLight::Define(stage, usd_path);
119 set_attribute(distant_light.CreateAngleAttr(pxr::VtValue(), true),
120 RAD2DEGF(light->sun_angle / 2.0f),
121 timecode,
123 usd_light_api = distant_light.LightAPI();
124 break;
125 }
126 default:
128 break;
129 }
130
131 float intensity;
132 if (light->type == LA_SUN) {
133 /* Unclear why, but approximately matches Karma. */
134 intensity = light->energy / 4.0f;
135 }
136 else {
137 /* Convert from radiant flux to intensity. */
138 intensity = light->energy / M_PI;
139 }
140
141 set_attribute(usd_light_api.CreateIntensityAttr(pxr::VtValue(), true),
142 intensity,
143 timecode,
145 set_attribute(usd_light_api.CreateExposureAttr(pxr::VtValue(), true),
146 light->exposure,
147 timecode,
149
150 set_attribute(usd_light_api.CreateColorAttr(pxr::VtValue(), true),
151 pxr::GfVec3f(light->r, light->g, light->b),
152 timecode,
154 set_attribute(usd_light_api.CreateEnableColorTemperatureAttr(
155 pxr::VtValue(), (light->mode & LA_USE_TEMPERATURE) != 0),
156 true,
157 timecode,
159 set_attribute(usd_light_api.CreateColorTemperatureAttr(pxr::VtValue(), true),
160 light->temperature,
161 timecode,
163
164 set_attribute(usd_light_api.CreateDiffuseAttr(pxr::VtValue(), true),
165 light->diff_fac,
166 timecode,
168 set_attribute(usd_light_api.CreateSpecularAttr(pxr::VtValue(), true),
169 light->spec_fac,
170 timecode,
172 set_attribute(usd_light_api.CreateNormalizeAttr(pxr::VtValue(), true),
173 (light->mode & LA_UNNORMALIZED) == 0,
174 timecode,
176
177 pxr::UsdPrim prim = usd_light_api.GetPrim();
178 write_id_properties(prim, light->id, timecode);
179
180 /* Only a subset of light types are "boundable". */
181 if (auto boundable = pxr::UsdGeomBoundable(prim)) {
182 this->author_extent(boundable, timecode);
183 }
184}
185
186} // namespace blender::io::usd
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define RAD2DEGF(_rad)
#define M_PI
@ LA_USE_TEMPERATURE
@ LA_UNNORMALIZED
@ LA_AREA
@ LA_LOCAL
@ LA_SPOT
@ LA_SUN
@ LA_AREA_ELLIPSE
@ LA_AREA_SQUARE
@ LA_AREA_RECT
@ LA_AREA_DISK
const pxr::SdfPath & usd_path() const
void author_extent(const pxr::UsdGeomBoundable &boundable, const pxr::UsdTimeCode timecode)
pxr::UsdTimeCode get_export_time_code() const
pxr::UsdUtilsSparseValueWriter usd_value_writer_
USDAbstractWriter(const USDExporterContext &usd_export_context)
void write_id_properties(const pxr::UsdPrim &prim, const ID &id, pxr::UsdTimeCode=pxr::UsdTimeCode::Default()) const
const USDExporterContext usd_export_context_
bool is_supported(const HierarchyContext *context) const override
USDLightWriter(const USDExporterContext &ctx)
void do_write(HierarchyContext &context) override
void set_attribute(const pxr::UsdAttribute &attr, const USDT value, pxr::UsdTimeCode timecode, pxr::UsdUtilsSparseValueWriter &value_writer)
float sun_angle
float energy
float temperature
float spec_fac
float area_sizey
short area_shape
float spotblend
float spotsize
float exposure
float radius
float area_size
short type
float diff_fac