Changing color to the face of the cube when hover over occurs

I have been trying to change the colour of the face of the cube, when i hover over of the mouse occurs, on that given face.

I read many different examples but i could not make it. Here is the gist of the code:

var cubeGeometry = new THREE.BoxGeometry(20, 20, 20);
var cubeMaterial = new THREE.MeshBasicMaterial(
        {
            color: 0xffffff, //white
            vertexColors: THREE.FaceColors
        });

 cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
 cube.userData.originalColor = 0xffff00;

function onDocumentMouseMove(event)
    {
      
      event.preventDefault();

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


        // calculate objects intersecting the picking ray
        var intersects = raycaster.intersectObjects( scene.children );
 if ( intersects.length > 0 && intersects[ 0 ].object === cube && isClicked === false)
        {
             var index = Math.floor( intersects[0].faceIndex / 2 );
            cubeGeometry.faces[index].color.setHex(0xff000);
        }               
        else if (isClicked === false) //when its not clicked, and there are no intersects, return it to original color
        {
            cube.material.color.set( cube.userData.originalColor );
        }
    }
1 Like

It’s this code in particular that i think it is causing the issue.
I also tried
cube.faces[index].color.setHex(0xff000);

but it failed as well.

Try it with this code: https://jsfiddle.net/u63Lx2hf/

When changing face/vertex colors, it’s important to set Geometry.colorsNeedUpdate to true.

I added that line to my program, but still it doesn’t work.
Your version seems to color one of the two triangles of the face. What about the whole face?

 function onDocumentMouseMove(event)
    {
        cube.geometry.colorsNeedUpdate = true;
      event.preventDefault();

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

        var intersects = raycaster.intersectObjects( scene.children );



        if ( intersects.length > 0 && intersects[ 0 ].object === cube && isClicked === false)
        {
             var index = Math.floor( intersects[0].faceIndex / 2 );
            cubeGeometry.faces[index].color.setHex(0xff000);
        }               
        else if (isClicked === false) /
        {
            cube.material.color.set( cube.userData.originalColor );
        }
    }

In three.js, a face is a triangle. There are not faces with four or more vertices.

So you can only solve this issue by defining which faces belong logically together. This has to be done on app level.

If you only have to work with cubes, you can assign a material for each side of the cube and then just change the materials color.

I tried what you said but i didn’t work.

I succesfully managed to place different materials on each side of the cube.

I tried different things but nothing came to the desired effect.

This is one approach:

 if ( intersects.length > 0 && intersects[ 0 ].object === cube && isClicked === false)
    {
        const intersection = intersects[0];
        const faceIndex = intersection.faceIndex;
        cube.geometry.faces[ faceIndex ].color.set( Math.random() * 0xff0000 );
        cube.geometry.colorsNeedUpdate = true;
    
        }               
        else if (isClicked === false)
        {
            cube.material.color.set( cube.userData.originalColor );
        }
    }

And this is another:

 if ( intersects.length > 0 && intersects[ 0 ].object === cube && isClicked === false)
  {
            cube.geometry.colorsNeedUpdate = true;
            for ( var i = 0; i < cube.faces.length; i += 2 )
            {
                var faceColor = Math.random() * 0xff0000;
                cube.faces[i].color.setHex(faceColor);
                cube.faces[i+1].color.setHex(faceColor);
            }
           
   
  }               
        else if (isClicked === false)
        {
            cube.material.color.set( cube.userData.originalColor );
        }
    }

No approach worked however.

What about this?

2 Likes

So dope! Do you have a version of it with React Three Fiber? I’ve turned this into a question on Stack Overflow as well.

I wrote that sandbox 3 years ago? Time goes fast

Here is something quick in R3F

2 Likes

Dang! That’s cool, Sean! Thanks for the answer!

If you’d like, place it in a Stack Overflow answer as well, so I can give you the points!

1 Like