42 BLI_assert_msg(cu,
"The same F-Curve is being created twice, this is unexpected.");
49 BLI_assert(key_index >= 0 && key_index < curve->totvert);
52 bez.
vec[1][1] = value;
73 const ufbx_anim_layer &flayer)
77 for (
const ufbx_anim_prop &fprop : flayer.anim_props) {
78 if (fprop.anim_value->curves[0] ==
nullptr) {
81 bool supported_prop =
false;
83 const bool is_position =
STREQ(fprop.prop_name.data,
"Lcl Translation");
84 const bool is_rotation =
STREQ(fprop.prop_name.data,
"Lcl Rotation");
85 const bool is_scale =
STREQ(fprop.prop_name.data,
"Lcl Scaling");
86 const bool is_blend_shape =
STREQ(fprop.prop_name.data,
"DeformPercent");
87 const bool is_focal_length =
STREQ(fprop.prop_name.data,
"FocalLength");
88 const bool is_focus_dist =
STREQ(fprop.prop_name.data,
"FocusDistance");
89 const bool is_diffuse =
STREQ(fprop.prop_name.data,
"DiffuseColor");
90 if (is_position || is_rotation || is_scale || is_blend_shape || is_focal_length ||
91 is_focus_dist || is_diffuse)
93 supported_prop =
true;
96 if (!supported_prop) {
100 const bool is_anim_camera = is_focal_length || is_focus_dist;
101 const bool is_anim_mat = is_diffuse;
103 ID *target_id =
nullptr;
106 if (is_blend_shape) {
109 if (target_key !=
nullptr) {
110 target_id = &target_key->
id;
113 else if (is_anim_camera) {
115 if (fprop.element->instances.count > 0) {
119 target_id = (
ID *)
obj->data;
124 else if (is_anim_mat) {
128 if (mat !=
nullptr) {
129 target_id = (
ID *)mat;
134 const ufbx_node *fnode = ufbx_as_node(fprop.element);
139 if (
obj ==
nullptr) {
142 if (
obj ==
nullptr) {
150 target_id = &
obj->id;
154 if (target_id ==
nullptr) {
160 anims.
order = order++;
173 if (is_blend_shape) {
176 if (is_focal_length) {
209 std::string rna_prefix;
211 const ufbx_node *fnode = ufbx_as_node(anim.
fbx_elem);
215 rna_prefix = std::string(
"pose.bones[\"") + group_name_str +
"\"].";
223 int rot_channels = 3;
228 rna_rotation = curve_name_alloc.
copy_string(rna_prefix +
"rotation_quaternion");
232 rna_rotation = curve_name_alloc.
copy_string(rna_prefix +
"rotation_axis_angle");
236 rna_rotation = curve_name_alloc.
copy_string(rna_prefix +
"rotation_euler");
244 for (
int i = 0;
i < 3;
i++) {
245 r_curve_desc.
append({rna_position,
i, {}, {}, group_name});
247 for (
int i = 0;
i < rot_channels;
i++) {
248 r_curve_desc.
append({rna_rotation,
i, {}, {}, group_name});
250 for (
int i = 0;
i < 3;
i++) {
251 r_curve_desc.
append({rna_scale,
i, {}, {}, group_name});
256 const ufbx_anim *fbx_anim,
259 const float anim_offset,
262 const ufbx_node *fnode = ufbx_as_node(anim.
fbx_elem);
263 ufbx_matrix bone_xform = ufbx_identity_matrix;
271 const bool bone_at_scene_root = fnode->node_depth <= 1;
272 ufbx_matrix world_to_arm = ufbx_identity_matrix;
273 if (!bone_at_scene_root) {
275 if (arm_obj !=
nullptr) {
277 arm_obj, ufbx_identity_matrix);
282 bone_xform = ufbx_matrix_invert(&bone_xform);
285 int rot_channels = 3;
306 const ufbx_anim_curve *input_curves[9] = {};
318 input_curves[6] = anim.
prop_scale->anim_value->curves[0];
319 input_curves[7] = anim.
prop_scale->anim_value->curves[1];
320 input_curves[8] = anim.
prop_scale->anim_value->curves[2];
325 for (
int i = 0;
i < 9;
i++) {
326 if (input_curves[
i] !=
nullptr) {
327 for (
const ufbx_keyframe &key : input_curves[
i]->keyframes) {
328 if (key.interpolation == UFBX_INTERPOLATION_CUBIC) {
330 const_cast<ufbx_keyframe &
>(key).interpolation = UFBX_INTERPOLATION_LINEAR;
332 unique_key_times.
add(key.time);
337 std::sort(sorted_key_times.
begin(), sorted_key_times.
end());
340 int64_t rot_index = pos_index + 3;
341 int64_t scale_index = rot_index + rot_channels;
342 int64_t tot_curves = scale_index + 3;
344 BLI_assert_msg(curves[
i],
"fbx: animation curve was not created successfully");
351 double t = sorted_key_times[
i];
352 float tf =
float(t * fps + anim_offset);
353 ufbx_transform xform = ufbx_evaluate_transform(fbx_anim, fnode, t);
357 xform = ufbx_matrix_to_transform(&matrix);
364 math::Quaternion quat(xform.rotation.w, xform.rotation.x, xform.rotation.y, xform.rotation.z);
368 if (
i != 0 &&
math::dot(quat, quat_prev) < 0.0f) {
402 const float anim_offset)
409 const ufbx_anim_curve *input_curve = anim.
prop_focal_length->anim_value->curves[0];
411 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
412 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
413 float tf =
float(fkey.time * fps + anim_offset);
414 float val =
float(fkey.value);
421 const ufbx_anim_curve *input_curve = anim.
prop_focus_dist->anim_value->curves[0];
423 channelbag, {
"dof.focus_distance", 0}, input_curve->keyframes.count);
424 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
425 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
426 float tf =
float(fkey.time * fps + anim_offset);
428 float val =
float(fkey.value / 1000.0 * metadata.geometry_scale * metadata.root_scale);
439 const float anim_offset)
445 const char *rna_path_1 =
"diffuse_color";
446 const char *rna_path_2 =
"nodes[\"Principled BSDF\"].inputs[0].default_value";
458 for (
int ch = 0; ch < 3; ch++) {
459 const ufbx_anim_curve *input_curve = anim.
prop_mat_diffuse->anim_value->curves[ch];
460 FCurve *curve_1 =
create_fcurve(channelbag, {rna_path_1, ch}, input_curve->keyframes.count);
461 FCurve *curve_2 =
create_fcurve(chbag_node, {rna_path_2, ch}, input_curve->keyframes.count);
462 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
463 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
464 float tf =
float(fkey.time * fps + anim_offset);
465 float val =
float(fkey.value);
478 const float anim_offset)
480 const ufbx_blend_channel *fchan = ufbx_as_blend_channel(anim.
prop_blend_shape->element);
482 std::string rna_path = std::string(
"key_blocks[\"") + fchan->target_shape->name.data +
484 const ufbx_anim_curve *input_curve = anim.
prop_blend_shape->anim_value->curves[0];
486 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
487 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
488 double t = fkey.time;
489 float tf =
float(t * fps + anim_offset);
490 float val =
float(fkey.value / 100.0);
497 const ufbx_scene &
fbx,
500 const float anim_offset)
504 for (
const ufbx_anim_stack *fstack :
fbx.anim_stacks) {
505 for (
const ufbx_anim_layer *flayer : fstack->layers) {
512 std::string action_name = fstack->name.data;
513 if (!
STREQ(fstack->name.data, flayer->name.data) && fstack->layers.count != 1) {
515 action_name += flayer->name.data;
528 animated_ids.add(anim.target_id);
535 for (
ID *
id : animated_ids) {
538 const std::string slot_name =
id->name;
544 BLI_assert_msg(adt !=
nullptr,
"fbx: could not create animation data for an ID");
545 if (adt->
action ==
nullptr) {
553 "fbx: failed to assign slot to ID");
569 anim_transform_curve_index[index] = curve_desc.
size();
573 anim_transform_curve_index[index] = -1;
589 transform_curves.
data() +
590 anim_transform_curve_index[index]);
603 for (
FCurve *curve : transform_curves) {
Functions and classes to work with Actions.
Functions to work with AnimData.
Blender kernel action and pose functionality.
AnimData * BKE_animdata_ensure_id(ID *id)
void BKE_fcurve_handles_recalc(FCurve *fcu)
void BKE_fcurve_bezt_resize(FCurve *fcu, int new_totvert)
void id_fake_user_set(ID *id)
#define BLI_assert_msg(a, msg)
#define UNUSED_VARS_NDEBUG(...)
Object is a sort of wrapper for general info.
SubIterator begin() const
Value lookup_default(const Key &key, const Value &default_value) const
bool contains(const Key &key) const
StringRefNull copy_string(StringRef str)
Value & lookup_or_add_default(const Key &key)
ValueIterator values() const &
const Value & lookup(const Key &key) const
void append(const T &value)
IndexRange index_range() const
Span< T > as_span() const
void layer_keystrip_ensure()
const Layer * layer(int64_t index) const
Slot & slot_add_for_id_type(ID_Type idtype)
void slot_identifier_define(Slot &slot, StringRefNull new_identifier)
Vector< FCurve * > fcurve_create_many(Main *bmain, Span< FCurveDescriptor > fcurve_descriptors)
FCurve * fcurve_create_unique(Main *bmain, const FCurveDescriptor &fcurve_descriptor)
const Strip * strip(int64_t index) const
static constexpr slot_handle_t unassigned
Channelbag & channelbag_for_slot_ensure(const Slot &slot)
const T & data(const Action &owning_action) const
Slot * assign_action_ensure_slot_for_keying(Action &action, ID &animated_id)
Action & action_add(Main &bmain, StringRefNull name)
Channelbag & action_channelbag_ensure(bAction &dna_action, ID &animated_id)
bool assign_action(bAction *action, ID &animated_id)
ActionSlotAssignmentResult assign_action_slot(Slot *slot_to_assign, ID &animated_id)
ActionSlotAssignmentResult
static void create_transform_curve_desc(const FbxElementMapping &mapping, const ElementAnimations &anim, LinearAllocator<> &curve_name_alloc, Vector< animrig::FCurveDescriptor > &r_curve_desc)
static void create_camera_curves(const ufbx_metadata &metadata, const ElementAnimations &anim, animrig::Channelbag &channelbag, const double fps, const float anim_offset)
const char * get_fbx_name(const ufbx_string &name, const char *def)
static void create_transform_curve_data(const FbxElementMapping &mapping, const ufbx_anim *fbx_anim, const ElementAnimations &anim, const double fps, const float anim_offset, FCurve **curves)
static void create_material_curves(const ElementAnimations &anim, bAction *action, animrig::Channelbag &channelbag, const double fps, const float anim_offset)
static void set_curve_sample(FCurve *curve, int64_t key_index, float time, float value)
static void finalize_curve(FCurve *cu)
static Vector< ElementAnimations > gather_animated_properties(const FbxElementMapping &mapping, const ufbx_anim_layer &flayer)
void import_animations(Main &bmain, const ufbx_scene &fbx, const FbxElementMapping &mapping, const double fps, const float anim_offset)
static FCurve * create_fcurve(animrig::Channelbag &channelbag, const animrig::FCurveDescriptor &descriptor, int64_t key_count)
ufbx_matrix calc_bone_pose_matrix(const ufbx_transform &local_xform, const ufbx_node &node, const ufbx_matrix &local_bind_inv_matrix)
static void create_blend_shape_curves(const ElementAnimations &anim, animrig::Channelbag &channelbag, const double fps, const float anim_offset)
QuaternionBase< float > Quaternion
AxisAngleBase< float, AngleRadianBase< float > > AxisAngle
EulerXYZBase< float > EulerXYZ
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
AxisAngleBase< T, AngleT > to_axis_angle(const EulerXYZBase< T > &euler)
Euler3Base< T > to_euler(const AxisAngleBase< T, AngleT > &axis_angle, EulerOrder order)
struct bNodeTree * nodetree
const ufbx_anim_prop * prop_focal_length
const ufbx_anim_prop * prop_blend_shape
eRotationModes object_rotmode
const ufbx_anim_prop * prop_mat_diffuse
const ufbx_anim_prop * prop_rotation
const ufbx_anim_prop * prop_position
const ufbx_anim_prop * prop_focus_dist
const ufbx_element * fbx_elem
const ufbx_anim_prop * prop_scale
Map< const ufbx_node *, Object * > bone_to_armature
Map< const ufbx_material *, Material * > mat_to_material
Map< const ufbx_node *, std::string > node_to_name
Set< const ufbx_node * > node_is_blender_bone
Map< const Object *, ufbx_matrix > armature_world_to_arm_pose_matrix
ufbx_matrix calc_local_bind_matrix(const ufbx_node *bone_node, const ufbx_matrix &world_to_arm) const
Map< const ufbx_element *, Object * > el_to_object
Map< const ufbx_element *, Key * > el_to_shape_key
const AngleT & angle() const
const vec3_type & axis() const
static QuaternionBase identity()