41 BLI_assert_msg(cu,
"The same F-Curve is being created twice, this is unexpected.");
48 BLI_assert(key_index >= 0 && key_index < curve->totvert);
51 bez.
vec[1][1] = value;
72 const ufbx_anim_layer &flayer)
76 for (
const ufbx_anim_prop &fprop : flayer.anim_props) {
77 if (fprop.anim_value->curves[0] ==
nullptr) {
80 bool supported_prop =
false;
82 const bool is_position =
STREQ(fprop.prop_name.data,
"Lcl Translation");
83 const bool is_rotation =
STREQ(fprop.prop_name.data,
"Lcl Rotation");
84 const bool is_scale =
STREQ(fprop.prop_name.data,
"Lcl Scaling");
85 const bool is_blend_shape =
STREQ(fprop.prop_name.data,
"DeformPercent");
86 const bool is_focal_length =
STREQ(fprop.prop_name.data,
"FocalLength");
87 const bool is_focus_dist =
STREQ(fprop.prop_name.data,
"FocusDistance");
88 const bool is_diffuse =
STREQ(fprop.prop_name.data,
"DiffuseColor");
89 if (is_position || is_rotation || is_scale || is_blend_shape || is_focal_length ||
90 is_focus_dist || is_diffuse)
92 supported_prop =
true;
95 if (!supported_prop) {
99 const bool is_anim_camera = is_focal_length || is_focus_dist;
100 const bool is_anim_mat = is_diffuse;
102 ID *target_id =
nullptr;
105 if (is_blend_shape) {
108 if (target_key !=
nullptr) {
109 target_id = &target_key->
id;
112 else if (is_anim_camera) {
114 if (fprop.element->instances.count > 0) {
118 target_id = (
ID *)
obj->data;
123 else if (is_anim_mat) {
127 if (mat !=
nullptr) {
128 target_id = (
ID *)mat;
133 const ufbx_node *fnode = ufbx_as_node(fprop.element);
138 if (
obj ==
nullptr) {
141 if (
obj ==
nullptr) {
149 target_id = &
obj->id;
153 if (target_id ==
nullptr) {
159 anims.
order = order++;
172 if (is_blend_shape) {
175 if (is_focal_length) {
208 std::string rna_prefix;
210 const ufbx_node *fnode = ufbx_as_node(anim.
fbx_elem);
214 rna_prefix = std::string(
"pose.bones[\"") + group_name_str +
"\"].";
222 int rot_channels = 3;
227 rna_rotation = curve_name_alloc.
copy_string(rna_prefix +
"rotation_quaternion");
231 rna_rotation = curve_name_alloc.
copy_string(rna_prefix +
"rotation_axis_angle");
235 rna_rotation = curve_name_alloc.
copy_string(rna_prefix +
"rotation_euler");
243 for (
int i = 0;
i < 3;
i++) {
244 r_curve_desc.
append({rna_position,
i, {}, {}, group_name});
246 for (
int i = 0;
i < rot_channels;
i++) {
247 r_curve_desc.
append({rna_rotation,
i, {}, {}, group_name});
249 for (
int i = 0;
i < 3;
i++) {
250 r_curve_desc.
append({rna_scale,
i, {}, {}, group_name});
255 const ufbx_anim *fbx_anim,
258 const float anim_offset,
261 const ufbx_node *fnode = ufbx_as_node(anim.
fbx_elem);
262 ufbx_matrix bone_xform = ufbx_identity_matrix;
270 const bool bone_at_scene_root = fnode->node_depth <= 1;
271 ufbx_matrix world_to_arm = ufbx_identity_matrix;
272 if (!bone_at_scene_root) {
274 if (arm_obj !=
nullptr) {
276 arm_obj, ufbx_identity_matrix);
281 bone_xform = ufbx_matrix_invert(&bone_xform);
284 int rot_channels = 3;
305 const ufbx_anim_curve *input_curves[9] = {};
317 input_curves[6] = anim.
prop_scale->anim_value->curves[0];
318 input_curves[7] = anim.
prop_scale->anim_value->curves[1];
319 input_curves[8] = anim.
prop_scale->anim_value->curves[2];
324 for (
int i = 0;
i < 9;
i++) {
325 if (input_curves[
i] !=
nullptr) {
326 for (
const ufbx_keyframe &key : input_curves[
i]->keyframes) {
327 if (key.interpolation == UFBX_INTERPOLATION_CUBIC) {
329 const_cast<ufbx_keyframe &
>(key).interpolation = UFBX_INTERPOLATION_LINEAR;
331 unique_key_times.
add(key.time);
336 std::sort(sorted_key_times.
begin(), sorted_key_times.
end());
339 int64_t rot_index = pos_index + 3;
340 int64_t scale_index = rot_index + rot_channels;
341 int64_t tot_curves = scale_index + 3;
343 BLI_assert_msg(curves[
i],
"fbx: animation curve was not created successfully");
350 double t = sorted_key_times[
i];
351 float tf = float(t * fps + anim_offset);
352 ufbx_transform xform = ufbx_evaluate_transform(fbx_anim, fnode, t);
356 xform = ufbx_matrix_to_transform(&matrix);
363 math::Quaternion quat(xform.rotation.w, xform.rotation.x, xform.rotation.y, xform.rotation.z);
367 if (
i != 0 &&
math::dot(quat, quat_prev) < 0.0f) {
401 const float anim_offset)
408 const ufbx_anim_curve *input_curve = anim.
prop_focal_length->anim_value->curves[0];
410 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
411 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
412 float tf = float(fkey.time * fps + anim_offset);
413 float val = float(fkey.value);
420 const ufbx_anim_curve *input_curve = anim.
prop_focus_dist->anim_value->curves[0];
422 channelbag, {
"dof.focus_distance", 0}, input_curve->keyframes.count);
423 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
424 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
425 float tf = float(fkey.time * fps + anim_offset);
427 float val = float(fkey.value / 1000.0 * metadata.geometry_scale * metadata.root_scale);
438 const float anim_offset)
444 const char *rna_path_1 =
"diffuse_color";
445 const char *rna_path_2 =
"nodes[\"Principled BSDF\"].inputs[0].default_value";
457 for (
int ch = 0; ch < 3; ch++) {
458 const ufbx_anim_curve *input_curve = anim.
prop_mat_diffuse->anim_value->curves[ch];
459 FCurve *curve_1 =
create_fcurve(channelbag, {rna_path_1, ch}, input_curve->keyframes.count);
460 FCurve *curve_2 =
create_fcurve(chbag_node, {rna_path_2, ch}, input_curve->keyframes.count);
461 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
462 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
463 float tf = float(fkey.time * fps + anim_offset);
464 float val = float(fkey.value);
477 const float anim_offset)
479 const ufbx_blend_channel *fchan = ufbx_as_blend_channel(anim.
prop_blend_shape->element);
481 std::string rna_path = std::string(
"key_blocks[\"") + fchan->target_shape->name.data +
483 const ufbx_anim_curve *input_curve = anim.
prop_blend_shape->anim_value->curves[0];
485 for (
int i = 0;
i < input_curve->keyframes.count;
i++) {
486 const ufbx_keyframe &fkey = input_curve->keyframes[
i];
487 double t = fkey.time;
488 float tf = float(t * fps + anim_offset);
489 float val = float(fkey.value / 100.0);
496 const ufbx_scene &
fbx,
499 const float anim_offset)
503 for (
const ufbx_anim_stack *fstack :
fbx.anim_stacks) {
504 for (
const ufbx_anim_layer *flayer : fstack->layers) {
511 std::string action_name = fstack->name.data;
512 if (!
STREQ(fstack->name.data, flayer->name.data) && fstack->layers.count != 1) {
514 action_name += flayer->name.data;
527 animated_ids.add(anim.target_id);
534 for (
ID *
id : animated_ids) {
537 const std::string slot_name =
id->name;
543 BLI_assert_msg(adt !=
nullptr,
"fbx: could not create animation data for an ID");
544 if (adt->
action ==
nullptr) {
552 "fbx: failed to assign slot to ID");
568 anim_transform_curve_index[index] = curve_desc.
size();
572 anim_transform_curve_index[index] = -1;
588 transform_curves.
data() +
589 anim_transform_curve_index[index]);
602 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(...)
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()