00001
00002
00003
00004
00005
00006
00007
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <math.h>
00011 #include <windows.h>
00012 #include <sys/types.h>
00013
00014 #include "struct.h"
00015 #include "dstruct.h"
00016
00017 #include "reverse.h"
00018
00019 #define DESELECTED 0
00020 #define SELECTED 1
00021 #define UNIT 32768.0
00022
00023
00024 static HWND hParent;
00025 static HINSTANCE hThisInstance;
00026
00027
00028 #if __WATCOMC__
00029 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00030 #else
00031 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00032 #endif
00033 switch (dwReason) {
00034 case DLL_PROCESS_ATTACH: {
00035 hThisInstance=hDLL;
00036 if(hDLL == NULL)MessageBox ( GetFocus()," NULL instance",NULL, MB_OK);
00037 break;
00038 }
00039 case DLL_PROCESS_DETACH:
00040 break;
00041 }
00042 return TRUE;
00043 }
00044
00045 #if __SC__
00046 #pragma startaddress(DllMain)
00047 #endif
00048
00049 void ImplicitPolygon(void);
00050
00051 BOOL _Xmodeler
00052 (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00053 char text_string[255],name_string[255];
00054 lpEVI=lpevi;
00055 hParent=parent_window;
00056 LoadString(hThisInstance,IDX_STRING2,text_string,256);
00057 LoadString(hThisInstance,IDX_STRING1,name_string,256);
00058 if(MessageBox(hParent,text_string,name_string,MB_OKCANCEL)
00059 == IDCANCEL)return FALSE;
00060 else{
00061 HCURSOR hSave;
00062 hSave=SetCursor(LoadCursor(NULL,IDC_WAIT));
00063 ImplicitPolygon();
00064 SetCursor(hSave);
00065 }
00066 return TRUE;
00067 }
00068
00070
00071 #define TET 0
00072 #define NOTET 1
00073
00074 #define RES 10
00075
00076 #define L 0
00077 #define R 1
00078 #define B 2
00079 #define T 3
00080 #define N 4
00081 #define F 5
00082 #define LBN 0
00083 #define LBF 1
00084 #define LTN 2
00085 #define LTF 3
00086 #define RBN 4
00087 #define RBF 5
00088 #define RTN 6
00089 #define RTF 7
00090
00091
00092
00093
00094 #define RAND() ((rand()&32767)/32767.)
00095 #define HASHBIT (5)
00096 #define HASHSIZE (size_t)(1<<(3*HASHBIT))
00097 #define MASK ((1<<HASHBIT)-1)
00098 #define HASH(i,j,k) ((((((i)&MASK)<<HASHBIT)|((j)&MASK))<<HASHBIT)|((k)&MASK))
00099 #define BIT(i, bit) (((i)>>(bit))&1)
00100 #define FLIP(i,bit) ((i)^1<<(bit))
00101
00102 typedef struct ipt {
00103 double x, y, z;
00104 } IPOINT;
00105
00106 typedef struct test {
00107 IPOINT p;
00108 double value;
00109 int ok;
00110 } TEST;
00111
00112 typedef struct pvert {
00113 IPOINT position, normal;
00114 } IVERTEX;
00115
00116 typedef struct pverts {
00117 int count, max;
00118 IVERTEX *ptr;
00119 } IVERTICES;
00120
00121 typedef struct corner {
00122 int i, j, k;
00123 double x, y, z, value;
00124 } CORNER;
00125
00126 typedef struct cube {
00127 int i, j, k;
00128 CORNER *corners[8];
00129 } CUBE;
00130
00131 typedef struct cubes {
00132 CUBE cube;
00133 struct cubes *next;
00134 } CUBES;
00135
00136 typedef struct centerlist {
00137 int i, j, k;
00138 struct centerlist *next;
00139 } CENTERLIST;
00140
00141 typedef struct cornerlist {
00142 int i, j, k;
00143 double value;
00144 struct cornerlist *next;
00145 } CORNERLIST;
00146
00147 typedef struct edgelist {
00148 int i1, j1, k1, i2, j2, k2;
00149 int vid;
00150 struct edgelist *next;
00151 } EDGELIST;
00152
00153 typedef struct intlist {
00154 int i;
00155 struct intlist *next;
00156 } INTLIST;
00157
00158 typedef struct intlists {
00159 INTLIST *list;
00160 struct intlists *next;
00161 } INTLISTS;
00162
00163 typedef struct process {
00164 double (*function)();
00165 int (*triproc)();
00166 double size, delta;
00167 int bounds;
00168 IPOINT start;
00169 CUBES *cubes;
00170 IVERTICES vertices;
00171 CENTERLIST **centers;
00172 CORNERLIST **corners;
00173 EDGELIST **edges;
00174 } PROCESS;
00175
00176 typedef struct _threeints {
00177 long i1,i2,i3;
00178 } THREEINTS;
00179
00180 void *calloc();
00181 char *mycalloc();
00182
00183
00184
00185
00186
00187
00188
00189 double torus (x, y, z)
00190 double x, y, z;
00191 {
00192 double x2 = x*x, y2 = y*y, z2 = z*z;
00193 double a = x2+y2+z2+(0.5*0.5)-(0.1*0.1);
00194 return a*a-4.0*(0.5*0.5)*(y2+z2);
00195 }
00196
00197
00198
00199
00200 double sphere (x, y, z)
00201 double x, y, z;
00202 {
00203 double rsq = x*x+y*y+z*z;
00204 return 1.0/(rsq < 0.00001? 0.00001 : rsq);
00205 }
00206
00207
00208
00209
00210 double blob (x, y, z)
00211 double x, y, z;
00212 {
00213 return 4.0-sphere(x+1.0,y,z)-sphere(x,y+1.0,z)-sphere(x,y,z+1.0);
00214 }
00215
00216 double sphere1(double x, double y, double z){
00217 return (x*x+y*y+z*z)-1.0;
00218 }
00219
00220
00221 int gntris;
00222 IVERTICES gvertices;
00223 THREEINTS *listf;
00224
00225
00226
00227 triangle (i1, i2, i3, vertices)
00228 int i1, i2, i3;
00229 IVERTICES vertices;
00230 {
00231 gvertices=vertices;
00232 gntris++;
00233 if(listf == NULL){
00234 if((listf=(THREEINTS *)malloc(sizeof(THREEINTS))) != NULL){
00235 listf[0].i1=i1;
00236 listf[0].i2=i2;
00237 listf[0].i3=i3;
00238 }
00239 }
00240 else{
00241 if((listf=(THREEINTS *)realloc(listf,sizeof(THREEINTS)*gntris)) != NULL){
00242 listf[gntris-1].i1=i1;
00243 listf[gntris-1].i2=i2;
00244 listf[gntris-1].i3=i3;
00245 }
00246 }
00247 return 1;
00248 }
00249
00251
00252 void InsertInVertexList(long base, long Vj, long Vi){
00253 vertex *vj,*vi;
00254 long *list,i,j;
00255 vj=(MainVp+base+Vj);
00256 vi=(MainVp+base+Vi);
00257 list = (long *)vi->sp;
00258 if(vi->id > 0)for(i=0;i<vi->id;i++)if(list[i] == Vj)return;
00259 list = (long *)vj->sp;
00260 if(vj->id > 0)for(j=0;j<vj->id;j++)if(list[j] == Vi)return;
00261 if(vi->id == 0){
00262 if((list = (long *)X__Malloc((vi->id + 1)*sizeof(long))) == NULL){
00263 return;
00264 }
00265 vi->sp=(struct SKELETON *)list;
00266 }
00267 else{
00268 list = (long *)vi->sp;
00269 if((list = (long *)X__Realloc(list,(vi->id + 1)*sizeof(long))) == NULL){
00270 return;
00271 }
00272 vi->sp=(struct SKELETON *)list;
00273 }
00274 list[vi->id] = base+Vj;
00275 (vi->id)++;
00276 }
00277
00278 void BuildEdges(long base){
00279 long n,j,i,*list;
00280 vertex *vp;
00281 vp=(MainVp+base);
00282 for(j=base;j<Nvert;j++){
00283 if(vp->id != 0 && vp->sp != NULL){
00284 if(!UpdateEdgeHeap(Nedge+vp->id))return;
00285 list = (long *)vp->sp;
00286 for(i=0;i<vp->id;i++)CreateEdge(j,list[i]);
00287 X__Free(vp->sp); vp->sp=NULL; vp->id=0;
00288 }
00289 vp++;
00290 }
00291 }
00292
00293 void ImplicitPolygon(void){
00294 int i,id1,id2,id3;
00295 char *err, *polygonize();
00296 vertex *Vp;
00297 gntris = 0;
00298 gvertices.ptr=NULL;
00299 listf=NULL;
00300
00301 if ((err = polygonize(torus, .1, 10, 0.,0.,0., triangle, NOTET)) != NULL) {
00302
00303
00304
00305
00306
00307 goto FREEPOINT;
00308 }
00309 if(gvertices.ptr != NULL && listf != NULL){
00310 if(UpdateVertexHeap(Nvert+gvertices.count)){
00311 long BaseVert=Nvert;
00312 for(i = 0;i<gvertices.count;i++) {
00313 IVERTEX v;
00314 v = gvertices.ptr[i];
00315 CreateVertex();
00316 Vp=(MainVp+Nvert-1);
00317 Vp->id=0;
00318 Vp->xyz[0]=(long)(v.position.x * UNIT);
00319 Vp->xyz[1]=(long)(v.position.y * UNIT);
00320 Vp->xyz[2]=(long)(v.position.z * UNIT);
00321 }
00322 if(UpdateFaceHeap(Nface+gntris)){
00323 for(i=0;i<gntris;i++){
00324 id1=listf[i].i1; id2=listf[i].i2; id3=listf[i].i3;
00325 CreateFace(BaseVert+id1,
00326 BaseVert+id2,
00327 BaseVert+id3);
00328
00329
00330 InsertInVertexList(BaseVert,id1,id2);
00331 InsertInVertexList(BaseVert,id2,id3);
00332 InsertInVertexList(BaseVert,id3,id1);
00333 }
00334 BuildEdges(BaseVert);
00335 }
00336 }
00337 }
00338 FREEPOINT:
00339 if(listf != NULL)free(listf);
00340 if(gvertices.ptr != NULL)free(gvertices.ptr);
00341 MessageBox(NULL,"DONE","Debug",MB_OK);
00342 return;
00343 }
00344
00345
00346
00347 static void testface (int i, int j, int k, CUBE *old, int ipface, int c1,
00348 int c2, int c3, int c4, PROCESS *p);
00349 static void converge (IPOINT *p1, IPOINT *p2, double v,
00350 double (*function)(), IPOINT *p);
00351 void makecubetable(void);
00352 void freecubetable(void);
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 char *polygonize (function, size, bounds, x, y, z, triproc, mode)
00384 double (*function)(), size, x, y, z;
00385 int bounds, (*triproc)(), mode;
00386 {
00387 PROCESS p;
00388 int n, noabort;
00389 CORNER *setcorner();
00390 TEST in, out, find();
00391
00392 p.function = function;
00393 p.triproc = triproc;
00394 p.size = size;
00395 p.bounds = bounds;
00396 p.delta = size/(double)(RES*RES);
00397
00398
00399
00400 p.centers = (CENTERLIST **) mycalloc(HASHSIZE,sizeof(CENTERLIST *));
00401 p.corners = (CORNERLIST **) mycalloc(HASHSIZE,sizeof(CORNERLIST *));
00402 p.edges = (EDGELIST **) mycalloc(2*HASHSIZE,sizeof(EDGELIST *));
00403 memset(p.centers,0,HASHSIZE*sizeof(CENTERLIST *));
00404 memset(p.corners,0,HASHSIZE*sizeof(CORNERLIST *));
00405 memset(p.edges,0,2*HASHSIZE*sizeof(EDGELIST *));
00406
00407 makecubetable();
00408
00409
00410 srand(1);
00411 in = find(1, &p, x, y, z);
00412 out = find(0, &p, x, y, z);
00413 if (!in.ok || !out.ok) return "can't find starting point";
00414 converge(&in.p, &out.p, in.value, p.function, &p.start);
00415
00416
00417 p.cubes = (CUBES *) mycalloc(1, sizeof(CUBES));
00418 p.cubes->cube.i = p.cubes->cube.j = p.cubes->cube.k = 0;
00419 p.cubes->next = NULL;
00420
00421
00422 for (n = 0; n < 8; n++)
00423 p.cubes->cube.corners[n] = setcorner(&p, BIT(n,2), BIT(n,1), BIT(n,0));
00424
00425 p.vertices.count = p.vertices.max = 0;
00426 p.vertices.ptr = NULL;
00427
00428 setcenter(p.centers, 0, 0, 0);
00429
00430 while (p.cubes != NULL) {
00431 CUBE c;
00432 CUBES *temp = p.cubes;
00433 c = p.cubes->cube;
00434
00435 noabort = mode == TET?
00436
00437 dotet(&c, LBN, LTN, RBN, LBF, &p) &&
00438 dotet(&c, RTN, LTN, LBF, RBN, &p) &&
00439 dotet(&c, RTN, LTN, LTF, LBF, &p) &&
00440 dotet(&c, RTN, RBN, LBF, RBF, &p) &&
00441 dotet(&c, RTN, LBF, LTF, RBF, &p) &&
00442 dotet(&c, RTN, LTF, RTF, RBF, &p)
00443 :
00444
00445 docube(&c, &p);
00446 if (! noabort) return "aborted";
00447
00448
00449 p.cubes = p.cubes->next;
00450
00451 testface(c.i-1, c.j, c.k, &c, L, LBN, LBF, LTN, LTF, &p);
00452 testface(c.i+1, c.j, c.k, &c, R, RBN, RBF, RTN, RTF, &p);
00453 testface(c.i, c.j-1, c.k, &c, B, LBN, LBF, RBN, RBF, &p);
00454 testface(c.i, c.j+1, c.k, &c, T, LTN, LTF, RTN, RTF, &p);
00455 testface(c.i, c.j, c.k-1, &c, N, LBN, LTN, RBN, RTN, &p);
00456 testface(c.i, c.j, c.k+1, &c, F, LBF, LTF, RBF, RTF, &p);
00457
00458 for(n=0;n<8;n++){
00459 if(temp->cube.corners[n] != NULL)free(temp->cube.corners[n]);
00460 }
00461 free((char *) temp);
00462 }
00463 {
00464 CUBES *pc,*temppc;
00465 if((pc=p.cubes) != NULL){
00466 while(pc != NULL){
00467 temppc=pc;
00468 pc=pc->next;
00469 for(n=0;n<8;n++){
00470 if(temppc->cube.corners[n] != NULL)free(temppc->cube.corners[n]);
00471 }
00472 free((char *)temppc);
00473 }
00474 }
00475 }
00476 if(p.centers != NULL){
00477 for(n=0;n<HASHSIZE;n++){
00478 CENTERLIST *xx,*tempxx;
00479 if((xx=p.centers[n]) != NULL){
00480 while(xx != NULL){
00481 tempxx=xx;
00482 xx=xx->next;
00483 free(tempxx);
00484 }
00485 }
00486 }
00487 free(p.centers);
00488 }
00489 if(p.corners != NULL){
00490 for(n=0;n<HASHSIZE;n++){
00491 CORNERLIST *xx,*tempxx;
00492 if((xx=p.corners[n]) != NULL){
00493 while(xx != NULL){
00494 tempxx=xx;
00495 xx=xx->next;
00496 free(tempxx);
00497 }
00498 }
00499 }
00500 free(p.corners);
00501 }
00502 if(p.edges != NULL){
00503 for(n=0;n<2*HASHSIZE;n++){
00504 EDGELIST *xx,*tempxx;
00505 if((xx=p.edges[n]) != NULL){
00506 while(xx != NULL){
00507 tempxx=xx;
00508 xx=xx->next;
00509 free(tempxx);
00510 }
00511 }
00512 }
00513 free(p.edges);
00514 }
00515 freecubetable();
00516 return NULL;
00517 }
00518
00519
00520
00521
00522
00523
00524 static void testface (int i, int j, int k, CUBE *old, int ipface, int c1,
00525 int c2, int c3, int c4, PROCESS *p){
00526 CUBE new;
00527 CUBES *oldcubes = p->cubes;
00528 CORNER *setcorner();
00529 static int ipfacebit[6] = {2, 2, 1, 1, 0, 0};
00530 int n, pos = old->corners[c1]->value > 0.0 ? 1 : 0, bit = ipfacebit[ipface];
00531
00532
00533 if ((old->corners[c2]->value > 0) == pos &&
00534 (old->corners[c3]->value > 0) == pos &&
00535 (old->corners[c4]->value > 0) == pos) return;
00536 if (abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;
00537 if (setcenter(p->centers, i, j, k)) return;
00538
00539
00540 new.i = i;
00541 new.j = j;
00542 new.k = k;
00543 for (n = 0; n < 8; n++) new.corners[n] = NULL;
00544
00545
00546
00547
00548 new.corners[FLIP(c1, bit)] = (CORNER *) mycalloc(1, sizeof(CORNER));
00549 memcpy(new.corners[FLIP(c1,bit)],old->corners[c1],sizeof(CORNER));
00550 new.corners[FLIP(c2, bit)] = (CORNER *) mycalloc(1, sizeof(CORNER));
00551 memcpy(new.corners[FLIP(c2,bit)],old->corners[c2],sizeof(CORNER));
00552 new.corners[FLIP(c3, bit)] = (CORNER *) mycalloc(1, sizeof(CORNER));
00553 memcpy(new.corners[FLIP(c3,bit)],old->corners[c3],sizeof(CORNER));
00554 new.corners[FLIP(c4, bit)] = (CORNER *) mycalloc(1, sizeof(CORNER));
00555 memcpy(new.corners[FLIP(c4,bit)],old->corners[c4],sizeof(CORNER));
00556
00557 for (n = 0; n < 8; n++)
00558 if (new.corners[n] == NULL)
00559 new.corners[n] = setcorner(p, i+BIT(n,2), j+BIT(n,1), k+BIT(n,0));
00560
00561
00562 p->cubes = (CUBES *) mycalloc(1, sizeof(CUBES));
00563 p->cubes->cube = new;
00564 p->cubes->next = oldcubes;
00565 }
00566
00567
00568
00569
00570
00571 CORNER *setcorner (p, i, j, k)
00572 int i, j, k;
00573 PROCESS *p;
00574 {
00575
00576 CORNER *c = (CORNER *) mycalloc(1, sizeof(CORNER));
00577 int index = HASH(i, j, k);
00578 CORNERLIST *l = p->corners[index];
00579 c->i = i; c->x = p->start.x+((double)i-.5)*p->size;
00580 c->j = j; c->y = p->start.y+((double)j-.5)*p->size;
00581 c->k = k; c->z = p->start.z+((double)k-.5)*p->size;
00582 for (; l != NULL; l = l->next)
00583 if (l->i == i && l->j == j && l->k == k) {
00584 c->value = l->value;
00585 return c;
00586 }
00587 l = (CORNERLIST *) mycalloc(1, sizeof(CORNERLIST));
00588 l->i = i; l->j = j; l->k = k;
00589 l->value = c->value = p->function(c->x, c->y, c->z);
00590 l->next = p->corners[index];
00591 p->corners[index] = l;
00592 return c;
00593 }
00594
00595
00596
00597 TEST find (sign, p, x, y, z)
00598 int sign;
00599 PROCESS *p;
00600 double x, y, z;
00601 {
00602 int i;
00603 TEST test;
00604 double range = p->size;
00605 test.ok = 1;
00606 for (i = 0; i < 10000; i++) {
00607 test.p.x = x+range*(RAND()-0.5);
00608 test.p.y = y+range*(RAND()-0.5);
00609 test.p.z = z+range*(RAND()-0.5);
00610 test.value = p->function(test.p.x, test.p.y, test.p.z);
00611 if (sign == (test.value > 0.0)) return test;
00612 range = range*1.0005;
00613 }
00614 test.ok = 0;
00615 return test;
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 int dotet (cube, c1, c2, c3, c4, p)
00627 CUBE *cube;
00628 int c1, c2, c3, c4;
00629 PROCESS *p;
00630 {
00631 CORNER *a = cube->corners[c1];
00632 CORNER *b = cube->corners[c2];
00633 CORNER *c = cube->corners[c3];
00634 CORNER *d = cube->corners[c4];
00635 int index = 0, apos, bpos, cpos, dpos, e1, e2, e3, e4, e5, e6;
00636 if (apos = (a->value > 0.0)) index += 8;
00637 if (bpos = (b->value > 0.0)) index += 4;
00638 if (cpos = (c->value > 0.0)) index += 2;
00639 if (dpos = (d->value > 0.0)) index += 1;
00640
00641 if (apos != bpos) e1 = vertid(a, b, p);
00642 if (apos != cpos) e2 = vertid(a, c, p);
00643 if (apos != dpos) e3 = vertid(a, d, p);
00644 if (bpos != cpos) e4 = vertid(b, c, p);
00645 if (bpos != dpos) e5 = vertid(b, d, p);
00646 if (cpos != dpos) e6 = vertid(c, d, p);
00647
00648 switch (index) {
00649 case 1: return p->triproc(e5, e6, e3, p->vertices);
00650 case 2: return p->triproc(e2, e6, e4, p->vertices);
00651 case 3: return p->triproc(e3, e5, e4, p->vertices) &&
00652 p->triproc(e3, e4, e2, p->vertices);
00653 case 4: return p->triproc(e1, e4, e5, p->vertices);
00654 case 5: return p->triproc(e3, e1, e4, p->vertices) &&
00655 p->triproc(e3, e4, e6, p->vertices);
00656 case 6: return p->triproc(e1, e2, e6, p->vertices) &&
00657 p->triproc(e1, e6, e5, p->vertices);
00658 case 7: return p->triproc(e1, e2, e3, p->vertices);
00659 case 8: return p->triproc(e1, e3, e2, p->vertices);
00660 case 9: return p->triproc(e1, e5, e6, p->vertices) &&
00661 p->triproc(e1, e6, e2, p->vertices);
00662 case 10: return p->triproc(e1, e3, e6, p->vertices) &&
00663 p->triproc(e1, e6, e4, p->vertices);
00664 case 11: return p->triproc(e1, e5, e4, p->vertices);
00665 case 12: return p->triproc(e3, e2, e4, p->vertices) &&
00666 p->triproc(e3, e4, e5, p->vertices);
00667 case 13: return p->triproc(e6, e2, e4, p->vertices);
00668 case 14: return p->triproc(e5, e3, e6, p->vertices);
00669 }
00670 return 1;
00671 }
00672
00673
00674
00675 #define LB 0
00676 #define LT 1
00677 #define LN 2
00678 #define LF 3
00679 #define RB 4
00680 #define RT 5
00681 #define RN 6
00682 #define RF 7
00683 #define BN 8
00684 #define BF 9
00685 #define TN 10
00686 #define TF 11
00687
00688 static INTLISTS *cubetable[256];
00689
00690
00691 static int corner1[12] = {LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF};
00692 static int corner2[12] = {LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF};
00693 static int leftface[12] = {B, L, L, F, R, T, N, R, N, B, T, F};
00694
00695 static int rightface[12] = {L, T, N, L, B, R, R, F, B, F, N, T};
00696
00697
00698
00699
00700
00701 int docube (cube, p)
00702 CUBE *cube;
00703 PROCESS *p;
00704 {
00705 INTLISTS *polys;
00706 int i, index = 0;
00707 for (i = 0; i < 8; i++) if (cube->corners[i]->value > 0.0) index += (1<<i);
00708 for (polys = cubetable[index]; polys; polys = polys->next) {
00709 INTLIST *edges;
00710 int a = -1, b = -1, count = 0;
00711 for (edges = polys->list; edges; edges = edges->next) {
00712 CORNER *c1 = cube->corners[corner1[edges->i]];
00713 CORNER *c2 = cube->corners[corner2[edges->i]];
00714 int c = vertid(c1, c2, p);
00715 if (++count > 2 && ! p->triproc(a, b, c, p->vertices)) return 0;
00716 if (count < 3) a = b;
00717 b = c;
00718 }
00719 }
00720 return 1;
00721 }
00722
00723
00724
00725
00726 int nextcwedge (ipedge, ipface)
00727 int ipedge, ipface;
00728 {
00729 switch (ipedge) {
00730 case LB: return (ipface == L)? LF : BN;
00731 case LT: return (ipface == L)? LN : TF;
00732 case LN: return (ipface == L)? LB : TN;
00733 case LF: return (ipface == L)? LT : BF;
00734 case RB: return (ipface == R)? RN : BF;
00735 case RT: return (ipface == R)? RF : TN;
00736 case RN: return (ipface == R)? RT : BN;
00737 case RF: return (ipface == R)? RB : TF;
00738 case BN: return (ipface == B)? RB : LN;
00739 case BF: return (ipface == B)? LB : RF;
00740 case TN: return (ipface == T)? LT : RN;
00741 case TF: return (ipface == T)? RT : LF;
00742 }
00743 }
00744
00745
00746
00747
00748 int otherface (ipedge, ipface)
00749 int ipedge, ipface;
00750 {
00751 int other = leftface[ipedge];
00752 return ipface == other? rightface[ipedge] : other;
00753 }
00754
00755
00756
00757
00758 void makecubetable (void){
00759 int i, e, c, done[12], pos[8];
00760 for (i = 0; i < 256; i++) {
00761 cubetable[i]=NULL;
00762 for (e = 0; e < 12; e++) done[e] = 0;
00763 for (c = 0; c < 8; c++) pos[c] = BIT(i, c);
00764 for (e = 0; e < 12; e++)
00765 if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
00766 INTLIST *ints = 0;
00767 INTLISTS *lists = (INTLISTS *) mycalloc(1, sizeof(INTLISTS));
00768 int start = e, ipedge = e;
00769
00770 int ipface = pos[corner1[e]]? rightface[e] : leftface[e];
00771 while (1) {
00772 ipedge = nextcwedge(ipedge, ipface);
00773 done[ipedge] = 1;
00774 if (pos[corner1[ipedge]] != pos[corner2[ipedge]]) {
00775 INTLIST *tmp = ints;
00776 ints = (INTLIST *) mycalloc(1, sizeof(INTLIST));
00777 ints->i = ipedge;
00778 ints->next = tmp;
00779 if (ipedge == start) break;
00780 ipface = otherface(ipedge, ipface);
00781 }
00782 }
00783 lists->list = ints;
00784 lists->next = cubetable[i];
00785 cubetable[i] = lists;
00786 }
00787 }
00788 }
00789
00790 void freecubetable(void){
00791 int i;
00792 INTLIST *il,*tempil;
00793 INTLISTS *ils,*tempils;
00794 for(i=0;i<256;i++){
00795 if((ils=cubetable[i]) != NULL){
00796 while(ils != NULL){
00797 tempils=ils;
00798 if((il=ils->list) !=NULL){
00799 while(il != NULL){
00800 tempil=il;
00801 il=il->next;
00802 free(tempil);
00803 }
00804 }
00805 ils=ils->next;
00806 free(tempils);
00807 }
00808 }
00809 }
00810 }
00811
00812
00813
00814
00815
00816 char *mycalloc (nitems, nbytes)
00817 int nitems, nbytes;
00818 {
00819 char *ptr = calloc(nitems, nbytes);
00820 if (ptr != NULL) return ptr;
00821 MessageBox(NULL,"Memory Error",NULL,MB_OK);
00822 return NULL;
00823 }
00824
00825
00826
00827
00828
00829 int setcenter(table, i, j, k)
00830 CENTERLIST *table[];
00831 int i, j, k;
00832 {
00833 int index = HASH(i, j, k);
00834 CENTERLIST *new, *l, *q = table[index];
00835 for (l = q; l != NULL; l = l->next)
00836 if (l->i == i && l->j == j && l->k == k) return 1;
00837 new = (CENTERLIST *) mycalloc(1, sizeof(CENTERLIST));
00838 new->i = i; new->j = j; new->k = k; new->next = q;
00839 table[index] = new;
00840 return 0;
00841 }
00842
00843
00844
00845
00846 setedge (table, i1, j1, k1, i2, j2, k2, vid)
00847 EDGELIST *table[];
00848 int i1, j1, k1, i2, j2, k2, vid;
00849 {
00850 unsigned int index;
00851 EDGELIST *new;
00852 if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
00853 int t=i1; i1=i2; i2=t; t=j1; j1=j2; j2=t; t=k1; k1=k2; k2=t;
00854 }
00855 index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
00856 new = (EDGELIST *) mycalloc(1, sizeof(EDGELIST));
00857 new->i1 = i1; new->j1 = j1; new->k1 = k1;
00858 new->i2 = i2; new->j2 = j2; new->k2 = k2;
00859 new->vid = vid;
00860 new->next = table[index];
00861 table[index] = new;
00862 }
00863
00864
00865
00866 int getedge (table, i1, j1, k1, i2, j2, k2)
00867 EDGELIST *table[];
00868 int i1, j1, k1, i2, j2, k2;
00869 {
00870 EDGELIST *q;
00871 if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
00872 int t=i1; i1=i2; i2=t; t=j1; j1=j2; j2=t; t=k1; k1=k2; k2=t;
00873 };
00874 q = table[HASH(i1, j1, k1)+HASH(i2, j2, k2)];
00875 for (; q != NULL; q = q->next)
00876 if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
00877 q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
00878 return q->vid;
00879 return -1;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 int vertid (c1, c2, p)
00891 CORNER *c1, *c2;
00892 PROCESS *p;
00893 {
00894 IVERTEX v;
00895 IPOINT a, b;
00896 int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
00897 if (vid != -1) return vid;
00898 a.x = c1->x; a.y = c1->y; a.z = c1->z;
00899 b.x = c2->x; b.y = c2->y; b.z = c2->z;
00900 converge(&a, &b, c1->value, p->function, &v.position);
00901 vnormal(&v.position, p, &v.normal);
00902 addtovertices(&p->vertices, v);
00903 vid = p->vertices.count-1;
00904 setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
00905 return vid;
00906 }
00907
00908
00909
00910
00911 addtovertices (vertices, v)
00912 IVERTICES *vertices;
00913 IVERTEX v;
00914 {
00915 if (vertices->count == vertices->max) {
00916 int i;
00917 IVERTEX *new;
00918 vertices->max = vertices->count == 0 ? 10 : 2*vertices->count;
00919 new = (IVERTEX *) mycalloc(vertices->max, sizeof(IVERTEX));
00920 for (i = 0; i < vertices->count; i++) new[i] = vertices->ptr[i];
00921 if (vertices->ptr != NULL) free((char *) vertices->ptr);
00922 vertices->ptr = new;
00923 }
00924 vertices->ptr[vertices->count++] = v;
00925 }
00926
00927
00928
00929
00930 vnormal (ipt, p, v)
00931 IPOINT *ipt, *v;
00932 PROCESS *p;
00933 {
00934 double f = p->function(ipt->x, ipt->y, ipt->z);
00935 v->x = p->function(ipt->x+p->delta, ipt->y, ipt->z)-f;
00936 v->y = p->function(ipt->x, ipt->y+p->delta, ipt->z)-f;
00937 v->z = p->function(ipt->x, ipt->y, ipt->z+p->delta)-f;
00938 f = sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
00939 if (f != 0.0) {v->x /= f; v->y /= f; v->z /= f;}
00940 }
00941
00942
00943
00944
00945 static void converge (IPOINT *p1, IPOINT *p2, double v,
00946 double (*function)(), IPOINT *p){
00947 int i = 0;
00948 IPOINT pos, neg;
00949 if (v < 0) {
00950 pos.x = p2->x; pos.y = p2->y; pos.z = p2->z;
00951 neg.x = p1->x; neg.y = p1->y; neg.z = p1->z;
00952 }
00953 else {
00954 pos.x = p1->x; pos.y = p1->y; pos.z = p1->z;
00955 neg.x = p2->x; neg.y = p2->y; neg.z = p2->z;
00956 }
00957 while (1) {
00958 p->x = 0.5*(pos.x + neg.x);
00959 p->y = 0.5*(pos.y + neg.y);
00960 p->z = 0.5*(pos.z + neg.z);
00961 if (i++ == RES) return;
00962 if ((function(p->x, p->y, p->z)) > 0.0)
00963 {pos.x = p->x; pos.y = p->y; pos.z = p->z;}
00964 else {neg.x = p->x; neg.y = p->y; neg.z = p->z;}
00965 }
00966 }