반응형
이번 글에서는 Three.js에서 OrbitControls를 사용했을 때 FPS처럼 키보드 WASD로 상하좌우로 카메라를 이동하는 방법에 대해 기록한다.
Three.js OrbitControls WASD 카메라 이동하는 방법
Three.js에서 WASD 카메라 이동하는 컨트롤의 경우 OrbitControls와 PointerLockControls가 있다. 이번 글에서는 OrbitControls를 사용하는 글이다.
1. OrbitControls를 정의한다.
controls = new OrbitControls( camera, renderer.domElement ); // scene 주위 공전
controls.enableDamping = true; // 부드러운 동작
controls.enablePan = false;
controls.enableZoom = false;
// controls.maxPolarAngle = Math.PI / 2; // 아래로 회전 제한 (바닥을 뚫지 않음)
controls.minPolarAngle = 0; // 위로 회전 제한
//controls.update()는 카메라 변환설정을 수동으로 변경한 후에 호출해야 합니다.
camera.position.set( 0, 20, 100 )
2. OrbitControls에 키입력 이벤트를 사용하여 카메라 이동을 할 수 있다.
// 키 입력 관리
const keys = {};
// 키 입력 이벤트
window.addEventListener('keydown', (event) => {
keys[event.key] = true;
});
window.addEventListener('keyup', (event) => {
keys[event.key] = false;
});
3. 각 키 이벤트에 대해 addScaledVector를 사용하여 카메라의 포지션을 이동시킨다.
function movePlayer() {
const direction = new THREE.Vector3();
const right = new THREE.Vector3();
// 카메라 방향 기준으로 이동 벡터 계산
camera.getWorldDirection(direction);
direction.y = 0; // 수평 이동만 허용
direction.normalize();
right.crossVectors(camera.up, direction).normalize();
if (keys['w']) {
camera.position.addScaledVector(direction, moveSpeed); // 앞으로
}
if (keys['s']) {
camera.position.addScaledVector(direction, -moveSpeed); // 뒤로
}
if (keys['a']) {
camera.position.addScaledVector(right, moveSpeed); // 왼쪽으로
}
if (keys['d']) {
camera.position.addScaledVector(right, -moveSpeed); // 오른쪽으로
}
}
4. animate 중간에 movePlayer를 넣고, 그 다음으로 controls.update를 한다.
function animate() {
requestAnimationFrame( animate );
movePlayer();
controls.update();
renderer.render( scene, camera ); // sceene, camera 렌더링
}
5. 전체 소스 코드
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Exercise</title>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three/build/three.module.js",
"three/addons/": "https://unpkg.com/three/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
var scene, camera, renderer, controls;
// 센터 바닥 default
var base;
var baseX = 0;
var baseY = 0;
var baseZ = 0;
// 키 입력 관리
const keys = {};
// 키 입력 이벤트
window.addEventListener('keydown', (event) => {
keys[event.key] = true;
});
window.addEventListener('keyup', (event) => {
keys[event.key] = false;
});
// 이동 속도
const moveSpeed = 0.1;
function movePlayer() {
const direction = new THREE.Vector3();
const right = new THREE.Vector3();
// 카메라 방향 기준으로 이동 벡터 계산
camera.getWorldDirection(direction);
direction.y = 0; // 수평 이동만 허용
direction.normalize();
right.crossVectors(camera.up, direction).normalize();
if (keys['w']) {
camera.position.addScaledVector(direction, moveSpeed); // 앞으로
}
if (keys['s']) {
camera.position.addScaledVector(direction, -moveSpeed); // 뒤로
}
if (keys['a']) {
camera.position.addScaledVector(right, moveSpeed); // 왼쪽으로
}
if (keys['d']) {
camera.position.addScaledVector(right, -moveSpeed); // 오른쪽으로
}
}
function init() {
// scene 생성
scene = new THREE.Scene();
// render 인스턴스 생성 및 크기 설정
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
// 카메라 설정
camera = new THREE.PerspectiveCamera( 45, 1, 1, 10000 ); // FOV, aspect, near, far
camera.position.x = 80;
camera.position.y = 50;
camera.position.z = 70;
//x-y-z axis (중심선)
const axesHelper = new THREE.AxesHelper(3);
axesHelper.position.x = 0;
axesHelper.position.y = 0;
axesHelper.position.z = 0;
scene.add(axesHelper); // scene에 추가
// grid helper
const size = 100;
const divisions = 100; // 나누는 개수
const gridHelper = new THREE.GridHelper( size, divisions, 0x444444, 0x888888 );
gridHelper.position.set(baseX/2,baseY/2,baseZ/2); // 그리드 중앙선 기준으로 (0, 0, 0)
scene.add( gridHelper );
document.body.appendChild( renderer.domElement ); // canvas 태그
controls = new OrbitControls( camera, renderer.domElement ); // scene 주위 공전
controls.enableDamping = true; // 부드러운 동작
controls.enablePan = false;
controls.enableZoom = false;
// controls.maxPolarAngle = Math.PI / 2; // 아래로 회전 제한 (바닥을 뚫지 않음)
controls.minPolarAngle = 0; // 위로 회전 제한
//controls.update()는 카메라 변환설정을 수동으로 변경한 후에 호출해야 합니다.
camera.position.set( 0, 20, 100 )
}
function animate() {
requestAnimationFrame( animate );
movePlayer();
controls.update();
renderer.render( scene, camera ); // sceene, camera 렌더링
}
init();
animate();
</script>
</head>
<body>
</body>
</html>
6. 결과
반응형
'IT > Three.js' 카테고리의 다른 글
[Three.js] Three.js OrbitControls 카메라 부드러운 이동하기 (0) | 2024.12.16 |
---|---|
[Three.js] Three.js 그리드(grid) 생성 및 예제(gridHelper) (1) | 2024.12.13 |
[Three.js] Three.js 장면(Scene) 생성 및 예제 (0) | 2024.12.13 |
[Three.js] Three.js Script 방식 정리 (0) | 2024.12.13 |
[Three.js] Three.js 알아보기 (1) | 2024.11.13 |
최근댓글