Extrude a face in Three.js along its respective normal vector

My goal is to extrude faces from a THREE.Geometry object, and my step-by-step approach involves: - Specifying the faces to be extruded - Extracting vertices on the outer edges - Creating a THREE.Shape with these vertices - Extruding the shape using THREE.ExtrudeGeometry (I'm using a customized version that doesn't generate front faces, as I handle cloning them to maintain the original topology).

Initially, the extrusion works well when dealing with a CircleGeometry on an XY plane and extruding in the Z direction. https://i.sstatic.net/p0Ipw.png

However, when I rotate the circle slightly, the extrusion seems to follow the Z World Axes instead of its local orientation. https://i.sstatic.net/zmGmJ.png

I am looking for a solution to this issue. Below is the function I have been using:

function faceExtrude( geometry, face_group, amount ) {

if ( geometry.type === "undefined" ) {

    console.log( "faceextrude error" );

    return;

}

// Conversion of face_group to vertex_group
var vertex_group = [];

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

        // Retrieve vertices ID
        var f = face_group[i];
        var a = f.a;
        var b = f.b;
        var c = f.c;

        // Cloning vertices
        var v1 = geometry.vertices[a].clone();
        var v2 = geometry.vertices[b].clone();
        var v3 = geometry.vertices[c].clone();

        // Adding them to an array
        vertex_group.push(v1, v2, v3);

}

// Side Faces

var vertsToExtrude = [];

// Select only vertices on the outer edge
for ( var v = 0; v < vertex_group.length; v++ ) {

    var shareCount = 0;

    // Count their presence in each face
    for ( var f = 0; f < face_group.length; f++ ) {

        if( v == face_group[ f ].a || 
            v == face_group[ f ].b ||
            v == face_group[ f ].c ) 
        {

            shareCount++;
        }
    }

    // Check if less than 4 shares, then it's on an outer edge. Add it to the array
    if ( shareCount < 4) {

        vertsToExtrude.push( vertex_group[ v ].clone() );

    }
}

// Create a shape with selected vertices

var shape = new THREE.Shape();

shape.moveTo( vertsToExtrude[ 0 ].x, vertsToExtrude[ 0 ].y );

for ( var i = 1; i < vertsToExtrude.length; i++ ){

    shape.lineTo( vertsToExtrude[ i ].x, vertsToExtrude[ i ].y );

}

shape.lineTo( vertsToExtrude[ 0 ].x, vertsToExtrude[ 0 ].y );

// Extrude the shape

var extrudeSettings = { amount: amount, steps: 2, bevelEnabled: false };

var sideGeo = new THREE.MyExtrudeGeometry( shape, extrudeSettings );


// Front Faces

var frontGeo = new THREE.Geometry();

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

        // Retrieve vertices ID
        var f = face_group[i];
        var a = f.a;
        var b = f.b;
        var c = f.c;

        // New vertices IDs
        var new_a = frontGeo.vertices.length;
        var new_b = frontGeo.vertices.length + 1;
        var new_c = frontGeo.vertices.length + 2;

        // Clone vertices
        var v1 = geometry.vertices[a].clone();
        var v2 = geometry.vertices[b].clone();
        var v3 = geometry.vertices[c].clone();
        frontGeo.vertices.push(v1, v2, v3);

        // Adjust their z-coordinate based on "amount"
        v1.z = v1.z + amount;
        v2.z = v2.z + amount;
        v3.z = v3.z + amount;

        // Add them to a face 
        var f = new THREE.Face3(new_a, new_b, new_c);
        frontGeo.faces.push(f);

}

frontGeo.computeFaceNormals();

geometry.merge( sideGeo );

geometry.merge( frontGeo );

};

Answer №1

After perusing the documentation on ExtrudeGeometry, I realized my oversight:

"extrudePath — THREE.CurvePath. 3D spline path to extrude shape along. (creates Frames if frames aren't defined)"

I believe this may be the key to solving my problem :)

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

Display images in a list with a gradual fade effect as they load in Vue.js

In my Vue project, I am looking to display images one at a time with a fading effect. I have added a transition group with a fade in effect and a function that adds each image with a small delay. However, I am facing an issue where all the images show up ...

if statement not recognizing data returned from PHP function

I'm currently working with a function that is being used for an AJAX query: var formData = $(this).serialize(); //store form names and values in an array called 'formData' $.get('filtertest.php',formData,processData); //jQ ...

Attempting to reach <p> from numerous web pages

Currently, I am working on a project where I need to extract text data from various websites. I have successfully managed to retrieve the text data using <p> tags. I would really appreciate any assistance with this task. Thank you! ...

