以编程方式更改 gltf 导入的网格的 material - 反应三纤维
Change material of gltf-imported mesh programmatically - react three fiber
我目前正在做一个反应三纤维的项目。我已经从 @react-three/drei.
使用 useGLTF 导入了模型
有
const { nodes, materials } = useGLTF('/model.glb');
我从 glb 文件访问 materials。
为了访问和操作模型,我使用了 gltfjsx 来生成模型。
现在我需要以编程方式更改网格的 material。因为我无法直接访问模型的 JSX,所以我使用 React.cloneElement
并修改网格的道具。
所以我尝试了这样的事情:
return React.cloneElement(mesh, {
material: overwriteMaterial ?
<meshStandardMaterial attach="material" color={0xa3005c} metalness={1} roughness={0.2} visible={true} /> :
materials['mat_7']
});
如果 overwriteMaterial
为假,则有效。它显示了它应该的 material 。但如果它是真的,那么网格就会消失。
我还想过将 <meshStandardMaterial />
放在网格的 children 属性中。像这样:
return React.cloneElement(mesh, {
material: overwriteMaterial ? undefined : materials['mat_7'],
children: overwriteMaterial ? <meshStandardMaterial attach="material" color={0xa3005c} metalness={1} roughness={0.2} visible={true} /> : undefined
});
有了这个,我总是得到这个错误,我不知道为什么会出现:
TypeError: Cannot read properties of undefined (reading 'visible')
这种方法能否奏效,还是我做错了什么?
欢迎大家的帮助。谢谢
好吧,经过几个小时的寻找解决方案后,我自己找到了答案。
material 属性 不接受 JSX 标签。因此,如果您创建 class MeshStandardMaterial
的实例,您可以将其传递给 属性 并且它工作得很好。现在看起来像这样:
return React.cloneElement(mesh, {
material: overwriteMaterial
? new MeshStandardMaterial({ color: 0x0ff000 })
: materials['mat_7']
})
注意:class MeshStandardMaterial 是从 three
包导出的。
我真的不认为你必须克隆任何反应元素,这似乎不正确。您可以像在普通的三个应用程序中一样克隆或改变材料。我不知道你为什么要克隆 jsx。
const { scene } = useGLTF(url)
const clonedScene = useMemo(() => scene.clone(), [])
useLayoutEffect(() => {
clonedScene.traverse(o => {
if (o.type === 'Mesh') {
o.material = ...
}
})
}, [clonedScene]}
return <primitive object={clonedScene} />
您也可以完全跳过 clonedScene 的事情,这仅适用于您计划在场景中多次重复使用该模型的情况。
我目前正在做一个反应三纤维的项目。我已经从 @react-three/drei.
使用 useGLTF 导入了模型有
const { nodes, materials } = useGLTF('/model.glb');
我从 glb 文件访问 materials。 为了访问和操作模型,我使用了 gltfjsx 来生成模型。
现在我需要以编程方式更改网格的 material。因为我无法直接访问模型的 JSX,所以我使用 React.cloneElement
并修改网格的道具。
所以我尝试了这样的事情:
return React.cloneElement(mesh, {
material: overwriteMaterial ?
<meshStandardMaterial attach="material" color={0xa3005c} metalness={1} roughness={0.2} visible={true} /> :
materials['mat_7']
});
如果 overwriteMaterial
为假,则有效。它显示了它应该的 material 。但如果它是真的,那么网格就会消失。
我还想过将 <meshStandardMaterial />
放在网格的 children 属性中。像这样:
return React.cloneElement(mesh, {
material: overwriteMaterial ? undefined : materials['mat_7'],
children: overwriteMaterial ? <meshStandardMaterial attach="material" color={0xa3005c} metalness={1} roughness={0.2} visible={true} /> : undefined
});
有了这个,我总是得到这个错误,我不知道为什么会出现:
TypeError: Cannot read properties of undefined (reading 'visible')
这种方法能否奏效,还是我做错了什么?
欢迎大家的帮助。谢谢
好吧,经过几个小时的寻找解决方案后,我自己找到了答案。
material 属性 不接受 JSX 标签。因此,如果您创建 class MeshStandardMaterial
的实例,您可以将其传递给 属性 并且它工作得很好。现在看起来像这样:
return React.cloneElement(mesh, {
material: overwriteMaterial
? new MeshStandardMaterial({ color: 0x0ff000 })
: materials['mat_7']
})
注意:class MeshStandardMaterial 是从 three
包导出的。
我真的不认为你必须克隆任何反应元素,这似乎不正确。您可以像在普通的三个应用程序中一样克隆或改变材料。我不知道你为什么要克隆 jsx。
const { scene } = useGLTF(url)
const clonedScene = useMemo(() => scene.clone(), [])
useLayoutEffect(() => {
clonedScene.traverse(o => {
if (o.type === 'Mesh') {
o.material = ...
}
})
}, [clonedScene]}
return <primitive object={clonedScene} />
您也可以完全跳过 clonedScene 的事情,这仅适用于您计划在场景中多次重复使用该模型的情况。