Pass events to CSS3D elements when in Pointerlock

Hello everyone, pretty new here. I’m attempting to do something similar to Doom3 (still) incredible interactive screens in three.js, leveraging CSS3D elements and firsperson-controls (well, PointerLockControls actually).

I have a somewhat working demo where I’m using the raycaster to check that I am hovering on the CSS3D element (and changing some of its values).

Code: https://glitch.com/edit/#!/adorable-buttery-fiction?path=index.html:28:24
Result: https://adorable-buttery-fiction.glitch.me/

But it seems like click events are not passed to the CSS3D element. I presume this has something to do with PointerLockControls limitations but maybe there is a way to send events to the CSS3D element and I’m just not googling the right thing. Is the thing I’m trying to do even possible in First person mode? Or it’s only available without PointerLock in the mix?

Thanks in advance.

When I remember correctly there are some troubles with mouse events and pointer lock. Check out this discussion for more information.

Um, it looks like you are not doing this right now. You perform a ray intersection test with the entire scene which means the button status changes even if you look at the floor. Try to raycast only against the plane mesh.

IMO, using CSS/HTML for this particular use case is the wrong choice. The controls of the crane in Doom 3 from your video represents a diegetic user interface. This terminology in context of game development is explained in short here. In any event, you normally don’t use CSS/HTML to implement diegetic UI’s but WebGL. Simply because transformed HTML elements do not blend well into 3D environments due to missing depth information. You can already see this in your demo. Check out how the button disappears “behind” the yellow floor.


Hence, I suggest you just map a texture onto your already existing plane mesh.

Thanks for the answer and the tips, @Mugen87!

Um, it looks like you are not doing this right now. You perform a ray intersection test with the entire scene which means the button status changes even if you look at the floor. Try to raycast only against the plane mesh.

There are two intersections in the code. But this one:

        var vector = new THREE.Vector3(0, 0, -1);
            vector = camera.localToWorld(vector);
          vector.sub(camera.position);
        var ray = new THREE.Raycaster(
          camera.position,
          vector
        );

        var cssIntersects = ray.intersectObjects(scene.children);
        if (cssIntersects.length > 0) {
          virtualButton.textContent = "I am a button hovered  ";
        } else {
          virtualButton.textContent = "I am a button";
        }
      }

does work for me. It correctly changes the text of the HTML element when the 0, 0 overlaps with the virtualButton element.

The idea of using CSS/HTML for this scenario would be to speed up development. It’s much easier (for me) to implement complex interactions with CSS/HTML than with WebGL. And I’d be okay with the tradeoffs :slight_smile: