11

私は Three.js と WebGL をいじっていますが、思い通りのコントロールを得ることができません。Three.js の FirstPersonControls はポインター ロックを使用しないため、「独自のコントロールをロールする」ことを選択しました。

とにかく、組み込みの FirstPersonControls からほとんどのコードを取得し、(movementXの代わりにpageX - offset) ポインター ロックを使用するように変換しましたが、見た目の動きを滑らかにするのに問題があります。

これが私のものです( jqueryイベントであるためonMouseMove使用しています):originalEvent

onMouseMove: function(e) {
    if(!document.pointerLockElement) return;

    var moveX = e.originalEvent.movementX       ||
                    e.originalEvent.mozMovementX    ||
                    e.originalEvent.webkitMovementX ||
                    0,
        moveY = e.originalEvent.movementY       ||
                    e.originalEvent.mozMovementY    ||
                    e.originalEvent.webkitMovementY ||
                    0;

    //Update the mouse movement for coming frames
    this.mouseMovementX = moveX;
    this.mouseMovementY = moveY;
}

そして私の(デルタControls.update()で、各アニメーションフレームで呼び出されます):THREE.Clock

update: function(delta) {            
    if(this.freeze) {
        return;
    }

    //movement, works fine
    if(this.moveForward) this.camera.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
    if(this.moveBackward) this.camera.translateZ(actualMoveSpeed);

    if(this.moveLeft) this.camera.translateX(-actualMoveSpeed);
    if(this.moveRight) this.camera.translateX(actualMoveSpeed);

    /////////
    //ISSUES ARE WITH THIS CODE:
    /////////
    //look movement, really jumpy
    this.lon += this.mouseMovementX;
    this.lat -= this.mouseMovementY;

    this.lat = Math.max(-85, Math.min(85, this.lat));
    this.phi = (90 - this.lat) * Math.PI / 180;
    this.theta = this.lon * Math.PI / 180;

    this.target.x = this.camera.position.x + 100 * Math.sin(this.phi) * Math.cos(this.theta);
    this.target.y = this.camera.position.y + 100 * Math.cos(this.phi);
    this.target.z = this.camera.position.z + 100 * Math.sin(this.phi) * Math.sin(this.theta);

    this.camera.lookAt(this.target);
}

このコードは機能しますが、マウスの動きに合わせてカメラを動かすと不安定になります。それを滑らかにする方法を考え出すのに、本当に助けが必要です。

ここで「ジャンピー」の意味がわかります。私は Three.js、WebGL、および一般的な 3D を初めて使用するので、助けていただければ幸いです。

ありがとう、

-チャド


編集@przemo_liで作業した後、彼が思いついた作業コードは次のとおりです。

onMouseMove: function(e) {
    if(!document.pointerLockElement) return;

    var moveX = e.originalEvent.movementX       ||
                    e.originalEvent.mozMovementX    ||
                    e.originalEvent.webkitMovementX ||
                    0,
        moveY = e.originalEvent.movementY       ||
                    e.originalEvent.mozMovementY    ||
                    e.originalEvent.webkitMovementY ||
                    0;

    //Update the initial coords on mouse move
    this.mouseMovementX += moveX; //aggregate mouse movements as a total delta delta
    this.mouseMovementY += moveY;
},
update: function(delta) {            
    if(this.freeze) {
        return;
    }

    //movement
    if(this.moveForward) this.camera.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
    if(this.moveBackward) this.camera.translateZ(actualMoveSpeed);

    if(this.moveLeft) this.camera.translateX(-actualMoveSpeed);
    if(this.moveRight) this.camera.translateX(actualMoveSpeed);

    //look movement
    this.lon += this.mouseMovementX;
    this.lat -= this.mouseMovementY;

    this.mouseMovementX = 0; //reset mouse deltas to 0 each rendered frame
    this.mouseMovementY = 0;

    this.phi = (90 - this.lat) * Math.PI / 180;
    this.theta = this.lon * Math.PI / 180;

    if(this.constrainVertical) {
        this.phi = THREE.Math.mapLinear(this.phi, 0, Math.PI, this.verticalMin, this.verticalMax);
    }

    this.target.x = this.camera.position.x + 100 * Math.sin(this.phi) * Math.cos(this.theta);
    this.target.y = this.camera.position.y + 100 * Math.cos(this.phi);
    this.target.z = this.camera.position.z + 100 * Math.sin(this.phi) * Math.sin(this.theta);

    this.camera.lookAt(this.target);
}
4

2 に答える 2

20

「公式」バージョンが追加されました: https://github.com/mrdoob/three.js/blob/master/examples/js/controls/PointerLockControls.js

于 2012-11-04T23:21:00.333 に答える
4

1)制約?あなたのコードでは、マウス X の動きを -|+ 85 に制限しています。そのような制約が必要になる可能性は低いです。

2) フレーム中に発生するすべてのイベントを集約する コードでは、新しいイベントごとにマウスの動きをオーバーライドします。そのため、フレーム中に 3 つのイベントを取得すると、最新のイベントのみが保存されます。

それらの動きを追加します。フレームをレンダリングした後よりも、カウントをクリアできます。そして、再びイベントの収集を開始します。

于 2012-09-19T19:29:41.513 に答える