Three.js에는 미리 만들어져있는 다양한 컨트롤들이 존재하는데 이들에 대해서 소개를 좀 하고자 한다.
미리 만들어져있어서 쓰기는 편하지만 새로운 기능을 추가할때는 까다로울 수 있기 때문에 새로 카메라 컨트롤을 직접 만들지 기존 컨트롤을 수정할지는 상황에 따라 진행하면 된다.
궤도 컨트롤이라고 부르며 사용 방법은 다음과 같다.
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const geometry = new THREE.BoxGeometry(1, 1, 1);
let mesh;
let material;
const controls = new OrbitControls(camera, renderer.domElement);
for (let i = 0; i < 20; i++) {
// 배경이 0에 가까워지면 안보일 수 있기 때문에 이를 방지하기 위해 초기 50값을 줌
material = new THREE.MeshStandardMaterial({
color: `rgb(
${50 + Math.floor(Math.random() * 205)},
${50 + Math.floor(Math.random() * 205)},
${50 + Math.floor(Math.random() * 205)}
)`,
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.x = (Math.random() - 0.5) * 5;
mesh.position.y = (Math.random() - 0.5) * 5;
mesh.position.z = (Math.random() - 0.5) * 5;
scene.add(mesh);
}
결과
그리고 다양한 옵션이 존재한다 예로 enableDamping의 옵션을 활성화 해주면 화면의 움직임이 부드럽게 처리가 된다.
const geometry = new THREE.BoxGeometry(1, 1, 1);
let mesh;
let material;
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
for (let i = 0; i < 20; i++) {
// 배경이 0에 가까워지면 안보일 수 있기 때문에 이를 방지하기 위해 초기 50값을 줌
material = new THREE.MeshStandardMaterial({
color: `rgb(
${50 + Math.floor(Math.random() * 205)},
${50 + Math.floor(Math.random() * 205)},
${50 + Math.floor(Math.random() * 205)}
)`,
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.x = (Math.random() - 0.5) * 5;
mesh.position.y = (Math.random() - 0.5) * 5;
mesh.position.z = (Math.random() - 0.5) * 5;
scene.add(mesh);
}
function draw() {
const delta = clock.getDelta();
// enableDamping은 update()함수를 호출해주어야 한다.
controls.update();
renderer.render(scene, camera);
renderer.setAnimationLoop(draw);
}
적용 전
적용 후
옵션 | 설명 |
---|---|
enableDamping | 화면 회전에 부드러움 적용 |
enableZoom | 마우스 줌이 불가능하게 막는다. |
minDistance, maxDistance | 마우스 줌의 거리를 조절할 수 있다. |
minPolarAngle, maxPolarAngle | 수직으로 돌아가는 각도를 막을 수 있다. |
autoRotate | 자동으로 화면이 돌아가도록 한다. |
autoRotateSpeed | 자동으로 화면이 돌아가는 속도를 조절한다. |
enableZoom | 줌이 불가능하게 막을 수 있다. |
OrbitControls와 동일하지만 트랙볼 방향으로 컨트롤 할 수 있다는 점과 update메서드를 호출을 해주어야 사용이 가능하다.
트랙볼 마우스를 생각하면 될듯하다.
다른 컨트롤과는 다르게 update 메서드 매개변수에 delta값을 넣어주어야 동작한다. autoForward속성을 true로 하면 controls이 앞으로 계속 움직이도록 할수있다.
const controls = new FlyControls(camera, renderer.domElement);
function draw() {
const delta = clock.getDelta();
controls.update(delta);
renderer.render(scene, camera);
renderer.setAnimationLoop(draw);
}
마우스 컨트롤 조정
키보드 컨트롤 조정
FlyControls의 대체구현으로 FlyControls와 동일하게 동작하며 activeLook 옵션을 false로 지정하면 좌우 주변을 둘러볼 수 없다.
다른 Controls과는 다르게 update메서드가 존재하지 않는다. 이 컨트롤을 실행하려면 lock 메서드를 실행해야 하는데 이것은 사용자의 특정 동작에 의해서 메서드를 실행해야한다.
이 컨트롤러를 실행하면 화면 상단에 커서를 표시하려면 ESC를 누르세요.
라는 문구가 나타나게 된다.
// 캔버스 메서드
controls.domElement.addEventListener("click", () => {
controls.lock();
});
각 오브젝트를 이동시킬때 사용하는 컨트롤러이다. 드래그가 시작될때나 완료가 되었을때 이벤트를 처리해할수있다.
PointerLockControls에 키보드의 움직임을 추가하면 마인크래프트 스타일의 컨트롤이 완성된다.
export class KeyController {
constructor() {
this.keys = [];
window.addEventListener("keydown", (e) => {
this.keys[e.code] = true;
});
window.addEventListener("keyup", (e) => {
delete this.keys[e.code];
});
}
}
PointerLock에는 moveFoward 메서드와 moveRight 메서드밖에 없기때문에 뒤로 이동 혹은 왼쪽으로 이동은 -값을 넣어주면 된다
// Controls
const controls = new PointerLockControls(camera, renderer.domElement);
// 캔버스 메서드
controls.domElement.addEventListener("click", () => {
controls.lock();
});
const keyController = new KeyController();
const walk = () => {
if (keyController.keys["KeyW"]) {
controls.moveForward(0.05);
} else if (keyController.keys["KeyD"]) {
controls.moveRight(0.05);
} else if (keyController.keys["KeyA"]) {
controls.moveRight(-0.05);
} else if (keyController.keys["KeyS"]) {
controls.moveForward(-0.05);
}
};
function draw() {
walk();
renderer.render(scene, camera);
renderer.setAnimationLoop(draw);
}