Subversion Repositories gelsvn

Rev

Rev 136 | Rev 417 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
61 jab 1
/**********************************************************************
2
 
3
polygonizer.h
4
 
5
This is Jules Bloomenthal's implicit surface polygonizer from GRAPHICS 
6
GEMS IV. Bloomenthal's polygonizer is still used and the present code
7
is simply the original code morphed into C++.
8
 
9
J. Andreas Bærentzen 2003.
10
 
11
**********************************************************************/
12
 
385 jab 13
#include <string>
61 jab 14
#include <stdlib.h>
15
#include <math.h>
16
#include <iostream>
17
#include <vector>
18
#include <list>
19
#include <sys/types.h>
20
#include "Polygonizer.h"
21
 
22
using namespace std;
23
 
64 jab 24
namespace Geometry
61 jab 25
{
26
 
27
	namespace
28
	{
29
		const int RES =	10; /* # converge iterations    */
30
 
31
		const int L =	0;  /* left direction:	-x, -i */
32
		const int R =	1;  /* right direction:	+x, +i */
33
		const int B =	2;  /* bottom direction: -y, -j */
34
		const int T =	3;  /* top direction:	+y, +j */
35
		const int N =	4;  /* near direction:	-z, -k */
36
		const int F =	5;  /* far direction:	+z, +k */
37
		const int LBN =	0;  /* left bottom near corner  */
38
		const int LBF =	1;  /* left bottom far corner   */
39
		const int LTN =	2;  /* left top near corner     */
40
		const int LTF =	3;  /* left top far corner      */
41
		const int RBN =	4;  /* right bottom near corner */
42
		const int RBF =	5;  /* right bottom far corner  */
43
		const int RTN =	6;  /* right top near corner    */
44
		const int RTF =	7;  /* right top far corner     */
45
 
46
 
47
		/* the LBN corner of cube (i, j, k), corresponds with location
48
		 * (start.x+(i-.5)*size, start.y+(j-.5)*size, start.z+(k-.5)*size) */
49
 
50
		inline float RAND() 
51
		{
52
			return (rand()&32767)/32767.0f;
53
		}
54
 
55
		const int HASHBIT = 5;
56
 
57
		const int HASHSIZE = (size_t)(1<<(3*HASHBIT));   
58
 
59
		const int MASK = ((1<<HASHBIT)-1);
60
 
61
		inline int HASH( int i, int j,int k) 
62
		{ 
63
			return (((((i&MASK)<<HASHBIT)|j&MASK)<<HASHBIT)|k&MASK);
64
		} 
65
 
66
		inline int BIT(int i, int bit) 
67
		{ 
68
			return (i>>bit)&1; 
69
		}
70
 
71
		// flip the given bit of i 
72
		inline int FLIP(int i, int bit) 
73
		{
74
			return i^1<<bit;
75
		}
76
 
77
		struct TEST {		   /* test the function for a signed value */
78
			POINT p;			   /* location of test */
79
			float value;		   /* function value at p */
80
			int ok;			   /* if value is of correct sign */
81
		};
82
 
83
		struct CORNER {		   /* corner of a cube */
84
			int i, j, k;		   /* (i, j, k) is index within lattice */
85
			float x, y, z, value;	   /* location and function value */
86
		};
87
 
88
		struct CUBE {		   /* partitioning cell (cube) */
89
			int i, j, k;		   /* lattice location of cube */
90
			CORNER *corners[8];		   /* eight corners */
91
		};
92
 
93
		struct CENTERELEMENT {	   /* list of cube locations */
94
			int i, j, k;		   /* cube location */
95
			CENTERELEMENT(int _i, int _j, int _k): i(_i), j(_j), k(_k) {}
96
		};
97
		typedef list<CENTERELEMENT> CENTERLIST;
98
 
99
		struct CORNERELEMENT {	   /* list of corners */
100
			int i, j, k;		   /* corner id */
101
			float value;		   /* corner value */
102
			CORNERELEMENT(int _i, int _j, int _k, float _value):
103
				i(_i), j(_j), k(_k), value(_value) {}
104
		};
105
		typedef list<CORNERELEMENT> CORNERLIST;
106
 
107
		struct EDGEELEMENT {	   /* list of edges */
108
			int i1, j1, k1, i2, j2, k2;	   /* edge corner ids */
109
			int vid;			   /* vertex id */
110
		};
111
 
112
		typedef list<EDGEELEMENT> EDGELIST;
113
		typedef list<int> INTLIST;
114
		typedef list<INTLIST> INTLISTS;
115
 
116
 
117
		//----------------------------------------------------------------------
118
		// Implicit surface evaluation functions
119
		//----------------------------------------------------------------------
120
 
121
		/* converge: from two points of differing sign, converge to zero crossing */
122
 
123
		void converge (POINT* p1, POINT* p2, float v, 
124
									 ImplicitFunction* function, POINT* p)
125
		{
126
			int i = 0;
127
			POINT pos, neg;
128
			if (v < 0) {
129
				pos.x = p2->x; pos.y = p2->y; pos.z = p2->z;
130
				neg.x = p1->x; neg.y = p1->y; neg.z = p1->z;
131
			}
132
			else {
133
				pos.x = p1->x; pos.y = p1->y; pos.z = p1->z;
134
				neg.x = p2->x; neg.y = p2->y; neg.z = p2->z;
135
			}
136
			while (1) {
102 bj 137
				p->x = 0.5f*(pos.x + neg.x);
138
				p->y = 0.5f*(pos.y + neg.y);
139
				p->z = 0.5f*(pos.z + neg.z);
61 jab 140
				if (i++ == RES) return;
141
				if ((function->eval(p->x, p->y, p->z)) > 0.0)
142
					{pos.x = p->x; pos.y = p->y; pos.z = p->z;}
143
				else {neg.x = p->x; neg.y = p->y; neg.z = p->z;}
144
			}
145
		}
146
 
147
 
148
		/* vnormal: compute unit length surface normal at point */
149
 
150
		inline void vnormal (ImplicitFunction* function, POINT* point, POINT* n, float delta)
151
		{
152
			float f = function->eval(point->x, point->y, point->z);
153
			n->x = function->eval(point->x+delta, point->y, point->z)-f;
154
			n->y = function->eval(point->x, point->y+delta, point->z)-f;
155
			n->z = function->eval(point->x, point->y, point->z+delta)-f;
156
			f = sqrt(n->x*n->x + n->y*n->y + n->z*n->z);
157
			if (f != 0.0) {n->x /= f; n->y /= f; n->z /= f;}
158
		}
159
 
160
 
161
 
162
		// ----------------------------------------------------------------------
163
 
164
		class EDGETABLE
165
		{
166
			vector<EDGELIST> table;		   /* edge and vertex id hash table */
167
 
168
		public:
169
 
170
			EDGETABLE(): table(2*HASHSIZE) {}
171
 
172
			void setedge (int i1, int j1, int k1, 
173
										int i2, int j2, int k2, int vid);
174
			int getedge (int i1, int j1, int k1, 
175
									 int i2, int j2, int k2);
176
 
177
 
178
		};
179
 
180
		/* setedge: set vertex id for edge */
181
		void EDGETABLE::setedge (int i1, int j1, int k1, 
182
														 int i2, int j2, int k2, int vid)
183
		{
184
			unsigned int index;
185
 
186
			if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
187
				int t=i1; i1=i2; i2=t; t=j1; j1=j2; j2=t; t=k1; k1=k2; k2=t;
188
			}
189
			index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
190
 
191
			EDGEELEMENT new_obj;
192
			new_obj.i1 = i1; 
193
			new_obj.j1 = j1; 
194
			new_obj.k1 = k1;
195
			new_obj.i2 = i2; 
196
			new_obj.j2 = j2; 
197
			new_obj.k2 = k2;
198
			new_obj.vid = vid;
199
			table[index].push_front(new_obj);
200
		}
201
 
202
 
203
		/* getedge: return vertex id for edge; return -1 if not set */
204
 
205
		int EDGETABLE::getedge (int i1, int j1, int k1, int i2, int j2, int k2)
206
		{
207
 
208
			if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
209
				int t=i1; i1=i2; i2=t; t=j1; j1=j2; j2=t; t=k1; k1=k2; k2=t;
210
			};
211
			int hashval = HASH(i1, j1, k1)+HASH(i2, j2, k2);
212
			EDGELIST::const_iterator q = table[hashval].begin();
213
			for (; q != table[hashval].end(); ++q)
214
				if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
215
						q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
216
					return q->vid;
217
			return -1;
218
		}
