加载模型
加载模型方法1:从R3F引入useLoader
从three中的examples中引入GLTFLoader
路径是相对于public文件下的index出发的
const model = useLoader(GLTFLoader, "./hambergur1148.glb");
将模型添加到场景中并缩放:
<primitive object={model.scene} scale={0.01} />
添加draco类型的模型,draco模型比较小
将dracoLoader添加到GLTFLoader:在useLoader的第三个参数,是一个函数,函数的参数就是loader,即为GLTFLoader
const model = useLoader(GLTFLoader, "./hambergur-draco.glb", (loader) => {
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("./draco/");
loader.setDRACOLoader(dracoLoader);
});
加载模型方法2:用drei加载GLTF模型
export function Hambergur() {
const model = useGLTF("./hambergur1148.glb");
return <primitive object={model.scene} scale={0.35} />;
}
<Suspense fallback={<PlaceHolder position-y={0.5} scale={[2, 3, 2]} />}>
<Hambergur />
</Suspense>
用drei加载draco模型也是用useGLTF
懒加载
问题:大模型会出现一开始是白屏,等待几秒模型下载后才出现
解决方法:懒加载
懒加载概念:当模型准备好就加入场景,在模型没有加载好之前就先展示其他东西,而不会出现白屏。懒加载用于加载大模型时的性能优化。
包裹模型组件。
<Suspense
//在模型还没下载下来之前展示fallback中的内容
fallback={
<mesh position-y={0.5} scale={[2, 3, 2]}>
<boxGeometry args={[1, 1, 1, 2, 2, 2]} />
<meshBasicMaterial wireframe color="red" />
</mesh>
}
>
<Model />
</Suspense>
预加载
预先加载所有模型
可以用useGLTF函数上的preload方法
// 当这行代码所在的Model.js被加载 ./hambergur1148.glb"这个模型就会开始下载
useGLTF.preload("./hambergur1148.glb");
克隆
要100个汉堡包,使用drei中的Clone
这也可以优化性能,因为它只加载一个文件,然后把它应用到多个mesh
import { Clone, useGLTF } from "@react-three/drei";
export function Hambergur() {
const model = useGLTF("./hambergur1148.glb");
return (
<>
<Clone object={model.scene} scale={0.35} position-x={4} />
<Clone object={model.scene} scale={0.35} position-x={-4} />
</>
);
}
在线改变模型的细节并生成代码
这个网站可以将模型转为组件, 组件分为模型的各个部分。可以调整模型并生成对应的代码
如果模型在我们项目的public文件下,就可以直接拷贝代码,如果需要下载模型,就选择export中的download zip
修改模型阴影:圆曲面会有阴影线,在方向光中设置:
<directionalLight
castShadow
position={[1, 2, 3]}
// 调整曲面的阴影线
shadow-normalBias={0.04}
//../>
加载模型动画
基本使用
使用drei的 useAnimations
github中
gtlf-Sample-Models 库中有模型
import { useGLTF, useAnimations } from "@react-three/drei";
const animations = useAnimations(fox.animations, fox.scene);
// 在第一次渲染的时候还没有加载好动画,所以要在useEffect中调用动画
useEffect(() => {
const action = animations.actions.Run;
action.play();
}, []);
动画过渡
跑步2到3秒后开始走路,中间有过渡
window.setTimeout(() => {
animations.actions.Walk.play();
// 从Run过渡到Walk,用1s,调用crossFadeFrom
animations.actions.Walk.crossFadeFrom(animations.actions.Run, 1);
}, 2000)
控制动画,让狐狸走或跑或搜寻
要使用Leva的useControls
const { animationName } = useControls({
animationName: {
options: animations.names,
},
});
// 在第一次渲染的时候还没有加载好动画,所以要在useEffect中调用动画
// 在第一次渲染的时候还没有加载好动画,所以要在useEffect中调用动画
useEffect(() => {
const action = animations.actions[animationName];
// reset()让动画重新开始,这样从最后的Run选项切换到第一个选项就不会卡住
action.reset().fadeIn(0.5).play();
return () => {
// 这个函数会在animationName改变的时候被调用,可以拿到上一个action
action.fadeOut(0.5);
};
}, [animationName]);
渐渐消失fadeOut