Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
39 bj 1
#pragma warning(disable: 4786) // disable warning C4786: symbol greater than 255 
2
 
3
#include <stack>
4
#include "TriMeshBuilder.h"
5
 
6
using namespace std;
7
using namespace CGLA;
8
 
9
namespace IMesh
10
{
11
 
12
 
13
	namespace
14
	{
15
		/** Neighbours is a simple class which overloads ().
16
				Given an instance nbrs of this class nbrs(a,b) will
17
				return true if a and b share an edge. */
18
		class Neighbours
19
		{
20
			const TriMeshBuilder* const bldr;
21
		public:
22
 
23
			Neighbours(const TriMeshBuilder* const _bldr):
24
				bldr(_bldr)
25
			{}
26
 
27
			bool operator()(int a, int b)
28
			{
29
				Vec3i fa = bldr->face(a);
30
				Vec3i fb = bldr->face(b);
31
				for(int i=0;i<3;++i)
32
					for(int j=0;j<3;++j)
33
						if(fa[i]==fb[j] && fa[(i+1)%3]==fb[(j+2)%3])
34
							return true;
35
				return false;
36
			}
37
 
38
		};
39
	}
40
 
41
 
42
	void compute_face_normals(TriMeshBuilder& bldr, bool do_flip)
43
	{
44
		bldr.register_face_normals();
45
		for(int i=0;i<bldr.no_faces(); ++i)
46
			{
47
				Vec3f p0 = bldr.vpos(i,0);
48
				Vec3f p1 = bldr.vpos(i,1);
49
				Vec3f p2 = bldr.vpos(i,2);
50
				Vec3f norm = cross(p1-p0,p2-p0);
51
 
52
				float len = norm.length();
53
				if(len > 0)
54
					norm /= len;
55
 
56
				if(do_flip)
57
					bldr.add_fnorm(-norm);
58
				else
59
					bldr.add_fnorm(norm);
60
			}
61
	}
62
 
63
 
64
	void compute_vertex_normals(TriMeshBuilder& bldr)
65
	{
66
		AttrHandle<CGLA::Vec3f> norm_handle; 
67
		if(!bldr.get_vattr_handle("VA_NORM", norm_handle))
68
			{
69
				bldr.register_vertex_normals();
70
				for(int i=0;i<bldr.no_vertices(); ++i)
71
					bldr.add_vnorm(Vec3f(0));
72
			}
73
		for(int face_idx=0; face_idx<bldr.no_faces(); ++face_idx)
74
			{
75
				int i;
76
				Vec3f p[3];	
77
				for(i=0;i<3;++i)
78
					p[i] = bldr.vpos(face_idx,i);
79
 
80
				Vec3f v10 = p[1]-p[0];
81
				Vec3f v20 = p[2]-p[0];
82
				Vec3f v21 = p[2]-p[1];
83
				Vec3f v01 = p[0]-p[1];
84
 
85
				float l10 = v10.length();
86
				float l20 = v20.length();
87
				float l21 = v21.length();
88
				float l01 = v01.length();
89
 
90
				v10 = (l10>0.0f) ? v10 / l10 : Vec3f(0);
91
				v20 = (l20>0.0f) ? v20 / l20 : Vec3f(0);
92
				v21 = (l21>0.0f) ? v21 / l21 : Vec3f(0);
93
				v01 = (l01>0.0f) ? v01 / l01 : Vec3f(0);
94
 
95
				float a[3];
96
				a[0] = acos(dot(v10, v20));
97
				a[1] = acos(dot(v21,v01));
98
				a[2] = M_PI - a[0] - a[1];
99
 
100
				Vec3f fn = bldr.fnorm(face_idx);
101
				for(i=0;i<3;++i)
102
					bldr.vnorm(face_idx,i) += fn * a[i];
103
			}
104
		for(int norm_idx=0;norm_idx<bldr.no_vnorm();++norm_idx)
105
			bldr.vnorm(norm_idx).normalize();
106
	}
107
 
108
	void compute_vertex_normals(TriMeshBuilder& bldr, 
109
											 AttrHandle<int> smooth_group_attr)
110
	{
111
		int face_set = bldr.register_face_set();
112
		bldr.register_vertex_normals(face_set);
113
 
114
		vector<vector<int> > per_vertex_face_vec(bldr.no_vertices());
115
 
116
		for(int face_idx=0; face_idx < bldr.no_faces(); ++face_idx)
117
			{
118
				Vec3i face = bldr.face(face_idx);
119
				per_vertex_face_vec[face[0]].push_back(face_idx);
120
				per_vertex_face_vec[face[1]].push_back(face_idx);
121
				per_vertex_face_vec[face[2]].push_back(face_idx);
122
			}
123
		Neighbours nbrs(&bldr);
124
		for(int vert_idx=0; vert_idx<bldr.no_vertices(); ++vert_idx)
125
			{
126
				int n_faces = per_vertex_face_vec[vert_idx].size();
127
				vector<int> N(n_faces, -1);
128
				for(int i=0;i<n_faces;++i)
129
					{
130
						if(N[i] == -1)
131
							{
132
								N[i] = bldr.add_vnorm(Vec3f(0));
133
 
134
								stack<int> q;
135
								q.push(i);
136
								while(!q.empty())
137
									{
138
										int l = q.top();
139
										q.pop();
140
 
141
										int idx_l = per_vertex_face_vec[vert_idx][l];
142
										int sg_l = bldr.fattr(smooth_group_attr, idx_l);
143
										for(int j=i+1;j<n_faces;++j)
144
											{
145
												int idx_j = per_vertex_face_vec[vert_idx][j];
146
												int sg_j = bldr.fattr(smooth_group_attr, idx_j);
147
												if((N[j] == -1) && 
148
													 nbrs(idx_j,idx_l) && 
149
													 ((sg_j&sg_l) != 0))
150
													{
151
														N[j] = N[l];
152
														q.push(j);
153
													}
154
											}
155
									}
156
							}
157
					}
158
				for(int k=0;k<n_faces; ++k)
159
					{
160
						assert(N[k] != -1);
161
						int face_idx = per_vertex_face_vec[vert_idx][k];
162
						Vec3i face = bldr.face(face_idx);
163
						Vec3i norm_face = bldr.face(face_idx, face_set);
164
						for(int j=0;j<3;++j)
165
							if(face[j] == vert_idx)
166
								norm_face[j] = N[k];
167
						bldr.face(face_idx, face_set) = norm_face;
168
					}
169
			}
170
		compute_vertex_normals(bldr);
171
	}
172
 
173
 
174
 
175
	void compute_vertex_normals(TriMeshBuilder& bldr, float cos_ang) 
176
	{
177
		int face_set = bldr.register_face_set();
178
		bldr.register_vertex_normals(face_set);
179
 
180
		vector<vector<int> > per_vertex_face_vec(bldr.no_vertices());
181
 
182
		for(int face_idx=0; face_idx < bldr.no_faces(); ++face_idx)
183
			{
184
				Vec3i face = bldr.face(face_idx);
185
				per_vertex_face_vec[face[0]].push_back(face_idx);
186
				per_vertex_face_vec[face[1]].push_back(face_idx);
187
				per_vertex_face_vec[face[2]].push_back(face_idx);
188
			}
189
		Neighbours nbrs(&bldr);
190
		for(int vert_idx=0; vert_idx<bldr.no_vertices(); ++vert_idx)
191
			{
192
				int n_faces = per_vertex_face_vec[vert_idx].size();
193
				vector<int> N(n_faces, -1);
194
				for(int i=0;i<n_faces;++i)
195
					{
196
						if(N[i] == -1)
197
							{
198
								N[i] = bldr.add_vnorm(Vec3f(0));
199
 
200
								stack<int> q;
201
								q.push(i);
202
								while(!q.empty())
203
									{
204
										int l = q.top();
205
										q.pop();
206
 
207
										int idx_l = per_vertex_face_vec[vert_idx][l];
208
										Vec3f norm_l = bldr.fnorm(idx_l);
209
										for(int j=i+1;j<n_faces;++j)
210
											{
211
												int idx_j = per_vertex_face_vec[vert_idx][j];
212
												Vec3f norm_j = bldr.fnorm(idx_j);
213
												if((N[j] == -1) && 
214
													 nbrs(idx_j,idx_l) && 
215
													 (dot(norm_l, norm_j)>cos_ang))
216
													{
217
														N[j] = N[l];
218
														q.push(j);
219
													}
220
											}
221
									}
222
							}
223
					}
224
				for(int k=0;k<n_faces; ++k)
225
					{
226
						assert(N[k] != -1);
227
						int face_idx = per_vertex_face_vec[vert_idx][k];
228
						Vec3i face = bldr.face(face_idx);
229
						Vec3i norm_face = bldr.face(face_idx, face_set);
230
						for(int j=0;j<3;++j)
231
							if(face[j] == vert_idx)
232
								norm_face[j] = N[k];
233
						bldr.face(face_idx, face_set) = norm_face;
234
					}
235
			}
236
		compute_vertex_normals(bldr);
237
	}
238
}