Raycaster applying materials to multiple objects on click

Hello everyone,

I have setup a raycaster which changes the hex of an object when selected and deselected. The issue being, that although the raycaster detects intersections on individual objects on the scene, it applys the hex colour change to all the objects rather than just the one clicked on. I have coded it to iterates through the scene’s children however, the hex colour applies to all of the children and not the intersected one.

// Import libraries
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.124.0/build/three.module.js'
import { MapControls } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/controls/OrbitControls.js'
import { Rhino3dmLoader } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/loaders/3DMLoader.js'


// function to setup the scene, camera, renderer, and load 3d model


    
   window.addEventListener( 'click', onClick, false);

    const model = 'plant.3dm'
  
    let scene, camera, renderer, controls, raycaster, pointlight;

    const mouse = new THREE.Vector2()
    window.addEventListener( 'click', onClick, false);
    
    THREE.Object3D.DefaultUp = new THREE.Vector3( 0, 0, 1 )
       
    let INTERSECTED;

    function init() {
      scene = new THREE.Scene();

      renderer = new THREE.WebGLRenderer({alpha:true,antialias:true});
      renderer.setSize(window.innerWidth,window.innerHeight);
      document.body.appendChild(renderer.domElement);

      renderer.outputEncoding = THREE.sRGBEncoding;
      renderer.toneMapping = THREE.ACESFilmicToneMapping;
      renderer.toneMappingExposure = 1.25;

      camera = new THREE.PerspectiveCamera(30,window.innerWidth/window.innerHeight,1,1000);
      camera.position.set(0,0,60);


      raycaster = new THREE.Raycaster()

        controls = new MapControls( camera, renderer.domElement );


        controls.enableDamping = true;
        controls.dampingFactor = 0.05;

        controls.screenSpacePanning = false;

        controls.minDistance = 10;
        controls.maxDistance = 500;

        controls.maxPolarAngle = Math.PI / 2;



      pointlight = new THREE.PointLight(0xffffff,1);
      pointlight.position.set(200,200,200);
      scene.add(pointlight);



        let mainMat = new THREE.MeshPhysicalMaterial({  
          clearcoat: 1.0,
          cleacoatRoughness:0.1,
          metalness: 0.9,
          roughness:0.5,
          color: 0x000000,
   
        }); 
        


            //load the model
        const loader = new Rhino3dmLoader()
        loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@0.13.0/' )

       
    
    
          
        loader.load( model, function ( object ) {

        object.traverse( function (child) {         
            child.material = mainMat
            }); 

        
            scene.add( object )
    
         } )
         
    }



    function onClick( event ) {

      console.log( `click! (${event.clientX}, ${event.clientY})`)
  
  
    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1
      mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1
      
      raycaster.setFromCamera( mouse, camera )
  
    
      const intersects = raycaster.intersectObjects( scene.children, true )
  
      let container = document.getElementById( 'container' )
      if (container) container.remove()
  

      // find intersections


  if ( intersects.length > 0 ) {

    if ( INTERSECTED != intersects[ 0 ].object ) {

      //if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

      INTERSECTED = intersects[0].object;

      console.log(`this is ${INTERSECTED}`);

      INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
      INTERSECTED.material.emissive.setHex( 0xff0000 );

    }

  } else {

    if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

    INTERSECTED = null;

  }


}


    function animate() {
      controls.update();
      renderer.render(scene, camera);
      requestAnimationFrame(animate);
      controls.update()
    }
    
    init();
    animate();
    


The objects in your scene share the same material, so any changes to that material applied to all of them.
You need to clone the material when you assign it to the objects, so that each object has its own material.
Just switch your code to do object.material = mainMat.clone() in order to clone the material.

1 Like

Amazing, thank you works perfectly now.