Subversion Repositories gelsvn

Rev

Rev 125 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 125 Rev 136
1
#include <cfloat>
1
#include <cfloat>
2
#include <algorithm>
2
#include <algorithm>
3
#include <fstream>
3
#include <fstream>
4
#include <iostream>
4
#include <iostream>
5
#include <list>
5
#include <list>
6
 
6
 
7
#include "CGLA/Mat2x3f.h"
7
#include "CGLA/Mat2x3f.h"
8
#include "CGLA/Mat2x2f.h"
8
#include "CGLA/Mat2x2f.h"
9
#include "HMesh/Manifold.h"
9
#include "HMesh/Manifold.h"
10
#include "HMesh/VertexCirculator.h"
10
#include "HMesh/VertexCirculator.h"
11
#include "HMesh/FaceCirculator.h"
11
#include "HMesh/FaceCirculator.h"
12
 
12
 
13
 
13
 
14
#include "Geometry/RGrid.h"
14
#include "Geometry/RGrid.h"
15
#include "Geometry/TrilinFilter.h"
15
#include "Geometry/TrilinFilter.h"
16
#include "Geometry/GradientFilter.h"
16
#include "Geometry/GradientFilter.h"
17
#include "Geometry/Neighbours.h"
17
#include "Geometry/Neighbours.h"
18
#include "Util/HashTable.h"
18
#include "Util/HashTable.h"
19
#include "Util/HashKey.h"
19
#include "Util/HashKey.h"
20
 
20
 
21
#include "fair_polygonize.h"
21
#include "fair_polygonize.h"
22
 
22
 
