Three.js how to click on building floor

hI guys, I really need help, I have model(building model) and my task is to get and show building floor info when user clicks on specific floor(for example 3floor or 5 floor).I read some topics but I can’t do it.
Should I use meshes?
here is my code

<head>
    <title>threejs - models</title>
</head>
<body>

    <canvas id="myCanvas"></canvas>

    <script type="module">
			import * as THREE from '../build/three.module.js';

			import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
			import { DRACOLoader } from './jsm/loaders/DRACOLoader.js';
			import { OrbitControls } from './jsm/controls/OrbitControls.js';
			var camera, scene, renderer;

			// Instantiate a loader
			var loader = new GLTFLoader();
			var renderer;

			var scene = new THREE.Scene();
			var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

		

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

				var controls = new OrbitControls( camera, renderer.domElement );
				controls.addEventListener( 'change', render );
				controls.target.set( 0, 1.2, 2 );
				controls.minDistance = 1;
				controls.maxDistance = 300;
				controls.update();

				window.addEventListener( 'resize', onWindowResize, false );
				function render() {

					renderer.render( scene, camera );

					}

				function onWindowResize() {

							camera.aspect = window.innerWidth / window.innerHeight;
							camera.updateProjectionMatrix();

							renderer.setSize( window.innerWidth, window.innerHeight );
								render();
				}
				// Color for white
				renderer.setClearColor( 0xffffff, 1 );



							//LIGHTS
				var light = new THREE.AmbientLight(0xffff, 0.5);
				scene.add(light);
				var light2 = new THREE.PointLight(0xffffff, 2);
				scene.add(light2);

				var dracoLoader = new DRACOLoader();
				dracoLoader.setDecoderPath( '/examples/js/libs/draco/' );
				loader.setDRACOLoader( dracoLoader );

				var toIntersect = [];

				// Load a glTF resource
				loader.load(
					//'max.gltf',
					'./last.gltf',
					function ( gltf ) {
						console.log('gltf', gltf)
						camera.position.z = 40;
						scene.add( gltf.scene );
						var t = gltf.scenes[0].children;
						scene.traverse(function (t) {
							if (t instanceof THREE.Mesh) {
								toIntersect.push(t);
							}
						});
					
					},
					// called while loading is progressing
					function ( xhr ) {
						console.log('done')
						console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

					},
					// called when loading has errors
					function ( error ) {
						console.log(error);
					}
				);

				var raycaster, mouse = { x : 0, y : 0 };
				raycaster = new THREE.Raycaster();
				var mouse = new THREE.Vector2();

				renderer.domElement.addEventListener( 'click', raycast, false );
			

				function raycast ( e ) {
				
					mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
					mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
					var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
					raycaster.setFromCamera( mouse, camera );
					var intersects = raycaster.intersectObjects( toIntersect );
					console.log(intersects)
					var INTERSECTED;

					if ( intersects.length > 0 )
					{
						var color = (Math.random() * 0xffffff);
						intersects[0].object.material.color.setHex(color);
					}
					

					}
    </script>
</body>
</html>

Maybe you want to try adding annotation type functionality to your scene.

Here is an example : https://codesandbox.io/s/github/Sean-Bradley/Three.js-TypeScript-Boilerplate/tree/annotations/?file=/src/client/client.ts

Anyway, the trick you might want to try is that for specific meshes that you want selectable, you can set there custom userData to some value. And when you check with the raycaster intersects, you can see if the intersected object contains that userData and then do a specific event for example show some information.
In my example see line 87 where I add custom userData to a circle mesh, and then line 142 where I do something with it. In my case, I change the camera position and controls target.

1 Like

thanks a lot for comments.
So if I understood right I should add userData specific data in each mesh and after clicking on it check and run my event?
I am using this model is this correct?Residential Buildings 008.fbx (196.6 KB)

Or this gltf formatlast.gltf (1.7 MB)

it doesn’t matter what format you use, you need to tell it what you want it to do.

ok let me try, thanks a lot

I have tried but no result(((
1.How can I click each of this floor(this is one model) and make my event,
Customer don’t want annotation, he want user click on floor and after that it will see information of that floor.

Please any advice?