14#include <pxr/base/tf/token.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>
98 if (path[0] ==
'\0') {
106 if (!pxr::SdfPath::IsValidPathString(path, &errMsg)) {
114 pxr::SdfPath sdf_path(path);
115 if (!sdf_path.IsAbsolutePath()) {
120 if (!sdf_path.IsPrimPath()) {
153 if (
params.root_prim_path[0] ==
'\0') {
157 pxr::UsdGeomXform root_xf = pxr::UsdGeomXform::Define(
stage,
158 pxr::SdfPath(
params.root_prim_path));
164 pxr::UsdGeomXformCommonAPI xf_api(root_xf.GetPrim());
170 if (
params.convert_orientation) {
181 xf_api.SetRotate(pxr::GfVec3f(eul[0], eul[1], eul[2]));
184 for (
const auto &path : pxr::SdfPath(
params.root_prim_path).GetPrefixes()) {
185 auto xform = pxr::UsdGeomXform::Define(
stage, path);
187 xform.GetPrim().SetCustomDataByKey(pxr::TfToken(
"Blender:generated"), pxr::VtValue(
true));
194 const char *export_filepath = data->export_filepath();
195 std::cout <<
"USD export of '" << export_filepath <<
"' took ";
208 data->params.usdz_downscale_custom_size :
219 for (
int index = 0; index < num_files; index++) {
225 CLOG_WARN(&
LOG,
"Unable to open file for downscaling: %s", entries[index].path);
231 const int longest = width >= height ? width : height;
232 const float scale = 1.0 / (
float(longest) /
float(image_size));
234 if (longest > image_size) {
235 const int width_adjusted =
float(width) * scale;
236 const int height_adjusted =
float(height) * scale;
242 &opts, data->
bmain, data->scene, im,
nullptr,
false,
false))
244 bool result =
BKE_image_save(
nullptr, data->bmain, im,
nullptr, &opts);
247 "Unable to resave '%s' (new size: %dx%d)",
255 "Downscaled '%s' to %dx%d",
287 sizeof(usdc_temp_dir),
294 char original_working_dir_buff[
FILE_MAX];
296 sizeof(original_working_dir_buff));
299 BLI_assert(original_working_dir == original_working_dir_buff);
305 pxr::UsdUtilsCreateNewUsdzPackage(pxr::SdfAssetPath(usdc_file), usdz_file);
313 result =
BLI_delete(data->usdz_filepath,
false,
false);
317 "USD Export: Unable to delete existing usdz file %s",
318 data->usdz_filepath);
322 result =
BLI_path_move(usdz_temp_full_path, data->usdz_filepath);
326 "USD Export: Couldn't move new usdz file from temporary location %s to %s",
328 data->usdz_filepath);
350 BLI_path_join(file_path,
sizeof(file_path), dir_path.c_str(), file_name.c_str());
358 "color_%02d%02d%02d.hdr",
361 int(color[2] * 255));
385 const char *filepath)
387 pxr::UsdStageRefPtr usd_stage = pxr::UsdStage::CreateNew(filepath);
410 usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit,
double(scene->unit.scale_length));
411 usd_stage->GetRootLayer()->SetDocumentation(std::string(
"Blender v") +
415 if (
params.export_animation) {
416 usd_stage->SetTimeCodesPerSecond(
FPS);
417 usd_stage->SetStartTimeCode(scene->r.sfra);
418 usd_stage->SetEndTimeCode(scene->r.efra);
422 const int orig_frame = scene->r.cfra;
427 pxr::VtValue upAxis = pxr::VtValue(pxr::UsdGeomTokens->
z);
428 if (
params.convert_orientation) {
430 upAxis = pxr::VtValue(pxr::UsdGeomTokens->x);
432 upAxis = pxr::VtValue(pxr::UsdGeomTokens->y);
435 usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, upAxis);
444 if (
params.export_animation) {
446 float progress_per_frame = 0.75f / std::max(1, (scene->r.efra - scene->r.sfra + 1));
448 for (
float frame = scene->r.sfra; frame <= scene->r.efra; frame++) {
449 if (
G.is_break || worker_status->
stop) {
454 scene->r.cfra =
int(frame);
455 scene->r.subframe = frame - scene->r.cfra;
461 worker_status->
progress += progress_per_frame;
475 if (
params.export_shapekeys ||
params.export_armatures) {
482 if (
params.convert_world_material) {
487 if (!usd_stage->GetDefaultPrim()) {
490 for (
auto prim : usd_stage->TraverseAll()) {
491 usd_stage->SetDefaultPrim(prim);
502 if (scene->r.cfra != orig_frame) {
503 scene->r.cfra = orig_frame;
517 data->start_time = timeit::Clock::now();
519 G.is_rendering =
true;
539 data->params.worker_status = worker_status;
542 data->params, data->depsgraph, data->unarchived_filepath);
549 "USD Export: unable to find suitable USD plugin to write %s",
550 data->unarchived_filepath);
554 usd_stage->GetRootLayer()->Save();
556 data->export_ok =
true;
574 "USD Export: Attempting to delete directory that doesn't match the expected "
575 "temporary directory for usdz export.");
585 if (data->targets_usdz()) {
592 if (!usd_conversion_success) {
593 data->export_ok =
false;
599 if (!data->export_ok &&
BLI_exists(data->unarchived_filepath)) {
600 BLI_delete(data->unarchived_filepath,
false,
false);
603 G.is_rendering =
false;
644 const char *filepath,
646 bool as_background_job,
678 "USD Export: Unable to find collection '%s'",
692 bool export_ok =
false;
693 if (as_background_job) {
711 worker_status.
reports = reports;
const char * BKE_blender_version_string(void)
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)
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()
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)
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
#define BLI_assert_msg(a, msg)
File and directory operations.
bool BLI_change_working_dir(const char *dir)
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
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()
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()
int BLI_path_move(const char *path_src, const char *path_dst) ATTR_NONNULL()
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
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)
#define SNPRINTF(dst, format,...)
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
#define CLOG_ERROR(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
#define CLOG_INFO(clg_ref, level,...)
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
void DEG_graph_free(Depsgraph *graph)
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)
Object groups, one object can be in many groups at once.
void IMB_rectfill(ImBuf *drect, const float col[4])
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
virtual void iterate_and_write()
void process_usd_skel() const
void set_export_frame(float frame_nr)
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 *)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
std::string image_cache_file_path()
void world_material_to_dome_light(const USDExportParams ¶ms, 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 ¶ms)
static void export_endjob_usdz_cleanup(const ExportJobData *data)
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 ¶ms)
pxr::UsdStageRefPtr export_to_stage(const USDExportParams ¶ms, Depsgraph *depsgraph, const char *filepath)
void call_export_hooks(pxr::UsdStageRefPtr stage, Depsgraph *depsgraph, ReportList *reports)
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
@ USD_TEXTURE_SIZE_CUSTOM
static void process_usdz_textures(const ExportJobData *data, const char *path)
static void export_endjob(void *customdata)
void register_hook_converters()
std::chrono::nanoseconds Nanoseconds
Clock::time_point TimePoint
void print_duration(Nanoseconds duration)
bool targets_usdz() const
const char * export_filepath() const
char usdz_filepath[FILE_MAX]
char unarchived_filepath[FILE_MAX]
timeit::TimePoint start_time
char collection[MAX_IDPROP_NAME]
bool visible_objects_only
wmJobWorkerStatus * worker_status
void * BKE_tempdir_session
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)
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))