Luke Vuksta

Turning Meshes into Horrifying Piecewise Functions

I recently wrote a program, mesh2frep, that is, honestly, a bit unhinged at best. Let me tell you about it!

So what does it do?

It takes an STL as an input, then outputs a Rhai script that is simply a huge mathematical function! Well, importantly, that mathematical function is a Signed Distance Function (SDF) that represents the same surface as the STL.

Before going further, we should briefly talk about the difference between these representations of the object. An STL is a bounding surface mesh made up of triangles; that is, the only data contained is a list of vertices and a list of triangles, constructed by indexing into the former list. This list of triangles is sewn up so they all attach to each other, and create a watertight surface (in a well-formed STL at least). An SDF is a function such that the value at each point represents the distance from the surface of the function. Thus, a point inside the function is negative, outside is positive, and the boundary is zero. There are some additional constraints that this condition of being a distance enforces, e.g. the function has unit gradients almost everywhere. Notably, these functions only need to be continuous, and not continuously differentiable.

SDFs are very interesting, and very powerful representations of volumes.

So how do you go about turning a bunch of triangles in space into an SDF?

Well, we need a number of tools for this. Let's start with the obvious one: an SDF triangle. This is a relatively tall order, actually. To understand why, let's naively construct one from a number of half planes, in Rhai:

let planes = [
    -x,
    -y,
    (x + y - 1.0) / sqrt(2),
];

// Iterate over the planes and intersect them.
let triangle = planes[0];
for i in 1..planes.len() {
    triangle = max(triangle, planes[i]);
}

triangle = max(triangle, abs(z));

triangle

There you have it, a triangle in three-space, with vertices at (0, 0, 0), (0, 1, 0), and (1, 0, 0)! If you don't see anything, that's expected (you are following along, right?), as this shape has no volume. But note what happens when we try

triangle - 1

or try subtracting any value from this representation... it isn't actually an SDF. If it was an SDF, the distance from the vertices would be spheres, and the edges would be cylinders. What we have here actually, is a Unit Gradient Field (UGF). As interesting as those are, we are attempting to create an SDF, so we will have to be a bit more clever.

Without writing the code quite yet, let's assume we can tell if we are "inside" or "outside" the half planes defined in the previous function. If we can do that, we can at least keep the part that defines the triangle plane, abs(z). Then we might be able to come up with some other construction like an SDF for a line segment to represent the triangle edges, and swap between these line segments and the plane based on where we are in space! The issue with this is that Fidget, the underlying library we are using to parse these expressions, and many other SDF engines, don't parse programmatic control flow into the expression.

So how do you add programmatic control flow to SDFs?

Piecewise functions.

I may have spoiled that revelation with the title. Fortunately, due to the meddling of my past self, Fidget actually supports a basic building block of piecewise functions. In Rhai:

// Conditional nonzero function that does not propagate
//  NaN from either parameter a or b.
fn if_nonzero_else(condition, a, b) {
    let lhs = and(condition, a);
    let n_condition = not(condition);
    let rhs = and(n_condition, b);
    or(lhs, rhs)
}

But this only gets us a very specific condition, we need to do better. Generally, we would like some equivalent of "greater than" or "less than" inequalities to direct control flow. Note that, a < b implies a - b < 0. That is, all we need to achieve an equivalent to "less than" is a function that returns zero if the condition is negative, and nonzero if nonnegative. If we always return one when the condition is nonnegative, we have just described a variant of the Heaviside Step Function! Let's put this in Rhai as well:

// A version of the Heaviside step function where H(0) = 1.
fn heaviside_step_function(a) {
    min(0.0, compare(a, 0.0)) + 1.0
}

And putting it together with if_nonzero_else, we have:

// A function that returns a if condition is nonnegative, b otherwise.
fn if_nonnegative_else(condition, a, b) {
    let res = heaviside_step_function(condition);
    if_nonzero_else(res, a, b)
}

And now we can write control flow into our SDFs!

So then, how does this help us make a triangle?

