Rotating the face normal in ThreeJS, just not specifically on the floor

I am currently working on developing a house generator using a floorplan. The mesh generation process is running smoothly, but now I am faced with the task of flipping the normals on certain faces.

buildRoomMeshFromPoints(planeScalar, heightScalar){
    var pointsAsVector2 = []
    this.points.map(e => {
        pointsAsVector2.push(new THREE.Vector2(e.x * planeScalar, e.y * planeScalar))
    })
    var shape = new THREE.Shape();

    shape.moveTo(pointsAsVector2[0].x, pointsAsVector2[0].y)
    pointsAsVector2.shift()
    pointsAsVector2.forEach(e => shape.lineTo(e.x, e.y))
    
    const extrusionSettings = {
        steps: 2,
        depth: heightScalar,
        bevelEnabled: false
    };
    
    var roomGeometry = new THREE.ExtrudeGeometry( shape, extrusionSettings );
    var materialFront = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
    var materialSide = new THREE.MeshBasicMaterial( { color: 0xff8800 } );
    var materialArray = [ materialFront, materialSide ];
    var roomMaterial = new THREE.MeshFaceMaterial(materialArray);

    var room = new THREE.Mesh(roomGeometry, roomMaterial);
    room.position.set(0,0,0);
    room.rotation.set(THREE.MathUtils.degToRad(-90),0,0)
    return room;
}

This piece of code is responsible for creating the house structure based on a set of 2D points. In order to make the walls transparent, I need to adjust the normals of all walls and the roof.

My plan involves evaluating the angle between each face normal and an upward vector (THREE.Vector3(0,1,0)), and if the angle exceeds a certain threshold, I aim to flip it. However, I am unsure about how to achieve this at the moment :)

Any assistance would be greatly appreciated!

Warm regards, Pascal

Answer №1

To put it simply, "flipping" a normal vector involves reversing each of its components. For instance, if your normal vector n is a THREE.Vector3 object, then its negative counterpart would be n.multiplyScalar(-1). If the vector is represented as an array like [ x, y, z ], then flipping it means transforming it into [ -1 * x, -1 * y, -1 * z ].

However, merely flipping the normal vectors will not achieve all the desired results. In Three.js and many other engines, normals are distinct from the concept of the triangle's rendering side. So, just flipping the vectors will cause Three.js to keep rendering the front side of the triangles, resulting in darker faces due to light reflection issues.

For each triangle, you must (a) flip the normals of its vertices, and (b) either render the back side or reverse the facing direction of the triangle.

To display the back side of a triangle, you can adjust the .side property of your material to THREE.BackSide. However, this change might have implications that need attention throughout your codebase due to rendering backfaces.

A more effective solution involves altering the triangles themselves to face the opposite way.

ExtrudeGeometry generates BufferGeometry, storing vertex positions in a flat array within the .attributes.position.array property. By swapping elements in the array appropriately, you can modify the winding order of triangles, thereby changing Three.js's perception of the front side. This transformation changes ABC to ACB in terms of representation.

The following code snippet accomplishes this operation:

// Code snippet here

You can view a demonstration of this technique on CodePen here.

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

Encountering an error: Module missing after implementing state syntax

My browser console is showing the error message: Uncaught Error: Cannot find module "./components/search_bar" As I dive into learning ReactJS and attempt to create a basic component, this error pops up. It appears after using the state syntax within my ...

Say goodbye to the 'Access-Control-Allow-Origin' issue when using HMVC Codeigniter!

Upon loading the page, I encountered an error in my console that stated: A font from origin 'http://example.com' was blocked from loading due to Cross-Origin Resource Sharing policy. The requested resource does not have an 'Access-Contr ...

The show/hide jquery function is functioning perfectly on desktop devices, but issues arise on mobile devices where the divs overlap each other when using the show() method

I need a way to toggle input text boxes based on selection using a select box This is the HTML code snippet: <div class="row"> <div class="form-group"> <div class="col-sm-1 label2"> <label class="control-label ...

Retrieving the total count of data entries from the JSON server endpoint

Working on a practice application with the JSON server serving as the backend, I have a question. Is there a way to determine the total number of records at an endpoint without actually loading all the records? For example, if my db.json file contains da ...

