개발/React : React Three Fiber

【React Three Fiber】#02 오브젝트 변형하기

고독한 쵸이 2022. 9. 26. 23:50
반응형

이번에는 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>

그러면 다음과 같이 정육면체가 오른쪽으로 이동할 것이다.

React Three Fiber에서 position 지정

그럼 y축을 1로 설정하면 어떻게 될까?

<mesh position={[0, 1, 0]}>

정육면체가 위로 이동하는 것을 확인할 수 있다.

React Three Fiber에서 position 지정

이번에는 z축도 설정해보자.

<mesh position={[0, 0, 1]}>

z 축을 지정하면 앞뒤로 오브젝트가 이동하기 때문에, 아래와 같이 오브젝트가 더 가까워진 것을 알 수 있다.

React Three Fiber에서 position 지정

만약 오브젝트를 대각선 방향으로 움직이고 싶다면 어떻게 프로퍼티를 지정하면 될까?

다음과 같이 x, y축을 동시에 지정해주면 된다.

<mesh position={[1, -1, 0]}>

그러면 아래 스크린샷과 같이 오른쪽 아래 대각선 방향으로 오브젝트가 이동한다.

React Three Fiber에서 position 지정

참고로 소수점 단위로 지정할 수 있기 때문에, 좀 더 세밀하게 위치 조정이 가능하다.

 

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;
};

위 코드를 실행하면 다음과 같이 오브젝트가 약간 평평해진다. 아무리 봐도 언제 쓰는지 잘 모르겠다...

React Three Fiber에서 오브젝트 정규화

AxesHelper

좌표축 표시. 정육면체 컴포넌트 밑에 axesHelper태그를 추가하면 아래 스크린샷과 같이 좌표축이 나타난다.

<div className={classes.canvas}>
  <Canvas camera={{ position: [0, 0, 3] }}>
    <Cube />
    <axesHelper />
  </Canvas>
</div>

가로가 x축, 세로가 y 축이다. z 축은 지금 시점에서는 보이지 않는다.

 

React Three Fiber에서 axesHelper 설정

scale속성을 지정하면 크기도 조정할 수 있다.

<axesHelper scale={2} />

 

React Three Fiber에서 axesHelper 설정

 

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배가 된 것을 확인할 수 있다.

React Three Fiber에서 scale 지정

반대로, y축에 0.5를 지정하면 오브젝트가 세로로 짜부라지는 것을 볼 수 있다. 

<mesh position={[1, -1, 0]} scale={[2, 0.5, 1]}>

React Three Fiber에서 scale 지정

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>

다음과 같이 오브젝트가 회전된 것을 확인할 수 있다.

React Three Fiber에서 rotation 지정

 

참고로 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 Three Fiber에서 group 설정

つづく

반응형