Well, this added control flow tool allows us to do something fairly interesting:

fn signed_distance_function_triangle() {
    let planes = [
        -x,
        -y,
        (x + y - 1.0),
    ];

    // Iterate over the planes and count what region we are in.
    let region_marker = if_nonnegative_else(planes[0], 1, 0);
    for i in 1..planes.len() {
        region_marker += if_nonnegative_else(planes[i], 1, 0);
    }

    // If the region_marker is equal to 1 or 2 (greater than 0.5).
    if_nonnegative_else(region_marker - 0.5,
        // Don't tell the Rhai folks about my crimes.
        parse_float("Inf"),
    // Or else.
    -parse_float("Inf")
    )
}

signed_distance_function_triangle()

I will note immediately, this is not an SDF, but attempting to render it with Fidget (in heightmap mode, it will not work with normals) results in an infinitely tall prism. Inside the boundaries of those planes, it is always -Inf, and Inf elsewhere. Try subtracting a constant from it and you will not see any change; this is because you are not subtracting the value from the control flow statements, just the overall result of the expression. That is the magic that lets us move forward with constructing a triangle SDF.

As a brief aside, you may have noticed that we dropped the normalization from the last half plane. It was only there to ensure the object was a UGF, and is no longer needed in our piecewise construction.

As mentioned before, abs(z) works perfectly fine for distance inside the prism, but we need to construct an SDF for a line segment, to use for the edges. This SDF line segment is effectively just a capsule of radius zero, that does not grow in length. This is now easy enough to define:

// A function that creates a vertical capsule of a fixed height.
fn vertical_capsule(radius, height) {
    if_nonnegative_else(-z,
        sphere(radius),
    if_nonnegative_else(z - height,
        remap(sphere(radius), x, y, z - height),
    // Else
    sqrt(x*x + y*y) - radius
    ))
}

Putting three of these capsules together with the piecewise triangle as well as the plane and we get:

fn signed_distance_function_triangle() {
    let planes = [
        -x,
        -y,
        (x + y - 1.0),
    ];

    // Iterate over the planes and count what region we are in.
    let region_marker = if_nonnegative_else(planes[0], 1, 0);
    for i in 1..planes.len() {
        region_marker += if_nonnegative_else(planes[i], 1, 0);
    }

    let pi = 3.1415926535;

    // If the region_marker equal to 1 or 2 (greater than 0.5).
    if_nonnegative_else(region_marker - 0.5,
        min(remap(vertical_capsule(0, 1), z, y, x),
        min(remap(vertical_capsule(0, 1), x, z, y),
            remap(vertical_capsule(0, sqrt(2)),
                  z,
                  sin(pi/4) * x + cos(pi/4) * (y-1),
                  cos(pi/4) * x - sin(pi/4) * (y-1))
        )),
    // Else.
    abs(z)
    )
}

signed_distance_function_triangle()

And we have a triangle SDF!

The issue that we immediately run into is a side effect of performing an affine transformation on this triangle to translate and stretch it into the place of any triangle in the original surface mesh. If we perform a linear transformation to remap our x and y axes into two vectors (like two of our triangle edges with their shared vertex relocated to the origin), this does not preserve the gradients of the SDF. Rather than attempting to compensate for this, we just use a helper function to construct our triangles in the real library:

