How to animate the translation of a sphere in vispy

66 Views Asked by At

I'm trying to visualize the translation of a sphere in Vispy without sucess.

I have used the code from Vispy Documentation examples - Draw a Sphere to generate the sphere and then tried to update its position using the vispy.visuals.transforms.STTransform method.

However, when I run the script presented below, the sphere only appears at the last position and I cannot see any animation.

import sys
import numpy as np
import vispy
from vispy import scene
from vispy.visuals.transforms import STTransform

canvas = scene.SceneCanvas(keys='interactive',
                           size=(800, 600),
                           show=True)

view = canvas.central_widget.add_view()
view.camera = 'arcball'
view.camera = 'turntable'

# Add grid
grid_3D = scene.visuals.GridLines(color="white",
                                  scale=(0.5, 0.5))
view.add(grid_3D)

# Add a 3D axis to keep us oriented
axis = scene.visuals.XYZAxis(parent=view.scene)

# Add a sphere
sphere1 = scene.visuals.Sphere(radius=0.5,
                               method='latitude',
                               parent=view.scene,
                               edge_color='black')

for _ in np.arange(0, 5, 0.5):
    sphere1.transform = STTransform(translate=[_, 0, 0])

view.camera.set_range(x=[-10, 10])

if __name__ == '__main__' and sys.flags.interactive == 0:
    canvas.app.run()

Thank you in advance for any help.

2

There are 2 best solutions below

0
djhoese On BEST ANSWER

This is a common mistake when dealing with GUIs and animations. Your visualization isn't drawn until the app is run and the canvas shown. By the time that happens your code has already iterated through your for loop and done all the updates you coded in. Not to mention they've happened as fast as your computer can process them because you don't have a delay between the updates. This speed is way too fast for you to see.

The solution is to do these updates over time and slow enough that you, the human, can see them. The easiest way to do this is to use a Timer. You can find examples of using timers in the realtime data tutorial here:

https://vispy.org/gallery/scene/#realtime-data-tutorial

I've also made a video series of these examples here:

https://www.youtube.com/playlist?list=PL2OQ8odJIDfPU67ML2k-ldvgtISoxJE8b

0
TMoover On

Based on @djhoese suggestion here's a very basic working example on how to animate the translation of a sphere.

import sys
import numpy as np
import vispy
from vispy import app, scene
from vispy.visuals.transforms import STTransform
from vispy.app import use_app, Timer
import time

# Generate sphere coordinates
nPoints = 20
pos = np.zeros((nPoints, 3))
for _ in range(0, nPoints, 1):
    pos[_, 0] = _

idx = 0

canvas = scene.SceneCanvas(keys='interactive',
                           bgcolor='white',
                           size=(800, 600),
                           show=True)

view = canvas.central_widget.add_view()
view.camera = 'turntable'

# Add grid
grid_3D = scene.visuals.GridLines(color="white",
                                  scale=(0.5, 0.5))
view.add(grid_3D)

# Add a 3D axis to keep us oriented
axis = scene.visuals.XYZAxis(parent=view.scene)

# Add a sphere
sphere1 = scene.visuals.Sphere(radius=0.5,
                               method='latitude',
                               parent=view.scene,
                               edge_color='black')

def update(ev):
    global pos, idx, nPoints
    if idx < nPoints:
        sphere1.transform = STTransform(translate=[pos[idx, 0],
                                                   pos[idx, 1],
                                                   pos[idx, 2]])
        idx += 1

view.camera.set_range(x=[-5, 25])

timer = app.Timer()
timer.connect(update)
timer.start(0.4)

if __name__ == '__main__' and sys.flags.interactive == 0:
    app.run()

Kind regards. Ivo