pythreejs icon indicating copy to clipboard operation
pythreejs copied to clipboard

Animate multiple objects simultaneously

Open Boomer91 opened this issue 6 years ago • 12 comments

Hi,

I have two Meshes and two AnimationActions. I would like to have a single animation control widget to control both animations/objects. How is this possible?

I guess something like syncWith() in Three js could be done.

Thanks!

` from pythreejs import *

scene = Scene() scene.add(AmbientLight()) camera = PerspectiveCamera(position=[5,5,5]) scene.add(SpotLight(position=[5,5,0])) renderer = Renderer(scene=scene, camera=camera, controls=[OrbitControls(controlling=camera)]) renderer

box1 = Mesh(geometry=BoxBufferGeometry(), material=MeshStandardMaterial(color='red')) scene.add(box1)

box2 = Mesh(geometry=BoxBufferGeometry(), material=MeshStandardMaterial(color='blue'), position=[0,0,2]) scene.add(box2)

track1 = NumberKeyframeTrack(name='.rotation[z]', times=[0,1], values=[0,1]) clip1 = AnimationClip(tracks=[track1]) animation1 = AnimationAction(mixer=AnimationMixer(), clip=clip1, localRoot=box1) animation1

track2 = NumberKeyframeTrack(name='.position[y]', times=[0,1], values=[0,-0.5]) clip2 = AnimationClip(tracks=[track2])

animation2 = AnimationAction(mixer=AnimationMixer(), clip=clip2, localRoot=box2) animation2

animation1.play() animation2.play() `

Boomer91 avatar Apr 19 '19 02:04 Boomer91

I'm not familiar enough with the threejs animation system to answer this. There might be a way to use the root / sub-indexing to do it, or you might be able to do it by using jslink on the time properties (there might be a 1-frame delay? not sure). Please let us know what you discover :)

vidartf avatar Apr 24 '19 09:04 vidartf

This seems like a very common need to animate multiple objects with different tracks. I'm struggling to find an answer to this too.

moorepants avatar Nov 23 '19 15:11 moorepants

This is the best thing I've found showing how one might do this in Three.js: https://stackoverflow.com/questions/57255000/how-to-animate-2-objects-with-2-different-animations-one-after-another-in-3-js

This jsfiddle, in particular: https://jsfiddle.net/6hzr0a9v/

It requires an event listener function so that when one animation plays the other plays too. I am not sure how to do this in pythreejs.

moorepants avatar Nov 23 '19 16:11 moorepants

I opened this question here too: https://stackoverflow.com/questions/59011697/how-do-i-animate-multiple-objects-simultaneously-with-each-having-a-different-ke

moorepants avatar Nov 23 '19 20:11 moorepants

Did anyone try linking the time properties of the AnimationActions?

vidartf avatar Nov 24 '19 11:11 vidartf

I had a go, and linking time wasn't straight forward (ideally it should be though). Hope to look into this later. For now, I would recommend taking advantage of the property naming options you have. E.g in the animation example notebook, if you add a name='sphere' keyword argument to the sphere constructor (and one for the cube as well), you can use this code:

sphere_color_track = ColorKeyframeTrack(name='scene/sphere.material.color',
    times=[0, 1], values=[1, 0, 0,  0, 0, 1])  # red to blue
cube_color_track = ColorKeyframeTrack(name='scene/cube.material.color',
    times=[0, 1], values=[0, 1, 0,  1, 1, 0])  # green to yellow

color_clip = AnimationClip(tracks=[sphere_color_track, cube_color_track], duration=1.5)
color_action = AnimationAction(AnimationMixer(scene), color_clip, scene)

vidartf avatar Nov 24 '19 11:11 vidartf

Sweet, that works!! Thanks so much. I'll post the full working example and share.

moorepants avatar Nov 24 '19 15:11 moorepants

Here is a working example:

https://gist.github.com/moorepants/c5ebb846499c4002744b8c101705015f

You'd need to:

conda install -c conda-forge pydy numpy matplotlib sympy

To have the dependencies.

moorepants avatar Nov 24 '19 16:11 moorepants

Here's some more docs for the name syntax: https://threejs.org/docs/#api/en/animation/PropertyBinding.parseTrackName

vidartf avatar Nov 25 '19 22:11 vidartf

While this track-name method generally works for me, I also need an additional slider to manually "scroll" through the animation. I did try to link the time attribute of the mixer to the slider value, but that seems one-way only. As in if I pause my play action, the slider moves. But if I move the slider the animation state does not change. Is that similar to what you observed in your failed attempt @vidartf? Any suggestions where to go from here?

renefritze avatar Jun 12 '20 12:06 renefritze

My current alternative solution is not using the animation system at all and switching meshes' visibility on slider value update. That's not working with static html representation though, since that's on the python kernel side. And I cannot properly jslink the slider property to the mesh.visibility since that would need some kind of value mapping, which ipywidgets does not support (afaik).

renefritze avatar Jul 02 '20 07:07 renefritze