2022. 2. 18. 23:21ㆍTechnology[Front]
THREE.js에서 마우스를 움직이면 이에 맞춰 카메라 시점이 변경되는 코드를 작성하려고 하는데, 다행히도 THREE.js는 유명한 JavaScript 라이브러리라 공식홈페이지에 다양한 예제를 제공하고 있고 해당 소스 전체를 공개하고 있습니다. 이번 게시글에서는 공개하고 있는 소스 일부를 사용하여 마우스로 카메라 각도를 변경하는 코드를 손쉽게 작성해보겠습니다.
(1) THREE.js 오픈소스 중 PointerLockControls.js
import {
Euler,
EventDispatcher,
Vector3
} from 'three';
const _euler = new Euler( 0, 0, 0, 'YXZ' );
const _vector = new Vector3();
const _changeEvent = { type: 'change' };
const _lockEvent = { type: 'lock' };
const _unlockEvent = { type: 'unlock' };
const _PI_2 = Math.PI / 2;
class PointerLockControls extends EventDispatcher {
constructor( camera, domElement ) {
super();
if ( domElement === undefined ) {
console.warn( 'THREE.PointerLockControls: The second parameter "domElement" is now mandatory.' );
domElement = document.body;
}
this.domElement = domElement;
this.isLocked = false;
// Set to constrain the pitch of the camera
// Range is 0 to Math.PI radians
this.minPolarAngle = 0; // radians
this.maxPolarAngle = Math.PI; // radians
const scope = this;
function onMouseMove( event ) {
if ( scope.isLocked === false ) return;
const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
_euler.setFromQuaternion( camera.quaternion );
_euler.y -= movementX * 0.002;
_euler.x -= movementY * 0.002;
_euler.x = Math.max( _PI_2 - scope.maxPolarAngle, Math.min( _PI_2 - scope.minPolarAngle, _euler.x ) );
camera.quaternion.setFromEuler( _euler );
scope.dispatchEvent( _changeEvent );
}
function onPointerlockChange() {
if ( scope.domElement.ownerDocument.pointerLockElement === scope.domElement ) {
scope.dispatchEvent( _lockEvent );
scope.isLocked = true;
} else {
scope.dispatchEvent( _unlockEvent );
scope.isLocked = false;
}
}
function onPointerlockError() {
console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' );
}
this.connect = function () {
scope.domElement.ownerDocument.addEventListener( 'mousemove', onMouseMove );
scope.domElement.ownerDocument.addEventListener( 'pointerlockchange', onPointerlockChange );
scope.domElement.ownerDocument.addEventListener( 'pointerlockerror', onPointerlockError );
};
this.disconnect = function () {
scope.domElement.ownerDocument.removeEventListener( 'mousemove', onMouseMove );
scope.domElement.ownerDocument.removeEventListener( 'pointerlockchange', onPointerlockChange );
scope.domElement.ownerDocument.removeEventListener( 'pointerlockerror', onPointerlockError );
};
this.dispose = function () {
this.disconnect();
};
this.getObject = function () { // retaining this method for backward compatibility
return camera;
};
this.getDirection = function () {
const direction = new Vector3( 0, 0, - 1 );
return function ( v ) {
return v.copy( direction ).applyQuaternion( camera.quaternion );
};
}();
this.moveForward = function ( distance ) {
// move forward parallel to the xz-plane
// assumes camera.up is y-up
_vector.setFromMatrixColumn( camera.matrix, 0 );
_vector.crossVectors( camera.up, _vector );
camera.position.addScaledVector( _vector, distance );
};
this.moveRight = function ( distance ) {
_vector.setFromMatrixColumn( camera.matrix, 0 );
camera.position.addScaledVector( _vector, distance );
};
this.lock = function () {
this.domElement.requestPointerLock();
};
this.unlock = function () {
scope.domElement.ownerDocument.exitPointerLock();
};
this.connect();
}
}
export { PointerLockControls };
위의 코드는 THREE.js에서 오픈소스로 공개하고 있는 코드로 자유롭게 사용하시면 됩니다. onMouseMove라는 함수를 정의하고 마우스가 움직일 때 움직인 방향의 x와 y 좌표값을 이용해 camera.quaternion을 조정하고 이를 domElement에 addEventListener를 통해 mousemove이벤트를 추가하고 있습니다. 그리고 onPointerlockChange 함수에서 현재 domElement가 PointerlockElement인지를 확인해서 화면을 잠깐 멈추는 상태인 unlock과 해당 unlock상태를 해제한 lock상태를 부여할 수 있는 코드를 작성하고 이를 addEventListener를 통해 pointerlockchange이벤트를 추가하였습니다. 이후 connect와 disconnect를 이용해 연결된 상태일때는 이벤트를 추가하고 연결해제시 이벤트를 해제하는 코드를 구현하고 있습니다. 또한 getDirection을 통해 카메라의 방향을 얻어올 수 있고 moveForward와 moveRight를 구현하여 카메라를 이동가능하게 구현하였습니다.
이후 게시글에서는 위의 class PointerLockControls를 import해서 캐릭터를 카메라가 보는 방향으로 이동시키고 해당 캐릭터를 카메라가 따라가는 형태로 구현해보겠습니다.
'Technology[Front]' 카테고리의 다른 글
3D맵 구현하기 - 3인칭 카메라 구현하기(카메라 조종, 캐릭터가 카메라를 따라서 이동, 카메라가 보는 방향을 캐릭터가 응시) (1) | 2022.02.20 |
---|---|
3D맵 구현하기 - 키보드로 카메라 이동시키기 (1) | 2022.02.19 |
3D맵 구현하기 - THREE.js 구조 (1) | 2022.02.17 |
정적 이미지파일 React - Spring 업데이트 데이터 전송 (1) | 2022.02.14 |
Phaser 사용법 2 - Scene1.js (1) | 2022.02.13 |