I am new to Three.js, I am building a 3D product configurator using React-three-fiber. I have followed some tutorials and am able to render and edit textures/colors live, but still unable to find a way to dynamically load any 3D object and edit it on the go. Right now everything is hardcoded. Any piece of code or if anyone can point me in the right direction for how can I make it dynamic so it can handle any product and user can modify any element of the 3D object from the website. Right now this is how I am doing.
const Franklin = () => {
const group = useRef();
const { nodes, materials } = useGLTF('/wes/franklin/franklin.glb');
const [
backMap,
backEmissiveMap,
backDisplacementMap,
backMetalnessMap,
backNormalMap,
backRoughnessMap,
] = useLoader(TextureLoader, [
'/wes/franklin/textures/Franklin_back_BaseColor.png',
'/wes/franklin/textures/Franklin_back_Emissive.png',
'/wes/franklin/textures/Franklin_back_Height.png',
'/wes/franklin/textures/Franklin_back_Metallic.png',
'/wes/franklin/textures/Franklin_back_Normal.png',
'/wes/franklin/textures/Franklin_back_Roughness.png',
]);
const [
frameMap,
frameEmissiveMap,
frameDisplacementMap,
frameMetalnessMap,
frameNormalMap,
frameRoughnessMap,
] = useLoader(TextureLoader, [
'/wes/franklin/textures/Franklin_frame_BaseColor.png',
'/wes/franklin/textures/Franklin_frame_Emissive.png',
'/wes/franklin/textures/Franklin_frame_Height.png',
'/wes/franklin/textures/Franklin_frame_Metallic.png',
'/wes/franklin/textures/Franklin_frame_Normal.png',
'/wes/franklin/textures/Franklin_frame_Roughness.png',
]);
const [
capMap,
capEmissiveMap,
capDisplacementMap,
capMetalnessMap,
capNormalMap,
capRoughnessMap,
] = useLoader(TextureLoader, [
'/wes/franklin/textures/Franklin_cap_BaseColor.png',
'/wes/franklin/textures/Franklin_cap_Emissive.png',
'/wes/franklin/textures/Franklin_cap_Height.png',
'/wes/franklin/textures/Franklin_cap_Metallic.png',
'/wes/franklin/textures/Franklin_cap_Normal.png',
'/wes/franklin/textures/Franklin_cap_Roughness.png',
]);
const [
seatMap,
seatEmissiveMap,
seatDisplacementMap,
seatMetalnessMap,
seatNormalMap,
seatRoughnessMap,
] = useLoader(TextureLoader, [
'/wes/franklin/textures/Franklin_seat_BaseColor.png',
'/wes/franklin/textures/Franklin_seat_Emissive.png',
'/wes/franklin/textures/Franklin_seat_Height.png',
'/wes/franklin/textures/Franklin_seat_Metallic.png',
'/wes/franklin/textures/Franklin_seat_Normal.png',
'/wes/franklin/textures/Franklin_seat_Roughness.png',
]);
return (
<group ref={group} dispose={null}>
<mesh
geometry={nodes.Bottom_Bars001.geometry}
material={nodes.Bottom_Bars001.material}
>
<meshStandardMaterial
map={frameMap}
emissiveMap={frameEmissiveMap}
displacementMap={frameDisplacementMap}
metalnessMap={frameMetalnessMap}
normalMap={frameNormalMap}
roughnessMap={frameRoughnessMap}
/>
</mesh>
<mesh
geometry={nodes.Back_Seat002.geometry}
material={nodes.Back_Seat002.material}
>
<meshStandardMaterial
map={backMap}
emissiveMap={backEmissiveMap}
displacementMap={backDisplacementMap}
metalnessMap={backMetalnessMap}
normalMap={backNormalMap}
roughnessMap={backRoughnessMap}
/>
</mesh>
<mesh geometry={nodes.Base001.geometry} material={nodes.Base001.material}>
<meshStandardMaterial
map={frameMap}
emissiveMap={frameEmissiveMap}
displacementMap={frameDisplacementMap}
metalnessMap={frameMetalnessMap}
normalMap={frameNormalMap}
roughnessMap={frameRoughnessMap}
/>
</mesh>
<mesh geometry={nodes.Seat001.geometry} material={nodes.Seat001.material}>
<meshStandardMaterial
map={seatMap}
emissiveMap={seatEmissiveMap}
displacementMap={seatDisplacementMap}
metalnessMap={seatMetalnessMap}
normalMap={seatNormalMap}
roughnessMap={seatRoughnessMap}
/>
</mesh>
<mesh geometry={nodes.Caps003.geometry} material={nodes.Caps003.material}>
<meshStandardMaterial
map={capMap}
emissiveMap={capEmissiveMap}
displacementMap={capDisplacementMap}
metalnessMap={capMetalnessMap}
normalMap={capNormalMap}
roughnessMap={capRoughnessMap}
/>
</mesh>
</group>
);
};
I did it this way, take the scene from GLTFLoader and traverse through it to apply textures to specific nodes and at the end pass this scene to primitive as object. Taken from pure three.js approach.
scene.traverse((node) => {
if (node.isMesh) {
const checkItem = selectedItems.find((itm) =>
node.name.includes(itm.value)
);
if (checkItem) {
const fabric = items.filter(
(item) => item.name.value === checkItem.value
);
var tempMaterial = new MeshStandardMaterial({
...node.material,
map: loadTexture(fabric[0].texture),
});
node.material = tempMaterial;
}
}
});