44 const ufbx_scene &
fbx;
56 ufbx_transform root_tr;
57 root_tr.translation = ufbx_zero_vec3;
58 root_tr.rotation = this->fbx.metadata.root_rotation;
59 root_tr.scale.x = root_tr.scale.y = root_tr.scale.z = this->fbx.metadata.root_scale;
63 std::string debug_file_path =
params.filepath;
64 debug_file_path = debug_file_path.substr(0, debug_file_path.size() - 4) +
"-dbg-b.txt";
65 g_debug_file =
BLI_fopen(debug_file_path.c_str(),
"wb");
93 double fps = this->
fbx.settings.frames_per_second;
100 for (
const ufbx_material *fmat : this->
fbx.materials) {
102 if (this->
params.use_custom_props) {
105 this->
mapping.mat_to_material.add(fmat, mat);
117 const ufbx_node *node = camera->instances[0];
120 if (node->node_depth == 1 && node->children.count == 0 &&
121 STREQ(
"MotionBuilder",
fbx.metadata.original_application.name.data))
123 if (
STREQ(node->name.data, camera->name.data)) {
124 if (
STREQ(
"Producer Perspective", node->name.data) ||
125 STREQ(
"Producer Front", node->name.data) ||
STREQ(
"Producer Back", node->name.data) ||
126 STREQ(
"Producer Right", node->name.data) ||
STREQ(
"Producer Left", node->name.data) ||
127 STREQ(
"Producer Top", node->name.data) ||
STREQ(
"Producer Bottom", node->name.data))
138 for (
const ufbx_camera *fcam : this->
fbx.cameras) {
139 if (fcam->instances.count == 0) {
145 const ufbx_node *node = fcam->instances[0];
148 if (this->
params.use_custom_props) {
152 bcam->
type = fcam->projection_mode == UFBX_PROJECTION_MODE_ORTHOGRAPHIC ?
CAM_ORTHO :
154 bcam->
dof.
focus_distance = ufbx_find_real(&fcam->props,
"FocusDistance", 10.0f) *
155 this->
fbx.metadata.geometry_scale * this->
fbx.metadata.root_scale;
156 if (ufbx_find_bool(&fcam->props,
"UseDepthOfField",
false)) {
159 bcam->
lens = fcam->focal_length_mm;
160 constexpr double m_to_in = 0.0393700787;
161 bcam->
sensor_x = fcam->film_size_inch.x / m_to_in;
162 bcam->
sensor_y = fcam->film_size_inch.y / m_to_in;
166 bcam->
ortho_scale = ufbx_find_real(&fcam->props,
"OrthoZoom", 1.0);
168 bcam->
shiftx = ufbx_find_real(&fcam->props,
"FilmOffsetX", 0.0) / (m_to_in * bcam->
sensor_x);
169 bcam->
shifty = ufbx_find_real(&fcam->props,
"FilmOffsetY", 0.0) / (m_to_in * bcam->
sensor_x);
170 bcam->
clip_start = fcam->near_plane * this->
fbx.metadata.root_scale;
171 bcam->
clip_end = fcam->far_plane * this->
fbx.metadata.root_scale;
175 if (!node->visible) {
178 if (this->
params.use_custom_props) {
182 this->
mapping.el_to_object.add(&node->element,
obj);
189 for (
const ufbx_light *flight : this->
fbx.lights) {
190 if (flight->instances.count == 0) {
193 const ufbx_node *node = flight->instances[0];
196 if (this->
params.use_custom_props) {
199 switch (flight->type) {
200 case UFBX_LIGHT_POINT:
203 case UFBX_LIGHT_DIRECTIONAL:
206 case UFBX_LIGHT_SPOT:
209 lamp->
spotblend = 1.0f - flight->inner_angle / flight->outer_angle;
215 lamp->
r = flight->color.x;
216 lamp->
g = flight->color.y;
217 lamp->
b = flight->color.z;
218 lamp->
energy = flight->intensity;
219 lamp->
exposure = ufbx_find_real(&flight->props,
"Exposure", 0.0);
220 if (flight->cast_shadows) {
227 if (!node->visible) {
231 if (this->
params.use_custom_props) {
235 this->
mapping.el_to_object.add(&node->element,
obj);
248 for (
const ufbx_node *node : this->
fbx.nodes) {
250 if (node->is_root ||
this->mapping.node_is_blender_bone.contains(node) ||
251 this->mapping.el_to_object.contains(&node->element))
257 if (
ELEM(node->attrib_type, UFBX_ELEMENT_CAMERA, UFBX_ELEMENT_CAMERA_SWITCHER) &&
258 node->node_depth == 1 && node->children.count == 0)
264 if (!node->visible) {
267 if (this->
params.use_custom_props) {
271 this->
mapping.el_to_object.add(&node->element,
obj);
278 if (this->
params.use_anim) {
286 for (
const auto &item : this->
mapping.el_to_object.items()) {
287 if (item.value->parent !=
nullptr) {
290 const ufbx_node *node = ufbx_as_node(item.key);
291 if (node ==
nullptr) {
295 Object *obj_par = this->
mapping.el_to_object.lookup_default(&node->parent->element,
nullptr);
296 if (!
ELEM(obj_par,
nullptr, item.value)) {
297 item.value->parent = obj_par;
304 ufbx_thread_pool_context ctx,
306 uint32_t start_index,
310 ufbx_thread_pool_run_task(ctx, index);
315 ufbx_thread_pool_context ,
332 ufbx_load_opts opts = {};
333 opts.filename.data =
params.filepath;
334 opts.filename.length = strlen(
params.filepath);
335 opts.evaluate_skinning =
false;
336 opts.evaluate_caches =
false;
337 opts.load_external_files =
false;
338 opts.clean_skin_weights =
true;
339 opts.use_blender_pbr_material =
true;
341 opts.geometry_transform_handling = UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY;
342 opts.pivot_handling = UFBX_PIVOT_HANDLING_ADJUST_TO_ROTATION_PIVOT;
344 opts.space_conversion = UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS;
345 opts.target_axes.right = UFBX_COORDINATE_AXIS_POSITIVE_X;
346 opts.target_axes.up = UFBX_COORDINATE_AXIS_POSITIVE_Z;
347 opts.target_axes.front = UFBX_COORDINATE_AXIS_NEGATIVE_Y;
348 opts.target_unit_meters = 1.0f /
params.global_scale;
350 opts.target_camera_axes.right = UFBX_COORDINATE_AXIS_POSITIVE_X;
351 opts.target_camera_axes.up = UFBX_COORDINATE_AXIS_POSITIVE_Y;
352 opts.target_camera_axes.front = UFBX_COORDINATE_AXIS_POSITIVE_Z;
353 opts.target_light_axes.right = UFBX_COORDINATE_AXIS_POSITIVE_X;
354 opts.target_light_axes.up = UFBX_COORDINATE_AXIS_POSITIVE_Y;
355 opts.target_light_axes.front = UFBX_COORDINATE_AXIS_POSITIVE_Z;
361 ufbx_error fbx_error;
362 ufbx_scene *
fbx = ufbx_load_stdio(file, &opts, &fbx_error);
367 "Failed to import FBX file '%s': '%s'\n",
369 fbx_error.description.data);
372 "FBX Import: Cannot import file '%s': '%s'",
374 fbx_error.description.data);
384#ifdef FBX_DEBUG_PRINT
386 fprintf(g_debug_file,
"Initial NODE local matrices:\n");
388 for (
const ufbx_node *node : ctx.
fbx.nodes) {
394 std::sort(
nodes.begin(),
nodes.end(), [](
const ufbx_node *a,
const ufbx_node *
b) {
395 int ncmp = strcmp(a->name.data, b->name.data);
399 return a->attrib_type >
b->attrib_type;
401 for (
const ufbx_node *node :
nodes) {
402 ufbx_matrix mtx = ufbx_matrix_mul(node->node_depth < 2 ? &node->node_to_world :
403 &node->node_to_parent,
404 &node->geometry_to_node);
405 fprintf(g_debug_file,
"init NODE %s self.matrix:\n", node->name.data);
408 fprintf(g_debug_file,
"\n");
412 ctx.import_materials();
413 ctx.import_armatures();
415 ctx.import_cameras();
417 ctx.import_empties();
418 ctx.import_animation(
FPS);
419 ctx.setup_hierarchy();
421 ufbx_free_scene(
fbx);
424 for (
Object *
obj : ctx.mapping.imported_objects) {
431 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)
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