Discussion:
[Bf-python] Getting fcurve data from parented object
Asbjørn
2013-01-23 23:51:51 UTC
Permalink
Hi,

in LuxBlend25 we use bpy.types.FCurve's evaluate() method[1] to get the
animation data at a given time point for rendering motion blur.

This works well, as long as the object has at least one keyframe.

However, if the object is a child object, and _only_ the parent has
keyframes, then the evaluate() call does not return animated data,
making it look as if the child object is not animated.

If the parent is animated, and the child object contains just a single
"no-op" keyframe, then evaluate() behaves as expected, returning the
parent's animation data.

Are we doing things wrong, or is this by design? In either case, is
there a proper way of handling this, without walking up the tree until
we find a (grand)parent with animation data?

Cheers
- Asbj?rn

[1]:
http://src.luxrender.net/luxblend25/file/196744443a50/src/luxrender/export/__init__.py#l274
Campbell Barton
2013-01-24 00:25:03 UTC
Permalink
Post by Asbjørn
Hi,
in LuxBlend25 we use bpy.types.FCurve's evaluate() method[1] to get the
animation data at a given time point for rendering motion blur.
This works well, as long as the object has at least one keyframe.
However, if the object is a child object, and _only_ the parent has
keyframes, then the evaluate() call does not return animated data,
making it look as if the child object is not animated.
If the parent is animated, and the child object contains just a single
"no-op" keyframe, then evaluate() behaves as expected, returning the
parent's animation data.
Are we doing things wrong, or is this by design? In either case, is
there a proper way of handling this, without walking up the tree until
we find a (grand)parent with animation data?
Cheers
- Asbj?rn
http://src.luxrender.net/luxblend25/file/196744443a50/src/luxrender/export/__init__.py#l274
I wouldn't suggest to attempt to calculate the objects transformation
directly because there are too many influences: constraints, drivers,
vertex parents, bone parents... etc. which can all be animated.

Better use scene.frame_set(frame, subframe), then collect object
matrix data for motion blur.

http://www.blender.org/documentation/blender_python_api_2_65_release/bpy.types.Scene.html#bpy.types.Scene.frame_set
--
- Campbell
Asbjørn
2013-01-24 01:09:45 UTC
Permalink
Post by Campbell Barton
Better use scene.frame_set(frame, subframe), then collect object
matrix data for motion blur.
This did the trick! One detail though, besides comparing the subframe
matrices, how can I reliably determine if an object is animated? I'd
like to avoid changing the subframe if I don't have to.

Cheers again :)
- Asbj?rn
Campbell Barton
2013-01-24 04:29:24 UTC
Permalink
Post by Asbjørn
Post by Campbell Barton
Better use scene.frame_set(frame, subframe), then collect object
matrix data for motion blur.
This did the trick! One detail though, besides comparing the subframe
matrices, how can I reliably determine if an object is animated? I'd
like to avoid changing the subframe if I don't have to.
Cheers again :)
- Asbj?rn
Quite sure there isn't, blender does flush flags internally via the
depsgraph so its possible to expose.

However even then I don't think it would be 100% reliable, the reason
being that you can't know ahead of time if changing an animated
property will tag the data-block to be updated through its 'set'
function (which would in-turn be flushed to other objects).
--
- Campbell
Asbjørn
2013-01-24 14:32:39 UTC
Permalink
Post by Campbell Barton
Quite sure there isn't, blender does flush flags internally via the
depsgraph so its possible to expose.
Allrighty then. I'll have to run some performance tests to see how bad
it is when exporting a lot of objects.

Thanks for the help.

Cheers
- Asbj?rn
Matt Ebb
2013-01-26 21:04:29 UTC
Permalink
As a hint, It will probably be faster for you to minimize scene updates, so rather than set the current frame for all your subframe steps, for each object, it will be better to set the frame to the first subframe, iterate over your required objects storing their matrices, the set the frame to a new subframe, and then go over and collect all the matrices again. I do something a bit like that in the 3delight exporter.
Post by Asbjørn
Post by Campbell Barton
Quite sure there isn't, blender does flush flags internally via the
depsgraph so its possible to expose.
Allrighty then. I'll have to run some performance tests to see how bad
it is when exporting a lot of objects.
Thanks for the help.
Cheers
- Asbj?rn
_______________________________________________
Bf-python mailing list
Bf-python at blender.org
http://lists.blender.org/mailman/listinfo/bf-python
Asbjørn
2013-01-27 19:43:53 UTC
Permalink
Post by Matt Ebb
As a hint, It will probably be faster for you to minimize scene updates, so rather than set the current frame for all your subframe steps, for each object, it will be better to set the frame to the first subframe, iterate over your required objects storing their matrices, the set the frame to a new subframe, and then go over and collect all the matrices again. I do something a bit like that in the 3delight exporter.
Yeah, I thought about it but it would require some non-trivial
refactoring of the exporter. The current way was very non-intrusive :)

