ThreeJS camera.lookAt() has no effect, is there something I'm doing wrong?

23,966

Solution 1

Looking at the source code of THREE.TrackballControls, I figured out that I can make the camera look where I want by setting trackballControls.target to the THREE.Vector3 I want it to look at, and then rerendering the scene.

Solution 2

Yes Please beware... It seems that having THREE.TrackballControls or THREE.OrbitControls seems to override the camera.lookAt function as your are passing in your camera when you instantiate an instance of the controls. You might want to get rid of the controls and then performing camera.lookAt() or tween your camera some other way to verify that the controls are having a overriding effect on your Camera. I googled for a while why camera.lookat() seemed to have no effect.

Solution 3

In my opinion, we are not supposed to mess with the original code. I found a way around to achieve the objective of looking at any particular point. After having declared your "control" variable, simply execute these two lines of code:

// Assuming you know how to set the camera and myCanvas variables
control = new THREE.OrbitControls(camera, myCanvas);

// Later in your code
control.object.position.set(camX, camY, camZ);
control.target = new THREE.Vector3(targetX, targetY, targetZ);

Keep in my mind that this will switch the center of the focus to your new target. In other words, your new target will be the center of all rotations of the camera. Some parts will be difficult to look at as you became familiar to manipulate the camera assuming the default center. Try zoom in as much as you can and you will have a sense of what I am saying Hope this help.

Solution 4

I figured it out. To prevent THREE.TrackballControls or THREE.OrbitControls from overriding camera.lookAt upon initialization, you need to change the line that sets the control's target property to equal the sum of the camera.position vector and the camera.getWorldDirection() vector, instead of how it's currently implemented using a new THREE.Vector3() (which defaults to (0, 0, 0)).

So, for THREE.TrackballControls, change line 39 to:

this.target = new THREE.Vector3().addVectors(/*new line for readability*/
    object.position, object.getWorldDirection());

Same goes for THREE.OrbitControls, on line 36. I actaully haven't tested it on TrackballControls.js but it does work on OrbitControls.js. Hope this helps.

Solution 5

Here's an alternative solution: create an object (i.e. cube) with 0 dimensions.

var cameraTarget = new THREE.Mesh( new THREE.CubeGeometry(0,0,0));

In the render function set the camera.lookAt to the position of the cameraTarget.

function render() {
    camera.lookAt( cameraTarget.position );
    renderer.render( scene, camera );
}

Then just move cameraTarget around as you wish.

Share:
23,966
houbysoft
Author by

houbysoft

Updated on May 30, 2020

Comments

  • houbysoft
    houbysoft almost 4 years

    In Three.js, I want a camera to be pointed at a point in 3D space.

    For this purpose, I tried using the camera.lookAt function like so:

    camera.lookAt(new THREE.Vector3(-100,-100,0));
    

    However, I found out that the call has no effect whatsoever. It just does nothing at all. I tried changing the numbers in the vector, and I always get the same look on screen, when it should be changing.

    I just found now that if I remove the THREE.TrackballControls I have in my code, the camera.lookAt() works as it should. Is there something wrong with how I use THREE.TrackballControls? This is how I initialize them:

        controls = new THREE.TrackballControls( camera, renderer.domElement );
    
        controls.rotateSpeed = 10.0;
        controls.zoomSpeed = 1.2;
        controls.panSpeed = 0.2;
    
        controls.noZoom = false;
        controls.noPan = false;
    
        controls.staticMoving = true;
        controls.dynamicDampingFactor = 1.0;
    
        var radius = 5;
        controls.minDistance = radius * 1.1;
        controls.maxDistance = radius * 100;
    
        controls.keys = [ 65, 83, 68 ]; // [ rotateKey, zoomKey, panKey ]*/
    

    And then in my render function I do:

    function render() {
      controls.update();
      renderer.render(scene, camera);
    }
    

    Documentation on Three.js is pretty scarce, so I thought I'd ask here. Am I doing something wrong?

  • Wang Liang
    Wang Liang over 10 years
    Thanks! I've googled for the answer for like forever, finally!
  • theprof
    theprof over 10 years
    Correct answer! Set controls.target = new THREE.Vector3(1500, 500, 0); where 1500, 500, 0 is my desired target to look at
  • Andrea Aloi
    Andrea Aloi over 9 years
    Yes, precisely the issue I'm facing and for which I posted a new quesiton here. In my case, manually changing the source code of THREE.OrbitControls by initializing its target property to the same vector passed to camera.lookAt() is not feasible, I'd rather come up with an inverse function so I could write something like target = getLookAtVectorFor(camera) and never have to change OrbitControls.js's source code every time I change the lookAt vector of my camera.
  • lhrec_106
    lhrec_106 about 8 years
    Same here, searched the result for literally two days! wanted to change the camera lookat but got no result until this answer.
  • ty.
    ty. about 5 years
    This answer helped me. If you have OrbitControls, TrackballControls, etc in your visualization, you should use the controls.target property instead of camera.lookAt.
  • dcromley
    dcromley almost 4 years
    With revision 88 R88 the issue went away.
  • Grant Vinson
    Grant Vinson about 3 years
    If you don't want to override the source code, you can update your controls target in the render loop