45 const ufbx_scene &
fbx;
57 ufbx_transform root_tr;
58 root_tr.translation = ufbx_zero_vec3;
59 root_tr.rotation = this->fbx.metadata.root_rotation;
60 root_tr.scale.x = root_tr.scale.y = root_tr.scale.z = this->fbx.metadata.root_scale;
64 std::string debug_file_path =
params.filepath;
65 debug_file_path = debug_file_path.substr(0, debug_file_path.size() - 4) +
"-dbg-b.txt";
66 g_debug_file =
BLI_fopen(debug_file_path.c_str(),
"wb");
94 double fps = this->
fbx.settings.frames_per_second;
101 for (
const ufbx_material *fmat : this->
fbx.materials) {
108 if (mat ==
nullptr) {
110 if (this->
params.use_custom_props) {
114 this->
mapping.mat_to_material.add(fmat, mat);
126 const ufbx_node *node = camera->instances[0];
129 if (node->node_depth == 1 && node->children.count == 0 &&
130 STREQ(
"MotionBuilder",
fbx.metadata.original_application.name.data))
132 if (
STREQ(node->name.data, camera->name.data)) {
133 if (
STREQ(
"Producer Perspective", node->name.data) ||
134 STREQ(
"Producer Front", node->name.data) ||
STREQ(
"Producer Back", node->name.data) ||
135 STREQ(
"Producer Right", node->name.data) ||
STREQ(
"Producer Left", node->name.data) ||
136 STREQ(
"Producer Top", node->name.data) ||
STREQ(
"Producer Bottom", node->name.data))
147 for (
const ufbx_camera *fcam : this->
fbx.cameras) {
148 if (fcam->instances.count == 0) {
154 const ufbx_node *node = fcam->instances[0];
157 if (this->
params.use_custom_props) {
161 bcam->
type = fcam->projection_mode == UFBX_PROJECTION_MODE_ORTHOGRAPHIC ?
CAM_ORTHO :
163 bcam->
dof.
focus_distance = ufbx_find_real(&fcam->props,
"FocusDistance", 10.0f) *
164 this->
fbx.metadata.geometry_scale * this->
fbx.metadata.root_scale;
165 if (ufbx_find_bool(&fcam->props,
"UseDepthOfField",
false)) {
168 bcam->
lens = fcam->focal_length_mm;
169 constexpr double m_to_in = 0.0393700787;
170 bcam->
sensor_x = fcam->film_size_inch.x / m_to_in;
171 bcam->
sensor_y = fcam->film_size_inch.y / m_to_in;
175 bcam->
ortho_scale = ufbx_find_real(&fcam->props,
"OrthoZoom", 1.0);
177 bcam->
shiftx = ufbx_find_real(&fcam->props,
"FilmOffsetX", 0.0) / (m_to_in * bcam->
sensor_x);
178 bcam->
shifty = ufbx_find_real(&fcam->props,
"FilmOffsetY", 0.0) / (m_to_in * bcam->
sensor_x);
179 bcam->
clip_start = fcam->near_plane * this->
fbx.metadata.root_scale;
180 bcam->
clip_end = fcam->far_plane * this->
fbx.metadata.root_scale;
184 if (!node->visible) {
187 if (this->
params.use_custom_props) {
191 this->
mapping.el_to_object.add(&node->element,
obj);
198 for (
const ufbx_light *flight : this->
fbx.lights) {
199 if (flight->instances.count == 0) {
202 const ufbx_node *node = flight->instances[0];
205 if (this->
params.use_custom_props) {
208 switch (flight->type) {
209 case UFBX_LIGHT_POINT:
212 case UFBX_LIGHT_DIRECTIONAL:
215 case UFBX_LIGHT_SPOT:
218 lamp->
spotblend = 1.0f - flight->inner_angle / flight->outer_angle;
224 lamp->
r = flight->color.x;
225 lamp->
g = flight->color.y;
226 lamp->
b = flight->color.z;
227 lamp->
energy = flight->intensity;
228 lamp->
exposure = ufbx_find_real(&flight->props,
"Exposure", 0.0);
229 if (flight->cast_shadows) {
236 if (!node->visible) {
240 if (this->
params.use_custom_props) {
244 this->
mapping.el_to_object.add(&node->element,
obj);
257 for (
const ufbx_node *node : this->
fbx.nodes) {
259 if (node->is_root || this->mapping.node_is_blender_bone.contains(node) ||
260 this->mapping.el_to_object.contains(&node->element))
266 if (
ELEM(node->attrib_type, UFBX_ELEMENT_CAMERA, UFBX_ELEMENT_CAMERA_SWITCHER) &&
267 node->node_depth == 1 && node->children.count == 0)
273 if (!node->visible) {
276 if (this->
params.use_custom_props) {
280 this->
mapping.el_to_object.add(&node->element,
obj);
287 if (this->
params.use_anim) {
295 for (
const auto &item : this->
mapping.el_to_object.items()) {
296 if (item.value->parent !=
nullptr) {
299 const ufbx_node *node = ufbx_as_node(item.key);
300 if (node ==
nullptr) {
304 Object *obj_par = this->
mapping.el_to_object.lookup_default(&node->parent->element,
nullptr);
305 if (!
ELEM(obj_par,
nullptr, item.value)) {
306 item.value->parent = obj_par;
313 ufbx_thread_pool_context ctx,
315 uint32_t start_index,
319 ufbx_thread_pool_run_task(ctx, index);
324 ufbx_thread_pool_context ,
341 ufbx_load_opts opts = {};
342 opts.filename.data =
params.filepath;
343 opts.filename.length = strlen(
params.filepath);
344 opts.evaluate_skinning =
false;
345 opts.evaluate_caches =
false;
346 opts.load_external_files =
false;
347 opts.clean_skin_weights =
true;
348 opts.use_blender_pbr_material =
true;
350 opts.geometry_transform_handling = UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY;
351 opts.pivot_handling = UFBX_PIVOT_HANDLING_ADJUST_TO_ROTATION_PIVOT;
353 opts.space_conversion = UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS;
354 opts.target_axes.right = UFBX_COORDINATE_AXIS_POSITIVE_X;
355 opts.target_axes.up = UFBX_COORDINATE_AXIS_POSITIVE_Z;
356 opts.target_axes.front = UFBX_COORDINATE_AXIS_NEGATIVE_Y;
357 opts.target_unit_meters = 1.0f /
params.global_scale;
359 opts.target_camera_axes.right = UFBX_COORDINATE_AXIS_POSITIVE_X;
360 opts.target_camera_axes.up = UFBX_COORDINATE_AXIS_POSITIVE_Y;
361 opts.target_camera_axes.front = UFBX_COORDINATE_AXIS_POSITIVE_Z;
362 opts.target_light_axes.right = UFBX_COORDINATE_AXIS_POSITIVE_X;
363 opts.target_light_axes.up = UFBX_COORDINATE_AXIS_POSITIVE_Y;
364 opts.target_light_axes.front = UFBX_COORDINATE_AXIS_POSITIVE_Z;
370 ufbx_error fbx_error;
371 ufbx_scene *
fbx = ufbx_load_stdio(file, &opts, &fbx_error);
376 "Failed to import FBX file '%s': '%s'\n",
378 fbx_error.description.data);
381 "FBX Import: Cannot import file '%s': '%s'",
383 fbx_error.description.data);
393#ifdef FBX_DEBUG_PRINT
395 fprintf(g_debug_file,
"Initial NODE local matrices:\n");
397 for (
const ufbx_node *node : ctx.
fbx.nodes) {
403 std::sort(
nodes.begin(),
nodes.end(), [](
const ufbx_node *a,
const ufbx_node *
b) {
404 int ncmp = strcmp(a->name.data, b->name.data);
408 return a->attrib_type >
b->attrib_type;
410 for (
const ufbx_node *node :
nodes) {
411 ufbx_matrix mtx = ufbx_matrix_mul(node->node_depth < 2 ? &node->node_to_world :
412 &node->node_to_parent,
413 &node->geometry_to_node);
414 fprintf(g_debug_file,
"init NODE %s self.matrix:\n", node->name.data);
417 fprintf(g_debug_file,
"\n");
421 ctx.import_materials();
422 ctx.import_armatures();
424 ctx.import_cameras();
426 ctx.import_empties();
427 ctx.import_animation(scene->frames_per_second());
428 ctx.setup_hierarchy();
430 ufbx_free_scene(
fbx);
433 for (
Object *
obj : ctx.mapping.imported_objects) {
440 for (
Object *obj : ctx.mapping.imported_objects) {
Camera data-block and utility functions.
struct Camera * BKE_camera_add(struct Main *bmain, const char *name)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
LayerCollection * BKE_layer_collection_get_active(ViewLayer *view_layer)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_view_layer_base_deselect_all(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
void BKE_view_layer_base_select_and_set_active(ViewLayer *view_layer, Base *selbase)
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()
General operations, lookup, etc. for blender lights.
Light * BKE_light_add(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
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
#define CLOG_ERROR(clg_ref,...)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
Object groups, one object can be in many groups at once.
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
static void fbx_task_run_fn(void *, ufbx_thread_pool_context ctx, uint32_t, uint32_t start_index, uint32_t count)
const char * get_fbx_name(const ufbx_string &name, const char *def)
static bool should_import_camera(const ufbx_scene &fbx, const ufbx_camera *camera)
void read_custom_properties(const ufbx_props &props, ID &id, bool enums_as_strings)
void node_matrix_to_obj(const ufbx_node *node, Object *obj, const FbxElementMapping &mapping)
Material * import_material(Main *bmain, const std::string &base_dir, const ufbx_material &fmat)
void importer_main(Main *bmain, Scene *scene, ViewLayer *view_layer, const FBXImportParams ¶ms)
void import_animations(Main &bmain, const ufbx_scene &fbx, const FbxElementMapping &mapping, const double fps, const float anim_offset)
static void fbx_task_wait_fn(void *, ufbx_thread_pool_context, uint32_t, uint32_t)
void import_armatures(Main &bmain, const ufbx_scene &fbx, FbxElementMapping &mapping, const FBXImportParams ¶ms)
void import_meshes(Main &bmain, const ufbx_scene &fbx, FbxElementMapping &mapping, const FBXImportParams ¶ms)
void parallel_for_each(Range &&range, const Function &function)
struct CameraDOFSettings dof
ufbx_matrix global_conv_matrix
FbxImportContext(Main *main, const ufbx_scene *fbx, const FBXImportParams ¶ms)
FbxElementMapping mapping
void import_globals(Scene *scene) const
void import_animation(double fps)
const FBXImportParams & params