Casual Bob
Casual Bob

Reputation: 87

Three.js - how can I use an EllipseCurve as an extrusion path?

The problem: In the awesome Three.js, I can't figure out how to convert an EllipseCurve into a path that I can extrude along.

In the example below, if I uncomment the LineCurve3, my square extrudes along it nicely. If I run it as the EllipseCurve, there are no errors but nothing shows on screen. I have tried zooming the camera right out to make sure it's not off the screen for any reason.

I know the EllipseCurve is being generated correctly as I can write it out with a line material (not shown in the code below).

The code

var radius = 1100;
var degreesStart = 75;
var degreesEnd = 30;
var radiansStart = (degreesStart * Math.PI) / 180;
var radiansEnd = ((degreesEnd) * Math.PI) / 180;

// this won't seem to work as an extrude path, but doesn't give any errors
var path = new THREE.EllipseCurve(0, 0, radius, radius, radiansStart, radiansEnd, true);

// this works fine as an extrude path
//var path = new THREE.LineCurve3(new THREE.Vector3(0, 0, 0), new THREE.Vector3(1000, 1000, 0));

var extrusionSettings = { steps: 100, bevelEnabled: false, extrudePath: path };

// draw a square to extrude along the path
var sectionSize = [];
sectionSize.push(new THREE.Vector2(0, 0));
sectionSize.push(new THREE.Vector2(1000, 0));
sectionSize.push(new THREE.Vector2(1000, 1000));
sectionSize.push(new THREE.Vector2(0, 1000));

var sectionShape = new THREE.Shape(sectionSize);

var componentGeometry = new THREE.ExtrudeGeometry(sectionShape, extrusionSettings);
var component = new THREE.Mesh(componentGeometry, material);

group.add(component);

What I have tried: My attempts to make it work have all tried to extract the points from the curve into a path to use in the extrusion. The closest I felt I got was

 var ellipsePath = new THREE.CurvePath(path.getSpacedPoints(20)); 
// where 'path' is my EllipseCurve in the code above
// (and then changed the extrusion settings to use 'ellipsePath ' instead).

This gave the error "Cannot read property 'distanceTo' of null".

I can't seem to get my head around how the EllipseCurve relates to points that relate to a path.

Can anyone point me in the right direction please, or have code where you've come across the same problem? Many thanks.

Upvotes: 1

Views: 1568

Answers (2)

Noleli
Noleli

Reputation: 662

Inspired by @james-dunn’s solution, I implemented a Path3D class that’s the same as a regular THREE.Path except that getPoint() returns a Vector3 with z = 0:

class Path3D extends THREE.Path {
    constructor(pts) {
        super(pts);
    }
    
    getPoint(t) {
        const pt2d = super.getPoint(t);
        const pt3d = new THREE.Vector3(pt2d.x, pt2d.y, 0);
        return pt3d;
    }
}

Upvotes: 1

James William Dunn
James William Dunn

Reputation: 456

I ran into the same problem. After experimenting with EllipseCurve and CurvePath, I concluded that these two are building 2D paths which lead to problems inside ExtrudeGeometry. Examining the source of three.js and the example extrusion based on a 3D spline, I built my own Curve and defined a 3D .getPoint function. This solved the problem and rendered a perfect extrusion. Replace the "var path" line of your code with the following:

var path = new THREE.Curve();
path.getPoint = function (t) {
    // trace the arc as t ranges from 0 to 1
    var segment = (radiansStart - radiansEnd) * t;
    return new THREE.Vector3(radius * Math.cos(segment), radius * Math.sin(segment), 0);
    };

Upvotes: 2

Related Questions