219
 
220
 
221
		// ----------------------------------------------------------------------
222
		class PROCESS
223
		{	   /* parameters, function, storage */
224
 
225
			std::vector<NORMAL>* gnormals;  
226
			std::vector<VERTEX>* gvertices;  
227
			std::vector<TRIANGLE> *gtriangles;
228
 
229
			ImplicitFunction* function;	   /* implicit surface function */
230
 
231
			float size, delta;		   /* cube size, normal delta */
232
			int bounds;			   /* cube range within lattice */
233
			POINT start;		   /* start point on surface */
234
			bool use_normals;
235
 
236
			// Global list of corners (keeps track of memory)
237
			list<CORNER> corner_lst;
238
			list<CUBE> cubes;		   /* active cubes */
239
			vector<CENTERLIST> centers;	   /* cube center hash table */
240
			vector<CORNERLIST> corners;	   /* corner value hash table */
241
			EDGETABLE edges;
242
 
243
			CORNER *setcorner (int i, int j, int k);
244
 
245
			void testface (int i, int j, int k, CUBE* old, 
246
										 int face, int c1, int c2, int c3, int c4); 
247
 
248
			TEST find (int sign, float x, float y, float z);
249
 
250
			int vertid (CORNER* c1, CORNER* c2);
251
 
252
			int dotet (CUBE* cube, int c1, int c2, int c3, int c4);
253
 
254
			int docube (CUBE* cube);
255
 
256
			int triangle (int i1, int i2, int i3)
257
			{
258
				TRIANGLE t;
259
				t.v0 = i1;
260
				t.v1 = i2;
261
				t.v2 = i3;
262
				(*gtriangles).push_back(t);
263
				return 1;
264
			}
265
 
266
		public:
267
			PROCESS(ImplicitFunction* _function,
268
							float _size, float _delta, 
269
							int _bounds,
270
							vector<VERTEX>& _gvertices,
271
							vector<NORMAL>& _gnormals,
272
							vector<TRIANGLE>& _gtriangles,
273
							bool _compute_normals=false);
274
 
275
 
276
			~PROCESS() {}
277
 
278
			void march(int mode, float x, float y, float z);
279
 
280
		};
