I'm trying to create a decal on my mesh using three.js and react-three-fiber. I believe I correctly set up the mesh and material but for some reason the decal is not showing up on the canvas.
This is the parent component that holds both the model, backplate, and decal.
<Canvas camera={{ position: [0, 0, 2], fov: 70 }}>
<Lights />
<Suspense fallback={null}>
<Model flipped={flipped} returnMesh={setMesh} />
<Decal mesh={mesh} />
<Back />
</Suspense>
</Canvas>
This is part of the component where I create the t-shirt mesh from a .glb file. The mesh is passed back to the parent and then to the Decal component.
let geometry, material, mesh;
// GEOMETRY
geometry = useGLTF("/tshirt.glb").nodes.tshirt.geometry;
useEffect(() => {
material = new THREE.MeshStandardMaterial({ color: "orange" });
mesh = new THREE.Mesh(geometry, material);
}, []);
This is how I am trying to set up the decal mesh:
extend({ DecalGeometry });
const Decal = ({ mesh }) => {
let decalGeometry;
useEffect(() => {
if (mesh) {
decalGeometry = new DecalGeometry(
mesh,
new THREE.Vector3(0, 0, 0),
new THREE.Euler(0, 0, -1, "XYZ"),
new THREE.Vector3(0.5, 0.5, 0.5)
);
}
}, [mesh]);
return (
<mesh geometry={decalGeometry}>
<meshStandardMaterial attach="material" color="red" />
</mesh>
);
};
I am getting no errors, the decal just doesn't appear. I hope someone has some insight. There isn't a lot about Decal Geometry with threejs out there, even less specific to r3f.
You are using decalGeometry
before it is assigned. This is because callbacks given to useEffect
are executed after Decal
is called.
Suggested fix: use the useMemo
hook.
e.g.
extend({ DecalGeometry });
const Decal = ({ mesh }) => {
const decalGeometry = useMemo(() => {
return new DecalGeometry(
mesh,
new THREE.Vector3(0, 0, 0),
new THREE.Euler(0, 0, -1, "XYZ"),
new THREE.Vector3(0.5, 0.5, 0.5)
);
}, [mesh]);
return (
<mesh geometry={decalGeometry}>
<meshStandardMaterial attach="material" color="red" />
</mesh>
);
};