Custom CAP function in MeshBuilder.ExtrudeShape

Hey folks !

Following discussions in these topics :

@Deltakosh :

@sachou_sachou :

I come with a PR to resolve an issue with extruding non convex shapes, such as U-shaped or H-shaped IPN sections :


Here is a Playground for testing the PR snapshot :

  • On the left, default function
  • On the right, custom function

@sachou_sachou , @Evgeni_Popov , I can confirm that the problem came from triangle fan default CAP method :

const pointCap = Array<Vector3>();
const barycenter = Vector3.Zero();
let i: number;
for (i = 0; i < shapePath.length; i++) {
    barycenter.addInPlace(shapePath[i]);
}
barycenter.scaleInPlace(1.0 / shapePath.length);
for (i = 0; i < shapePath.length; i++) {
    pointCap.push(barycenter);
}
return pointCap;

The previous function (that I keep as default in this PR) what just adding for all points, the barycenter.

NB: Params has been added at the end of the list, for retrocompatibility and non breaking change.

NB2: The above playground is using a custom cap function I tried myself, just to test. Please note that various CAP function could be used, this test is not guaranteed to work on any shape, but that’s not the point of the PR. The point is just being able to pass a function.

3 Likes

@sachou_sachou here is your playground running on the snapshot with my custom CAP :

2 Likes

@Tricotou good job bro, that defenitvelly does the job .
however, you can go deep to it and add another function that will be used for holes, for more complexe shapes to extrude . what do you think ?

I think it would be nice, but I am trying to go step by step.

For now the current capFunction (which was already existing, and can now be custom) had very low power on the geometry :

The function takes the last loop as input, and returns the new loop. That’s all it does (no change in number of vertices, faces, or whatever. And then it adds it at first, at last, or at both :

const capPath = capFunction || defaultCapPath;
switch (cap) {
    case Mesh.NO_CAP:
        break;
    case Mesh.CAP_START:
        shapePaths[0] = capPath(shapePaths[2]);
        shapePaths[1] = shapePaths[2];
        break;
    case Mesh.CAP_END:
        shapePaths[index] = shapePaths[index - 1];
        shapePaths[index + 1] = capPath(shapePaths[index - 1]);
        break;
    case Mesh.CAP_ALL:
        shapePaths[0] = capPath(shapePaths[2]);
        shapePaths[1] = shapePaths[2];
        shapePaths[index] = shapePaths[index - 1];
        shapePaths[index + 1] = capPath(shapePaths[index - 1]);
        break;
    default:
        break;
}

By the way, that’s why the default function could be that simple :

const defaultCapPath = (shapePath: Vector3[]) => {
    const pointCap = Array<Vector3>();
    const barycenter = Vector3.Zero();
    let i: number;
    for (i = 0; i < shapePath.length; i++) {
        barycenter.addInPlace(shapePath[i]);
    }
    barycenter.scaleInPlace(1.0 / shapePath.length);
    for (i = 0; i < shapePath.length; i++) {
        pointCap.push(barycenter);
    }
    return pointCap;
};

In fact it’s just returning a list containing N-times the barycenter. The rest (creating new faces from this list) is done else where.


So to conclude, in order to be able to add more complex geometry in the CAP, it would need a bit more complex modification of the code

I see , so indeed we can work on holes :
Since it taking the last loop and returning the current one , i guess that it s giving the loops in the same order you passed the shape , so you can use the current loop to create the cap like you did , and then draw faces of the cross bridge between the current and the last cap … We need a complxe