0

我有一个网格,我想通过用户输入来控制它的偏航和俯仰。我天真地尝试围绕 z 和 y 轴旋转网格,这似乎可以控制偏航,但上下是不稳定的。

function checkKeys(keys) {
    if (keys.left) spaceship.rotation.z += .05;
    if (keys.right) spaceship.rotation.z -= .05;
    if (keys.up) spaceship.rotation.y += .05;
    if (keys.down) spaceship.rotation.y -= .05;
}

如何使左/右控制飞机的偏航和上/下控制俯仰?

http://jsfiddle.net/trevordixon/d9BN9/2/

更新:我简化了 wagerfield 提到的 FlyControls.js,因此它服从我的游戏手柄并仅处理旋转。这是我最终得到的结果(https://gist.github.com/trevordixon/5783321):

THREE.FlyControls = function(object) {
    this.object = object;

    // API

    this.movementSpeed = 1.0;
    this.rollSpeed = 0.005;

    // disable default target object behavior

    this.object.useQuaternion = true;

    // internals

    this.tmpQuaternion = new THREE.Quaternion();

    this.moveState = {up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0};
    this.moveVector = new THREE.Vector3(0, 0, 0);
    this.rotationVector = new THREE.Vector3(0, 0, 0);

    this.handleEvent = function(event) {
        if (typeof this[event.type] == 'function') {
            this[event.type](event);
        }
    };

    this.update = function(delta) {
        this.moveState.yawLeft   = -gamepad.axes[2];
        this.moveState.pitchDown =   gamepad.axes[3];

        this.moveState.rollLeft = (Math.abs(gamepad.axes[0]) < 0.15 ? 0 : gamepad.axes[0]) ||
                              gamepad.buttons[15]/2;

        this.moveState.rollRight = (Math.abs(gamepad.axes[1]) < 0.15 ? 0 : gamepad.axes[1]) ||
                               gamepad.buttons[14]/2;

        this.updateRotationVector();

        var moveMult = delta * this.movementSpeed;
        var rotMult = delta * this.rollSpeed;

        this.object.translateX(this.moveVector.x * moveMult);
        this.object.translateY(this.moveVector.y * moveMult);
        this.object.translateZ(this.moveVector.z * moveMult);

        this.tmpQuaternion.set(this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1).normalize();
        this.object.quaternion.multiply(this.tmpQuaternion);

        // expose the rotation vector for convenience
        this.object.rotation.setEulerFromQuaternion(this.object.quaternion, this.object.eulerOrder);
    };

    this.updateRotationVector = function() {
        this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp );
        this.rotationVector.y = ( -this.moveState.yawRight  + this.moveState.yawLeft );
        this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft );
    };

    function bind(scope, fn) {
        return function () {
            fn.apply( scope, arguments );
        };
    };

    this.updateRotationVector();
};
4

2 回答 2

2

偏航轴是上轴,或者在这种情况下是 y 轴,所以你需要旋转你的飞船几何形状,使其水平开始:

geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); 

然后你需要改变eulerOrder你的飞船,所以偏航(Y)是第一,俯仰(X)是第二:

spaceship.rotation.order = "YXZ"; // three.js r.65

然后你需要相应地调整你的键码。

三.js r.65

于 2013-06-10T17:14:08.460 回答
1

您遇到的问题是由于计算旋转并将其应用于 three.js 中的对象的方式(通常是 3D 引擎)。对于每个旋转轴(x、y 和 z),一个旋转矩阵乘以对象的矩阵(其中包含它的位置、比例和旋转)。

由于矩阵是不可交换的;这意味着 A * B != B * A,乘法的顺序很重要。默认情况下,这个“欧拉顺序”是 X 然后 Y 然后 Z。这就是为什么你的 Z 旋转似乎是有道理的,但你的 Y 旋转并不是你直观期望的那样。

别怕,有办法!我假设您希望您的飞机以与此演示中的相机相同的方式旋转,其中每个额外的旋转变化都相对于当前旋转应用。在 3D Studio Max 等 3D 程序中,这称为局部旋转:

http://threejs.org/examples/webgl_geometry_terrain.html

如果您检查此演示的源代码,您将看到相机的控件是在第 76 行创建的:

controls = new THREE.FirstPersonControls( camera );

还有FlyControls,可能更适合你?

http://threejs.org/examples/misc_controls_fly.html

无论哪种方式,我都会首先使用这些现成的控件并在构造函数中使用您的平面对象而不是相机。

希望有帮助。

于 2013-06-10T17:52:50.290 回答