# How to clone a model and change color respectively?

**URL:** <https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450>\
**Category:** Questions\
**Tags:** object3d, model, gltf\
**Created:** [January 3, 2023, 9:09am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450 "2023-01-03T09:09:31Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![delongjs](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@delongjs](https://discourse.threejs.org/u/delongjs)\
**Post date:** [January 3, 2023, 9:09am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450/1 "2023-01-03T09:09:31Z")

</div>

I made three copies of the model, and want to change the color when the mouse hovers it. But when I hover one of the models, the rest of the two models also change color.

The most stupid way is to create three identical glb model files, I have tried it can work, but I still hope to shared the code.

```javascript
import { useGLTF } from "@react-three/drei";
import{ Hover } from "modifiers/Hover";

export default function MyScene() {
  const gltf = useGLTF("/example.glb");
  const positions = [
    { x: -4, y: 1.6, z: 3.5, rx: 0, ry: 0, rz: 0 },
    { x: 0, y: 0, z: 3.5, rx: 0, ry: 0, rz: 0 },
    { x: 1.15, y: 1.6, z: 7.7, rx: 0, ry: Math.PI/2, rz: 0 },
  ];

  return (
    <>
      {positions.map((position, index) => {
        const clone = gltf.scene.clone();
        clone.position.set(position.x, position.y, position.z);
        clone.rotation.set(position.rx, position.ry, position.rz);
        return <Hover key={index} > <primitive object={clone} /> </Hover>
      })}
    </>
  );
}

```

Hover function:

```javascript
import React, { useRef, useState, ReactNode} from "react";
import { Group, Raycaster, Vector3 } from "three";
import { useFrame } from "@react-three/fiber";

export function Hover(props: HoverProps) {
  const {
    children,
  } = props;
  const hoverRef = useRef<Group>(null);
  const raycaster = new Raycaster();
  const posTemp = new Vector3();
  const [isHover, setHover] = useState(false);
  const [intersectState, setIntersectState] = useState('');
  let intersections;
  useFrame(({ camera }) => {
    if(hoverRef.current) {
      raycaster.set(camera.position, camera.getWorldDirection(posTemp));
      intersections = raycaster.intersectObject(hoverRef.current, true);
      if(intersections && intersections.length > 0 ){ 
        setIntersectState(intersections);
        intersections[0].object.material.emissive.setHex(0xffff00);
      } else {
        if(intersectState && intersectState.length > 0) {
          intersectState[0].object.material.emissive.setHex(0x333333);
          setIntersectState(null);
        }
      }
    }
  });

return (
    <group name="hover" ref={hoverRef}>  
      {children}
    </group>
  );
}

```

---

<div class="post-metadata">

**Author:** ![PavelBoytchev](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pavelboytchev/32/38639_2.png) [@PavelBoytchev](https://discourse.threejs.org/u/PavelBoytchev)\
**Post date:** [January 3, 2023, 9:31am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450/2 "2023-01-03T09:31:47Z")

</div>

@delongjs –

To have different colors, you must have different materials. So, this code will not work:

```javascript
objA = new THREE.Mesh( geometry, material );
objB = objA.clone(); // objB reuses geometry and material of objA
objB.position.x = 20;
objB.material.color.setRGB(0,1,0);

```

It will not work, because `objA` and `objB` share the same material (they also share the same geometry, but this is irrelevant now). To have a distinct material, it must be explicitly cloned:

```javascript
objA = new THREE.Mesh( geometry, material );
objB = objA.clone();
objB.position.x = 20;
objB.material = objB.material.clone(); // cloning the material
objB.material.color.setRGB(0,1,0);

```

In your case, you have to traverse the loaded model (as it may contain many objects and subobjects) and replace all materials that you want to change.

– Pavel

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [January 3, 2023, 10:49am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450/3 "2023-01-03T10:49:18Z")

</div>

the best way to deal with models is [gltfjsx](https://github.com/pmndrs/gltfjsx). this creates a virtual graph of the model, it can be re-used by default. watch this video and you’ll understand:

[https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/0/0/00a0f1fdb45eeaacd53c45c1c14465cc0d2bed7d.mp4](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/0/0/00a0f1fdb45eeaacd53c45c1c14465cc0d2bed7d.mp4)

here is an example of a [shoe model](https://codesandbox.io/s/dix1y) and giving them a different color.

if you do not want to create a jsx graph, either just call clone like pavel said.

```plaintext
function Model({ url, ...props }) {
  const { scene } = useGLTF(url)
  const cloned = useMemo(() => scene.clone(), [scene])
  return <primitive object={cloned} {...props} />

```

or, easier, there’s a drei abstraction

```plaintext
import { Clone } from '@react-three/drei'

function Model({ url, ...props }) {
  const { scene } = useGLTF(url)
  return <Clone object={scene} {...props} />

```

`<Clone>` has some benefits over `scene.clone`, it has shortcuts for castShadow/receiveShadow, can inject materials, but it also works with skinned models whereas `scene.clone()` would now fail.

---

<div class="post-metadata">

**Author:** ![delongjs](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@delongjs](https://discourse.threejs.org/u/delongjs)\
**Post date:** [January 3, 2023, 11:36am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450/5 "2023-01-03T11:36:33Z")

</div>

Thanks for the answer, I used [gltfjsx](https://github.com/pmndrs/gltfjsx) 、[gltf.pmnd](https://gltf.pmnd.rs/) originally, but I still get stuck. I’m not sure my question is clear enough, I have three same tsx models file, Map1、Map2、Map3, and they have the same color, when I hover Map1 it should change color(Map2、Map3 doesn’t change)， when the mouse leaves Map1, the color will become original, just like this example [three.js examples](https://threejs.org/examples/#webgl_interactive_cubes)

```javascript
// Map1.tsx

type GLTFResult = GLTF & {
  nodes: {
    meshExample01: THREE.Mesh;
    meshExample02: THREE.Mesh;
    .....
  };
  materials: {
    materialExample01: THREE.MeshPhysicalMaterial;
    materialExample02: THREE.MeshPhysicalMaterial;
    ....
  };
};

export default function Map1(props: BoardProps) {
  const group = useRef<THREE.Group>(null);
  const { nodes, materials } = useGLTF("example.glb") as GLTFResult;
  return (
    <group ref={group} position={[0,0,0]} rotation={[0, Math.PI/2, 0]} dispose={null}>
      <group name="Scene">
        <Hover >
          <mesh
            name="meshExample01"
            geometry={nodes.meshExample01.geometry}
            material={materials.materialExample01}
            position={[0.02, 0.17, 0.02]}
            rotation={[Math.PI / 2, 0, Math.PI / 2]}
          />
          <mesh
            name="meshExample02"
            geometry={nodes.meshExample02.geometry}
            material={materials["materialExample01"]}
            position={[0.24, 0.1, 0.02]}
            rotation={[Math.PI / 2, 0.2, Math.PI / 2]}
          />
          .................etc
        </Hover>
      </group>
    </group>
  );
}

useGLTF.preload("example.glb");

```

```javascript
// Map2.tsx

same with Map1.tsx

```

```javascript
// Map3.tsx

same with Map1.tsx

```

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [January 3, 2023, 11:59am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450/6 "2023-01-03T11:59:40Z")

</div>

if you mount Map multiple times, they will all share the same material. if you want each to have its own hover color you just need to give it a distinct material.

gltfjsx gives you something like this:

```plaintext
<mesh
  geometry={nodes.meshExample01.geometry}
  material={materials.materialExample01}
  ...>

```

make it

```plaintext
<mesh geometry={nodes.meshExample01.geometry}>
  <meshStandardMaterial color={materials.materialExample01.color} />

```

look into that shoe example above once more. the reason it can have a distinct color is because it makes its own material.

---

<div class="post-metadata">

**Author:** ![delongjs](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@delongjs](https://discourse.threejs.org/u/delongjs)\
**Post date:** [January 4, 2023, 6:42am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450/7 "2023-01-04T06:42:09Z")

</div>

Thanks for the very clear explanation, I still have one more question to ask from the shoe example, How can I extract the mesh material from material={materials.mesh} to \<meshStandardMaterial … /\>? Thanks.

```javascript
material={materials.mesh}

```

```javascript
<meshStandardMaterial
  aoMap={materials.mesh.aoMap}
  normalMap={materials.mesh.normalMap}
  normalMap-encoding={THREE.LinearEncoding}
  roughnessMap={materials.mesh.roughnessMap}
  metalnessMap={materials.mesh.metalnessMap}
  envMapIntensity={0.8}
/>

```

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [January 4, 2023, 10:28am UTC](https://discourse.threejs.org/t/how-to-clone-a-model-and-change-color-respectively/46450/8 "2023-01-04T10:28:28Z")

</div>

yes, like that, if you need it to have a distinct material but you want to copy over something things that’s how you’d do it.
