3D 그래픽을 더욱 현실감 있게 만들기 위해 물리 엔진을 추가하면 객체가 중력에 반응하고 충돌하는 등의 물리적 효과를 구현할 수 있다. react-three-rapier는 Rapier라는 경량 물리 엔진을 react-three-fiber와 통합하여, React에서 쉽게 물리 효과를 적용할 수 있게 해주는 라이브러리다. 이번 글에서는 react-three-rapier의 기본 사용법과 주요 개념을 통해 3D 장면에 물리적 상호작용을 추가해 보겠다.
react-three-rapier 공식 github: https://github.com/pmndrs/react-three-rapier
이전 글
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 객체를 드래그하거나 이동할 수 있는 상호작용을 지원한다. 마우스를 이용해 객체를 드래그하여 이동시키려면 Raycasting과 onPointerDown 이벤트를 사용하여 물체를 드래그할 수 있도록 구현할 수 있다.
간단한 드래그 예제
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 경험을 제공할 수 있으며, 다양한 상호작용과 물리 효과를 추가해 볼 수 있다.
'개발자일기 > 3D 웹 세상' 카테고리의 다른 글
3D 물리 엔진 개요와 Three.js에서의 사용 (0) | 2024.11.12 |
---|---|
Three.js 애니메이션과 인터랙션 (0) | 2024.11.11 |
Three.js에서 조명과 재질을 사용해보자! (0) | 2024.11.10 |
react-three-fiber로 간단한 3D 객체 렌더링하기 (0) | 2024.11.09 |
React와 Three.js의 결합: react-three-fiber (1) | 2024.11.08 |