kopia lustrzana https://github.com/fellesverkstedet/fabmodules
668 wiersze
20 KiB
C
668 wiersze
20 KiB
C
//
|
|
// vol_stl.c
|
|
// .vol to .stl
|
|
//
|
|
// Neil Gershenfeld 5/21/14
|
|
// (c) Massachusetts Institute of Technology 2014
|
|
//
|
|
// This work may be reproduced, modified, distributed,
|
|
// performed, and displayed for any purpose, but must
|
|
// acknowledge the fab modules project. Copyright is
|
|
// retained and must be preserved. The work is provided
|
|
// as is; no warranty is provided, and users accept all
|
|
// liability.
|
|
//
|
|
|
|
#define MAX_LINE 10000
|
|
|
|
#include "fab.h"
|
|
|
|
/*
|
|
vertices:
|
|
---
|
|
6 7
|
|
4 5
|
|
---
|
|
2 3
|
|
0 1
|
|
---
|
|
edges:
|
|
---
|
|
k
|
|
l j
|
|
i
|
|
---
|
|
h g
|
|
e f
|
|
---
|
|
c
|
|
d b
|
|
a
|
|
---
|
|
*/
|
|
|
|
//
|
|
// rotate_x
|
|
// rotate rule around x and add
|
|
//
|
|
void rotate_x(char rules[255][20], int *index) {
|
|
int i,b[8];
|
|
int old_index = *index;
|
|
for (i = 0; i < 8; ++i) b[i] = (*index & (1 << i)) >> i;
|
|
*index =
|
|
(b[4] << 0)
|
|
+(b[5] << 1)
|
|
+(b[0] << 2)
|
|
+(b[1] << 3)
|
|
+(b[6] << 4)
|
|
+(b[7] << 5)
|
|
+(b[2] << 6)
|
|
+(b[3] << 7);
|
|
for (i
|
|
= 0; i < strlen(rules[old_index]); ++i) {
|
|
switch (rules[old_index][i]) {
|
|
case 'a': rules[*index][i] = 'c'; break;
|
|
case 'b': rules[*index][i] = 'g'; break;
|
|
case 'c': rules[*index][i] = 'k'; break;
|
|
case 'd': rules[*index][i] = 'h'; break;
|
|
case 'e': rules[*index][i] = 'd'; break;
|
|
case 'f': rules[*index][i] = 'b'; break;
|
|
case 'g': rules[*index][i] = 'j'; break;
|
|
case 'h': rules[*index][i] = 'l'; break;
|
|
case 'i': rules[*index][i] = 'a'; break;
|
|
case 'j': rules[*index][i] = 'f'; break;
|
|
case 'k': rules[*index][i] = 'i'; break;
|
|
case 'l': rules[*index][i] = 'e'; break;
|
|
case ' ': rules[*index][i] = ' '; break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// rotate_y
|
|
// rotate rule around y and add
|
|
//
|
|
void rotate_y(char rules[255][20], int *index) {
|
|
int i,b[8];
|
|
int old_index = *index;
|
|
for (i = 0; i < 8; ++i) b[i] = (*index & (1 << i)) >> i;
|
|
*index =
|
|
(b[1] << 0)
|
|
+(b[5] << 1)
|
|
+(b[3] << 2)
|
|
+(b[7] << 3)
|
|
+(b[0] << 4)
|
|
+(b[4] << 5)
|
|
+(b[2] << 6)
|
|
+(b[6] << 7);
|
|
for (i = 0; i < strlen(rules[old_index]); ++i) {
|
|
switch (rules[old_index][i]) {
|
|
case 'a': rules[*index][i] = 'e'; break;
|
|
case 'b': rules[*index][i] = 'd'; break;
|
|
case 'c': rules[*index][i] = 'h'; break;
|
|
case 'd': rules[*index][i] = 'l'; break;
|
|
case 'e': rules[*index][i] = 'i'; break;
|
|
case 'f': rules[*index][i] = 'a'; break;
|
|
case 'g': rules[*index][i] = 'c'; break;
|
|
case 'h': rules[*index][i] = 'k'; break;
|
|
case 'i': rules[*index][i] = 'f'; break;
|
|
case 'j': rules[*index][i] = 'b'; break;
|
|
case 'k': rules[*index][i] = 'g'; break;
|
|
case 'l': rules[*index][i] = 'j'; break;
|
|
case ' ': rules[*index][i] = ' '; break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// rotate_z
|
|
// rotate rule around z and add
|
|
//
|
|
void rotate_z(char rules[255][20], int *index) {
|
|
int i,b[8];
|
|
int old_index = *index;
|
|
for (i = 0; i < 8; ++i) b[i] = (*index & (1 << i)) >> i;
|
|
*index =
|
|
(b[2] << 0)
|
|
+(b[0] << 1)
|
|
+(b[3] << 2)
|
|
+(b[1] << 3)
|
|
+(b[6] << 4)
|
|
+(b[4] << 5)
|
|
+(b[7] << 6)
|
|
+(b[5] << 7);
|
|
for (i = 0; i < strlen(rules[old_index]); ++i) {
|
|
switch (rules[old_index][i]) {
|
|
case 'a': rules[*index][i] = 'b'; break;
|
|
case 'b': rules[*index][i] = 'c'; break;
|
|
case 'c': rules[*index][i] = 'd'; break;
|
|
case 'd': rules[*index][i] = 'a'; break;
|
|
case 'e': rules[*index][i] = 'f'; break;
|
|
case 'f': rules[*index][i] = 'g'; break;
|
|
case 'g': rules[*index][i] = 'h'; break;
|
|
case 'h': rules[*index][i] = 'e'; break;
|
|
case 'i': rules[*index][i] = 'j'; break;
|
|
case 'j': rules[*index][i] = 'k'; break;
|
|
case 'k': rules[*index][i] = 'l'; break;
|
|
case 'l': rules[*index][i] = 'i'; break;
|
|
case ' ': rules[*index][i] = ' '; break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// print_rules
|
|
// print the rule table
|
|
//
|
|
void print_rules(char rules[255][20]) {
|
|
int i,b;
|
|
printf("76543210\n");
|
|
for (i = 0; i < 256; ++i) {
|
|
for (b = 7; b >= 0; --b) {
|
|
printf("%d",(i & (1 << b)) >> b);
|
|
}
|
|
printf(" %d %s\n",i,rules[i]);
|
|
}
|
|
}
|
|
// add_rules
|
|
// add a rule and its variants to the table
|
|
//
|
|
void add_rules(char rules[255][20], int index, char *edges) {
|
|
int i,j,k,l;
|
|
strcpy(rules[index],edges);
|
|
for (i=0; i<4; ++i) {
|
|
for (j=0; j<4; ++j) {
|
|
for (k=0; k<4; ++k) {
|
|
rotate_x(rules,&index);
|
|
}
|
|
rotate_y(rules,&index);
|
|
}
|
|
rotate_z(rules,&index);
|
|
}
|
|
}
|
|
//
|
|
// init_rules
|
|
// create the rule table
|
|
//
|
|
void init_rules(char rules[255][20]) {
|
|
int i,j;
|
|
for (i = 0; i < 256; ++i)
|
|
for (j = 0; j < 20; ++j)
|
|
rules[i][j] = 0;
|
|
add_rules(rules,0b00000000,""); // 0
|
|
add_rules(rules,0b11111111,""); // ~0
|
|
add_rules(rules,0b00000001,"eda"); // 1
|
|
add_rules(rules,0b11111110,"ade"); // ~1
|
|
add_rules(rules,0b00000011,"fed dbf"); // 2
|
|
add_rules(rules,0b11111100,"def fbd"); // ~2
|
|
add_rules(rules,0b00100001,"eda jif"); // 3
|
|
add_rules(rules,0b11011110,"ade fij"); // ~3
|
|
add_rules(rules,0b10000001,"eda gkj"); // 4
|
|
add_rules(rules,0b01111110,"ade jkg"); // ~4
|
|
add_rules(rules,0b00001110,"fhg fdh fad"); // 5
|
|
add_rules(rules,0b11110001,"ghf hdf daf"); // ~5
|
|
add_rules(rules,0b10000011,"fed fdb gkj"); // 6
|
|
add_rules(rules,0b01111100,"def bdf jkg"); // ~6
|
|
add_rules(rules,0b10010010,"bfa ile gkj"); // 7
|
|
add_rules(rules,0b01101101,"afb eli jkg"); // ~7
|
|
add_rules(rules,0b00001111,"ehg feg"); // 8
|
|
add_rules(rules,0b11110000,"ghe gef"); // ~8
|
|
add_rules(rules,0b01001101,"elk eka akg agb"); // 9
|
|
add_rules(rules,0b10110010,"kle ake gka bga"); // ~9
|
|
add_rules(rules,0b10011001,"ild ida ckj cjb"); // 10
|
|
add_rules(rules,0b01100110,"dli adi jkc bjc"); // ~10
|
|
add_rules(rules,0b10001101,"hkj hja hae ajb"); // 11
|
|
add_rules(rules,0b01110010,"jkh ajh eah bja"); // ~11
|
|
add_rules(rules,0b00011110,"ile hgf hfd dfa"); // 12
|
|
add_rules(rules,0b11100001,"eli fgh dfh afd"); // ~12
|
|
add_rules(rules,0b01101001,"eda bcg lkh jif"); // 13
|
|
add_rules(rules,0b10010110,"ade gcb hkl fij"); // ~13
|
|
add_rules(rules,0b01001110,"lkg lga lad agf"); // 14
|
|
add_rules(rules,0b10110001,"gkl agl dal fga"); // ~14
|
|
}
|
|
//
|
|
// vertex
|
|
// add a triangle vertex
|
|
//
|
|
void vertex(char c, int x, int y, int z, float voxel_size, float t, float *w, float *array) {
|
|
switch(c) {
|
|
case 'a':
|
|
array[0] = x+(w[0]-t)/(w[0]-w[1]);
|
|
array[1] = y;
|
|
array[2] = z;
|
|
break;
|
|
case 'b':
|
|
array[0] = x+1;
|
|
array[1] = y+(w[1]-t)/(w[1]-w[3]);
|
|
array[2] = z;
|
|
break;
|
|
case 'c':
|
|
array[0] = x+(w[2]-t)/(w[2]-w[3]);
|
|
array[1] = y+1;
|
|
array[2] = z;
|
|
break;
|
|
case 'd':
|
|
array[0] = x;
|
|
array[1] = y+(w[0]-t)/(w[0]-w[2]);
|
|
array[2] = z;
|
|
break;
|
|
case 'e':
|
|
array[0] = x;
|
|
array[1] = y;
|
|
array[2] = z+(w[0]-t)/(w[0]-w[4]);
|
|
break;
|
|
case 'f':
|
|
array[0] = x+1;
|
|
array[1] = y;
|
|
array[2] = z+(w[1]-t)/(w[1]-w[5]);
|
|
break;
|
|
case 'g':
|
|
array[0] = x+1;
|
|
array[1] = y+1;
|
|
array[2] = z+(w[3]-t)/(w[3]-w[7]);
|
|
break;
|
|
case 'h':
|
|
array[0] = x;
|
|
array[1] = y+1;
|
|
array[2] = z+(w[2]-t)/(w[2]-w[6]);
|
|
break;
|
|
case 'i':
|
|
array[0] = x+(w[4]-t)/(w[4]-w[5]);
|
|
array[1] = y;
|
|
array[2] = z+1;
|
|
break;
|
|
case 'j':
|
|
array[0] = x+1;
|
|
array[1] = y+(w[5]-t)/(w[5]-w[7]);
|
|
array[2] = z+1;
|
|
break;
|
|
case 'k':
|
|
array[0] = x+(w[6]-t)/(w[6]-w[7]);
|
|
array[1] = y+1;
|
|
array[2] = z+1;
|
|
break;
|
|
case 'l':
|
|
array[0] = x;
|
|
array[1] = y+(w[4]-t)/(w[4]-w[6]);
|
|
array[2] = z+1;
|
|
break;
|
|
}
|
|
array[0] = voxel_size*array[0];
|
|
array[1] = voxel_size*array[1];
|
|
array[2] = voxel_size*array[2];
|
|
}
|
|
//
|
|
// triangulate
|
|
// triangulate voxel at lattice site x,y,z with vertex weights w
|
|
//
|
|
void triangulate(int x, int y, int z, float voxel_size, float t, float *w, char rules[255][20], struct fab_vars *v) {
|
|
int i,index;
|
|
char c;
|
|
//
|
|
// set index code
|
|
//
|
|
index = ((w[0] < t) ? 0 : 1)
|
|
+ ((w[1] < t) ? 0 : 2)
|
|
+ ((w[2] < t) ? 0 : 4)
|
|
+ ((w[3] < t) ? 0 : 8)
|
|
+ ((w[4] < t) ? 0 : 16)
|
|
+ ((w[5] < t) ? 0 : 32)
|
|
+ ((w[6] < t) ? 0 : 64)
|
|
+ ((w[7] < t) ? 0 : 128);
|
|
//
|
|
// add triangles for rule
|
|
//
|
|
i = 0;
|
|
while (1) {
|
|
//
|
|
// loop over rule chars
|
|
//
|
|
c = rules[index][i];
|
|
if (c == 0)
|
|
//
|
|
// end of rule
|
|
//
|
|
break;
|
|
else if (c == ' ') {
|
|
//
|
|
// space between rules
|
|
//
|
|
i += 1;
|
|
continue;
|
|
}
|
|
else {
|
|
//
|
|
// create triangle for rule
|
|
//
|
|
v->mesh->last = malloc(sizeof(struct fab_mesh_triangle_type));
|
|
v->mesh->last->previous = v->mesh->triangle;
|
|
v->mesh->triangle->next = v->mesh->last;
|
|
v->mesh->triangle = v->mesh->last;
|
|
v->mesh->triangle->next = 0;
|
|
v->mesh->triangle->attribute = 0;
|
|
v->mesh->triangle->normal[0] = v->mesh->triangle->normal[1] = v->mesh->triangle->normal[2] = 0;
|
|
//
|
|
// add vertices for rule
|
|
//
|
|
c = rules[index][i];
|
|
vertex(c,x,y,z,voxel_size,t,w,v->mesh->triangle->v0);
|
|
i += 1;
|
|
c = rules[index][i];
|
|
vertex(c,x,y,z,voxel_size,t,w,v->mesh->triangle->v1);
|
|
i += 1;
|
|
c = rules[index][i];
|
|
vertex(c,x,y,z,voxel_size,t,w,v->mesh->triangle->v2);
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void fab_write_stl(struct fab_vars *v, char *output_file_name) {
|
|
//
|
|
// write mesh as STL
|
|
//
|
|
FILE *output_file;
|
|
char buf[80];
|
|
uint32_t count;
|
|
//
|
|
// open output file
|
|
//
|
|
output_file = fopen(output_file_name, "wb");
|
|
if (output_file == 0) {
|
|
printf("fab.c: oops -- can't open %s\n",output_file_name);
|
|
exit(-1);
|
|
}
|
|
//
|
|
// write header
|
|
//
|
|
fwrite(buf,80,1,output_file);
|
|
//
|
|
// write count
|
|
//
|
|
count = 0;
|
|
v->mesh->triangle = v->mesh->first;
|
|
while (v->mesh->triangle->next != 0) {
|
|
v->mesh->triangle = v->mesh->triangle->next;
|
|
count += 1;
|
|
}
|
|
fwrite(&count,4,1,output_file);
|
|
//
|
|
// write triangles
|
|
//
|
|
v->mesh->triangle = v->mesh->first;
|
|
while (v->mesh->triangle->next != 0) {
|
|
v->mesh->triangle = v->mesh->triangle->next;
|
|
fwrite(v->mesh->triangle->normal,4,3,output_file);
|
|
fwrite(v->mesh->triangle->v0,4,3,output_file);
|
|
fwrite(v->mesh->triangle->v1,4,3,output_file);
|
|
fwrite(v->mesh->triangle->v2,4,3,output_file);
|
|
fwrite(&(v->mesh->triangle->attribute),2,1,output_file);
|
|
}
|
|
//
|
|
// return
|
|
//
|
|
printf("wrote %d triangles to %s\n",count,output_file_name);
|
|
fclose(output_file);
|
|
}
|
|
|
|
float interp(int x,int y,int i,int j,int k,float **lower_array,float **upper_array,int p) {
|
|
//
|
|
// trilinear interpolation within a voxel
|
|
//
|
|
return (lower_array[y][x]*((p+1.0-i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ lower_array[y][x+1]*((i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ lower_array[y+1][x]*((p+1.0-i)/(p+1.0))*((j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ lower_array[y+1][x+1]*((i)/(p+1.0))*((j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ upper_array[y][x]*((p+1.0-i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((k)/(p+1.0))
|
|
+ upper_array[y][x+1]*((i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((k)/(p+1.0))
|
|
+ upper_array[y+1][x]*((p+1.0-i)/(p+1.0))*((j)/(p+1.0))*((k)/(p+1.0))
|
|
+ upper_array[y+1][x+1]*((i)/(p+1.0))*((j)/(p+1.0))*((k)/(p+1.0)));
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
//
|
|
// local vars
|
|
//
|
|
FILE *input_file;
|
|
uint64_t count;
|
|
uint16_t itype;
|
|
int x,y,z,i,j,k,n,p,imin,imax,nx,ny,nz;
|
|
int image_width,image_height,color_resolution,ret;
|
|
float w[8],**lower_array,**upper_array;
|
|
float threshold,voxel_size;
|
|
float ftype,fmin=1e10,fmax=-1e10;
|
|
char format,comment[256],rules[255][20];
|
|
struct fab_vars v;
|
|
init_vars(&v);
|
|
//
|
|
// command line args
|
|
//
|
|
if (!((argc == 6) || (argc == 7) || (argc == 8) || (argc == 9) || (argc == 10))) {
|
|
printf("command line: vol_stl in.vol out.stl nx ny nz [format [threshold [size [points [angle]]]]]\n");
|
|
printf(" in.vol = input VOL file\n");
|
|
printf(" out.stl = output STL file\n");
|
|
printf(" nx,ny,nz = x,y,z input voxel number\n");
|
|
printf(" format = 'f' for float 32, 'i' for uint16_t (default 'f')\n");
|
|
printf(" threshold: surface intensity threshold (0 = min, 1 = max, default 0.5))\n");
|
|
printf(" size = voxel size (mm, default from file))\n");
|
|
printf(" points = points to interpolate per point (default 0)\n");
|
|
printf(" to be implemented: angle = minimum relative face angle to decimate vertices (default 0)\n");
|
|
exit(-1);
|
|
}
|
|
format = 'f';
|
|
p = 0;
|
|
threshold = 0.5;
|
|
voxel_size = -1;
|
|
image_width = -1;
|
|
image_height = -1;
|
|
sscanf(argv[3],"%d",&nx);
|
|
sscanf(argv[4],"%d",&ny);
|
|
sscanf(argv[5],"%d",&nz);
|
|
if (argc >= 7) {
|
|
sscanf(argv[6],"%c",&format);
|
|
if (!((format == 'f') || (format == 'i'))) {
|
|
printf("vol_gif: oops -- format must be 'f' or 'i'\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
if (argc >= 8)
|
|
sscanf(argv[7],"%f",&threshold);
|
|
if (argc >= 9)
|
|
sscanf(argv[8],"%f",&voxel_size);
|
|
if (argc >= 10)
|
|
sscanf(argv[9],"%d",&p);
|
|
//
|
|
// initialize the rule table
|
|
//
|
|
init_rules(rules);
|
|
//
|
|
// check and find limits
|
|
//
|
|
input_file = fopen(argv[1],"rb");
|
|
if (input_file == NULL) {
|
|
printf("vol_stl: oops -- can not open %s\n",argv[1]);
|
|
exit(-1);
|
|
}
|
|
printf("read %s\n",argv[1]);
|
|
if (format == 'f') {
|
|
count = 0;
|
|
while (fread(&ftype,sizeof(ftype),1,input_file) != 0) {
|
|
if (ftype > fmax) fmax = ftype;
|
|
if (ftype < fmin) fmin = ftype;
|
|
count += 1;
|
|
}
|
|
}
|
|
else if (format == 'i') {
|
|
count = 0;
|
|
while (fread(&itype,sizeof(itype),1,input_file) != 0) {
|
|
if (itype > fmax) fmax = itype;
|
|
if (itype < fmin) fmin = itype;
|
|
count += 1;
|
|
}
|
|
}
|
|
if (nx*ny*nz != count) {
|
|
printf("vol_stl: oops -- file size doesn't match pixel number\n");
|
|
exit(-1);
|
|
}
|
|
printf(" %" PRIu64 " points, min %f, max %f\n",count,fmin,fmax);
|
|
printf(" nx ny nz: %d %d %d\n",nx,ny,nz);
|
|
rewind(input_file);
|
|
//
|
|
// scan the file
|
|
//
|
|
printf("read %s\n",argv[1]);
|
|
//
|
|
// set threshold
|
|
//
|
|
threshold = fmin + threshold*(fmax-fmin);
|
|
//
|
|
// add empty border
|
|
//
|
|
image_width = nx+2;
|
|
image_height = ny+2;
|
|
//
|
|
// allocate arrays
|
|
//
|
|
lower_array = malloc(image_height*sizeof(float *));
|
|
for (y = 0; y < image_height; ++y) {
|
|
lower_array[y] = malloc(image_width*sizeof(float));
|
|
for (x = 0; x < image_width; ++x)
|
|
lower_array[y][x] = 0;
|
|
}
|
|
upper_array = malloc(image_height*sizeof(float *));
|
|
for (y = 0; y < image_height; ++y) {
|
|
upper_array[y] = malloc(image_width*sizeof(float));
|
|
for (x = 0; x < image_width; ++x)
|
|
upper_array[y][x] = 0;
|
|
}
|
|
//
|
|
// read the file
|
|
//
|
|
z = 0;
|
|
v.mesh = malloc(sizeof(struct fab_mesh_type));
|
|
v.mesh->triangle = malloc(sizeof(struct fab_mesh_triangle_type));
|
|
v.mesh->first = v.mesh->triangle;
|
|
v.mesh->last = v.mesh->triangle;
|
|
v.mesh->triangle->previous = v.mesh->triangle->next = 0;
|
|
for (z = 0; z < nz; ++z) {
|
|
//
|
|
// read layer
|
|
//
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",z);
|
|
for (y = 0; y < ny; ++y) {
|
|
for (x = 0; x < nx; ++x) {
|
|
lower_array[y+1][x+1] = upper_array[y+1][x+1];
|
|
if (format == 'f') {
|
|
fread(&ftype,sizeof(ftype),1,input_file);
|
|
upper_array[y+1][x+1] = ftype;
|
|
}
|
|
else if (format == 'i') {
|
|
fread(&itype,sizeof(itype),1,input_file);
|
|
upper_array[y+1][x+1] = itype;
|
|
}
|
|
}
|
|
}
|
|
if (p == 0) {
|
|
//
|
|
// no interpolation, loop over layer voxels
|
|
//
|
|
for (x = 0; x < (image_width-1); ++x) {
|
|
for (y = 0; y < (image_height-1); ++y) {
|
|
w[0] = lower_array[y][x];
|
|
w[1] = lower_array[y][x+1];
|
|
w[2] = lower_array[y+1][x];
|
|
w[3] = lower_array[y+1][x+1];
|
|
w[4] = upper_array[y][x];
|
|
w[5] = upper_array[y][x+1];
|
|
w[6] = upper_array[y+1][x];
|
|
w[7] = upper_array[y+1][x+1];
|
|
triangulate(x,y,z,voxel_size,threshold,w,rules,&v);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// yes interpolation, loop over layer sub-voxels
|
|
//
|
|
for (x = 0; x < (image_width-1); ++x) {
|
|
for (y = 0; y < (image_height-1); ++y) {
|
|
for (i = 0; i <= p; ++i) {
|
|
for (j = 0; j <= p; ++j) {
|
|
for (k = 0; k <= p; ++k) {
|
|
w[0] = interp(x,y,i,j,k,lower_array,upper_array,p);
|
|
w[1] = interp(x,y,i+1,j,k,lower_array,upper_array,p);
|
|
w[2] = interp(x,y,i,j+1,k,lower_array,upper_array,p);
|
|
w[3] = interp(x,y,i+1,j+1,k,lower_array,upper_array,p);
|
|
w[4] = interp(x,y,i,j,k+1,lower_array,upper_array,p);
|
|
w[5] = interp(x,y,i+1,j,k+1,lower_array,upper_array,p);
|
|
w[6] = interp(x,y,i,j+1,k+1,lower_array,upper_array,p);
|
|
w[7] = interp(x,y,i+1,j+1,k+1,lower_array,upper_array,p);
|
|
triangulate((1+p)*x+i,(1+p)*y+j,(1+p)*z+k,voxel_size,threshold,w,rules,&v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// add empty top layer
|
|
//
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",z);
|
|
for (y = 0; y < (image_height-2); ++y) {
|
|
for (x = 0; x < (image_width-2); ++x) {
|
|
lower_array[y+1][x+1] = upper_array[y+1][x+1];
|
|
upper_array[y+1][x+1] = 0;
|
|
}
|
|
}
|
|
if (p == 0) {
|
|
//
|
|
// no interpolation, loop over layer voxels
|
|
//
|
|
for (x = 0; x < (image_width-1); ++x) {
|
|
for (y = 0; y < (image_height-1); ++y) {
|
|
w[0] = lower_array[y][x];
|
|
w[1] = lower_array[y][x+1];
|
|
w[2] = lower_array[y+1][x];
|
|
w[3] = lower_array[y+1][x+1];
|
|
w[4] = upper_array[y][x];
|
|
w[5] = upper_array[y][x+1];
|
|
w[6] = upper_array[y+1][x];
|
|
w[7] = upper_array[y+1][x+1];
|
|
triangulate(x,y,z,voxel_size,threshold,w,rules,&v);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// yes interpolation, loop over layer sub-voxels
|
|
//
|
|
for (x = 0; x < (image_width-1); ++x) {
|
|
for (y = 0; y < (image_height-1); ++y) {
|
|
for (i = 0; i <= p; ++i) {
|
|
for (j = 0; j <= p; ++j) {
|
|
for (k = 0; k <= p; ++k) {
|
|
w[0] = interp(x,y,i,j,k,lower_array,upper_array,p);
|
|
w[1] = interp(x,y,i+1,j,k,lower_array,upper_array,p);
|
|
w[2] = interp(x,y,i,j+1,k,lower_array,upper_array,p);
|
|
w[3] = interp(x,y,i+1,j+1,k,lower_array,upper_array,p);
|
|
w[4] = interp(x,y,i,j,k+1,lower_array,upper_array,p);
|
|
w[5] = interp(x,y,i+1,j,k+1,lower_array,upper_array,p);
|
|
w[6] = interp(x,y,i,j+1,k+1,lower_array,upper_array,p);
|
|
w[7] = interp(x,y,i+1,j+1,k+1,lower_array,upper_array,p);
|
|
triangulate((1+p)*x+i,(1+p)*y+j,(1+p)*z+k,voxel_size,threshold,w,rules,&v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("\n");
|
|
//
|
|
// write STL
|
|
//
|
|
fab_write_stl(&v,argv[2]);
|
|
//
|
|
// exit
|
|
//
|
|
fclose(input_file);
|
|
exit(0);
|
|
}
|