Blender V4.3
usd_light_convert.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "usd.hh"
8#include "usd_asset_utils.hh"
9#include "usd_private.hh"
10#include "usd_reader_prim.hh"
12
13#include <pxr/base/gf/rotation.h>
14#include <pxr/base/gf/vec3f.h>
15#include <pxr/usd/usdGeom/metrics.h>
16#include <pxr/usd/usdGeom/tokens.h>
17#include <pxr/usd/usdGeom/xformCache.h>
18#include <pxr/usd/usdGeom/xformCommonAPI.h>
19#include <pxr/usd/usdLux/domeLight.h>
20
21#include "BKE_image.hh"
22#include "BKE_main.hh"
23#include "BKE_node.hh"
24#include "BKE_node_runtime.hh"
26#include "BLI_fileops.h"
27#include "BLI_listbase.h"
28#include "BLI_math_vector.h"
29#include "BLI_path_utils.hh"
30
31#include "DNA_node_types.h"
32#include "DNA_scene_types.h"
33#include "DNA_world_types.h"
34
35#include <string>
36
37#include "CLG_log.h"
38static CLG_LogRef LOG = {"io.usd"};
39
40namespace usdtokens {
41// Attribute names.
42static const pxr::TfToken color("color", pxr::TfToken::Immortal);
43static const pxr::TfToken intensity("intensity", pxr::TfToken::Immortal);
44static const pxr::TfToken texture_file("texture:file", pxr::TfToken::Immortal);
45} // namespace usdtokens
46
47namespace {
48
59template<typename T>
60bool get_authored_value(const pxr::UsdAttribute &attr,
61 const double motionSampleTime,
62 const pxr::UsdPrim &prim,
63 const pxr::TfToken fallback_attr_name,
64 T *r_value)
65{
66 if (attr && attr.HasAuthoredValue()) {
67 return attr.Get<T>(r_value, motionSampleTime);
68 }
69
70 if (!prim || fallback_attr_name.IsEmpty()) {
71 return false;
72 }
73
74 pxr::UsdAttribute fallback_attr = prim.GetAttribute(fallback_attr_name);
75 if (fallback_attr && fallback_attr.HasAuthoredValue()) {
76 return fallback_attr.Get<T>(r_value, motionSampleTime);
77 }
78
79 return false;
80}
81
86struct WorldNtreeSearchResults {
88 pxr::UsdStageRefPtr stage;
89
90 std::string file_path;
91
92 float world_intensity = 0.0f;
93 float world_color[3]{};
94 float mapping_rot[3]{};
95 float color_mult[3]{};
96
97 bool background_found = false;
98 bool env_tex_found = false;
99 bool mult_found = false;
100
101 WorldNtreeSearchResults(const blender::io::usd::USDExportParams &in_params,
102 pxr::UsdStageRefPtr in_stage)
103 : params(in_params), stage(in_stage)
104 {
105 }
106};
107
108} // End anonymous namespace.
109
110namespace blender::io::usd {
111
117static pxr::SdfPath get_unique_path(pxr::UsdStageRefPtr stage, const std::string &path)
118{
119 std::string unique_path = path;
120 int suffix = 2;
121 while (stage->GetPrimAtPath(pxr::SdfPath(unique_path)).IsValid()) {
122 unique_path = path + std::to_string(suffix++);
123 }
124 return pxr::SdfPath(unique_path);
125}
126
131static Image *load_image(std::string tex_path, Main *bmain, const USDImportParams &params)
132{
133 /* Optionally copy the asset if it's inside a USDZ package. */
134 const bool import_textures = params.import_textures_mode != USD_TEX_IMPORT_NONE &&
135 should_import_asset(tex_path);
136
137 std::string imported_file_source_path = tex_path;
138
139 if (import_textures) {
140 /* If we are packing the imported textures, we first write them
141 * to a temporary directory. */
142 const char *textures_dir = params.import_textures_mode == USD_TEX_IMPORT_PACK ?
144 params.import_textures_dir;
145
146 const eUSDTexNameCollisionMode name_collision_mode = params.import_textures_mode ==
149 params.tex_name_collision_mode;
150
151 tex_path = import_asset(tex_path.c_str(), textures_dir, name_collision_mode, nullptr);
152 }
153
154 Image *image = BKE_image_load_exists(bmain, tex_path.c_str());
155 if (!image) {
156 return nullptr;
157 }
158
159 if (import_textures && imported_file_source_path != tex_path) {
160 ensure_usd_source_path_prop(imported_file_source_path, &image->id);
161 }
162
163 if (import_textures && params.import_textures_mode == USD_TEX_IMPORT_PACK &&
165 {
166 BKE_image_packfiles(nullptr, image, ID_BLEND_PATH(bmain, &image->id));
168 BLI_delete(temp_textures_dir(), true, true);
169 }
170 }
171
172 return image;
173}
174
175/* Create a new node of type 'new_node_type' and connect it
176 * as an upstream source to 'dst_node' with the given sockets. */
177static bNode *append_node(bNode *dst_node,
178 int16_t new_node_type,
179 const char *out_sock,
180 const char *in_sock,
181 bNodeTree *ntree,
182 float offset)
183{
184 bNode *src_node = bke::node_add_static_node(nullptr, ntree, new_node_type);
185 if (!src_node) {
186 return nullptr;
187 }
188
189 bke::node_add_link(ntree,
190 src_node,
191 bke::node_find_socket(src_node, SOCK_OUT, out_sock),
192 dst_node,
193 bke::node_find_socket(dst_node, SOCK_IN, in_sock));
194
195 src_node->locx = dst_node->locx - offset;
196 src_node->locy = dst_node->locy;
197
198 return src_node;
199}
200
206static bool node_search(bNode *fromnode,
207 bNode * /*tonode*/,
208 void *userdata,
209 const bool /*reversed*/)
210{
211 if (!(userdata && fromnode)) {
212 return true;
213 }
214
215 WorldNtreeSearchResults *res = reinterpret_cast<WorldNtreeSearchResults *>(userdata);
216
217 if (!res->background_found && fromnode->type == SH_NODE_BACKGROUND) {
218 /* Get light color and intensity */
219 const bNodeSocketValueRGBA *color_data = bke::node_find_socket(fromnode, SOCK_IN, "Color")
220 ->default_value_typed<bNodeSocketValueRGBA>();
221 const bNodeSocketValueFloat *strength_data =
222 bke::node_find_socket(fromnode, SOCK_IN, "Strength")
223 ->default_value_typed<bNodeSocketValueFloat>();
224
225 res->background_found = true;
226 res->world_intensity = strength_data->value;
227 res->world_color[0] = color_data->value[0];
228 res->world_color[1] = color_data->value[1];
229 res->world_color[2] = color_data->value[2];
230 }
231 else if (!res->env_tex_found && fromnode->type == SH_NODE_TEX_ENVIRONMENT) {
232 /* Get env tex path. */
233
234 res->file_path = get_tex_image_asset_filepath(fromnode, res->stage, res->params);
235
236 if (!res->file_path.empty()) {
237 res->env_tex_found = true;
238 if (res->params.export_textures) {
239 export_texture(fromnode, res->stage, res->params.overwrite_textures);
240 }
241 }
242 }
243 else if (!res->env_tex_found && !res->mult_found && fromnode->type == SH_NODE_VECTOR_MATH) {
244
245 if (fromnode->custom1 == NODE_VECTOR_MATH_MULTIPLY) {
246 res->mult_found = true;
247
248 bNodeSocket *vec_sock = bke::node_find_socket(fromnode, SOCK_IN, "Vector");
249 if (vec_sock) {
250 vec_sock = vec_sock->next;
251 }
252
253 if (vec_sock) {
254 copy_v3_v3(res->color_mult, ((bNodeSocketValueVector *)vec_sock->default_value)->value);
255 }
256 }
257 }
258 else if (res->env_tex_found && fromnode->type == SH_NODE_MAPPING) {
259 copy_v3_fl(res->mapping_rot, 0.0f);
260 if (bNodeSocket *socket = bke::node_find_socket(fromnode, SOCK_IN, "Rotation")) {
261 const bNodeSocketValueVector *rot_value = static_cast<bNodeSocketValueVector *>(
262 socket->default_value);
263 copy_v3_v3(res->mapping_rot, rot_value->value);
264 }
265 }
266
267 return true;
268}
269
275 const Scene *scene,
276 pxr::UsdStageRefPtr stage)
277{
278 if (!(stage && scene && scene->world && scene->world->use_nodes && scene->world->nodetree)) {
279 return;
280 }
281
282 /* Find the world output. */
283 const bNodeTree *ntree = scene->world->nodetree;
284 ntree->ensure_topology_cache();
285 const blender::Span<const bNode *> bsdf_nodes = ntree->nodes_by_type("ShaderNodeOutputWorld");
286 const bNode *output = bsdf_nodes.is_empty() ? nullptr : bsdf_nodes.first();
287
288 if (!output) {
289 /* No output, no valid network to convert. */
290 return;
291 }
292
293 WorldNtreeSearchResults res(params, stage);
294
295 bke::node_chain_iterator(scene->world->nodetree, output, node_search, &res, true);
296
297 if (!(res.background_found || res.env_tex_found)) {
298 /* No nodes to convert */
299 return;
300 }
301
302 /* Create USD dome light. */
303
304 pxr::SdfPath env_light_path = get_unique_path(stage,
305 std::string(params.root_prim_path) + "/env_light");
306
307 pxr::UsdLuxDomeLight dome_light = pxr::UsdLuxDomeLight::Define(stage, env_light_path);
308
309 if (!res.env_tex_found) {
310 /* Like the Hydra delegate, if no texture is found export a solid
311 * color texture as a stand-in so that Hydra renderers don't
312 * throw errors. */
313
314 float fill_color[4] = {res.world_color[0], res.world_color[1], res.world_color[2], 1.0f};
315
316 std::string source_path = cache_image_color(fill_color);
317 const std::string base_path = stage->GetRootLayer()->GetRealPath();
318
319 /* It'll be short, coming from cache_image_color. */
320 char file_path[64];
321 BLI_path_split_file_part(source_path.c_str(), file_path, 64);
322 char dest_path[FILE_MAX];
323 BLI_path_split_dir_part(base_path.c_str(), dest_path, FILE_MAX);
324
325 BLI_path_append_dir(dest_path, FILE_MAX, "textures");
326 BLI_dir_create_recursive(dest_path);
327
328 BLI_path_append(dest_path, FILE_MAX, file_path);
329
330 if (BLI_copy(source_path.c_str(), dest_path) != 0) {
331 CLOG_WARN(&LOG, "USD Export: Couldn't write world color image to %s", dest_path);
332 }
333 else {
334 res.env_tex_found = true;
335 BLI_path_join(dest_path, FILE_MAX, ".", "textures", file_path);
336 res.file_path = dest_path;
337 }
338 }
339
340 if (res.env_tex_found) {
341 pxr::SdfAssetPath path(res.file_path);
342 dome_light.CreateTextureFileAttr().Set(path);
343
344 if (res.mult_found) {
345 pxr::GfVec3f color_val(res.color_mult[0], res.color_mult[1], res.color_mult[2]);
346 dome_light.CreateColorAttr().Set(color_val);
347 }
348 }
349 else {
350 pxr::GfVec3f color_val(res.world_color[0], res.world_color[1], res.world_color[2]);
351 dome_light.CreateColorAttr().Set(color_val);
352 }
353
354 if (res.background_found) {
355 dome_light.CreateIntensityAttr().Set(res.world_intensity);
356 }
357
358 /* We always set a default rotation on the light since res.mapping_rot defaults to zeros. */
359
360 /* Convert radians to degrees. */
361 mul_v3_fl(res.mapping_rot, 180.0f / M_PI);
362
363 pxr::GfMatrix4d xf =
364 pxr::GfMatrix4d().SetRotate(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), 90.0)) *
365 pxr::GfMatrix4d().SetRotate(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0)) *
366 pxr::GfMatrix4d().SetRotate(
367 pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), -res.mapping_rot[2])) *
368 pxr::GfMatrix4d().SetRotate(
369 pxr::GfRotation(pxr::GfVec3d(0.0, 1.0, 0.0), -res.mapping_rot[1])) *
370 pxr::GfMatrix4d().SetRotate(
371 pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -res.mapping_rot[0]));
372
373 pxr::GfVec3d angles = xf.DecomposeRotation(
374 pxr::GfVec3d::ZAxis(), pxr::GfVec3d::YAxis(), pxr::GfVec3d::XAxis());
375
376 pxr::GfVec3f rot_vec(angles[2], angles[1], angles[0]);
377
378 pxr::UsdGeomXformCommonAPI xform_api(dome_light);
379 xform_api.SetRotate(rot_vec, pxr::UsdGeomXformCommonAPI::RotationOrderXYZ);
380}
381
382/* Import the dome light as a world material. */
383
385 const ImportSettings & /*settings*/,
386 Scene *scene,
387 Main *bmain,
388 const pxr::UsdLuxDomeLight &dome_light,
389 const double motionSampleTime)
390{
391 if (!(scene && scene->world && dome_light)) {
392 return;
393 }
394
395 if (!scene->world->use_nodes) {
396 scene->world->use_nodes = true;
397 }
398
399 if (!scene->world->nodetree) {
400 scene->world->nodetree = bke::node_tree_add_tree(nullptr, "Shader Nodetree", "ShaderNodeTree");
401 if (!scene->world->nodetree) {
402 CLOG_WARN(&LOG, "Couldn't create world ntree");
403 return;
404 }
405 }
406
407 bNodeTree *ntree = scene->world->nodetree;
408 bNode *output = nullptr;
409 bNode *bgshader = nullptr;
410
411 /* We never delete existing nodes, but we might disconnect them
412 * and move them out of the way. */
413
414 /* Look for the output and background shader nodes, which we will reuse. */
415 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
416 if (node->type == SH_NODE_OUTPUT_WORLD) {
417 output = node;
418 }
419 else if (node->type == SH_NODE_BACKGROUND) {
420 bgshader = node;
421 }
422 else {
423 /* Move existing node out of the way. */
424 node->locy += 300;
425 }
426 }
427
428 /* Create the output and background shader nodes, if they don't exist. */
429 if (!output) {
430 output = bke::node_add_static_node(nullptr, ntree, SH_NODE_OUTPUT_WORLD);
431
432 if (!output) {
433 CLOG_WARN(&LOG, "Couldn't create world output node");
434 return;
435 }
436
437 output->locx = 300.0f;
438 output->locy = 300.0f;
439 }
440
441 if (!bgshader) {
442 bgshader = append_node(output, SH_NODE_BACKGROUND, "Background", "Surface", ntree, 200);
443
444 if (!bgshader) {
445 CLOG_WARN(&LOG, "Couldn't create world shader node");
446 return;
447 }
448
449 /* Set the default background color. */
450 bNodeSocket *color_sock = bke::node_find_socket(bgshader, SOCK_IN, "Color");
451 copy_v3_v3(((bNodeSocketValueRGBA *)color_sock->default_value)->value, &scene->world->horr);
452 }
453
454 /* Make sure the first input to the shader node is disconnected. */
455 bNodeSocket *shader_input = bke::node_find_socket(bgshader, SOCK_IN, "Color");
456
457 if (shader_input && shader_input->link) {
458 bke::node_remove_link(ntree, shader_input->link);
459 }
460
461 /* Set the background shader intensity. */
462 float intensity = 1.0f;
463 get_authored_value(dome_light.GetIntensityAttr(),
464 motionSampleTime,
465 dome_light.GetPrim(),
467 &intensity);
468
469 intensity *= params.light_intensity_scale;
470
471 bNodeSocket *strength_sock = bke::node_find_socket(bgshader, SOCK_IN, "Strength");
472 ((bNodeSocketValueFloat *)strength_sock->default_value)->value = intensity;
473
474 /* Get the dome light texture file and color. */
475 pxr::SdfAssetPath tex_path;
476 bool has_tex = get_authored_value(dome_light.GetTextureFileAttr(),
477 motionSampleTime,
478 dome_light.GetPrim(),
480 &tex_path);
481
482 pxr::GfVec3f color;
483 bool has_color = get_authored_value(
484 dome_light.GetColorAttr(), motionSampleTime, dome_light.GetPrim(), usdtokens::color, &color);
485
486 if (!has_tex) {
487 /* No texture file is authored on the dome light. Set the color, if it was authored,
488 * and return early. */
489 if (has_color) {
490 bNodeSocket *color_sock = bke::node_find_socket(bgshader, SOCK_IN, "Color");
491 copy_v3_v3(((bNodeSocketValueRGBA *)color_sock->default_value)->value, color.data());
492 }
493
494 bke::node_set_active(ntree, output);
495 BKE_ntree_update_main_tree(bmain, ntree, nullptr);
496
497 return;
498 }
499
500 /* If the light has authored color, create a color multiply node for the environment
501 * texture output. */
502 bNode *mult = nullptr;
503
504 if (has_color) {
505 mult = append_node(bgshader, SH_NODE_VECTOR_MATH, "Vector", "Color", ntree, 200);
506
507 if (!mult) {
508 CLOG_WARN(&LOG, "Couldn't create vector multiply node");
509 return;
510 }
511
513
514 /* Set the color in the vector math node's second socket. */
515 bNodeSocket *vec_sock = bke::node_find_socket(mult, SOCK_IN, "Vector");
516 if (vec_sock) {
517 vec_sock = vec_sock->next;
518 }
519
520 if (vec_sock) {
521 copy_v3_v3(((bNodeSocketValueVector *)vec_sock->default_value)->value, color.data());
522 }
523 else {
524 CLOG_WARN(&LOG, "Couldn't find vector multiply second vector socket");
525 }
526 }
527
528 bNode *tex = nullptr;
529
530 /* Append an environment texture node to the mult node, if it was created, or directly to
531 * the background shader. */
532 if (mult) {
533 tex = append_node(mult, SH_NODE_TEX_ENVIRONMENT, "Color", "Vector", ntree, 400);
534 }
535 else {
536 tex = append_node(bgshader, SH_NODE_TEX_ENVIRONMENT, "Color", "Color", ntree, 400);
537 }
538
539 if (!tex) {
540 CLOG_WARN(&LOG, "Couldn't create world environment texture node");
541 return;
542 }
543
544 bNode *mapping = append_node(tex, SH_NODE_MAPPING, "Vector", "Vector", ntree, 200);
545
546 if (!mapping) {
547 CLOG_WARN(&LOG, "Couldn't create mapping node");
548 return;
549 }
550
551 bNode *tex_coord = append_node(mapping, SH_NODE_TEX_COORD, "Generated", "Vector", ntree, 200);
552
553 if (!tex_coord) {
554 CLOG_WARN(&LOG, "Couldn't create texture coordinate node");
555 return;
556 }
557
558 /* Load the texture image. */
559 std::string resolved_path = tex_path.GetResolvedPath();
560
561 if (resolved_path.empty()) {
562 CLOG_WARN(&LOG, "Couldn't get resolved path for asset %s", tex_path.GetAssetPath().c_str());
563 return;
564 }
565
566 Image *image = load_image(resolved_path, bmain, params);
567 if (!image) {
568 CLOG_WARN(&LOG, "Couldn't load image file %s", resolved_path.c_str());
569 return;
570 }
571
572 tex->id = &image->id;
573
574 /* Set the transform. */
575 pxr::UsdGeomXformCache xf_cache(motionSampleTime);
576 pxr::GfMatrix4d xf = xf_cache.GetLocalToWorldTransform(dome_light.GetPrim());
577
578 pxr::UsdStageRefPtr stage = dome_light.GetPrim().GetStage();
579
580 if (!stage) {
581 CLOG_WARN(
582 &LOG, "Couldn't get stage for dome light %s", dome_light.GetPrim().GetPath().GetText());
583 return;
584 }
585
586 if (pxr::UsdGeomGetStageUpAxis(stage) == pxr::UsdGeomTokens->y) {
587 /* Convert from Y-up to Z-up with a 90 degree rotation about the X-axis. */
588 xf *= pxr::GfMatrix4d().SetRotate(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), 90.0));
589 }
590
591 xf = pxr::GfMatrix4d().SetRotate(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), -90.0)) *
592 pxr::GfMatrix4d().SetRotate(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90.0)) * xf;
593
594 pxr::GfVec3d angles = xf.DecomposeRotation(
595 pxr::GfVec3d::XAxis(), pxr::GfVec3d::YAxis(), pxr::GfVec3d::ZAxis());
596 pxr::GfVec3f rot_vec(-angles[0], -angles[1], -angles[2]);
597
598 /* Convert degrees to radians. */
599 rot_vec *= M_PI / 180.0f;
600
601 if (bNodeSocket *socket = bke::node_find_socket(mapping, SOCK_IN, "Rotation")) {
602 bNodeSocketValueVector *rot_value = static_cast<bNodeSocketValueVector *>(
603 socket->default_value);
604 copy_v3_v3(rot_value->value, rot_vec.data());
605 }
606
607 bke::node_set_active(ntree, output);
609 BKE_ntree_update_main_tree(bmain, ntree, nullptr);
610}
611
612} // namespace blender::io::usd
void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
Image * BKE_image_load_exists(Main *bmain, const char *filepath, bool *r_exists=nullptr)
bool BKE_image_has_packedfile(const Image *image)
#define SH_NODE_OUTPUT_WORLD
Definition BKE_node.hh:914
#define SH_NODE_TEX_COORD
Definition BKE_node.hh:938
#define SH_NODE_VECTOR_MATH
Definition BKE_node.hh:905
#define SH_NODE_TEX_ENVIRONMENT
Definition BKE_node.hh:940
#define SH_NODE_MAPPING
Definition BKE_node.hh:900
void BKE_ntree_update_main_tree(Main *bmain, bNodeTree *ntree, NodeTreeUpdateExtraParams *params)
File and directory operations.
int BLI_copy(const char *path_src, const char *path_dst) ATTR_NONNULL()
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
Definition fileops_c.cc:391
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL()
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:433
#define LISTBASE_FOREACH(type, var, list)
#define M_PI
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
size_t BLI_path_append(char *__restrict dst, size_t dst_maxncpy, const char *__restrict file) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
size_t size_t BLI_path_append_dir(char *__restrict dst, size_t dst_maxncpy, const char *__restrict dir) ATTR_NONNULL(1
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_NTREE_OUTPUT
Definition DNA_ID.h:1122
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:647
@ NODE_VECTOR_MATH_MULTIPLY
@ SOCK_OUT
@ SOCK_IN
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
SIMD_FORCE_INLINE void mult(const btTransform &t1, const btTransform &t2)
Set the current transform as the value of the product of two transforms.
Definition btTransform.h:76
constexpr const T & first() const
Definition BLI_span.hh:316
constexpr bool is_empty() const
Definition BLI_span.hh:261
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
OperationNode * node
EvaluationStage stage
Definition deg_eval.cc:83
uint tex_coord
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define LOG(severity)
Definition log.h:33
void node_set_active(bNodeTree *ntree, bNode *node)
Definition node.cc:3896
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
Definition node.cc:2642
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
void node_chain_iterator(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *, const bool), void *userdata, bool reversed)
Definition node.cc:2501
bNodeTree * node_tree_add_tree(Main *bmain, const char *name, const char *idname)
Definition node.cc:3226
void node_remove_link(bNodeTree *ntree, bNodeLink *link)
Definition node.cc:2958
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
void world_material_to_dome_light(const USDExportParams &params, const Scene *scene, pxr::UsdStageRefPtr stage)
const char * temp_textures_dir()
static pxr::SdfPath get_unique_path(pxr::UsdStageRefPtr stage, const std::string &path)
bool should_import_asset(const std::string &path)
static Image * load_image(std::string tex_path, Main *bmain, const USDImportParams &params)
std::string import_asset(const char *src, const char *import_dir, eUSDTexNameCollisionMode name_collision_mode, ReportList *reports)
static void export_texture(const USDExporterContext &usd_export_context, bNode *node)
@ USD_TEX_IMPORT_NONE
Definition usd.hh:65
@ USD_TEX_IMPORT_PACK
Definition usd.hh:66
std::string cache_image_color(const float color[4])
static bool node_search(bNode *fromnode, bNode *, void *userdata, const bool)
eUSDTexNameCollisionMode
Definition usd.hh:74
@ USD_TEX_NAME_COLLISION_OVERWRITE
Definition usd.hh:76
static std::string get_tex_image_asset_filepath(const USDExporterContext &usd_export_context, bNode *node)
void dome_light_to_world_material(const USDImportParams &params, const ImportSettings &, Scene *scene, Main *bmain, const pxr::UsdLuxDomeLight &dome_light, const double motionSampleTime)
void ensure_usd_source_path_prop(const std::string &path, ID *id)
static bNode * append_node(bNode *dst_node, int16_t new_node_type, const char *out_sock, const char *in_sock, bNodeTree *ntree, float offset)
static const pxr::TfToken intensity("intensity", pxr::TfToken::Immortal)
static const pxr::TfToken texture_file("texture:file", pxr::TfToken::Immortal)
static const pxr::TfToken color("color", pxr::TfToken::Immortal)
signed short int16_t
Definition stdint.h:76
struct bNodeLink * link
struct bNodeSocket * next
void * default_value
ListBase nodes
int16_t custom1
float locy
float locx
int16_t type
static CLG_LogRef LOG