// Helper to create infinitely thin triangles with a unit gradient. When subtracting a value, a, from this
//  function, it behaves like the Minkowski sum of the triangle and a sphere of radius a. The remapping
//  functions are the inverse transformation of the map that takes the unit vectors in x, y, z and maps them
//  to edge one, two, and the unit normal of the given triangle.
//
// remap_x_param: remapping of the x axis for the triangle
// remap_y_param: remapping of the y axis for the triangle
// remap_z_param: remapping of the z axis for the triangle
// edge_function: union of three vertical capsules of radius zero and height equal to the length of the
//  triangle edge it corresponds to, oriented in space at the edge.
fn signed_distance_function_triangle_helper(remap_x_param, remap_y_param, remap_z_param, edge_function) {
    let planes = [
        -x,
        -y,
        (x + y - 1.0),
    ];

    // Iterate over the planes and count what region we are in.
    let region_marker = if_nonnegative_else(planes[0], 1, 0);
    for i in 1..planes.len() {
        region_marker += if_nonnegative_else(planes[i], 1, 0);
    }

    // If the region_marker equal to 1 or 2 (greater than 0.5).
    if_nonnegative_else(remap(region_marker - 0.5, remap_x_param, remap_y_param, remap_z_param),
        // We do not remap the edge function, as it would stretch the cylinders and spheres, ruining the SDF property.
        edge_function,
    // Else: we are in the positive region.
    remap(abs(z), remap_x_param, remap_y_param, remap_z_param)
    )
}

This is called for each triangle in the surface, where the remapping parameters are an affine transformation that preserves the unit gradient for the triangle normal, and the edge_function is the union of three vertical capsules, all individually remapped with an affine transformation. I am glossing over the details of this transformation for this post, as it's just a bunch of relatively simple linear algebra.

So you have a surface, but nothing inside of it?

Right! So far, we are only able to construct a surface by unioning a list of our triangles; our SDF still has no volume. If you are worried that you missed where we constructed this list, don't be, because we didn't. I will include an example later, for now, just visualize our SDF to be the triangles in the original mesh, and when you subtract a value from the SDF, the mesh surface expands both inwards and outwards. What we can do with this to turn it into a proper SDF with volume? Simply negate the values we know to be inside!

So how do you negate the inside of the SDF?

We already have demonstrated that we can construct a piecewise function that does not change when subtracting any value from it, this just leaves the question of what piecewise function are we constructing to tell us when we are inside the mesh? The simplest solution is to just tetrahedralize the input STL. This results in both a list of surface triangles and a list of interior tetrahedrons. Following the same pattern as above, we can make another Rhai function for this tetrahedron:

// A tetrahedron formed from the origin and unit vectors on the
//  x, y, z axis, which returns 0 inside and 1 outside.
fn bounded_unit_tetrahedron() {
    if_nonnegative_else(x,
        if_nonnegative_else(y,
            if_nonnegative_else(z,
                if_nonnegative_else(-x - y - z + 1.0,
                    0,
                // Else
                1),
            // Else
            1),
        // Else
        1),
    // Else
    1)
}

Performing yet another affine transformation for each interior tetrahedron, we can bring it all together with:

// Construct a signed distance function from a list of bounded
//  tetrahedrons inside the volume and a list of surface triangles.
fn sdf_mesh(tetrahedrons, triangles) {
    let sdf_base = triangles[0];
    for i in 1..triangles.len() {
        sdf_base = min(sdf_base, triangles[i]);
    }

    // Determine what region we are in.
    let region = tetrahedrons[0];
    for i in 1..tetrahedrons.len() {
        region *= tetrahedrons[i];
    }

    // If we are inside a single tetrahedron then region = 0, else region = 1.
    if_nonzero_else(region, sdf_base, -sdf_base)
}

Where this function takes a list of tetrahedrons and a list of triangles, and produces an SDF for a mesh!

So what does the entire result look like?

Behold, a cube!

// Generated file representing a mesh transformed into a functional representation.

// Conditional nonzero function that does not propagate NaN from either parameter a or b.
fn if_nonzero_else(condition, a, b) {
    let lhs = and(condition, a);
    let n_condition = not(condition);
    let rhs = and(n_condition, b);
    or(lhs, rhs)
}

// A version of the Heaviside step function where H(0) = 1.
fn heaviside_step_function(a) {
    min(0.0, compare(a, 0.0)) + 1.0
}

// A function that returns a if condition is nonnegative, b otherwise.
fn if_nonnegative_else(condition, a, b) {
    let res = heaviside_step_function(condition);
    if_nonzero_else(res, a, b)
}

