Blender V4.3
usd_capi_export.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
5#include <iostream>
6
8#include "usd.hh"
10#include "usd_hook.hh"
11#include "usd_light_convert.hh"
12#include "usd_private.hh"
13
14#include <pxr/base/tf/token.h>
15#include <pxr/pxr.h>
16#include <pxr/usd/sdf/assetPath.h>
17#include <pxr/usd/usd/primRange.h>
18#include <pxr/usd/usd/stage.h>
19#include <pxr/usd/usdGeom/tokens.h>
20#include <pxr/usd/usdGeom/xform.h>
21#include <pxr/usd/usdGeom/xformCommonAPI.h>
22#include <pxr/usd/usdUtils/usdzPackage.h>
23
24#include "MEM_guardedalloc.h"
25
26#include "DEG_depsgraph.hh"
29
31#include "DNA_scene_types.h"
32
33#include "BKE_appdir.hh"
34#include "BKE_blender_version.h"
35#include "BKE_context.hh"
36#include "BKE_global.hh"
37#include "BKE_image.hh"
38#include "BKE_image_save.hh"
39#include "BKE_lib_id.hh"
40#include "BKE_report.hh"
41#include "BKE_scene.hh"
42
43#include "BLI_fileops.h"
44#include "BLI_math_matrix.h"
45#include "BLI_math_rotation.h"
46#include "BLI_math_vector.h"
47#include "BLI_path_utils.hh"
48#include "BLI_string.h"
49#include "BLI_timeit.hh"
50
51#include <IMB_imbuf.hh>
52#include <IMB_imbuf_types.hh>
53
54#include "WM_api.hh"
55#include "WM_types.hh"
56
57#include "CLG_log.h"
58static CLG_LogRef LOG = {"io.usd"};
59
60namespace blender::io::usd {
61
64 Depsgraph *depsgraph;
67
72
75
76 bool targets_usdz() const
77 {
78 return usdz_filepath[0] != '\0';
79 }
80
81 const char *export_filepath() const
82 {
83 if (targets_usdz()) {
84 return usdz_filepath;
85 }
87 }
88};
89
90/* Returns true if the given prim path is valid, per
91 * the requirements of the prim path manipulation logic
92 * of the exporter. Also returns true if the path is
93 * the empty string. Returns false otherwise. */
94static bool prim_path_valid(const char *path)
95{
96 BLI_assert(path);
97
98 if (path[0] == '\0') {
99 /* Empty paths are ignored in the code,
100 * so they can be passed through. */
101 return true;
102 }
103
104 /* Check path syntax. */
105 std::string errMsg;
106 if (!pxr::SdfPath::IsValidPathString(path, &errMsg)) {
107 WM_reportf(RPT_ERROR, "USD Export: invalid path string '%s': %s", path, errMsg.c_str());
108 return false;
109 }
110
111 /* Verify that an absolute prim path can be constructed
112 * from this path string. */
113
114 pxr::SdfPath sdf_path(path);
115 if (!sdf_path.IsAbsolutePath()) {
116 WM_reportf(RPT_ERROR, "USD Export: path '%s' is not an absolute path", path);
117 return false;
118 }
119
120 if (!sdf_path.IsPrimPath()) {
121 WM_reportf(RPT_ERROR, "USD Export: path string '%s' is not a prim path", path);
122 return false;
123 }
124
125 return true;
126}
127
135{
136 bool valid = true;
137
138 if (!prim_path_valid(params.root_prim_path)) {
139 valid = false;
140 }
141
142 return valid;
143}
144
151static void ensure_root_prim(pxr::UsdStageRefPtr stage, const USDExportParams &params)
152{
153 if (params.root_prim_path[0] == '\0') {
154 return;
155 }
156
157 pxr::UsdGeomXform root_xf = pxr::UsdGeomXform::Define(stage,
158 pxr::SdfPath(params.root_prim_path));
159
160 if (!root_xf) {
161 return;
162 }
163
164 pxr::UsdGeomXformCommonAPI xf_api(root_xf.GetPrim());
165
166 if (!xf_api) {
167 return;
168 }
169
170 if (params.convert_orientation) {
171 float mrot[3][3];
172 mat3_from_axis_conversion(IO_AXIS_Y, IO_AXIS_Z, params.forward_axis, params.up_axis, mrot);
173 transpose_m3(mrot);
174
175 float eul[3];
176 mat3_to_eul(eul, mrot);
177
178 /* Convert radians to degrees. */
179 mul_v3_fl(eul, 180.0f / M_PI);
180
181 xf_api.SetRotate(pxr::GfVec3f(eul[0], eul[1], eul[2]));
182 }
183
184 for (const auto &path : pxr::SdfPath(params.root_prim_path).GetPrefixes()) {
185 auto xform = pxr::UsdGeomXform::Define(stage, path);
186 /* Tag generated prims to allow filtering on import */
187 xform.GetPrim().SetCustomDataByKey(pxr::TfToken("Blender:generated"), pxr::VtValue(true));
188 }
189}
190
191static void report_job_duration(const ExportJobData *data)
192{
193 timeit::Nanoseconds duration = timeit::Clock::now() - data->start_time;
194 const char *export_filepath = data->export_filepath();
195 std::cout << "USD export of '" << export_filepath << "' took ";
196 timeit::print_duration(duration);
197 std::cout << '\n';
198}
199
200static void process_usdz_textures(const ExportJobData *data, const char *path)
201{
202 const eUSDZTextureDownscaleSize enum_value = data->params.usdz_downscale_size;
203 if (enum_value == USD_TEXTURE_SIZE_KEEP) {
204 return;
205 }
206
207 const int image_size = (enum_value == USD_TEXTURE_SIZE_CUSTOM) ?
208 data->params.usdz_downscale_custom_size :
209 enum_value;
210
211 char texture_path[FILE_MAX];
212 STRNCPY(texture_path, path);
213 BLI_path_append(texture_path, FILE_MAX, "textures");
214 BLI_path_slash_ensure(texture_path, sizeof(texture_path));
215
216 direntry *entries;
217 uint num_files = BLI_filelist_dir_contents(texture_path, &entries);
218
219 for (int index = 0; index < num_files; index++) {
220 /* We can skip checking extensions as this folder is only created
221 * when we're doing a USDZ export. */
222 if (!BLI_is_dir(entries[index].path)) {
223 Image *im = BKE_image_load(data->bmain, entries[index].path);
224 if (!im) {
225 CLOG_WARN(&LOG, "Unable to open file for downscaling: %s", entries[index].path);
226 continue;
227 }
228
229 int width, height;
230 BKE_image_get_size(im, nullptr, &width, &height);
231 const int longest = width >= height ? width : height;
232 const float scale = 1.0 / (float(longest) / float(image_size));
233
234 if (longest > image_size) {
235 const int width_adjusted = float(width) * scale;
236 const int height_adjusted = float(height) * scale;
237 BKE_image_scale(im, width_adjusted, height_adjusted, nullptr);
238
239 ImageSaveOptions opts;
240
242 &opts, data->bmain, data->scene, im, nullptr, false, false))
243 {
244 bool result = BKE_image_save(nullptr, data->bmain, im, nullptr, &opts);
245 if (!result) {
247 "Unable to resave '%s' (new size: %dx%d)",
248 data->usdz_filepath,
249 width_adjusted,
250 height_adjusted);
251 }
252 else {
253 CLOG_INFO(&LOG,
254 2,
255 "Downscaled '%s' to %dx%d",
256 entries[index].path,
257 width_adjusted,
258 height_adjusted);
259 }
260 }
261
263 }
264
265 /* Make sure to free the image so it doesn't stick
266 * around in the library of the open file. */
267 BKE_id_free(data->bmain, (void *)im);
268 }
269 }
270
271 BLI_filelist_free(entries, num_files);
272}
273
283{
284 char usdc_temp_dir[FILE_MAX], usdc_file[FILE_MAX];
285 BLI_path_split_dir_file(data->unarchived_filepath,
286 usdc_temp_dir,
287 sizeof(usdc_temp_dir),
288 usdc_file,
289 sizeof(usdc_file));
290
291 char usdz_file[FILE_MAX];
292 BLI_path_split_file_part(data->usdz_filepath, usdz_file, FILE_MAX);
293
294 char original_working_dir_buff[FILE_MAX];
295 const char *original_working_dir = BLI_current_working_dir(original_working_dir_buff,
296 sizeof(original_working_dir_buff));
297 /* Buffer is expected to be returned by #BLI_current_working_dir, although in theory other
298 * returns are possible on some platforms, this is not handled by this code. */
299 BLI_assert(original_working_dir == original_working_dir_buff);
300
301 BLI_change_working_dir(usdc_temp_dir);
302
303 process_usdz_textures(data, usdc_temp_dir);
304
305 pxr::UsdUtilsCreateNewUsdzPackage(pxr::SdfAssetPath(usdc_file), usdz_file);
306 BLI_change_working_dir(original_working_dir);
307
308 char usdz_temp_full_path[FILE_MAX];
309 BLI_path_join(usdz_temp_full_path, FILE_MAX, usdc_temp_dir, usdz_file);
310
311 int result = 0;
312 if (BLI_exists(data->usdz_filepath)) {
313 result = BLI_delete(data->usdz_filepath, false, false);
314 if (result != 0) {
315 BKE_reportf(data->params.worker_status->reports,
316 RPT_ERROR,
317 "USD Export: Unable to delete existing usdz file %s",
318 data->usdz_filepath);
319 return false;
320 }
321 }
322 result = BLI_path_move(usdz_temp_full_path, data->usdz_filepath);
323 if (result != 0) {
324 BKE_reportf(data->params.worker_status->reports,
325 RPT_ERROR,
326 "USD Export: Couldn't move new usdz file from temporary location %s to %s",
327 usdz_temp_full_path,
328 data->usdz_filepath);
329 return false;
330 }
331
332 return true;
333}
334
336{
337 char dir_path[FILE_MAX];
338 BLI_path_join(dir_path, sizeof(dir_path), BKE_tempdir_session(), "usd", "image_cache");
339 return dir_path;
340}
341
342std::string get_image_cache_file(const std::string &file_name, bool mkdir)
343{
344 std::string dir_path = image_cache_file_path();
345 if (mkdir) {
346 BLI_dir_create_recursive(dir_path.c_str());
347 }
348
349 char file_path[FILE_MAX];
350 BLI_path_join(file_path, sizeof(file_path), dir_path.c_str(), file_name.c_str());
351 return file_path;
352}
353
354std::string cache_image_color(const float color[4])
355{
356 char name[128];
357 SNPRINTF(name,
358 "color_%02d%02d%02d.hdr",
359 int(color[0] * 255),
360 int(color[1] * 255),
361 int(color[2] * 255));
362 std::string file_path = get_image_cache_file(name);
363 if (BLI_exists(file_path.c_str())) {
364 return file_path;
365 }
366
367 ImBuf *ibuf = IMB_allocImBuf(4, 4, 32, IB_rectfloat);
368 IMB_rectfill(ibuf, color);
369 ibuf->ftype = IMB_FTYPE_RADHDR;
370
371 if (IMB_saveiff(ibuf, file_path.c_str(), IB_rectfloat)) {
372 CLOG_INFO(&LOG, 1, "%s", file_path.c_str());
373 }
374 else {
375 CLOG_ERROR(&LOG, "Can't save %s", file_path.c_str());
376 file_path = "";
377 }
378 IMB_freeImBuf(ibuf);
379
380 return file_path;
381}
382
383pxr::UsdStageRefPtr export_to_stage(const USDExportParams &params,
384 Depsgraph *depsgraph,
385 const char *filepath)
386{
387 pxr::UsdStageRefPtr usd_stage = pxr::UsdStage::CreateNew(filepath);
388 if (!usd_stage) {
389 return usd_stage;
390 }
391
392 wmJobWorkerStatus *worker_status = params.worker_status;
394 Main *bmain = DEG_get_bmain(depsgraph);
395
396 SubdivModifierDisabler mod_disabler(depsgraph);
397
398 /* If we want to set the subdiv scheme, then we need to the export the mesh
399 * without the subdiv modifier applied. */
400 if (ELEM(params.export_subdiv, USD_SUBDIV_BEST_MATCH, USD_SUBDIV_IGNORE)) {
401 mod_disabler.disable_modifiers();
403 }
404
405 /* This whole `export_to_stage` function is assumed to cover about 80% of the whole export
406 * process, from 0.1f to 0.9f. */
407 worker_status->progress = 0.10f;
408 worker_status->do_update = true;
409
410 usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit, double(scene->unit.scale_length));
411 usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender v") +
413
414 /* Set up the stage for animated data. */
415 if (params.export_animation) {
416 usd_stage->SetTimeCodesPerSecond(FPS);
417 usd_stage->SetStartTimeCode(scene->r.sfra);
418 usd_stage->SetEndTimeCode(scene->r.efra);
419 }
420
421 /* For restoring the current frame after exporting animation is done. */
422 const int orig_frame = scene->r.cfra;
423
424 /* Ensure Python types for invoking hooks are registered. */
426
427 pxr::VtValue upAxis = pxr::VtValue(pxr::UsdGeomTokens->z);
428 if (params.convert_orientation) {
429 if (params.up_axis == IO_AXIS_X)
430 upAxis = pxr::VtValue(pxr::UsdGeomTokens->x);
431 else if (params.up_axis == IO_AXIS_Y)
432 upAxis = pxr::VtValue(pxr::UsdGeomTokens->y);
433 }
434
435 usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, upAxis);
436
437 ensure_root_prim(usd_stage, params);
438
439 USDHierarchyIterator iter(bmain, depsgraph, usd_stage, params);
440
441 worker_status->progress = 0.11f;
442 worker_status->do_update = true;
443
444 if (params.export_animation) {
445 /* Writing the animated frames is not 100% of the work, here it's assumed to be 75% of it. */
446 float progress_per_frame = 0.75f / std::max(1, (scene->r.efra - scene->r.sfra + 1));
447
448 for (float frame = scene->r.sfra; frame <= scene->r.efra; frame++) {
449 if (G.is_break || worker_status->stop) {
450 break;
451 }
452
453 /* Update the scene for the next frame to render. */
454 scene->r.cfra = int(frame);
455 scene->r.subframe = frame - scene->r.cfra;
457
458 iter.set_export_frame(frame);
459 iter.iterate_and_write();
460
461 worker_status->progress += progress_per_frame;
462 worker_status->do_update = true;
463 }
464 }
465 else {
466 /* If we're not animating, a single iteration over all objects is enough. */
467 iter.iterate_and_write();
468 }
469
470 worker_status->progress = 0.86f;
471 worker_status->do_update = true;
472
473 iter.release_writers();
474
475 if (params.export_shapekeys || params.export_armatures) {
476 iter.process_usd_skel();
477 }
478
479 /* Creating dome lights should be called after writers have
480 * completed, to avoid a name collision when creating the light
481 * prim. */
482 if (params.convert_world_material) {
483 world_material_to_dome_light(params, scene, usd_stage);
484 }
485
486 /* Set the default prim if it doesn't exist */
487 if (!usd_stage->GetDefaultPrim()) {
488 /* Use TraverseAll since it's guaranteed to be depth first and will get the first top level
489 * prim, and is less verbose than getting the PseudoRoot + iterating its children. */
490 for (auto prim : usd_stage->TraverseAll()) {
491 usd_stage->SetDefaultPrim(prim);
492 break;
493 }
494 }
495
496 call_export_hooks(usd_stage, depsgraph, params.worker_status->reports);
497
498 worker_status->progress = 0.88f;
499 worker_status->do_update = true;
500
501 /* Finish up by going back to the keyframe that was current before we started. */
502 if (scene->r.cfra != orig_frame) {
503 scene->r.cfra = orig_frame;
505 }
506
507 worker_status->progress = 0.9f;
508 worker_status->do_update = true;
509
510 return usd_stage;
511}
512
513static void export_startjob(void *customdata, wmJobWorkerStatus *worker_status)
514{
515 ExportJobData *data = static_cast<ExportJobData *>(customdata);
516 data->export_ok = false;
517 data->start_time = timeit::Clock::now();
518
519 G.is_rendering = true;
520 if (data->wm) {
521 WM_set_locked_interface(data->wm, true);
522 }
523 G.is_break = false;
524
525 worker_status->progress = 0.01f;
526 worker_status->do_update = true;
527
528 /* Evaluate the depsgraph for exporting.
529 *
530 * Note that, unlike with its building, this is expected to be safe to perform from worker
531 * thread, since UI is locked during export, so there should not be any more changes in the Main
532 * original data concurrently done from the main thread at this point. All necessary (deferred)
533 * changes are expected to have been triggered and processed during depsgraph building in
534 * #USD_export. */
535 BKE_scene_graph_update_tagged(data->depsgraph, data->bmain);
536
537 worker_status->progress = 0.1f;
538 worker_status->do_update = true;
539 data->params.worker_status = worker_status;
540
541 pxr::UsdStageRefPtr usd_stage = export_to_stage(
542 data->params, data->depsgraph, data->unarchived_filepath);
543 if (!usd_stage) {
544 /* This happens when the USD JSON files cannot be found. When that happens,
545 * the USD library doesn't know it has the functionality to write USDA and
546 * USDC files, and creating a new UsdStage fails. */
547 BKE_reportf(worker_status->reports,
548 RPT_ERROR,
549 "USD Export: unable to find suitable USD plugin to write %s",
550 data->unarchived_filepath);
551 return;
552 }
553
554 usd_stage->GetRootLayer()->Save();
555
556 data->export_ok = true;
557 worker_status->progress = 1.0f;
558 worker_status->do_update = true;
559}
560
562{
563 if (!BLI_exists(data->unarchived_filepath)) {
564 return;
565 }
566
567 char dir[FILE_MAX];
568 BLI_path_split_dir_part(data->unarchived_filepath, dir, FILE_MAX);
569
570 char usdc_temp_dir[FILE_MAX];
571 BLI_path_join(usdc_temp_dir, FILE_MAX, BKE_tempdir_session(), "USDZ", SEP_STR);
572
573 BLI_assert_msg(BLI_strcasecmp(dir, usdc_temp_dir) == 0,
574 "USD Export: Attempting to delete directory that doesn't match the expected "
575 "temporary directory for usdz export.");
576 BLI_delete(usdc_temp_dir, true, true);
577}
578
579static void export_endjob(void *customdata)
580{
581 ExportJobData *data = static_cast<ExportJobData *>(customdata);
582
583 DEG_graph_free(data->depsgraph);
584
585 if (data->targets_usdz()) {
586 /* NOTE: call to #perform_usdz_conversion has to be done here instead of the main threaded
587 * worker callback (#export_startjob) because USDZ conversion requires changing the current
588 * working directory. This is not safe to do from a non-main thread. Once the USD library fix
589 * this weird requirement, this call can be moved back at the end of #export_startjob, and not
590 * block the main user interface anymore. */
591 bool usd_conversion_success = perform_usdz_conversion(data);
592 if (!usd_conversion_success) {
593 data->export_ok = false;
594 }
595
597 }
598
599 if (!data->export_ok && BLI_exists(data->unarchived_filepath)) {
600 BLI_delete(data->unarchived_filepath, false, false);
601 }
602
603 G.is_rendering = false;
604 if (data->wm) {
605 WM_set_locked_interface(data->wm, false);
606 }
608}
609
615static void create_temp_path_for_usdz_export(const char *filepath,
617{
618 char usdc_file[FILE_MAX];
619 STRNCPY(usdc_file, BLI_path_basename(filepath));
620
621 if (BLI_path_extension_check(usdc_file, ".usdz")) {
622 BLI_path_extension_replace(usdc_file, sizeof(usdc_file), ".usdc");
623 }
624
625 char usdc_temp_filepath[FILE_MAX];
626 BLI_path_join(usdc_temp_filepath, FILE_MAX, BKE_tempdir_session(), "USDZ", usdc_file);
627
628 STRNCPY(job->unarchived_filepath, usdc_temp_filepath);
629 STRNCPY(job->usdz_filepath, filepath);
630}
631
632static void set_job_filepath(blender::io::usd::ExportJobData *job, const char *filepath)
633{
634 if (BLI_path_extension_check_n(filepath, ".usdz", nullptr)) {
636 return;
637 }
638
639 STRNCPY(job->unarchived_filepath, filepath);
640 job->usdz_filepath[0] = '\0';
641}
642
643bool USD_export(const bContext *C,
644 const char *filepath,
645 const USDExportParams *params,
646 bool as_background_job,
647 ReportList *reports)
648{
650 return false;
651 }
652
653 ViewLayer *view_layer = CTX_data_view_layer(C);
654 Scene *scene = CTX_data_scene(C);
655
657 MEM_mallocN(sizeof(blender::io::usd::ExportJobData), "ExportJobData"));
658
659 job->bmain = CTX_data_main(C);
660 job->wm = CTX_wm_manager(C);
661 job->scene = scene;
662 job->export_ok = false;
663 set_job_filepath(job, filepath);
664
665 job->depsgraph = DEG_graph_new(job->bmain, scene, view_layer, params->evaluation_mode);
666 job->params = *params;
667
668 /* Construct the depsgraph for exporting.
669 *
670 * Has to be done from main thread currently, as it may affect Main original data (e.g. when
671 * doing deferred update of the view-layers, see #112534 for details). */
672 if (job->params.collection[0]) {
673 Collection *collection = reinterpret_cast<Collection *>(
675 if (!collection) {
677 RPT_ERROR,
678 "USD Export: Unable to find collection '%s'",
679 job->params.collection);
680 return false;
681 }
682
684 }
685 else if (job->params.visible_objects_only) {
687 }
688 else {
690 }
691
692 bool export_ok = false;
693 if (as_background_job) {
694 wmJob *wm_job = WM_jobs_get(
695 job->wm, CTX_wm_window(C), scene, "USD Export", WM_JOB_PROGRESS, WM_JOB_TYPE_USD_EXPORT);
696
697 /* setup job */
698 WM_jobs_customdata_set(wm_job, job, MEM_freeN);
700 WM_jobs_callbacks(wm_job,
702 nullptr,
703 nullptr,
705
706 WM_jobs_start(CTX_wm_manager(C), wm_job);
707 }
708 else {
709 wmJobWorkerStatus worker_status = {};
710 /* Use the operator's reports in non-background case. */
711 worker_status.reports = reports;
712
713 blender::io::usd::export_startjob(job, &worker_status);
715 export_ok = job->export_ok;
716
717 MEM_freeN(job);
718 }
719
720 return export_ok;
721}
722
724{
725 /* USD 19.11 defines:
726 *
727 * #define PXR_MAJOR_VERSION 0
728 * #define PXR_MINOR_VERSION 19
729 * #define PXR_PATCH_VERSION 11
730 * #define PXR_VERSION 1911
731 *
732 * So the major version is implicit/invisible in the public version number.
733 */
734 return PXR_VERSION;
735}
736
737} // namespace blender::io::usd
const char * BKE_blender_version_string(void)
Definition blender.cc:139
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
Image * BKE_image_load(Main *bmain, const char *filepath)
bool BKE_image_scale(Image *image, int width, int height, ImageUser *iuser)
void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_height)
bool BKE_image_save(ReportList *reports, Main *bmain, Image *ima, ImageUser *iuser, const ImageSaveOptions *opts)
bool BKE_image_save_options_init(ImageSaveOptions *opts, Main *bmain, Scene *scene, Image *ima, ImageUser *iuser, const bool guess_path, const bool save_as_render)
Definition image_save.cc:82
void BKE_image_save_options_free(ImageSaveOptions *opts)
ID * BKE_libblock_find_name(Main *bmain, short type, const char *name, const std::optional< Library * > lib=std::nullopt) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition lib_id.cc:1657
void BKE_id_free(Main *bmain, void *idv)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2568
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2647
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
File and directory operations.
bool BLI_change_working_dir(const char *dir)
Definition storage.cc:63
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:350
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
Definition fileops_c.cc:391
unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist)
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
void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries)
char * BLI_current_working_dir(char *dir, size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:85
int BLI_path_move(const char *path_src, const char *path_dst) ATTR_NONNULL()
#define M_PI
void transpose_m3(float R[3][3])
void mat3_to_eul(float eul[3], const float mat[3][3])
bool mat3_from_axis_conversion(int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3])
MINLINE void mul_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
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
bool BLI_path_extension_replace(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
#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 BLI_path_split_dir_file(const char *filepath, char *dir, size_t dir_maxncpy, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool BLI_path_extension_check(const char *path, const char *ext) ATTR_NONNULL(1
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
bool BLI_path_extension_check_n(const char *path,...) ATTR_NONNULL(1) ATTR_SENTINEL(0)
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
unsigned int uint
#define ELEM(...)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:273
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:301
void DEG_graph_build_from_collection(Depsgraph *graph, Collection *collection)
void DEG_graph_build_for_all_objects(Depsgraph *graph)
void DEG_graph_build_from_view_layer(Depsgraph *graph)
Main * DEG_get_bmain(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
@ ID_GR
Object groups, one object can be in many groups at once.
#define FPS
void IMB_rectfill(ImBuf *drect, const float col[4])
Definition rectop.cc:1051
@ IMB_FTYPE_RADHDR
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
@ IO_AXIS_Y
@ IO_AXIS_Z
@ IO_AXIS_X
Read Guarded memory(de)allocation.
@ WM_JOB_TYPE_USD_EXPORT
Definition WM_api.hh:1599
@ WM_JOB_PROGRESS
Definition WM_api.hh:1566
#define NC_SCENE
Definition WM_types.hh:345
#define ND_FRAME
Definition WM_types.hh:401
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
EvaluationStage stage
Definition deg_eval.cc:83
const Depsgraph * depsgraph
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
bool IMB_saveiff(struct ImBuf *, const char *, int)
void IMB_freeImBuf(ImBuf *)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define LOG(severity)
Definition log.h:33
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define G(x, y, z)
std::string image_cache_file_path()
void world_material_to_dome_light(const USDExportParams &params, const Scene *scene, pxr::UsdStageRefPtr stage)
static void set_job_filepath(blender::io::usd::ExportJobData *job, const char *filepath)
static bool perform_usdz_conversion(const ExportJobData *data)
std::string cache_image_color(const float color[4])
static void report_job_duration(const ExportJobData *data)
static bool prim_path_valid(const char *path)
std::string get_image_cache_file(const std::string &file_name, bool mkdir)
static bool export_params_valid(const USDExportParams &params)
static void export_endjob_usdz_cleanup(const ExportJobData *data)
@ USD_SUBDIV_BEST_MATCH
Definition usd.hh:88
@ USD_SUBDIV_IGNORE
Definition usd.hh:81
bool USD_export(const bContext *C, const char *filepath, const USDExportParams *params, bool as_background_job, ReportList *reports)
static void ensure_root_prim(pxr::UsdStageRefPtr stage, const USDExportParams &params)
pxr::UsdStageRefPtr export_to_stage(const USDExportParams &params, Depsgraph *depsgraph, const char *filepath)
void call_export_hooks(pxr::UsdStageRefPtr stage, Depsgraph *depsgraph, ReportList *reports)
Definition usd_hook.cc:333
static void export_startjob(void *customdata, wmJobWorkerStatus *worker_status)
static void create_temp_path_for_usdz_export(const char *filepath, blender::io::usd::ExportJobData *job)
eUSDZTextureDownscaleSize
Definition usd.hh:97
@ USD_TEXTURE_SIZE_CUSTOM
Definition usd.hh:98
@ USD_TEXTURE_SIZE_KEEP
Definition usd.hh:99
static void process_usdz_textures(const ExportJobData *data, const char *path)
static void export_endjob(void *customdata)
void register_hook_converters()
Definition usd_hook.cc:137
std::chrono::nanoseconds Nanoseconds
Definition BLI_timeit.hh:16
Clock::time_point TimePoint
Definition BLI_timeit.hh:15
void print_duration(Nanoseconds duration)
Definition timeit.cc:42
enum eImbFileType ftype
const char * export_filepath() const
char collection[MAX_IDPROP_NAME]
Definition usd.hh:168
wmJobWorkerStatus * worker_status
Definition usd.hh:173
const char * path
ReportList * reports
Definition WM_types.hh:985
void * BKE_tempdir_session
Definition stubs.c:38
#define SEP_STR
Definition unit.cc:39
static CLG_LogRef LOG
void WM_reportf(eReportType type, const char *format,...)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:352
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:455
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:189
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:364
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:336