javascriptthree.jsgsapraycasting

Unable to raycast a single object in a group in three.js in order to run an animation


I am having a problem with raycasting into a group I've created in three.js.

I am attempting to trigger animations with TweenMax when I click on object. The problem is when you click an object with another behind it, it triggers both of the objects animation sequences since it's raycasting both objects.

My raycasting code is below and here is a link to the working url to see the entire project. -> www.jacobtruax.info

Is there a better way to achieve what I am attempting to do, or a way I can stop it from raycasting two objects at a time?

let mouse = new THREE.Vector2();
let raycaster = new THREE.Raycaster(),INTERSECTED;

  document.addEventListener("mousemove", function (event) {
    if (isMouseDown) {
      document.body.style.cursor = 'grabbing'
    }

    aimX = ((window.innerWidth / 2) - event.pageX) * 0.35
    aimY = ((window.innerHeight / 2) - event.pageY) * 0.5
    aimX2 = ((window.innerWidth / 2) - event.pageX) * 0.05
    aimY2 = ((window.innerHeight / 2) - event.pageY) * 0.05

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

    raycaster.setFromCamera(mouse, camera)

    const intersections = raycaster.intersectObjects(group.children)

    const sWorks = document.getElementById('sWorks')

    if (intersections.length > 0) {
          if (INTERSECTED != intersections[0].object) {
              if (INTERSECTED)
              INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
              INTERSECTED = intersections[0].object;
              INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
              //setting up new material on hover
              INTERSECTED.material.color.setHex( 0xadadad );
              // uRL()
              if (INTERSECTED){
                sWorks.innerHTML = intersections[0].object.userData.NAME
              }
              if (INTERSECTED){
                document.body.style.cursor = "pointer"
              }
          }
      } else {
          if (INTERSECTED) INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
          sWorks.innerHTML = "Selected Works";
          document.body.style.cursor = "grab";
          INTERSECTED = null;


      }

    if(isMouseDown) {
      aimX = aimX + (event.pageX - startX)
      aimY = aimY + (event.pageY - startY)
      group.rotation.set(0, ((aimX + (event.pageX - startX)) + (aimY + (event.pageY - startY))) / 900, 0)
      //createShape(event.pageX, event.pageY)
    }
  })

  document.addEventListener('mousedown', onDocumentMouseDown, false);

    function onDocumentMouseDown(event) {
          event.preventDefault();
          mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
          mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
          raycaster.setFromCamera(mouse, camera);
          var intersectFnup = raycaster.intersectObject(fnup);
          var intersectOld = raycaster.intersectObject(old);
          var intersectCam = raycaster.intersectObject(cam);
          var intersectAlex = raycaster.intersectObject(alex);
          const intersections = raycaster.intersectObjects(group.children)
          if (intersections.length > 0){
            if (intersectOld.length > 0) {
                  TweenMax.to(old, 1.5, {three:{scaleX: 2.5, scaleY: 2.5, x:0, y:0, z:0, rotationX: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(fnup, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(alex, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(cam, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                oldRotate = false
                groupRotate = false
                fnupPosition = false
                TweenMax.to(mirrorCube, 1, {three:{y:-400, opacity: 0 }, ease:Power2.easeInOut});
            }
            if (intersectFnup.length > 0) {

                  TweenMax.to(fnup, 1.5, {three:{scaleX: 2.5, scaleY: 2.5, x:0, y:0, z:0 }, ease:Power2.easeInOut});
                  TweenMax.to(old, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(alex, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(cam, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                oldRotate = false
                groupRotate = false
                fnupPosition = false
                TweenMax.to(mirrorCube, 1, {three:{y:-400, opacity: 0 }, ease:Power2.easeInOut});
            }
            if (intersectCam.length > 0) {
                  TweenMax.to(cam, 1.5, {three:{scaleX: 2.5, scaleY: 2.5, x:0, y:0, z:0 , rotationX: 0}, ease:Power2.easeInOut});
                  TweenMax.to(fnup, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(alex, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(old, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                oldRotate = false
                groupRotate = false
                fnupPosition = false
                TweenMax.to(mirrorCube, 1, {three:{y:-400, opacity: 0 }, ease:Power2.easeInOut});
            }
            if (intersectAlex.length > 0) {
                  TweenMax.to(alex, 1.5, {three:{scaleX: 2.5, scaleY: 2.5, x:0, y:0, z:0, rotationX: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(fnup, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(cam, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                  TweenMax.to(old, 1, {three:{y:-4000, opacity: 0 }, ease:Power2.easeInOut});
                oldRotate = false
                groupRotate = false
                fnupPosition = false
                TweenMax.to(mirrorCube, 1, {three:{y:-400, opacity: 0 }, ease:Power2.easeInOut});
            }

          }


      };

Solution

  • The information which is returned by THREE.Raycaster, contains the distance to the object and if mor than 1 objects are returned by the then the objects are sorted by its distance (e.g. intersections[0].distance). You can compare this distances to find the object with the closest distance.

    But I recommend to use a single intersectObject test, with all the objects. The reference to the closest object can be compared by == or === to a know object.
    Generate an array containing the objects fnup, old, cam, and alex, and compare the result of intersectObject to the objects:

    var objects = [fnup, old, cam, alex];
    var intersections = raycaster.intersectObjects(objects)
    
    if (intersections.length > 0) {
    
        if ( intersects[0].object == fnup ) {
            // [...]
        }
    
        if ( intersects[0].object == old ) {
            // [...]
        }
    
        if ( intersects[0].object == cam ) {
            // [...]
        }
    
        if ( intersects[0].object == alex ) {
            // [...]
        }
    }