39

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?

houbysoft
  • 32,532
  • 24
  • 103
  • 156
  • Show us more code. Take at look at this simple sample: http://jsfiddle.net/TE5bM/ – Juan Mellado Apr 26 '12 at 09:08
  • do you have an update loop in which you re-render the scene ? it sounds like you're not updating/rendering. – George Profenza Apr 26 '12 at 10:54
  • @Juan George : I am calling .lookAt() when I set up the scene, before anything is rendered, so my call should have an effect. However, I think I just found the problem; I have THREE.TrackballControls in my code, which I think is interfering with what I tell .lookAt(), because when I remove the THREE.TrackballControls, the .lookAt() function works as it should. What am I doing wrong with THREE.TrackballControls? – houbysoft Apr 26 '12 at 12:26
  • @GeorgeProfenza Juan : I've also put up the code here : https://github.com/houbysoft/js-pdb/blob/master/js-pdb.js with the corresponding HTML at https://github.com/houbysoft/js-pdb/blob/master/index.html – houbysoft Apr 26 '12 at 12:47
  • are you using latest version. There is somethings on changelog. – atilkan Apr 26 '12 at 13:39
  • @emrah: Yes, I have http://mrdoob.github.com/three.js/build/Three.js – houbysoft Apr 26 '12 at 13:46

6 Answers6

55

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.

houbysoft
  • 32,532
  • 24
  • 103
  • 156
  • 2
    Thanks! I've googled for the answer for like forever, finally! – Wang Liang Nov 30 '13 at 06:02
  • 3
    Correct answer! Set controls.target = new THREE.Vector3(1500, 500, 0); where 1500, 500, 0 is my desired target to look at – theprof Jan 26 '14 at 17:26
  • 2
    Yes, precisely the issue I'm facing and for which I posted a new quesiton [here](http://stackoverflow.com/questions/26557252/inverse-of-camera-lookat). 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. – Andrea Aloi Oct 26 '14 at 15:06
  • Same here, searched the result for literally two days! wanted to change the camera lookat but got no result until this answer. – lhrec_106 May 06 '16 at 01:44
  • With revision 88 R88 the issue went away. – dcromley May 22 '20 at 21:47
12

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.

Leon
  • 5,701
  • 3
  • 38
  • 38
9

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.

  • This answer helped me. If you have `OrbitControls`, `TrackballControls`, etc in your visualization, you should use the `controls.target` property instead of `camera.lookAt`. – ty. Feb 08 '19 at 20:19
2

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.

Andrea Aloi
  • 971
  • 1
  • 17
  • 37
1

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.

sebjwallace
  • 753
  • 1
  • 8
  • 17
0

I ran into the same problem and was able to make it work by using OrbitControls.target. Below is what I did after declaring a controller.

    controller = new THREE.OrbitControls(camera, renderer.domElement);
    controller.addEventListener('change', renderer.domElement);
    controller.target = new THREE.Vector3(0, 1, 0);