jupyter-widgets / pythreejs

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

How to set properly camera target? #200

Closed KelSolaar closed 6 years ago

KelSolaar commented 6 years ago

Hi,

I'm trying to initialised my scene with the camera looking at a defined target and it does not really work as expected. Basically I need to initiate camera movement to have the view snap where it should have been at start. The following snippet reproduces the issue:

def renderer(width=960, height=540):
    grid = GridHelper(10, 20, '#000000', '#AAAAAA')

    ball = Mesh(geometry=SphereGeometry(radius=1), 
            material=MeshLambertMaterial(color='red'),
            position=[0, 1, 0])

    camera = PerspectiveCamera(
        position=[-3, 3, 3], fov=20, aspect=width / height)
    controls = OrbitControls(controlling=camera, target=(1 / 3, 0.5, 1 / 3))

    children = [grid, ball]

    scene = Scene(children=children)

    return Renderer(
        camera=camera,
        scene=scene,
        controls=[controls],
        width=width,
        height=height)

display(renderer())

Cheers,

Thomas

vidartf commented 6 years ago

I'm not currently at the computer, but you might need to add the camera to the scene (e.g. add it as a child). If this doesn't work, I can look at it again next week!

KelSolaar commented 6 years ago

Hi,

Having the scene as child does not change the result, (I actually had it in my full code). Could be a bug in Three.js itself.

Cheers,

vidartf commented 6 years ago

I finally got the time to look at this, and for me this works:

def renderer(width=960, height=540):
    grid = GridHelper(10, 20, '#000000', '#AAAAAA')

    ball = Mesh(geometry=SphereGeometry(radius=1), 
            material=MeshLambertMaterial(color='red'),
            position=[0, 1, 0])

    camera = PerspectiveCamera(
        position=[-3, 3, 3], fov=20, aspect=width / height)
-   controls = OrbitControls(controlling=camera, target=(1 / 3, 0.5, 1 / 3))
+   target = (1 / 3, 0.5, 1 / 3)
+   controls = OrbitControls(controlling=camera, target=target)
+   camera.lookAt(target)

    children = [grid, ball, camera]

    scene = Scene(children=children)

    return Renderer(
        camera=camera,
        scene=scene,
        controls=[controls],
        width=width,
        height=height)

display(renderer())

So at least you have a working example. Whether or not this is "expected" behavior is less clear. I don't think a controller should perform any actions on the camera before it is actually used (interacted with). Having it modify the camera in the constructor seems like it would be a surprising side-effect. What do you think?

KelSolaar commented 6 years ago

Looks good to me!

Thanks