Simple Rectangular Geometry Extrusion (Anyone?)

Here is a version with open/closed contour :slight_smile:
Looks like it needs .openEnded parameter, like in THREE.CylinderGeometry().

https://jsfiddle.net/prisoner849/bygy1xkt/

  function ProfiledContourGeometry(profileShape, contour, contourClosed) {
    
    contourClosed = contourClosed !== undefined ? contourClosed : true;
		
    let profileGeometry = new THREE.ShapeBufferGeometry(profileShape);
    profileGeometry.rotateX(Math.PI * .5);
    let profile = profileGeometry.attributes.position;

    let profilePoints = new Float32Array(profile.count * contour.length * 3);

    for (let i = 0; i < contour.length; i++) {
      let v1 = new THREE.Vector2().subVectors(contour[i - 1 < 0 ? contour.length - 1 : i - 1], contour[i]);
      let v2 = new THREE.Vector2().subVectors(contour[i + 1 == contour.length ? 0 : i + 1], contour[i]);
      let angle = v2.angle() - v1.angle();
      let halfAngle = angle * .5;
			
      let hA = halfAngle;
      let tA = v2.angle() + Math.PI * .5;
      if (!contourClosed){
      	if (i == 0 || i == contour.length - 1) {hA = Math.PI * .5;}
        if (i == contour.length - 1) {tA = v1.angle() - Math.PI * .5;}
      }
      
      let shift = Math.tan(hA - Math.PI * .5);
      let shiftMatrix = new THREE.Matrix4().set(
        1, 0, 0, 0, -shift, 1, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
      );
			
      
      let tempAngle = tA;
      let rotationMatrix = new THREE.Matrix4().set(
        Math.cos(tempAngle), -Math.sin(tempAngle), 0, 0,
        Math.sin(tempAngle), Math.cos(tempAngle), 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
      );

      let translationMatrix = new THREE.Matrix4().set(
        1, 0, 0, contour[i].x,
        0, 1, 0, contour[i].y,
        0, 0, 1, 0,
        0, 0, 0, 1,
      );

      let cloneProfile = profile.clone();
      shiftMatrix.applyToBufferAttribute(cloneProfile);
      rotationMatrix.applyToBufferAttribute(cloneProfile);
      translationMatrix.applyToBufferAttribute(cloneProfile);

      profilePoints.set(cloneProfile.array, cloneProfile.count * i * 3);
    }

    let fullProfileGeometry = new THREE.BufferGeometry();
    fullProfileGeometry.addAttribute("position", new THREE.BufferAttribute(profilePoints, 3));
    let index = [];
		
    let lastCorner = contourClosed == false ? contour.length - 1: contour.length;
    for (let i = 0; i < lastCorner; i++) {
      for (let j = 0; j < profile.count; j++) {
        let currCorner = i;
        let nextCorner = i + 1 == contour.length ? 0 : i + 1;
        let currPoint = j;
        let nextPoint = j + 1 == profile.count ? 0 : j + 1;

        let a = nextPoint + profile.count * currCorner;
        let b = currPoint + profile.count * currCorner;
        let c = currPoint + profile.count * nextCorner;
        let d = nextPoint + profile.count * nextCorner;


        index.push(a, b, d);
        index.push(b, c, d);
      }
    }

    fullProfileGeometry.setIndex(index);
    fullProfileGeometry.computeVertexNormals();

    return fullProfileGeometry;
  }
6 Likes