平移相机推车的有效方法
Efficient way to translate a camera dolly
我目前有一个 VR 相机连接到一个小车上,以便进行平移和旋转。
我正在尝试根据游戏手柄输入相对于相机(链接到 VR 耳机)的方向平移小车。
我也在努力避免让摄影车相对于相机上下倾斜。
我当前的代码如下所示:
this.camerDirectionVector = new THREE.Vector3()
this.camera.getWorldDirection(this.cameraDirectionVector)
this.moveVec.y = 0
this.dolly.translateOnAxis(this.cameraDirectionVector, this.gamepad.axes[0] * this.moveSpeed)
这非常适合在相机指向的方向(减去 y 旋转)移动小车。
我想不通的是如何根据额外的游戏手柄输入相对于相机平移推车 "left and right"。
根据问题的评论,我想我明白了。如果我不这样做,请发表评论,我会更新此答案。
我的理解是,您希望能够相对于 相机 左右移动,而不改变移动车的 up
方向。
这实际上比听起来更容易,而且更容易,因为您已经习惯了沿轴平移。
首先,了解相机有自己的空间参照系,它位于原点,+Y up
方向,向下看 -Z 轴。考虑到这一点,您已经知道 "left" 和 "right" 轴:-X (-1, 0, 0
) 和 +X (1, 0, 0
).
但是相机(尤其是在 VR 中)可能不会在世界中很好地对齐 space,因此您需要将这些漂亮的统一轴转换为世界轴。 Three.js 使用 Object3D.localToWorld
.
使这变得非常容易
(注:Object3D.localToWorld
对输入有破坏性Vector3
.)
这是一个获取世界对齐左轴的函数:
const getLeftWorld = (function(){
const localLeft = new THREE.Vector3(-1, 0, 0);
return function(vectorRef){ // you can give it a vector to overwrite
let out = vectorRef || new THREE.Vector3();
out.copy(localLeft);
camera.localToWorld(out);
return out;
};
))();
您可以为 "right" 轴创建一个类似的函数。
有了新的与世界对齐的左轴,您可以使用控制器输入给出的 "speed" 沿它平移小车。平移不会改变推车的倾斜度,尽管它 可能 会改变高度,具体取决于计算时相机的倾斜方式(但您可以将 y
像以前一样的组件,如果你愿意的话)。
这是最适合我的解决方案。我从这里的 Brian Peiris 代码中改编了它:https://github.com/brianpeiris/three-firstperson-vr-controls/blob/master/FirstPersonVRControls.js#L125
// Create a dolly
this.dolly = new THREE.Group()
this.dolly.add(this.camera)
this.scene.add(this.dolly)
// Some variables for movement translations
this.dummy = new THREE.Object3D()
this.dummyDirection = new THREE.Vector3()
this.ZAXIS = new THREE.Vector3(0, 0, 1)
this.moveSpeed = 0.075
// Get controller stick positions
const stickForwardBack = this.leftStick[3]
const stickLeftRight = this.leftStick[2]
// In THREE.js when using the WebXR API, the camera rotation will not update to match the headset orientation.
// You'll need to get pose information from the XRSession or get the xr camera using the following method.
const xrCamera = globals.renderer.xr.getCamera(this.camera)
this.dummy.position.set(0, 0, 0)
this.dummy.quaternion.copy(xrCamera.quaternion)
this.collapseY(this.dummy.quaternion)
// Translate the dummy object forwards/backwards left/right relative to the direction the camera is facing
this.dummy.translateZ(stickForwardBack * this.moveSpeed)
this.dummy.translateX(stickLeftRight * this.moveSpeed)
// Add the dummy position to the dolly
this.dolly.position.add(this.dummy.position)
// Flatten out up and down rotation
collapseY(quaternion) {
this.dummyDirection.set(0, 0, 1)
this.dummyDirection.applyQuaternion(quaternion)
this.dummyDirection.y = 0
this.dummyDirection.normalize()
quaternion.setFromUnitVectors(this.ZAXIS, this.dummyDirection)
}
我目前有一个 VR 相机连接到一个小车上,以便进行平移和旋转。 我正在尝试根据游戏手柄输入相对于相机(链接到 VR 耳机)的方向平移小车。
我也在努力避免让摄影车相对于相机上下倾斜。
我当前的代码如下所示:
this.camerDirectionVector = new THREE.Vector3()
this.camera.getWorldDirection(this.cameraDirectionVector)
this.moveVec.y = 0
this.dolly.translateOnAxis(this.cameraDirectionVector, this.gamepad.axes[0] * this.moveSpeed)
这非常适合在相机指向的方向(减去 y 旋转)移动小车。
我想不通的是如何根据额外的游戏手柄输入相对于相机平移推车 "left and right"。
根据问题的评论,我想我明白了。如果我不这样做,请发表评论,我会更新此答案。
我的理解是,您希望能够相对于 相机 左右移动,而不改变移动车的 up
方向。
这实际上比听起来更容易,而且更容易,因为您已经习惯了沿轴平移。
首先,了解相机有自己的空间参照系,它位于原点,+Y up
方向,向下看 -Z 轴。考虑到这一点,您已经知道 "left" 和 "right" 轴:-X (-1, 0, 0
) 和 +X (1, 0, 0
).
但是相机(尤其是在 VR 中)可能不会在世界中很好地对齐 space,因此您需要将这些漂亮的统一轴转换为世界轴。 Three.js 使用 Object3D.localToWorld
.
(注:Object3D.localToWorld
对输入有破坏性Vector3
.)
这是一个获取世界对齐左轴的函数:
const getLeftWorld = (function(){
const localLeft = new THREE.Vector3(-1, 0, 0);
return function(vectorRef){ // you can give it a vector to overwrite
let out = vectorRef || new THREE.Vector3();
out.copy(localLeft);
camera.localToWorld(out);
return out;
};
))();
您可以为 "right" 轴创建一个类似的函数。
有了新的与世界对齐的左轴,您可以使用控制器输入给出的 "speed" 沿它平移小车。平移不会改变推车的倾斜度,尽管它 可能 会改变高度,具体取决于计算时相机的倾斜方式(但您可以将 y
像以前一样的组件,如果你愿意的话)。
这是最适合我的解决方案。我从这里的 Brian Peiris 代码中改编了它:https://github.com/brianpeiris/three-firstperson-vr-controls/blob/master/FirstPersonVRControls.js#L125
// Create a dolly
this.dolly = new THREE.Group()
this.dolly.add(this.camera)
this.scene.add(this.dolly)
// Some variables for movement translations
this.dummy = new THREE.Object3D()
this.dummyDirection = new THREE.Vector3()
this.ZAXIS = new THREE.Vector3(0, 0, 1)
this.moveSpeed = 0.075
// Get controller stick positions
const stickForwardBack = this.leftStick[3]
const stickLeftRight = this.leftStick[2]
// In THREE.js when using the WebXR API, the camera rotation will not update to match the headset orientation.
// You'll need to get pose information from the XRSession or get the xr camera using the following method.
const xrCamera = globals.renderer.xr.getCamera(this.camera)
this.dummy.position.set(0, 0, 0)
this.dummy.quaternion.copy(xrCamera.quaternion)
this.collapseY(this.dummy.quaternion)
// Translate the dummy object forwards/backwards left/right relative to the direction the camera is facing
this.dummy.translateZ(stickForwardBack * this.moveSpeed)
this.dummy.translateX(stickLeftRight * this.moveSpeed)
// Add the dummy position to the dolly
this.dolly.position.add(this.dummy.position)
// Flatten out up and down rotation
collapseY(quaternion) {
this.dummyDirection.set(0, 0, 1)
this.dummyDirection.applyQuaternion(quaternion)
this.dummyDirection.y = 0
this.dummyDirection.normalize()
quaternion.setFromUnitVectors(this.ZAXIS, this.dummyDirection)
}