Subversion Repositories gelsvn

Rev

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