vispy / vispy

Main repository for Vispy
http://vispy.org
Other
3.29k stars 617 forks source link

InstanceMesh picking #2615

Open lej0hn opened 1 month ago

lej0hn commented 1 month ago

Hi everyone! I am trying to figure out a way to pick (by clicking on) a specific InstancedMesh. I've worked out an example based on a simplification of existing examples, which uses visual_at to get the InstanceMesh clicked. However, this seems to return the object of InstancedMesh but I can not figure out a way to get which instance of that InstanceMesh it is. Is there a way to accomplish that?


# -*- coding: utf-8 -*-
# vispy: gallery 30
# -----------------------------------------------------------------------------
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
# -----------------------------------------------------------------------------
"""
Instanced Mesh Visual
=====================

Show usage of the InstancedMesh visual and its filters.
"""
from vispy.scene import transforms

from itertools import cycle
import argparse

import numpy as np
from scipy.spatial.transform import Rotation
from vispy import app, scene, use, color
from vispy.io import imread, load_data_file, read_mesh
from vispy.scene.visuals import InstancedMesh, Mesh
from vispy.visuals.filters import InstancedShadingFilter, WireframeFilter, TextureFilter, ShadingFilter, FacePickingFilter
# needed for instanced rendering to work
use(gl='gl+')

mesh_path = load_data_file('spot/spot.obj.gz')
texture_path = load_data_file('spot/spot.png')

vertices, faces, normals, texcoords = read_mesh(mesh_path)
vertices_d, faces_d, normals_d, texcoords_d = read_mesh(mesh_path)

texture = np.flipud(imread(texture_path))

canvas = scene.SceneCanvas(keys='interactive', bgcolor='white', show=True)
view = canvas.central_widget.add_view()

view.camera = 'arcball'
view.camera.depth_value = 10 * (vertices.max() - vertices.min())

n_instances = 8
n_instances_d = 8

# instance_colors = np.random.rand(n_instances, 3).astype(np.float32)
instance_colors = np.array(
    [color.Color("#%06x" % np.random.randint(0, 0xFFFFFF)).rgba for _ in range(n_instances)]
)
instance_positions = ((np.random.rand(n_instances, 3) - 0.5) ).astype(np.float32)
face_colors = np.random.rand(len(faces), 3)
instance_transforms = Rotation.random(n_instances).as_matrix().astype(np.float32)

# Create a colored `MeshVisual`.
mesh = InstancedMesh(
    vertices,
    faces,
    instance_colors=instance_colors,
    face_colors=face_colors,
    instance_positions=instance_positions,
    instance_transforms=instance_transforms,
    parent=view.scene,
)

#Creating a second InstancedMesh
mesh_d = InstancedMesh(
    vertices_d,
    faces_d,
    instance_colors=instance_colors,
    face_colors=face_colors,
    instance_positions=instance_positions,
    instance_transforms=instance_transforms,
    parent=view.scene,
)
mesh_d.transform = transforms.MatrixTransform()
mesh_d.transform.rotate(90, (1, 0, 0))

wireframe_filter = WireframeFilter(width=1)
mesh.attach(wireframe_filter)

mesh_d.interactive = True
mesh.interactive = True

shading_cycle = cycle(['flat', None, 'smooth'])
color_cycle = cycle([None, instance_colors])
face_color_cycle = cycle([None, face_colors])

@canvas.events.mouse_press.connect
def mouse_press(event):

    visual = canvas.visual_at(event.pos)
    print(visual)

if __name__ == "__main__":
    app.run()

Thanks,

lej0hn commented 1 month ago

cc: @sanjayankur31