Exploring Faces with React Three Fiber through Hovering

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.

Answer №1

Check out this functional R3F adaptation inspired by the CodeSandbox iteration.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for altering date format in AngularJS version 1.x

Is there a way to transform the date format from 1-Jan-2018 to 1-1-2018 using angularjs? One potential method is by utilizing HTML Template Binding as shown below: {{ date_expression | date : format : timezone}} ...

What is the best way to trigger a parent function from a Bootstrap modal within a Vue.js component

In my vue.js component, I am calling a Bootstrap modal within a function. I want to call another function after the modal is closed, but I am facing issues with the scope. this.myFunction() // This works here $('#app-modal-warning').on('hi ...

Utilizing the localStorage feature for multiple users

I rely on localStorage for handling data input and output on HTML forms. I'm curious to know if this method is "multiuser proof" - meaning, will one user be separate from another when using the form concurrently? My understanding is that since localSt ...

increase the current date by 12 months

Hello there! I am looking to increase my current date by 12 months and decrease it by 1 day. For Example : valStartDate :2018-01-20 expected_date:2019-01-19 Unfortunately, I encountered an error while trying the following code: "getFullYear() not a ...

Leveraging AngularJS with Angular Material or JQuery to showcase a custom window design

Seeking solutions on how to create a button like the FAB speed dial from angular material, or another option that displays a small window next to the clicked button. The small window should contain a text area and a button. Preferably looking to implement ...

Ways to accomplish a task prior to form submission without relying on preventDefault

How can I perform an action before form submission without using e.preventDefault();? I am faced with a situation where I have two form buttons and need to set a hidden field value before submitting the form. In my Symfony2 framework, when I submit the fo ...

Using Angular to create a dynamic form with looping inputs that reactively responds to user

I need to implement reactive form validation for a form that has dynamic inputs created through looping data: This is what my form builder setup would be like : constructor(private formBuilder: FormBuilder) { this.userForm = this.formBuilder.group({ ...

Securely store files by encrypting them with Node.js before saving to the disk

At the moment, I am making use of the multer library to store files on the File system. This particular application is built using Node and Express. I currently have a process in place where I save the file on the server first and then encrypt it. After e ...

TypeScript - Issue with generic function's return type

There exists a feature in typescript known as ReturnType<TFunction> that enables one to deduce the return type of a specific function, like this function arrayOf(item: string): string[] { return [item] } Nevertheless, I am encountering difficulti ...

Is there a way to transform text input into a dropdown menu that dynamically alters the rows of a table?

Currently, I am working on creating a drop-down menu selection that will dynamically change the table rows based on user input. At the moment, users can enter their input into a text field to see changes in the table rows. However, I would like to impleme ...

Launching a pre-built React application

I'm facing an issue while attempting to run a pre-existing React App on my Mac locally. I have all the source files and node.js installed on my machine. Upon running npm install, I encountered a massive list of deprecations and npm ERRors that surpas ...

Executing functions across modules in node.js

I need assistance with two of my modules: var client = require('./handlers/client.js'); var server = require('./handlers/server.js'); server.createClient() The client module: var client = function(){ console.log("New client"); ...

Dealing with promises in AngularJS within the ui-router configuration

Below is a snippet of my $stateProvider code: $stateProvider .state("home", { url: "/", template: "<employee-info-component user='$resolve.user'></employee-info-component>", resolve: { user: function(indiv ...

Executing a completion function with node-cron: A comprehensive guide

My use of node-cron involves triggering a function on job execution (onTick) and another function when the job ends (onComplete). However, I'm facing unexpected behavior. If the job does run, then onComplete never executes: var CronJob = require(&ap ...

Retrieve the input values and arrange them neatly in a table

I am encountering an issue with extracting values from a table. My goal is to retrieve all the input values from the table, but I am finding it challenging because the number of rows in the table can vary. <table id="receiptTable" class="table table-bo ...

Vue.js: axios unexpectedly running synchronously across multiple components instead of asynchronously

Upon initializing my component, I am attempting to load ajax data. However, I have noticed that this causes other items loaded via ajax in the created() method to load synchronously rather than asynchronously. When this specific ajax request is triggered, ...

Employ the Google Charting library for creating a GeoChart that is currently not displaying

Hello everyone. I'm having a bit of an issue with my web page development. I've been trying to add a GeoChart, but no matter how many times I copy-paste the code from the Google developer's website, the map just won't show up. I must be ...

Tips for sending textarea data via AJAX with TinyMCE

Recently, I encountered an issue with submitting forms using the TinyMCE Jquery plugin. While regular input fields like text fields and select boxes submit just fine, there seems to be a glitch when it comes to submitting a textarea with TinyMCE. It requir ...

When a form is submitted in JQuery, it creates a fresh form on the

My current setup involves a JQuery script that sends user input to a PHP script within the same file. The PHP script processes this input and displays the results successfully. However, I have encountered a peculiar issue where upon submission, the JQuery ...

Issues with displaying calendar items on the React timeline are only resolved after pressing F12 or resizing the

I am encountering a problem while trying to plot the items array in the timeline calendar. Interestingly, the groups array is working fine. The items array also functions properly when values are provided manually. However, the items only render after pre ...