개발자일기/3D 웹 세상

react-three-rapier로 물리 엔진 연동하기

뫙뭉 2024. 11. 14. 10:56
반응형

 

3D 그래픽을 더욱 현실감 있게 만들기 위해 물리 엔진을 추가하면 객체가 중력에 반응하고 충돌하는 등의 물리적 효과를 구현할 수 있다. react-three-rapier는 Rapier라는 경량 물리 엔진을 react-three-fiber와 통합하여, React에서 쉽게 물리 효과를 적용할 수 있게 해주는 라이브러리다. 이번 글에서는 react-three-rapier의 기본 사용법과 주요 개념을 통해 3D 장면에 물리적 상호작용을 추가해 보겠다.

 

react-three-rapier 공식 github: https://github.com/pmndrs/react-three-rapier

 

GitHub - pmndrs/react-three-rapier: 🤺 Rapier physics in React

🤺 Rapier physics in React. Contribute to pmndrs/react-three-rapier development by creating an account on GitHub.

github.com

 

 

이전 글

1. [개발자일기/3D 웹 세상] - 웹에서의 3D 그래픽

2. [개발자일기/3D 웹 세상] - Three.js의 기본 개념과 원리

3. [개발자일기/3D 웹 세상] - Three.js의 기본 개념과 원리

4. [개발자일기/3D 웹 세상] - React와 Three.js의 결합: react-three-fiber

5. [개발자일기/3D 웹 세상] - react-three-fiber로 간단한 3D 객체 렌더링하기

6. [개발자일기/3D 웹 세상] - Three.js에서 조명과 재질을 사용해보자!

7. [개발자일기/3D 웹 세상] - Three.js에서 조명과 재질을 사용해보자!

8. [개발자일기/3D 웹 세상] - Three.js 애니메이션과 인터랙션

9. [개발자일기/3D 웹 세상] - 3D 물리 엔진 개요와 Three.js에서의 사용

 


 

1. 프로젝트 준비: react-three-rapier 설치

 

먼저 react-three-rapier와 @react-three/fiber를 프로젝트에 설치해야 한다. 다음 명령어를 실행하여 필요한 패키지를 설치하자.

 

npm install @react-three/fiber @react-three/rapier
 

설치가 완료되면, react-three-rapier를 사용해 물리 효과가 적용된 3D 객체를 만들 준비가 완료된다.

 

 


 

2. 물리 세계(World) 생성하기

 

react-three-rapier에서 물리적 상호작용을 구현하기 위해 먼저 World라는 물리 세계를 생성해야 한다. World는 모든 물리 객체들이 존재하는 환경을 의미하며, Physics 컴포넌트를 사용해 Three.js 장면에 물리 세계를 추가할 수 있다.

 

기본적인 Physics 컴포넌트 예제

 

import { Canvas } from '@react-three/fiber';
import { Physics } from '@react-three/rapier';

function App() {
  return (
    <Canvas>
      <Physics>
        {/* 물리 엔진이 적용된 객체들을 이 안에 추가 */}
      </Physics>
    </Canvas>
  );
}

export default App;
 

위 예제에서 Physics 컴포넌트는 Three.js 장면에 물리 엔진을 활성화하고, 모든 물리 객체가 이 컴포넌트 내부에서 동작하도록 만든다. 이 Physics 내부에 물리적 효과를 적용할 객체들을 추가할 수 있다.

 


 

3. RigidBody: 고정된 물리 객체 만들기

 

react-three-rapier에서 RigidBody 컴포넌트는 물리 엔진의 기본 요소로, 중력과 충돌 같은 물리 법칙이 적용되는 객체를 생성한다. 예를 들어, 바닥과 같은 고정된 객체와 중력의 영향을 받는 상자 객체를 만들 수 있다.

 

예제: 고정된 바닥과 중력의 영향을 받는 상자

 

import { Canvas } from '@react-three/fiber';
import { Physics, RigidBody } from '@react-three/rapier';

function Box() {
  return (
    <RigidBody>
      <mesh>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="orange" />
      </mesh>
    </RigidBody>
  );
}

function Floor() {
  return (
    <RigidBody type="fixed">
      <mesh position={[0, -1, 0]}>
        <boxGeometry args={[10, 1, 10]} />
        <meshStandardMaterial color="lightgray" />
      </mesh>
    </RigidBody>
  );
}

