I am trying to rotate a cube by pressing 'z' on my keyboard using vispy.
However, I would like that cube to rotate everytime I press 'z', which is not the case right now : it only rotates the first time I press it and then, when I press it again, nothing happens...
Here's the code.
from vispy import app, scene, geometry
import numpy as np
class MonCanvas(scene.SceneCanvas):
def on_key_press(self,event):
global cube1, cube2, c1data, c2data
if event.text == 'a':
c1data.set_face_colors([[0,0,1,1],[0,0,1,1],[0,1,0,1],[0,1,0,1],[1,1,1,1],[1,1,1,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,0,0,1],[1,0.5,0,1],[1,0.5,0,1]])
cube1.mesh_data_changed()
if event.text == 'z':
rot1 = scene.transforms.MatrixTransform()
rot1.rotate(90,(0,0,1))
cube2.transform = rot1
fenetre = MonCanvas(title="FenĂȘtre principale", size=(2000,1000), keys="interactive")
view = fenetre.central_widget.add_view()
view.camera = 'turntable'
view.camera.distance = 10
c1data = geometry.MeshData(vertices = np.array([[0.5,0.5,-0.5],[0.5,-0.5,-0.5],[-0.5,0.5,-0.5],[-0.5,-0.5,-0.5],[0.5,0.5,0.5],[0.5,-0.5,0.5],[-0.5,0.5,0.5],[-0.5,-0.5,0.5]]), edges = np.array([[0,1],[0,2],[0,4],[3,1],[3,2],[3,7],[5,1],[5,4],[5,7],[6,2],[6,4],[6,7]]), faces = np.array([[1,2,3],[0,1,2],[5,6,7],[4,5,6],[0,1,5],[0,5,4],[2,3,7],[2,7,6],[1,3,7],[1,7,5],[0,2,6],[0,6,4]]))
c1data.set_face_colors([[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1],[0,0,1,1]])
cube1 = scene.visuals.Mesh(meshdata = c1data)
view.add(cube1)
c2data = geometry.MeshData(vertices = np.array([[0.5,0.5,0.5],[0.5,-0.5,0.5],[-0.5,0.5,0.5],[-0.5,-0.5,0.5],[0.5,0.5,1.5],[0.5,-0.5,1.5],[-0.5,0.5,1.5],[-0.5,-0.5,1.5]]), edges = np.array([[0,1],[0,2],[0,4],[3,1],[3,2],[3,7],[5,1],[5,4],[5,7],[6,2],[6,4],[6,7]]), faces = np.array([[1,2,3],[0,1,2],[5,6,7],[4,5,6],[0,1,5],[0,5,4],[2,3,7],[2,7,6],[1,3,7],[1,7,5],[0,2,6],[0,6,4]]))
c2data.set_face_colors([[0,0,1,1],[0,0,1,1],[0,1,0,1],[0,1,0,1],[1,1,1,1],[1,1,1,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,0,0,1],[1,0.5,0,1],[1,0.5,0,1]])
cube2 = scene.visuals.Mesh(meshdata = c2data)
view.add(cube2)
fenetre.show()
app.run()
Thanks in advance for the help !
The transform is applied to the coordinates of the MeshVisual
inside the GPU. They do not modify the coordinates in-place inside the MeshVisual
. So when you run:
rot1 = scene.transforms.MatrixTransform()
rot1.rotate(90,(0,0,1))
cube2.transform = rot1
You are telling vispy and the GPU to take the coordinates for cube2
and rotate them 90 degrees before using/drawing them. Put another way, you are telling it what transformation to apply, but you aren't performing that transformation. So, you need to take that 90 and add 90 to it every time. So your series of rotations would be the X, then after the first z
they'd be X + 90, then X + 180, then X + 270, and so on. But there should be an easier way to do that...
It looks like you can do cube2.transform.rotate(90)
and that will modify the existing transform inplace. This has the added performance benefit of not creating a new transform object since doing that would require recompiling the shader code for every rotation which would be slower. So doing this works for me:
if event.text == 'z':
cube2.transform.rotate(90, (0, 0, 1))
But you need to make sure after you create cube2
to set the initial transform to a MatrixTransform otherwise cube2.transform
won't be a matrix transform that you can rotate:
cube2 = scene.visuals.Mesh(meshdata = c2data)
cube2.transform = scene.transforms.MatrixTransform()
view.add(cube2)