18

マウス操作を可能にするために OrbitControls.js を使用しています。マウス操作の前の状態にカメラを「リセット」できるボタンをシーンに追加しています。

相互作用の前に camera.position と camera.rotation を保存しようとしました:

    camera_initial_position = camera.position;
    camera_initial_rotation = camera.rotation;

「リセット」ボタンを押すと、初期位置と回転が設定されます。

    camera.position = camera_initial_position;
    camera.rotation = camera_initial_rotation;

鍋を使わないとうまくいきます。ユーザーがマウスの右ボタンを使用してパンした場合、上記のコードはカメラを「リセット」できません。

カメラを以前の状態に「リセット」する正しい方法は何ですか?

three.js のリビジョンは r58 で、これは OrbitControls.js です。

/**
 * @作者チャオ / https://github.com/qiao
 * @著者 mrdoob / http://mrdoob.com
 * @author modifiedq / http://alteredqualia.com/
 * @author WestLangley / http://github.com/WestLangley
 */

THREE.OrbitControls = 関数 (オブジェクト、domElement) {

    this.object = オブジェクト;
    this.domElement = (domElement !== 未定義) ? domElement : ドキュメント;

    // API

    this.enabled = true;

    this.center = 新しい THREE.Vector3();

    this.userZoom = true;
    this.userZoomSpeed = 1.0;

    this.userRotate = true;
    this.userRotateSpeed = 1.0;

    this.userPan = true;
    this.userPanSpeed = 2.0;

    this.autoRotate = false;
    this.autoRotateSpeed = 2.0; // fps が 60 の場合、1 ラウンドあたり 30 秒

    this.minPolarAngle = 0; // ラジアン
    this.maxPolarAngle = Math.PI; // ラジアン

    this.minDistance = 0;
    this.maxDistance = 無限;

    this.keys = { 左: 37、上: 38、右: 39、下: 40 };

    // 内部

    var スコープ = これ;

    var EPS = 0.000001;
    var PIXELS_PER_ROUND = 1800;

    var 回転開始 = 新しい THREE.Vector2();
    var rotateEnd = 新しい THREE.Vector2();
    var rotateDelta = new THREE.Vector2();

    var zoomStart = new THREE.Vector2();
    var zoomEnd = 新しい THREE.Vector2();
    var zoomDelta = new THREE.Vector2();

    var phiDelta = 0;
    var thetaDelta = 0;
    var スケール = 1;

    var lastPosition = 新しい THREE.Vector3();

    var STATE = { なし: -1、回転: 0、ズーム: 1、パン: 2 };
    var 状態 = STATE.NONE;

    // イベント

    var changeEvent = { type: '変更' };


    this.rotateLeft = 関数 (角度) {

        if ( 角度 === 未定義 ) {

            angle = getAutoRotationAngle();

        }

        thetaDelta -= 角度;

    };

    this.rotateRight = 関数 (角度) {

        if ( 角度 === 未定義 ) {

            angle = getAutoRotationAngle();

        }

        thetaDelta += 角度;

    };

    this.rotateUp = 関数 (角度) {

        if ( 角度 === 未定義 ) {

            angle = getAutoRotationAngle();

        }

        phiDelta -= 角度;

    };

    this.rotateDown = 関数 (角度) {

        if ( 角度 === 未定義 ) {

            angle = getAutoRotationAngle();

        }

        phiDelta += 角度;

    };

    this.zoomIn = 関数 ( zoomScale ) {

        if ( zoomScale === 未定義 ) {

            zoomScale = getZoomScale();

        }

        スケール/= zoomScale;

    };

    this.zoomOut = 関数 ( zoomScale ) {

        if ( zoomScale === 未定義 ) {

            zoomScale = getZoomScale();

        }

        スケール *= zoomScale;

    };

    this.pan = 関数 (距離) {

        distance.transformDirection( this.object.matrix );
        distance.multiplyScalar(scope.userPanSpeed);

        this.object.position.add(距離);
        this.center.add(距離);

    };

    this.update = 関数 () {

        var position = this.object.position;
        var オフセット = position.clone().sub( this.center );

        // z 軸から y 軸周りの角度

        var theta = Math.atan2( offset.x, offset.z );

        // y 軸からの角度

        var phi = Math.atan2( Math.sqrt( オフセット.x * オフセット.x + オフセット.z * オフセット.z ), オフセット.y );

        if ( this.autoRotate ) {

            this.rotateLeft( getAutoRotationAngle() );

        }

        シータ += シータデルタ;
        ファイ += ファイデルタ;

        // phi を希望の範囲内に制限する
        phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );

        // ファイを EPS と PI-EPS の間に制限する
        phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );

        var radius = offset.length() * scale;

        // 希望の範囲内になるように半径を制限します
        radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );

        offset.x = 半径 * Math.sin( ファイ ) * Math.sin( シータ );
        offset.y = 半径 * Math.cos( ファイ );
        offset.z = 半径 * Math.sin( ファイ ) * Math.cos( シータ );

        position.copy( this.center ).add( オフセット );

        this.object.lookAt( this.center );

        シータデルタ = 0;
        ファイデルタ = 0;
        スケール = 1;

        if ( lastPosition.distanceTo( this.object.position ) > 0 ) {

            this.dispatchEvent( changeEvent );

            lastPosition.copy( this.object.position );

        }

    };


    関数 getAutoRotationAngle() {

        return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;

    }

    関数 getZoomScale() {

        return Math.pow( 0.95, scope.userZoomSpeed );

    }

    関数 onMouseDown( イベント ) {

        if ( scope.enabled === false ) 戻ります。
        if ( scope.userRotate === false ) return;

        event.preventDefault();

        if ( event.button === 0 ) {

            状態 = 状態.ROTATE;

            rotateStart.set( event.clientX, event.clientY );

        } そうでなければ ( event.button === 1 ) {

            状態 = 状態.ZOOM;

            zoomStart.set( event.clientX, event.clientY );

        } その他の場合 ( event.button === 2 ) {

            状態 = 状態.PAN;

        }

        document.addEventListener( 'mousemove', onMouseMove, false );
        document.addEventListener( 'mouseup', onMouseUp, false );

    }

    関数 onMouseMove( イベント ) {

        if ( scope.enabled === false ) 戻ります。

        event.preventDefault();

        if (状態 === 状態.ROTATE) {

            rotateEnd.set( event.clientX, event.clientY );
            rotateDelta.subVectors(rotateEnd、rotateStart);

            scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
            scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );

            回転開始.コピー(回転終了);

        } それ以外の場合 (状態 === 状態.ズーム) {

            zoomEnd.set( event.clientX, event.clientY );
            zoomDelta.subVectors( zoomEnd, zoomStart );

            もし ( zoomDelta.y > 0 ) {

                scope.zoomIn();

            } そうしないと {

                scope.zoomOut();

            }

            zoomStart.copy( zoomEnd );

        } それ以外の場合 (状態 === STATE.PAN ) {

            var MovementX = event.movementX || event.mozMovementX || イベント.mozMovementX || event.webkitMovementX || 0;
            var motionY = event.movementY || event.mozMovementY || イベント.mozMovementY || event.webkitMovementY || 0;

            scope.pan( new THREE.Vector3( - 動きX, 動きY, 0 ) );

        }

    }

    関数 onMouseUp( イベント ) {

        if ( scope.enabled === false ) 戻ります。
        if ( scope.userRotate === false ) return;

        document.removeEventListener( 'mousemove', onMouseMove, false );
        document.removeEventListener( 'mouseup', onMouseUp, false );

        状態 = 状態.NONE;

    }

    関数 onMouseWheel( イベント ) {

        if ( scope.enabled === false ) 戻ります。
        if ( scope.userZoom === false ) 戻ります。

        var デルタ = 0;

        if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9

            デルタ = event.wheelDelta;

        } else if ( event.detail ) { // Firefox

            デルタ = - event.detail;

        }

        もし (デルタ > 0 ) {

            scope.zoomOut();

        } そうしないと {

            scope.zoomIn();

        }

    }

    関数 onKeyDown( イベント ) {

        if ( scope.enabled === false ) 戻ります。
        if ( scope.userPan === false ) 戻ります。

        スイッチ ( event.keyCode ) {

            ケースscope.keys.UP:
                scope.pan( 新しい THREE.Vector3( 0, 1, 0 ) );
                壊す;
            ケースscope.keys.BOTTOM:
                scope.pan( 新しい THREE.Vector3( 0, - 1, 0 ) );
                壊す;
            ケースscope.keys.LEFT:
                scope.pan( 新しい THREE.Vector3( - 1, 0, 0 ) );
                壊す;
            ケース scope.keys.RIGHT:
                scope.pan( 新しい THREE.Vector3( 1, 0, 0 ) );
                壊す;
        }

    }

    this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
    this.domElement.addEventListener( 'mousedown', onMouseDown, false );
    this.domElement.addEventListener( 'マウスホイール', onMouseWheel, false );
    this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // ファイアフォックス
    this.domElement.addEventListener( 'keydown', onKeyDown, false );

};

THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );

4

3 に答える 3

10

パン操作は と呼ばれるベクトルを更新this.centerしています。パン メソッドを表示するにはリセットする必要があります。

this.center.add( distance );

このメソッドを次のように設定します。

this.resetCamera = function ( ) {
        this.object.position.x= camera_initial_position.xPosition;
        this.object.position.y = camera_initial_position.yPosition;
        this.object.position.z = camera_initial_position.zPosition;
        this.center.x= camera_initial_target.x;
        this.center.y= camera_initial_target.y;
        this.center.z= camera_initial_target.z;
    };

そして update メソッドはカメラをcenterベクトルに向け続けます。

于 2013-05-14T07:40:44.017 に答える