As a newcomer to the Three.js ecosystem, I've been facing some challenges even when I come close to finding a solution. Recently, I managed to figure out how to highlight the face of a geometry on hover thanks to seanwasere's input on Three.js Discourse, accessible through this CodeSandbox example.
I am now wondering how I can implement this code snippet in React Three Fiber.
To provide context, here is the code snippet for reference:
import * as THREE from "/build/three.module.js";
import { OrbitControls } from "/jsm/controls/OrbitControls.js";
import Stats from "/jsm/libs/stats.module.js";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
100
);
camera.position.z = 2;
const light = new THREE.DirectionalLight();
light.position.set(2, 2, 10);
scene.add(light);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
const geometry = new THREE.BoxGeometry();
var materials = [
new THREE.MeshPhongMaterial({
color: 0x00ff00
}),
new THREE.MeshPhongMaterial({
color: 0x00ff00
}),
new THREE.MeshPhongMaterial({
color: 0x00ff00
}),
new THREE.MeshPhongMaterial({
color: 0x00ff00
}),
new THREE.MeshPhongMaterial({
color: 0x00ff00
}),
new THREE.MeshPhongMaterial({
color: 0x00ff00
})
];
const cube = new THREE.Mesh(geometry, materials);
scene.add(cube);
window.addEventListener(
"resize",
() => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
},
false
);
renderer.domElement.addEventListener("mousemove", onMouseMove, false);
const raycaster = new THREE.Raycaster();
let activeFaceIndex = 0;
function onMouseMove(event) {
raycaster.setFromCamera(
{
x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,
y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1
},
camera
);
const intersects = raycaster.intersectObject(cube, false);
if (intersects.length > 0) {
if (
intersects[0].face.materialIndex !== activeFaceIndex &&
activeFaceIndex !== -1
) {
materials[activeFaceIndex].color.setHex(0x00ff00);
}
activeFaceIndex = intersects[0].face.materialIndex;
materials[activeFaceIndex].color.setHex(0xff0000);
} else {
if (activeFaceIndex !== -1) {
materials[activeFaceIndex].color.setHex(0x00ff00);
}
activeFaceIndex = -1;
}
}
const stats = Stats();
document.body.appendChild(stats.dom);
var animate = function () {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
controls.update();
render();
stats.update();
};
function render() {
renderer.render(scene, camera);
}
animate();
For further insights on highlighting triangles on a face, you can check out Mugen87's explanation on Three.js Discourse, or explore it in action using this JSFiddle demo.