When extruding along the normal in Three.js, the resulting mesh rotates

When working with a PlaneGeometry that has only 2 faces (the red one in the image), I encountered an issue while trying to extrude one of them along its normal using a specific function:

function extrude( mesh, amount ) {

var geometry = mesh.geometry;

//Performing the operation on the first face only
for( var f = 0; f < geometry.faces.length -1; f++){

    var face = geometry.faces[ f ];
    var f_normal = face.normal;

    //Vertex used by the extrusion path//
    var vertex = geometry.vertices[ face.a ]; 

    //Creating the extrusion path
    var spline = new THREE.SplineCurve3( [
        new THREE.Vector3( vertex.x, vertex.y, vertex.z ),
        new THREE.Vector3( vertex.x + (f_normal.x * amount), vertex.y + (f_normal.y * amount), vertex.z + (f_normal.z * amount) )
        ] );

    //Gathering vertices
    var v1 = geometry.vertices[ face.a ];
    var v2 = geometry.vertices[ face.b ];
    var v3 = geometry.vertices[ face.c ];

    //Drawing the shape
    var shape = new THREE.Shape();

    shape.moveTo( v1.x, v1.y, v1.z );

    shape.lineTo( v2.x, v2.y, v2.z );

    shape.lineTo( v3.x, v3.y, v3.z );

    shape.lineTo( v1.x, v1.y, v1.z );

    //Extruding it

    var extrudeSettings = { amount: amount, extrudePath: spline, steps: 1, bevelEnabled: false };

    var extrudedGeo = new THREE.ExtrudeGeometry( shape, extrudeSettings );


    var material = new THREE.MeshPhongMaterial( {color: 0x00ff00, wireframe: true} );

    //Creating a new mesh
    var mesh = new THREE.Mesh( extrudedGeo, material);

    scene.add( mesh);


}

}

Although the extrusion occurs perfectly along its normal, the resulting mesh appears to be rotated. This happens even when switching the vertex used for the extrusion path from a to b or c. Why is this rotation occurring? How can I ensure that the new geometry/mesh aligns perfectly with the original face it was extruded from? https://i.sstatic.net/3Etzk.png

Answer №1

When you extrude a shape over a path, it has the freedom to spin along the path. This is necessary because if the shape is extruded over a spline curve, it must rotate to maintain a consistent shape.

Unfortunately, controlling or predicting the initial rotation is not easy.

If you want to prevent the shape from rotating, consider using extrude depth instead of extrude path:

var extrudeSettings = {
    bevelEnabled: false,
    steps: 1,
    amount: depth // depth or height for extrusion
};

var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var mesh = new THREE.Mesh( geometry, material );

Also, check out my related question on the difference between extrude depth and extrude path on stackoverflow here

UPDATE1:

I completely agree with your comment:

"this is one of the most basic modifiers in every 3d modelling software, thought it was simpler to replicate"

I wish it were more user-friendly, but that seems to be how it works in the current version of three.js. To extrude in a different direction, you can apply a shear matrix after performing the extrusion. You can find instructions on how to do this in response to another question I posted on this topic.

UPDATE2:

I also recall using the following technique:

Extrude a shape using a depth and then apply a transformation to half of the vertices (geometry.vertices) of the extruded result (essentially the upper plane of the geometry). Sometimes, this approach may be simpler than determining the correct shear matrix for the desired outcome.

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 come (23 == true) is incorrect but (!!23 == true) is correct? After all, there is === for exact comparisons

The question boils down to this: are both 23 and true truthy values? If so, shouldn't they be equal under the loose comparison operator ==? However, there is also the strict comparison operator === for cases where precise equality is required. UPDATE ...

Angular material table cell coloring

Here is my current setup: I have an array of objects like this: users : User []; average = 5; compareValue (value){ ...} And I am displaying a table as shown below: <table mat-table [dataSource]="users"> <ng-container matColumnDef= ...

Gradually introduce each element in sequence

I've written some code that works, but it's a bit messy with all the repeated lines. I tried using a loop to clean it up by replacing [0] with [i], however, the elements end up fading in simultaneously. Here is an example of my code on JSFIDDLE. ...

Using jQuery, you can easily insert a <span> tag around selected text and then save this modification permanently in a local HTML file

I have compiled notes in an HTML file stored on my local computer, with the intention of keeping it solely for personal use. For instance, I have a snippet like this: <p> this is an example text</p> My goal is to highlight the word "example" ...

