Eliminating the interior surfaces using Three.js

Utilizing three.js, I am combining multiple cubes to form various block shapes using the THREE.GeometryUtils.merge function. My goal is to achieve transparency for these block shapes; however, this currently results in a visible display of multiple individual cubes stuck together.

How can I create transparent merged cubes without rendering the inner edges? (Is there a way to eliminate the internal faces?)

Below is my code snippet for merging the cubes:

geometry = new THREE.CubeGeometry(STEP_SIZE, STEP_SIZE, STEP_SIZE);
for (i = 0; i < shape.length; i++) {
    tmpGeometry =  new THREE.Mesh(new THREE.CubeGeometry(STEP_SIZE, STEP_SIZE, STEP_SIZE));
    tmpGeometry.position.x = STEP_SIZE * shape[i].x;
    tmpGeometry.position.y = STEP_SIZE * shape[i].y;
    THREE.GeometryUtils.merge(geometry, tmpGeometry);
}

block = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: 0x0000ff, opacity: 0.5, transparent: true }));

Answer №1

Through some trial and error, I was able to achieve the desired result. Hopefully, this method will benefit others as well.

I meticulously examine each face of the block and perform a raycast on the block itself using the centroid of the face and its inverted normal (pointing inward). If there is an intersection with another face of the block, it indicates that the face is internal, allowing us to proceed with its removal.

// The block variable represents a Three.Mesh object
function removeInternalFaces(block) {
    var geometry = block.geometry;
    var face;
    var toDelete = [];
    var blockRaycaster = new THREE.Raycaster();

    // Iterate through each face, casting rays from their centroids (with negated normals)
    // Any intersected face is considered an inner face
    for (i = 0; i < geometry.faces.length; i++) {
        face = geometry.faces[i];
        if (face) {
            normal = face.normal.clone();
            normal.negate();
            blockRaycaster.set(face.centroid, normal);
            intersects = blockRaycaster.intersectObject(block);
            for (j = 0; j < intersects.length; j++) {
                toDelete.push(intersects[j].faceIndex);
            }
        }
    }

    // Delete the identified faces
    for (i = 0; i < toDelete.length; i++) {
        delete geometry.faces[toDelete[i]];
    }
    geometry.faces = geometry.faces.filter( function(v) { return v; });
    geometry.elementsNeedUpdate = true; // Update the faces
}

Answer №2

To initialize each face of a cube's material separately, you can individually set the opacity of the inner faces to 0. The following code demonstrates how to achieve this:

var materialArray = [];

    // Face 1
    materialArray.push(new THREE.MeshLambertMaterial({
        opacity: 0,
        color: 0x0000FF,
        transparent: true
    }));
    
    // Face 2
    materialArray.push(new THREE.MeshLambertMaterial({
        opacity: 0,
        color: 0x0000FF,
        transparent: true
    }));

    // Faces 3, 4, 5, 6
    for (var i = 0; i < 4; i++) {
        materialArray.push(new THREE.MeshLambertMaterial({
            opacity: 0.5,
            color: 0x0000FF,
            transparent: true
        }));
    }

    var CubeMat = new THREE.MeshFaceMaterial(materialArray);

You can then pass this material array to your cube mesh like so:

block = new THREE.Mesh(geometry, CubeMat);

For a demonstration, you can check out this JsFiddle link.

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

How can the onclick attribute be modified in an HTML document?

I am looking to update the data-pro-bar-percent attribute of a progress bar from 80 to 100 when a specific link is clicked. The change in attribute needs to be as follows: data-pro-bar-percent="80" --> data-pro-bar-percent="100" This is the current HT ...

Vue, list reordering acts strangely when selecting the displayed checkbox

I am facing a perplexing issue that has me stumped. Despite my attempts to replicate the error, the code below seems to be functioning perfectly! Here is what is expected to occur: <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.j ...

Load a script in a specific div using React

Can anyone assist me with loading a script onto a specific component in my React application? Here is the script that needs to be loaded at the bottom-most div within my component: <div id="rexxxx"></div> <script> new carouselI ...

The performance of my SVG Filter is dismal

Here is the SVG filter I am using: <svg style="visibility: hidden; height: 0; width: 0;"> <filter id="rgbShift"> <feOffset in="SourceGraphic" dx="1" dy="-1" result="text1" /> <feFlood flood-color="#FF0000" result=" ...

