2013-05-13 26 views
9

Tôi đang sử dụng OrbitControls.js để cho phép tương tác chuột. Tôi đang thêm một nút vào cảnh cho phép "đặt lại" máy ảnh về trạng thái của nó trước khi có bất kỳ tương tác chuột nào.Đặt lại máy ảnh bằng OrbitControls.js

Tôi đã cố gắng để tiết kiệm camera.position và camera.rotation trước khi bất kỳ sự tương tác:

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

Và sau khi "thiết lập lại" nút được nhấn, vị trí ban đầu và luân chuyển được thiết lập:

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

Nó hoạt động tốt nếu pan không được sử dụng. Nếu người dùng sử dụng nút chuột phải, thì mã trên không thể "đặt lại" máy ảnh.

Phương pháp đúng để "đặt lại" máy ảnh về trạng thái trước đó của nó là gì?

Revision của three.js là R58 và đây là 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', onMouseMove, false); 
     document.removeEventListener('mouseup', onMouseUp, 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, 0)); 
       break; 
      case scope.keys.RIGHT: 
       scope.pan(new THREE.Vector3(1, 0, 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', onMouseWheel, false); // firefox 
    this.domElement.addEventListener('keydown', onKeyDown, false); 

}; 

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

Trả lời

8

hoạt động Pan đang cập nhật vector gọi this.center, bạn cần phải thiết lập lại nó để xem phương pháp chảo,

this.center.add(distance); 

cũng xem phương thức này quá

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; 
    }; 

và sau đó phương thức cập nhật sẽ k eep máy ảnh nhìn vào các vector center

5

ah.adel là chính xác Hoạt động của Pan sẽ cập nhật trung tâm của bộ điều khiển máy ảnh. Do đó, nếu bạn cần đặt lại/khôi phục máy ảnh về máy ảnh được xác định trước, bạn cũng cần đặt trung tâm điều khiển máy ảnh.

mã sau là một mã đơn giản để lưu trữ vị trí camera, luân chuyển và điều khiển trung tâm

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

Sử dụng chức năng này để khôi phục lại máy ảnh sau đó.

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(); 
} 

Khôi phục cuộc gọiCamera để khôi phục máy ảnh đã lưu.

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

Hy vọng điều này sẽ giúp cho bất cứ ai có vấn đề này

+0

isn' t nó controls.target? – Tlatis

+2

'controls.center' được đổi tên thành' controls.target' tại một số điểm –

18

Bạn có thể khôi phục máy ảnh khi sử dụng OrbitControls như vậy:

controls.reset(); 

three.js r.71

+1

Cảm ơn! Đây là một cách thanh lịch. Tôi cho rằng đây là một bổ sung mới. Không làm việc trong r.58 hay như vậy? –

+1

Nó đã được thêm vào trong r.66. – WestLangley

+0

['.saveState'] (https://threejs.org/docs/index.html#examples/controls/OrbitControls.saveState) Lưu trạng thái hiện tại của các điều khiển. Điều này sau này có thể được phục hồi với .reset. – zwcloud

Các vấn đề liên quan