Exploring the challenging surfaces of a mesh through raycasting in Three.js

I successfully built a box using three.js

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 100, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(5, 5, 10);

var geo = new THREE.BoxGeometry(5,2,5);

var mat = new THREE.MeshBasicMaterial({color:0xff0ff0, wireframe:false, vertexColors: THREE.FaceColors});

var mesh = new THREE.Mesh( geo, mat);
scene.add(mesh);

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.render(scene, camera);

Now, I want to be able to change the color of the entire face of the cube when hovered over by the mouse. Here is the function I created for that purpose:

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

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

    raycaster.setFromCamera( mouse, camera );   

    var intersects = raycaster.intersectObject( mesh);

    for ( var i = 0; i < intersects.length; i++ ) {
        intersects[ i ].face.color.setHex( 0xDDC2A3);
        mesh.geometry.colorsNeedUpdate = true;
    }

    renderer.render( scene, camera );
}

window.addEventListener( 'mousemove', onMouseMove, false );

Although the function is working, it currently only changes the color of half of the face of the cube. I am looking to target the complete face or hard-face, specifically those made up of Face3+Face3. Any suggestions on how I can achieve this?

Answer №1

This code snippet is tailored for use with geometries that are pre-built and not buffered, such as BoxGeometry, SphereGeometry, CircleGeometry, and others.

var intersects = raycaster.intersectObject( mesh);

for ( var i = 0; i < intersects.length; i++ ) {

    var faceIndex = intersects[i].faceIndex;

    if(faceIndex == 0 || (faceIndex % 2) == 0) {
        intersects[i].object.geometry.faces[faceIndex].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.faces[faceIndex + 1].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.colorsNeedUpdate = true;

    }else {
        intersects[i].object.geometry.faces[faceIndex].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.faces[faceIndex - 1].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.colorsNeedUpdate = true;
    }

}

renderer.render(scene, camera);

Answer №2

For the scenario you provided, where a default box-geometry is being used with 2 faces per side arranged in a specific direction, you can easily pair each set of two faces together by following this approach:

var facesPerSide = 2;
for ( var i = 0; i < intersects.length; i++ ) {
    var side = Math.floor(intersects[i].faceIndex/facesPerSide);
    for(var j=0;j<facesPerSide;j++) {
        mesh.geometry.faces[side*facesPerSide+j].color.setHex(0xDDC2A3);
    }
    mesh.geometry.colorsNeedUpdate = true;
}

It's worth noting that the process may become more intricate if a variable number of segments are used for width/height/depth, or if non-platonic solid geometry is employed.

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

Exploring Vue Slots: A guide to parsing and rendering slot components

Currently facing a challenge while developing a web page using Vue, specifically with parsing and rendering the child components inside the <slot>. I need to extract the slot content, convert it into an array of components, and display these compo ...

AngularJS animation fails to activate

I've been working on a simple AngularJS application and I'm trying to add animations between my views. However, for some reason, the animation is not triggering despite following the tutorial on the AngularJS website. There are no errors in the c ...

Opening a Bootstrap Modal in React without relying on npm react-bootstrap

I've been trying to create a Modal in React.js using Bootstrap5, but I'm unable to use npm react-bootstrap for various reasons. I attempted an approach where I utilized state to set Modal classes with a button, which worked well with my NavBar, b ...

Encountered unexpected character error while parsing JSON data