I'll probably do this if it becomes an issue.

Cheers
- Asbj?rn
Asbjørn
2013-01-26 23:54:49 UTC
Permalink
Post by Campbell Barton
I wouldn't suggest to attempt to calculate the objects transformation
directly because there are too many influences: constraints, drivers,
vertex parents, bone parents... etc. which can all be animated.
Hi again,

seems there's some issue when an object has a motion path, and the
motion path has a driver on the "evaluation time", and the object has no
keyframes. Then the transformation matrices are not updated it seems. If
the object has a keyframe, we get the correct result.

Here's a small blend file with the setup
http://www.pasteall.org/blend/19064

Is this a blender limitation? Or are we doing it wrong[1]? :)

[1]:
http://src.luxrender.net/luxblend25/file/5eed3263787e/src/luxrender/export/__init__.py#l274


Cheers
- Asbjr?n
Brecht Van Lommel
2013-01-27 16:45:55 UTC
Permalink
Hi,
Post by Asbjørn
seems there's some issue when an object has a motion path, and the
motion path has a driver on the "evaluation time", and the object has no
keyframes. Then the transformation matrices are not updated it seems. If
the object has a keyframe, we get the correct result.
Here's a small blend file with the setup
http://www.pasteall.org/blend/19064
Is this a blender limitation? Or are we doing it wrong[1]? :)
http://src.luxrender.net/luxblend25/file/5eed3263787e/src/luxrender/export/__init__.py#l274
One issue I see here is that Blender basically assume subframe to be
in range [0,1[ but doesn't enforce this. I've fixed this in svn now,
so that it will work with this script.

The other issue is the way the driver is set up here. It's driving the
value with scene.frame_current which is an integer and does not take
subframes into account. There is a built in variable "frame" for
drivers that can be used instead of the custom "var" here to get
proper subframe motion.

Further, frame_set() is an expensive call, you should not be doing
this per object, but rather do it once and then get the animation for
all objects. This is because of complex dependencies that can exist
between objects, it's not possible to move one only object in time and
so the entire scene needs to be reevaluated. For simple scenes it may
not be noticeable but for more complex ones it's a problem.

Brecht.
Asbjørn
2013-01-27 19:55:55 UTC
Permalink
Post by Brecht Van Lommel
One issue I see here is that Blender basically assume subframe to be
in range [0,1[ but doesn't enforce this. I've fixed this in svn now,
so that it will work with this script.
Alright, the docs did specify "float in [0, 1]" so I assumed it was
cool. Thanks for fixing this.
Post by Brecht Van Lommel
The other issue is the way the driver is set up here. It's driving the
value with scene.frame_current which is an integer and does not take
subframes into account. There is a built in variable "frame" for
drivers that can be used instead of the custom "var" here to get
proper subframe motion.
Ok, I guessed the issue was related to integers. I'll pass this on, thanks.
Post by Brecht Van Lommel
Further, frame_set() is an expensive call, you should not be doing
this per object, but rather do it once and then get the animation for
all objects.
I figured it was expensive, however I'm not really intimate with
luxblend25, so I'll have to take some time to figure out how to refactor it.

Cheers
- Asbj?rn
Asbjørn
2013-03-11 19:05:53 UTC
Permalink
Post by Campbell Barton
Better use scene.frame_set(frame, subframe), then collect object
matrix data for motion blur.
Between 2.65 and 2.66 the behavior of frame_set() changed. In 2.66 if I
call scene.frame_set(n, 1.0) then scene.frame_current returns n+1. Is
this expected behavior? In 2.65 it returns n, which is what I'd expect
given the wording in the documentation.

Just curious as it was somewhat unexpected. It's not an issue, but
perhaps docs could be updated to reflect this.

Cheers
- Asbj?rn

Loading...