I can not get raycaster insersectObjects

Hello, I want to get count click position related to threeD obj, below is what I did:

play3D() {
        const domElement = this.nativeElement.children[0];
        domElement.innerHTML = '';
        this.renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(domElement.offsetWidth, domElement.offsetHeight);
domElement.appendChild(this.renderer.domElement);

        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
        this.camera.add(new THREE.PointLight(0xffffff, 0.8));
        this.scene.add(this.camera);
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        const loader = new OBJLoader();

        loader.load(this.threeDPath, obj => {
          
            this.scene.add(obj);
            this.controls.update();


        }, this.onProgress);

        this.raycaster = new THREE.Raycaster();
        this.mouse = new THREE.Vector2();


        window.addEventListener('resize', this.onWindowResize, false);
        window.addEventListener( 'click', this.onMouseClick, false );
    }

onMouseClick( event ) {

        this.mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        this.mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
        console.log(this.mouse.x, this.mouse.y);
        this.raycaster.setFromCamera(this.mouse, this.camera);
        // calculate objects intersecting the picking ray
        const intersects = this.raycaster.intersectObjects(this.scene.children, true);
        console.log(intersects);
        for ( let i = 0; i < intersects.length; i++ ) {
                  intersects[ i ].object.material.color.set( 0xff0000 );
        }
    }

But when I run it, the intersects are always empty.
So may I ask what is the accurate way to get mouse click position x,y related to the 3D object?

Thanks

I have not checked everything, but I notice that you use domElement.offsetWidth for the renderer and window.innerWidth for the mouseclick. I personally use clientWidth of a container element for both, but I think it is most important that you use compatible coordinates.

We lately had a similar issue in an other topic. I’ve posted there a live example that might help to debug and correct your code:

If id does not help to solve your issue, please update the live example in order to reproduce the wrong raycasting behavior.

Hi, thanks for your suggestion, I am now using threeJS in angular6, and found the raycaster.intersectObjects sometimes is working, sometimes not working, that means, when I click some part of 3D, I got intersects obj, sometimes, I got 0 instersected objects, this behavior is strange, any idea why this happened?

Hope to hear your advice here.
Thanks

import { Component, OnInit, AfterViewInit, Input, Output, ElementRef, EventEmitter, OnDestroy } from ‘@angular/core’;
import { ThreeD, TYPE_3D } from ‘./threeD.entity’;
import { OrbitControls } from ‘three/examples/jsm/controls/OrbitControls’;
import * as THREE from ‘three’;
import { OBJLoader } from ‘three/examples/jsm/loaders/OBJLoader’;

@Component({
    selector: 'app-3d-player',
    template: `<div id='3d_player' class='threeD_player'></div>`,
    styleUrls: ['./threeD_player.component.scss']
})
export class ThreeDPlayerComponent {

    @Input() threeDPath: string;

    nativeElement: any;
    comp: any;
    object: any;

    renderer: any;
    camera: any;
    scene: any;
    controls: any;

    constructor(el: ElementRef) {
        this.nativeElement = el.nativeElement;
        setTimeout(() => {
            this.loaderType = this.threeDPath.substr(this.threeDPath.lastIndexOf('.') + 1);
            this.play3D();
            this.animate();
        });
        this.render = this.render.bind(this);
        this.onMouseClick = this.onMouseClick.bind(this);

        this.animate = this.animate.bind(this);
        this.preservingBuffer = true;
        this.darkMode = true;

    }

    animate() {
        requestAnimationFrame(this.animate);
        this.render();
    }
    play3D() {
        const domElement = this.nativeElement.children[0];
        domElement.innerHTML = '';
        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setPixelRatio(window.devicePixelRatio);
        // this.renderer.setSize(domElement.offsetWidth, domElement.offsetWidth / window.devicePixelRatio);
        this.renderer.setSize( window.innerWidth, window.innerHeight );

        domElement.appendChild(this.renderer.domElement);

        this.scene = new THREE.Scene();
        if (this.darkMode) {
            this.scene.background = new THREE.Color(0x000000);
        } else {
            this.scene.background = new THREE.Color(0xffffff);
        }
        this.scene.add(new THREE.AmbientLight(0xcccccc, 0.4));
        this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);

        this.camera.position.set(-2, 2, 1);

        this.camera.add(new THREE.PointLight(0xffffff, 0.8));
        this.scene.add(this.camera);

        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        const loader = new OBJLoader();

        loader.load(this.threeDPath, obj => {

            const box = new THREE.Box3().setFromObject( obj );
            const center = new THREE.Vector3();
            box.getCenter( center );
            obj.position.sub( center );
            this.scene.add( obj );
            this.render();
        });
        this.renderer.domElement.addEventListener('click', this.onMouseClick, false);
    }

    onMouseClick(event) {
        event.preventDefault();

        const raycaster1 = new THREE.Raycaster();
        const mouse1 = new THREE.Vector2();

        mouse1.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse1.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

        raycaster1.setFromCamera( mouse1, this.camera );

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

        if ( intersects.length > 0 ) {

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

        }

    }
    render() {
        this.renderer.render(this.scene, this.camera);
    }

}

Getting inconsistent results may be consistent with an unintended offset from the actual click position. You should check and confirm that the canvas is absolutely positioned at top: 0, left: 0, or otherwise (as I would recommend), put it in a container that you have full control of, and then use only container client coordinates (clientX, clientWidth etc).

Thanks,
Are there any concrete example that can show how to attach hotspot to 3D object?
What I mean is even if the hotspot is added to the scene using sprite and separate Object3D layer, when the 3D is rotating, the hotspot image is not actually attached to 3D, for example, front cover and back cover both have hotspot, when I rotate the object, the hotspot is really not attached to the 3D at all.
I think this is because my implementation is not elegant, and i am looking to see if there are any good example I can follow.
Thanks

I think your last post was intended for this thread: How to add hotspot to 3D?