마우스 이벤트 추가
const mouse = new THREE.Vector2(); /* 이벤트 */ window.addEventListener("resize", setSize); canvas.addEventListener("click", (e) => { console.log("📢 [ex02_eventClick.js:85]", e); });
// 이벤트 콘솔 결과 PointerEvent { clientX: 300, clientY : 200 }
마우스로 클릭한 위치 표시 - clientX, clientY
threejs에 맞게 좌표를 변환해야 한다.

/* 2D 화면상의 마우스 위치 만들기 */ const mouse = new THREE.Vector2(); /* 이벤트 */ window.addEventListener("resize", setSize); canvas.addEventListener("click", (e) => { console.log("📢 [ex02_eventClick.js:85]", e); // threejs에 맞게 3차원 좌표로 변환 // 실제 클릭한 좌표의 위치 : e.clientX, e.clientY mouse.x = (e.clientX / canvas.clientWidth) * 2 - 1; mouse.y = -((e.clientY / canvas.clientHeight) * 2 - 1); console.log("📢 [ex02_eventClick.js:89]", mouse);
- Three.js에서 화면상의 2D 좌표 (clientX, clientY)를 WebGL의 3D 공간에 맞는 좌표로 변환해야 한다.
- ThreeJS는 가운데가 0이어야 한다.
- e.clientX는 클릭한 위치의 좌표이다.
3차원 좌표로 변환하는 계산법
- X좌표 변환:
- e.clientX는 클릭한 위치의 X 좌표이다.
- canvas.clientWidth는 캔버스의 가로길이이다.
- (e.clientX / canvas.clientWidth)는 클릭한 위치가 화면에서 차지하는 비율을 구한다.
- 값은 0에서 1 사이이다.
- * 2 - 1을 통해 비율을 -1에서 1 범위로 변환한다.
- mouse.x = (e.clientX / canvas.clientWidth) * 2 - 1;
- Y좌표 변환:
- e.clientY는 클릭한 위치의 Y 좌표이다.
- canvas.clientHeight는 캔버스의 세로 길이이다.
- (e.clientY / canvas.clientHeight)는 클릭 위치의 비율을 구한다.
- * 2 - 1로 NDC의 범위에 맞춘 후 -를 붙여 Y축 방향을 반전한다.
- mouse.y = **-**((e.clientY / canvas.clientHeight) * 2 - 1);
- 전체 길이를 두 배로 늘려서 -1에서 1 사이의 값으로 만드는 과정
- 0에서 1 사이 값
- 클릭 위치 비율이 0일 때는 0이고, 1일 때는 1이다.
- 두 배로 확장
- 여기에 * 2를 하면,
- 0은 여전히 0 * 2 = 0.
- 1은 1 * 2 = 2로 2배로 늘어난다.
- 범위 이동
- 이 값을 - 1을 해주어 -1에서 1 사이로 이동시킨다.
- 0은 0 * 2 - 1 = -1로 변환된다.
- 0.5는 0.5 * 2 - 1 = 0으로 변환된다.
- 1은 1 * 2 - 1 = 1로 변환된다.
- 이렇게 함으로써, 화면상의 0~1 비율이 NDC 좌표계의 -1~1 범위로 매핑되게 된다.
- 0에서 1 사이 값
마우스가 클릭되면 광선 위치 카메라 시점으로 세팅하기
/* 광선 만들기 */ const raycaster = new THREE.Raycaster(); function checkIntersects() { // 카메라와 마우스 위치를 사용해 Raycaster 업데이트 raycaster.setFromCamera(mouse, camera); // 마우스 위치와 교차하는 객체 확인 const intersects = raycaster.intersectObjects(meshes); for (const item of intersects) { console.log(item.object.name); } } /* 이벤트 */ window.addEventListener("resize", setSize); canvas.addEventListener("click", (e) => { // threejs에 맞게 3차원 좌표로 변환 mouse.x = (e.clientX / canvas.clientWidth) * 2 - 1; // 실제 클릭한 X의 위치 : e.clientX mouse.y = -((e.clientY / canvas.clientHeight) * 2 - 1); // 실제 클릭한 Y의 위치 : e.clientY checkIntersects(); });
- setFromCamera
- Three.js의 Raycaster 클래스에서 사용되는 메서드이다.
- 2D 화면상의 마우스 위치를 3D 공간의 광선(Ray)으로 변환하는 데 사용한다.
- Raycaster의 방향과 시작 위치를 카메라를 기준으로 설정한다.
- 이때 mouse 위치를 기준으로 화면을 향하는 3D 광선이 생성된다.
- 자동으로 카메라 위치를 origin으로 잡아서 마우스 클릭한 지점으로 광선이 세팅된다.
클릭한 물체 색상 변경
function checkIntersects() { // 카메라와 마우스 위치를 사용해 Raycaster 업데이트 raycaster.setFromCamera(mouse, camera); // 마우스 위치와 교차하는 객체 확인 const intersects = raycaster.intersectObjects(meshes); for (const item of intersects) { console.log(item.object.name); // 광선이 관통하면 색상이 변경되도록 설정 item.object.material.color.set("red"); break; // 첫 번째 물체만 작동하기 위해 break 작동시킴 } }
- for ... of 사용해 원소를 돌면서 아이템이라는 이름으로 세팅하기
- 물체를 관통을 하기 때문에 클릭 시 두 물체가 있으면 다 잡힌다.
- 처음 잡힌 물체만 선택되길 원한다면 break를 추가해 주면 된다.
재클릭해 원래 색상으로 변경
// 객체 초기화 시 원래 색상을 저장 for (const mesh of meshes) { mesh.originalColor = mesh.material.color.clone(); } function checkIntersects() { // 카메라와 마우스 위치를 사용해 Raycaster 업데이트 raycaster.setFromCamera(mouse, camera); // 마우스 위치와 교차하는 객체 확인 const intersects = raycaster.intersectObjects(meshes); for (const item of intersects) { // 색상이 이미 빨간색인지 확인 if (item.object.material.color.equals(new THREE.Color("red"))) { // 빨간색이면 원래 색상으로 변경 item.object.material.color.copy(item.object.originalColor); } else { // 원래 색상이면 빨간색으로 변경 item.object.material.color.set("red"); } break; // 첫 번째 교차한 객체만 처리 } }
'Frontend > Three.js' 카테고리의 다른 글
glTF, 3D 모델과 장면을 경량화하고 빠르게 전송·렌더링하기 위한 표준 파일 포맷 (0) | 2024.11.26 |
---|---|
Raycaster, 드래그 클릭 방지 (0) | 2024.11.25 |
Raycaster, 특정 방향의 광선(Ray)에 맞은 Mesh 판별하기 (0) | 2024.11.12 |
Raycaster, 동작 원리 (0) | 2024.11.12 |
조명, RectAreaLight_직사각형 모양으로 균일한 빛을 방사하는 조명 효과 (0) | 2024.11.11 |