Is there a library for Javascript distance functions?

After inserting SDFs into the three.js scene via shader (SDFs in the scene - raymarching ), I am now in the process of generating the SDFs directly as BufferGeometry. The solution that was temporarily integrated in three.js is too specialized and limited for me, see
How do you integrate Signed Distance Fields (SDF) into a basic three.js scene? - #2 by Mugen87
and
How do you integrate Signed Distance Fields (SDF) into a basic three.js scene? - #6 by hofk


This is already working:

I need the distance functions from Inigo Quilez
Inigo Quilez :: computer graphics, mathematics, shaders, fractals, demoscene and more
in the form of a closure.

Similar to the SDF-JS-Renderer

function Sphere(radius, shader) { 
    return function(p){
        const distance = p.norm() - radius;
        return new DistanceShaderPair(distance, shader );
    }
}

whereby no shader is returned.

So for example

function sdEllipsoid( r3 ) {
  return (p) => {
    const q1 = divV3( p, r3  );
    const k0 = lengthV3( q1 );
    const q2 = divV3( p, mulV3( r3, r3 ) );
    const k1 = lengthV3( q2 );
    return k0*( k0 - 1.0)/ k1;
  };
}

in my current notation with functions such as
const lengthV3 = ( { x: x, y: y, z: z } ) => ( Math.sqrt( x * x + y * y + z * z ) );

The adjustments require quite a lot of effort.

My question:

Are there already corresponding versions of the distance functions for Javascript somewhere?

2 Likes

Not that I’m aware of, but this is a great use case for using an LLM - just copy the whole page form IQ’s website and ask Chat GPT or other to transform it to the appropriate format.

You mean these functions ?

No, the complete list of shader compatible SDF functions according to Inigo Quilez, but transformed similar to the example function sdEllipsoid( r3 ) {... from the original article.

Oh sorry didn’t catch that.

I second what @Arthur said. :smiley:

Thing is, IQs sdfs are more than just straight math.. it’s more like.. an expression of his art.. as soon as you get something more complex than the most basic primitives, the implementations become more interpretive, and the skill of the creator shows through..
Things like.. the order of operations, magic constants to make them work/optimal etc.
So there isn’t just some platonic fundamental taxonomy of implementations.

1 Like

That’s true, but most things can be created by combining the primitives. This also easily becomes an artistic task.
I have already tried a few dines out of curiosity.

1 Like

I tried it, but with my free version I only got a few new examples with some clever explanations in addition to the examples provided as a template.

The amount of code was probably too big. I’ll try it soon with small code snippets, bit by bit. At least that will save me from my constant mistakes.


//..... define SDF ......................................
let SDF;
 
const sdf1 = sdSphere( center, r );
const sdf2 = sdSphere( { x: 0.5, y: 0.8, z: 0.5 }, 0.7 );
const sdf3 = sdEllipsoid( { x: 0.5, y: 0.0, z: 0.5 }, { x: 1.5, y: 1.1, z: 1.2 } );

SDF = opSmoothSubtraction( sdf2, sdf3, 0.6 );
SDF = opUnion( SDF, sdf1 );
3 Likes

Is this from gkjohnson in that vein? It helped me a lot.

No, it is a special approach and is based on E. Hartmann’s triangulation algorithm, which he implemented in Pascal over 20 years ago.


(partly German)
Implizite Fläche – Wikipedia
https://www2.mathematik.tu-darmstadt.de/~ehartmann/cdgen0104.pdf
https://www2.mathematik.tu-darmstadt.de/~ehartmann/cdg0/cdg0n.pdf


I have already used this algorithm in a modified form several times.
See
GitHub - hofk/THREEi.js: three.js addon for triangulation of implicit surfaces and for forms with holes. The addon generates indexed BufferGeometries.

Single-branched geometry organically shaped in the web editor

Specific changes must be made for each application. The original algorithm requires an implicit function whose partial derivatives must be given, e.g.


// Example: implicit surface genus2:

const isf = ( x, y, z ) => ( 2*y*( y*y - 3*x*x )*( 1 - z*z ) + ( x*x + y*y )*( x*x + y*y ) - ( 9*z*z - 1 )*( 1 - z*z ) );// IMPLICIT SURFACE Function
const dx = ( x, y, z ) => ( -12*x*y*( 1 - z*z ) + 4*x*( x*x + y*y ) );// PARTIAL DERIVATE to x
const dy = ( x, y, z ) => ( 6*( y*y - x*x )*( 1 - z*z ) + 4*y*( x*x + y*y ) );// PARTIAL DERIVATE to y
const dz = ( x, y, z ) => ( -4*y*( y*y - 3*x*x )*z + 36*z*z*z - 20*z );// PARTIAL DERIVATE to z

I still have open problems with the adjustment to SDFs.
For edges with external angles of 270° or more, the connection to the surface is no longer clear.
Such angles also occur during subtraction and there are no clear tangents at the sharp cutting edges.

I still have to come up with something.
I hope that these problems can be solved somehow. :thinking:

I can’t yet assess whether what I’m doing here is suitable for that. So far, I’m interested in determining volume for real buoyancy. I could store the triangles that intersect the voxel in buffers for each voxel and then calculate the exact distances when a ray moves through the voxel. But these are just ideas so far. I’m busy with other things.

A small experiment on determining the normals of SDFs. I did it because I’m having errors with the normals in my project, and it’s difficult to debug. The test shows that the functions used are fine. The error I’m looking for is apparently well hidden in the overall algorithm.

It drags on. :face_with_spiral_eyes:

1 Like