이번에는 React Three Fiber를 이용해 오브젝트를 이동, 변형하는 방법에 대해 알아보자.
이전 글은 아래를 참고해주세요.
【React Three Fiber】#01 시작하기(초기 설정, 정육면체 렌더링)
현재 일본 파견회사에서 3년 이상(4년 차) 일하고 있는데, 안 그래도 낮은 연봉이 인상도 잘 안될뿐더러, 한심한 사장을 보고 앞으로의 비전도 없다고 느꼈기 때문에 (대부분의 파견회사가 여기
solitary-choi.tistory.com
1편에서 작성했던 Basic.tsx을 복사해, 컴포넌트명만 변경해준다.
TransformObject.tsx
/* eslint-disable react/no-unknown-property */
import { Canvas } from "@react-three/fiber";
import React from "react";
import classes from "../styles/Global.module.css";
const Cube = () => {
const object = (
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="#e91e63" />
</mesh>
);
return object;
};
const TransformObject = () => {
return (
<div className={classes.canvas}>
<Canvas camera={{ position: [1, 1, 3] }}>
<Cube />
</Canvas>
</div>
);
};
export default TransformObject;
그리고 App.tsx에서 위의 TransformObject.tsx를 임포트 한다.
지난 글에도 언급했듯, App.tsx에 직접 코드를 넣어도 전혀 상관없다.
App.tsx
import React from "react";
import TransformObject from "./components/TransformObject";
function App() {
return <TransformObject />;
}
export default App;
Position
오브젝트의 중심 좌표.
React Three Fiber의 경우, 오브젝트를 감싸고 있는 mesh태그에 position 프로퍼티를 지정하면 된다.
순서는 x, y, z 축 순으로 지정하면 되며, 디폴트 값은 0, 0, 0이다.
일단 x축에 1을 설정해보자.
<mesh position={[1, 0, 0]}>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color={props.color} />
</mesh>
그러면 다음과 같이 정육면체가 오른쪽으로 이동할 것이다.
그럼 y축을 1로 설정하면 어떻게 될까?
<mesh position={[0, 1, 0]}>
정육면체가 위로 이동하는 것을 확인할 수 있다.
이번에는 z축도 설정해보자.
<mesh position={[0, 0, 1]}>
z 축을 지정하면 앞뒤로 오브젝트가 이동하기 때문에, 아래와 같이 오브젝트가 더 가까워진 것을 알 수 있다.
만약 오브젝트를 대각선 방향으로 움직이고 싶다면 어떻게 프로퍼티를 지정하면 될까?
다음과 같이 x, y축을 동시에 지정해주면 된다.
<mesh position={[1, -1, 0]}>
그러면 아래 스크린샷과 같이 오른쪽 아래 대각선 방향으로 오브젝트가 이동한다.
참고로 소수점 단위로 지정할 수 있기 때문에, 좀 더 세밀하게 위치 조정이 가능하다.
Position.normalize()
길이가 1인 단위 벡터로 변환하는 메서드.
크기의 정보가 필요 없는 경우 단위 벡터로 변환해두면 나중에 사용하기 쉽다고 하는데, 어떤 경우에 써야 할지 아직 전혀 감이 안 잡힌다.
자주 쓰이는 기능은 아니라고 하니 일단은 넘어가자.
import React, { useEffect, useRef } from "react";
import { Canvas } from "@react-three/fiber";
import classes from "../styles/Global.module.css";
const Cube = () => {
// mesh의 속성을 수정하고 싶을때는 useRef를 사용하면 된다.
const cubeRef = useRef<THREE.Mesh>(null);
// useEffect의 2번째 인자를 빈 배열로 하여, 초기 로딩시 한번만 실행되도록 한다.
useEffect(() => {
// ?.를 사용하여, current가 존재하지 않을 경우의 js에러 발생을 방지한다.
cubeRef.current?.position.normalize();
}, []);
const object = (
<mesh ref={cubeRef} position={[1, -1, 0]}>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="#e91e63" />
</mesh>
);
return object;
};
위 코드를 실행하면 다음과 같이 오브젝트가 약간 평평해진다. 아무리 봐도 언제 쓰는지 잘 모르겠다...
AxesHelper
좌표축 표시. 정육면체 컴포넌트 밑에 axesHelper태그를 추가하면 아래 스크린샷과 같이 좌표축이 나타난다.
<div className={classes.canvas}>
<Canvas camera={{ position: [0, 0, 3] }}>
<Cube />
<axesHelper />
</Canvas>
</div>
가로가 x축, 세로가 y 축이다. z 축은 지금 시점에서는 보이지 않는다.
scale속성을 지정하면 크기도 조정할 수 있다.
<axesHelper scale={2} />
Scale
오브젝트의 크기.
Position과 동일하게, mesh태그에 scale 프로퍼티를 지정하면 된다.
순서도 동일하게 x, y, z 축 순이며, 디폴트 값은 1, 1, 1이다.
위의 코드에서 scale을 다음과 같이 추가해보자.
<mesh position={[1, -1, 0]} scale={[2, 1, 1]}>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="#e91e63" />
</mesh>
그러면 오브젝트의 가로길이가 2배가 된 것을 확인할 수 있다.
반대로, y축에 0.5를 지정하면 오브젝트가 세로로 짜부라지는 것을 볼 수 있다.
<mesh position={[1, -1, 0]} scale={[2, 0.5, 1]}>
Rotation
오브젝트 회전. 다른 프로퍼티와 마찬가지로 x, y, z 축 순으로 지정한다.
three.js의 Rotation은 라디안을 사용하기 때문에, Radians Math.PI * X.XX 혹은 Math.PI / X 형식으로 지정해주는 것이 좋다.
number를 지정해도 움직이기는 하지만, 지정한 숫자 =/= 회전 각도라서 계산하기 굉장히 힘들다.
아래는 x축으로 90도 회전하겠다는 의미이다.
<mesh
ref={cubeRef}
position={[1, -1, 0]}
scale={[2, 0.5, 1]}
rotation={[Math.PI / 2, 0, 0]}
>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="#e91e63" />
</mesh>
다음과 같이 오브젝트가 회전된 것을 확인할 수 있다.
참고로 three.js의 경우에는 reorder()를 사용해 x, y, z 축을 재정의 하는 것이 가능한데, React Three Fiber에서는 재정의할 방법이 없는 것 같다.
다음에 기회가 되면 한번 더 찾아보겠지만, 애초에 자료가 너무 적어서 아마 못 찾을 가능성이 높다.
Group
React Three Fiber에서는 각 오브젝트를 group태그로 감싸면, 그룹 단위로 오브젝트의 제어가 가능하다.
예를 들어, 다음 코드 같은 경우 세 정육면체를 그룹으로 묶어서, 한꺼번에 위치, 크기, 회전 각도를 변경한다.
/* eslint-disable react/no-unknown-property */
import * as THREE from "three";
import React, { useEffect, useRef } from "react";
import { Canvas } from "@react-three/fiber";
import classes from "../styles/Global.module.css";
const Cube = (props: { position: THREE.Vector3; color: string }) => {
const cubeRef = useRef<THREE.Mesh>(null);
useEffect(() => {
// cubeRef.current?.position.normalize();
}, []);
const object = (
<mesh
ref={cubeRef}
position={props.position}
>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color={props.color} />
</mesh>
);
return object;
};
const TransformObject = () => {
return (
<div className={classes.canvas}>
<Canvas camera={{ position: [0, 0, 3] }}>
<group position={[0, 1, 0]} scale={[1, 2, 1]} rotation={[0, 1, 0]}>
<Cube position={new THREE.Vector3(0, 0, 0)} color="#e91e63" />
<Cube position={new THREE.Vector3(-2, 0, 0)} color="#94ff79" />
<Cube position={new THREE.Vector3(2, 0, 0)} color="#6fecff" />
</group>
<axesHelper scale={2} />
</Canvas>
</div>
);
};
export default TransformObject;
코드를 실행하면 이런 느낌이다.
つづく
'개발 > React : React Three Fiber' 카테고리의 다른 글
【React Three Fiber】#03 카메라: Orthographic Camera, OrbitControls (0) | 2023.08.27 |
---|---|
【React Three Fiber】#02 카메라: Perspective Camera (0) | 2023.08.27 |
【React Three Fiber】#01 초기설정, 튜토리얼 (0) | 2023.08.27 |
【React Three Fiber】#06 화면 리사이징 하기, 더블 클릭 시 전체 화면 모드로 변경하기 (0) | 2022.10.13 |
【React Three Fiber】#03 애니메이션 구현하기 (0) | 2022.09.29 |