mouseOver on a GLTF with Orbital Controls

Hi there,
iam short before finishing a project for an simple GLTF model viewer.
i can turn the model(orbital) and click on intersections and get the object name.
but iam unable to create any mouseOver effect just change the color of the object.
its only working when i am in the moment of using the orbital control.
i used that example for the GLTF viewer and Click!

and this for mouseOVER:

thanks for links or help!

Here is an updated fiddle combining pointerdown and pointermove with the latest three.js version:

Full code:

import * as THREE from 'three';

import { OrbitControls } from 'https://unpkg.com/three@0.140.2/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'https://unpkg.com/three@0.140.2/examples/jsm/loaders/GLTFLoader.js';
import { RGBELoader } from 'https://unpkg.com/three@0.140.2/examples/jsm/loaders/RGBELoader.js';

let camera, scene, renderer;

const pointer = new THREE.Vector2();
const raycaster = new THREE.Raycaster();

init();
animate();

function init() {

  const container = document.createElement( 'div' );
  document.body.appendChild( container );

  camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
  camera.position.set( - 1.8, 0.6, 2.7 );

  scene = new THREE.Scene();

  new RGBELoader()
    .setPath( 'https://threejs.org/examples/textures/equirectangular/' )
    .load( 'royal_esplanade_1k.hdr', function ( texture ) {

    texture.mapping = THREE.EquirectangularReflectionMapping;

    scene.background = texture;
    scene.environment = texture;

    // model

    const loader = new GLTFLoader().setPath( 'https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/' );
    loader.load( 'DamagedHelmet.gltf', function ( gltf ) {

      scene.add( gltf.scene );
      
      gltf.scene.traverse( function( object ) {
      
      	if ( object.isMesh === true ) object.material.userData.color = object.material.color.clone(); // used for resetting
      
      } );

    } );

  } );

  renderer = new THREE.WebGLRenderer( { antialias: true } );
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
  renderer.toneMappingExposure = 1;
  renderer.outputEncoding = THREE.sRGBEncoding;
  container.appendChild( renderer.domElement );

  const controls = new OrbitControls( camera, renderer.domElement );
  controls.minDistance = 2;
  controls.maxDistance = 10;
  controls.target.set( 0, 0, - 0.2 );
  controls.update();

  window.addEventListener( 'resize', onWindowResize );

  renderer.domElement.addEventListener('pointerdown', onPointerDown);
  renderer.domElement.addEventListener('pointermove', onPointerMove);

}

function onWindowResize() {

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

  renderer.setSize( window.innerWidth, window.innerHeight );

}

function animate() {

	requestAnimationFrame( animate );
  renderer.render( scene, camera );

}

function onPointerMove() {

	pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
  pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
  
  raycaster.setFromCamera(pointer, camera);
  
  const intersects = raycaster.intersectObjects(scene.children, true);
  
  // reset colors
  
  scene.traverse( function( object ) {
      
    if ( object.isMesh === true ) object.material.color.copy( object.material.userData.color );

  } );
  
  //

  if (intersects.length > 0) {

    const object =  intersects[0].object;
    
    object.traverse( function( obj ) {
    
    	if ( obj.isMesh === true ) {
      
      	obj.material.color.set( 0xff0000 );
      
      }
    
    } );

  }

}

function onPointerDown() {

  raycaster.setFromCamera(pointer, camera);

  const intersects = raycaster.intersectObjects(scene.children, true);

  if (intersects.length > 0) {

    console.log('Intersection:', intersects[0]);

  }

}
1 Like

thank YOU!
that done the work.
great forum

1 Like

hi there I still have a problem with the raycaster it is 100 pixel over every intersectObject.

Try using getBoundingClientRect() when computing the pointer location:

FOUND solution: for the CODE with GLTF and Mouse OVER:

function onPointerMove() {

const rect = renderer.domElement.getBoundingClientRect();

const x = event.clientX - rect.left;
const y = event.clientY - rect.top;

pointer.x = ( ( event.clientX - rect.left ) / ( rect.width - rect.left ) ) * 2 - 1;
pointer.y = - ( ( event.clientY - rect.top ) / ( rect.bottom - rect.top) ) * 2 + 1;

camera.updateMatrixWorld();
raycaster.setFromCamera( pointer, camera );

YOU have to define a div for threes in HTML file
and link it with the container!
container = document.getElementById( ‘canvas’ );

1 Like