Closed chrisjsewell closed 1 year ago
Maybe this would be easier using the AxesHelper
object? Either way, I think you might be able to use ipywidgets.jslink
to link the two cameras. I think you would need to link the position
, quaternion
and zoom
traits.
Thanks for the reply.
Maybe this would be easier using the
AxesHelper
object?
I chose not to use this, so that I could have more control over properties like the line thickness. But, in essence, there shouldn't be any difference.
I think you would need to link the
position
,quaternion
andzoom
traits
Ah, I'd tried this before, but forgot to link the position
as well.
It's an improvement, but two issues:
zoom
trait). Really the world axes should remain a fixed size, as is the case for my current implementation. This is also an issue if you want to have different fov
for both cameras.Here's a toy example:
import numpy as np
import pythreejs as pjs
import ipywidgets
width = 400
height = 400
CANVAS_WIDTH = 100
CANVAS_HEIGHT = 100
CAM_DISTANCE = 150
scene = pjs.Scene()
camera = pjs.PerspectiveCamera(fov=20, aspect=width / height, near=1, far=10000)
camera.position = (camera.position[0], 150, 700)
controls = pjs.OrbitControls(controlling=camera, screenSpacePanning=True)
renderer = pjs.Renderer(
scene=scene, camera=camera, controls=[controls], width=width, height=height
)
cube = pjs.Mesh(
pjs.BoxGeometry(200, 200, 200, 1, 1, 1),
pjs.MeshBasicMaterial(color="red", wireframe=True),
)
scene.add(cube)
axes = pjs.AxesHelper(size=100)
scene.add(axes)
scene2 = pjs.Scene()
camera2 = pjs.PerspectiveCamera(
fov=20, aspect=CANVAS_WIDTH / CANVAS_HEIGHT, near=1, far=1000
)
renderer2 = pjs.Renderer(
scene=scene2, camera=camera2, width=CANVAS_WIDTH, height=CANVAS_HEIGHT
)
axes2 = pjs.AxesHelper(size=50)
scene2.add(axes2)
camera2.up = camera.up
# def align_axes(change=None):
# new_position = np.array(camera.position) - np.array(controls.target)
# new_position = CAM_DISTANCE * new_position / np.linalg.norm(new_position)
# camera2.position = new_position.tolist()
# camera2.lookAt(scene2.position)
# align_axes()
# camera.observe(align_axes, names="position")
# controls.observe(align_axes, names="target")
# scene2.observe(align_axes, names="position")
camera2.quaternion = camera.quaternion
camera2.position = camera.position
camera2.zoom = camera.zoom
ipywidgets.jslink((camera, 'quaternion'), (camera2, 'quaternion'))
ipywidgets.jslink((camera, 'zoom'), (camera2, 'zoom'))
ipywidgets.jslink((camera, 'position'), (camera2, 'position'))
ipywidgets.HBox([renderer, renderer2])
Closing as stale.
Hey guys, thanks for the great package. I've recently utilized it in my ase-notebook package, to create visualisations of atomic configurations.
As you can see in the tutorial here, I've created a simple GUI that contains an axes widget (top right) that syncs with the main scene on the python-side (you can use this Binder link to see it actually working).
I achieved this by adapting the threejs code here (see threejs.py#L406). As mentioned, the linking is currently done on the python-side, but ideally it would be on the javascript-side. Could you give me any pointer on how/if this could be hooked in to the render loop?