How to add click event on child mesh of an object?

Hi. So I have a model that has multiple meshes which I’m getting by using getObjectByName

Model = newElement.getObject3D('mesh').getObjectByName('Mesh006')
ModelMouth = newElement.getObject3D('mesh').getObjectByName('Mesh006_1')
ModelLeftEye = newElement.getObject3D('mesh').getObjectByName('_Leye_geo')
ModelRightEye = newElement.getObject3D('mesh').getObjectByName('_Reye_geo')
ModelPlank = newElement.getObject3D('mesh').getObjectByName('_high_geo')

Is it possible to have a click event listeners to each of these meshe? I’d like to trigger something when Model is clciked and when ModelPlank is clicked.

what i have so far, though i just keep getting no plank

const mouse = new THREE.Vector2()
const raycaster2 = new THREE.Raycaster()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

      document.body.addEventListener('click', (e) => {
        mouse.x = (e.clientX / window.innerWidth) * 2 - 1
        mouse.y = -(e.clientY / window.innerHeight) * 2 + 1
        raycaster2.setFromCamera(mouse, camera)
        // raycaster2.ray.at(distance, mesh.position)
        const intersects = raycaster2.intersectObject(chameleonPlank)
        const intersectModel = raycaster2.intersectObject(chameleonModel)
        if (intersectModel.length > 0) {
          console.log('hit')
        } else {
          console.log('no plank')
        }
      })

You can define the objects to be selected by raycast yourself.

See from the Collection of examples from discourse.threejs.org :

BeginnerExample step 10



// ... step 10: raycaster 
//=================================================================================================
			// https://threejs.org/docs/index.html#api/en/core/Raycaster
const raycaster = new THREE.Raycaster( ); // see function raycasting( ); in animate
const mouse = new THREE.Vector2( ); // see function onWindowMousemove( event )
let intersects = []; // array of intersected objects
			// https://threejs.org/docs/index.html#api/en/geometries/OctahedronGeometry
const ohGeometry = new THREE.OctahedronGeometry( 0.3 );
const ohMesh = new THREE.Mesh( ohGeometry, new THREE.MeshPhongMaterial( { color: 0xff0045 } ) );
scene.add( ohMesh );
const objs = [ ohMesh, flowerMesh, modelLh, ballMesh, diceMesh, sandPileMesh, rampMesh, stemMesh, flagpoleMesh, flagMesh, sfSprite, sheetMesh ];
const infos = [ 'octahedron', 'flower', 'lighthouse', 'ball', 'dice', 'sand', 'ramp', 'stem', 'pole', 'three.js', 'sunflower', 'sheet' ]
let index = 0;
objs.forEach( obj => { obj.name = infos[ index ]; index ++; } );  // names for some objects

// ======= to step 10 ============

function raycasting( ) {
	
	if( range.value > 9.5 && range.value < 10.5  ) { // only step 10 
		
		raycaster.setFromCamera( mouse, camera );
		intersects = raycaster.intersectObjects( objs ); // objs - objects to raycast
		
		if ( intersects.length > 0 ) { // hit
			
			info.style.fontSize = '5vh';
			info.style.color = 'white';
			info.innerHTML = ' you got a hit => ' + intersects[ 0 ].object.name; //  ...[ 0 ]  first intersected object
			ohMesh.material.color.setHex( 0x4500ff );
			
		} else {
			
			info.style.fontSize = '1.9vh';
			info.style.color = 'black';
			info.innerHTML = 'Beginner Example';
			ohMesh.material.color.setHex( 0xff0045 );
			
		}
		
	}
	
}

So does the raycaster only work on threejs mesh? I’m working with AFrame as well. The newElement in my OP is an AFrame entity which has the main model. And I got the the other meshes in the main model by name. Now I need to have the plank have the ability to be clicked. I’ve seen numerous example of using the Raycaster but they’ve all used a mesh/model that was created using threejs, so I’m confused how to apply it to this model that i have.

It is appropriate to indicate keywords that match the question. The problem seems to be AFrame. This was not obvious. Please add it so that future viewers know what it is about and can also find it in the forum search.

I myself do not know AFrame.

But I took a look:
Developing with three.js – A-Frame


2022-11-01 17.33.45


2022-11-01 17.38.12


Is it possible to achieve something with it :thinking:

Hi. Yes, I’ve seen the AFrame documentation but am somehow unable to get the mesh. As in OP, I have 1 3d object and accessing and customising the different meshes in the model. Now, I’m trying to figure out if each of those meshes can be clicked/raycast somehow. Have not been successfull.

since you already use threejs declaratively is switching to react a possibility? in three three-fiber this would be absolutely trivial since you have real pointer events, bubbling, stopPropagation, events on groups, etc.

<group onClick={(e) => {
  // e.object is the clicked mesh, no matter how deeply nested
  // e.eventObject is the source (the group)
  // e.stopPropagation() would stop bubbling (nearest object wins) 
}}>
  <group>
    <mesh ... />
  </group>
  <mesh ... />
  <mesh ... />
  <mesh ... />
</group>

bruno simon has a complete tutorial on this as well: Three.js Journey — Mouse Events with R3F in the middle of that course he does exactly what you want with a hamburger model (distributing events between top bun, cheese, burger, bottom bun).

Will have to look into it, have not personally used React. Would i need to change everything that i’ve done? As this is a webar project using 8thwall, aframe, threejs.

it depends. it might make sense since 8thwall has a lot of fiber components and integrations, i think many people use it with react. but if the project is too large perhaps you’re better off implementing the event handler you need.