Reputation: 69
I'm trying to make several instances of this chicken component, but running into issues with copying skinnedMesh
s. Looking through PRs, it looks like there a method, SkeletonUtils.clone
, and this seems to create multiple instances of the chicken in the dom, but only the last instance shows up and has bones.
Cloning non-animated objects seems to work fine, because there's no skinnedMesh
component or bones and so Threejs doesn't have to worry about trying to apply an animation to multiple meshes. I'm not attached to using GLTF, if another export works better, I'm down to try it as long as Blender exports it.
Does anyone have any ideas on how to get these other meshes to show up?
Thanks
const Chicken = ({ initPos = [-4, 5], count = 3 }) => {
// loading a single instance of nodes, materials, animations
// I think creating copies of actions for each chicken instance
// will be enough, but correct me if I'm wrong
const { nodes, materials, animations } = useLoader(
GLTFLoader,
"/chicken.gltf"
);
// storing the different chicken refs
const [chickenRefs, setChickenRefs] = useState([]);
useEffect(() => {
if (chickenRefs?.length) {
if (chickenRefs?.length >= count) {
return;
}
const newChicken = SkeletonUtils.clone(chickenRefs[0].current);
const newChickenRef = createRef();
newChickenRef.current = newChicken;
setChickenRefs([...chickenRefs, newChickenRef]);
} else {
setChickenRefs([createRef()])
}
}, [chickenRefs]);
// creating the jsx for the component functionally so I can add it
// individually to each chickenRef
const chickenJSX = (chickenRef, idx) => (
<group
ref={chickenRef}
position={[initPos[0] + idx * 3, 0, initPos[1] + idx * 3]}
dispose={null}
key={`chicken_${idx}`}
>
<group position={[0, 0.5, 0]} scale={[0.5, 0.5, 0.5]}>
<primitive object={nodes.Body} />
<primitive object={nodes.Bottom} />
<primitive object={nodes.LegIKL} />
<primitive object={nodes.LegPullTargetL} />
<primitive object={nodes.LegIKR} />
<primitive object={nodes.LegPullTargetR} />
<skinnedMesh
geometry={nodes.Plane.geometry}
material={materials["Material.002"]}
skeleton={nodes.Plane.skeleton}
/>
<skinnedMesh
geometry={nodes.Plane_1.geometry}
material={materials["Material.003"]}
skeleton={nodes.Plane_1.skeleton}
/>
<skinnedMesh
geometry={nodes.Plane_2.geometry}
material={materials["Material.004"]}
skeleton={nodes.Plane_2.skeleton}
/>
<skinnedMesh
geometry={nodes.Plane_3.geometry}
material={materials["Material.005"]}
skeleton={nodes.Plane_3.skeleton}
/>
</group>
</group>;
);
// mapping the refs to the jsx
return <>
{
chickenRefs?.map((chickenRef, idx) => chickenJSX(chickenRef, idx))
}
</>;
};
Upvotes: 1
Views: 2326
Reputation: 694
You might need to use clone on the nodes,
you can use the package @react-three/drei to simplify the import a bit
here is an example from multiple instances of skinned meshes working :
https://codesandbox.io/s/react-three-fiber-wildlife-nrbnq?file=/src/Model.js
You can also use the package gltfjsx so you dont have to wory about your model file it will be generated the right way by gltfjsx :
i'll gladly update my post if you have any additional questions
Upvotes: 3