23
namespace Geometry
23
namespace Geometry
24
{
24
{
25
		using namespace HMesh;
25
		using namespace HMesh;
26
		using namespace Util;
26
		using namespace Util;
27
		using namespace CGLA;
27
		using namespace CGLA;
28
		using namespace std;
28
		using namespace std;
29
 
29
 
30
		namespace 
30
		namespace 
31
		{
31
		{
32
				/*
32
				/*
33
					Vectors along edges. For each of six cube faces there are four such vectors
33
					Vectors along edges. For each of six cube faces there are four such vectors
34
					since the faces of a cube are quads.
34
					since the faces of a cube are quads.
35
				*/
35
				*/
36
				const Vec3i edges[6][4] = {
36
				const Vec3i edges[6][4] = {
37
						{Vec3i(0,-1,0),Vec3i(0,0,1),Vec3i(0,1,0),Vec3i(0,0,-1)},
37
						{Vec3i(0,-1,0),Vec3i(0,0,1),Vec3i(0,1,0),Vec3i(0,0,-1)},
38
						{Vec3i(0,1,0),Vec3i(0,0,1),Vec3i(0,-1,0),Vec3i(0,0,-1)},
38
						{Vec3i(0,1,0),Vec3i(0,0,1),Vec3i(0,-1,0),Vec3i(0,0,-1)},
39
						{Vec3i(0,0,-1),Vec3i(1,0,0),Vec3i(0,0,1),Vec3i(-1,0,0)},
39
						{Vec3i(0,0,-1),Vec3i(1,0,0),Vec3i(0,0,1),Vec3i(-1,0,0)},
40
						{Vec3i(0,0,1),Vec3i(1,0,0),Vec3i(0,0,-1),Vec3i(-1,0,0)},
40
						{Vec3i(0,0,1),Vec3i(1,0,0),Vec3i(0,0,-1),Vec3i(-1,0,0)},
41
						{Vec3i(-1,0,0),Vec3i(0,1,0),Vec3i(1,0,0),Vec3i(0,-1,0)},
41
						{Vec3i(-1,0,0),Vec3i(0,1,0),Vec3i(1,0,0),Vec3i(0,-1,0)},
42
						{Vec3i(1,0,0),Vec3i(0,1,0),Vec3i(-1,0,0),Vec3i(0,-1,0)}};
42
						{Vec3i(1,0,0),Vec3i(0,1,0),Vec3i(-1,0,0),Vec3i(0,-1,0)}};
43
 
43
 
44
				/* Convert a direction vector to a cube face index. */
44
				/* Convert a direction vector to a cube face index. */
45
				int dir_to_face(const Vec3i& dir)
45
				int dir_to_face(const Vec3i& dir)
46
				{
46
				{
47
						assert(dot(dir,dir)==1);
47
						assert(dot(dir,dir)==1);
48
 
48
 
49
						if(dir[0] != 0)
49
						if(dir[0] != 0)
50
								return (dir[0]<0) ? 0 : 1;
50
								return (dir[0]<0) ? 0 : 1;
51
						if(dir[1] != 0)
51
						if(dir[1] != 0)
52
								return (dir[1]<0) ? 2 : 3;
52
								return (dir[1]<0) ? 2 : 3;
53
						if(dir[2] != 0)
53
						if(dir[2] != 0)
54
								return (dir[2]<0) ? 4 : 5;
54
								return (dir[2]<0) ? 4 : 5;
55
 
55
 
56
						return -1;
56
						return -1;
57
				}
57
				}
58
		
58
		
59
				/* Convert a face index and an edge vector to an edge index. */
59
				/* Convert a face index and an edge vector to an edge index. */
60
				int dir_to_edge(int face, const Vec3i& edge)
60
				int dir_to_edge(int face, const Vec3i& edge)
61
				{
61
				{
62
						for(int i=0;i<4;++i)
62
						for(int i=0;i<4;++i)
63
								if(edges[face][i] == edge) return i;
63
								if(edges[face][i] == edge) return i;
64
						assert(0);
64
						assert(0);
65
						return -1;
65
						return -1;
66
				}
66
				}
67
			
67
			
68
				/* Cube faces are created whenever a voxel that is inside is adjacent
68
				/* Cube faces are created whenever a voxel that is inside is adjacent
69
					 to a voxel that is outside. Thus the voxel can be seen as a small
69
					 to a voxel that is outside. Thus the voxel can be seen as a small
70
					 box that either contains material or not. A face is created where
70
					 box that either contains material or not. A face is created where
71
					 full and empty boxes meet. A vertex is placed on every box face.
71
					 full and empty boxes meet. A vertex is placed on every box face.
72
				 
72
				 
73
					 A halfedge is created for every edge of the (quadrilateral) face.
73
					 A halfedge is created for every edge of the (quadrilateral) face.
74
					 This halfedge connects the face to its neighbour. */
74
					 This halfedge connects the face to its neighbour. */
75
				struct CubeFace
75
				struct CubeFace
76
				{
76
				{
77
						bool used;
77
						bool used;
78
						VertexIter vert;
78
						VertexIter vert;
79
						HalfEdgeIter he[4];
79
						HalfEdgeIter he[4];
80
				
80
				
81
						CubeFace();
81
						CubeFace();
82
 
82
 
83
						HalfEdgeIter& get_he(Manifold* m, int i)
83
						HalfEdgeIter& get_he(Manifold* m, int i)
84
								{
84
								{
85
										if(he[i] == NULL_HALFEDGE_ITER)
85
										if(he[i] == NULL_HALFEDGE_ITER)
86
												he[i] = m->create_halfedge();
86
												he[i] = m->create_halfedge();
87
										return he[i];
87
										return he[i];
88
								}
88
								}
89
				};
89
				};
90
 
90
 
91
				CubeFace::CubeFace(): used(false), vert(NULL_VERTEX_ITER)
91
				CubeFace::CubeFace(): used(false), vert(NULL_VERTEX_ITER)
92
				{
92
				{
93
						for(int i=0;i<4;++i)
93
						for(int i=0;i<4;++i)
94
								he[i] = NULL_HALFEDGE_ITER;
94
								he[i] = NULL_HALFEDGE_ITER;
95
				}
95
				}
96
		
96
		
97
 
97
 
98
				/* A cube consists of six faces and a position. The cube centre is
98
				/* A cube consists of six faces and a position. The cube centre is
99
					 an integer (voxel grid) position. */
99
					 an integer (voxel grid) position. */
100
				struct Cube
100
				struct Cube
101
				{
101
				{
102
						Vec3i pos;
102
						Vec3i pos;
103
						CubeFace faces[6];
103
						CubeFace faces[6];
104
			
104
			
105
						Cube(const Vec3i& _pos): pos(_pos) {}
105
						Cube(const Vec3i& _pos): pos(_pos) {}
106
				};
106
				};
107
 
107
 
108
 
108
 
109
				/* The mesher class does the actual work. It is not pretty and it
109
				/* The mesher class does the actual work. It is not pretty and it
110
					 is not seen by the user. */
110
					 is not seen by the user. */
111
				template<class T>
111
				template<class T>
112
				class Mesher
112
				class Mesher
113
				{
113
				{
114
						const RGrid<T>* const voxel_grid;        // The voxel grid we work on
114
						const RGrid<T>* const voxel_grid;        // The voxel grid we work on
115
						Manifold* m;		                         // Output manifold
115
						Manifold* m;		                         // Output manifold
116
						HashTable<HashKey3usi,Cube*> cube_hash;  // Hashtable of cube pointers
116
						HashTable<HashKey3usi,Cube*> cube_hash;  // Hashtable of cube pointers
117
						list<Cube> cube_table;                   // Linked list containing
117
						list<Cube> cube_table;                   // Linked list containing
118
						// the actual cubes.
118
						// the actual cubes.
119
 
119
 
120
				public:
120
				public:
121
			
121
			
122
						Mesher(const RGrid<T>* _voxel_grid, // input voxel grid
122
						Mesher(const RGrid<T>* _voxel_grid, // input voxel grid
123
									 Manifold* _m,                // output HMesh
123
									 Manifold* _m,                // output HMesh
124
									 float iso,                   // iso value
124
									 float iso,                   // iso value
125
									 bool inv_cont);              // invert contour?
125
									 bool inv_cont);              // invert contour?
126
 
126
 
127
						void process_cubes();
127
						void process_cubes();
128
 
128
 
129
						void create_faces();
129
						void create_faces();
130
 
130
 
131
						void triangulate(float iso);
131
						void triangulate(float iso);
132
 
132
 
133
						void remove_duplicates();
133
						void remove_duplicates();
134
 
134
 
135
						void push_vertices(float iso);
135
						void push_vertices(float iso);
136
 
136
 
137
				};
137
				};
138
	
138
	
139
				template<class T>
139
				template<class T>
140
				inline bool comp(bool d, T a, T b)
140
				inline bool comp(bool d, T a, T b)
141
				{
141
				{
142
						return d? (a<b) : (b<a); 
142
						return d? (a<b) : (b<a); 
143
				}
143
				}
144
		
144
		
145
				template<class T>
145
				template<class T>
146
				Mesher<T>::Mesher(const RGrid<T>* _voxel_grid, 
146
				Mesher<T>::Mesher(const RGrid<T>* _voxel_grid, 
147
													Manifold* _m, float iso, bool inv_cont): 
147
													Manifold* _m, float iso, bool inv_cont): 
148
						voxel_grid(_voxel_grid),
148
						voxel_grid(_voxel_grid),
149
						m(_m)
149
						m(_m)
150
				{
150
				{
151
						/* Loop over all voxels */
151
						/* Loop over all voxels */
152
						for(int k=0;k<voxel_grid->get_dims()[ 2 ];++k)
152
						for(int k=0;k<voxel_grid->get_dims()[ 2 ];++k)
153
								for(int j=0;j<voxel_grid->get_dims()[ 1 ];++j)
153
								for(int j=0;j<voxel_grid->get_dims()[ 1 ];++j)
154
										for(int i=0;i<voxel_grid->get_dims()[ 0 ];++i)
154
										for(int i=0;i<voxel_grid->get_dims()[ 0 ];++i)
155
										{
155
										{
156
												Vec3i pi0(i,j,k);
156
												Vec3i pi0(i,j,k);
157
												float val0 = (*voxel_grid)[pi0];
157
												float val0 = (*voxel_grid)[pi0];
158
 
158
 
159
												/* If the voxel value is above the isovale (or below if we
159
												/* If the voxel value is above the isovale (or below if we
160
													 are finding the inverse contour) */
160
													 are finding the inverse contour) */
161
												if(comp(inv_cont,val0,iso))
161
												if(comp(inv_cont,val0,iso))
162
												{
162
												{
163
														bool interface_cell = false;
163
														bool interface_cell = false;
164
														vector<VertexIter> vertices;
164
														vector<VertexIter> vertices;
165
														Cube* cube;
165
														Cube* cube;
166
 
166
 
167
														// For each neighbouring voxel.
167
														// For each neighbouring voxel.
168
														for(int l=0;l<6;++l)
168
														for(int l=0;l<6;++l)
169
														{
169
														{
170
																// First make sure the voxel is inside the voxel grid.
170
																// First make sure the voxel is inside the voxel grid.
171
																Vec3i pi1(pi0);
171
																Vec3i pi1(pi0);
172
																pi1 += N6i[l];
172
																pi1 += N6i[l];
173
																bool indom = voxel_grid->in_domain(pi1);
173
																bool indom = voxel_grid->in_domain(pi1);
174
												
174
												
175
																/* If the neighbour is **not** in the grid or it 
175
																/* If the neighbour is **not** in the grid or it 
176
																	 is on the other side of the isovalue */
176
																	 is on the other side of the isovalue */
177
																if(!indom || 
177
																if(!indom || 
178
																	 !comp(inv_cont,float((*voxel_grid)[pi1]),iso))
178
																	 !comp(inv_cont,float((*voxel_grid)[pi1]),iso))
179
																{
179
																{
180
																		/* Create a cube face for the interface between
180
																		/* Create a cube face for the interface between
181
																			 our voxel and this neighbour. */
181
																			 our voxel and this neighbour. */
182
 
182
 
183
																		float val1 = iso;
183
																		float val1 = iso;
184
																		if(indom)
184
																		if(indom)
185
																				val1 = (*voxel_grid)[pi1];
185
																				val1 = (*voxel_grid)[pi1];
186
																		
186
																		
187
																		/* Store the cube in a hash table. This code is
187
																		/* Store the cube in a hash table. This code is
188
																			 executed the first time we create a face
188
																			 executed the first time we create a face
189
																			 for the cube. In other words only cubes that 
189
																			 for the cube. In other words only cubes that 
190
																			 actually have faces are stored in the hash */
190
																			 actually have faces are stored in the hash */
191
																		if(!interface_cell)
191
																		if(!interface_cell)
192
																		{
192
																		{
193
																				interface_cell = true;
193
																				interface_cell = true;
194
																				Cube** c_ptr;
194
																				Cube** c_ptr;
195
																				cube_hash.create_entry(HashKey3usi(pi0), c_ptr);
195
																				cube_hash.create_entry(HashKey3usi(pi0), c_ptr);
196
																				Cube c(pi0);
196
																				Cube c(pi0);
197
																				cube_table.push_back(c);
197
																				cube_table.push_back(c);
198
																				cube = (*c_ptr) = &cube_table.back();
198
																				cube = (*c_ptr) = &cube_table.back();
199
																		}
199
																		}
200
																		// Now add the face to the cube.
200
																		// Now add the face to the cube.
201
																		int face_idx  = dir_to_face(N6i[l]);
201
																		int face_idx  = dir_to_face(N6i[l]);
202
																		CubeFace& face = cube->faces[face_idx];
202
																		CubeFace& face = cube->faces[face_idx];
203
																		face.used = true;
203
																		face.used = true;
204
 
204
 
205
																		// Finally, we place a vertex corresponding to the
205
																		// Finally, we place a vertex corresponding to the
206
																		// centre of the cube face. The vertex is 
206
																		// centre of the cube face. The vertex is 
207
																		// positioned on the line between the two voxels
207
																		// positioned on the line between the two voxels
208
																		// (which pierces the new face) at the point where
208
																		// (which pierces the new face) at the point where
209
																		// the interpolated value = isovalue
209
																		// the interpolated value = isovalue
210
																		float t= (iso-val0)/(val1-val0);
210
																		float t= (iso-val0)/(val1-val0);
211
																		Vec3f p = Vec3f(pi0)*(1.0f-t)+Vec3f(pi1)*t;
211
																		Vec3f p = Vec3f(pi0)*(1.0f-t)+Vec3f(pi1)*t;
212
																		face.vert = m->create_vertex(p);
212
																		face.vert = m->create_vertex(p);
213
																		
213
																		
214
																		// We mark the vertex with the cube index.
214
																		// We mark the vertex with the cube index.
215
																		face.vert->touched = reinterpret_cast<TouchType>(cube);
215
																		face.vert->touched = reinterpret_cast<TouchType>(cube);
216
																}
216
																}
217
														}
217
														}
218
												}
218
												}
219
										}		
219
										}		
220
				}
220
				}
221
 
221
 
222
 
222
 
223
				/* This complicated function is used to connect the cube faces.
223
				/* This complicated function is used to connect the cube faces.
224
					 If the faces are cosidered to be little square pieces of paper, this
224
					 If the faces are cosidered to be little square pieces of paper, this
225
					 function glues them along the edges. However, it takes care to glue
225
					 function glues them along the edges. However, it takes care to glue
226
					 faces in such a way as to not create edges with more the two adjacent
226
					 faces in such a way as to not create edges with more the two adjacent
227
					 faces. */
227
					 faces. */
228
				template<class T>
228
				template<class T>
229
				void Mesher<T>::process_cubes()
229
				void Mesher<T>::process_cubes()
230
				{
230
				{
231
						/* For each cube in the table of cubes */
231
						/* For each cube in the table of cubes */
232
						typename list<Cube>::iterator cube_iter = cube_table.begin();
232
						typename list<Cube>::iterator cube_iter = cube_table.begin();
233
						for(;cube_iter != cube_table.end(); ++cube_iter)
233
						for(;cube_iter != cube_table.end(); ++cube_iter)
234
						{
234
						{
235
								/* For each of the six faces, if the face is used */
235
								/* For each of the six faces, if the face is used */
236
								Cube& cube = *cube_iter;
236
								Cube& cube = *cube_iter;
237
								for(int i=0;i<6;++i)
237
								for(int i=0;i<6;++i)
238
										if(cube.faces[i].used)
238
										if(cube.faces[i].used)
239
										{
239
										{
240
												Vec3i pos = cube.pos;
240
												Vec3i pos = cube.pos;
241
												Vec3i dir = N6i[i];
241
												Vec3i dir = N6i[i];
242
 
242
 
243
												// Let e be one of the four edges of the face
243
												// Let e be one of the four edges of the face
244
												for(int e=0;e<4;++e)
244
												for(int e=0;e<4;++e)
245
												{
245
												{
246
														Vec3i edge = edges[i][e];	       // Vector _along_ edge
246
														Vec3i edge = edges[i][e];	       // Vector _along_ edge
247
														Vec3i to_edge = cross(edge,dir); // vector to edge
247
														Vec3i to_edge = cross(edge,dir); // vector to edge
248
														CubeFace& face = cube.faces[i];  // The face
248
														CubeFace& face = cube.faces[i];  // The face
249
 
249
 
250
														Cube* cube_n;  // Neighbouring cube
250
														Cube* cube_n;  // Neighbouring cube
251
														Vec3i dir_n;   // direction from center to neighbour face
251
														Vec3i dir_n;   // direction from center to neighbour face
252
														Vec3i edge_n; // Edge vector for neighbour face
252
														Vec3i edge_n; // Edge vector for neighbour face
253
 
253
 
254
 
254
 
255
														/*
255
														/*
256
															Algorithm: Pick faces to glue
256
															Algorithm: Pick faces to glue
257
 
257
 
258
															Algorithm which connects cube faces. If both A and B
258
															Algorithm which connects cube faces. If both A and B
259
															are above the isovalue and 0 and C are below, A and B
259
															are above the isovalue and 0 and C are below, A and B
260
															will be seperated, i.e. the 0A and AC face will be 
260
															will be seperated, i.e. the 0A and AC face will be 
261
															connected. There is a different out-commented algorithm
261
															connected. There is a different out-commented algorithm
262
															at the end of this file which connects AO and 0B
262
															at the end of this file which connects AO and 0B
263
															instead.
263
															instead.
264
															
264
															
265
															Figure.
265
															Figure.
266
 
266
 
267
															0|B
267
															0|B
268
															-+-
268
															-+-
269
															A|C
269
															A|C
270
															
270
															
271
															Explanation:
271
															Explanation:
272
														
272
														
273
															Let the current cube be A. Since we are here, the voxel
273
															Let the current cube be A. Since we are here, the voxel
274
															of A is above the isovalue, and the voxel of O is below
274
															of A is above the isovalue, and the voxel of O is below
275
															since there is a face AO.
275
															since there is a face AO.
276
 
276
 
277
															We first check if there is a face between A and C. 
277
															We first check if there is a face between A and C. 
278
															if that is the case, the AO face is connected to the AC 
278
															if that is the case, the AO face is connected to the AC 
279
															face. 
279
															face. 
280
 
280
 
281
															Otherwise, we check if B is also inside the isocontour.
281
															Otherwise, we check if B is also inside the isocontour.
282
															If that is true there is an OB face, and we connect the
282
															If that is true there is an OB face, and we connect the
283
															A0 and the 0B faces.
283
															A0 and the 0B faces.
284
															
284
															
285
															Failing that, there must be a CB face, and we connect
285
															Failing that, there must be a CB face, and we connect
286
															with that.
286
															with that.
287
														*/
287
														*/
288
										
288
										
289
														// Begin "Pick faces to glue"
289
														// Begin "Pick faces to glue"
290
														Cube* dummy;
290
														Cube* dummy;
291
														if(cube.faces[dir_to_face(to_edge)].used)
291
														if(cube.faces[dir_to_face(to_edge)].used)
292
														{
292
														{
293
																dir_n = to_edge;
293
																dir_n = to_edge;
294
																edge_n = - edge; 
294
																edge_n = - edge; 
295
																cube_n = &cube;  
295
																cube_n = &cube;  
296
														}
296
														}
297
														else if(!cube_hash.find_entry(HashKey3usi(pos+dir+to_edge),
297
														else if(!cube_hash.find_entry(HashKey3usi(pos+dir+to_edge),
298
																													dummy))
298
																													dummy))
299
														{
299
														{
300
																assert(sqr_length(to_edge)==1);
300
																assert(sqr_length(to_edge)==1);
301
																dir_n = dir;
301
																dir_n = dir;
302
																edge_n = - edge;
302
																edge_n = - edge;
303
																cube_hash.find_entry(HashKey3usi(pos + to_edge), 
303
																cube_hash.find_entry(HashKey3usi(pos + to_edge), 
304
																										 cube_n);
304
																										 cube_n);
305
														}
305
														}
306
														else 
306
														else 
307
														{
307
														{
308
																dir_n = - to_edge;
308
																dir_n = - to_edge;
309
																edge_n = - edge;
309
																edge_n = - edge;
310
																cube_n = dummy;
310
																cube_n = dummy;
311
														}
311
														}
312
														// End "Pick faces to glue"
312
														// End "Pick faces to glue"
313
 
313
 
314
														// Do the actual gluing ...
314
														// Do the actual gluing ...
315
														
315
														
316
														/* Let the vertex of this face's halfedge be the one on
316
														/* Let the vertex of this face's halfedge be the one on
317
															 the connected face. */
317
															 the connected face. */
318
														int i_n = dir_to_face(dir_n);
318
														int i_n = dir_to_face(dir_n);
319
														CubeFace& face_n = cube_n->faces[i_n];
319
														CubeFace& face_n = cube_n->faces[i_n];
320
														HalfEdgeIter& he = face.get_he(m,e);
320
														HalfEdgeIter& he = face.get_he(m,e);
321
														face.vert->he = he;
321
														face.vert->he = he;
322
														he->vert = face_n.vert;
322
														he->vert = face_n.vert;
323
 
323
 
324
														/* Link this halfedge to the _next_ halfedge on the 
324
														/* Link this halfedge to the _next_ halfedge on the 
325
															 connected face. */
325
															 connected face. */
326
														int e_n = dir_to_edge(i_n, edge_n);
326
														int e_n = dir_to_edge(i_n, edge_n);
327
														assert(face_n.used);
327
														assert(face_n.used);
328
														HalfEdgeIter& he_n = face_n.get_he(m, (e_n+3)%4);
328
														HalfEdgeIter& he_n = face_n.get_he(m, (e_n+3)%4);
329
														link(he, he_n);
329
														link(he, he_n);
330
 
330
 
331
														/* Glue this halfedge to the corresponding one on the
331
														/* Glue this halfedge to the corresponding one on the
332
															 connected face.*/
332
															 connected face.*/
333
														HalfEdgeIter& he_opp = face_n.get_he(m, e_n);
333
														HalfEdgeIter& he_opp = face_n.get_he(m, e_n);
334
														face_n.vert->he = he_opp;
334
														face_n.vert->he = he_opp;
335
														glue(he, he_opp);
335
														glue(he, he_opp);
336
												}
336
												}
337
										}
337
										}
338
 
338
 
339
						}
339
						}
340
				}
340
				}
341
 
341
 
342
				template<class T>
342
				template<class T>
343
				void Mesher<T>::create_faces()
343
				void Mesher<T>::create_faces()
344
				{
344
				{
345
						// For each halfedge
345
						// For each halfedge
346
						HalfEdgeIter he0 = m->halfedges_begin();
346
						HalfEdgeIter he0 = m->halfedges_begin();
347
						while(he0 != m->halfedges_end())
347
						while(he0 != m->halfedges_end())
348
						{
348
						{
349
								// If this halfedge is not assigned to a face.
349
								// If this halfedge is not assigned to a face.
350
								if(he0->face == NULL_FACE_ITER)
350
								if(he0->face == NULL_FACE_ITER)
351
								{
351
								{
352
										// Create a face and let the current halfedge belong to it.
352
										// Create a face and let the current halfedge belong to it.
353
										FaceIter fi = m->create_face();
353
										FaceIter fi = m->create_face();
354
										fi->last = he0;
354
										fi->last = he0;
355
										he0->face = fi;
355
										he0->face = fi;
356
 
356
 
357
										// Loop over all connected halfedges and let them also belong 
357
										// Loop over all connected halfedges and let them also belong 
358
										// to the face.
358
										// to the face.
359
										HalfEdgeIter he = he0->next;
359
										HalfEdgeIter he = he0->next;
360
										while(he != he0)
360
										while(he != he0)
361
										{
361
										{
362
												he->face = fi;
362
												he->face = fi;
363
												he = he->next;
363
												he = he->next;
364
										}
364
										}
365
								}
365
								}
366
								++he0;
366
								++he0;
367
						}
367
						}
368
				}
368
				}
369
 
369
 
370
 
370
 
371
				/* A fairly complex algorithm which triangulates faces. It triangulates
371
				/* A fairly complex algorithm which triangulates faces. It triangulates
372
					 by iteratively splitting faces. It always splits a face by picking the
372
					 by iteratively splitting faces. It always splits a face by picking the
373
					 edge whose midpoint is closest to the isovalue. */
373
					 edge whose midpoint is closest to the isovalue. */
374
					
374
					
375
				template<class T>
375
				template<class T>
376
				void Mesher<T>::triangulate(float iso)
376
				void Mesher<T>::triangulate(float iso)
377
				{
377
				{
378
#ifndef NDEBUG
378
#ifndef NDEBUG
379
						cout << "Initial mesh valid : " << m->is_valid() << endl;
379
						cout << "Initial mesh valid : " << m->is_valid() << endl;
380
#endif
380
#endif
381
						Geometry::TrilinFilter<Geometry::RGrid<T> > grid_interp(voxel_grid);
381
						Geometry::TrilinFilter<Geometry::RGrid<T> > grid_interp(voxel_grid);
382
						int work;
382
						int work;
383
						do
383
						do
384
						{
384
						{
385
								// For every face.
385
								// For every face.
386
								work = 0;
386
								work = 0;
387
								for(FaceIter fi =m->faces_begin(); fi != m->faces_end(); ++fi)
387
								for(FaceIter fi =m->faces_begin(); fi != m->faces_end(); ++fi)
388
								{
388
								{
389
										// Create a vector of vertices.
389
										// Create a vector of vertices.
390
										vector<VertexIter> verts;
390
										vector<VertexIter> verts;
391
										for(FaceCirculator fc(fi); !fc.end(); ++fc)
391
										for(FaceCirculator fc(fi); !fc.end(); ++fc)
392
												verts.push_back(fc.get_vertex());
392
												verts.push_back(fc.get_vertex());
393
								
393
								
394
										// If there are just three we are done.
394
										// If there are just three we are done.
395
										if(verts.size() == 3) continue;
395
										if(verts.size() == 3) continue;
396
										
396
										
397
										// Find vertex pairs that may be connected.
397
										// Find vertex pairs that may be connected.
398
										vector<pair<int,int> > vpairs;
398
										vector<pair<int,int> > vpairs;
399
										const int N = verts.size();
399
										const int N = verts.size();
400
										for(int i=0;i<N-2;++i)
400
										for(int i=0;i<N-2;++i)
401
												for(int j=i+2;j<N; ++j)
401
												for(int j=i+2;j<N; ++j)
402
														if(!is_connected(verts[i], verts[j]))
402
														if(!is_connected(verts[i], verts[j]))
403
																vpairs.push_back(pair<int,int>(i,j));
403
																vpairs.push_back(pair<int,int>(i,j));
404
										
404
										
405
										assert(!vpairs.empty());
405
										assert(!vpairs.empty());
406
									
406
									
407
										/* For all vertex pairs, find the absolute value of iso-x
407
										/* For all vertex pairs, find the absolute value of iso-x
408
											 where x is the interpolated value of the volume at the 
408
											 where x is the interpolated value of the volume at the 
409
											 midpoint of the line segment connecting the two vertices.*/
409
											 midpoint of the line segment connecting the two vertices.*/
410
											 
410
											 
411
										float min_val=FLT_MAX;
411
										float min_val=FLT_MAX;
412
										int min_k = -1;
412
										int min_k = -1;
413
										for(int k=0;k<vpairs.size(); ++k)
413
										for(size_t k=0;k<vpairs.size(); ++k)
414
										{
414
										{
415
												int i = vpairs[k].first;
415
												int i = vpairs[k].first;
416
												int j = vpairs[k].second;
416
												int j = vpairs[k].second;
417
												Vec3f centre = 
417
												Vec3f centre = 
418
														(verts[i]->pos + 
418
														(verts[i]->pos + 
419
														 verts[j]->pos)/2.0f;
419
														 verts[j]->pos)/2.0f;
420
												
420
												
421
												float val;
421
												float val;
422
												if(grid_interp.in_domain(centre))
422
												if(grid_interp.in_domain(centre))
423
														val = fabs(grid_interp(centre)-iso);
423
														val = fabs(grid_interp(centre)-iso);
424
												else
424
												else
425
														val = 0.0f;
425
														val = 0.0f;
426
												if(val<min_val)
426
												if(val<min_val)
427
												{
427
												{
428
														min_val = val;
428
														min_val = val;
429
														min_k = k;
429
														min_k = k;
430
												}
430
												}
431
										}
431
										}
432
										assert(min_k != -1);
432
										assert(min_k != -1);
433
										
433
										
434
										{
434
										{
435
											// Split faces along edge whose midpoint is closest to isovalue
435
											// Split faces along edge whose midpoint is closest to isovalue
436
											int i = vpairs[min_k].first;
436
											int i = vpairs[min_k].first;
437
											int j = vpairs[min_k].second;
437
											int j = vpairs[min_k].second;
438
											m->split_face(fi, verts[i], verts[j]);
438
											m->split_face(fi, verts[i], verts[j]);
439
										}
439
										}
440
										++work;
440
										++work;
441
										
441
										
442
								}
442
								}
443
						}
443
						}
444
						while(work);
444
						while(work);
445
 
445
 
446
#ifndef NDEBUG
446
#ifndef NDEBUG
447
						cout << "Valid after triangulation : " << m->is_valid() << endl;
447
						cout << "Valid after triangulation : " << m->is_valid() << endl;
448
#endif
448
#endif
449
				}
449
				}
450
 
450
 
451
				/* This function collapses every edge whose endpoints belong to the same 
451
				/* This function collapses every edge whose endpoints belong to the same 
452
					 cube if this edge can be removed without violating the manifold condition*/
452
					 cube if this edge can be removed without violating the manifold condition*/
453
				template<class T>
453
				template<class T>
454
				void Mesher<T>::remove_duplicates()
454
				void Mesher<T>::remove_duplicates()
455
				{
455
				{
456
						// BUG --- we never do this loop more than one time.
456
						// BUG --- we never do this loop more than one time.
457
						// does it matter.
457
						// does it matter.
458
						VertexIter vi = m->vertices_begin();
458
						VertexIter vi = m->vertices_begin();
459
						bool did_work = false;
459
						bool did_work = false;
460
						do
460
						do
461
						{
461
						{
462
								did_work = false;
462
								did_work = false;
463
								while(vi != m->vertices_end())
463
								while(vi != m->vertices_end())
464
								{
464
								{
465
										bool did = false;
465
										bool did = false;
466
										VertexCirculator vc(vi);
466
										VertexCirculator vc(vi);
467
										int k=0;
467
										int k=0;
468
										for(;!vc.end();++vc)
468
										for(;!vc.end();++vc)
469
										{
469
										{
470
												assert(++k<1000);
470
												assert(++k<1000);
471
												HalfEdgeIter he = vc.get_halfedge();
471
												HalfEdgeIter he = vc.get_halfedge();
472
												VertexIter n = vc.get_vertex();
472
												VertexIter n = vc.get_vertex();
473
												if(n->touched == vi->touched && m->collapse_precond(vi,he))
473
												if(n->touched == vi->touched && m->collapse_precond(vi,he))
474
												{
474
												{
475
														VertexIter vi2 = vi;
475
														VertexIter vi2 = vi;
476
														++vi;
476
														++vi;
477
														m->collapse_halfedge(vi2,he,true);
477
														m->collapse_halfedge(vi2,he,true);
478
														did = did_work = true;
478
														did = did_work = true;
479
														break;
479
														break;
480
												}
480
												}
481
										}
481
										}
482
										if(!did) ++vi;
482
										if(!did) ++vi;
483
								}
483
								}
484
 
484
 
485
						}
485
						}
486
						while(did_work);
486
						while(did_work);
487
#ifndef NDEBUG
487
#ifndef NDEBUG
488
						cout << "Valid after removal of excess vertices : " << m->is_valid() << endl;
488
						cout << "Valid after removal of excess vertices : " << m->is_valid() << endl;
489
#endif
489
#endif
490
				}
490
				}
491
		
491
		
492
				/* A function (not used now) which pushes vertices onto the isosurface. */
492
				/* A function (not used now) which pushes vertices onto the isosurface. */
493
				template<class T>
493
				template<class T>
494
				void Mesher<T>::push_vertices(float iso)
494
				void Mesher<T>::push_vertices(float iso)
495
				{
495
				{
496
						GradientFilter<RGrid<T> > grad(voxel_grid);
496
						GradientFilter<RGrid<T> > grad(voxel_grid);
497
						TrilinFilter<GradientFilter<RGrid<T> > > ginter(&grad);
497
						TrilinFilter<GradientFilter<RGrid<T> > > ginter(&grad);
498
						TrilinFilter<RGrid<T> > inter(voxel_grid);
498
						TrilinFilter<RGrid<T> > inter(voxel_grid);
499
		
499
		
500
						cout << "Pushing vertices" << endl;
500
						cout << "Pushing vertices" << endl;
501
						for(int i=0;i<4;++i)
501
						for(int i=0;i<4;++i)
502
						{
502
						{
503
								cout << "." << flush;
503
								cout << "." << flush;
504
								for(VertexIter vi= m->vertices_begin();
504
								for(VertexIter vi= m->vertices_begin();
505
										vi != m->vertices_end(); ++vi)
505
										vi != m->vertices_end(); ++vi)
506
								{
506
								{
507
										Vec3f p = vi->pos;
507
										Vec3f p = vi->pos;
508
										if(ginter.in_domain(p))
508
										if(ginter.in_domain(p))
509
										{
509
										{
510
												Vec3f g = ginter(p);
510
												Vec3f g = ginter(p);
511
												float s = sqr_length(g);
511
												float s = sqr_length(g);
512
												if(s>0.0001)
512
												if(s>0.0001)
513
												{
513
												{
514
														float v = inter(p)-iso;
514
														float v = inter(p)-iso;
515
														vi->pos = (p-g*v/s);
515
														vi->pos = (p-g*v/s);
516
												}
516
												}
517
										}
517
										}
518
								}
518
								}
519
						}
519
						}
520
				}
520
				}
521
 
521
 
522
		}
522
		}
523
 
523
 
524
		template<typename T>
524
		template<typename T>
525
		void fair_polygonize(const RGrid<T>& voxel_grid, 
525
		void fair_polygonize(const RGrid<T>& voxel_grid, 
526
												 Manifold& mani, 
526
												 Manifold& mani, 
527
												 float iso,
527
												 float iso,
528
												 bool invert_contour)
528
												 bool invert_contour)
529
		{
529
		{
530
				Mesher<T> m(&voxel_grid, &mani, iso, invert_contour);
530
				Mesher<T> m(&voxel_grid, &mani, iso, invert_contour);
531
				m.process_cubes();
531
				m.process_cubes();
532
				m.create_faces();
532
				m.create_faces();
533
				m.triangulate(iso);
533
				m.triangulate(iso);
534
				m.remove_duplicates();
534
				m.remove_duplicates();
535
				//m.push_vertices(iso);
535
				//m.push_vertices(iso);
536
		}
536
		}
537
 
537
 
538
		template void fair_polygonize<unsigned char>(const RGrid<unsigned char>&,
538
		template void fair_polygonize<unsigned char>(const RGrid<unsigned char>&,
539
																								 Manifold&, float, bool);
539
																								 Manifold&, float, bool);
540
		template void fair_polygonize<float>(const RGrid<float>&,
540
		template void fair_polygonize<float>(const RGrid<float>&,
541
																				 Manifold&, float, bool);
541
																				 Manifold&, float, bool);
542
}
542
}
543
 
