2

我正在尝试在 THREE.js 中实现类似于 FlyControls 的东西,但我无法终生弄清楚如何正确旋转相机的俯仰角:

http://radiantjs.herokuapp.com/

按 A 或 Z 键“向上看/向下看”。因为该演示中的初始位置已经在偏航轴上旋转,所以俯仰基本上看起来像滚动。

我更新相机位置和旋转的代码如下:

/**
 * Updates this View. This is called once per frame.
 * 
 * @param {Number} delta The length of the frame (16 / milliseconds).
 */
update: function(delta) {

        if (this.velocity.length() < 0.15) {
            this.velocity.clear()
        } else {
            this.velocity.multiplyScalar(0.85 * delta)
        }

        if (this.velocity.x || this.velocity.y || this.velocity.z) {
            this.camera.position = this.camera.localToWorld(this.velocity.clone())
            this.camera.position.clamp(-16384, 16384)
        }

        if (this.rotation.length() < 0.15) {
            this.rotation.clear()
        } else {
            this.rotation.multiplyScalar(0.85 * delta)
        }

        if (this.rotation.x || this.rotation.y) {
            var rotation = this.rotation.clone().multiplyScalar(Math.PI / 180)
            this.camera.rotation.add(rotation)
        }
    }

完整的代码也可以在这里找到: https ://github.com/jdolan/radiantjs/blob/master/public/scripts/main/view.js#L291

非常感谢任何帮助!

4

2 回答 2

3

A kind user in the THREE.js IRC channel explained that the easiest way to accomplish what I wanted to do was to wrap the camera in a separate object (a parent / container). Translation and yaw are applied to the container, while pitch is applied to the camera itself:

this.boom = new THREE.Object3D()
this.boom.position.copy(params.position)
this.boom.up.set(0, 0, 1)
this.boom.lookAt(new THREE.Vector3(0, 1, 0).add(params.position))

this.camera = new THREE.PerspectiveCamera(this.fov, this.aspect, 0.1, 4096)

this.boom.add(this.camera)
this.scene.add(this.boom)

Then to apply my transform at each frame:

if (this.velocity.length() < 0.15) {
    this.velocity.clear()
} else {
    this.velocity.multiplyScalar(0.85)
}

if (this.velocity.x || this.velocity.y || this.velocity.z) {
    this.boom.translate(3, this.velocity.clone())
    this.boom.position.clamp(-16384, 16384)
}

if (this.avelocity.length() < 0.15) {
    this.avelocity.clear()
} else {
    this.avelocity.multiplyScalar(0.85)
}

if (this.avelocity.x || this.avelocity.y) {
    var rotation = this.avelocity.clone().multiplyScalar(Math.PI / 180)
    this.boom.rotation.y += rotation.y
    this.camera.rotation.x += rotation.x
}

Works like a charm! Note that, again, yaw is applied to this.boom while pitch is applied to this.camera. This has the effect of rotating the camera relative to the boom, rather than relative to the scene.

于 2013-01-17T21:14:53.430 回答
2

我的方法是先设置camera.eulerOrder = "YXZ";,然后我可以camera.rotation.y用作偏航和camera.rotation.x俯仰。

对于运动,我camera.translateZ用于前进/后退和camera.translateX扫射。因为我希望玩家总是向上/向下看,即使他们直接向上/向下看,我也使用camera.position.y += velocity.y;而不是translateY(基于旋转)。

我不确定这是否比使用容器更好或更差。

于 2013-02-28T23:40:11.713 回答