[프로젝트]블록체인 기반 중고차 거래 플랫폼 - 2 (구현)

else·2023년 4월 10일
1

프로젝트

목록 보기
6/12

홈 화면의 구성

  • 3D 모델링
  • gsap을 이용한 버튼들의 동적인 움직임
  • 캐러셀 형태의 최신 판매글
  • 서비스의 간략한 소개
  • 서비스의 사용 현황 수를 api로 받아와 출력

three.js를 이용한 사용자 홈 화면 만들기 (feat.three-fiber)

  • three-fiber이란?

    • React-three-fiber는 three.js를 리액트 문법에 맞게 사용할 수 있도록 해주는 패키지이다.
  • 3D 모델링 파일 구하기

  • gltf 모델링 파일을 jsx 컴포넌트로 바꾸기

    • npx gltfjsx 모델링파일.gltf

    • gltf loader가 아무리해도 경로 설정이 되질 않아서 다른 방법을 찾아보니 이런식으로 컴포넌트 화 시켜주는 라이브러리가 있었다.

    • 참고 : https://www.npmjs.com/package/@react-three/gltfjsx

  • ThreeModel

import { useRef, Suspense } from "react";
import { extend, useFrame } from "@react-three/fiber";
import { OrbitControls, useGLTF } from "@react-three/drei";

function Model(props) {
  const { nodes, materials } = useGLTF("/scene.gltf");
  return (
    <group {...props} dispose={null}>
      <group rotation={[-Math.PI / 2 - 0.01, 0, -Math.PI]}>
        <mesh
          geometry={nodes.Object_2.geometry}
          material={materials["Material.001"]}
        />
        ...
      </group>
    </group>
  );
}
useGLTF.preload("/scene.gltf");  // 생성된 컴포넌트의 코드를 복붙해서 붙여놓은것

export default function ThreeModel() {
  return (
    <>
      <object3D ref={object3d}>
        <OrbitControls/>  // 카메라 컨트롤
        <Suspense fallback={null}> 
          <Model />
        </Suspense>
      </object3D>
    </>
  );
}
  • 해당 컴포넌트를 fiber를 사용해 렌더링 시켜주면 기초 작업은 끝
/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";
import { Canvas, useFrame } from "@react-three/fiber";
import ThreeModel from "./ThreeModel";

  const container = css`
    height: 71.5vh;
    width: 100%;
    overflow: hidden;
    background-color: black;
    display: flex;
    justify-content: center;
    z-index: 10;
    position: relative;
  `;

  const color = 0xffffff;
  const intensity = 1;

  export default function CarModel() {
    return (
      <div css={container}>
        <div
          css={{
            width: "80%",
            height: "100%",
          }}>
          <Canvas
            camera={{
              fov: 5,
              near: 10,
              aspect: window.innerWidth / window.innerHeight,
              far: 1000,
              position: [-45, 10, 50],
            }}>
            <pointLight color={color} intensity={intensity} />				//
            <directionalLight color={color} intensity={intensity} />		// 조명에 대한 옵션들
            <ambientLight color={color} intensity={intensity} />			//
            <ThreeModel />  // 이게 gltfjsx를 이용해 컴포넌트화 시킨 컴포넌트
          </Canvas>
        </div>
      </div>
    );
  }
  • 이렇게하면 기본적으로 마우스 클릭과 휠에 따라 움직이는 모델링이 렌더링된다.

  • 3D 텍스트 더하기 (Textgeometry)

    • 홈 화면에 차 하나만 덜렁 있기에 너무 허전해서 서비스 명을 3D 모델링 시키고자 한다.

    • TextGeometry 사용, 폰트 자체를 렌더링 시키는 과정은 굉장히 간단하다.

    • 필요한 라이브러리 및 폰트 임포트

      import { FontLoader } from "three/examples/jsm/loaders/FontLoader";
      import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry";
      import ThreeFont from "../../assets/3dFont/Oswald_Bold.json";
    • 사용할 폰트를 FontLoader을 이용해 font 객체를 생성한다.
      const font = new FontLoader().parse(ThreeFont);

    • 모델링 컴포넌트 내에 textGeomtry를 이용해 args를 필요한 prop해주준다.

      <mesh>
       <textGeometry args={["CAR-BORN", { font, size: 1.1, height: 1 }]} /> // args=[["텍스트",{옵션}]]
       <meshLambertMaterial attach="material" color={"red"} />
      </mesh>

    • 손쉽게 3D모델링 브라우저에 렌더링하기 끝! 하지만 무엇인가 아쉽다...

  • three-fiber 자동으로 회전 시키기

    • 사용자가 직접 컨트롤 하는것도 좋지만 컨트롤 하지 않더라도 다양한 각도의 모델링 파일을 보여주면 재밌을 것 같다는 생각이 들었다.
    • OrbitControls의 옵션 중 autoRotate 사용
       return (
       <>
         <object3D ref={object3d}>
           <OrbitControls autoRotate/>
           <Suspense fallback={null}>
             <Model />
           </Suspense>
         </object3D>
       </>
      );
      }
    • 여기서 한 쪽으로만 도는 것이 아닌 좌우로 왔다갔다 하게 설정
      export default function ThreeModel() {
      const object3d = useRef(null);
      const controlsRef = useRef(null);
      useFrame(() => {
        controlsRef.current.update();
        if (controlsRef.current.getAzimuthalAngle() < -0.97) {
          controlsRef.current.autoRotateSpeed = -0.2;
        } else if (controlsRef.current.getAzimuthalAngle() > -0.6) {
          controlsRef.current.autoRotateSpeed = 0.2;
        }
      });
      return (
        <>
          <object3D ref={object3d}>
            <OrbitControls
      ...
    • useFrame을 사용해서 모델링이 렌더링 될때마다 값을 받고 각도를 체크한다.
    • 나의 경우 angle의 값이 -0.97 ~ -0.6에서 왔다갔다하는 것이 보기 좋아보였다.
    • 속도가 음수값이 되면 반대방향으로 돈다.
    • rotateLeft() 라는 함수가 있다고 stackoverflow에서 떠들어데는데 아무리 콘솔을 찍고 코드를 뒤져봐도 나는 보이지 않았다.
    • (이렇게 쉬운 코드를 떠올리는데 굉장히 오래걸렸다.)
  • 완성도 높이기

    <OrbitControls
     ref={controlsRef}
     minAzimuthAngle={-Math.PI / 3}
     maxAzimuthAngle={0.06}
     minPolarAngle={Math.PI / 2.2}
     maxPolarAngle={Math.PI - Math.PI / 2}
     enableZoom={false}
     autoRotate
    />
    
    • 사용자가 조작할 수 있는 최대앵글을 설정하고 확대를 못하게 방지한다.
  • 사용자 완성 홈화면

profile
피아노 -> 개발자

0개의 댓글