[three.js] Controls

chaewon Im·2022년 11월 23일
0

공부 기록✏️

목록 보기
15/15
post-thumbnail

Controls

카메라를 쉽게 컨트롤 하기 위해 Controls 객체를 사용하여 시야를 컨트롤 한다.
미리 만들어져서 사용이 쉽지만, 특정 기능을 추가하기엔 까다로울 수 있다.
-> (이 경우 커스텀을 위해 기본적으로 제공하는 controls 기능에 추가로 기능을 구현할 것인지, 새롭게 control을 하는 객체를 만들 것인지 결정해야 함)

controls 종류

  • OrbitControls ⭐
  • TrackballControls
  • FlyControls
  • FirstPersonControls
  • PointerLockControls
  • DragControls

OrbitControls

✔ 타겟 대상을 중심으로 카메라를 여러 방향으로 회전시킬 수 있다.

new OrbitControls(object: Camera(필수), domElement: HTMLDOMElement)

➡ 첫 번째 매개변수로 컨트롤을 할 카메라 오브젝트를 전달하고, 두 번째 인자로는 이벤트 리스너를 적용할 HTML DOM 엘리먼트(=three.js 캔버스)를 전달한다.

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
const controls = new OrbitControls( camera, renderer.domElement );
controls.enableDamping = true;
controls.enableZoom = false;
controls.maxDistance = 10;
controls.minDistance = 3;
controls.minPolarAngle = Math.PI / 4; //45deg
controls.maxPolarAngle = THREE.MathUtils.degToRad(45);

camera.position.set( 0, 20, 100 );
controls.update();

function animate() {
	requestAnimationFrame( animate );
	controls.update();
	renderer.render( scene, camera );
}

컨트롤을 정의한 후 갱신이 생기면 update()메서드를 적용해주어야 한다.

대표적인 속성

  • .target.set(x, y, z)
    - 회전축 기준점을 x,y,z 좌표로 설정할 수 있다.
  • .enableDamping : boolean
    - 화면 회전 시에 부드럽게 감속이 되며 회전이 되는 효과를 낼 수 있다.
  • .enableZoom : boolean
    - 줌을 적용할 것인지 여부
  • .maxDistance : number
    - 줌 적용 시, 카메라 줌이 가능한 최대 거리(가장 먼 곳)
  • .minDistance : number
    - 줌 적용 시, 카메라 줌이 가능한 최소 거리(가장 가까운 곳)
  • .minPolarAngle : number
    - 수직 방향을 기준으로 회전이 가능한 최소 각도, 범위: 0~Math.PI radian
  • .maxPolarAngle : number
    - 수직 방향을 기준으로 회전이 가능한 최대 각도, 범위: 0~Math.PI radian
    • 우리가 아는 각도를 기준으로 숫자를 지정하려면 THREE의 내장 객체인 MathUtils를 이용하면 일반 degree를 radian 기준으로 변환해준다.
    • THREE.MathUtils.degToRad(45); -> 45도

그 외의 속성들은 필요에 따라 공식 문서: OrbitControls 에서 확인할 수 있다.


TrackballControls

✔ OrbitControls와 유사하게 동작한다.

[ OrbitControls ]와의 차이점

  1. .enableDamping 속성이 이미 적용된 것 처럼 부드럽게 동작한다.
  2. 첫 세팅 시 update() 함수를 호출하지 않으면 적용이 되지 않는다.
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls';

const controls = new TrackballControls(camera, renderer.domElement);

controls.maxDistance = 120;
controls.minDistance = 5;

대표적인 속성

  • .target.set(x, y, z)
    - 회전축 기준점을 x,y,z 좌표로 설정할 수 있다.
  • .maxDistance : number
    - 줌 적용 시, 카메라 줌이 가능한 최대 거리(가장 먼 곳)
  • .minDistance : number
    - 줌 적용 시, 카메라 줌이 가능한 최소 거리(가장 가까운 곳)

공식 문서: TrackballControls


FlyControls

✔ 게임처럼 방향키를 이용해서 화면을 컨트롤 할 수 있게 도와준다.

특징

  1. update시 delta값을 전달해주어야 한다.
  2. 키보드 자판, 방향키, 그리고 마우스를 이용해서 화면을 컨트롤 할 수 있다.
    • w, 마우스 왼쪽 클릭: 앞으로 전진
    • a: 왼쪽으로 이동
    • s, 마우스 오른쪽 클릭: 뒤로 후진
    • d: 오른쪽으로 이동
    • e: 왼쪽으로 회전
    • q: 오른쪽으로 회전
    • r: 위로 이동
    • f: 아래로 이동
    • 방향키 위: 위쪽으로 회전
    • 방향키 아래: 아래쪽으로 회전
    • 방향키 좌: 왼쪽으로 회전
    • 방향키 우: 오른쪽으로 회전
import { FlyControls } from 'three/examples/jsm/controls/FlyControls';

const controls = new FlyControls(camera, renderer.domElement);

controls.rollSpeed = 0.5;
controls.movementSpeed = 1;
controls.dragToLook = true;