Is it possible to improve object iteration to avoid the necessity of nesting a while loop within another while loop with identical conditions?

I'm currently exploring the idea of embedding a while loop with the conditions (qgLLInco = 1) within another identical while loop. The goal is to break out of the loop immediately instead of adding each qualifying item individually, as there will be ...

Errors occurred in Typescript and Next.js due to an unexpected token 'export'

I am currently working on developing an online board app using React, Next.js, and TypeScript as a project for my portfolio. This is my first time using TypeScript. However, I encountered an issue with importing roughjs into canvas.tsx. Below is the code ...

The feature to "Highlight text on the page" in React-pdf is currently malfunctioning

I am currently working on incorporating the pdf highlighting feature from React-pdf: import React, { useMemo, useState } from 'react'; // import { Document, Page } from 'react-pdf'; import { Document, Page } from 'react-pdf/dist ...

Ajax is able to fetch the URL without any issues, but the page is not being updated as expected. Instead,

I am currently working on implementing next/prev buttons using JavaScript, and have utilized a DynamicPage script for testing purposes. The only modification I made was to the beginning of the URL variable in pagenumber.js, although it essentially delivers ...

Which is Better: Lazy Loading, Combining and Minifying, or Using a CDN for Javascript in Angular

When is it advisable to utilize a CDN for loading a JavaScript file? Are there specific files that should be lazy loaded? Additionally, which scripts would benefit from being combined and minified? For instance: jquery + jquery plugins - Should thes ...

Utilizing ng-repeat to link model data in an Ionic application

In the Ionic 1.2 code I'm working with, my template.html looks like this: <form ng-submit="addToCart(products)"> <div ng-repeat="product in databaseProducts.products.details"> <input ng-model="products.value" type="number"& ...

What steps can I take to make a timestamp that is easy for users to understand

Currently delving into the world of jQuery, I am working on a project called "twittler" that utilizes both jQuery and moment.js libraries. Despite my best efforts, the time generated for each twit always shows up as "a few seconds ago." Can anyone spot th ...

Can we retrieve the CSS of an element?

Using Selenium's webdriverJS, I have automated tasks on an HTML5 page. To incorporate a CSS selector into a function, I had to rely on XPath for selecting elements: var complexXpath = "//*/div/a"; /* This is just an example */ var element = mydri ...

Linking a variable in typescript to a translation service

I am attempting to bind a TypeScript variable to the translate service in a similar way as binding in HTML markup, which is functioning correctly. Here's what I have attempted so far: ngOnInit() { this.customTranslateService.get("mainLayout.user ...

Transferring contacts from Gmail, Yahoo, Hotmail, Facebook, and Twitter

Looking to streamline the process of importing contacts from various platforms like gmail, yahoo, hotmail, and facebook using Google API's. Are there any libraries available that can handle this task or should I dive into writing code for all the diff ...

Chrome on IOS: Experiencing screen freezing while scrolling

1) I'm working with Material UI in React JS. I have added a simple scrollable code, but when I reach the bottom of the screen/scroll, it freezes. 2) I also tried it with a simple HTML page and it worked correctly. <div style={{ ...

Upon refreshing the browser page, AngularJS fails to redirect to the default page as expected

In my AngularJS route configuration, I have set up the following paths: moduleA.config(function($routeProvider){ $routeProvider. when('/A',{templateUrl:'A.jsp'}). when('/B',{templateUrl:'B.jsp'}). wh ...

Guide on incorporating an Ajax spinner to a Slideshow

I am in need of assistance with creating a manual slideshow that includes an ajax loader image. The goal is to display the loader image every time I click on the Previous or Next buttons, until the Test 1, Test 2, and Test 3 texts are fully loaded. Any sug ...

Is there a way to manage form submission while inside an ajax callback function?

Initially, I had the return true/false in my ajax callback function. However, I realized that it might not be in the correct context to be called. Therefore, I made some revisions to my function as shown below. Despite these changes, it still doesn't ...

Guide to converting Bootstrap class col-md-10 to col-md-12 within a div using CSS

For my project, I utilized a thumbnail section and a view section. To achieve this layout, I divided the parent div into two separate divs. The first div is col-md-3 (the thumbnail section) and the second div is col-md-9 (the view section). Now, I am looki ...

What is the best way to create a redirect link using the post method?

Does anyone know a simple way to create a link that redirects to a page with POST method of data using Jquery? I am looking for something similar to the code below (without actually redirecting to the page) <script language="javascript"> function ...