SkinedMesh의 Clone

애니메이션 모델 리소스로부터 가져온 데이터를 여러개 복사해서 사용하고자 할때 필요한 코드입니다.

1개만 사용할때는 문제가 없는 기본적으로 작성된 코드는 다음과 같습니다.

import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'
import * as THREE from "three"

export function Robot({ color = "gray", ...props }) {
  const group = useRef()
  const { nodes, materials, animations } = useGLTF('/Robot.glb')
  const { actions } = useAnimations(animations, group)
  const [ animation, setAnimation ] = useState("Idle")

  useEffect(() => {
    actions[animation].reset().fadeIn(0.5).play()
    return () => actions[animation].fadeOut(0.5)
  }, [ animation ])

  materials.Alpha_Body_MAT.color = new THREE.Color(color)

  return (
    <group ref={group} {...props} dispose={null}>
      <group name="Scene">
        <group name="Armature" rotation={[Math.PI / 2, 0, 0]} scale={0.01}>
          <primitive object={nodes.mixamorigHips} />
          <skinnedMesh name="Alpha_Joints" geometry={nodes.Alpha_Joints.geometry} material={materials.Alpha_Joints_MAT} skeleton={nodes.Alpha_Joints.skeleton} />
          <skinnedMesh name="Alpha_Surface" geometry={nodes.Alpha_Surface.geometry} material={materials.Alpha_Body_MAT} skeleton={nodes.Alpha_Surface.skeleton} />
        </group>
      </group>
    </group>
  )
}

useGLTF.preload('/Robot.glb')

위의 코드에 대한 모델 여러개를 장면에 추가하기 위해 다음처럼 코드를 수정해야 합니다.

import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'
import * as THREE from "three"
import { useGraph } from '@react-three/fiber'
import { SkeletonUtils } from "three-stdlib"

export function Robot({ color = "gray", ...props }) {
  const group = useRef()
  const { scene, materials, animations } = useGLTF('/Robot.glb')
  const clone = useMemo(() => SkeletonUtils.clone(scene), [scene])
  const { nodes } = useGraph(clone)
  const { actions } = useAnimations(animations, group)
  const [ animation, setAnimation ] = useState("Idle")

  useEffect(() => {
    actions[animation].reset().fadeIn(0.5).play()
    return () => actions[animation].fadeOut(0.5)
  }, [ animation ])

  const material = materials.Alpha_Body_MAT.clone()
  material.color = new THREE.Color(color)

  return (
    <group ref={group} {...props} dispose={null}>
      <group name="Scene">
        <group name="Armature" rotation={[Math.PI / 2, 0, 0]} scale={0.01}>
          <primitive object={nodes.mixamorigHips} />
          <skinnedMesh name="Alpha_Joints" geometry={nodes.Alpha_Joints.geometry} material={materials.Alpha_Joints_MAT} skeleton={nodes.Alpha_Joints.skeleton} />
          <skinnedMesh name="Alpha_Surface" geometry={nodes.Alpha_Surface.geometry} material={material} skeleton={nodes.Alpha_Surface.skeleton} />
        </group>
      </group>
    </group>
  )
}

useGLTF.preload('/Robot.glb')

위의 코드에서 SkeletonUtils를 사용하고 있는데 이를 위해 아래의 코드를 실행하여 three-stdlib를 설치해야 합니다.

npm i three-stdlib

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다