jupyter-widgets / pythreejs

A Jupyter - Three.js bridge
https://pythreejs.readthedocs.io
Other
936 stars 187 forks source link

Picker example does not work when I change geometry #248

Closed nickc92 closed 5 years ago

nickc92 commented 5 years ago

The Picker example uses a SurfaceGeometry. I would like to use a plain Geometry, where I specify a polyhedron via its vertices and faces, but when I modified the example to use a plain Geometry, it no longer worked. I tried a DodecahedronGeometry for the heck of it, and that seemed to work fine. Is there something I'm not getting?

vidartf commented 5 years ago

Hi @nickc92! Thanks for your feedback. Would you mind sharing how you specify the Geometry? Does it render correctly but with a broken picker? Are there any errors/warnings in the browser developer console?

nickc92 commented 5 years ago

I basically cut and pasted the example of an indexed geometry (a cube with different color vertices) from the Examples.ipynb notebook into the 'Clickable Surface' example in that same notebook. What happens is that the cube renders, but the picker seems to do nothing. I've pasted the code below. Fortunately, I found that the BufferGeometry seemed to work with Picker, and I was able to accomplish what I wanted to. But nonetheless, plain Geometry doesn't seem to work for me.

Code:

view_width = 600
view_height = 400

vertices = [
    [0, 0, 0],
    [0, 0, 1],
    [0, 1, 0],
    [0, 1, 1],
    [1, 0, 0],
    [1, 0, 1],
    [1, 1, 0],
    [1, 1, 1]
]

faces = [
    [0, 1, 3],
    [0, 3, 2],
    [0, 2, 4],
    [2, 6, 4],
    [0, 4, 1],
    [1, 4, 5],
    [2, 3, 6],
    [3, 7, 6],
    [1, 5, 3],
    [3, 5, 7],
    [4, 6, 5],
    [5, 6, 7]
]

vertexcolors = ['#000000', '#0000ff', '#00ff00', '#ff0000',
                '#00ffff', '#ff00ff', '#ffff00', '#ffffff']

# Map the vertex colors into the 'color' slot of the faces
faces = [f + [None, [vertexcolors[i] for i in f], None] for f in faces]

cubeGeometry = Geometry(vertices=vertices,faces=faces, colors=vertexcolors)

#cubeGeometry = Geometry(vertices=vertices,
#    faces=faces,
#    colors=vertexcolors)
# Calculate normals per face, for nice crisp edges:
cubeGeometry.exec_three_obj_method('computeFaceNormals')

surf = Mesh(geometry=cubeGeometry,
            material=MeshLambertMaterial(map=height_texture(z[::-1], 'YlGnBu_r')))

# Set up picking bojects:
hover_point = Mesh(geometry=SphereGeometry(radius=0.05),
                   material=MeshLambertMaterial(color='hotpink'))

click_picker = Picker(controlling=surf, event='dblclick')
hover_picker = Picker(controlling=surf, event='mousemove')

# Set up scene:
key_light = DirectionalLight(color='white', position=[3, 5, 1], intensity=0.4)
c = PerspectiveCamera(position=[0, 3, 3], up=[0, 0, 1], aspect=view_width / view_height,
                      children=[key_light])

scene = Scene(children=[surf, c, hover_point, AmbientLight(intensity=0.8)])

renderer = Renderer(camera=c, scene=scene,
                    width=view_width, height=view_height,
                    controls=[OrbitControls(controlling=c), click_picker, hover_picker])

# Set up picking responses:
# Add a new marker when double-clicking:
out = Output()
def f(change):
    value = change['new']
    with out:
        print('Clicked on %s' % (value,))
    point = Mesh(geometry=SphereGeometry(radius=0.05), 
                 material=MeshLambertMaterial(color='red'),
                 position=value)
    scene.add(point)

click_picker.observe(f, names=['point'])

# Have marker follow picker point:
link((hover_point, 'position'), (hover_picker, 'point'))

# Show picker point coordinates as a label:
h = HTML()
def g(change):
    h.value = 'Green point at (%.3f, %.3f, %.3f)' % tuple(change['new'])
g({'new': hover_point.position})
hover_picker.observe(g, names=['point'])

display(VBox([h, renderer, out]))
vidartf commented 5 years ago

Sorry for the slow response here. Having looked at this a little closer, the error is an incorrect default value for the faceVertexUvs attribute of the Geometry class. A workaround for now is to set the value explicitly. In you example, running the following fixes the issue:

cubeGeometry.faceVertexUvs = [[]]