我目前正在做一个react-three-fiber项目。我已经用useGLTF从@react-three/drei导入了模型。
const { nodes, materials } = useGLTF('/model.glb');
我访问glb文件中的材料。为了访问和操作模型,我使用gltfjsx来生成模型。
现在我需要改变一个网格的材料编程。因为我不能直接访问模型的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
为假,则工作。它显示了它应该显示的材料。但如果为真,则网格消失。
我还想把<meshStandardMaterial />
在网格的儿童道具。像这样:
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标签。所以,如果你创建一个MeshStandardMaterial
类的实例,你可以把它传递给属性,它工作得很好。现在它看起来像这样:
return React.cloneElement(mesh, {
material: overwriteMaterial
? new MeshStandardMaterial({ color: 0x0ff000 })
: materials['mat_7']
})
注意:类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,这只有当你计划在你的场景中多次重复使用模型时。