How to disable clicking through the mesh

Hello, everyone. I am trying to a simple app where you can highlight one of the three floors.


The problem is if I click on the place where floors align, all of the meshes gets highlighted
image

I image there should be a simple way to disable clicking through the mesh.

import React, { useRef, useState, Suspense } from "react";
import { Canvas, useFrame, useLoader, useThree, extend } from "react-three-fiber";
import { softShadows } from "drei";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import "./App.scss";

extend({ OrbitControls });

softShadows();

const Floor = ({ position }) => {
  const [colors, setColors] = useState(false);
  const changeColor = () => {
    let currentColors = colors;
    setColors(!currentColors);
  };

  const { nodes } = useLoader(GLTFLoader, "./models/floor01.glb");
  return (
    <mesh geometry={nodes.floor1_1.geometry} onClick={() => changeColor()} rotation={[1.5, 0, 0]} position={position}>
      <meshStandardMaterial attach="material" color={colors ? "yellow" : "white"} />
    </mesh>
  );
};

const CameraControls = () => {
  const {
    camera,
    gl: { domElement }
  } = useThree();
  const controls = useRef();
  useFrame((state) => controls.current.update());
  return <orbitControls ref={controls} args={[camera, domElement]} minDistance={150} />;
};

const App = () => {
  return (
    <>
      <Canvas colorManagement shadowMap camera={{ position: [-5, 2, 10], fov: 60 }}>
        <CameraControls />
        <ambientLight intensity={0.3} />
        <pointLight position={[-10, 0, -20]} intensity={0.5} />
        <group>
          <Suspense fallback={null}>
            <Floor position={[0, 10, 0]} />
            <Floor position={[0, -10, 0]} />
            <Floor position={[0, 0, 0]} />
          </Suspense>
        </group>
      </Canvas>
    </>
  );
};

Its really hard to read react code to me, but in general you want to have a Raycaster that fires a invisible ray beam from your mouse into the scene. The ray will hit objects and store the intersections in a array, sorted from nearest to farthest. For that to work, each of the floors have to be its own mesh/obj. Then you just get the first element of the interesection array

1 Like

It’s probably due to the click event propagating, I had the same problem recently. Try using the stopPropagation method on the event and it should solve it:

onClick={(ev) => {
ev.stopPropagation();
changeColor();
}

Let me know if it works.

2 Likes