2013-05-13 18 views
9

Uso OrbitControls.js per consentire l'interazione con il mouse. Sto aggiungendo un pulsante nella scena che permette di "resettare" la fotocamera al suo stato in cui si trovava prima di qualsiasi interazione del mouse.Reimposta fotocamera utilizzando OrbitControls.js

ho cercato di salvare camera.position e camera.rotation prima di ogni interazione:

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

e dopo il "reset" si preme il pulsante, la posizione iniziale e la rotazione è impostato:

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

Funziona bene se non si utilizza la panoramica. Se l'utente esegue la panoramica utilizzando il pulsante destro del mouse, il codice sopra riportato non può "reimpostare" la fotocamera.

Qual è il metodo corretto per "ripristinare" la telecamera al suo stato precedente?

Revisione di Three.js è R58 e questo è 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); 

risposta

8

operazione Pan sta aggiornando vettore chiamato this.center, è necessario reimpostare per vedere metodo di pan,

this.center.add(distance); 

vedere questo metodo troppo

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

e quindi il metodo di aggiornamento sarà k eep la fotocamera ha guardato il vettore center

5

ah.adel è corretto L'operazione di Pan aggiornerà il centro del controller della videocamera. Pertanto, se è necessario ripristinare/ripristinare la videocamera su una videocamera predefinita, è necessario impostare anche il centro del controller della videocamera.

seguito codice è un codice semplice per memorizzare la posizione della fotocamera, rotazione e controllo centro

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

Usare questa funzione per ripristinare telecamera tardi.

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

Ripristina chiamata Funzione fotocamera per ripristinare la telecamera salvata.

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

Spero che questo vi aiuterà a tutti coloro che avendo questo problema

+0

isn' t control.target? – Tlatis

+2

'controls.center' è stato rinominato in' controls.target' ad un certo punto –

18

È possibile ripristinare la fotocamera quando si utilizza OrbitControls in questo modo:

controls.reset(); 

Three.js r.71

+1

Grazie! Questo è un modo elegante. Presumo che questa sia una nuova aggiunta. Non funziona in r.58 o giù di lì? –

+1

È stato aggiunto in r.66. – WestLangley

+0

['.saveState'] (https://threejs.org/docs/index.html#examples/controls/OrbitControls.saveState) Salvare lo stato corrente dei controlli. Questo può essere successivamente ripristinato con .reset. – zwcloud

Problemi correlati