Avoiding an event from spreading in Angular

I am working on a navigation setup that looks like this: <a (click)="onCustomParameters()"> <app-custom-start-card></app-custom-start-card> </a> When the user clicks on the app-custom-start-card, the onCustomParame ...

Developing applications in AngularJS that utilize a remote REST API for data retrieval

Is there a way to make a remote REST API call within an angular js application without enabling CORS on the server? Currently, my setup includes bower for dependency management, grunt for server and build task running, and angular js as the front-end fram ...

Exploring the file structure of the MEAN stack and unleashing the power of

Currently, I am immersing myself in learning the MEAN stack through a personal project. Initially, I utilized the yeoman/grunt/bower trio, but I found the file structure generated by the yeoman generators to be unsatisfactory. As a result, I have switched ...

The addEventListener feature in Bootstrap 5.2.3 seems to be malfunctioning

I have a sample page with a Bootstrap dialog being returned from the server. I want to display it inside a DIV. However, when clicked, I receive this error: Uncaught TypeError: myModal.addEventListener is not a function It points to this line of code: ...

What is the method to retrieve the ID name of an HTML tag based on its value?

Is there a way to determine the ID of an HTML tag based on its content? For example, if I have the following textboxes: I need to identify the id with the value "A2" So the expected result is id=option2 because its value is A2 <input type="text ...

Transform an asynchronous callback into an asynchronous generator format

I have the following function from a third-party package that I am unable to modify async function runTransaction(callback) { const client = await createClient(); try { await client.query("BEGIN"); await callback(client); } ...

What is the best way to add a style to the currently active link on a NavLink component using the mui styled() function

I have a custom NavLink component that I want to style with an ".active" class when it is active. However, I am not sure how to achieve this using the "styled()" function in MUI. Does anyone know how to accomplish this? Below is the code for my custom Nav ...

Bypassing the "Your connection is not private" error in NodeJS + Express with fetch() using Javascript

Presently, I have a setup with a NodeJS + ExpressJS client-side server that communicates with the back-end server via API calls. However, every time I make a call, I need to manually navigate to the URL of the API back-end server and click on Advanced -> ...

Utilizing a Meteor Method within a Promise Handler [Halting without Throwing an Error]

I've been working on integrating the Gumroad-API NPM package into my Meteor app, but I've run into some server-side issues. Specifically, when attempting to make a Meteor method call or insert data into a collection within a Promise callback. Be ...

Retrieve JSON object based on its unique identifier from a different JSON file

I am working with 2 API resources: and it returns JSON data like this: { "id": 771, "title": "Call to Alyce Herman - Engine Assembler", "assigned_with_person_id": 317, } provides ...

How to Use $scope within a Function in AngularJS

When a page is loaded, I run the following function: $scope.showTags = function(Id) { $scope.toggleSelectedBlocks = function selectB(block) { // There is a checkbox to be selected... } $scope.greetUser() { console.log("GREETIN ...

Troubleshooting Hover Problem with D3 Chord Example on Internet Explorer 11

I came across an interesting tutorial on how to create chord diagrams in D3, which I'm currently experimenting with. The tutorial can be found at One example that caught my attention is about hair color preferences. When you hover over a group on the ...

Switch Button Hyperlink in HTML/CSS

I have the following code: document.addEventListener("DOMContentLoaded", function(event) { (function() { requestAnimationFrame(function() { var banner; banner = document.querySelector('.exponea-banner3'); banner.classList ...

When submitting the form for the zip code input, use an XMLHttpRequest to input the zip code and retrieve the corresponding city

I'm currently working on a project that involves inputting zip codes and retrieving the corresponding city information from . In the future, I plan to parse this data and store it as variables in my program while potentially using longitude/latitude f ...

Retrieving input field values in JS/Ajax without needing to refresh the page or click a button

Currently, I have set up a JavaScript function that submits data without refreshing the page or requiring a button click. The input field is located within tab #2 and triggers the JS function when the user stops typing. However, the issue arises when the ...

The customized Vaadin component with a tag is missing from the MainView layout

I am attempting to integrate my custom vis component into the MainView VerticalLayout. However, it is appearing above the layout and the layout itself contains an empty component tag. Custom component code In this section, I have labeled my component as " ...