使用react-three-fiber加载gltf格式3D文件,并播放3D模型自带动画

684 阅读2分钟

image.png

一、react-three-fiber简介

使用可重用、自包含的组件以声明方式构建您的场景,这些组件对状态做出反应、易于交互并且可以利用 React 的生态系统。 没有任何限制,一切工作在three.js这里将无一例外地工作。 生态完善。

需要安装的依赖

npm install three @react-three/fiber  @react-three/drei  @react-spring/three @react-three/postprocessing three

二、寻找免费角色和动画

首先让我们找到一个角色和一组要使用的动画。 为此,我们可以使用 Mixamo,这是一个由 Adobe 提供的免费角色模型和动画库。 如果没有帐户,则需要先创建一个。

第 1 步登录 Mixamo(或创建一个免费帐户)

第 2 步查找要下载的角色。 如果想使用与教程相同的角色,请使用 Michelle 角色。

我下载的是这个模型

image.png

然后导出模型转换为gltf格式

三、生成 React Component Wrapper

当我们在 React 中使用导出的 gltf 文件时,我们需要访问导出场景的某些部分,例如我们需要提取几何体、骨架和动画。

你可以通过不手动操作来节省大量时间,而是使用由 react-three-fiber 团队创建的名为 GLFTJSX 的有用工具。 这是一个命令行工具,你可以将 gltf 或 glb 文件作为输入运行,它将创建一个结构良好的 React 组件包装器作为输出。 GLFTJSX 不需要安装 只是使用命令 npx gltf scene.gltf(你下载的gltf文件),npx在执行的时候跟要gltf文件同目录

npx gltfjsx scene.gltf

四、 上代码!!!

index.tsx文件

import { PageContainer } from '@ant-design/pro-components';
import { Canvas } from '@react-three/fiber';
import { Card } from 'antd';

import {Html, OrbitControls,useProgress,} from '@react-three/drei';
import { Suspense } from 'react';
import { Model } from './person.jsx';

function Loader() {
  const { progress } = useProgress();
  return <Html center>{progress} % loaded</Html>;
}

const Page: React.FC = () => {
  return (
    <PageContainer ghost>
      <Card>
        <Canvas
          style={{ height: '700px' }}
          shadows
          camera={{ position: [0, 0, 5], fov: 40 }}
        >
          <Suspense fallback={<Loader />}>
            <ambientLight intensity={2}></ambientLight>
            <directionalLight intensity={2} />
            <Model scale={1} />
            <OrbitControls />
            {/* <OrbitControls makeDefault autoRotate /> */}
          </Suspense>
        </Canvas>
      </Card>
    </PageContainer>
  );
};
export default Page;

person.jsx文件


/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.13 scene.gltf 
*/

import React, { useRef, useEffect } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'

export function Model(props) {
  const group = useRef()
  const { nodes, materials, animations } = useGLTF('/person.gltf')

  const { actions } = useAnimations(animations, group)



  //     actions.Armada.play();  如果动画较多的情况下  是会出现.play()方法不存在


  useEffect(() => {
    if (animations && animations.length > 0) {
      animations.forEach((animation) => {
        actions[animation.name].play()
      })
      //actions.animation.play()
    }
  }, [actions, animations])
  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="Ch03" geometry={nodes.Ch03.geometry} material={materials.Ch03_Body} skeleton={nodes.Ch03.skeleton} />
        </group>
      </group>
    </group>
  )
}

useGLTF.preload('/scene.gltf')