@@ -626,39 +626,6 @@ def _transformation_curves_gen(item, values_arrays, channel_keys):
626
626
yield from sca
627
627
628
628
629
- def blen_read_animation_channel_curves (curves ):
630
- """Read one or (very rarely) more animation curves, that affect a single channel of a single property, from FBX
631
- data.
632
-
633
- When there are multiple curves, they will be combined into a single sorted animation curve with later curves taking
634
- precedence when the curves contain duplicate times.
635
-
636
- It is expected that there will almost never be more than a single curve to read because FBX's default animation
637
- system only uses the first curve assigned to a channel.
638
-
639
- Returns an array of sorted, unique FBX keyframe times and an array of values for each of those keyframe times."""
640
- if len (curves ) > 1 :
641
- times_and_values_tuples = list (map (blen_read_single_animation_curve , curves ))
642
- # The FBX animation system's default implementation only uses the first curve assigned to a channel.
643
- # Additional curves per channel are allowed by the FBX specification, but the handling of these curves is
644
- # considered the responsibility of the application that created them. Note that each curve node is expected to
645
- # have a unique set of channels, so these additional curves with the same channel would have to belong to
646
- # separate curve nodes. See the FBX SDK documentation for FbxAnimCurveNode.
647
-
648
- # Combine the curves together to produce a single array of sorted keyframe times and a single array of values.
649
- # The arrays are concatenated in reverse so that if there are duplicate times in the read curves, then only the
650
- # value of the last occurrence is kept.
651
- all_times = np .concatenate ([t [0 ] for t in reversed (times_and_values_tuples )])
652
- all_values = np .concatenate ([t [1 ] for t in reversed (times_and_values_tuples )])
653
- # Get the unique, sorted times and the index in all_times of the first occurrence of each unique value.
654
- sorted_unique_times , unique_indices_in_all_times = np .unique (all_times , return_index = True )
655
-
656
- values_of_sorted_unique_times = all_values [unique_indices_in_all_times ]
657
- return sorted_unique_times , values_of_sorted_unique_times
658
- else :
659
- return blen_read_single_animation_curve (curves [0 ])
660
-
661
-
662
629
def _combine_curve_keyframe_times (times_and_values_tuples , initial_values ):
663
630
"""Combine multiple parsed animation curves, that affect different channels, such that every animation curve
664
631
contains the keyframes from every other curve, interpolating the values for the newly inserted keyframes in each
@@ -779,8 +746,8 @@ def _convert_fbx_time_to_blender_time(key_times, blen_start_offset, fbx_start_of
779
746
return key_times
780
747
781
748
782
- def blen_read_single_animation_curve (fbx_curve ):
783
- """Read a single animation curve from FBX data.
749
+ def blen_read_animation_curve (fbx_curve ):
750
+ """Read an animation curve from FBX data.
784
751
785
752
The parsed keyframe times are guaranteed to be strictly increasing."""
786
753
key_times = parray_as_ndarray (elem_prop_first (elem_find_first (fbx_curve , b'KeyTime' )))
@@ -851,11 +818,19 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset, glo
851
818
"""
852
819
from bpy .types import Object , PoseBone , ShapeKey , Material , Camera
853
820
854
- fbx_curves : dict [bytes , dict [int , list [ FBXElem ] ]] = {}
821
+ fbx_curves : dict [bytes , dict [int , FBXElem ]] = {}
855
822
for curves , fbxprop in cnodes .values ():
856
823
channels_dict = fbx_curves .setdefault (fbxprop , {})
857
824
for (fbx_acdata , _blen_data ), channel in curves .values ():
858
- channels_dict .setdefault (channel , []).append (fbx_acdata )
825
+ if channel in channels_dict :
826
+ # Ignore extra curves when one has already been found for this channel because FBX's default animation
827
+ # system implementation only uses the first curve assigned to a channel.
828
+ # Additional curves per channel are allowed by the FBX specification, but the handling of these curves
829
+ # is considered the responsibility of the application that created them. Note that each curve node is
830
+ # expected to have a unique set of channels, so these additional curves with the same channel would have
831
+ # to belong to separate curve nodes. See the FBX SDK documentation for FbxAnimCurveNode.
832
+ continue
833
+ channels_dict [channel ] = fbx_acdata
859
834
860
835
# Leave if no curves are attached (if a blender curve is attached to scale but without keys it defaults to 0).
861
836
if len (fbx_curves ) == 0 :
@@ -894,23 +869,23 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset, glo
894
869
for prop , nbr_channels , grpname in props for channel in range (nbr_channels )]
895
870
896
871
if isinstance (item , Material ):
897
- for fbxprop , channel_to_curves in fbx_curves .items ():
872
+ for fbxprop , channel_to_curve in fbx_curves .items ():
898
873
assert (fbxprop == b'DiffuseColor' )
899
- for channel , curves in channel_to_curves .items ():
874
+ for channel , curve in channel_to_curve .items ():
900
875
assert (channel in {0 , 1 , 2 })
901
876
blen_curve = blen_curves [channel ]
902
- fbx_key_times , values = blen_read_animation_channel_curves ( curves )
877
+ fbx_key_times , values = blen_read_animation_curve ( curve )
903
878
blen_store_keyframes (fbx_key_times , blen_curve , values , anim_offset , fps )
904
879
905
880
elif isinstance (item , ShapeKey ):
906
881
deform_values = shape_key_deforms .setdefault (item , [])
907
- for fbxprop , channel_to_curves in fbx_curves .items ():
882
+ for fbxprop , channel_to_curve in fbx_curves .items ():
908
883
assert (fbxprop == b'DeformPercent' )
909
- for channel , curves in channel_to_curves .items ():
884
+ for channel , curve in channel_to_curve .items ():
910
885
assert (channel == 0 )
911
886
blen_curve = blen_curves [channel ]
912
887
913
- fbx_key_times , values = blen_read_animation_channel_curves ( curves )
888
+ fbx_key_times , values = blen_read_animation_curve ( curve )
914
889
# A fully activated shape key in FBX DeformPercent is 100.0 whereas it is 1.0 in Blender.
915
890
values = values / 100.0
916
891
blen_store_keyframes (fbx_key_times , blen_curve , values , anim_offset , fps )
@@ -921,15 +896,15 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset, glo
921
896
deform_values .append (values .max ())
922
897
923
898
elif isinstance (item , Camera ):
924
- for fbxprop , channel_to_curves in fbx_curves .items ():
899
+ for fbxprop , channel_to_curve in fbx_curves .items ():
925
900
is_focus_distance = fbxprop == b'FocusDistance'
926
901
assert (fbxprop == b'FocalLength' or is_focus_distance )
927
- for channel , curves in channel_to_curves .items ():
902
+ for channel , curve in channel_to_curve .items ():
928
903
assert (channel == 0 )
929
904
# The indices are determined by the creation of the `props` list above.
930
905
blen_curve = blen_curves [1 if is_focus_distance else 0 ]
931
906
932
- fbx_key_times , values = blen_read_animation_channel_curves ( curves )
907
+ fbx_key_times , values = blen_read_animation_curve ( curve )
933
908
if is_focus_distance :
934
909
# Remap the imported values from FBX to Blender.
935
910
values = values / 1000.0
@@ -950,13 +925,13 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset, glo
950
925
times_and_values_tuples = []
951
926
initial_values = []
952
927
channel_keys = []
953
- for fbxprop , channel_to_curves in fbx_curves .items ():
928
+ for fbxprop , channel_to_curve in fbx_curves .items ():
954
929
if fbxprop not in transform_prop_to_attr :
955
930
# Currently, we only care about transformation curves.
956
931
continue
957
- for channel , curves in channel_to_curves .items ():
932
+ for channel , curve in channel_to_curve .items ():
958
933
assert (channel in {0 , 1 , 2 })
959
- fbx_key_times , values = blen_read_animation_channel_curves ( curves )
934
+ fbx_key_times , values = blen_read_animation_curve ( curve )
960
935
961
936
channel_keys .append ((fbxprop , channel ))
962
937
0 commit comments