281
 
282
 
283
		/* setcenter: set (i,j,k) entry of table[]
284
			 return 1 if already set; otherwise, set and return 0 */
285
		int setcenter(vector<CENTERLIST>& table,
286
									int i, int j, int k)
287
		{
288
			int index = HASH(i,j,k);
289
			CENTERLIST::const_iterator q = table[index].begin();
290
			for(; q != table[index].end(); ++q)
291
				if(q->i == i && q->j==j && q->k == k) return 1;
292
 
293
			CENTERELEMENT elem(i,j,k);
294
			table[index].push_front(elem);
295
			return 0;
296
		}
297
 
298
		/* setcorner: return corner with the given lattice location
299
			 set (and cache) its function value */
300
		CORNER* PROCESS::setcorner (int i, int j, int k)
301
		{
302
			/* for speed, do corner value caching here */
303
			corner_lst.push_back(CORNER());
304
			CORNER *c = &corner_lst.back();
305
			int index = HASH(i, j, k);
306
 
102 bj 307
			c->i = i; c->x = start.x+((float)i-.5f)*size;
308
			c->j = j; c->y = start.y+((float)j-.5f)*size;
309
			c->k = k; c->z = start.z+((float)k-.5f)*size;
61 jab 310
 
311
			CORNERLIST::const_iterator l = corners[index].begin();
312
			for (; l != corners[index].end(); ++l)
313
				if (l->i == i && l->j == j && l->k == k) {
314
					c->value = l->value;
315
					return c;
316
				}
317
 
318
			c->value = function->eval(c->x, c->y, c->z);
319
			CORNERELEMENT elem(i,j,k,c->value);
320
			corners[index].push_front(elem);
321
			return c;
322
		}
