three.js: Removing Generics from Meshes causes a lot of headaches
Describe the bug
For some context, i’m using react-three-fiber
. My use case is when i’m loading a GLTF
model, to TS it’s a black box, So I know it’s a mesh & can typecast the return of the gltf
to be Mesh
. However, when I want to edit the properties of the mesh materials, I now have to typecast the material because Mesh
is no longer a generic. This is quite a headache. I’m not saying i’m right, it’d be good to get some clarity on why this commit was done?
Old Code
type GLTFResult = GLTF &
ObjectMap & {
nodes: {
[name: string]: Mesh<BufferGeometry, MeshStandardMaterial>
}
}
const { nodes } = useGLTF(
`${ENV_MODEL_PATH}/rain/RainPond_Droplets_Polyredux.gltf`
) as GLTFResult
const instanceMeshes = React.useMemo(
() =>
meshes
.filter((mesh) => mesh.material)
.map((mesh, i) => {
mesh.material.metalness = 0 // all good here, no typecast needed
mesh.material.transparent = true
mesh.material.onBeforeCompile = compileMaterialForInstance
mesh.geometry.setAttribute(
'instOpacity',
new InstancedBufferAttribute(
new Float32Array(new Array(INSTANCE_COUNT).fill(0)),
1
)
)
return (
<instancedMesh
ref={(ref: THREE.InstancedMesh) =>
setKeyValue(instanceRefs.current, i, ref)
}
key={mesh.name}
args={[mesh.geometry, mesh.material, INSTANCE_COUNT]}
/>
)
}),
[meshes]
)
New Code
type GLTFResult = GLTF &
ObjectMap & {
nodes: {
[name: string]: Mesh
}
}
const { nodes } = useGLTF(
`${ENV_MODEL_PATH}/rain/RainPond_Droplets_Polyredux.gltf`
) as GLTFResult
const instanceMeshes = React.useMemo(
() =>
meshes
.filter((mesh) => mesh.material)
.map((mesh, i) => {
mesh.material.metalness = 0 // this now throws an error because metalness does not exist on type Material[]
mesh.material.transparent = true
mesh.material.onBeforeCompile = compileMaterialForInstance
mesh.geometry.setAttribute(
'instOpacity',
new InstancedBufferAttribute(
new Float32Array(new Array(INSTANCE_COUNT).fill(0)),
1
)
)
return (
<instancedMesh
ref={(ref: THREE.InstancedMesh) =>
setKeyValue(instanceRefs.current, i, ref)
}
key={mesh.name}
args={[mesh.geometry, mesh.material, INSTANCE_COUNT]}
/>
)
}),
[meshes]
)
Expected behavior
Ideally i’d like to pass the Generics back in, because even if it was able to figure out if it was Material
or Material[]
I know the material is MeshStandardMaterial
so metalness
will still throw a typescript error.
disclaimer I’m happy to work on a solution if we want to fix this.
Platform:
- Three.js version: r125
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 19 (19 by maintainers)
And that’s how you force JavaScript people learn TypeScript. Makes contributing harder.
I’m not liking this at all.
This isn’t my intention. I was more suggesting that if a PR is made that changes something that requires a
.d.ts
change, then it should be done at the same time, whether that is someone like myself introducing the change on their behalf into their PR, or if the original contributor is able to, doing so themself.