Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animate multiple objects simultaneously #262

Open
Boomer91 opened this issue Apr 19, 2019 · 12 comments
Open

Animate multiple objects simultaneously #262

Boomer91 opened this issue Apr 19, 2019 · 12 comments

Comments

@Boomer91
Copy link

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()
`

@vidartf
Copy link
Member

vidartf commented Apr 24, 2019

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 :)

@moorepants
Copy link

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
Copy link

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
Copy link

@vidartf
Copy link
Member

vidartf commented Nov 24, 2019

Did anyone try linking the time properties of the AnimationActions?

@vidartf
Copy link
Member

vidartf commented Nov 24, 2019

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)

@moorepants
Copy link

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

@moorepants
Copy link

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.

@vidartf
Copy link
Member

vidartf commented Nov 25, 2019

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

@renefritze
Copy link

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
Copy link

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).

@nikhilmishra000
Copy link

@vidartf's solution mostly works for me, except in this case with nested bodies: #405

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants