微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

three.js – 使用OrbitControls.js重置相机

我使用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:


/**
 * @author qiao / https://github.com/qiao
 * @author mrdoob / http://mrdoob.com
 * @author alteredq / http://alteredqualia.com/
 * @author WestLangley / http://github.com/WestLangley
 */

THREE.OrbitControls = function ( object,domElement ) {

    this.object = object;
    this.domElement = ( domElement !== undefined ) ? domElement : document;

    // API

    this.enabled = true;

    this.center = new 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; // 30 seconds per round when fps is 60

    this.minPolarangle = 0; // radians
    this.maxPolarangle = Math.PI; // radians

    this.mindistance = 0;
    this.maxdistance = Infinity;

    this.keys = { LEFT: 37,UP: 38,RIGHT: 39,BottOM: 40 };

    // internals

    var scope = this;

    var EPS = 0.000001;
    var PIXELS_PER_ROUND = 1800;

    var rotateStart = new THREE.Vector2();
    var rotateEnd = new THREE.Vector2();
    var rotateDelta = new THREE.Vector2();

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

    var phiDelta = 0;
    var thetaDelta = 0;
    var scale = 1;

    var lastPosition = new THREE.Vector3();

    var STATE = { NONE: -1,ROTATE: 0,ZOOM: 1,PAN: 2 };
    var state = STATE.NONE;

    // events

    var changeEvent = { type: 'change' };


    this.rotateLeft = function ( angle ) {

        if ( angle === undefined ) {

            angle = getAutoRotationAngle();

        }

        thetaDelta -= angle;

    };

    this.rotateRight = function ( angle ) {

        if ( angle === undefined ) {

            angle = getAutoRotationAngle();

        }

        thetaDelta += angle;

    };

    this.rotateUp = function ( angle ) {

        if ( angle === undefined ) {

            angle = getAutoRotationAngle();

        }

        phiDelta -= angle;

    };

    this.rotateDown = function ( angle ) {

        if ( angle === undefined ) {

            angle = getAutoRotationAngle();

        }

        phiDelta += angle;

    };

    this.zoomIn = function ( zoomScale ) {

        if ( zoomScale === undefined ) {

            zoomScale = getZoomScale();

        }

        scale /= zoomScale;

    };

    this.zoomOut = function ( zoomScale ) {

        if ( zoomScale === undefined ) {

            zoomScale = getZoomScale();

        }

        scale *= zoomScale;

    };

    this.pan = function ( distance ) {

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

        this.object.position.add( distance );
        this.center.add( distance );

    };

    this.update = function () {

        var position = this.object.position;
        var offset = position.clone().sub( this.center );

        // angle from z-axis around y-axis

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

        // angle from y-axis

        var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ),offset.y );

        if ( this.autoRotate ) {

            this.rotateLeft( getAutoRotationAngle() );

        }

        theta += thetaDelta;
        phi += phiDelta;

        // restrict phi to be between desired limits
        phi = Math.max( this.minPolarangle,Math.min( this.maxPolarangle,phi ) );

        // restrict phi to be betwee EPS and PI-EPS
        phi = Math.max( EPS,Math.min( Math.PI - EPS,phi ) );

        var radius = offset.length() * scale;

        // restrict radius to be between desired limits
        radius = Math.max( this.mindistance,Math.min( this.maxdistance,radius ) );

        offset.x = radius * Math.sin( phi ) * Math.sin( theta );
        offset.y = radius * Math.cos( phi );
        offset.z = radius * Math.sin( phi ) * Math.cos( theta );

        position.copy( this.center ).add( offset );

        this.object.lookAt( this.center );

        thetaDelta = 0;
        phiDelta = 0;
        scale = 1;

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

            this.dispatchEvent( changeEvent );

            lastPosition.copy( this.object.position );

        }

    };


    function getAutoRotationAngle() {

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

    }

    function getZoomScale() {

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

    }

    function onMouseDown( event ) {

        if ( scope.enabled === false ) return;
        if ( scope.userRotate === false ) return;

        event.preventDefault();

        if ( event.button === 0 ) {

            state = STATE.ROTATE;

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

        } else if ( event.button === 1 ) {

            state = STATE.ZOOM;

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

        } else if ( event.button === 2 ) {

            state = STATE.PAN;

        }

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

    }

    function onMouseMove( event ) {

        if ( scope.enabled === false ) return;

        event.preventDefault();

        if ( state === STATE.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 );

            rotateStart.copy( rotateEnd );

        } else if ( state === STATE.ZOOM ) {

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

            if ( zoomDelta.y > 0 ) {

                scope.zoomIn();

            } else {

                scope.zoomOut();

            }

            zoomStart.copy( zoomEnd );

        } else if ( state === STATE.PAN ) {

            var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
            var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;

            scope.pan( new THREE.Vector3( - movementX,movementY,0 ) );

        }

    }

    function onmouseup( event ) {

        if ( scope.enabled === false ) return;
        if ( scope.userRotate === false ) return;

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

        state = STATE.NONE;

    }

    function onMouseWheel( event ) {

        if ( scope.enabled === false ) return;
        if ( scope.userZoom === false ) return;

        var delta = 0;

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

            delta = event.wheelDelta;

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

            delta = - event.detail;

        }

        if ( delta > 0 ) {

            scope.zoomOut();

        } else {

            scope.zoomIn();

        }

    }

    function onKeyDown( event ) {

        if ( scope.enabled === false ) return;
        if ( scope.userPan === false ) return;

        switch ( event.keyCode ) {

            case scope.keys.UP:
                scope.pan( new THREE.Vector3( 0,1,0 ) );
                break;
            case scope.keys.BottOM:
                scope.pan( new THREE.Vector3( 0,- 1,0 ) );
                break;
            case scope.keys.LEFT:
                scope.pan( new THREE.Vector3( - 1,0 ) );
                break;
            case scope.keys.RIGHT:
                scope.pan( new THREE.Vector3( 1,0 ) );
                break;
        }

    }

    this.domElement.addEventListener( 'contextmenu',function ( event ) { event.preventDefault(); },false );
    this.domElement.addEventListener( 'mousedown',onMouseDown,false );
    this.domElement.addEventListener( 'mousewheel',onMouseWheel,false );
    this.domElement.addEventListener( 'DOMMouseScroll',false ); // firefox
    this.domElement.addEventListener( 'keydown',onKeyDown,false );

};

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

解决方法

平移操作是更新向量称为this.center,您需要重置它才能看到pan方法,
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;
    };

然后更新方法将保持相机看中心向量

原文地址:https://www.jb51.cc/js/152152.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