Subversion Repositories gelsvn

Rev

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

Rev 62 Rev 99
1
#include <queue>
1
#include <queue>
2
#include <iostream>
2
#include <iostream>
3
#include "quadric_simplify.h"
3
#include "quadric_simplify.h"
4
#include "mesh_optimization.h"
-
 
5
#include "smooth.h"
4
#include "smooth.h"
6
#include "HMesh/VertexCirculator.h"
5
#include "HMesh/VertexCirculator.h"
7
#include "Geometry/QEM.h"
6
#include "Geometry/QEM.h"
8
 
7
 
9
 
8
 
10
namespace HMeshUtil
9
namespace HMeshUtil
11
{
10
{
12
  using namespace CGLA;
11
  using namespace CGLA;
13
  using namespace std;
12
  using namespace std;
14
	using namespace GEO;
13
	using namespace GEO;
15
	using namespace HMesh;
14
	using namespace HMesh;
16
 
15
 
17
	namespace
16
	namespace
18
	{
17
	{
19
		struct HalfEdgeRec
18
		struct HalfEdgeRec
20
		{
19
		{
21
			HalfEdgeIter he;
20
			HalfEdgeIter he;
22
			int time_stamp;
21
			int time_stamp;
23
			void halfedge_removed() {time_stamp = -1;}
22
			void halfedge_removed() {time_stamp = -1;}
24
			HalfEdgeRec(): time_stamp(0) {}
23
			HalfEdgeRec(): time_stamp(0) {}
25
		};
24
		};
26
 
25
 
27
		struct SimplifyRec
26
		struct SimplifyRec
28
		{
27
		{
29
			Vec3f opt_pos;
28
			Vec3f opt_pos;
30
			int he_index;
29
			int he_index;
31
			float err;
30
			float err;
32
			int time_stamp;
31
			int time_stamp;
33
		};
32
		};
34
 
33
 
35
		bool operator<(const SimplifyRec& s1, const SimplifyRec& s2)
34
		bool operator<(const SimplifyRec& s1, const SimplifyRec& s2)
36
		{
35
		{
37
			return s1.err > s2.err;
36
			return s1.err > s2.err;
38
		}
37
		}
39
 
38
 
40
		class QuadricSimplifier
39
		class QuadricSimplifier
41
		{
40
		{
42
			typedef priority_queue<SimplifyRec> SimplifyQueue;
41
			typedef priority_queue<SimplifyRec> SimplifyQueue;
43
			typedef vector<QEM> QEMVec;
42
			typedef vector<QEM> QEMVec;
44
			typedef vector<HalfEdgeRec> HalfEdgeVec;
43
			typedef vector<HalfEdgeRec> HalfEdgeVec;
45
 
44
 
46
			Manifold& m;
45
			Manifold& m;
47
			HalfEdgeVec halfedge_vec;
46
			HalfEdgeVec halfedge_vec;
48
			QEMVec qem_vec;
47
			QEMVec qem_vec;
49
			SimplifyQueue sim_queue;
48
			SimplifyQueue sim_queue;
50
 
49
 
51
			void push_simplify_rec(HalfEdgeIter he);
50
			void push_simplify_rec(HalfEdgeIter he);
52
 
51
 
53
			void put_onering_in_queue(VertexIter vi);
52
			void put_onering_in_queue(VertexIter vi);
54
 
53
 
55
			int collapse(const SimplifyRec& simplify_rec);
54
			int collapse(const SimplifyRec& simplify_rec);
56
 
55
 
57
		public:
56
		public:
58
 
57
 
59
			QuadricSimplifier(Manifold& _m): 
58
			QuadricSimplifier(Manifold& _m): 
60
				m(_m), 
59
				m(_m), 
61
				halfedge_vec(m.no_halfedges()), 
60
				halfedge_vec(m.no_halfedges()), 
62
				qem_vec(m.no_vertices()) 
61
				qem_vec(m.no_vertices()) 
63
			{
62
			{
64
				// Enumerate vertices
63
				// Enumerate vertices
65
				m.enumerate_vertices();
64
				m.enumerate_vertices();
66
			
65
			
67
				// Enumerate halfedges
66
				// Enumerate halfedges
68
				m.enumerate_halfedges();
67
				m.enumerate_halfedges();
69
			}
68
			}
70
	
69
	
71
			void reduce(int max_work);
70
			void reduce(int max_work);
72
		};
71
		};
73
 
72
 
74
		void QuadricSimplifier::push_simplify_rec(HalfEdgeIter he)
73
		void QuadricSimplifier::push_simplify_rec(HalfEdgeIter he)
75
		{
74
		{
76
			// Update time_stamp
75
			// Update time_stamp
77
			assert(halfedge_vec[he->touched].time_stamp >=0);
76
			assert(halfedge_vec[he->touched].time_stamp >=0);
78
			assert(halfedge_vec[he->opp->touched].time_stamp>=0);
77
			assert(halfedge_vec[he->opp->touched].time_stamp>=0);
79
			int time_stamp = s_max(halfedge_vec[he->touched].time_stamp,
78
			int time_stamp = s_max(halfedge_vec[he->touched].time_stamp,
80
														 halfedge_vec[he->opp->touched].time_stamp);
79
														 halfedge_vec[he->opp->touched].time_stamp);
81
			time_stamp++;
80
			time_stamp++;
82
			halfedge_vec[he->touched].time_stamp = time_stamp;
81
			halfedge_vec[he->touched].time_stamp = time_stamp;
83
			halfedge_vec[he->opp->touched].time_stamp = time_stamp;
82
			halfedge_vec[he->opp->touched].time_stamp = time_stamp;
84
			// Get QEM for both end points
83
			// Get QEM for both end points
85
			const QEM& Q1 = qem_vec[he->vert->touched];
84
			const QEM& Q1 = qem_vec[he->vert->touched];
86
			const QEM& Q2 = qem_vec[he->opp->vert->touched];
85
			const QEM& Q2 = qem_vec[he->opp->vert->touched];
87
 
86
 
88
			QEM q = Q1;
87
			QEM q = Q1;
89
			q += Q2;
88
			q += Q2;
90
 
89
 
91
			float err;
90
			float err;
92
			Vec3f opt_pos(0);
91
			Vec3f opt_pos(0);
93
 
92
 
94
			//cout << q.determinant() << endl;
93
			//cout << q.determinant() << endl;
95
			if (q.determinant()>= 1e-8)
94
			if (q.determinant()>= 1e-8)
96
				{
95
				{
97
					opt_pos = q.opt_pos(0.001);
96
					opt_pos = q.opt_pos(0.001);
98
					err = q.error(opt_pos);
97
					err = q.error(opt_pos);
99
				}
98
				}
100
			else
99
			else
101
				{
100
				{
102
					// To see the effectivenes of the scheme, we can create 
101
					// To see the effectivenes of the scheme, we can create 
103
					// Random errors for comparison. Uncomment to use:
102
					// Random errors for comparison. Uncomment to use:
104
					// 			float e0 = time_stamp + rand()/float(RAND_MAX);//q.error(v0);
103
					// 			float e0 = time_stamp + rand()/float(RAND_MAX);//q.error(v0);
105
					// 			float e1 = time_stamp + rand()/float(RAND_MAX);//q.error(v1);
104
					// 			float e1 = time_stamp + rand()/float(RAND_MAX);//q.error(v1);
106
 
105
 
107
					Vec3f v0 = he->vert->pos;
106
					Vec3f v0 = he->vert->pos;
108
					Vec3f v1 = he->opp->vert->pos;
107
					Vec3f v1 = he->opp->vert->pos;
109
					float e0 = q.error(v0);
108
					float e0 = q.error(v0);
110
					float e1 = q.error(v1);
109
					float e1 = q.error(v1);
111
		
110
		
112
					if(e0 < e1)
111
					if(e0 < e1)
113
						{
112
						{
114
							err = e0;
113
							err = e0;
115
							opt_pos = v0;
114
							opt_pos = v0;
116
						}
115
						}
117
					else
116
					else
118
						{
117
						{
119
							err = e1;
118
							err = e1;
120
							opt_pos = v1;
119
							opt_pos = v1;
121
						}
120
						}
122
				}			
121
				}			
123
 
122
 
124
			// Create SimplifyRec
123
			// Create SimplifyRec
125
			int he_index = he->touched;
124
			int he_index = he->touched;
126
			SimplifyRec simplify_rec;
125
			SimplifyRec simplify_rec;
127
			simplify_rec.opt_pos = opt_pos;
126
			simplify_rec.opt_pos = opt_pos;
128
			simplify_rec.err = err;
127
			simplify_rec.err = err;
129
			simplify_rec.he_index = he_index;
128
			simplify_rec.he_index = he_index;
130
			simplify_rec.time_stamp = time_stamp;
129
			simplify_rec.time_stamp = time_stamp;
131
 
130
 
132
			// push it.
131
			// push it.
133
			sim_queue.push(simplify_rec);
132
			sim_queue.push(simplify_rec);
134
		}
133
		}
135
		
134
		
136
 
135
 
137
		void QuadricSimplifier::put_onering_in_queue(VertexIter vi)
136
		void QuadricSimplifier::put_onering_in_queue(VertexIter vi)
138
		{
137
		{
139
			// For all emanating edges he
138
			// For all emanating edges he
140
			for(VertexCirculator vc(vi);
139
			for(VertexCirculator vc(vi);
141
					!vc.end(); ++vc)
140
					!vc.end(); ++vc)
142
				{
141
				{
143
					HalfEdgeIter he = vc.get_halfedge();
142
					HalfEdgeIter he = vc.get_halfedge();
144
					push_simplify_rec(he);
143
					push_simplify_rec(he);
145
				}
144
				}
146
		}
145
		}
147
 
146
 
148
		int QuadricSimplifier::collapse(const SimplifyRec& simplify_rec)
147
		int QuadricSimplifier::collapse(const SimplifyRec& simplify_rec)
149
		{
148
		{
150
			int he_index = simplify_rec.he_index;
149
			int he_index = simplify_rec.he_index;
151
 
150
 
152
			// Check the time stamp to verify that the simplification 
151
			// Check the time stamp to verify that the simplification 
153
			// record is the newest. If the halfedge has been removed
152
			// record is the newest. If the halfedge has been removed
154
			// the time stamp is -1 and the comparison will also fail.
153
			// the time stamp is -1 and the comparison will also fail.
155
			if(halfedge_vec[he_index].time_stamp == simplify_rec.time_stamp)
154
			if(halfedge_vec[he_index].time_stamp == simplify_rec.time_stamp)
156
				{
155
				{
157
					HalfEdgeIter he = halfedge_vec[he_index].he;
156
					HalfEdgeIter he = halfedge_vec[he_index].he;
158
					VertexIter v = he->opp->vert;
157
					VertexIter v = he->opp->vert;
159
					VertexIter n = he->vert;
158
					VertexIter n = he->vert;
160
 
159
 
161
					// If the edge is, in fact, collapsible
160
					// If the edge is, in fact, collapsible
162
					if(m.collapse_precond(v,he))
161
					if(m.collapse_precond(v,he))
163
						{
162
						{
164
							//cout << simplify_rec.err << " " << &(*he->vert) << endl;
163
							//cout << simplify_rec.err << " " << &(*he->vert) << endl;
165
							// Get QEM for both end points
164
							// Get QEM for both end points
166
							const QEM& Q1 = qem_vec[he->vert->touched];
165
							const QEM& Q1 = qem_vec[he->vert->touched];
167
							const QEM& Q2 = qem_vec[he->opp->vert->touched];
166
							const QEM& Q2 = qem_vec[he->opp->vert->touched];
168
 
167
 
169
							// Compute Q_new = Q_1 + Q_2
168
							// Compute Q_new = Q_1 + Q_2
170
							QEM q = Q1;
169
							QEM q = Q1;
171
							q += Q2;
170
							q += Q2;
172
 
171
 
173
							// Mark all halfedges that will be removed as dead
172
							// Mark all halfedges that will be removed as dead
174
							halfedge_vec[he->touched].halfedge_removed();
173
							halfedge_vec[he->touched].halfedge_removed();
175
							halfedge_vec[he->opp->touched].halfedge_removed();
174
							halfedge_vec[he->opp->touched].halfedge_removed();
176
						
175
						
177
							if(he->next->next->next == he)
176
							if(he->next->next->next == he)
178
								{
177
								{
179
									halfedge_vec[he->next->touched].halfedge_removed();
178
									halfedge_vec[he->next->touched].halfedge_removed();
180
									halfedge_vec[he->next->next->touched].halfedge_removed();
179
									halfedge_vec[he->next->next->touched].halfedge_removed();
181
								}
180
								}
182
							if(he->opp->next->next->next == he->opp)
181
							if(he->opp->next->next->next == he->opp)
183
								{
182
								{
184
									halfedge_vec[he->opp->next->touched].halfedge_removed();
183
									halfedge_vec[he->opp->next->touched].halfedge_removed();
185
									halfedge_vec[he->opp->next->next->touched].halfedge_removed();
184
									halfedge_vec[he->opp->next->next->touched].halfedge_removed();
186
								}
185
								}
187
 
186
 
188
							// Do collapse
187
							// Do collapse
189
							m.collapse_halfedge(v,he,false);
188
							m.collapse_halfedge(v,he,false);
190
							n->pos = simplify_rec.opt_pos;
189
							n->pos = simplify_rec.opt_pos;
191
							qem_vec[n->touched] = q;
190
							qem_vec[n->touched] = q;
192
						
191
						
193
							put_onering_in_queue(n);
192
							put_onering_in_queue(n);
194
							return 1;
193
							return 1;
195
						}
194
						}
196
				}
195
				}
197
			return 0;
196
			return 0;
198
		}
197
		}
199
 
198
 
200
		void QuadricSimplifier::reduce(int max_work)
199
		void QuadricSimplifier::reduce(int max_work)
201
		{
200
		{
202
 
201
 
203
			// Set t = 0 for all halfedges
202
			// Set t = 0 for all halfedges
204
			int i=0;
203
			int i=0;
205
			for(HalfEdgeIter he = m.halfedges_begin();
204
			for(HalfEdgeIter he = m.halfedges_begin();
206
					he != m.halfedges_end(); ++he, ++i)
205
					he != m.halfedges_end(); ++he, ++i)
207
				halfedge_vec[i].he = he;
206
				halfedge_vec[i].he = he;
208
		
207
		
209
			// For all vertices, compute quadric and store in qem_vec
208
			// For all vertices, compute quadric and store in qem_vec
210
			for(VertexIter vi=m.vertices_begin(); vi != m.vertices_end(); ++vi)
209
			for(VertexIter vi=m.vertices_begin(); vi != m.vertices_end(); ++vi)
211
				{
210
				{
212
					Vec3d p(vi->pos);
211
					Vec3d p(vi->pos);
213
					QEM q;
212
					QEM q;
214
					for(VertexCirculator vc(vi); !vc.end(); ++vc)
213
					for(VertexCirculator vc(vi); !vc.end(); ++vc)
215
						{
214
						{
216
							FaceIter f = vc.get_face();
215
							FaceIter f = vc.get_face();
217
							if(f != NULL_FACE_ITER)
216
							if(f != NULL_FACE_ITER)
218
								{
217
								{
219
									Vec3d n(normal(f));
218
									Vec3d n(normal(f));
220
									double a = area(f);
219
									double a = area(f);
221
									q += QEM(p, n, a / 3.0);
220
									q += QEM(p, n, a / 3.0);
222
								}
221
								}
223
						}
222
						}
224
					qem_vec[vi->touched] = q;
223
					qem_vec[vi->touched] = q;
225
				}
224
				}
226
 
225
 
227
			for(HalfEdgeIter he = m.halfedges_begin();
226
			for(HalfEdgeIter he = m.halfedges_begin();
228
					he != m.halfedges_end(); ++he)
227
					he != m.halfedges_end(); ++he)
229
				// For all halfedges, 
228
				// For all halfedges, 
230
				{
229
				{
231
					if(halfedge_vec[he->touched].time_stamp == 0)
230
					if(halfedge_vec[he->touched].time_stamp == 0)
232
						push_simplify_rec(he);
231
						push_simplify_rec(he);
233
				}
232
				}
234
 
233
 
235
 
234
 
236
			int work = 0;
235
			int work = 0;
237
			while(!sim_queue.empty() && work < max_work)
236
			while(!sim_queue.empty() && work < max_work)
238
				{
237
				{
239
					int dwork = collapse(sim_queue.top());
238
					int dwork = collapse(sim_queue.top());
240
					if(dwork>0)
239
					if(dwork>0)
241
						{
240
						{
242
							work += dwork;
241
							work += dwork;
243
							if((work % 100) == 0)
242
							if((work % 100) == 0)
244
								cout << "work = " << work << endl;
243
								cout << "work = " << work << endl;
245
						}
244
						}
246
					sim_queue.pop();
245
					sim_queue.pop();
247
				}
246
				}
248
		}
247
		}
249
	}
248
	}
250
 
249
 
251
	void quadric_simplify(Manifold& m, int max_work)
250
	void quadric_simplify(Manifold& m, int max_work)
252
	{
251
	{
253
		srand(1210);
252
		srand(1210);
254
		QuadricSimplifier qsim(m);
253
		QuadricSimplifier qsim(m);
255
		qsim.reduce(max_work);
254
		qsim.reduce(max_work);
256
	}
255
	}
257
 
256
 
258
}
257
}
259
 
258