2013-05-13 5 views
9

Ich verwende OrbitControls.js, um Mausinteraktion zu ermöglichen. Ich füge eine Schaltfläche in die Szene ein, die es ermöglicht, die Kamera in den Zustand zurückzusetzen, in dem sie sich vor Mausinteraktionen befand.Kamera mit OrbitControls.js zurücksetzen

ich versucht habe camera.position und camera.rotation vor allen Interaktionen zu speichern:

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

Und nach dem "Reset" -Taste gedrückt wird, wird die anfängliche Position und Rotation gesetzt:

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

Es funktioniert gut, wenn Pan nicht verwendet wird. Wenn Benutzer mit der rechten Maustaste der Maus schwenkt, kann der obige Code die Kamera nicht "zurücksetzen".

Was ist die richtige Methode, um die Kamera in den vorherigen Zustand zurückzusetzen?

Revision von three.js ist r58 und das ist die 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); 

Antwort

8

Pan Operation aktualisiert Vektor this.center genannt, müssen Sie es zurücksetzen pan-Methode, um zu sehen,

this.center.add(distance); 

sehen diese Methode zu

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

und dann wird die Update-Methode k eep die Kamera schaute auf die center Vektor

5

ah.adel ist korrekt Pan-Betrieb wird die Mitte der Kamera-Controller aktualisieren. Wenn Sie daher die Kamera auf eine vordefinierte Kamera zurücksetzen/wiederherstellen müssen, müssen Sie auch den Kamera-Controller-Center einstellen.

folgende Code ist ein einfacher Code Kameraposition zu speichern, Rotation und Leitzentrale

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

Mit dieser Funktion Kamera später wiederherzustellen.

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

Aufruf restoreCamera-Funktion zum Wiederherstellen gespeicherter Kamera.

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

Hoffnung dies jedem helfen, der dieses Problem mit

+0

isn‘ t es steuert.target? – Tlatis

+2

'controls.center' wurde irgendwann in' controls.target' umbenannt –

18

Sie können die Kamera zurückgesetzt, wenn OrbitControls mit etwa so:

controls.reset(); 

three.js r.71

+1

Danke! Dies ist eine elegante Art und Weise. Ich nehme an, das ist eine neue Ergänzung. Nicht in r.58 oder so arbeiten? –

+1

Es wurde in r.66 hinzugefügt. – WestLangley

+0

['.saveState'] (https://threejs.org/docs/index.html#examples/controls/OrbitControls.saveState) Speichert den aktuellen Status der Steuerelemente. Dies kann später mit .reset wiederhergestellt werden. – zwcloud