React/ReactThreeFiber

GUI Controller

최 수빈 2025. 3. 3. 03:18

 

 

GUI(Graphical User Interface) Controller

 

사용자가 소프트웨어의 기능을 시각적으로 조작할 수 있도록 도와주는 인터페이스

예 : 게임에서 클릭할 수 있는 메뉴 버튼/ 설정 패널

 

 

 

Leva 라이브러리 활용

 

Leva

React 애플리케이션에서 사용 가능한 경량화된 GUI 컨트롤러 라이브러리

실시간으로 장면 속성을 조정할 수 있는 인터페이스를 제공

 

npm i leva

 

  • useControls 훅을 사용하여 다양한 입력 컨트롤을 쉽게 생성하고 관리할 수 있음
  • 장면 내 요소의 속성을 실시간으로 조정 가능
  • 코드 몇 줄의 추가로 GUI 패널을 추가할 수 있어 편리

 

 

Leva를 활용한 3D 객체 컨트롤

 

useControls를 이용한 속성 조정

const options = useMemo(() => {
  return {
    x: { value: 0, min: 0, max: Math.PI * 2, step: 0.01 },
    y: { value: 0, min: 0, max: Math.PI * 2, step: 0.01 },
    z: { value: 0, min: 0, max: Math.PI * 2, step: 0.01 },
    visible: true,
    color: { value: "lime" },
  };
}, []);

 

  • x, y, z 회전값을 최소 0부터 최대 2π까지 슬라이더(step: 0.01)조정 가능 설정
  • visible 옵션으로 객체의 표시 여부 선택 가능
  • color 속성을 변경하여 실시간 색상 조정 가능

→ 설정된 값들은 Leva 패널을 통해 실시간으로 조절 가능

 

 

 

App.jsx

import { Canvas } from "@react-three/fiber";
import Polyhedron from "./Polyhedron";
// Polyhedron 컴포넌트 import - 3D 오브젝트 생성
import * as THREE from "three";
import { useMemo } from "react";
// 성능 최적화를 위해 값이 변경되지 않으면 기존 값을 재사용할 수 있도록 useMemo 훅을 사용
import { Stats, OrbitControls } from "@react-three/drei";
// FPS 등 성능을 모니터링하는 Stats 컴포넌트 가져옴
import { useControls } from "leva";
// Leva 라이브러리를 이용해 GUI 컨트롤러를 추가할 수 있도록 하는 useControls 훅을 가져옴
import "./App.css";

{/* App 컴포넌트 정의 */ }
export default function App() {
  // 3D 씬 생성, Polyhedron 배치, GUI 컨트롤 추가
  const polyhedron = useMemo(
    // useMemo를 사용하여 polyhedron 배열을 메모이제이션하여 불필요한 재생성 방지
    () => [
      new THREE.BoxGeometry(), // 박스 형태 3D 도형 생성
      new THREE.SphereGeometry(0.785398), // 반지름 0.785398인 구형 도형 생성
      new THREE.DodecahedronGeometry(0.785398), // 반지름 0.785398인 십이면체 도형 생성
    ],
    []
  );

  const options = useMemo(() => {
    // GUI 컨트롤을 위한 옵션을 useMemo로 생성하여 성능 최적화
    return {
      // value : 초기값, min: 최소값, max: 최대값, step: 슬라이더 단위
      x: { value: 0, min: 0, max: Math.PI * 2, step: 0.01 },
      y: { value: 0, min: 0, max: Math.PI * 2, step: 0.01 },
      z: { value: 0, min: 0, max: Math.PI * 2, step: 0.01 },
      visible: true, // 오브젝트 가시성 여부 설정
      color: { value: "lime" }, // 기본 색상 lime으로 설정
    };
  }, []);

  const pA = useControls("Polyhedron A", options);
  const pB = useControls("Polyhedron B", options);
  // Leva의 GUI 컨트롤을 사용하여 "Polyhedron A", "Polyhedron B" 속성 조절 가능하도록 설정

  return (
    <Canvas camera={{ position: [1, 2, 3] }}>
      {/* Three.js의 3D 씬을 렌더링하는 Canvas 컴포넌트
          카메라를 [1, 2, 3] 좌표에 배치하여 오브젝트를 볼 수 있도록 설정 */}
      <Polyhedron
        // position={[-1, 1, 0]}
        position={[pA.x, pA.y, pA.z]} // Leva에서 조절한 x, y, z 값을 위치 값으로 사용
        rotation={[pA.x, pA.y, pA.z]} // Leva에서 조절한 x, y, z값을 회전 값으로 사용
        visible={pA.visible} // Leva의 visible 속성에 따라 표시 여부 결정
        color={pA.color} // Leva의 color 값을 적용
        polyhedron={polyhedron} // polyhedron 배열을 전달, 도형을 변경 가능하게 함
      />
      <Polyhedron
        position={[1, 1, 0]} // Polyhedron B의 위치를 (1, 1, 0)으로 고정
        rotation={[pB.x, pB.y, pB.z]}
        visible={pB.visible}
        color={pB.color}
        polyhedron={polyhedron}
      />
      <OrbitControls target={[0, 1, 0]} />
      <axesHelper args={[5]} />
      <gridHelper />
      <Stats />
      {/* FPS 및 성능 모니터링을 위한 Stats 컴포넌트 추가 */}
    </Canvas>
  );
}
  • Canvas를 이용해 3D 공간 생성
  • useControls를 활용해 객체별로 CUI 컨트롤 추가
  • Polyhedron 컴포넌트를 활용하여 다면체 배치

 

 

Polyhedron.jsx

import { useRef, useState } from "react";
// useRef: 특정 DOM 요소나 Three.js 객체에 직접 접근할 때 사용
// useState: 상태 변화를 관리 할 때 사용
import { Mesh } from "three";

{/* Polyhedron 컴포넌트 정의 */ }
export default function Polyhedron({ polyhedron, color, ...props }) {
    // polyhedron : 3D 도형 배열을 전달받음
    // color : 도형의 색상을 설정하는 props
    // props: 기타 추가적인 props를 받음

    const ref = useRef();
    // useRef를 사용해 mesh 요소에 대한 참조 생성
    // Three.js 객체에 직접 접근할 때 사용

    const [count, setCount] = useState(2);
    // count 상태 생성, 초기값 2로 설정
    // 현재 어떤 polyhedron을 사용할지 결정하는 변수

    return (
        <mesh
            {...props} // 부모 컴포넌트에서 전달된 props 적용
            ref={ref} // Three.js의 mesh 요소에 대한 참조 설정
            onPointerDown={() => {
                setCount((count + 1) % 3);
                // 클릭할 때마다 count 값을 1 증가시키고, 3이 되면 다시 0으로 초기화
                // polyhedron 배열의 인덱스를 변경하여 도형의 형태 변경
            }}
            geometry={polyhedron[count]}
        // polyhedron 배열에서 count에 해당하는 도형을 선택적용

        >
            <meshBasicMaterial color={color} wireframe />
            {/* meshBasicMaterial을 사용해 색상과 wireframe(와이어 형태) 적용 */}
        </mesh>
    );
}
  • mesh 클릭 시 polyhedron 변경
  • props를 받아 3D 객체 속성 설정

 

 

Leva -GUI Controller

 

 

 

 

 

 

'React > ReactThreeFiber' 카테고리의 다른 글

Material & Texture  (1) 2025.03.05
Geometry  (0) 2025.03.04
3D 개발을 도와주는 도구들 - OrbitControls, AxesHelper, GridHelper  (0) 2025.03.02
Scene  (0) 2025.02.28
Camera  (0) 2025.02.28