pythreejs
pythreejs copied to clipboard
Animate multiple objects simultaneously
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() `
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 :)
This seems like a very common need to animate multiple objects with different tracks. I'm struggling to find an answer to this too.
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.
I opened this question here too: https://stackoverflow.com/questions/59011697/how-do-i-animate-multiple-objects-simultaneously-with-each-having-a-different-ke
Did anyone try linking the time properties of the AnimationActions?
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)
Sweet, that works!! Thanks so much. I'll post the full working example and share.
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.
Here's some more docs for the name syntax: https://threejs.org/docs/#api/en/animation/PropertyBinding.parseTrackName
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?
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).