Guide on creating windows, openings, or cutting shapes in three.js

I'm new to working with three.js and I have a project where I need to create a "room" with doors and windows. It seems like a simple task, but all the answers I've found so far are not up-to-date. Similar questions can be found here: - subtra ...

Is there a way to disregard the data returned from previous AJAX calls?

I've been wondering about a strategy for managing delayed AJAX data returns in a scenario where newer calls should take precedence over earlier ones. For instance, if a first data fetch initiated at 12:01:33 is delayed and comes back at 12:01;39, whil ...

Renaming errors within a project with a complex nested structure using npm

I am encountering an issue in my NodeJS project which consists of nested subprojects with their own package.json files. Whenever I make changes to dependencies in the subprojects, I encounter errors similar to the one below: npm ERR! code ENOENT npm ERR! ...

What is the reason for the unusual incrementing of the index in JavaScript?

When running this code snippet, the first console log correctly shows 0. However, the second console log displays 1. Why is the index being incremented before the loop has ended? for (var i = 0; i < this.offlineTimeSlots.length; i++) { con ...

Hermes js engine encounters a TypeError when attempting to access the property '__expo_module_name__' of an undefined value

After updating my expo and react native app to the latest version, I encountered a problem that I couldn't find a solution for despite searching on Google. Link to image ...

Guide on assigning JSON response values to TypeScript variables in Angular 4

I'm just starting with Angular 4 and I'm attempting to retrieve a JSON value using http.post. The response I'm receiving is: {"status":"SUCCESS"} component onSubmit(value: any) { console.log("POST"); let url = `${this.posts_Url}`; t ...

Disable the ng2-tooltip-directive tooltip when the mouse is moved

Is there a way to hide the tooltip when the mouse enters? How can I achieve this? <div (mousemove)="closeTooltip()" [tooltip]="TooltipComponent" content-type="template" show-delay="500" placement= ...

How can I import icons or JSX elements dynamically using a string?

Currently, I am developing an icon selector feature. Once a user selects an icon, the selector returns it as a string (e.g., AirBalloon). To display this chosen icon on my webpage, I need to import it using the Tabler Icons React package from https://www.n ...

Blender Three.JS integration plugin experiencing technical issues

I am encountering difficulties installing the Three.js plugin for Blender. Despite creating the directory io_mesh_threejs in /usr/share/Blender ... /addon and copying the 3 .py files into it, the plugin does not show up in user preferences. I have tried us ...

Issues with rendering AngularJS onto an HTML page are currently being experienced

I was attempting to learn AngularJs in order to improve my front-end development skills, but unfortunately I ran into some issues. Despite following the video tutorials on their site step by step, I couldn't get it to render correctly. Here's the ...

Having trouble getting jquery to filter json data based on the selected option

I have developed a code using jQuery to filter the options in a drop-down list based on the selection made. The data is in JSON format and is fetched from a database. However, when I select an option from the drop-down list, the code does not enter the loo ...

Check through an array for any updates whenever a function is called and my react state is altered

I am currently working on a project related to playlists. My goal is to display the image attached to each song whenever that song is clicked from the playlist. Here is the code I have so far... const Component = () => { const value = useContext(DataC ...

What is preventing the AJAX from saving the data in the database?

PIC I want to ensure that when I hit enter, the input data is successfully saved to the database. The Controller: public function saveData(Request $request){ $data = Data::create([ 'user' => Auth::user()->id, 'rec ...

AngularJS radio buttons are interactive HTML elements that allow users

I've been looking for a solution to bind my radio inputs to a model in a simple and clean way, but I haven't found one that works for me yet. In my HTML, I have: <input ng-model="searchByRma" type="radio" name="search-type"> <input ng-m ...

How to dynamically insert a new row below a specific row with a sliding animation in jQuery

My task is to create a tree-like table structure where clicking on a specific row will reveal and add new rows below it. Specifically, I am designing the Category and SubCategory structure. Currently, I can append rows after a specified row but am struggl ...

The MVC 5 view is unable to display an HTML image when adding it within an appended div

Currently, I am working with ASP.net MVC5 at a novice level. I'm faced with the challenge of creating a div that displays an image using a JavaScript function. Here is the code snippet I have: function showLoadingImage() { $('#submit_Em ...