const clock = new THREE.Clock();
function draw() {
	const delta = clock.getDelta();

	controls.update(delta);

	renderer.render(scene, camera);
	renderer.setAnimationLoop(draw);
}
draw();
    

대표적인 속성

  • .rollSpeed : number
    - 회전 속도를 설정하는 속성. 기본값은 0.005
  • .movementSpeed : number
    - 움직임 속도를 설정하는 속성. 기본값은 1
  • .dragToLook : boolean
    - 기본적으로 FlyControls는 마우스 움직임도 인식해서 화면을 회전시키는데, 해당 옵션을 true로 주면 마우스 움직임과 클릭은 인식하지 않고 마우스 드래그에만 반응하게 만들 수 있다.

공식 문서: FlyControls


FirstPersonControls

✔ FlyControls의 대체 구현 버전으로, FlyControls에 몇 가지 기능을 추가하거나 수정해서 다시 내놓은 버전이다.
따라서 FlyControls와 대부분의 동작이 유사하다.
컨트롤에 사용되는 키도 FlyControls와 동일하고, update시에 delta 값을 전달해야 하는 것도 동일하다.

FlyControls와 다른 속성

  • .activeLook : boolean
    - 주변을 둘러볼 수 없도록 막는 설정. false로 설정하면 드래그나 방향키로 카메라를 움직일 수 없다.
  • .lookSpeed : number
    - FlyControls의 rollSpeed와 같은 효과, 카메라 회전 속도를 설정하는 속성. 기본값은 0.005
  • .autoForward : boolean
    - 자동으로 카메라가 앞으로 전진하게 만드는 속성. true로 설정 시 카메라가 앞으로 계속 이동한다.

공식 문서: FirstPersonControls


PointerLockControls

✔ 특정 이벤트 발생 시에 Controls를 활성화 시킬 수 있다.

특징

  1. 다른 controls와 다르게 생성만으로 실행되지 않는다. lock()이라는 메서드가 실행된 이후에만 활성화 된다.
  2. 이 lock메서드는 그냥 실행시킬 수 없다. 유저의 어떤 동작이 있을 때에만 실행된다.
  3. 따라서 addEventListener의 콜백 함수 안에서 controls.lock()을 실행시켜야 한다.
  4. 이 때 addEventListener는 controls의 domElement에 바인딩 해주어야 한다.
  5. controls가 활성화 되면 마우스 커서가 사라지고, 마우스를 이용해 화면을 컨트롤 할 수 있다.
  6. esc 키를 누르면 다시 controls가 비활성화 되고 커서가 나타난다.
  7. controls 자체에도 이벤트 리스너를 바인딩 할 수 있다. 'lock', 'change', 'unlock' 시 수행할 동작이 있다면 지정할 수 있다.
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls';

const controls = new PointerLockControls(camera, renderer.domElement);

controls.domElement.addEventListener('click', () => {
	controls.lock();
});

controls.addEventListener('lock', () => {
	console.log('lock!');
});
controls.addEventListener('change', () => {
	console.log('움직이는 중');
});
controls.addEventListener('unlock', () => {
	console.log('unlock!');
});

대표 Method

  • .moveForward(distance:Number) : xz평면과 평행하게 앞, 뒤로 움직인다. distance 값을 음수로 주면 뒤로 이동한다.
  • .moveRight(distance:Number) : xz평면과 평행하게 좌, 우로 움직인다. distance 값을 음수로 주면 왼쪽으로 이동한다.

공식 문서: PointerLockControls


DragControls

✔ 드래그앤드롭 인터랙션을 제공하는 Controls.
DragControls( objects : Array, camera : Camera, domElement : HTMLDOMElement )

특징

  1. 다른 controls와 다르게 드래그 앤 드롭 인터랙션을 적용할 3D Object Array를 첫 번째 매개변수로 전달한다.
  2. 이 때 전달되는 3D Object는 Three.js로 생성한 Mesh Object여야 한다.
  3. 이벤트 리스너에서 이벤트 객체를 전달받아 클릭한 target object의 정보를 확인할 수 있다.
import { DragControls } from 'three/examples/jsm/controls/DragControls';

// Mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const meshes = [];
let mesh;
let material;
for (let i = 0; i < 20; i++) {
	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;
	mesh.name = `box-${i}`;
	scene.add(mesh);
	meshes.push(mesh);
}

// Controls
const controls = new DragControls(meshes, camera, renderer.domElement);

controls.addEventListener('dragstart', e => {
	console.log(e.object.name);
});

mesh 생성 시에 name을 설정하고, addEventListener에서 drag가 시작될 때 타겟 mesh의 name을 출력하도록 하는 코드이다.

dragControls의 drag event

  • dragstart : 드래그 시작 시
  • drag : 드래그 중
  • dragend : 드래그 후
  • hoveron : 마우스 커서가 타겟 3d 오브젝트(혹은 타겟 3d 오브젝트의 자식요소) 위에 올라갈 때
  • hoveroff : 마우스 커서가 타겟 3d 오브젝트 위에서 나올 때

공식 문서: DragControls

profile
빙글빙글 FE 개발자

0개의 댓글