// A function that creates a vertical capsule of a fixed height.
fn vertical_capsule(radius, height) {
    if_nonnegative_else(-z,
        sphere(radius),
    if_nonnegative_else(z - height,
        remap(sphere(radius), x, y, z - height),
    // Else
    sqrt(x*x + y*y) - radius
    ))
}

// Helper to create infinitely thin triangles with a unit gradient. When subtracting a value, a, from this
//  function, it behaves like the Minkowski sum of the triangle and a sphere of radius a. The remapping
//  functions are the inverse transformation of the map that takes the unit vectors in x, y, z and maps them
//  to edge one, two, and the unit normal of the given triangle.
//
// remap_x_param: remapping of the x axis for the triangle
// remap_y_param: remapping of the y axis for the triangle
// remap_z_param: remapping of the z axis for the triangle
// edge_function: union of three vertical capsules of radius zero and height equal to the length of the
//  triangle edge it corresponds to, oriented in space at the edge.
fn signed_distance_function_triangle_helper(remap_x_param, remap_y_param, remap_z_param, edge_function) {
    let planes = [
        -x,
        -y,
        (x + y - 1.0),
    ];

    // Iterate over the planes and count what region we are in.
    let region_marker = if_nonnegative_else(planes[0], 1, 0);
    for i in 1..planes.len() {
        region_marker += if_nonnegative_else(planes[i], 1, 0);
    }

    // If the region_marker equal to 1 or 2 (greater than 0.5).
    if_nonnegative_else(remap(region_marker - 0.5, remap_x_param, remap_y_param, remap_z_param),
        // We do not remap the edge function, as it would stretch the cylinders and spheres, ruining the SDF property.
        edge_function,
    // Else: we are in the positive region.
    remap(abs(z), remap_x_param, remap_y_param, remap_z_param)
    )
}

// A tetrahedron formed from the origin and unit vectors on the x, y, z axis, which returns 0 inside and 1 outside.
fn bounded_unit_tetrahedron() {
    if_nonnegative_else(x,
        if_nonnegative_else(y,
            if_nonnegative_else(z,
                if_nonnegative_else(-x - y - z + 1.0,
                    0,
                // Else
                1),
            // Else
            1),
        // Else
        1),
    // Else
    1)
}

// Construct a signed distance function from a list of bounded tetrahedrons inside the volume and a list of surface triangles.
fn sdf_mesh(tetrahedrons, triangles) {
    let sdf_base = triangles[0];
    for i in 1..triangles.len() {
        sdf_base = min(sdf_base, triangles[i]);
    }

    // Determine what region we are in.
    let region = tetrahedrons[0];
    for i in 1..tetrahedrons.len() {
        region *= tetrahedrons[i];
    }

    // If we are inside a single tetrahedron then region = 0, else region = 1.
    if_nonzero_else(region, sdf_base, -sdf_base)
}

let tetrahedrons = [
    remap(bounded_unit_tetrahedron(), (x - -1) * -0.5 + (y - -1) * 0.5 + (z - -1) * -0.5, (x - -1) * -0 + (y - -1) * 0 + (z - -1) * 0.5, (x - -1) * 0.5 + (y - -1) * 0 + (z - -1) * 0),
    remap(bounded_unit_tetrahedron(), (x - -1) * -0.5 + (y - -1) * 0.5 + (z - -1) * 0, (x - -1) * -0 + (y - -1) * -0.5 + (z - -1) * 0.5, (x - -1) * 0.5 + (y - -1) * 0 + (z - -1) * 0),
    remap(bounded_unit_tetrahedron(), (x - 1) * 0 + (y - -1) * 0 + (z - 1) * -0.5, (x - 1) * -0.5 + (y - -1) * 0 + (z - 1) * 0.5, (x - 1) * 0 + (y - -1) * 0.5 + (z - 1) * 0),
    remap(bounded_unit_tetrahedron(), (x - -1) * -0.5 + (y - -1) * 0.5 + (z - -1) * 0, (x - -1) * 0.5 + (y - -1) * -0.5 + (z - -1) * 0.5, (x - -1) * 0 + (y - -1) * 0.5 + (z - -1) * -0.5),
    remap(bounded_unit_tetrahedron(), (x - 1) * -0.5 + (y - -1) * 0 + (z - 1) * 0, (x - 1) * -0 + (y - -1) * 0.5 + (z - 1) * 0, (x - 1) * 0.5 + (y - -1) * 0 + (z - 1) * -0.5),
    remap(bounded_unit_tetrahedron(), (x - 1) * -0.5 + (y - 1) * 0 + (z - 1) * -0, (x - 1) * -0 + (y - 1) * 0.5 + (z - 1) * -0.5, (x - 1) * 0.5 + (y - 1) * -0.5 + (z - 1) * 0),
];

