Exact position on mouse click

Helllou,
I trying to get position of mouse click on this plane.Is even possible get exact position of Click ,when you looking from this angle ?

I have something like this,but doesn’t work ,because this taking position of html window,not from scene.

      var cube = this.scene.getObjectByName('Cube'); //this is  object from blender
      var plane = this.scene.getObjectByName('Plane');  //this is  object from blender
 addEventListener('click',e =>{
        mousePosition.x = (e.clientX / window.innerWidth) * 2 - 1;
        mousePosition.y = -(e.clientY / window.innerHeight) * 2 + 1;
      console.log("X = "+mousePosition.x);
      console.log("Y = "+mousePosition.y);
      raycaster.setFromCamera(mousePosition,this.camera);

I want move cube to position where I will click,something like this

cube.position.setX(mousePosition.x)
cube.position.setZ(mousePosition.y)

Do you have some advice ?

1 Like

You are almost done.

Send a ray from the raycaster and get the intersection with the plane. This intersection contains many data, one of which is the exact 3D position of the intersection point. You can use it to position a cube there.

1 Like

I tried

const intersects = raycaster.intersectObjects(this.scene.children);
console.log( intersects[0].point);

response = Vector3 {x: 2, y: 0, z: 0.5804248372069998}
but this is not exact position where I clicked.
Probably is problem in intersetcObject, because there is some kind of children and I want only “Plane”
I tried this but doesn’t working

const intersects = raycaster.intersectObjects(this.scene.getObjectByName('Plane'));

I think what you’re looking for is intersectObject, which would be an individual object rather than an array of objects…

raycaster.intersectObject(this.scene.getObjectByName('Plane'))

I tried this before ,but same result

@Wynnyy Would be better to provide the model you use, if possible. Or provide a live code example (jsfiddle, codepen, codesandbox), that demonstrates the issue. :thinking:

1 Like


and there is also 1GLtf file/bin which contain Cube and Plane

can you provide the game.gltf file in this thread? with a bit of modification to make your code compatible with codepen the intersectsObject method seems to work fine with a plane exported from blender…

link for download gltf files
https://file.io/VjyfSOv1tk48

there’s a problem with that link :man_shrugging: can you upload the gltf to gitub as raw gltf files?

try this one

this works fine…

1 Like

thanks a lot :+1:
do you know what problem occurred when I put that object into intersectObject ?
because looks like same and this working

np :slight_smile: I think it may have just been a misundrestanding of what intersectsObject does, it takes in one object to raycast against but still returns an array of intersections ( this is incase recursive is set to true and the object in question has a multitude of child elements ) in your case I’m sure the error was simply because you were not checking if ( intersects.length > 0 ){ } eg in the following code from your pen…

const intersects = raycaster.intersectObject(this.scene.getObjectByName('Plane'));
console.log( intersects[0].point);
   
//if (intersects.length > 0) {
//  console.log(intersects[0].point);
//}

should probably be…

const intersects = raycaster.intersectObject(this.scene.getObjectByName('Plane'));

if (intersects.length > 0) {
  console.log(intersects[0].point);
}

there were a few other issues in your code, for instance you created your click event listener inside your animation loop, in essence creating a click event every frame will result in a huge memory leak, as well as creating raycaster, mousePosition, cube, plane, draggable in the same loop, these elements can be created once a reused, especially the click event!

1 Like

ok thanks man :slight_smile:

Hi @Lawrence3DPK anyway similar problem ,is much better but when I click on corner or another place ,my cube is not on exact position.Idk what can have impact on this, render size ,maybe another things.
here for example

Everything is same in code I think except for offset which is in camera hardcoded but nothing special

export class FooterComponent {  
  //Basics
  private loader = new GLTFLoader();
  private scene = new THREE.Scene();  
  private renderer = new THREE.WebGLRenderer( { antialias: true });
  //Movement
  private raycaster = new THREE.Raycaster();
  private mousePosition = new THREE.Vector2();
  cube : any;
  plane : any;
  private widthh? :  any //= document.querySelector<HTMLElement>("#containers")?.offsetWidth
  private heightt? : any // document.querySelector<HTMLElement>("#containers")?.offsetHeight
  
  //Lights
  private light3 = new THREE.PointLight('white',250,10,5)
  //Camera
  private camera = new THREE.PerspectiveCamera(50,1202/1202, 0.1,10000 );
  private controls = new OrbitControls(this.camera, this.renderer.domElement  );

  ngOnInit(){
    this.helpers();
    this.movement();
    this.heightt = document.querySelector<HTMLElement>("#containers")?.offsetHeight;
    this.widthh = document.querySelector<HTMLElement>("#containers")?.offsetWidth;
    document.getElementById("containers")?.appendChild(this.renderer.domElement);
 
    this.scene.add(this.light3);
    this.light3.position.set(0,2.5, 0);
    this.camera.position.set( 3,1.5, 0 );
    this.renderer.setSize(this.widthh!,this.heightt!);
	  this.renderer.setClearColor( 0xffffff, 0)

    this.loader.load( '/assets/blender/game.gltf',  ( gltf ) => {
      this.scene.add( gltf.scene );
      gltf.scene.matrixAutoUpdate = false;      
      gltf.scene.position.x = -0.5;	
      this.scene.add( gltf.scene );      
      animate();
      this.cube = this.scene.getObjectByName('Cube');
      this.plane = this.scene.getObjectByName('Plane');
      
 
  }, undefined, function ( error ) {

    console.error( error );});
 
      const animate = () => {
      requestAnimationFrame( animate );
      this.renderer.render( this.scene, this.camera );
      this.controls.update();      
    
     }
    
  }
  
  movement(){ 
    addEventListener('click',e =>{
      this.mousePosition.x = (e.clientX / window.innerWidth) * 2 - 1;
      this.mousePosition.y = -(e.clientY / window.innerHeight) * 2 + 1;

    this.raycaster.setFromCamera(this.mousePosition,this.camera);
    
    const intersects = this.raycaster.intersectObject(this.plane);
 
          if (intersects.length > 0) {
            this.cube.position.copy(intersects[0].point)
            this.cube.position.y = 0.125
      
    }


   
  });
    
  }
}

is your containers element the full size of the window or a smaller sized container? if it’s smaller then you’d need to use the following in the click event…

addEventListener('click',e =>{
  this.mousePosition.x = (e.clientX / widthh) * 2 - 1;
  this.mousePosition.y = -(e.clientY / heightt) * 2 + 1;

  this.raycaster.setFromCamera(this.mousePosition,this.camera);
  const intersects = this.raycaster.intersectObject(this.plane);

  if (intersects.length > 0) {
    this.cube.position.copy(intersects[0].point)
    this.cube.position.y = 0.125
  }

});

where widthh and heightt are the offsetWidth and offsetHeight of the container eg…

document.querySelector("#containers").offsetWidth
document.querySelector("#containers").offsetHeight

this is also why it’s useful to have a live working example in codesandbox or codepen, if the container is smaller than the window and has margins then you’d also need to account for the offsetTop and offsetLeft of the container to get accurate raycasting…

yeah see that,
this.mousePosition.x = (e.clientX / widthh) * 2 - 1;
this.mousePosition.y = -(e.clientY / heightt) * 2 + 1;
doesnt fix my problem,but every margin have impact on this position, also camera position have impact


now working, position :fixed, if I choice flex ,then doesnt work, so this is just playing with css position etc.

1 Like