Implicit Surface
Threshold 0.5Resolution
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(); }
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]; } }
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; }
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); } }