在react-three-fiber/drei/Three.js中使用相同的GLTF模型两次



在这个最小的react-three-fiber应用程序中,我试图加载并包含两次相同的GLTF模型:

import React, { Suspense } from "react";
import { Canvas } from "@react-three/fiber";
import { useGLTF } from "@react-three/drei";
function MyContent() {
const firstGltf = useGLTF("/eye/scene.gltf");
const secondGltf = useGLTF("/eye/scene.gltf");
return (
<>
<primitive object={firstGltf.scene} position={[-200, 0, -400]} />
<primitive object={secondGltf.scene} position={[200, 0, -400]} />
</>
);
}
export default function App() {
return (
<Canvas>
<ambientLight color="white" intensity={0.5} />
<Suspense fallback={null}>
<MyContent />
</Suspense>
</Canvas>
);
}

查看这个codesandbox

但是只有第二个<primitive>是可见的。如果我删除第二个<primitive>,那么第一个是可见的。我正在努力理解为什么会发生这种情况,以及如何做得更好。

(这是因为useGLTF的第二次调用记住"/eye/scene.gltf"已经加载并返回相同的对象吗?这是否在某种程度上扰乱了<primitive>的使用,也许是因为材料/几何形状没有被重新创建第二次,只存在一次?)

具体来说,这就是我想要达到的目标:

  • 在我的画布上多次使用gltf模型
  • 理想情况下,只加载一次gltf

最重要的是,也许你可以帮我澄清这些问题,这样我就能更好地理解这里到底发生了什么:

  • 因为我只想要一个3D模型,这是正确的方法与gltf.scene对象的工作?
  • <primitive>实际上是正确的方法来显示3D模型?或者我应该以某种方式从场景中提取几何体/纹理并渲染它们?

谢谢!

我不是three.js的专家,只是根据我的发现,试图回答你的问题。


1。即使定义了两个原语,也只显示一只眼睛

如果您使用useGLTF()导入相同的模型,它将引用相同的对象。因此,这两个原语指向同一个gltf,并且只应用最后一个配置。

const firstGltf = useGLTF("/eye/scene.gltf");
const secondGltf = useGLTF("/eye/scene.gltf");
const glassesGltf = useGLTF("/glasses/scene.gltf");
// for demonstrating first eye is same as second eye
// Output: false, true
console.log(firstGltf === glassesGltf, firstGltf === secondGltf);

2。<primitive>实际上是正确的方法来显示3D模型?

是的,它是。但是如果你想在屏幕上多次显示相同的GLTF,你需要创建网格并应用模型的几何形状和材料,这样你就可以有一个新的对象。

function Model(props) {
const { nodes, materials } = useGLTF("/eye/scene.gltf");
return (
<group
{...props}
dispose={null}
rotation={[Math.PI, 0, -Math.PI / 2]}
scale={[1, 1, 1]}
>
<mesh
geometry={nodes.Sphere001_Eye_0.geometry}
material={materials.material}
/>
</group>
);
}
...
<Model position={[-1, 0, 1]} />
<Model position={[1, 0, 1]} />

这是demo的代码盒


马其顿:

您可以使用这个库https://github.com/pmndrs/gltfjsx从模型生成jsx。

你不能在webgl/threejs中重复使用网格或将相同的对象放入场景中两次,它只会卸载和重新安装。

  1. 共享几何图形:参见此示例https://codesandbox.io/s/re-using-gltfs-dix1y?file=/src/Shoe.js:48-55
  2. 或深克隆基对象

下面是如何深度克隆基本对象,使用useMemo:

interface ObjectProps {
url: string;
position: [x: number, y: number, z: number];
}
const Object = ({ url, position, ...props }: ObjectProps) => {
const { scene } = useLoader(GLTFLoader, url)
const copiedScene = useMemo(() => scene.clone(), [scene])
return (
<group>
<primitive object={copiedScene} position={position} />
</group>
);
};

裁判:https://github.com/pmndrs/react-three-fiber/issues/245 issuecomment - 745552102

也许你可以使用Clone from '@react-three/drei'

<>
<Clone object={firstGltf.scene} position={[-200, 0, -400]} />
<Clone object={secondGltf.scene} position={[200, 0, -400]} />
</>

相关内容

  • 没有找到相关文章