pythreejs icon indicating copy to clipboard operation
pythreejs copied to clipboard

CloneArray children empty

Open gmonet opened this issue 6 years ago • 5 comments

Hi! I'm trying to visualize an atomic structure composed of about 1000 atoms with pythreejs. Knowing that I model atoms by the same mesh (a simple sphere), I tried to use the InstancedMesh class of three.js but there is no such equivalent in pythreejs. By adding the spheres one by one, it takes far too long (see #154). So I used CloneArray which is, indeed, much more efficient.

import pythreejs as tjs

view_width = 200
view_height = 200

camera = tjs.PerspectiveCamera(position=[10, 6, 10], aspect=view_width/view_height)
key_light = tjs.DirectionalLight(position=[0, 10, 10])
ambient_light = tjs.AmbientLight()
controller = tjs.OrbitControls(controlling=camera)

pos = [(0,0,0),(2,0,0),(4,0,0)]
sphere = tjs.SphereBufferGeometry()
atom = tjs.Mesh(sphere, tjs.MeshStandardMaterial())
atoms = tjs.CloneArray(atom, positions=pos, merge=False)

scn = tjs.Scene(children=[camera, key_light, ambient_light, atoms])
renderer = tjs.Renderer(camera=camera, scene=scn, controls=[controller],
                    width=view_width, height=view_height)

renderer

image

However, I can no longer access the spheres individually. For example, I can no longer change their position. Changing the "positions" attribute creates clones:

atoms.positions = [(0,3,0),(2,3,0),(4,3,0)]
renderer

image

And the CloneArray object has no children contrary to what is indicated here:

atoms.children

()

Is there a bug or did I miss something? If you have another idea to implement my problem, I'm a taker! Thanks!

gmonet avatar Nov 26 '19 09:11 gmonet

Thanks for the report!

For context, CloneArray was made as a workaround before InstancedMesh was a thing (that seems to have been introduced in r109 of threejs). The CloneArray has no children synced back to the kernel, as that would defeat the performance gains of the workaround (ref #154).

That the original clones are kept when updating the positions is likely a bug. This line is supposed to remove the old children, but I assume that might not be the right way?

vidartf avatar Nov 26 '19 16:11 vidartf

Actually, it seems the clearing logic was never implemented:

https://github.com/jupyter-widgets/pythreejs/blob/0ee2ca3034d617a06be5a8e9cb0e0a1ec60c257d/js/src/objects/CloneArray.js#L21-L23

vidartf avatar Nov 26 '19 16:11 vidartf

Thank you for your fast answer ! I see now where the problem is. Then I will try to make a custom widget from your blackbox object. Thank again 👍

gmonet avatar Nov 27 '19 09:11 gmonet

It would be better if someone did a PR that implemented the clear function though.

vidartf avatar Nov 27 '19 11:11 vidartf

Adding InstancedMesh to pythreejs would also be super useful!

@gmonet and @vidartf: Any ideas how I could make 5000 little spheres that each have a different color?

I was using a Points geometry which was working for me until now, but I need something more flexible with different shapes, and a geometry that is not always facing the camera. I'd managed to make points of various shapes using textures, such as in this example, but it was more of a quick fix.

And once you created the spheres, is it then possible to modify their colors, just like it's possible to change their positions?

Basically, I think this example is pretty close (https://threejs.org/examples/?q=instan#webgl_buffergeometry_instancing) but I can't seem to get this to work with pythreejs.

Many thanks!

nvaytet avatar Feb 10 '20 10:02 nvaytet