首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在反应中使用相同的GLTF模型两次-三纤维/drei/Three.js

在反应中使用相同的GLTF模型两次-三纤维/drei/Three.js
EN

Stack Overflow用户
提问于 2021-08-17 08:03:24
回答 2查看 2.7K关注 0票数 5

在这个最小的反应-三纤维应用程序,我试图加载和包括相同的GLTF模型两次:

代码语言:javascript
复制
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>
  );
}

参见此码箱

然而,只有第二个<primitive>是可见的。如果我移除第二个<primitive>,那么第一个是可见的。我很难理解为什么会发生这种事,以及如何做得更好。

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

特别是,这是我希望达到的目标:

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

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

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

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-17 15:16:13

我不是three.js方面的专家,只是基于我所发现的,并试图回答你的问题。

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

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

代码语言:javascript
复制
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);

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

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

代码语言:javascript
复制
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]} />

这是演示码箱

FYR:

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

票数 4
EN

Stack Overflow用户

发布于 2022-03-01 22:19:52

您不能在webgl/threejs中重用网格或将同一个对象放入场景两次,它只需卸载和重新装入即可。你可以:

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

下面是如何使用useMemo深入克隆基对象

代码语言:javascript
复制
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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68813736

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档