323
 
324
 
325
 
326
		/* testface: given cube at lattice (i, j, k), and four corners of face,
327
		 * if surface crosses face, compute other four corners of adjacent cube
328
		 * and add new cube to cube stack */
329
 
330
		inline void PROCESS::testface (int i, int j, int k, CUBE* old, 
331
														int face, int c1, int c2, int c3, int c4) 
332
		{
333
			CUBE new_obj;
334
 
335
			static int facebit[6] = {2, 2, 1, 1, 0, 0};
336
			int n, pos = old->corners[c1]->value > 0.0 ? 1 : 0, bit = facebit[face];
337
 
338
			/* test if no surface crossing, cube out of bounds, or already visited: */
339
			if ((old->corners[c2]->value > 0) == pos &&
340
					(old->corners[c3]->value > 0) == pos &&
341
					(old->corners[c4]->value > 0) == pos) return;
342
			if (abs(i) > bounds || abs(j) > bounds || abs(k) > bounds) return;
343
			if (setcenter(centers, i, j, k)) return;
344
 
345
			/* create new_obj cube: */
346
			new_obj.i = i;
347
			new_obj.j = j;
348
			new_obj.k = k;
349
			for (n = 0; n < 8; n++) new_obj.corners[n] = 0;
350
			new_obj.corners[FLIP(c1, bit)] = old->corners[c1];
351
			new_obj.corners[FLIP(c2, bit)] = old->corners[c2];
352
			new_obj.corners[FLIP(c3, bit)] = old->corners[c3];
353
			new_obj.corners[FLIP(c4, bit)] = old->corners[c4];
354
			for (n = 0; n < 8; n++)
355
				if (new_obj.corners[n] == 0)
356
					new_obj.corners[n] = setcorner(i+BIT(n,2), j+BIT(n,1), k+BIT(n,0));
357
 
358
			// Add new cube to top of stack
359
			cubes.push_front(new_obj);
360
		}
361
 
362
		/* find: search for point with value of given sign (0: neg, 1: pos) */
363
 
364
		TEST PROCESS::find (int sign, float x, float y, float z)
365
		{
366
			int i;
367
			TEST test;
368
			float range = size;
369
			test.ok = 1;
370
			for (i = 0; i < 10000; i++) {
102 bj 371
				test.p.x = x+range*(RAND()-0.5f);
372
				test.p.y = y+range*(RAND()-0.5f);
373
				test.p.z = z+range*(RAND()-0.5f);
61 jab 374
				test.value = function->eval(test.p.x, test.p.y, test.p.z);
375
				if (sign == (test.value > 0.0)) return test;
102 bj 376
				range = range*1.0005f; /* slowly expand search outwards */
61 jab 377
			}
378
			test.ok = 0;
379
			return test;
380
		}
381
 
382
 
383
		/* vertid: return index for vertex on edge:
384
		 * c1->value and c2->value are presumed of different sign
385
		 * return saved index if any; else compute vertex and save */
386
 
387
		int PROCESS::vertid (CORNER* c1, CORNER* c2)
