ThreeJS相机的lookAt()没有效果,我做错了什么吗?

39
在Three.js中,我想让相机指向3D空间中的一个点。 为此,我尝试使用camera.lookAt函数,像这样:
camera.lookAt(new THREE.Vector3(-100,-100,0));

然而,我发现这个调用完全没有任何效果。它根本什么也不做。我尝试更改向量中的数字,但屏幕上始终显示相同的内容,而实际上应该发生变化。

现在我刚刚发现,如果我从代码中删除THREE.TrackballControls,那么camera.lookAt()会按照预期工作。我在使用THREE.TrackballControls时出了什么问题吗?以下是初始化它们的方式:

    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 ]*/

然后在我的渲染函数中,我执行:

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

Three.js的文档相当匮乏,所以我想在这里问一下。 我做错了什么吗?


展示更多的代码。看一下这个简单的示例:http://jsfiddle.net/TE5bM/ - Juan Mellado
你的程序中有一个更新循环,用于重新渲染场景吗?听起来好像你没有进行更新或渲染。 - George Profenza
@Juan George:在设置场景之前,在任何东西被渲染之前,我正在调用.lookAt(),所以我的调用应该有影响。然而,我想我刚刚找到了问题所在; 我的代码中有THREE.TrackballControls,我认为这会干扰我告诉.lookAt()的内容,因为当我删除THREE.TrackballControls时,.lookAt()函数就像它应该做的那样工作了。我在使用THREE.TrackballControls方面做错了什么? - houbysoft
@GeorgeProfenza Juan:我也在这里放置了代码:https://github.com/houbysoft/js-pdb/blob/master/js-pdb.js,相应的HTML在https://github.com/houbysoft/js-pdb/blob/master/index.html。 - houbysoft
你正在使用最新版本吗?更新日志上有一些内容。 - atilkan
@emrah: 是的,我有 http://mrdoob.github.com/three.js/build/Three.js - houbysoft
6个回答

55

查看 THREE.TrackballControls 的源代码后,我发现只需将trackballControls.target设置为THREE.Vector3想要看的位置,然后重新渲染场景即可使相机看向目标位置。


2
谢谢!我已经在谷歌上搜索了好久,终于找到答案了! - Wang Liang
3
正确答案!将controls.target设置为new THREE.Vector3(1500, 500, 0);其中的1500、500和0是我想要观察的目标位置。 - theprof
2
是的,这正是我面临的问题,并为此发布了一个新问题在这里。在我的情况下,通过将THREE.OrbitControls的源代码手动更改为将其target属性初始化为传递给camera.lookAt()的相同向量是不可行的,我宁愿想出一个反函数,这样我就可以编写类似于target = getLookAtVectorFor(camera)的东西,而无需每次更改相机的lookAt向量时更改OrbitControls.js的源代码。 - Andrea Aloi
我也是,搜了两天才找到结果!想改变相机的视角,但一直没有结果,直到看到这个答案。 - lhrec_106
通过修订版88 R88,问题已经解决。 - dcromley
现在是2023年10月,我正在使用v0.157.0版本。但是如何让相机和OrbitControls一起工作仍然是一个谜。一旦给orbitControls分配了一个目标,它实际上就停止工作了... - undefined

12

请注意...似乎拥有THREE.TrackballControls或THREE.OrbitControls会覆盖camera.lookAt函数,因为在实例化控件的时候需要传递相机。您可能希望摆脱控件,然后执行camera.lookAt()或以其他方式对相机进行缓动,以验证控件对您的相机产生了覆盖效果。我搜索了一段时间为什么camera.lookat()似乎没有任何效果。


9

在我看来,我们不应该改动原始代码。我找到了一种方法以实现查看任何特定点的目标。 在声明了你的"控制变量"之后,只需执行这两行代码:

// 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);

请记住,这将把焦点中心切换到您的新目标。换句话说,您的新目标将是相机所有旋转的中心。由于您习惯于默认中心来操纵相机,因此某些部分可能很难观察。尝试尽可能缩放,您会明白我的意思。希望这可以帮到您。

这个答案对我很有帮助。如果你的可视化中有 OrbitControlsTrackballControls 等控件,你应该使用 controls.target 属性而不是 camera.lookAt - ty.

2
我找到了解决方法。为了防止THREE.TrackballControlsTHREE.OrbitControls在初始化时覆盖camera.lookAt,你需要改变设置控制器的target属性的那一行代码,使其等于camera.position向量与camera.getWorldDirection()向量之和,而不是使用new THREE.Vector3()(默认为(0,0,0))。
所以,对于THREE.TrackballControls,将第39行改为:
this.target = new THREE.Vector3().addVectors(/*new line for readability*/
    object.position, object.getWorldDirection());

同样适用于THREE.OrbitControls,在第36行。 我实际上还没有在TrackballControls.js上测试过,但在OrbitControls.js上是有效的。希望这有所帮助。


如果您不想覆盖源代码,可以在渲染循环中更新控件目标。 - Grant Vinson

1
这里有一种替代方案:创建一个0维度的对象(例如立方体)。
var cameraTarget = new THREE.Mesh( new THREE.CubeGeometry(0,0,0));

在渲染函数中,将相机的lookAt设置为cameraTarget的位置。
function render() {
    camera.lookAt( cameraTarget.position );
    renderer.render( scene, camera );
}

然后只需根据您的意愿移动cameraTarget。

0

我遇到了同样的问题,并且通过使用OrbitControls.target使其正常工作。在声明控制器后,以下是我的操作步骤。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接