2

I have an odd problem. I am exporting a scene, including animation curves. I have parent/child relationsships in my scene.

Base example: I create a big cube at the origin. I add a small green cube as a child of the big cube, offset z +2. I hit I to create a location keyframe. On a later frame, I shift the green cube 2 in the x axis, and take another location keyframe. And later again, I move it -2 on the x axis, and take another location keyframe.

Here is the result: enter image description here

The graph shows exactly what I would expect: the X position of the green cube goes from 0 to 2 to 0.

However, let's repeat the process, except starting with the big gray cube at offset 4. Create a cube at 4x,0y,0z. Add a red cube at 4x,0y,2z, and make it a child object of the cube. Create the same location keyframes: frame 0, x = 4. frame 30, x=6. frame 60, x = 4. enter image description here

So this shows the X Location in the curve as starting at 4, going to 6, and back to 4. This is not what I am expecting! Because the parent object is already at 4x, I was expecting the child object to go from 0x to 2x to 0x.

Now here's the fun part: Let's say I move the gray cube back to 0,0,0. Unexpectedly (to me at least), the red cube's curve stays at 4 to 6 to 4! In the scene, the red cube is moving from 0 to 2 to 0, but the curve says otherwise! Clearly there is some sort of offset saved in the curve!

So, my exported scene gets all messed up unless I happen to position my parent object at the origin before I start taking keyframes, which really is not practical.

For what it's worth, here is my code to export the animation curves:

scene = bpy.data.scenes['Scene']
fps = scene.render.fps
# Export actions that match the format "[name1]name2"
pattern = re.compile('\[([^\]]+)\](.+)')
actions = bpy.data.actions
fw('<animdata>\n')
for actionname in actions.keys():
    match = pattern.match(actionname)
    # Does the action match [name1]name2 ?
    if (match == None):
        continue
    action = actions[actionname]
    # Grab the [name1] portion of the action's name as the object name
    obname = match.group(1)
    # Grab the name2 portion of the action's name as the Action name
    shortname = match.group(2)
fw('  &lt;animation name=&quot;%s&quot; fps=&quot;%d&quot; start=&quot;%d&quot; end=&quot;%d&quot;&gt;\n' % (shortname, fps, scene.frame_start, scene.frame_end))

# Grab the curves of this action.
fcurves = action.fcurves
if (len(fcurves) &gt; 0):
    fw('    &lt;anim object=&quot;%s&quot;&gt;\n' % obname)
    # Write out each curve as a &lt;curve&gt; element
    for curve in fcurves:
        fw('      &lt;curve path=&quot;%s&quot; axis=&quot;%d&quot;&gt;\n' % (curve.data_path, curve.array_index))
        for kp in curve.keyframe_points:
            fw('        &lt;point interp=&quot;%s&quot; co=&quot;%f,%f&quot; lh=&quot;%f,%f&quot; rh=&quot;%f,%f&quot;/&gt;\n' % (kp.interpolation, kp.co.x, kp.co.y, kp.handle_left.x, kp.handle_left.y, kp.handle_right.x, kp.handle_right.y))
        fw('      &lt;/curve&gt;\n')
    fw('    &lt;/anim&gt;\n')
fw('  &lt;/animation&gt;\n')

fw('</animdata>\n')

Thanks for any insight!

Jamie
  • 149
  • 5
  • 2
    Related https://blender.stackexchange.com/questions/169416/does-a-child-object-inherit-the-matrix-from-the-parent or as shown in the issue here https://blender.stackexchange.com/questions/214740/two-objects-right-next-to-each-other-but-wildly-different-coordinates that when an object is parented "defaultly" the matrix parent inverse is set such that the matrix local at that location is unity. Options here would be to clear the parent inverse https://blender.stackexchange.com/questions/28896/how-to-clear-parent-inverse-without-actually-moving-the-object or get into habit of using parent – batFINGER Mar 19 '21 at 04:04
  • 2
    without inverse. Or adjust exported fcurves according the matrix parent inverse translation. – batFINGER Mar 19 '21 at 04:08
  • 1
    Thanks, @batFINGER ! – Jamie Mar 19 '21 at 12:57

0 Answers0