388
		{
389
			VERTEX v;
390
			NORMAL n;
391
			POINT a, b;
392
			int vid = edges.getedge(c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
393
			if (vid != -1) return vid;			     /* previously computed */
394
			a.x = c1->x; a.y = c1->y; a.z = c1->z;
395
			b.x = c2->x; b.y = c2->y; b.z = c2->z;
396
			converge(&a, &b, c1->value, function, &v); /* position */
397
			(*gvertices).push_back(v);			   /* save vertex */
398
			if(use_normals)
399
				{
400
					vnormal(function, &v, &n, delta);			   /* normal */
401
					(*gnormals).push_back(n);			   /* save vertex */
402
				}
403
			vid = gvertices->size()-1;
404
			edges.setedge(c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
405
			return vid;
406
		}
407
 
408
 
409
 
410
 
411
		/**** Tetrahedral Polygonization ****/
412
 
413
 
414
		/* dotet: triangulate the tetrahedron
415
		 * b, c, d should appear clockwise when viewed from a
416
		 * return 0 if client aborts, 1 otherwise */
417
 
418
		int PROCESS::dotet (CUBE* cube, int c1, int c2, int c3, int c4)
419
		{
420
			CORNER *a = cube->corners[c1];
421
			CORNER *b = cube->corners[c2];
422
			CORNER *c = cube->corners[c3];
423
			CORNER *d = cube->corners[c4];
424
			int index = 0, apos, bpos, cpos, dpos, e1, e2, e3, e4, e5, e6;
136 jab 425
			if ((apos = (a->value > 0.0))) index += 8;
426
			if ((bpos = (b->value > 0.0))) index += 4;
427
			if ((cpos = (c->value > 0.0))) index += 2;
428
			if ((dpos = (d->value > 0.0))) index += 1;
61 jab 429
			/* index is now 4-bit number representing one of the 16 possible cases */
430
			if (apos != bpos) e1 = vertid(a, b);
431
			if (apos != cpos) e2 = vertid(a, c);
432
			if (apos != dpos) e3 = vertid(a, d);
433
			if (bpos != cpos) e4 = vertid(b, c);
434
			if (bpos != dpos) e5 = vertid(b, d);
435
			if (cpos != dpos) e6 = vertid(c, d);
436
			/* 14 productive tetrahedral cases (0000 and 1111 do not yield polygons */
437
			switch (index) {
438
			case 1:	 return triangle(e5, e6, e3);
439
			case 2:	 return triangle(e2, e6, e4);
440
			case 3:	 return triangle(e3, e5, e4) &&
441
								 triangle(e3, e4, e2);
442
			case 4:	 return triangle(e1, e4, e5);
443
			case 5:	 return triangle(e3, e1, e4) &&
444
								 triangle(e3, e4, e6);
445
			case 6:	 return triangle(e1, e2, e6) &&
446
								 triangle(e1, e6, e5);
447
			case 7:	 return triangle(e1, e2, e3);
448
			case 8:	 return triangle(e1, e3, e2);
449
			case 9:	 return triangle(e1, e5, e6) &&
450
								 triangle(e1, e6, e2);
451
			case 10: return triangle(e1, e3, e6) &&
452
								 triangle(e1, e6, e4);
453
			case 11: return triangle(e1, e5, e4);
454
			case 12: return triangle(e3, e2, e4) &&
455
								 triangle(e3, e4, e5);
456
			case 13: return triangle(e6, e2, e4);
457
			case 14: return triangle(e5, e3, e6);
458
			}
459
			return 1;
460
		}
461
 
462
 
463
		/**** Cubical Polygonization (optional) ****/
464
 
465
 
466
		const int LB =	0;  /* left bottom edge	*/
467
		const int LT =	1;  /* left top edge	*/
468
		const int LN =	2;  /* left near edge	*/
469
		const int LF =	3;  /* left far edge	*/
470
		const int RB =	4;  /* right bottom edge */
471
		const int RT =	5;  /* right top edge	*/
472
		const int RN =	6;  /* right near edge	*/
473
		const int RF =	7;  /* right far edge	*/
474
		const int BN =	8;  /* bottom near edge	*/
475
		const int BF =	9;  /* bottom far edge	*/
476
		const int TN =	10; /* top near edge	*/
477
		const int TF =	11; /* top far edge	*/
478
 
479
 
480
		class CUBETABLE
481
		{
482
			vector<INTLISTS> ctable;
483
			int nextcwedge (int edge, int face);
484
			int otherface (int edge, int face);
485
 
486
		public:
487
 
488
			CUBETABLE();
489
 
490
			const INTLISTS& get_lists(int i) const
491
			{
492
				return ctable[i];
493
			}
494
		};
495
 
496
		/*			edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
497
		const int corner1[12]	   = {LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF};
498
		const int corner2[12]	   = {LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF};
499
		const int leftface[12]	   = {B,  L,  L,  F,  R,  T,  N,  R,  N,  B,  T,  F};
500
		/* face on left when going corner1 to corner2 */
501
		const int rightface[12]   = {L,  T,  N,  L,  B,  R,  R,  F,  B,  F,  N,  T};
502
		/* face on right when going corner1 to corner2 */
503
 
504
 
505
		/* nextcwedge: return next clockwise edge from given edge around given face */
506
 
507
		inline int CUBETABLE::nextcwedge (int edge, int face)
508
		{
509
			switch (edge) {
510
			case LB: return (face == L)? LF : BN;
511
			case LT: return (face == L)? LN : TF;
512
			case LN: return (face == L)? LB : TN;
513
			case LF: return (face == L)? LT : BF;
514
			case RB: return (face == R)? RN : BF;
515
			case RT: return (face == R)? RF : TN;
516
			case RN: return (face == R)? RT : BN;
517
			case RF: return (face == R)? RB : TF;
518
			case BN: return (face == B)? RB : LN;
519
			case BF: return (face == B)? LB : RF;
520
			case TN: return (face == T)? LT : RN;
521
			case TF: return (face == T)? RT : LF;
522
			}
102 bj 523
			return -1;
61 jab 524
		}
525
 
526
		/* otherface: return face adjoining edge that is not the given face */
527
 
528
		inline int CUBETABLE::otherface (int edge, int face)
529
		{
530
			int other = leftface[edge];
531
			return face == other? rightface[edge] : other;
532
		}
533
 
534
 
535
		CUBETABLE::CUBETABLE(): ctable(256)
536
		{
537
			int i, e, c, done[12], pos[8];
538
			for (i = 0; i < 256; i++) 
539
				{
540
					for (e = 0; e < 12; e++) 
541
						done[e] = 0;
542
					for (c = 0; c < 8; c++) 
543
						pos[c] = BIT(i, c);
544
					for (e = 0; e < 12; e++)
545
						if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) 
546
							{
547
								INTLIST ints;
548
								int start = e, edge = e;
549
 
550
								/* get face that is to right of edge from pos to neg corner: */
551
								int face = pos[corner1[e]]? rightface[e] : leftface[e];
552
								while (1) 
553
									{
554
										edge = nextcwedge(edge, face);
555
										done[edge] = 1;
556
										if (pos[corner1[edge]] != pos[corner2[edge]]) 
557
											{
558
												ints.push_front(edge);
559
												if (edge == start) 
560
													break;
561
												face = otherface(edge, face);
562
											}
563
									}
564
								ctable[i].push_front(ints);
565
							}
566
				}
567
		}
568
 
569
		inline const INTLISTS& get_cubetable_entry(int i) 
570
		{
571
			static CUBETABLE c;
572
			return c.get_lists(i);
573
		}
574
 
575
 
576
		/* docube: triangulate the cube directly, without decomposition */
577
 
578
		int PROCESS::docube (CUBE* cube)
579
		{
580
			int index = 0;
581
			for (int i = 0; i < 8; i++) 
582
				if (cube->corners[i]->value > 0.0) 
583
					index += (1<<i);
584
 
585
			INTLISTS intlists = get_cubetable_entry(index);
586
			INTLISTS::const_iterator polys = intlists.begin();
587
			for (; polys != intlists.end(); ++polys) 
588
				{
589
					INTLIST::const_iterator edges = polys->begin();
590
					int a = -1, b = -1, count = 0;
591
					for (; edges != polys->end(); ++edges) 
592
						{
593
							CORNER *c1 = cube->corners[corner1[(*edges)]];
594
							CORNER *c2 = cube->corners[corner2[(*edges)]];
595
							int c = vertid(c1, c2);
596
							if (++count > 2 && ! triangle(a, b, c)) 
597
								return 0;
598
							if (count < 3) 
599
								a = b;
600
							b = c;
601
						}
602
				}
603
			return 1;
604
		}
605
 
606
 
607
 
608
 
609
 
610
 
611
 
612
		/**** An Implicit Surface Polygonizer ****/
613
 
614
 
615
		/* polygonize: polygonize the implicit surface function
616
		 *   arguments are:
617
		 *	 ImplicitFunction
618
		 *	     the implicit surface function
619
		 *	     return negative for inside, positive for outside
620
		 *	 float size
621
		 *	     width of the partitioning cube
622
		 *   float delta 
623
		 *       a small step - used for gradient computation
624
		 *	 int bounds
625
		 *	     max. range of cubes (+/- on the three axes) from first cube
626
		 *   _gvertices, _gnormals, _gtriangles
627
		 *       the data structures into which information is put.
628
		 */
629
 
630
		PROCESS::PROCESS(ImplicitFunction* _function,
631
										 float _size, float _delta, 
632
										 int _bounds, 
633
										 vector<VERTEX>& _gvertices,
634
										 vector<NORMAL>& _gnormals,
635
										 vector<TRIANGLE>& _gtriangles,
636
										 bool _use_normals):
637
			function(_function), size(_size), delta(_delta), bounds(_bounds),
638
			centers(HASHSIZE), corners(HASHSIZE), 
639
			gvertices(&_gvertices),
640
			gnormals(&_gnormals),
641
			gtriangles(&_gtriangles),
642
			use_normals(_use_normals)
643
		{}
644
 
645
		void PROCESS::march(int mode, float x, float y, float z)
646
		{
647
			int noabort;
648
			TEST in, out;
649
 
650
			/* find point on surface, beginning search at (x, y, z): */
651
			srand(1);
652
			in = find(1, x, y, z);
653
			out = find(0, x, y, z);
654
			if (!in.ok || !out.ok) 
385 jab 655
            {
656
                exit(1);
657
            }
61 jab 658
			converge(&in.p, &out.p, in.value, function, &start);
659
 
660
			/* push initial cube on stack: */
661
			CUBE cube;
662
			cube.i = cube.j = cube.k = 0;
663
			cubes.push_front(cube);
664
 
665
			/* set corners of initial cube: */
666
			for (int n = 0; n < 8; n++)
667
				cubes.front().corners[n] = setcorner(BIT(n,2), BIT(n,1), BIT(n,0));
668
 
669
			setcenter(centers, 0, 0, 0);
670
 
671
			while (cubes.size() != 0) 
672
				{
673
					/* process active cubes till none left */
674
					CUBE c = cubes.front();
675
 
676
					noabort = mode == TET?
677
						/* either decompose into tetrahedra and polygonize: */
678
						dotet(&c, LBN, LTN, RBN, LBF) &&
679
						dotet(&c, RTN, LTN, LBF, RBN) &&
680
						dotet(&c, RTN, LTN, LTF, LBF) &&
681
						dotet(&c, RTN, RBN, LBF, RBF) &&
682
						dotet(&c, RTN, LBF, LTF, RBF) &&
683
						dotet(&c, RTN, LTF, RTF, RBF)
684
						:
685
						/* or polygonize the cube directly: */
686
						docube(&c);
385 jab 687
                        if (! noabort) {
688
                           exit(1);
689
                        }
61 jab 690
 
691
					/* pop current cube from stack */
692
					cubes.pop_front();
693
 
694
					/* test six face directions, maybe add to stack: */
695
					testface(c.i-1, c.j, c.k, &c, L, LBN, LBF, LTN, LTF);
696
					testface(c.i+1, c.j, c.k, &c, R, RBN, RBF, RTN, RTF);
697
					testface(c.i, c.j-1, c.k, &c, B, LBN, LBF, RBN, RBF);
698
					testface(c.i, c.j+1, c.k, &c, T, LTN, LTF, RTN, RTF);
699
					testface(c.i, c.j, c.k-1, &c, N, LBN, LTN, RBN, RTN);
700
					testface(c.i, c.j, c.k+1, &c, F, LBF, LTF, RBF, RTF);
701
				}
702
		}
703
	}
704
 
705
	void Polygonizer::march(float x, float y, float z)
706
		{
707
			gvertices.clear();
708
			gnormals.clear();
709
			gtriangles.clear();
710
			PROCESS p(func, size, size/(float)(RES*RES), bounds, 
711
								gvertices, gnormals, gtriangles, use_normals);
712
			p.march(use_tetra?TET:NOTET,x,y,z);
713
		}
714
 
715
}