Extrusion
A very desirable operation to perform on a mesh is diplacing the triangles of which it is composed. Althoug not evident on closed meshes, when displaced, triangles look flat and volumeless. This patch uses a custom geometry script to account for that.
Let's thicken them up
Open the patch thickness.maxpat
This patch takes a Jitter geometry and extrudes the triangles along their vertex normals, forming truncated pyramids of user-defined height. It then performs a random displacement of such extruded triangles to show them in all their glorious thickness.
Let's take a look at the patch:
The first step consists in grabbing a mesh, turning it into a Jitter geometry, and computing vertex normals using jit.geom.normgen. Each vertex in the Jitter geometry structure now retains vertex normals.
Then, jit.geom.todict converts the Jitter geometry into a dictionary accessible by JavaScript.
Double-click on v8 geom.thickness.js
to take a look at what the custom geometry script does.
// Go through all the faces
faces.forEach(face => {
// get two halfedges on this face
let he0 = face.halfedge;
let he1 = geom.halfedges[he0].next;
// get the index of the vertices of this face
let v0 = geom.halfedges[he0].from;
let v1 = geom.halfedges[he1].from;
let v2 = geom.halfedges[he1].to;
// get the vertex normals
let n0 = geom.vertices[v0].normal;
let n1 = geom.vertices[v1].normal;
let n2 = geom.vertices[v2].normal;
// get the position of the vertices
let p0 = geom.vertices[v0].point;
let p1 = geom.vertices[v1].point;
let p2 = geom.vertices[v2].point;
// create 3 new positions based on p0, p1, and p2,
// shifted by "thickness" along their normal vector
let pt0 = translate(p0, n0);
let pt1 = translate(p1, n0);
let pt2 = translate(p2, n0);
The script iterates over the triangles reading the positions and the normal vectors of the 3 vertices. It then computes 3 new positions, shifting each vertex inwards along the direction of their vertex normals.
// Push the points into the list
// top face
triangleVertices.push(p0);
triangleVertices.push(p1);
triangleVertices.push(p2);
// bottom face
triangleVertices.push(pt0);
triangleVertices.push(pt1);
triangleVertices.push(pt2);
// side faces
triangleVertices.push(p0);
triangleVertices.push(pt0);
triangleVertices.push(p1);
triangleVertices.push(p1);
triangleVertices.push(pt0);
triangleVertices.push(pt1);
triangleVertices.push(p1);
triangleVertices.push(pt1);
triangleVertices.push(p2);
triangleVertices.push(p2);
triangleVertices.push(pt1);
triangleVertices.push(pt2);
triangleVertices.push(p2);
triangleVertices.push(pt2);
triangleVertices.push(p0);
triangleVertices.push(p0);
triangleVertices.push(pt2);
triangleVertices.push(pt0);
It then triangulates the old and the new positions forming a volume.
Now, open the [p animate] subpatch if you want to take a look at how is the mesh dancing.
The animation is achieved by offsetting the volumes' positions along their face normals using procedural noise provided by jit.bfg.