543
 
544
 
544
 
545
// --- Alternative "Pick faces to glue" code.
545
// --- Alternative "Pick faces to glue" code.
546
//                          if(cube_hash.find_entry(HashKey3usi(pos + dir + to_edge),
546
//                          if(cube_hash.find_entry(HashKey3usi(pos + dir + to_edge),
547
//                                        cube_n))
547
//                                        cube_n))
548
// 														{
548
// 														{
549
// 																assert(sqr_length(dir + to_edge)==2);
549
// 																assert(sqr_length(dir + to_edge)==2);
550
// 																dir_n = - to_edge;
550
// 																dir_n = - to_edge;
551
// 																edge_n = - edge;
551
// 																edge_n = - edge;
552
// 														}
552
// 														}
553
// 														else if(cube_hash.find_entry(HashKey3usi(pos + to_edge), 
553
// 														else if(cube_hash.find_entry(HashKey3usi(pos + to_edge), 
554
// 																												 cube_n))
554
// 																												 cube_n))
555
// 														{
555
// 														{
556
// 																assert(sqr_length(to_edge)==1);
556
// 																assert(sqr_length(to_edge)==1);
557
// 																dir_n = dir;
557
// 																dir_n = dir;
558
// 																edge_n = - edge;
558
// 																edge_n = - edge;
559
// 														}
559
// 														}
560
// 														else
560
// 														else
561
// 														{
561
// 														{
562
// 																dir_n = to_edge;
562
// 																dir_n = to_edge;
563
// 																edge_n = - edge;
563
// 																edge_n = - edge;
564
// 																											cube_n = &cube;
564
// 																											cube_n = &cube;
565
// 														}
565
// 														}
566
 
566
 
567
 
567
 
568

Generated by GNU Enscript 1.6.6.
568

Generated by GNU Enscript 1.6.6.
569
 
569
 
570
 
570
 
571
 
571