title: Three.js - Extrude face along its normal vector
body: <p>I want to extrude faces from a THREE.Geometry object, so my approach was to:
  - specify the faces to extrude
  - extract vertices on the outer edges
  - Draw a THREE.Shape with those vertices
  - Extrude it using THREE.ExtrudeGeometry (I'm actually using a modified version which is not generating front faces, as I'm cloning them by myself to keep original topology).</p>
  
  <p>It seems to work having a CircleGeometry on a XY plane, so extruding on Z direction.
  <a href="https://i.stack.imgur.com/p0Ipw.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/p0Ipw.png" alt="enter image description here"></a></p>
  
  <p>but if I rotate the circle a bit this is what I get. It extrudes on Z World Axes, not following its local orientation
  <a href="https://i.stack.imgur.com/zmGmJ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/zmGmJ.png" alt="enter image description here"></a></p>
  
  <p>I can I solve this? Here's the function I'm using:</p>
  
  <pre><code>function faceExtrude( geometry, face_group, amount ) {
  
  if ( geometry.type === "undefined" ) {
  
      console.log( "faceextrude error" );
  
      return;
  
  }
  
  //convert face_group to vertex_group
  var vertex_group = [];
  
  for ( var i = 0; i &lt; face_group.length; i++ ) {
  
          //get vertices ID
          var f = face_group[i];
          var a = f.a;
          var b = f.b;
          var c = f.c;
  
          //clone vertices
          var v1 = geometry.vertices[a].clone();
          var v2 = geometry.vertices[b].clone();
          var v3 = geometry.vertices[c].clone();
  
          //add them to an array
          vertex_group.push(v1, v2, v3);
  
  }
  
  
  // Side Faces
  
  var vertsToExtrude = [];
  
  
  //Get only verts in outer edge
  for ( var v = 0; v &lt; vertex_group.length; v++ ) {
  
      var shareCount = 0;
  
      //count their presence in each face
      for ( var f = 0; f &lt; face_group.length; f++ ) {
  
          if( v == face_group[ f ].a || 
              v == face_group[ f ].b ||
              v == face_group[ f ].c ) 
          {
  
              shareCount++;
          }
      }
  
      //if &lt; 4 than it's in an outer edge. Add it to an array
      if ( shareCount &lt; 4) {
  
          vertsToExtrude.push( vertex_group[ v ].clone() );
  
      }
  }
  
  
  //make a shape with them
  
  var shape = new THREE.Shape();
  
  
  shape.moveTo( vertsToExtrude[ 0 ].x, vertsToExtrude[ 0 ].y );
  
  for ( var i = 1; i &lt; vertsToExtrude.length; i++ ){
  
      shape.lineTo( vertsToExtrude[ i ].x, vertsToExtrude[ i ].y );
  
  }
  
  shape.lineTo( vertsToExtrude[ 0 ].x, vertsToExtrude[ 0 ].y );
  
  //extrude it
  
  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 &lt; face_group.length; i++ ) {
  
          //get 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);
  
          //translate them depending 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 );
  </code></pre>
  
  <p>};</p>