A javascript implementation of the Marching cubes algorithm...
1- Description
TODO

Fig.1: The originally published 15 cube configurations. By Jmtrivial (License GPL, [Wikipedia])
2- The script
In the last update of ImageJ (version 1.49k), it is now possible to call multiple files in a script.
Note: [2018/04/03] The code is updated for ES6 (2015+) JavaScript
However, this feature is only available for java Sun/Oracle (it does not seem to work with OpenJDK). In this case, copy and paste the contents of the two scripts marchingCubes_Cube.js and marchingCubes_Slice.js in the main script.
This - long - script is divided in three parts:
- the class Cube for computing the configuration case and vertices along the edges.
- the class Slice involved in the storage of temporary cubes
- the main script marchingCubes.js
class Cube
+++ Javascript: MarchingCubes_Cube.js +++
+++ End of Script: +++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Marching Cubes | |
// Jean-Christophe Taveau | |
// http://crazybiocomputing.blogspot.com | |
// Nov 2014 | |
// class Cube | |
function Cube(x,y,z,size) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.size = size; | |
this.voxels = []; | |
this.edges=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]; | |
this.key=0; | |
} | |
Cube.prototype.getVertex = function (index) { | |
switch (index) { | |
case 0: | |
return {'x':this.x, 'y':this.y, 'z':this.z, 'voxel':this.voxels[0] }; // v0 | |
case 1: | |
return {'x':this.x+this.size, 'y':this.y, 'z':this.z, 'voxel':this.voxels[1] }; // v1 | |
case 2: | |
return {'x':this.x+this.size, 'y':this.y+this.size, 'z':this.z, 'voxel':this.voxels[2] }; // v2 | |
case 3: | |
return {'x':this.x, 'y':this.y+this.size, 'z':this.z, 'voxel':this.voxels[3] }; // v3 | |
case 4: | |
return {'x':this.x, 'y':this.y, 'z':this.z+this.size, 'voxel':this.voxels[4] }; // v4 | |
case 5: | |
return {'x':this.x+this.size, 'y':this.y, 'z':this.z+this.size, 'voxel':this.voxels[5] }; // v5 | |
case 6: | |
return {'x':this.x+this.size, 'y':this.y+this.size, 'z':this.z+this.size, 'voxel':this.voxels[6] }; // v6 | |
case 7: | |
return {'x':this.x, 'y':this.y+this.size, 'z':this.z+this.size, 'voxel':this.voxels[7] }; // v7 | |
} | |
} | |
Cube.prototype.setVoxels = function (stack) { | |
this.voxels[0]=stack.getVoxel(x ,y ,z ); // v0 | |
this.voxels[1]=stack.getVoxel(x+this.size,y ,z ); // v1 | |
this.voxels[2]=stack.getVoxel(x+this.size,y+this.size,z ); // v2 | |
this.voxels[3]=stack.getVoxel(x ,y+this.size,z ); // v3 | |
this.voxels[4]=stack.getVoxel(x ,y ,z+this.size); // v4 | |
this.voxels[5]=stack.getVoxel(x+this.size,y ,z+this.size); // v5 | |
this.voxels[6]=stack.getVoxel(x+this.size,y+this.size,z+this.size); // v6 | |
this.voxels[7]=stack.getVoxel(x ,y+this.size,z+this.size); // v7 | |
} | |
Cube.prototype.calcKey = function (threshold) { | |
var keystr = ''; | |
keystr +=(this.voxels[7] > threshold)?"1":"0"; | |
keystr +=(this.voxels[6] > threshold)?"1":"0"; | |
keystr +=(this.voxels[5] > threshold)?"1":"0"; | |
keystr +=(this.voxels[4] > threshold)?"1":"0"; | |
keystr +=(this.voxels[3] > threshold)?"1":"0"; | |
keystr +=(this.voxels[2] > threshold)?"1":"0"; | |
keystr +=(this.voxels[1] > threshold)?"1":"0"; | |
keystr +=(this.voxels[0] > threshold)?"1":"0"; | |
this.key = parseInt(keystr,2); | |
} | |
Cube.prototype.toString = function () { | |
var str='['; | |
for (var i=0;i<12;i++) str+=(this.edges[i]+"; "); | |
return ("Cube["+this.key+"]=(" + this.x +" "+this.y+" "+this.z +") "+str+"]"); | |
} |
+++ End of Script: +++
class Slice
+++ Javascript: MarchingCubes_Slice.js +++
+++ End of Script +++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Marching Cubes | |
// Jean-Christophe Taveau | |
// http://crazybiocomputing.blogspot.com | |
// Nov 2014 | |
// class Slice | |
function Slice(cubes_per_row, cubes_per_column) { | |
this.cubes = []; | |
this.count = 0; | |
this.w = cubes_per_row; | |
this.h = cubes_per_column; | |
} | |
Slice.prototype.reset_count = function () { | |
this.count=0; | |
} | |
Slice.prototype.push = function (a_cube) { | |
this.cubes[this.count++] = a_cube; | |
} | |
Slice.prototype.previous = function () { | |
//IJ.log('index previous '+this.count+' '+(this.count - 1) ); | |
return this.cubes[this.count - 1]; | |
} | |
Slice.prototype.above = function () { | |
//IJ.log('index above'+this.count+' '+(this.count - this.w) ); | |
return this.cubes[this.count - this.w]; | |
} | |
Slice.prototype.back = function () { | |
//IJ.log('index back'+this.count ); | |
return this.cubes[this.count]; | |
} |
+++ End of Script +++
Main Script
+++ Javascript: MarchingCubes_Slice.js +++
+++ End of Script +++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Marching Cubes | |
// Jean-Christophe Taveau | |
// http://crazybiocomputing.blogspot.com | |
// Nov 2014 | |
// Updated 2014/11/25: Bug fixes | |
// Updated 2018/04/03 - Upgrade ES6 + Bug Fixes | |
const require = load; | |
// C L A S S | |
// requires ImageJ 1.51u and later + java Oracle | |
// Nashorn JavaScript Engine | |
// Modify the path to fit where you store the two other files | |
require('./plugins/0Homemade/marchingCubes_Cube.js'); | |
require('./plugins/0Homemade/marchingCubes_Slice.js'); | |
// triangles to be drawn in each case | |
const triangles=[ | |
[], | |
[0,8,3], | |
[0,1,9], | |
[1,8,3,9,8,1], | |
[1,2,11], | |
[0,8,3,1,2,11], | |
[9,2,11,0,2,9], | |
[2,8,3,2,11,8,11,9,8], | |
[3,10,2], | |
[0,10,2,8,10,0], | |
[1,9,0,2,3,10], | |
[1,10,2,1,9,10,9,8,10], | |
[3,11,1,10,11,3], | |
[0,11,1,0,8,11,8,10,11], | |
[3,9,0,3,10,9,10,11,9], | |
[9,8,11,11,8,10], | |
[4,7,8], | |
[4,3,0,7,3,4], | |
[0,1,9,8,4,7], | |
[4,1,9,4,7,1,7,3,1], | |
[1,2,11,8,4,7], | |
[3,4,7,3,0,4,1,2,11], | |
[9,2,11,9,0,2,8,4,7], | |
[2,11,9,2,9,7,2,7,3,7,9,4], | |
[8,4,7,3,10,2], | |
[10,4,7,10,2,4,2,0,4], | |
[9,0,1,8,4,7,2,3,10], | |
[4,7,10,9,4,10,9,10,2,9,2,1], | |
[3,11,1,3,10,11,7,8,4], | |
[1,10,11,1,4,10,1,0,4,7,10,4], | |
[4,7,8,9,0,10,9,10,11,10,0,3], | |
[4,7,10,4,10,9,9,10,11], | |
[9,5,4], | |
[9,5,4,0,8,3], | |
[0,5,4,1,5,0], | |
[8,5,4,8,3,5,3,1,5], | |
[1,2,11,9,5,4], | |
[3,0,8,1,2,11,4,9,5], | |
[5,2,11,5,4,2,4,0,2], | |
[2,11,5,3,2,5,3,5,4,3,4,8], | |
[9,5,4,2,3,10], | |
[0,10,2,0,8,10,4,9,5], | |
[0,5,4,0,1,5,2,3,10], | |
[2,1,5,2,5,8,2,8,10,4,8,5], | |
[11,3,10,11,1,3,9,5,4], | |
[4,9,5,0,8,1,8,11,1,8,10,11], | |
[5,4,0,5,0,10,5,10,11,10,0,3], | |
[5,4,8,5,8,11,11,8,10], | |
[9,7,8,5,7,9], | |
[9,3,0,9,5,3,5,7,3], | |
[0,7,8,0,1,7,1,5,7], | |
[1,5,3,3,5,7], | |
[9,7,8,9,5,7,11,1,2], | |
[11,1,2,9,5,0,5,3,0,5,7,3], | |
[8,0,2,8,2,5,8,5,7,11,5,2], | |
[2,11,5,2,5,3,3,5,7], | |
[7,9,5,7,8,9,3,10,2], | |
[9,5,7,9,7,2,9,2,0,2,7,10], | |
[2,3,10,0,1,8,1,7,8,1,5,7], | |
[10,2,1,10,1,7,7,1,5], | |
[9,5,8,8,5,7,11,1,3,11,3,10], | |
[5,7,0,5,0,9,7,10,0,1,0,11,10,11,0], | |
[10,11,0,10,0,3,11,5,0,8,0,7,5,7,0], | |
[10,11,5,7,10,5], | |
[11,6,5], | |
[0,8,3,5,11,6], | |
[9,0,1,5,11,6], | |
[1,8,3,1,9,8,5,11,6], | |
[1,6,5,2,6,1], | |
[1,6,5,1,2,6,3,0,8], | |
[9,6,5,9,0,6,0,2,6], | |
[5,9,8,5,8,2,5,2,6,3,2,8], | |
[2,3,10,11,6,5], | |
[10,0,8,10,2,0,11,6,5], | |
[0,1,9,2,3,10,5,11,6], | |
[5,11,6,1,9,2,9,10,2,9,8,10], | |
[6,3,10,6,5,3,5,1,3], | |
[0,8,10,0,10,5,0,5,1,5,10,6], | |
[3,10,6,0,3,6,0,6,5,0,5,9], | |
[6,5,9,6,9,10,10,9,8], | |
[5,11,6,4,7,8], | |
[4,3,0,4,7,3,6,5,11], | |
[1,9,0,5,11,6,8,4,7], | |
[11,6,5,1,9,7,1,7,3,7,9,4], | |
[6,1,2,6,5,1,4,7,8], | |
[1,2,5,5,2,6,3,0,4,3,4,7], | |
[8,4,7,9,0,5,0,6,5,0,2,6], | |
[7,3,9,7,9,4,3,2,9,5,9,6,2,6,9], | |
[3,10,2,7,8,4,11,6,5], | |
[5,11,6,4,7,2,4,2,0,2,7,10], | |
[0,1,9,4,7,8,2,3,10,5,11,6], | |
[9,2,1,9,10,2,9,4,10,7,10,4,5,11,6], | |
[8,4,7,3,10,5,3,5,1,5,10,6], | |
[5,1,10,5,10,6,1,0,10,7,10,4,0,4,10], | |
[0,5,9,0,6,5,0,3,6,10,6,3,8,4,7], | |
[6,5,9,6,9,10,4,7,9,7,10,9], | |
[11,4,9,6,4,11], | |
[4,11,6,4,9,11,0,8,3], | |
[11,0,1,11,6,0,6,4,0], | |
[8,3,1,8,1,6,8,6,4,6,1,11], | |
[1,4,9,1,2,4,2,6,4], | |
[3,0,8,1,2,9,2,4,9,2,6,4], | |
[0,2,4,4,2,6], | |
[8,3,2,8,2,4,4,2,6], | |
[11,4,9,11,6,4,10,2,3], | |
[0,8,2,2,8,10,4,9,11,4,11,6], | |
[3,10,2,0,1,6,0,6,4,6,1,11], | |
[6,4,1,6,1,11,4,8,1,2,1,10,8,10,1], | |
[9,6,4,9,3,6,9,1,3,10,6,3], | |
[8,10,1,8,1,0,10,6,1,9,1,4,6,4,1], | |
[3,10,6,3,6,0,0,6,4], | |
[6,4,8,10,6,8], | |
[7,11,6,7,8,11,8,9,11], | |
[0,7,3,0,11,7,0,9,11,6,7,11], | |
[11,6,7,1,11,7,1,7,8,1,8,0], | |
[11,6,7,11,7,1,1,7,3], | |
[1,2,6,1,6,8,1,8,9,8,6,7], | |
[2,6,9,2,9,1,6,7,9,0,9,3,7,3,9], | |
[7,8,0,7,0,6,6,0,2], | |
[7,3,2,6,7,2], | |
[2,3,10,11,6,8,11,8,9,8,6,7], | |
[2,0,7,2,7,10,0,9,7,6,7,11,9,11,7], | |
[1,8,0,1,7,8,1,11,7,6,7,11,2,3,10], | |
[10,2,1,10,1,7,11,6,1,6,7,1], | |
[8,9,6,8,6,7,9,1,6,10,6,3,1,3,6], | |
[0,9,1,10,6,7], | |
[7,8,0,7,0,6,3,10,0,10,6,0], | |
[7,10,6], | |
[7,6,10], | |
[3,0,8,10,7,6], | |
[0,1,9,10,7,6], | |
[8,1,9,8,3,1,10,7,6], | |
[11,1,2,6,10,7], | |
[1,2,11,3,0,8,6,10,7], | |
[2,9,0,2,11,9,6,10,7], | |
[6,10,7,2,11,3,11,8,3,11,9,8], | |
[7,2,3,6,2,7], | |
[7,0,8,7,6,0,6,2,0], | |
[2,7,6,2,3,7,0,1,9], | |
[1,6,2,1,8,6,1,9,8,8,7,6], | |
[11,7,6,11,1,7,1,3,7], | |
[11,7,6,1,7,11,1,8,7,1,0,8], | |
[0,3,7,0,7,11,0,11,9,6,11,7], | |
[7,6,11,7,11,8,8,11,9], | |
[6,8,4,10,8,6], | |
[3,6,10,3,0,6,0,4,6], | |
[8,6,10,8,4,6,9,0,1], | |
[9,4,6,9,6,3,9,3,1,10,3,6], | |
[6,8,4,6,10,8,2,11,1], | |
[1,2,11,3,0,10,0,6,10,0,4,6], | |
[4,10,8,4,6,10,0,2,9,2,11,9], | |
[11,9,3,11,3,2,9,4,3,10,3,6,4,6,3], | |
[8,2,3,8,4,2,4,6,2], | |
[0,4,2,4,6,2], | |
[1,9,0,2,3,4,2,4,6,4,3,8], | |
[1,9,4,1,4,2,2,4,6], | |
[8,1,3,8,6,1,8,4,6,6,11,1], | |
[11,1,0,11,0,6,6,0,4], | |
[4,6,3,4,3,8,6,11,3,0,3,9,11,9,3], | |
[11,9,4,6,11,4], | |
[4,9,5,7,6,10], | |
[0,8,3,4,9,5,10,7,6], | |
[5,0,1,5,4,0,7,6,10], | |
[10,7,6,8,3,4,3,5,4,3,1,5], | |
[9,5,4,11,1,2,7,6,10], | |
[6,10,7,1,2,11,0,8,3,4,9,5], | |
[7,6,10,5,4,11,4,2,11,4,0,2], | |
[3,4,8,3,5,4,3,2,5,11,5,2,10,7,6], | |
[7,2,3,7,6,2,5,4,9], | |
[9,5,4,0,8,6,0,6,2,6,8,7], | |
[3,6,2,3,7,6,1,5,0,5,4,0], | |
[6,2,8,6,8,7,2,1,8,4,8,5,1,5,8], | |
[9,5,4,11,1,6,1,7,6,1,3,7], | |
[1,6,11,1,7,6,1,0,7,8,7,0,9,5,4], | |
[4,0,11,4,11,5,0,3,11,6,11,7,3,7,11], | |
[7,6,11,7,11,8,5,4,11,4,8,11], | |
[6,9,5,6,10,9,10,8,9], | |
[3,6,10,0,6,3,0,5,6,0,9,5], | |
[0,10,8,0,5,10,0,1,5,5,6,10], | |
[6,10,3,6,3,5,5,3,1], | |
[1,2,11,9,5,10,9,10,8,10,5,6], | |
[0,10,3,0,6,10,0,9,6,5,6,9,1,2,11], | |
[10,8,5,10,5,6,8,0,5,11,5,2,0,2,5], | |
[6,10,3,6,3,5,2,11,3,11,5,3], | |
[5,8,9,5,2,8,5,6,2,3,8,2], | |
[9,5,6,9,6,0,0,6,2], | |
[1,5,8,1,8,0,5,6,8,3,8,2,6,2,8], | |
[1,5,6,2,1,6], | |
[1,3,6,1,6,11,3,8,6,5,6,9,8,9,6], | |
[11,1,0,11,0,6,9,5,0,5,6,0], | |
[0,3,8,5,6,11], | |
[11,5,6], | |
[10,5,11,7,5,10], | |
[10,5,11,10,7,5,8,3,0], | |
[5,10,7,5,11,10,1,9,0], | |
[11,7,5,11,10,7,9,8,1,8,3,1], | |
[10,1,2,10,7,1,7,5,1], | |
[0,8,3,1,2,7,1,7,5,7,2,10], | |
[9,7,5,9,2,7,9,0,2,2,10,7], | |
[7,5,2,7,2,10,5,9,2,3,2,8,9,8,2], | |
[2,5,11,2,3,5,3,7,5], | |
[8,2,0,8,5,2,8,7,5,11,2,5], | |
[9,0,1,5,11,3,5,3,7,3,11,2], | |
[9,8,2,9,2,1,8,7,2,11,2,5,7,5,2], | |
[1,3,5,3,7,5], | |
[0,8,7,0,7,1,1,7,5], | |
[9,0,3,9,3,5,5,3,7], | |
[9,8,7,5,9,7], | |
[5,8,4,5,11,8,11,10,8], | |
[5,0,4,5,10,0,5,11,10,10,3,0], | |
[0,1,9,8,4,11,8,11,10,11,4,5], | |
[11,10,4,11,4,5,10,3,4,9,4,1,3,1,4], | |
[2,5,1,2,8,5,2,10,8,4,5,8], | |
[0,4,10,0,10,3,4,5,10,2,10,1,5,1,10], | |
[0,2,5,0,5,9,2,10,5,4,5,8,10,8,5], | |
[9,4,5,2,10,3], | |
[2,5,11,3,5,2,3,4,5,3,8,4], | |
[5,11,2,5,2,4,4,2,0], | |
[3,11,2,3,5,11,3,8,5,4,5,8,0,1,9], | |
[5,11,2,5,2,4,1,9,2,9,4,2], | |
[8,4,5,8,5,3,3,5,1], | |
[0,4,5,1,0,5], | |
[8,4,5,8,5,3,9,0,5,0,3,5], | |
[9,4,5], | |
[4,10,7,4,9,10,9,11,10], | |
[0,8,3,4,9,7,9,10,7,9,11,10], | |
[1,11,10,1,10,4,1,4,0,7,4,10], | |
[3,1,4,3,4,8,1,11,4,7,4,10,11,10,4], | |
[4,10,7,9,10,4,9,2,10,9,1,2], | |
[9,7,4,9,10,7,9,1,10,2,10,1,0,8,3], | |
[10,7,4,10,4,2,2,4,0], | |
[10,7,4,10,4,2,8,3,4,3,2,4], | |
[2,9,11,2,7,9,2,3,7,7,4,9], | |
[9,11,7,9,7,4,11,2,7,8,7,0,2,0,7], | |
[3,7,11,3,11,2,7,4,11,1,11,0,4,0,11], | |
[1,11,2,8,7,4], | |
[4,9,1,4,1,7,7,1,3], | |
[4,9,1,4,1,7,0,8,1,8,7,1], | |
[4,0,3,7,4,3], | |
[4,8,7], | |
[9,11,8,11,10,8], | |
[3,0,9,3,9,10,10,9,11], | |
[0,1,11,0,11,8,8,11,10], | |
[3,1,11,10,3,11], | |
[1,2,10,1,10,9,9,10,8], | |
[3,0,9,3,9,10,1,2,9,2,10,9], | |
[0,2,10,8,0,10], | |
[3,2,10], | |
[2,3,8,2,8,11,11,8,9], | |
[9,11,2,0,9,2], | |
[2,3,8,2,8,11,0,1,8,1,11,8], | |
[1,11,2], | |
[1,3,8,9,1,8], | |
[0,9,1], | |
[0,3,8], | |
[] | |
]; | |
// M A I N | |
// Default Marching Cubes Parameters | |
var threshold=128; | |
var SIZE=2; | |
var mode=0; // No interpolation | |
var interpolate = null; | |
var mesh = {}; | |
mesh.vertices = []; | |
mesh.faces = []; | |
// Dialog window to set parameters | |
dialog(); | |
// Get input stack/volume information and initialize slice of cubes | |
var imp=IJ.getImage(); | |
var stack=imp.getImageStack(); | |
var nx=imp.getWidth(); | |
var ny=imp.getHeight(); | |
var nz=imp.getStackSize(); | |
var center = {'x':(nx-1)/2.0, 'y':(ny-1)/2.0,'z':(nz-1)/2.0}; | |
var slice= new Slice(Math.floor( (nx -1)/SIZE ),Math.floor( (ny-1)/SIZE ) ); | |
// M a i n L o o p | |
IJ.log("\\Clear"); | |
IJ.log("Start of the main loop... Please wait."); | |
for (var z=0; z < nz-SIZE; z+=SIZE) { | |
slice.reset_count(); | |
for (var y=0; y < ny-SIZE; y+=SIZE) { | |
for (var x=0; x < nx-SIZE; x+=SIZE) { | |
// 1- Create a new marching cube | |
var cube = new Cube(x,y,z,SIZE); | |
// 2- Set voxels in the cube | |
cube.setVoxels(stack); | |
// 3- Calc configuration | |
cube.calcKey(threshold); | |
// 4- Create vertices and triangles | |
if (cube.key != 0 && cube.key != 255) { | |
createTriangles(cube); | |
} | |
// 5- Update slice | |
slice.push(cube); | |
} | |
} | |
if ( (z%10) == 0) IJ.log("z="+z); | |
} | |
saveAsOBJ(); | |
throw("-- End of Script --"); | |
// F U N C T I O N S | |
function dialog() { | |
var gd = new GenericDialog("Marching Cubes"); | |
gd.addNumericField("Threshold: ", threshold, 0); | |
gd.addNumericField("Cube Size: ", SIZE, 0); | |
gd.addChoice("Interpolation: ", ["None","Bilinear"], 0); | |
gd.showDialog(); | |
if (gd.wasCanceled()) { | |
return; | |
} | |
threshold = gd.getNextNumber(); | |
SIZE = gd.getNextNumber(); | |
mode = gd.getNextChoiceIndex(); | |
if (mode ==0) { | |
interpolate = function (v0,v1) { | |
return interpolateNone(v0,v1); | |
} | |
} | |
else { | |
interpolate = function (v0,v1) { | |
return interpolateBilinear(v0,v1); | |
} | |
} | |
var saveDialog = new SaveDialog("Save OBJ File As ...","Untitled",".obj"); | |
filename=saveDialog.getDirectory()+saveDialog.getFileName(); | |
IJ.log(filename); | |
} | |
function createTriangles(probe) { | |
//IJ.log("key "+probe.key+" "+ probe.x +" "+probe.y+" "+probe.z); | |
var vertices=[]; | |
var vertex = null; | |
var edges=triangles[probe.key]; | |
for (var i=0;i<edges.length;i++) { | |
var index=-1; | |
var edge = edges[i]; | |
//IJ.log("edge "+edge); | |
if (probe.edges[edge] != -1) { | |
// Edge already calculated | |
index = probe.edges[edge]; | |
} | |
else { | |
switch (edge) { | |
case 0: | |
if (probe.y != 0) { | |
probe.edges[edge] = slice.above().edges[2]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(0),probe.getVertex(1) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 1: | |
if (probe.z != 0) { | |
probe.edges[edge] = slice.back().edges[5]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(1),probe.getVertex(2) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 2: | |
if (probe.z != 0) { | |
probe.edges[edge] = slice.back().edges[6]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(2),probe.getVertex(3) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 3: | |
if (probe.x != 0) { | |
probe.edges[edge] = slice.previous().edges[1]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(0),probe.getVertex(3) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 4: | |
if (probe.y != 0) { | |
probe.edges[edge] = slice.above().edges[6]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(4),probe.getVertex(5) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 5: | |
vertex=interpolate(probe.getVertex(5),probe.getVertex(6) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
break; | |
case 6: | |
vertex=interpolate(probe.getVertex(6),probe.getVertex(7) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
break; | |
case 7: | |
if (probe.x != 0) { | |
probe.edges[edge] = slice.previous().edges[5]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(4),probe.getVertex(7) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 8: | |
if (probe.x != 0) { | |
probe.edges[edge] = slice.previous().edges[9]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(0),probe.getVertex(4) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 9: | |
if (probe.y != 0) { | |
probe.edges[edge] = slice.above().edges[11]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex=interpolate(probe.getVertex(1),probe.getVertex(5) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 10: | |
if (probe.x != 0) { | |
probe.edges[edge] = slice.previous().edges[11]; | |
index = probe.edges[edge]; | |
} | |
else { | |
vertex = interpolate(probe.getVertex(3),probe.getVertex(7) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
} | |
break; | |
case 11: | |
vertex=interpolate(probe.getVertex(2),probe.getVertex(6) ); | |
mesh.vertices.push(vertex); | |
index = mesh.vertices.length-1; | |
probe.edges[edge]= index; | |
break; | |
} | |
//IJ.log ("faces["+(mesh.faces.length-1)+"]= "+index); | |
} | |
mesh.faces.push(index); | |
} | |
} | |
function saveAsOBJ() { | |
IJ.log("Preparing file ..."); | |
var text=''; | |
// Header | |
text+="# Marching Cubes\n"; | |
text+="# Jean-Christophe Taveau\n"; | |
text+="# CrazyBioComputing\n"; | |
text+="# WaveFront OBJ File Format\n"; | |
text+="# Vertices: "+mesh.vertices.length+"\n"; | |
text+="\n"; | |
text+="o "+imp.getTitle()+"\n"; | |
text+="\n"; | |
// Write output text in file | |
var file = new java.io.File(filename); | |
var printWriter = new java.io.PrintWriter (filename); | |
IJ.log("Writing header..."); | |
printWriter.println (text); | |
// Vertices | |
for (var i=0;i<mesh.vertices.length;i++) { | |
printWriter.println ("v "+ (mesh.vertices[i].x - center.x)+" "+ (mesh.vertices[i].y - center.y) + " " + (mesh.vertices[i].z - center.z) ); | |
} | |
IJ.log("Writing vertices..."); | |
printWriter.println (" "); | |
// Faces (aka lines) | |
// *Note*: The first vertex in OBJ format has the index 1 (and not 0). | |
for (var i=0;i<mesh.faces.length;i+=3) | |
printWriter.println ("f "+(mesh.faces[i]+1) +" "+ (mesh.faces[i+1]+1) +" "+ (mesh.faces[i+2]+1) ); | |
IJ.log("Writing faces..."); | |
// Close file | |
printWriter.close (); | |
} | |
function interpolateNone(v0,v1) { | |
var x = ( v0.x + v1.x )/2.0; | |
var y = ( v0.y + v1.y )/2.0; | |
var z = ( v0.z + v1.z )/2.0; | |
return {"x":x,"y":y,"z":z}; | |
} | |
function interpolateBilinear(v0,v1) { | |
var k = (threshold - v0.voxel)/(v1.voxel - v0.voxel); | |
var x = v0.x + (v1.x - v0.x) * k; | |
var y = v0.y + (v1.y - v0.y) * k; | |
var z = v0.z + (v1.z - v0.z) * k; | |
return {"x":x,"y":y,"z":z}; | |
} | |
+++ End of Script +++
Hope that helps.
<< Previous: Principle Next: Render in Blender >>
No comments:
Post a Comment