18

我正在使用 OrbitControls.js 来允许鼠标交互。我在场景中添加了一个按钮,允许将相机“重置”到任何鼠标交互之前的状态。

我试图在任何交互之前保存 camera.position 和 camera.rotation :

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

按下“reset”按钮后,初始位置和旋转设置:

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

如果不使用平底锅,它会很好地工作。如果用户使用鼠标右键平移,则上述代码无法“重置”相机。

将相机“重置”到之前状态的正确方法是什么?

three.js 的修订版是 r58,这是 OrbitControls.js:

/**
 * @作者乔/https://github.com/qiao
 * @author mrdoob / http://mrdoob.com
 * @author changedq / http://alteredqualia.com/
 * @author WestLangley / http://github.com/WestLangley
 */

三.OrbitControls = function (object, domElement) {

    this.object = 对象;
    this.domElement = (domElement!== undefined) ?domElement:文档;

    // 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; // 当 fps 为 60 时,每轮 30 秒

    this.minPolarAngle = 0; // 弧度
    this.maxPolarAngle = Math.PI; // 弧度

    this.minDistance = 0;
    this.maxDistance = 无穷大;

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

    // 内部

    变量范围=这个;

    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;
    变量比例 = 1;

    var lastPosition = new THREE.Vector3();

    var状态={无:-1,旋转:0,缩放:1,平移:2};
    变种状态=状态。无;

    // 事件

    var changeEvent = { type: 'change' };


    this.rotateLeft = 函数(角度){

        如果(角度===未定义){

            角度 = getAutoRotationAngle();

        }

        thetaDelta -= 角度;

    };

    this.rotateRight = 函数(角度){

        如果(角度===未定义){

            角度 = getAutoRotationAngle();

        }

        thetaDelta += 角度;

    };

    this.rotateUp = 函数(角度){

        如果(角度===未定义){

            角度 = getAutoRotationAngle();

        }

        phiDelta -= 角度;

    };

    this.rotateDown = 函数(角度){

        如果(角度===未定义){

            角度 = getAutoRotationAngle();

        }

        phiDelta += 角度;

    };

    this.zoomIn = function (zoomScale) {

        如果(缩放比例===未定义){

            zoomScale = getZoomScale();

        }

        缩放 /= 缩放缩放;

    };

    this.zoomOut = function (zoomScale) {

        如果(缩放比例===未定义){

            zoomScale = getZoomScale();

        }

        比例 *= 缩放比例;

    };

    this.pan = 函数(距离){

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

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

    };

    this.update = 函数 () {

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

        // z 轴绕 y 轴的角度

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

        // 与y轴的角度

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

        如果(this.autoRotate){

            this.rotateLeft(getAutoRotationAngle());

        }

        θ+=θDelta;
        phi += phiDelta;

        // 将 phi 限制在所需的限制之间
        phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, phi));

        // 将 phi 限制在 EPS 和 PI-EPS 之间
        phi = Math.max(EPS, Math.min(Math.PI - EPS, phi));

        var radius = offset.length() * scale;

        // 将半径限制在所需范围之间
        半径= Math.max(this.minDistance,Math.min(this.maxDistance,半径));

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

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

        this.object.lookAt(this.center);

        θDelta = 0;
        phiDelta = 0;
        规模 = 1;

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

            this.dispatchEvent(changeEvent);

            lastPosition.copy(this.object.position);

        }

    };


    函数 getAutoRotationAngle() {

        返回 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;

    }

    函数 getZoomScale() {

        返回 Math.pow(0.95, scope.userZoomSpeed);

    }

    函数 onMouseDown(事件){

        if (scope.enabled === false) 返回;
        if (scope.userRotate === false) 返回;

        event.preventDefault();

        if ( event.button === 0 ) {

            状态=状态。旋转;

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

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

            状态=状态。缩放;

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

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

            状态=状态.PAN;

        }

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

    }

    功能 onMouseMove(事件){

        if (scope.enabled === false) 返回;

        event.preventDefault();

        if ( 状态 === 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.ZOOM ) {

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

            if (zoomDelta.y > 0) {

                scope.zoomIn();

            } 别的 {

                scope.zoomOut();

            }

            zoomStart.copy(zoomEnd);

        } else if ( 状态 === STATE.PAN ) {

            var moveX = event.movementX || 事件.mozMovementX || event.webkitMovementX || 0;
            var moveY = event.movementY || 事件.mozMovementY || event.webkitMovementY || 0;

            scope.pan(new THREE.Vector3(-motionX, moveY, 0));

        }

    }

    功能 onMouseUp(事件){

        if (scope.enabled === false) 返回;
        if (scope.userRotate === false) 返回;

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

        状态=状态。无;

    }

    功能 onMouseWheel(事件){

        if (scope.enabled === false) 返回;
        if (scope.userZoom === false) 返回;

        变量增量 = 0;

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

            delta = event.wheelDelta;

        } else if ( event.detail ) { // 火狐

            delta = - event.detail;

        }

        如果(增量> 0){

            scope.zoomOut();

        } 别的 {

            scope.zoomIn();

        }

    }

    函数 onKeyDown( 事件 ) {

        if (scope.enabled === false) 返回;
        if (scope.userPan === false) 返回;

        开关(事件.keyCode){

            案例范围.keys.UP:
                scope.pan(new THREE.Vector3(0,1,0));
                休息;
            案例范围.keys.BOTTOM:
                scope.pan(new THREE.Vector3(0, - 1, 0));
                休息;
            案例范围.keys.LEFT:
                scope.pan(new THREE.Vector3(-1,0,0));
                休息;
            案例范围.keys.RIGHT:
                scope.pan(new THREE.Vector3(1, 0, 0));
                休息;
        }

    }

    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', onMouseWheel, false); //火狐
    this.domElement.addEventListener('keydown', onKeyDown, false);

};

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

4

3 回答 3

43

您可以在使用时重置相机,OrbitControls如下所示:

controls.reset();

三.js r.71

于 2015-05-01T17:00:32.003 回答
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;
    };

然后更新方法将保持相机看着center向量。

于 2013-05-14T07:40:44.017 回答
8

ah.adel 是正确的平移操作将更新相机控制器的中心。因此,如果您需要将相机重置/恢复为预定义的相机,您还需要设置相机控制器中心。

以下代码是存储相机位置、旋转和控制中心的简单代码

var camToSave = {};
camToSave.position = camera.position.clone();
camToSave.rotation = camera.rotation.clone();
camToSave.controlCenter = controls.center.clone();

稍后使用此功能恢复相机。

function restoreCamera(position, rotation, controlCenter){
    camera.position.set(position.x, position.y, position.z);
    camera.rotation.set(rotation.x, rotation.y, rotation.z);

    controls.center.set(controlCenter.x, controlCenter.y, controlCenter.z);
    controls.update();

    render();
}

调用 restoreCamera 函数恢复保存的相机。

restoreCamera(camToSave.position, camToSave.rotation, camToSave.controlCenter);

希望这对遇到此问题的人有所帮助

于 2015-05-01T11:44:46.993 回答