FBX animation rotation problem

The FBX rotation generated by this code is completely different from what I expected. Is my code incorrect or is it a bug in Aspose?

Furthermore, the rotation works correctly when I set the X and Z axes separately, but the rotation parameters are not the Euler angles I input. I don’t understand what parameters should be input to determine the rotation angle.

private static void testfbx()
{
    Scene scene = new Scene();
    Node cube1 = scene.RootNode.CreateChildNode("cube1", new Box());
    Property Rotation = cube1.Transform.FindProperty("Rotation");
    BindPoint bindPoint = new BindPoint(scene, Rotation);
    bindPoint.BindKeyframeSequence("Y", new KeyframeSequence()
    {
        { 0, 0.0f, Interpolation.Constant }, // 使用 Linear 替换 BSpline
        { 3, 30.0f, Interpolation.Constant },
        { 6, 0.0f, Interpolation.Constant }
    });
    scene.Save(@"C:\Users\Administrator\Desktop\1\test2.fbx", FileFormat.FBX7700ASCII);
}

@LuoHui

The issue you’re encountering is likely due to binding the animation to the Rotation property directly, rather than using the EulerAngles property, which is the correct and documented way to animate rotations in Aspose.3D for FBX files.

  1. Use EulerAngles instead of Rotation:
    The Rotation property may not represent Euler angles directly and could be interpreted differently depending on the internal representation (e.g., quaternions or axis-angle). When animating rotational transformations with expected Euler angle behavior, you should bind to the EulerAngles property of the transform . Your current code uses:
Property Rotation = cube1.Transform.FindProperty("Rotation");

This is not the recommended approach for Euler angle animation.

  1. Correct binding via EulerAngles:
    As shown in official examples, rotation animations should be bound to Transform.EulerAngles, and keyframe sequences should target specific axes like "X", "Y", or "Z" under that property . For example:
BindPoint bindPoint = new BindPoint(scene, cube1.Transform, "EulerAngles");
bindPoint.BindKeyframeSequence("Y", new KeyframeSequence()
{
{ 0, 0.0f },
{ 3, 30.0f },
{ 6, 0.0f }
});

This ensures that the values you input (like 30.0f) are interpreted as degrees around the Y-axis in Euler angle space.

  1. Why separate X/Z works but values differ:
    You mentioned that setting X or Z axes separately works, but the angles don’t match expectations. This further suggests that the Rotation property is not mapping 1:1 to Euler angles — it may be using a different rotation representation (e.g., quaternion components or transformed values), leading to non-intuitive input-output relationships .

  2. Recommended fix:
    Update your code to bind to EulerAngles instead:

private static void testfbx()
{
Scene scene = new Scene();
Node cube1 = scene.RootNode.CreateChildNode("cube1", new Box());

// Bind to EulerAngles, not Rotation
BindPoint bindPoint = new BindPoint(scene, cube1.Transform, "EulerAngles");

bindPoint.BindKeyframeSequence("Y", new KeyframeSequence()
{
{ 0, 0.0f, Interpolation.Constant },
{ 3, 30.0f, Interpolation.Constant },
{ 6, 0.0f, Interpolation.Constant }
});

scene.Save(@"C:\Users\Administrator\Desktop\1\test2.fbx", FileFormat.FBX7700ASCII);
}

This approach aligns with documented usage patterns and should produce the expected Euler angle rotation animation . The problem is therefore most likely due to incorrect property usage, not a bug in Aspose.3D.

thx is working now!

@LuoHui

The FBX animation rotation issue was resolved by using the EulerAngles property instead of the Rotation property, as EulerAngles correctly interprets animation keyframes in Euler angle space, which aligns with expected rotational behavior .

Binding animation to the Rotation property can lead to unexpected results because it may internally use non-Euler representations such as quaternions, making direct degree-based inputs unintuitive or incorrectly interpreted .

Official usage patterns confirm that rotational animations should be bound to the Transform.EulerAngles property when animating individual axes (e.g., “X”, “Y”, “Z”) with expected degree values [2, 3]. For example:

BindPoint bindPoint = new BindPoint(scene, cube1.Transform, "EulerAngles");
bindPoint.BindKeyframeSequence("Y", new KeyframeSequence()
{
 { 0, 0.0f, Interpolation.Constant },
 { 3, 30.0f, Interpolation.Constant },
 { 6, 0.0f, Interpolation.Constant }
});

Glad to hear your animation rotation issue is now working!

@LuoHui

The Rotation property stores its value as a quaternion.
If you need the rotation expressed as Euler angles (in degrees), please use the EulerAngles property instead.

When exporting to a format that doesn’t natively support Euler angles, Aspose.3D will automatically resample the key‑frame sequence to preserve the animation.

                Property Rotation = cube1.Transform.FindProperty("EulerAngles");

How do I define quaternion animation?
Could you provide a sample code example?

var AngleQuaternion = partObj.keyframeDataList.Where(item => item.Type.Contains("PRSTontrollerAngleQuaternion")).ToList();
// ---四元數旋轉动画 ---
if (AngleQuaternion.Count >= 2)
{
    var xSeq = new KeyframeSequence();
    var ySeq = new KeyframeSequence();
    var zSeq = new KeyframeSequence();
    var rotationProperty = node.Transform.FindProperty("Rotation");
    var bindPointRotation = new BindPoint(scene, rotationProperty);
    foreach (var item in AngleQuaternion)
    {
        float currentTime = item.Time / 1000.0f;
        //var type = item.Type.Split('_')[1];
        //#mo_Dummy021 4.933 0.8320421 -0.008255602 0.00550303 -0.5546238 0 0
        Console.WriteLine($"{node.Name} {currentTime} {item.Value1} {item.Value2} {item.Value3} {item.Value4} {item.Value5} {item.Value6}");
        xSeq.Add(currentTime, item.Value1, Interpolation.Linear);
        ySeq.Add(currentTime, item.Value2, Interpolation.Linear);
        zSeq.Add(currentTime, item.Value3, Interpolation.Linear);
    }
    bindPointRotation.BindKeyframeSequence("X", xSeq);
    bindPointRotation.BindKeyframeSequence("Y", ySeq);
    bindPointRotation.BindKeyframeSequence("Z", zSeq);
}

@LuoHui

Because a quaternion consists of four components (X, Y, Z, W), you’ll need to bind a separate key‑frame sequence for each of those channels—just as you described in your original post.

If you’re primarily working with FBX files, I recommend sticking with Euler angles. This approach preserves the greatest compatibility, and it avoids the potential loss of animation detail that can occur when resampling key‑frame sequences for quaternions.

I understand, but what should I do if my data consists of quaternions? Should I use quaternion conversion?

We recommend converting the quaternion to Euler angles yourself and then creating the animation key‑frame sequence manually. This approach usually yields better results than using the built‑in resample feature, because it gives you full control over the animation details.