After 30 to 80 touches, the movement starts to lag and an error appears in the console

Error Details: [Intervention] A touchend event cancellation attempt was ignored due to cancelable=false, likely because scrolling is in progress and cannot be stopped. preventDefault @ jquery.min.js:2 (anonymous) @ number_grid_game.php:239 each @ ...

Utilize UI-Router $stateProvider in Angular run block for Promise Resolution

UI-Router has different capabilities compared to Angular's ngRoute. It not only supports all the features of ngRoute but also provides additional functionalities. I am transitioning my Angular application from ngRoute to UI-Router. However, I'm ...

How can I edit this code in JSPDF to print two pages instead of just one?

Currently, I have a script that can generate a PDF from one DIV, but now I need to create a two-page PDF from two separate DIVs. How can I modify the existing code to achieve this? The first DIV is identified as #pdf-one and the second DIV is #pdf-two. p ...

Update the dropdown menu based on the revised time

I need to create a PHP site and JavaScript function that changes a dropdown menu based on specific time intervals, such as 7:00-8:00 (id530), 13:00-15:00 (id1330), or 20:00-03:00 (id2130). For example, if the time is 7:31, the dropdown menu should display/ ...

Using a text box in jQuery to perform basic calculations is a straightforward process

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Creating a Lens Calculator Web App</title> <link href="http://code.jquery.com/mobile/1.0a3/jque ...

Utilizing a switch statement in Jquery to target specific input elements for focus

My Objective As a user presses enter, I want to target specific input elements with a data-index attribute value between 0-2 and of type text. Then, I plan to check their attribute values using a switch statement to perform certain actions. Presented bel ...

Use an EditText to capture user input, then pass the variables to a Webview by executing a javascript command

I'm currently working on a basic web application that aims to streamline the user experience by eliminating the need for repeated credential input upon website access (without saving passwords). After some exploration, I was able to identify and manip ...

Discover and capture zip codes using javascript

Looking to extract zip codes from strings like "HONOLULU HI 96814-2317 USA" and "HONOLULU HI 96814 USA" using JavaScript. Any suggestions on how to achieve this? ...

Field for user input featuring a button to remove the entry

I am attempting to add a close icon to a bootstrap 3 input field, positioned on the top right of the input. Here is what I have tried so far: https://jsfiddle.net/8konLjur/ However, there are two issues with this approach: The placement of the × ...

What is the best way to incorporate intervals and polling in Angular 2 for seamless integration with Protractor?

I have an angular2 application that I am looking to test using protractor. Within this application, there is a page featuring a graph that updates at regular intervals with data generated on its own. It appears that one aspect of protractor is the abilit ...

Invoking a function without specifying its parent function when nested within another function

I need to execute an anonymous function within another function without actually calling the parent function, as it will lead to errors. Here is the parent function: function onloadCallback() { grecaptcha.render("recaptchaHolder", { "size": "invisi ...

Unexpected token { in Fuse-Box when using Typescript

Here's the beginning of my fuse.ts file import { CSSPluginOptions } from 'fuse-box/plugins/stylesheet/CSSplugin'; import { argv } from 'yargs'; import * as path from 'path'; import { CSSPlugin, CSSResourcePlugin, Env ...

I'm looking for a way to retrieve an object from a select element using AngularJS. Can

I am working with a select HTML element that looks like this: <select required="" ng-model="studentGroup"> <option value="" selected="">--select group--</option> <option value="1">java 15-1</option> <option value="2">ja ...

Reorganize the JSON data to match the specified format

{ "EUR": { "Description": "", "Bid": "1.1222", "Region": "", "Bid1": "1.1283", "CurrencyCode": "EUR", "FeedSource": "1", "Ask": "1.1226", "ProviderName": "TEST 1", "Low": "1.1195", ...

The SharedArrayBuffer does not exist in this context

A new library, react-canvas, has been causing some trouble for me. Lately, an error message keeps appearing with the <p> tag in the canvas area where it should be displayed on browsers like Chrome. The framework I'm using is nextjs, and I&apos ...

Can props.children be given a ref without any existing ref?

Consider this scenario... MainComponent.js <Wrapper> <p ref={React.createRef()}>{state.item1}</p> <p>{state.item2}</p> <p>{state.item3}</p> <p>{state.item4}</p> </Wr ...

Is there a way for me to discover the identity of the victor?

There are 4 divs that move at different, random speeds each time. I am trying to determine which one is the fastest or reaches the goal first. Additionally, there is a betting box where you can choose a horse to bet on. I need to compare the winner with my ...