Selecting faces with Raycaster in ThreeJS with STL Loader

I am currently working on a .stl viewer using Three.js. The goal is select and calculate certain areas.
For this area calculation I need to be able to select (e.g. change the color) faces.

I have found something similar, but from what I have seen in my own research this only seems to be working with ready made meshes (like the cube in the example).

I am looking to implement this example in my own code.

It is evident that something like this has been done before, but I just can’t seem to implement any kind of working way in my own code:

My current code has a fully functional .stl loader and viewer. The raycaster is there, but doesn’t seem to be working properly so I have commented it out for the moment. Mugen87, thank you for the fix!

You can download my code and an example .stl file from github. Which only requires a Live Server environment which can easily be ran using VSCode (see readme).

My current code:

<!DOCTYPE html>
<html lang="en">

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3d viewer tjalle</title>
    <link rel="stylesheet" type="text/css" href="../style/render.css">

    <script src=""></script>
    <script src=""></script>
    <script src=""></script>

        function init() {
            var raycaster = new THREE.Raycaster();
            var mouse = new THREE.Vector2();
            document.addEventListener( 'mousemove', onMouseMove, false );

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

            // Setup some basic stuff
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0xdddddd);

            // Setup Camera 
            camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 5000);

            // Setup renerer and add to page
            renderer = new THREE.WebGLRenderer({
                antialias: true
            renderer.setSize(window.innerWidth, window.innerHeight);


            window.addEventListener('resize', onWindowResize, false);

            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;

                renderer.setSize(window.innerWidth, window.innerHeight);


            // Setup Camera Position
            camera.rotation.y = 45 / 180 * Math.PI;
            camera.position.x = 800;
            camera.position.y = 100;
            camera.position.z = 1000;

            // Add Camera Control through orbit.js
            let controls = new THREE.OrbitControls(camera, renderer.domElement);

            // Add some basic ambient lighting (Does light all parts equally and does not cast shadows)
            hlight = new THREE.AmbientLight(0xffffff, 5.3);

            //Add some point lights to simulate real lights
            light = new THREE.PointLight(0xffffff, 1, 10000);
            light.position.set(0, 300, 500);

            // Animation Script
            function animate() {
                raycaster.setFromCamera(mouse, camera);
                // calculate objects intersecting the picking ray
                var intersects = raycaster.intersectObjects(scene.children);
                for (var i = 0; i < intersects.length; i++) {

                renderer.render(scene, camera);

            // Setup GLTF Loader and load in car
            let loader = new THREE.STLLoader();
            loader.load('../converter/output/output.stl', function (geometry) {

                // console.log(gltf);
                var material = new THREE.MeshLambertMaterial({
                    color: 0x1313,
                    wireframe: false
                var mesh = new THREE.Mesh(geometry, material);
                mesh.castShadow = true;
                mesh.receiveShadow = true;
                mesh.position.set(0, 0, 0);

                renderer.render(scene, camera)
                console.log("SCene: ", )


        // Call method for starting init


  1. The example you’ve shown selects faces, not vertices. Do you mean to select triangles or points that build the triangles?
  2. If you’d like to select and interact with vertices, I don’t think you can use Raycaster directly on them. What you can do is use a point cloud created from a geometry.
    You can see an example here (source code; ignore the shaders etc, only casting geometry to points and raycasting onto them is important in this case.)

You can find a few more examples of raycasting on points here ->

You are right, I am trying to select triangles, so faces. Will edit this accordingly. Also the raycaster is now working, also has been posted in the edit.