0
$\begingroup$

I have imported a camera animation that came from a collada file. When I open the graph editor I see the rotations as quaternions.

How do I convert that to euler. I need to see euler in the Graph Editor.

thanks

NOTE: OK, I select the camera and change from Quaternions to XYZ Euler in the transform panel but the graph editor continues to show the animation in quaternions. I see that this box just changes the visualization mode on the transform panel instead of changing the keyframes that already exist. Any real way to convert existing keyframes from quaternions to euler?

$\endgroup$

4 Answers 4

3
$\begingroup$

Select the camera object, (still in quaternion rotation mode) copy script, paste into text editor, run script. It will create a set of rotation_euler fcurves matching the quaternion rotation. If all goes well manually change the rotation mode and clear the quaternion keyframes.

import bpy
from math import tan, atan
context = bpy.context
scene = context.scene
order = 'XYZ' # euler rotation order desired
cam_obj = context.active_object
action = cam_obj.animation_data.action

frames = []
fcurves = []

for index in [0, 1, 2, 4]:
    # search for rotation euler kfps
    fc = action.fcurves.find("rotation_quaternion", index=index)
    # make a list of frames that have quaternion rot keyframes
    if fc:
        frames.extend([kfp.co[0] for kfp in fc.keyframe_points])
        fcurves.append(fc)
# run thru and keyframe in 

for f in set(frames):
    scene.frame_set(f)
    cam_obj.rotation_euler = cam_obj.matrix_world.to_euler(order)
    #cam_obj.rotation_euler = [atan(tan(d)) for d in cam_obj.rotation_euler]
    cam_obj.keyframe_insert("rotation_euler", frame=f)
$\endgroup$
5
  • $\begingroup$ Fantastic the idea but your algorithm is generating a lot of discontinuity. If you want I can send you the DAE file I am testing on, so you can see for yourself. $\endgroup$
    – Duck
    Commented Mar 25, 2016 at 15:41
  • $\begingroup$ Do the rotation animations match between the original quaternion and new euler rotation modes? Perhaps the discontinuity is because 0 degrees = 360 degrees. Rather than post the file, post an image of the result. $\endgroup$
    – batFINGER
    Commented Mar 25, 2016 at 16:30
  • $\begingroup$ here you go this is the X Euler Rotation channel. Other channels are broken like this. Blender Euler Discontinuity filter is not fixing this. This is the same curve on Maya after applying the Euler filter. $\endgroup$
    – Duck
    Commented Mar 25, 2016 at 16:40
  • $\begingroup$ The hassle here is, for example, for the camera to face down in euler could use [0, 0, 0] or [180, 180, 0] . . Edit the q if you want an algorithm to search for the discontinuities and fix. Do the rotation animations match between quat and euler? $\endgroup$
    – batFINGER
    Commented Mar 25, 2016 at 17:16
  • $\begingroup$ I don't know how to do that. Thanks anyway. $\endgroup$
    – Duck
    Commented Mar 25, 2016 at 17:19
1
$\begingroup$

A little boring, but it works: go to the first quaternion keyframe, switch camera to euler, insert a rotation keyframe, switch back to quaternion, go to the next quaternion keyframe, etc ......

When keyed all keyframes, delete all quaternion curves in the graph editor: the animation will use the newly created euler curves.

$\endgroup$
0
$\begingroup$

Modifed code for blender 3.3 to fix error:

TypeError: Scene.frame_set(): error with argument 1, "frame" - Function.frame expected an int type, not float

replace scene.frame_set(f) with scene.frame_set(int(f))

import bpy
from math import tan, atan
context = bpy.context
scene = context.scene
order = 'XYZ' # euler rotation order desired
cam_obj = context.active_object
action = cam_obj.animation_data.action

frames = []
fcurves = []

for index in [0, 1, 2, 4]:
    # search for rotation euler kfps
    fc = action.fcurves.find("rotation_quaternion", index=index)
    # make a list of frames that have quaternion rot keyframes
    if fc:
        frames.extend([kfp.co[0] for kfp in fc.keyframe_points])
        fcurves.append(fc)
# run thru and keyframe in 

for f in set(frames):
    scene.frame_set(int(f))
    cam_obj.rotation_euler = cam_obj.matrix_world.to_euler(order)
    #cam_obj.rotation_euler = [atan(tan(d)) for d in cam_obj.rotation_euler]
    cam_obj.keyframe_insert("rotation_euler", frame=f)
$\endgroup$
0
$\begingroup$

Scriptless, out-of-the-box solution, that still only takes a minute for any length of animation:

Make another camera. Make it use some kind of Euler rotation in its transform settings, any kind you want. Give it a copy transforms constraint targeting your original camera. Use a "bake action" operation with visual keying and clear constraints. Now either use your new camera, or change your original to Euler and copy-paste the keys in.

Note: baking will create a keyframe for every frame. This is pretty much unavoidable if you want to perfectly match Euler rotations to quaternion rotations-- they don't interpolate the same way.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .