如何修改Three.js PointerLockControls旋转轴适配自定义camera.up?
修复Three.js PointerLockControls自定义up轴后的旋转异常问题
我在使用Three.js的PointerLockControls时,将相机的up轴设置为z轴:
camera.up.set(0,0,1);
但左右移动鼠标时,画面依然沿y轴旋转,而非预期的z轴。我的控件初始化代码如下:
const controls = new PointerLockControls( camera, document.body ); controls.addEventListener('lock', () => (menuPanel.style.display = 'none')) controls.addEventListener('unlock', () => (menuPanel.style.display = 'block')) startButton.addEventListener('click', function () { controls.lock(); }, false);
问题原因
PointerLockControls默认硬编码使用世界空间的y轴作为水平旋转轴,不会自动跟随相机的up属性变化,因此即使修改了相机up轴,旋转逻辑仍按原轴执行。
修复方案
通过重写控件的鼠标移动处理逻辑,让水平旋转绕相机自身的up轴进行。以下是两种实现方式:
方式1:自定义继承控件(推荐)
创建一个继承自PointerLockControls的自定义控件,修改旋转轴逻辑:
class CustomPointerLockControls extends PointerLockControls { constructor(camera, domElement) { super(camera, domElement); this.customUp = camera.up.clone(); } handleMouseMove(event) { if (!this.isLocked) return; const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; // 水平旋转绕自定义up轴,垂直旋转绕相机right轴 const yRotQuat = new THREE.Quaternion().setFromAxisAngle(this.customUp, -movementX * 0.002); const xRotQuat = new THREE.Quaternion().setFromAxisAngle(this.camera.right, movementY * 0.002); this.camera.quaternion.premultiply(yRotQuat); this.camera.quaternion.premultiply(xRotQuat); } } // 使用自定义控件替换原初始化代码 const controls = new CustomPointerLockControls(camera, document.body); controls.addEventListener('lock', () => (menuPanel.style.display = 'none')) controls.addEventListener('unlock', () => (menuPanel.style.display = 'block')) startButton.addEventListener('click', () => controls.lock(), false);
方式2:直接修改现有控件的处理方法
如果不想创建新类,可以直接覆盖原控件的handleMouseMove方法:
const controls = new PointerLockControls(camera, document.body); // 重写鼠标移动处理逻辑 controls.handleMouseMove = function(event) { if (!this.isLocked) return; const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; // 水平旋转绕camera.up轴 const yRotQuat = new THREE.Quaternion().setFromAxisAngle(this.camera.up, -movementX * 0.002); const xRotQuat = new THREE.Quaternion().setFromAxisAngle(this.camera.right, movementY * 0.002); this.camera.quaternion.premultiply(yRotQuat); this.camera.quaternion.premultiply(xRotQuat); }; // 后续事件监听保持不变 controls.addEventListener('lock', () => (menuPanel.style.display = 'none')) controls.addEventListener('unlock', () => (menuPanel.style.display = 'block')) startButton.addEventListener('click', () => controls.lock(), false);
说明
修改后,水平鼠标移动会绕相机设置的z轴旋转,垂直移动绕相机的right轴旋转,完全匹配自定义up轴的需求。
内容的提问来源于stack exchange,提问作者omega
相关产品推荐
相关产品推荐