I am encountering the following error message: JSON.parse: unexpected character when I execute this code in firebug: JSON.parse({"balance":0,"count":0,"time":1323973673061,"firstname":"howard","userId":5383,"localid":1,"freeExpiration":0,"status":fals ...

Steer clear of receiving null values from asynchronous requests running in the background

When a user logs in, I have a request that retrieves a large dataset which takes around 15 seconds to return. My goal is to make this request upon login so that when the user navigates to the page where this data is loaded, they can either see it instantly ...

The delete function is not functioning

I need help with implementing a custom Angular directive that includes a delete button to remove itself. When I click the button removeMe, it is not deleting an item from the array. Any suggestions on what might be causing this issue? HTML: <button t ...

Passing events from a grandchild component up to its grandparent component in VueJS 2.0

Vue.js 2.0 appears to have a limitation where events cannot be emitted directly from a grand child component to its grand parent. Vue.component('parent', { template: '<div>I am the parent - {{ action }} <child @eventtriggered="pe ...

Set a timeout for a single asynchronous request

Is there a way to implement a setTimeout for only one asynchronous call? I need to set a timeout before calling the GetData function from the dataservice, but it should be specific to only one asynchronous call. Any suggestions? Thank you. #html code < ...

Update the span's content according to the user's input

Is it possible to update the value of a span to match that of an input field in HTML? HTML: <p style='font-size:150%'> Hey friend, I am <span id='name_display'>Anonymous</span>, I'd like to invite you to..... &l ...

Experiencing the "Module not found" issue while incorporating SCSS into React applications

I attempted to apply a SCSS style to my "Logo.js" component, but I am still unable to resolve the error that keeps popping up: ERROR in ./src/components/Logo/Logo.js 5:0-19 Module not found: Error: Can't locate 'logo.scss' in '/Users/a ...

Is it possible to alter the name of a slot before displaying the element in the shadowDOM, depending on the slot utilized in the DOM?

In my project, I am working on implementing different features for both desktop and mobile devices. Some of these features can be replaced by slots. My goal is to have a slot that can be either replaced by a desktop slot called poster-foreground, or a mobi ...

What is the best way to set up a property in a service that will be used by multiple components?

Here is an example of how my service is structured: export class UserService { constructor() {} coords: Coordinates; getPosition() { navigator.geolocation.getCurrentPosition(position => { this.coords = [position.coords.latitude, posit ...

What is the best way to iterate over each character in a string and trigger a function in JavaScript?

I am currently working on a project to create a random password generator. The code responsible for generating the password is functioning correctly. However, I am facing an issue with converting the characters of the password into phonetic equivalents. I ...

methods for converting an array to JSON using javascript

Our team is currently working on developing a PhoneGap application. We are in the process of extracting data from a CSV file and storing it into a SQLite database using the File API in PhoneGap. function readDataUrl(file) { var reader = new FileReade ...

The implementation of texture in three.js appears to be error-free, yet it is still

Hey everyone, I'm diving into the world of three.js and working on a school project. The task at hand involves adding a texture to a cube, but unfortunately, all I see is a black screen with no console errors to guide me. I've tried everything I ...

Achieving compatibility with pseudo elements :before/:after in Internet Explorer 7

I've been attempting to make these functionalities compatible with IE 7, but I'm encountering difficulties. I've downloaded and included the jQuery plugin for it in the header as shown below: <!--[if lte IE 7]> <script type="text/j ...

Retrieving the chosen option from a dropdown menu using AngularJS

<tr (click)="onRowClick(myDropDownList.value)"> <td> <select #myDropDownList (click)="$event.stopPropagation()" (change)="onChange($event.target.value)"> <option *ngFor="let n of numbers" [value]="n">{{n}}</option> </se ...

Syntax highlighting in custom blocks with VueJS

Vue single file components allow for the creation of custom blocks (besides the commonly used script, template, and style). For more information, you can refer to the official documentation here: . However, I am struggling to enable syntax highlighting w ...

Class for making elements draggable using jQuery UI

Is it possible to use jQueryui's draggable/droppable combo and add a class to the dragged item when dropped into a specific container, rather than adding a class to the container itself? I've tried adding a class to the container, but that is not ...

Incorporating React's dynamic DIV layout algorithm to generate a nested box view design

My goal is to showcase a data model representation on a webpage, depicting objects, attributes, and child objects in a parent-child hierarchy. I had the idea of developing a versatile React component that can store a single data object while also allowing ...