Implicit Surface

Threshold 0.5
Resolution
Marching cube function :
function marchingcube(){
    var vertices = [];
	var faces = [];
	var interpolations = {};
	var grid = {};
	
	var values = [];
    
    for ( var x = -res; x < res; x ++ ) {
        for ( var y = -res; y < res; y ++ ) {
            for ( var z = -res; z < res; z ++ ) {
                var bitwise = 0;
                for(var c = 0; c < cube.length; c++){
                    values[c] = calculateGrid(x+cube[c][0],y+cube[c][1],z+cube[c][2],res,grid,spheres);
                    if(values[c]<seuil){
                        bitwise |= (1 << c);
                    }
                }
                //treat bitwise
                if(bitwise > 0 && bitwise < 255){
                    var vect = [];
                    
                    for(var c = 0; c < edges.length; c++){
                        if((THREE.edgeTable[bitwise] & 1 << c) > 0)
                            vect[c] = interpolate(x,y,z,c,vertices,values,interpolations);
                    }
                    var i = 0;
                    while ( THREE.triTable[bitwise][i] != -1 && i<16 ) {
                        faces.push(new THREE.Face3(vect[THREE.triTable[bitwise][i]], vect[THREE.triTable[bitwise][i+1]], vect[THREE.triTable[bitwise][i+2]]));
                		i += 3;
                	}
                }
            }
        }
    }
    
    surface.vertices =  vertices;
    surface.faces = faces;
    
    surface.computeVertexNormals();
}
Interpolate :
    function interpolate(x,y,z,c,vertices,gridValues, interpolations){
    var x1 = Math.max(x+cube[interpol[c][0]][0],x+cube[interpol[c][1]][0]);
    var x2 = Math.min(x+cube[interpol[c][0]][0],x+cube[interpol[c][1]][0]);
    var y1 = Math.max(y+cube[interpol[c][0]][1],y+cube[interpol[c][1]][1]);
    var y2 = Math.min(y+cube[interpol[c][0]][1],y+cube[interpol[c][1]][1]);
    var z1 = Math.max(z+cube[interpol[c][0]][2],z+cube[interpol[c][1]][2]);
    var z2 = Math.min(z+cube[interpol[c][0]][2],z+cube[interpol[c][1]][2]);
    if(interpolations[x1+"_"+y1+"_"+z1+"_"+x2+"_"+y2+"_"+z2]==undefined){
        var index = vertices.length;
        var vect1 = new THREE.Vector3(x/res+cube[interpol[c][0]][0]/res,y/res+cube[interpol[c][0]][1]/res,z/res+cube[interpol[c][0]][2]/res)
        var vect2 = new THREE.Vector3(x/res+cube[interpol[c][1]][0]/res,y/res+cube[interpol[c][1]][1]/res,z/res+cube[interpol[c][1]][2]/res)
        var factor = (seuil - gridValues[interpol[c][0]])/(gridValues[interpol[c][1]] - gridValues[interpol[c][0]]);
        var vect = vect1.add(vect2.sub(vect1).multiplyScalar(factor));
        vertices.push(vect);
        interpolations[x1+"_"+y1+"_"+z1+"_"+x2+"_"+y2+"_"+z2] = index;
        return index;
    }
    else{
        return interpolations[x1+"_"+y1+"_"+z1+"_"+x2+"_"+y2+"_"+z2];
    }
}
Calculate grid :
    function calculateGrid(x,y,z,res,grid,objects){
    //Slower
    /*if(grid[x+"_"+y+"_"+z]==undefined){
            var value = 0;
            for(var k in objects){
                value += objects[k].distance(x/res,y/res,z/res);
            }
            grid[x+"_"+y+"_"+z] = value;
            return value;
        }
        else
            return grid[x+"_"+y+"_"+z];*/
    var value = 0;
    for(var k in objects){
        value += objects[k].distance(x/res,y/res,z/res);
    }
    return value;
}
Metaball approximation :
class sphere{
constructor(x, y, z, r){
    this.x = x; 
    this.y = y;
    this.z = z;
    this.initial_x = x;
    this.initial_y = y;
    this.initial_z = z;
    this.r = r;
}

distance(x,y,z){
    return Math.min(Math.max(1 - ((x - this.x)*(x - this.x) + (y - this.y)*(y - this.y) + (z - this.z)*(z - this.z))/this.r, 0),1);
}
}