Triangulation of SDFs


Note
Online generation of SDF geometries is now available. 05/28/2025

Generation of SDFGeometry online



After creating SDFs via three.js material and shader, (SDFs in the scene - raymarching )
I am now working on the triangulation of the SDFs to efficiently transfer SDFs into BufferGeometry.

Creating really sharp edges is a problem that has not yet been solved.
All attempts to change the extremely complicated triangulation algorithm have so far been unsuccessful.

Some examples can be seen in the question post .
(Is there a library for Javascript distance functions?)

The functions have changed somewhat since then.

More examples:

const sdf1 = sdSphere( );
const sdf2 = sdSphere( 0.6, { x: 2.0, y: 0.0, z: -0.5 } );
const sdf3 = sdTorus( );
SDF = opSmoothUnion( sdf1, sdf2, 0.6 );
SDF = opSmoothUnion( SDF, sdf3, 0.3 );

const sdf1 = sdSphere( 1.6, { x: 2.0, y: 0.0, z: -0.5 } );
const sdf2 = sdRoundBox(  { x: 2.5, y: 0.4, z: 0.9 }, 0.0, { x: 0.0, y: -0.4, z: 0.0 } );
const sdf3 = sdTorus( 0.8, 0.3, { x: -0.8, y: -0.1, z: 0.0 } );
SDF = opSmoothSubtraction( sdf1, sdf2, 0.2 );
SDF = opSmoothSubtraction( SDF, sdf3, 0.2 );

const sdf1 = sdCapsule( 0.4 );
const sdf2 = sdRoundBox( { x: 2.5, y: 0.2, z: 1.2 } ) ;
SDF = opSmoothSubtraction( sdf1, sdf2, 0.2 );

const sdf1 = sdRoundBox( { x: 2, y: 0.2, z: 1 }, 0.05 );
const sdf2 = sdRoundBox( { x: 0.2, y: 2, z: 1 }, 0.05 );
const sdf3 = sdCapsule( 0.25, { x:  1, y: -1, z: 0 }, { x:  1, y: 1, z: 0 } );
const sdf4 = sdCapsule( 0.25, { x: -1, y: -1, z: 0 }, { x: -1, y: 1, z: 0 } );
const sdfA = opSmoothUnion( sdf1, sdf2, 0.05);
const sdfB = opUnion( sdf3, sdf4 );
SDF = opSmoothSubtraction( sdfB, sdfA, 0.05 );

UPDATE

All attempts to create the sharp edges by running something in addition to the core algorithm must fail. I am now sure that I have to change the core of E. Hartmann’s algorithm to achieve the goal.

But before that, I will create a resource to generate SDFs meshes online. There is a lot of detailed work to be done.

5 Likes

+ some user docs

1 Like

Yes, of course, even if it makes work. About as detailed as there, for example: Single-branched geometry organically shaped in the web editor

1 Like

This is cool!

I’m still experimenting with the designations for a clear and not too verbose description of the properties.


center

radius: r , radius btm radius top: rb rt, radius3: rxyz

width, height, dept: whd

(box) frame : f

great radius R ( Torus, Link)

angle arc ang ??

rotation x y z: rotx roty rotz (DEG)

smooth: s (edge, operations)


{
  "Settings": { "sideLength": 0.07 },
  "BoxA": { "type": "box", "whd": { "x": 1.9, "y": 1.2, "z": 0.6 }, "center": { "x": -0.25, "y": -0.2, "z": -1.1 }, "rotx": 22.5, "rotz": 45.0, "s": 0.08 }
}

1 Like

What about extracting properties directly from THREE.Mesh? The parameters properties of geometries contain the construction parameters (e.g. sizes); and the mesh itself could provide rotation, position and additional scale. There is no need to support all possible cases, just the basic geometries in their traditional use cases.

So, you could just pass a scene (or a group) to your SDFizer, and it will make the rest. An important thing to decide is how to indicate subtractions, unions and so on. It could be a custom flag in a mesh whether it is “negative space” or not; or it could be something else.

↑
This is just a fantasy.

1 Like

The parameters of the basic geometries and Object3D(Mesh) are usually parameters in a fixed order. The advantage is that only values have to be noted, the disadvantage is that you have to know and adhere to the sequence. Material, on the other hand, is a parameter object.

Inigo Quilez’s notation is less consistent in terms of content, but uses the particularly efficient possibilities of operations in GLSL, where parameters are summarized in vectors.

To upload to the server, I need a JSON in which the user must specify all SDF primitives to be used with additional properties such as center, rotation, softness, etc. as well as their combination to SDF operations. From this, an SDF object is first created on the server, using functions adapted from GLSL. Unfortunately, other languages do not offer these efficient vector operations. The triangulation is then performed. The calculated indices, positions and normals are returned and the mesh is generated locally.

Since only relatively few properties are required, I think that an abbreviated notation (unlike with three.js material) is appropriate and simplifies the creation of the JSON.

The above example would look like this if written in more detail:

{
  "Settings": { "sideLength": 0.07 },
  "Box": { "type": "box", "width_height_depth": { "x": 1.9, "y": 1.2, "z": 0.6 }, "center": { "x": -0.25, "y": -0.2, "z": -1.1 }, "rotationX": 22.5, "rotationZ": 45.0, "smooth": 0.08 }
}

There is also the quaternion property, which is used to generate a rotation very easily.

{
  "Settings": { "sideLength": 0.07 },
  "BoxQuat": { "type": "box", "whd": { "x": 1.2, "y": 1.9, "z": 0.7 },  "quat": { "w": 0.914,  "x": 0.0, "y": -0.266, "z": -0.307 },  "s": 0.08 }
}

The appropriate values can be taken from my visualization of the quaternion, for example. quaternion