マウス操作を可能にするために 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 です。
/** * @作者チャオ / https://github.com/qiao * @著者 mrdoob / http://mrdoob.com * @author modifiedq / http://alteredqualia.com/ * @author WestLangley / http://github.com/WestLangley */ THREE.OrbitControls = 関数 (オブジェクト、domElement) { this.object = オブジェクト; this.domElement = (domElement !== 未定義) ? domElement : ドキュメント; // API this.enabled = true; this.center = 新しい 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 の場合、1 ラウンドあたり 30 秒 this.minPolarAngle = 0; // ラジアン this.maxPolarAngle = Math.PI; // ラジアン this.minDistance = 0; this.maxDistance = 無限; this.keys = { 左: 37、上: 38、右: 39、下: 40 }; // 内部 var スコープ = これ; var EPS = 0.000001; var PIXELS_PER_ROUND = 1800; var 回転開始 = 新しい THREE.Vector2(); var rotateEnd = 新しい THREE.Vector2(); var rotateDelta = new THREE.Vector2(); var zoomStart = new THREE.Vector2(); var zoomEnd = 新しい THREE.Vector2(); var zoomDelta = new THREE.Vector2(); var phiDelta = 0; var thetaDelta = 0; var スケール = 1; var lastPosition = 新しい THREE.Vector3(); var STATE = { なし: -1、回転: 0、ズーム: 1、パン: 2 }; var 状態 = STATE.NONE; // イベント var changeEvent = { type: '変更' }; this.rotateLeft = 関数 (角度) { if ( 角度 === 未定義 ) { angle = getAutoRotationAngle(); } thetaDelta -= 角度; }; this.rotateRight = 関数 (角度) { if ( 角度 === 未定義 ) { angle = getAutoRotationAngle(); } thetaDelta += 角度; }; this.rotateUp = 関数 (角度) { if ( 角度 === 未定義 ) { angle = getAutoRotationAngle(); } phiDelta -= 角度; }; this.rotateDown = 関数 (角度) { if ( 角度 === 未定義 ) { angle = getAutoRotationAngle(); } phiDelta += 角度; }; this.zoomIn = 関数 ( zoomScale ) { if ( zoomScale === 未定義 ) { zoomScale = getZoomScale(); } スケール/= zoomScale; }; this.zoomOut = 関数 ( zoomScale ) { if ( zoomScale === 未定義 ) { zoomScale = getZoomScale(); } スケール *= zoomScale; }; this.pan = 関数 (距離) { distance.transformDirection( this.object.matrix ); distance.multiplyScalar(scope.userPanSpeed); this.object.position.add(距離); this.center.add(距離); }; this.update = 関数 () { var position = this.object.position; var オフセット = position.clone().sub( this.center ); // z 軸から y 軸周りの角度 var theta = Math.atan2( offset.x, offset.z ); // y 軸からの角度 var phi = Math.atan2( Math.sqrt( オフセット.x * オフセット.x + オフセット.z * オフセット.z ), オフセット.y ); if ( this.autoRotate ) { this.rotateLeft( getAutoRotationAngle() ); } シータ += シータデルタ; ファイ += ファイデルタ; // phi を希望の範囲内に制限する phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); // ファイを EPS と PI-EPS の間に制限する phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); var radius = offset.length() * scale; // 希望の範囲内になるように半径を制限します radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); offset.x = 半径 * Math.sin( ファイ ) * Math.sin( シータ ); offset.y = 半径 * Math.cos( ファイ ); offset.z = 半径 * Math.sin( ファイ ) * Math.cos( シータ ); position.copy( this.center ).add( オフセット ); this.object.lookAt( this.center ); シータデルタ = 0; ファイデルタ = 0; スケール = 1; if ( lastPosition.distanceTo( this.object.position ) > 0 ) { this.dispatchEvent( changeEvent ); lastPosition.copy( this.object.position ); } }; 関数 getAutoRotationAngle() { return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } 関数 getZoomScale() { return Math.pow( 0.95, scope.userZoomSpeed ); } 関数 onMouseDown( イベント ) { if ( scope.enabled === false ) 戻ります。 if ( scope.userRotate === false ) return; event.preventDefault(); if ( event.button === 0 ) { 状態 = 状態.ROTATE; rotateStart.set( event.clientX, event.clientY ); } そうでなければ ( event.button === 1 ) { 状態 = 状態.ZOOM; zoomStart.set( event.clientX, event.clientY ); } その他の場合 ( event.button === 2 ) { 状態 = 状態.PAN; } document.addEventListener( 'mousemove', onMouseMove, false ); document.addEventListener( 'mouseup', onMouseUp, false ); } 関数 onMouseMove( イベント ) { if ( scope.enabled === false ) 戻ります。 event.preventDefault(); if (状態 === 状態.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 ); 回転開始.コピー(回転終了); } それ以外の場合 (状態 === 状態.ズーム) { zoomEnd.set( event.clientX, event.clientY ); zoomDelta.subVectors( zoomEnd, zoomStart ); もし ( zoomDelta.y > 0 ) { scope.zoomIn(); } そうしないと { scope.zoomOut(); } zoomStart.copy( zoomEnd ); } それ以外の場合 (状態 === STATE.PAN ) { var MovementX = event.movementX || event.mozMovementX || イベント.mozMovementX || event.webkitMovementX || 0; var motionY = event.movementY || event.mozMovementY || イベント.mozMovementY || event.webkitMovementY || 0; scope.pan( new THREE.Vector3( - 動きX, 動きY, 0 ) ); } } 関数 onMouseUp( イベント ) { if ( scope.enabled === false ) 戻ります。 if ( scope.userRotate === false ) return; document.removeEventListener( 'mousemove', onMouseMove, false ); document.removeEventListener( 'mouseup', onMouseUp, false ); 状態 = 状態.NONE; } 関数 onMouseWheel( イベント ) { if ( scope.enabled === false ) 戻ります。 if ( scope.userZoom === false ) 戻ります。 var デルタ = 0; if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 デルタ = event.wheelDelta; } else if ( event.detail ) { // Firefox デルタ = - event.detail; } もし (デルタ > 0 ) { scope.zoomOut(); } そうしないと { scope.zoomIn(); } } 関数 onKeyDown( イベント ) { if ( scope.enabled === false ) 戻ります。 if ( scope.userPan === false ) 戻ります。 スイッチ ( event.keyCode ) { ケースscope.keys.UP: scope.pan( 新しい THREE.Vector3( 0, 1, 0 ) ); 壊す; ケースscope.keys.BOTTOM: scope.pan( 新しい THREE.Vector3( 0, - 1, 0 ) ); 壊す; ケースscope.keys.LEFT: scope.pan( 新しい THREE.Vector3( - 1, 0, 0 ) ); 壊す; ケース scope.keys.RIGHT: scope.pan( 新しい THREE.Vector3( 1, 0, 0 ) ); 壊す; } } this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); this.domElement.addEventListener( 'mousedown', onMouseDown, false ); this.domElement.addEventListener( 'マウスホイール', onMouseWheel, false ); this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // ファイアフォックス this.domElement.addEventListener( 'keydown', onKeyDown, false ); }; THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );