wam
w__am 개발노트
wam
  • 분류 전체보기 (165)
    • CS 지식 (10)
      • 자료구조 (0)
      • 알고리즘 (0)
      • 컴퓨터 구조 (0)
      • 운영체제 (0)
      • 네트워크 (7)
      • 데이터베이스 (0)
      • 디자인 패턴 (3)
    • Frontend (131)
      • Three.js (64)
      • NPM (1)
      • Nest.js (19)
      • React (10)
      • Apollo (7)
      • TypeScript (2)
      • JavaScript (12)
      • HTML, CSS (1)
      • Jest (3)
      • E2E (5)
      • Cypress (7)
    • Database (12)
      • TypeORM (12)
    • IT 지식 (8)
      • 클라우드 서비스 (3)
      • 네트워크 (1)
      • 데이터 포맷 (2)
      • 기타 (2)
    • IT Book (2)
    • 유용한 사이트 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 🐱 Github

인기 글

태그

  • axeshelper
  • 초기 환경설정
  • 원형적인 움직임
  • Interface
  • 함수의 범위
  • mapped types
  • reactive variables
  • 오프-프레미스(off-premise) 방식
  • Decorators
  • 함수 선언문
  • 데이터 포맷
  • 디자인 패턴
  • 함수 리터럴
  • gridhelper
  • 삼각함수
  • getelapsedtime()
  • react 성능 최적화
  • math.cos()
  • API
  • threejs 개발 할 때 도움을 줄 수 있는 유틸리티
  • 스코프
  • three.js 구성 요소
  • e.preventdefault()
  • 함수 표현식
  • getdelta()
  • isabstract
  • 렌더링 성능 최적화
  • joi 에러
  • type-graphql
  • math.sin()

최근 글

관리자

글쓰기 / 스킨편집 / 관리자페이지
hELLO · Designed By 정상우.
wam
Frontend/Three.js

Raycaster, 클릭한 Mesh 감지하기

Raycaster, 클릭한 Mesh 감지하기
Frontend/Three.js

Raycaster, 클릭한 Mesh 감지하기

2024. 11. 14. 15:46


마우스 이벤트 추가

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 범위로 매핑되게 된다.

 

 

마우스가 클릭되면 광선 위치 카메라 시점으로 세팅하기

/* 광선 만들기 */
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
  • 마우스 이벤트 추가
  • threejs에 맞게 좌표를 변환해야 한다.
  • 3차원 좌표로 변환하는 계산법
  • 마우스가 클릭되면 광선 위치 카메라 시점으로 세팅하기
  • 클릭한 물체 색상 변경
  • 재클릭해 원래 색상으로 변경
'Frontend/Three.js' 카테고리의 다른 글
  • glTF, 3D 모델과 장면을 경량화하고 빠르게 전송·렌더링하기 위한 표준 파일 포맷
  • Raycaster, 드래그 클릭 방지
  • Raycaster, 특정 방향의 광선(Ray)에 맞은 Mesh 판별하기
  • Raycaster, 동작 원리
wam
wam

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.