eogabor
eogabor

Reputation: 330

Three.js extrude vertically

I am new to three.js and I want to extrude a shape vertically. I can set the points of the 2D shape, but when I extrude it, the extrusion happens along the z axis. I want to extrude the shape along the y axis, how can I make this happen in the simplest way?(In this example I know could use a box geometry, because Im extruding a rectangle, but its only because of simplicity, i want to extrude complex shapes).

One thing i tried, is rotating the mesh afer extruding it, but that messes up the startpoint for me(makes it more difficult to calculate the positions of the objects, contained by the extruded objects).

So to keep it simple, I want something like this, without rotations.

enter image description here

my code:

export function createStorageLocation(storageLocation: StorageLocation) {
  const shape = new Shape();
  shape.moveTo(0, 0);
  shape.lineTo(0, 200 / 100);
  shape.lineTo(400 / 100, 200 / 100);
  shape.lineTo(400 / 100, 0);
  shape.lineTo(0, 0);

  const extrudeSettings: ExtrudeGeometryOptions = {
    steps: 2,
    depth: 10,
    bevelEnabled: false,
    bevelThickness: 1,
    bevelSize: 1,
    bevelOffset: 0,
    bevelSegments: 1,
  };

  const geometry = new ExtrudeGeometry(shape, extrudeSettings);

  const material = new MeshStandardMaterial({
    color: 'blue',
    opacity: 0.7,
    transparent: false,
  });

  const location = new Mesh(geometry, material);
  const axesHelper = new AxesHelper(5);
  location.add(axesHelper);
  location.position.set(
    storageLocation.startPoint.x / 100,
    storageLocation.startPoint.y / 100,
    storageLocation.startPoint.z / 100
  );
  return location;
}

current state of the app: enter image description here

Upvotes: 3

Views: 1652

Answers (2)

Phil N.
Phil N.

Reputation: 700

ExtrudeGeometry makes a hard presumption that the shape to be extruded is defined in the xy plane and that the extrusion is to be along +z. See, for example, lines 421-449 of the source code, in particular line 432:

v( vert.x, vert.y, depth / steps * s );

Where v(x, y, z) is a member function that pushes a coordinate triple into the object's vertex array; vert.x and vert.y are the x- and y-coordinates of the shape being extruded; and depth / steps * s yields the z-coordinate of the extrusion at a particular step.

Furthermore, the presumption about the shape being in the xy plane is necessary because Shape objects are two-dimensional; the Flatland of the xy plane is the only world they know.

To get the behavior you want (i.e., without rotations), you would have to implement it yourself. You could start from what ExtrudeGeometry does internally and transplant the extrusion from the z-axis to the y-axis. The logic is fairly trivial in the case of a rectangle with a straight extrusion path (like your examples here), becoming more complex in proportion to the complexity of the shape and the extrusion path, but it's still far more complex than biting a bullet and using the extrude-then-rotate method.

Upvotes: 5

eogabor
eogabor

Reputation: 330

Allright I found a solution with rotation and translation, what I messed up was that I rotated the mesh,not the geomerty. But I'm still courious about the correct way of doing this. Working code:

export function createStorageLocation(storageLocation: StorageLocation) {
  const shape = new Shape();
  shape.moveTo(0, 0);
  shape.lineTo(0, 200 / 100);
  shape.lineTo(400 / 100, 200 / 100);
  shape.lineTo(400 / 100, 0);
  shape.lineTo(0, 0);

  const extrudeSettings: ExtrudeGeometryOptions = {
    steps: 2,
    depth: 10,
    bevelEnabled: false,
    bevelThickness: 1,
    bevelSize: 1,
    bevelOffset: 0,
    bevelSegments: 1,
  };

  const geometry = new ExtrudeGeometry(shape, extrudeSettings);
  geometry.rotateX(MathUtils.degToRad(-90));
  geometry.translate(0, 0, 200 / 100);

  const material = new MeshStandardMaterial({
    color: 'blue',
    opacity: 0.7,
    transparent: false,
  });

  const location = new Mesh(geometry, material);
  const axesHelper = new AxesHelper(5);
  location.add(axesHelper);
  location.position.set(
    storageLocation.startPoint.x / 100,
    storageLocation.startPoint.y / 100,
    storageLocation.startPoint.z / 100
  );

  location.updateMatrix();
  return location;
}

result:

enter image description here

Upvotes: 2

Related Questions