我正在使用 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);