let triangles = [
    signed_distance_function_triangle_helper((x - 1) * 0 + (y - 1) * 0 + (z - -1) * 0.5, (x - 1) * -0.5 + (y - 1) * -0 + (z - -1) * -0.5, (x - 1) * 0 + (y - 1) * -1 + (z - -1) * 0, min(remap(vertical_capsule(0, 2.8284271247461903), (x - 1) * 0.7071067811865476 + (y - 1) * 0 + (z - -1) * 0.7071067811865475, (x - 1) * -0 + (y - 1) * 1 + (z - -1) * 0, (x - 1) * -0.7071067811865475 + (y - 1) * -0 + (z - -1) * 0.7071067811865476), min(remap(vertical_capsule(0, 2), (x - 1) * 0.00000000000000006123233995736766 + (y - 1) * 0 + (z - -1) * 1, (x - 1) * -0 + (y - 1) * 1 + (z - -1) * 0, (x - 1) * -1 + (y - 1) * -0 + (z - -1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - 1) * 0 + (z - 1) * 0, (x - -1) * 0 + (y - 1) * 1 + (z - 1) * 0, (x - -1) * 0 + (y - 1) * 0 + (z - 1) * -1)))),
    signed_distance_function_triangle_helper((x - -1) * 0 + (y - 1) * -0.5 + (z - -1) * 0, (x - -1) * 0.5 + (y - 1) * 0 + (z - -1) * 0, (x - -1) * -0 + (y - 1) * 0 + (z - -1) * 1, min(remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - 1) * 0 + (z - -1) * -0, (x - -1) * 0 + (y - 1) * 0.00000000000000006123233995736766 + (z - -1) * 1, (x - -1) * 0 + (y - 1) * -1 + (z - -1) * 0.00000000000000006123233995736766), min(remap(vertical_capsule(0, 2), (x - -1) * 0.00000000000000006123233995736766 + (y - 1) * 0 + (z - -1) * -1, (x - -1) * 0 + (y - 1) * 1 + (z - -1) * 0, (x - -1) * 1 + (y - 1) * 0 + (z - -1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2.8284271247461903), (x - -1) * 0.5000000000000001 + (y - -1) * -0.5 + (z - -1) * -0.7071067811865476, (x - -1) * -0.5 + (y - -1) * 0.5000000000000001 + (z - -1) * -0.7071067811865476, (x - -1) * 0.7071067811865476 + (y - -1) * 0.7071067811865476 + (z - -1) * 0.00000000000000006123233995736766)))),
    signed_distance_function_triangle_helper((x - -1) * 0 + (y - 1) * 0 + (z - -1) * 0.5, (x - -1) * 0 + (y - 1) * -0.5 + (z - -1) * 0, (x - -1) * 1 + (y - 1) * 0 + (z - -1) * -0, min(remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - 1) * 0 + (z - -1) * 0, (x - -1) * 0 + (y - 1) * 1 + (z - -1) * 0, (x - -1) * 0 + (y - 1) * 0 + (z - -1) * 1), min(remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - 1) * 0 + (z - -1) * -0, (x - -1) * 0 + (y - 1) * 0.00000000000000006123233995736766 + (z - -1) * 1, (x - -1) * 0 + (y - 1) * -1 + (z - -1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2.8284271247461903), (x - -1) * 1 + (y - 1) * 0 + (z - 1) * -0, (x - -1) * 0 + (y - 1) * -0.7071067811865475 + (z - 1) * 0.7071067811865476, (x - -1) * 0 + (y - 1) * -0.7071067811865476 + (z - 1) * -0.7071067811865475)))),
    signed_distance_function_triangle_helper((x - 1) * -0 + (y - 1) * -0.5 + (z - 1) * 0, (x - 1) * -0.5 + (y - 1) * 0.5 + (z - 1) * 0, (x - 1) * -0 + (y - 1) * 0 + (z - 1) * -1, min(remap(vertical_capsule(0, 2.8284271247461903), (x - 1) * 0.5000000000000001 + (y - 1) * -0.5 + (z - 1) * 0.7071067811865476, (x - 1) * -0.5 + (y - 1) * 0.5000000000000001 + (z - 1) * 0.7071067811865476, (x - 1) * -0.7071067811865476 + (y - 1) * -0.7071067811865476 + (z - 1) * 0.00000000000000006123233995736766), min(remap(vertical_capsule(0, 2), (x - 1) * 0.00000000000000006123233995736766 + (y - 1) * 0 + (z - 1) * 1, (x - 1) * -0 + (y - 1) * 1 + (z - 1) * 0, (x - 1) * -1 + (y - 1) * -0 + (z - 1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - -1) * 0 + (z - 1) * -0, (x - -1) * -0 + (y - -1) * 0.00000000000000006123233995736766 + (z - 1) * -1, (x - -1) * 0 + (y - -1) * 1 + (z - 1) * 0.00000000000000006123233995736766)))),
    signed_distance_function_triangle_helper((x - -1) * 0 + (y - 1) * -0.5 + (z - 1) * 0.5, (x - -1) * 0 + (y - 1) * 0 + (z - 1) * -0.5, (x - -1) * 1 + (y - 1) * 0 + (z - 1) * 0, min(remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - 1) * 0 + (z - 1) * -0, (x - -1) * 0 + (y - 1) * 0.00000000000000006123233995736766 + (z - 1) * 1, (x - -1) * 0 + (y - 1) * -1 + (z - 1) * 0.00000000000000006123233995736766), min(remap(vertical_capsule(0, 2.8284271247461903), (x - -1) * 1 + (y - 1) * 0 + (z - 1) * -0, (x - -1) * 0 + (y - 1) * -0.7071067811865475 + (z - 1) * 0.7071067811865476, (x - -1) * 0 + (y - 1) * -0.7071067811865476 + (z - 1) * -0.7071067811865475), remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - -1) * 0 + (z - 1) * 0, (x - -1) * 0 + (y - -1) * 1 + (z - 1) * 0, (x - -1) * 0 + (y - -1) * 0 + (z - 1) * -1)))),
    signed_distance_function_triangle_helper((x - 1) * 0.5 + (y - 1) * -0.5 + (z - 1) * 0, (x - 1) * -0.5 + (y - 1) * -0 + (z - 1) * 0, (x - 1) * 0 + (y - 1) * -0 + (z - 1) * -1, min(remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - 1) * 0 + (z - 1) * -0, (x - 1) * 0 + (y - 1) * 0.00000000000000006123233995736766 + (z - 1) * 1, (x - 1) * 0 + (y - 1) * -1 + (z - 1) * 0.00000000000000006123233995736766), min(remap(vertical_capsule(0, 2.8284271247461903), (x - 1) * 0.5000000000000001 + (y - 1) * -0.5 + (z - 1) * 0.7071067811865476, (x - 1) * -0.5 + (y - 1) * 0.5000000000000001 + (z - 1) * 0.7071067811865476, (x - 1) * -0.7071067811865476 + (y - 1) * -0.7071067811865476 + (z - 1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2), (x - 1) * 0.00000000000000006123233995736766 + (y - -1) * 0 + (z - 1) * 1, (x - 1) * -0 + (y - -1) * 1 + (z - 1) * 0, (x - 1) * -1 + (y - -1) * -0 + (z - 1) * 0.00000000000000006123233995736766)))),
    signed_distance_function_triangle_helper((x - -1) * -0.5 + (y - -1) * 0 + (z - -1) * 0.5, (x - -1) * 0.5 + (y - -1) * 0 + (z - -1) * 0, (x - -1) * 0 + (y - -1) * 1 + (z - -1) * 0, min(remap(vertical_capsule(0, 2), (x - -1) * 1 + (y - -1) * 0 + (z - -1) * 0, (x - -1) * 0 + (y - -1) * 1 + (z - -1) * 0, (x - -1) * 0 + (y - -1) * 0 + (z - -1) * 1), min(remap(vertical_capsule(0, 2.8284271247461903), (x - -1) * 0.7071067811865476 + (y - -1) * 0 + (z - -1) * -0.7071067811865475, (x - -1) * 0 + (y - -1) * 1 + (z - -1) * 0, (x - -1) * 0.7071067811865475 + (y - -1) * 0 + (z - -1) * 0.7071067811865476), remap(vertical_capsule(0, 2), (x - -1) * 0.00000000000000006123233995736766 + (y - -1) * 0 + (z - 1) * -1, (x - -1) * 0 + (y - -1) * 1 + (z - 1) * 0, (x - -1) * 1 + (y - -1) * 0 + (z - 1) * 0.00000000000000006123233995736766)))),
    signed_distance_function_triangle_helper((x - 1) * 0.5 + (y - 1) * 0 + (z - -1) * 0.5, (x - 1) * -0.5 + (y - 1) * 0 + (z - -1) * 0, (x - 1) * 0 + (y - 1) * -1 + (z - -1) * 0, min(remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - 1) * 0 + (z - -1) * 0, (x - 1) * 0 + (y - 1) * 1 + (z - -1) * 0, (x - 1) * 0 + (y - 1) * 0 + (z - -1) * 1), min(remap(vertical_capsule(0, 2.8284271247461903), (x - 1) * 0.7071067811865476 + (y - 1) * 0 + (z - -1) * 0.7071067811865475, (x - 1) * -0 + (y - 1) * 1 + (z - -1) * 0, (x - 1) * -0.7071067811865475 + (y - 1) * -0 + (z - -1) * 0.7071067811865476), remap(vertical_capsule(0, 2), (x - 1) * 0.00000000000000006123233995736766 + (y - 1) * 0 + (z - 1) * 1, (x - 1) * -0 + (y - 1) * 1 + (z - 1) * 0, (x - 1) * -1 + (y - 1) * -0 + (z - 1) * 0.00000000000000006123233995736766)))),
    signed_distance_function_triangle_helper((x - 1) * 0 + (y - -1) * -0.5 + (z - -1) * 0.5, (x - 1) * -0 + (y - -1) * 0.5 + (z - -1) * -0, (x - 1) * -1 + (y - -1) * 0 + (z - -1) * 0, min(remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - -1) * 0 + (z - -1) * 0, (x - 1) * 0 + (y - -1) * 1 + (z - -1) * 0, (x - 1) * 0 + (y - -1) * 0 + (z - -1) * 1), min(remap(vertical_capsule(0, 2.8284271247461903), (x - 1) * 1 + (y - -1) * 0 + (z - -1) * -0, (x - 1) * -0 + (y - -1) * 0.7071067811865476 + (z - -1) * -0.7071067811865475, (x - 1) * 0 + (y - -1) * 0.7071067811865475 + (z - -1) * 0.7071067811865476), remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - -1) * 0 + (z - 1) * -0, (x - 1) * -0 + (y - -1) * 0.00000000000000006123233995736766 + (z - 1) * -1, (x - 1) * 0 + (y - -1) * 1 + (z - 1) * 0.00000000000000006123233995736766)))),
    signed_distance_function_triangle_helper((x - -1) * 0 + (y - -1) * 0 + (z - -1) * 0.5, (x - -1) * 0.5 + (y - -1) * 0 + (z - -1) * -0.5, (x - -1) * 0 + (y - -1) * 1 + (z - -1) * 0, min(remap(vertical_capsule(0, 2.8284271247461903), (x - -1) * 0.7071067811865476 + (y - -1) * 0 + (z - -1) * -0.7071067811865475, (x - -1) * 0 + (y - -1) * 1 + (z - -1) * 0, (x - -1) * 0.7071067811865475 + (y - -1) * 0 + (z - -1) * 0.7071067811865476), min(remap(vertical_capsule(0, 2), (x - -1) * 0.00000000000000006123233995736766 + (y - -1) * 0 + (z - -1) * -1, (x - -1) * 0 + (y - -1) * 1 + (z - -1) * 0, (x - -1) * 1 + (y - -1) * 0 + (z - -1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - -1) * 0 + (z - 1) * 0, (x - 1) * 0 + (y - -1) * 1 + (z - 1) * 0, (x - 1) * 0 + (y - -1) * 0 + (z - 1) * -1)))),
    signed_distance_function_triangle_helper((x - 1) * 0 + (y - -1) * 0.5 + (z - -1) * 0, (x - 1) * -0.5 + (y - -1) * 0 + (z - -1) * 0, (x - 1) * 0 + (y - -1) * -0 + (z - -1) * 1, min(remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - -1) * 0 + (z - -1) * -0, (x - 1) * -0 + (y - -1) * 0.00000000000000006123233995736766 + (z - -1) * -1, (x - 1) * 0 + (y - -1) * 1 + (z - -1) * 0.00000000000000006123233995736766), min(remap(vertical_capsule(0, 2), (x - 1) * 0.00000000000000006123233995736766 + (y - -1) * 0 + (z - -1) * 1, (x - 1) * -0 + (y - -1) * 1 + (z - -1) * 0, (x - 1) * -1 + (y - -1) * -0 + (z - -1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2.8284271247461903), (x - 1) * 0.5000000000000001 + (y - 1) * -0.5 + (z - -1) * 0.7071067811865476, (x - 1) * -0.5 + (y - 1) * 0.5000000000000001 + (z - -1) * 0.7071067811865476, (x - 1) * -0.7071067811865476 + (y - 1) * -0.7071067811865476 + (z - -1) * 0.00000000000000006123233995736766)))),
    signed_distance_function_triangle_helper((x - 1) * 0 + (y - -1) * -0 + (z - -1) * 0.5, (x - 1) * -0 + (y - -1) * 0.5 + (z - -1) * -0.5, (x - 1) * -1 + (y - -1) * 0 + (z - -1) * 0, min(remap(vertical_capsule(0, 2.8284271247461903), (x - 1) * 1 + (y - -1) * 0 + (z - -1) * -0, (x - 1) * -0 + (y - -1) * 0.7071067811865476 + (z - -1) * -0.7071067811865475, (x - 1) * 0 + (y - -1) * 0.7071067811865475 + (z - -1) * 0.7071067811865476), min(remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - -1) * 0 + (z - -1) * -0, (x - 1) * -0 + (y - -1) * 0.00000000000000006123233995736766 + (z - -1) * -1, (x - 1) * 0 + (y - -1) * 1 + (z - -1) * 0.00000000000000006123233995736766), remap(vertical_capsule(0, 2), (x - 1) * 1 + (y - 1) * 0 + (z - 1) * 0, (x - 1) * 0 + (y - 1) * 1 + (z - 1) * 0, (x - 1) * 0 + (y - 1) * 0 + (z - 1) * -1)))),
];

sdf_mesh(tetrahedrons, triangles)

Final Thoughts

I would like to be able to render these monstrosities in LaTeX or similar, so I can turn a 3DBenchy into math. I think that would be funny.