#include #include #include #define NDIMS 3 typedef enum { EK_NONE = 1, EK_FLAT, EK_CONVEX, EK_CONCAVE, EK_CROSS } EDGEKIND; typedef struct xyzi XYZI; typedef struct facept FACEPT; typedef struct face FACE; typedef struct tri TRI; typedef struct loc LOC; typedef struct cell CELL; typedef struct edge EDGE; struct xyzi { int x; int y; int z; } ; struct loc { LOC *link; XYZI p; int n; } ; struct tri { TRI *link; LOC *a; LOC *b; LOC *c; int n; } ; struct cell { XYZI loc; EDGE *edges[3][2]; char filled; } ; struct edge { CELL *e1; CELL *e2; EDGEKIND kind; int rot; } ; #define XHP ((XYZI){1,0,0}) #define YHP ((XYZI){0,1,0}) #define ZHP ((XYZI){0,0,1}) #define XHN ((XYZI){-1,0,0}) #define YHN ((XYZI){0,-1,0}) #define ZHN ((XYZI){0,0,-1}) static int pcsz[NDIMS]; static int pcm[NDIMS]; static int pcnv; static CELL *pcv; #define pc(x,y,z) pcv[((x)*pcm[2])+((y)*pcm[1])+((z)*pcm[0])] static const XYZI dirs[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; static const int others[3][2] = { { 1, 2 }, { 2, 0 }, { 0, 1 } }; static LOC *locs; static int nlocs; static TRI *tris; static int ntris; static CELL *pcbxyzp(XYZI p) { return(&pcbit(p.x,p.y,p.z)); } static CELL pcbxyz(XYZI p) { return(*pcbxyzp(p)); } static int xyzi_zerop(XYZI) __attribute__((__const__)); static int xyzi_zerop(XYZI v) { return((v.x == 0) && (v.y == 0) && (v.z == 0)); } static int xyzi_dot(XYZI a, XYZI b) { return((a.x * b.x) + (a.y * b.y) + (a.z * b.z)); } static XYZI xyzi_sub(XYZI, XYZI) __attribute__((__const__)); static XYZI xyzi_sub(XYZI a, XYZI b) { return( (XYZI) { .x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z } ); } static XYZI xyzi_cross(XYZI, XYZI) __attribute__((__const__)); static XYZI xyzi_cross(XYZI a, XYZI b) { return( (XYZI) { .x = (a.y * b.z) - (a.z * b.y), .y = (a.z * b.x) - (a.x * b.z), .z = (a.x * b.y) - (a.y * b.x) } ); } static void baddescr(const char *how) { fprintf(stderr,"Bad piece (%s)\n",how); exit(1); } static void read_pc(void) { int ch; int dims[NDIMS]; int lens[NDIMS]; int muls[NDIMS]; int x; int y; int z; char *bits; int bithave; int bitlen; int i; int depth; int m; CELL c; EDGE *e; bits = 0; bitlen = 0; bithave = 0; for (i=NDIMS-1;i>=-0;i--) dims[i] = -1; depth = 0; lens[0] = 0; while <"readloop"> (1) { ch = getchar(); switch (ch) { default: baddescr("bad character in bitmap"); break; case '\n': break <"readloop">; break; case ' ': case '\t': break; case '(': depth ++; if (depth >= NDIMS) baddescr("too many (s in bitmap"); lens[depth] = 0; break; case ')': if (dims[depth] < 0) { dims[depth] = lens[depth]; } else if (lens[depth] != dims[depth]) { baddescr("length mismatch in bitmap"); } depth --; if (depth < 0) baddescr("unmatched ) in bitmap"); lens[depth] ++; break; case '0': case '1': if (depth != NDIMS-1) baddescr("bit not deep enough"); lens[depth] ++; if (bitlen >= bithave) bits = realloc(bits,bithave=bitlen+64); bits[bitlen++] = ('1'==ch) ? BIT_CUBE : 0; break; } } if (depth != 0) baddescr("misbalanced ()s in bitmap"); dims[0] = lens[0]; m = 1; for (i=NDIMS-1;i>=0;i--) { muls[i] = m; m *= dims[i]; } m = 1; for (i=NDIMS-1;i>=0;i--) { pcsz[i] = dims[i] + 2; pcm[i] = m; m *= pcsz[i]; } pcnv = m; pcv = malloc(m*sizeof(CELL)); for (x=pcsz[2]-1;x>=0;x--) { for (y=pcsz[1]-1;y>=0;y--) { for (z=pcsz[0]-1;z>=0;z--) { if ( (x == 0) || (x == pcsz[2]-1) || (y == 0) || (y == pcsz[1]-1) || (z == 0) || (z == pcsz[0]-1) || !bits[((x-1)*muls[2])+((y-1)*muls[1])+((z-1)*muls[0])] ) { c.filled = 0; } else { c.filled = 1; } c.loc.x = x; c.loc.y = y; c.loc.z = z; edges[0][0] = 0; edges[0][1] = 0; edges[1][0] = 0; edges[1][1] = 0; edges[2][0] = 0; edges[2][1] = 0; pc(x,y,z).filled = c; } } } for (x=pcsz[2]-1;x>=0;x--) { for (y=pcsz[1]-1;y>=0;y--) { for (z=pcsz[0]-1;z>=0;z--) { void maybe_edge(int dx, int dy, int dz, int ex) { EDGE *e; if ((x-dx < 0) || (y-dy < 0) || (z-dz < 0)) return; e = malloc(sizeof(EDGE)); e->e1 = pc(x-dx,y-dy,z-dz); e->e2 = pc(x,y,z); e->kind = EK_NONE; e->e1->edges[ex][1] = e; e->e2->edges[ex][0] = e; } maybe_edge(1,0,0,0); maybe_edge(0,1,0,1); maybe_edge(0,0,1,2); } } } free(bits); } static LOC *loc_cache(XYZI p) { LOC *l; for (l=locs;l;l=l->link) { if ((l->p.x == p.x) && (l->p.y == p.y) && (l->p.z == p.z)) return(l); } l = malloc(sizeof(LOC)); l->p = p; l->link = locs; locs = l; nlocs ++; return(l); } static void setup_mesh(void) { int x; int y; int z; int ex; EDGE *e; XYZI du; XYZI dr; int syndrome; static const EDGEKIND kindvec[16] = { EK_NONE, EK_CONVEX, EK_CONVEX, EK_FLAT, EK_CONVEX, EK_FLAT, EK_CROSS, EK_CONCAVE, EK_CONVEX, EK_CROSS, EK_FLAT, EK_CONCAVE, EK_FLAT, EK_CONCAVE, EK_CONCAVE, EK_NONE }; static const int rotvec[16] = { 0, 2, 3, 2, 1, 1, 1, 0, 0, 0, 3, 1, 0, 3, 2, 0 }; locs = 0; nlocs = 0; tris = 0; ntris = 0; for (x=pcsz[2]-1;x>0;x--) { for (y=pcsz[1]-1;y>0;y--) { for (z=pcsz[0]-1;z>0;z--) { for (ex=3-1;ex>=0;ex--) { e = pc(x,y,z).edges[ex][1]; du = dirs[others[ex][0]]; dr = dirs[others[ex][1]]; syndrome = (pc(x-du.x-dr.x,y-du.y-dr.y,z-du.z-dr.z).filled ? 1 : 0) | (pc(x-dr.x,y-dr.y,z-dr.z).filled ? 2 : 0) | (pc(x-du.x,y-du.y,z-du.z).filled ? 4 : 0) | (pc(x,y,z) ? 8 : 0); e->kind = kindvec[syndrome]; e->rot = rotvec[syndrome]; } } } } } static void dump_output(void) { LOC *l; TRI *t; int i; double cx; double cy; double cz; cx = 0; cy = 0; cz = 0; for (i=0,l=locs;l;l=l->link,i++) { l->n = i; cx += l->p.x; cy += l->p.y; cz += l->p.z; } cx /= nlocs; cy /= nlocs; cz /= nlocs; if (i != nlocs) abort(); for (i=0,t=tris;t;t=t->link,i++) t->n = i; if (i != ntris) abort(); printf("@\nModelV1\n"); printf("1 %d %d %d\n",nlocs,nlocs,ntris); printf("White 0 0 0 .7 .7 .7 10 .5\n"); for (l=locs;l;l=l->link) printf("%g %g %g\n",l->p.x-cx,l->p.y-cy,l->p.z-cz); for (l=locs;l;l=l->link) printf("%d c\n",l->n); for (t=tris;t;t=t->link) printf("0 %d %d %d\n",t->a->n,t->b->n,t->c->n); } int main(void); int main(void) { read_pc(); setup_mesh(); dump_output(); return(0); }