[Three] 1인칭 화면 회전 만들기

2025. 7. 9. 21:33·Frontend

카메라가 1인칭 시점으로 있을 때 마우스 움직임에 따라 화면을 회전시키는 방법에 대해 서술합니다.

1. 마우스 움직임 추적

마우스가 움직일 때를 다루는 이벤트는 'mousemove'이며, MouseEvent로 접근할 수 있습니다.

 

MouseEvent의 movementX, movementY 자체는 값이 많이 커서, 튀는 걸 방지하기 위해 작은 값을 곱해줍니다.

const mouseDel = new Vector2();

const updateMouse = (e: MouseEvent) => {
    mouseDel.x = e.movementX * 0.001;
    mouseDel.y = e.movementY * 0.001;
}

document.addEventListener('mousemove', updateMouse);

2. 카메라 회전

const euler = new Euler(0, 0, 0, 'YXZ');
const minPolarAngle = -Math.PI / 2;
const maxPolarAngle = Math.PI / 2;
const camOffset = new Vector3(0, 1, 0);

const rotate = (camera: Camera) => {
    euler.setFromQuaternion(camera.quaternion);
    // yaw
    euler.y -= mouseDel.x;
    // pitch
    euler.x -= mouseDel.y;
    // clamp
    euler.x = Math.max(minPolarAngle, Math.min(maxPolarAngle, euler.x));
    // smoothing
    mouseDel.x *= 0.8;
    mouseDel.y *= 0.8;
    if (Math.abs(this.mouseDel.x) < 0.1) mouseDel.x = 0;
    if (Math.abs(this.mouseDel.y) < 0.1) mouseDel.y = 0;
    
    camera.quaternion.setFromEuler(euler);
    // apply camer direction to the player direction
    agent.rotation.y = euler.y;
    // position
    camera.position.copy(agent.position.clone().add(camOffset));
}

먼저 수정 사항을 적용할 euler 변수를 만들어 현재 카메라의 회전값을 설정해둡니다.

euler.setFromQuaternion(camera.quaternion);

updateMouse( )로 갱신한 마우스 이동값을 euler에 더해줍니다.

 

좌우 회전(mouseDel.x)은 y(수직축)축을 기준으로 회전하기 때문에 euler의 y축에 더해줍니다.

 

상하 회전(mouseDel.y)은 x(수평축)축을 기준으로 회전하기 때문에 euler의 x축에 더해줍니다.

 

단, 상하 회전의 경우 너무 위로, 또는 너무 아래로 돌아 넘어가지 않도록 상한선과 하한선을 정해줍니다.

    // yaw
    euler.y -= mouseDel.x;
    // pitch
    euler.x -= mouseDel.y;
    // clamp
    euler.x = Math.max(minPolarAngle, Math.min(maxPolarAngle, euler.x));

마우스 이동값을 조금씩 감쇠시켜 부드러운 움직임을 유도합니다.

 

단, 너무 작은 값이 되지 않게 일정 수치 이하가 되면 0으로 처리합니다.

    // smoothing
    mouseDel.x *= 0.8;
    mouseDel.y *= 0.8;
    if (Math.abs(this.mouseDel.x) < 0.1) mouseDel.x = 0;
    if (Math.abs(this.mouseDel.y) < 0.1) mouseDel.y = 0;

이렇게 수정한 euler 값을 다시 카메라의 회전값에 집어 넣습니다.

 

또한 카메라가 따라다닐 플레이어(행위자)의 시점도 euler 값으로 설정합니다.

    camera.quaternion.setFromEuler(euler);
    // apply camera direction to the player direction
    agent.rotation.y = euler.y;

마지막으로 카메라를 플레이어의 위치에 놓습니다.

 

플레이어 객체의 눈 높이를 반영하여 y=1로 하였습니다.

const camOffset = new Vector3(0, 1, 0);

// ...

    // position
    camera.position.copy(agent.position.clone().add(camOffset));

3. 적용

만든 rotate() 함수를 update 루프 함수 안에서 호출합니다.

useEffect(() => {
    // ...
    const update = () => {
        // ...
        controller.rotate(camera);
        // ...
        renderer.render(scene, camera);
        renderer.setAnimationLoop(update);
    }
}, []);
728x90

'Frontend' 카테고리의 다른 글

[Three] 10. Ray casting  (0) 2025.09.04
[Three] Cannon.js - 물리엔진 적용하기  (1) 2025.07.10
[Three] 윈도우 크기에 따라 반응형으로 만들기  (0) 2025.07.05
[Three] 09. Loader - GLTF  (0) 2025.06.16
[Three] 08. Material  (0) 2025.05.16
'Frontend' 카테고리의 다른 글
  • [Three] 10. Ray casting
  • [Three] Cannon.js - 물리엔진 적용하기
  • [Three] 윈도우 크기에 따라 반응형으로 만들기
  • [Three] 09. Loader - GLTF
Rayi
Rayi
  • Rayi
    아카이브
    Rayi
  • 전체
    오늘
    어제
    • 분류 전체보기 (262)
      • CS (40)
        • ML (3)
        • CV (2)
        • PS (34)
      • Reveiw (17)
        • Paper (17)
        • Github (0)
      • Pytorch (5)
      • Language (58)
        • Python (7)
        • JavaScript (32)
        • TypeScript (16)
        • C++ (3)
      • IDE (12)
      • Git (13)
      • Frontend (71)
        • React (8)
        • SolidJS (20)
        • CSS (12)
      • UI (3)
      • Backend (15)
        • DB (17)
        • Node.js (11)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    PRISMA
    SOLID
    GAN
    react
    Git
    vscode
    API
    figma
    UI
    Express
    ts
    js
    python
    ML
    C++
    backend
    PyTorch
    frontend
    review
    postgresql
    CS
    Three
    CV
    mongo
    ps
    DB
    deploy
    nodejs
    html
    CSS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Rayi
[Three] 1인칭 화면 회전 만들기
상단으로

티스토리툴바