I was wandering if there is any method in three.js that allows the user to click on a model (for example an imported gltf file from blender) and as a result of the click something else to happen (for example a pop up box or an image is displayed).
I was trying to look it up in the three.js website but all found was the raycaster class. But from my understanding this will only work with objects that have a mesh and thus only the ones that are made in three.js itself with the geometry properties.
I also found tutorials with the use of threex.domevents. But once again I don’t see how this can be used with the models imported from blender. I tried using it but it only caused my models to disappear from the screen.
So is there another solution? or is it impossible?
Instead of logging something to the console, you can of course perform an arbitrary action. Most important part is the onClick() handler which triggers the actual intersection:
Hello @Mugen87, I have a proplem when I created Mouse Click Raycaster event on model GLTF loader import from Blender. I want click on a model and it will zoom in and other model will hide but it not work. How do I catch the click event on a GLTF model ?.
function loadModel(url) {
return new Promise((resolve) => {
gltfLoader.load(url, resolve);
});
}
let model1, model2;
let p1 = loadModel("models/human_teeth.gltf").then((result) => {
model1 = result.scene;
});
let p2 = loadModel("models/human_teeth1.gltf").then((result) => {
model2 = result.scene.children[0];
});
Promise.all([p1, p2]).then(() => {
//do something to the model
//add model to the scene
scene.add(model1, model2);
//continue the process
});
const raycaster = new THREE.Raycaster();
let currentIntersect = null;
const rayOrigin = new THREE.Vector3(-3, 0, 0);
const rayDirection = new THREE.Vector3(10, 0, 0);
rayDirection.normalize();
/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
window.addEventListener("resize", () => {
// Update sizes
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
// Update camera
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
// Update renderer
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});
/**
* Camera
*/
// Base camera
const camera = new THREE.PerspectiveCamera(
55,
sizes.width / sizes.height,
0.1,
100
);
camera.position.set(-12, 6, 8);
scene.add(camera);
const mouse = new THREE.Vector2();
window.addEventListener("mousemove", (event) => {
mouse.x = (event.clientX / sizes.width) * 2 - 1;
mouse.y = -(event.clientY / sizes.height) * 2 + 1;
});
window.addEventListener("click", () => {
if (currentIntersect) {
switch (currentIntersect.object) {
case model1:
console.log("click on object 1");
break;
case model2:
console.log("click on object 2");
break;
}
}
});
// Controls
const controls = new OrbitControls(camera, canvas);
controls.target.set(0, 4, 0);
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
});
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
/**
* Animate
*/
const tick = () => {
raycaster.setFromCamera(mouse, camera);
const objectsToTest = [model1, model2];
const intersects = raycaster.intersectObjects(objectsToTest);
if (intersects.length) {
if (!currentIntersect) {
console.log("mouse enter");
}
currentIntersect = intersects[0];
} else {
if (currentIntersect) {
console.log("mouse leave");
}
currentIntersect = null;
}
controls.update();
// Render
renderer.render(scene, camera);
// scene.background = new THREE.Color(0x555252);
// Call tick again on the next frame
window.requestAnimationFrame(tick);
};
tick();
And I have an error:
Uncaught TypeError: Cannot read properties of undefined (reading ‘layers’)
at intersectObject (three.module.js:46609:1)
at Raycaster.intersectObjects (three.module.js:46589:1)
at tick (script.js:153:32)
at script.js:191:1
at bundle.afdd5463a1049c8d.js:60375:3
at bundle.afdd5463a1049c8d.js:60377:12
So is there another solution? or is it impossible?