function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <Physics gravity={[0, -9.81, 0]}>
        <Floor />
        <Box />
      </Physics>
    </Canvas>
  );
}

export default App;
 

 

  • RigidBody: RigidBody는 물리적인 상호작용을 가진 객체를 나타내며, 중력, 충돌 등의 물리 효과가 적용된다.
  • type="fixed": RigidBody에 type="fixed"를 설정하면 객체가 고정되어 중력의 영향을 받지 않으며, 다른 객체와의 충돌만을 처리한다.
  • Physics gravity 속성: Physics 컴포넌트의 gravity 속성을 통해 장면의 중력 방향과 세기를 설정할 수 있다. 위 예제에서는 y축 방향으로 -9.81의 중력을 적용했다.

 

 

 


 

4. 충돌 감지와 반응 구현하기

 

react-three-rapier에서는 물체 간의 충돌을 감지하고 반응을 설정할 수 있다. 예를 들어, 두 개의 상자가 충돌했을 때 색상이 변경되도록 하는 코드를 작성할 수 있다.

 

예제: 충돌 시 색상 변경

import { useRef, useState } from 'react';
import { Canvas } from '@react-three/fiber';
import { Physics, RigidBody } from '@react-three/rapier';

function CollidableBox() {
  const [color, setColor] = useState("orange");
  const boxRef = useRef();

  function handleCollisionEnter() {
    setColor("red"); // 충돌 시 색상 변경
  }

  function handleCollisionExit() {
    setColor("orange"); // 충돌 해제 시 색상 복귀
  }

  return (
    <RigidBody
      ref={boxRef}
      onCollisionEnter={handleCollisionEnter}
      onCollisionExit={handleCollisionExit}
    >
      <mesh>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color={color} />
      </mesh>
    </RigidBody>
  );
}

function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <Physics gravity={[0, -9.81, 0]}>
        <CollidableBox />
        <CollidableBox position={[0, 3, 0]} />
      </Physics>
    </Canvas>
  );
}

export default App;

 

 

  • onCollisionEnter: 물체가 다른 물체와 충돌했을 때 호출되는 이벤트로, 이 예제에서는 색상을 빨간색으로 변경한다.
  • onCollisionExit: 충돌이 해제될 때 호출되는 이벤트로, 색상을 원래대로 복귀시킨다.

 

 


 

5. 상호작용 추가하기: 마우스로 물체 드래그하기

 

react-three-rapier는 마우스를 이용해 3D 객체를 드래그하거나 이동할 수 있는 상호작용을 지원한다. 마우스를 이용해 객체를 드래그하여 이동시키려면 RaycastingonPointerDown 이벤트를 사용하여 물체를 드래그할 수 있도록 구현할 수 있다.

 

간단한 드래그 예제

import { useRef } from 'react';
import { Canvas } from '@react-three/fiber';
import { Physics, RigidBody } from '@react-three/rapier';

function DraggableBox() {
  const boxRef = useRef();

  function onPointerDown(event) {
    const body = boxRef.current;
    body.applyImpulse({ x: 5, y: 5, z: 0 }); // 클릭 시 임의의 힘을 적용
  }

  return (
    <RigidBody ref={boxRef} onPointerDown={onPointerDown}>
      <mesh>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="blue" />
      </mesh>
    </RigidBody>
  );
}

function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <Physics gravity={[0, -9.81, 0]}>
        <DraggableBox />
      </Physics>
    </Canvas>
  );
}

export default App;
 

 

  • onPointerDown: 사용자가 객체를 클릭할 때 호출되는 이벤트로, 클릭 시 특정 방향으로 힘을 가해 객체가 움직이게 한다.
  • applyImpulse: applyImpulse 메서드는 클릭 시 즉각적인 힘을 가해 객체가 순간적으로 이동하도록 한다.

 

 


 

결론

 

react-three-rapier는 Three.js와 Rapier 물리 엔진을 결합하여 React 환경에서 쉽게 물리적 상호작용을 구현할 수 있게 해준다. RigidBody를 사용해 물리 객체를 생성하고, 충돌 감지와 이벤트 핸들링을 통해 더욱 인터랙티브한 3D 장면을 만들 수 있다. 이를 통해 사용자에게 더욱 몰입감 있는 3D 경험을 제공할 수 있으며, 다양한 상호작용과 물리 효과를 추가해 볼 수 있다.

 
반응형