ThreeJS 轨道控制设定目标,无需观察 [英] ThreeJS orbit controls set target without lookAt

查看:84
本文介绍了ThreeJS 轨道控制设定目标,无需观察的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作用于构建模型的 3D 查看器.我们已经加载了模型并试图与模型进行某种交互.因此,我们使用 OrbiControls 来旋转、平移和缩放模型.

I am trying to make a 3D viewer for building models. We have the model loaded and are trying to make some sort of interaction with the model. Therefor we are using OrbiControls for rotating, panning and zooming the model.

我们希望在查看器中具有这样一种行为,即当用户单击并拖动(从而旋转)时,旋转中心位于用户单击的建筑物的位置.

We want to have the behaviour in the viewer that when a user clicks and drags (thus rotating), the rotation center is at the point of the building where the user clicks.

我认为这样更改 OrbitControl 的目标是明智的:

I thought I was wise by changing the target of the OrbitControl as such:

control.target.set(newX, newY, newZ);

然而,我在 OrbitControl.js 文件的源代码中发现,当控件更新时,

However, what I found in the source of the OrbitControl.js file, is that when the control updates, the

camera.lookAt() 

函数被调用,导致相机跳到一个新的位置.

function is called, which results the camera jumping to a new position.

有什么办法可以解决这个问题吗?我已经尝试了几个小时,但似乎没有任何效果.

Is there any way to get around this? I've been trying for a few hours now, and nothing seemed to be working.

尝试更改 target0,然后在控件上调用 reset().还尝试将相机改回旧位置(这可能是这样做的,但我可能尝试得不好.

Tried changing target0, then calling reset() on the control. Also tried changing the camera back to the old position (this might be how its done, but I might have tried it poorly.

推荐答案

有什么办法可以解决这个问题吗?

简短的回答是是的,但它没有使用标准版本的 OrbitControls.js".

继续阅读我的详细推理......

Read on for my detailed reasoning....

我刚刚花了一些时间查看 OrbitControls.js (r87) 的源代码,考虑实现增强功能的想法,该增强功能将允许您提供一个可选的第二点,它将用作相机目标.

I have just spent some time looking at the source code of OrbitControls.js (r87) considering the idea of implementing an enhancement that would allow you to provide an optional 2nd point that it would use as the camera target.

但是,在探索了代码之后,我认为将其添加到标准公共版本中将是一个不好的功能.OrbitControls 有许多功能,例如限制视角、最小和最大旋转以及假设相机和轨道中心相同的推车距离的能力.如果有一个选项 2nd camera tagret,这些都需要修改为使用轨道中心或相机目标,或者有一个可配置的参数来切换它使用的那个.这将增加数百行额外的代码,使其更难理解,并且所有这些都是非常小众的功能.

However after exploring the code I think this would be a bad feature to add to the standard public version. There are many features of OrbitControls such as the ability to limit viewing angle, min and max rotation and dolly distance that assume camera and orbit center are the same. If there was an option 2nd camera tagret these would all need to be modified to use either the center of orbit or the camera target or to have a configurable parameter that switches which one it uses. That would add hundreds of extra lines of code, making it harder to understand and all for a very niche feature.

所以... 解决方案:

因为你正在构建一个技术工具,我怀疑你不关心有限的视角、距离或旋转所以如果我是你,我会把 OrbitControls.js 复制到你的项目中,重命名它到 OrbitControls_customised.js 并进行您需要的更改:

Because you are building a technical tool, I suspect you don't care about limited viewing angle, distance or rotation so if I were you I would copy OrbitControls.js into your project, rename it to OrbitControls_customised.js and make the changes you need:

this.target 下方添加 2 个新参数,名为 this.cameraTargetthis.coupleCenters

Add 2 new parameters below this.target called this.cameraTarget and this.coupleCenters

// "target" sets the location of focus, where the object orbits around
this.target = new THREE.Vector3();

// "cameraTarget" is where the camera is looking (by default the same as target
this.cameraTarget = new THREE.Vector3();

// Whether the camera should be locked to the orbit center
this.coupleCenters = true;

在它指示相机看中心的那条线上......

And on the line where it instructs the camera to look at the center...

scope.object.lookAt( scope.target );

...更改它,使其仅在 coupleCenters 为真时才更新相机...

...change it so it only updates the camera when coupleCenters is true...

if( scope.coupleCenters ){
    scope.cameraTarget = scope.target;
}
scope.object.lookAt( scope.cameraTarget );

现在,通过这些更改,您可以放置​​一个使用 RayCasting 找到对象上的点,将 controls.decoupleCenters 设置为 false 并将 controls.target 设置为相交/光线投射的交叉点.然后是一个 onMouseUp 事件,将 controls.target 设置回 controls.cameraTarget 以使其正常运行.

Now, with those changes made, you can put an onMouseDown event that uses RayCasting to find the point on your object, sets controls.decoupleCenters to false and sets controls.target to the intersecting/crossing point of the raycast. Then an onMouseUp event that sets the controls.target back to the controls.cameraTarget to allow it to behave as normal.

我希望这能回答您的问题,并为您提供一些粗略的工作路线图.

I hope that answers your question and gives you some rough road-map to work towards.

这篇关于ThreeJS 轨道控制设定目标,无需观察的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