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:
Can you try it with this (JS) code instead:
function onClick(event) {
const rect = renderer.domElement.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
mouse.x = ( x / canvas.clientWidth ) * 2 - 1;
mouse.y = ( y / canvas.clientHeight) * - 2 + 1
this.perspectiveCamera.updateMatrixWorld();
this.raycaster.setFromCamera( mouse, this.perspectiveCamera );
}
It will respect the relative position of the canvas in your HT…
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