Subversion Repositories gelsvn

Rev

Rev 394 | Rev 399 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 394 Rev 397
1
/*
1
/*
2
 *  harmonics.cpp
2
 *  harmonics.cpp
3
 *  GEL
3
 *  GEL
4
 *
4
 *
5
 *  Created by J. Andreas Bærentzen on 01/09/08.
5
 *  Created by J. Andreas Bærentzen on 01/09/08.
6
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
6
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
7
 *
7
 *
8
 */
8
 */
9
 
9
 
10
#include <iostream>
10
#include <iostream>
11
#include <CGLA/Vec3f.h>
11
#include <CGLA/Vec3f.h>
12
#include <CGLA/Vec3d.h>
12
#include <CGLA/Vec3d.h>
13
#include <LinAlg/Matrix.h>
13
#include <LinAlg/Matrix.h>
14
#include <LinAlg/Vector.h>
14
#include <LinAlg/Vector.h>
15
#include <LinAlg/LapackFunc.h>
15
#include <LinAlg/LapackFunc.h>
16
 
16
 
17
#include <GL/glew.h>
17
#include <GL/glew.h>
18
#include <GLGraphics/glsl_shader.h>
18
#include <GLGraphics/glsl_shader.h>
19
 
19
 
20
#include <HMesh/Manifold.h>
20
#include <HMesh/Manifold.h>
21
#include <HMesh/VertexCirculator.h>
21
#include <HMesh/VertexCirculator.h>
22
#include <HMesh/FaceCirculator.h>
22
#include <HMesh/FaceCirculator.h>
23
#include <HMesh/build_manifold.h>
23
#include <HMesh/build_manifold.h>
24
#include <HMesh/mesh_optimization.h>
24
#include <HMesh/mesh_optimization.h>
25
#include <HMesh/triangulate.h>
25
#include <HMesh/triangulate.h>
26
#include <HMesh/load.h>
26
#include <HMesh/load.h>
27
#include <HMesh/x3d_save.h>
27
#include <HMesh/x3d_save.h>
28
 
28
 
29
#include <GLConsole/GLConsole.h>
29
#include <GLConsole/GLConsole.h>
30
 
30
 
31
#include "harmonics.h"
31
#include "harmonics.h"
32
#include "wireframe.h"
32
#include "wireframe.h"
33
 
33
 
34
using namespace CGLA;
34
using namespace CGLA;
35
using namespace std;
35
using namespace std;
36
using namespace HMesh;
36
using namespace HMesh;
37
using namespace Geometry;
37
using namespace Geometry;
38
using namespace GLGraphics;
38
using namespace GLGraphics;
39
using namespace LinAlg;
39
using namespace LinAlg;
40
 
40
 
41
bool Harmonics::is_initialized=false;
41
bool Harmonics::is_initialized=false;
42
GLuint Harmonics::prog_P0;
42
GLuint Harmonics::prog_P0;
43
 
43
 
44
 
44
 
45
namespace
45
namespace
46
{
46
{
-
 
47
 
-
 
48
	string vss =
-
 
49
"#version 120\n"
-
 
50
"#extension GL_EXT_gpu_shader4 : enable\n"
-
 
51
"	\n"
-
 
52
"	\n"
-
 
53
"	attribute float eigenvalue;\n"
-
 
54
"	attribute float eigenvalue2;\n"
-
 
55
"	varying vec3 normal;\n"
-
 
56
"	varying float eig;\n"
-
 
57
"	varying float eig2;\n"
-
 
58
"	\n"
-
 
59
"	void main(void)\n"
-
 
60
"	{\n"
-
 
61
"		gl_Position =  ftransform();\n"
-
 
62
"		normal = normalize(gl_NormalMatrix * gl_Normal);\n"
-
 
63
"		eig = eigenvalue;\n"
-
 
64
"		eig2 = eigenvalue2;\n"
-
 
65
"	}\n";
-
 
66
	
-
 
67
string fss = 	
-
 
68
"#version 120\n"
-
 
69
"#extension GL_EXT_gpu_shader4 : enable\n"
-
 
70
"	\n"
-
 
71
"	varying vec3 normal;\n"
-
 
72
"	varying float eig;\n"
-
 
73
"	varying float eig2;\n"
-
 
74
"	uniform float eig_max;\n"
-
 
75
"	uniform float eig_max2;\n"
-
 
76
"	uniform bool do_highlight;\n"
-
 
77
"	uniform bool do_diffuse;\n"
-
 
78
"	const vec3 light_dir = vec3(0,0,1);\n"
-
 
79
"	\n"
-
 
80
"	void main()\n"
-
 
81
"	{\n"
-
 
82
"		float dot_ln = dot(light_dir, normal);\n"
-
 
83
"		\n"
-
 
84
"		float eig_norm = eig/eig_max;\n"
-
 
85
"		float stripe_signal = 100 * eig_norm;\n"
-
 
86
"		vec4 stripe_col = abs(stripe_signal) < 3.14 ? vec4(1,1,0,0) : vec4(.1,.1,.1,0);\n"
-
 
87
"		\n"
-
 
88
"		gl_FragColor = eig_norm * vec4(-1,0,1,0);\n"
-
 
89
"		if(do_diffuse)   gl_FragColor *= dot_ln;\n"
-
 
90
"		if(do_highlight) gl_FragColor += dot_ln*dot_ln*dot_ln*dot_ln*dot_ln*dot_ln*dot_ln*vec4(.5,.5,.5,0);\n"
-
 
91
"		gl_FragColor += stripe_col * smoothstep(0.8,1.0,cos(stripe_signal));\n"
-
 
92
"	}\n";
47
	
93
	
48
	double voronoi_area(VertexIter v)
94
	double voronoi_area(VertexIter v)
49
	{
95
	{
50
	double area_mixed = 0;
96
	double area_mixed = 0;
51
	//For each triangle T from the 1-ring neighborhood of x
97
	//For each triangle T from the 1-ring neighborhood of x
52
	for(VertexCirculator vc(v); !vc.end(); ++vc)
98
	for(VertexCirculator vc(v); !vc.end(); ++vc)
53
	{
99
	{
54
		FaceIter f = vc.get_face();
100
		FaceIter f = vc.get_face();
55
		double f_area = area(f);
101
		double f_area = area(f);
56
		
102
		
57
		HalfEdgeIter he = vc.get_halfedge();
103
		HalfEdgeIter he = vc.get_halfedge();
58
		Vec3d v1(he->vert->pos);
104
		Vec3d v1(he->vert->pos);
59
		Vec3d v2(he->next->vert->pos);
105
		Vec3d v2(he->next->vert->pos);
60
		Vec3d v0(he->next->next->vert->pos);
106
		Vec3d v0(he->next->next->vert->pos);
61
		
107
		
62
		double a0 = acos(dot(v1-v0, v2-v0)/(length(v1-v0)*length(v2-v0)));
108
		double a0 = acos(dot(v1-v0, v2-v0)/(length(v1-v0)*length(v2-v0)));
63
		double a1 = acos(dot(v2-v1, v0-v1)/(length(v2-v1)*length(v0-v1)));
109
		double a1 = acos(dot(v2-v1, v0-v1)/(length(v2-v1)*length(v0-v1)));
64
		double a2 = acos(dot(v0-v2, v1-v2)/(length(v0-v2)*length(v1-v2)));
110
		double a2 = acos(dot(v0-v2, v1-v2)/(length(v0-v2)*length(v1-v2)));
65
		
111
		
66
		if(a0>(M_PI/2.0) && a1>(M_PI/2.0) && a2>(M_PI/2.0)) // f is non-obtuse
112
		if(a0>(M_PI/2.0) && a1>(M_PI/2.0) && a2>(M_PI/2.0)) // f is non-obtuse
67
		{
113
		{
68
			// Add Voronoi formula (see Section 3.3)
114
			// Add Voronoi formula (see Section 3.3)
69
			area_mixed += (1.0/8) * 
115
			area_mixed += (1.0/8) * 
70
			((1.0/tan(a1)) * sqr_length(v2-v0) + 
116
			((1.0/tan(a1)) * sqr_length(v2-v0) + 
71
			 (1.0/tan(a2)) * sqr_length(v1-v0));
117
			 (1.0/tan(a2)) * sqr_length(v1-v0));
72
		}
118
		}
73
		else // Voronoi inappropriate
119
		else // Voronoi inappropriate
74
		{
120
		{
75
			// Add either area(f)/4 or area(f)/2
121
			// Add either area(f)/4 or area(f)/2
76
			if(a0>M_PI/2.0)// the angle of f at x is obtuse
122
			if(a0>M_PI/2.0)// the angle of f at x is obtuse
77
				area_mixed += f_area/2;
123
				area_mixed += f_area/2;
78
			else
124
			else
79
				area_mixed += f_area/4;
125
				area_mixed += f_area/4;
80
		}
126
		}
81
	}
127
	}
82
	return area_mixed;
128
	return area_mixed;
83
}
129
}
84
 
130
 
85
	double barycentric_area(VertexIter v)
131
	double barycentric_area(VertexIter v)
86
	{
132
	{
87
	double barea = 0;
133
	double barea = 0;
88
	//For each triangle T from the 1-ring neighborhood of x
134
	//For each triangle T from the 1-ring neighborhood of x
89
	for(VertexCirculator vc(v); !vc.end(); ++vc)
135
	for(VertexCirculator vc(v); !vc.end(); ++vc)
90
	{
136
	{
91
		FaceIter f = vc.get_face();
137
		FaceIter f = vc.get_face();
92
		barea += area(f)/3.0;
138
		barea += area(f)/3.0;
93
	}
139
	}
94
	return barea;
140
	return barea;
95
}
141
}
96
 
142
 
97
}
143
}
98
 
144
 
99
void Harmonics::make_laplace_operator()
145
void Harmonics::make_laplace_operator()
100
{
146
{
101
	Q.Resize(mani.no_vertices(), mani.no_vertices());
147
	Q.Resize(mani.no_vertices(), mani.no_vertices());
102
	
148
	
103
	for(VertexIter v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
149
	for(VertexIter v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
104
		if(!is_boundary(v))
150
		if(!is_boundary(v))
105
		{
151
		{
106
			int i = v->touched;
152
			int i = v->touched;
107
			double area_i = voronoi_area(v);
153
			double area_i = voronoi_area(v);
108
			Vec3d vertex(v->pos);
154
			Vec3d vertex(v->pos);
109
			Vec3d curv_normal(0);
155
			Vec3d curv_normal(0);
110
			double a_sum = 0;
156
			double a_sum = 0;
111
			for(VertexCirculator vc(v); !vc.end(); ++vc)
157
			for(VertexCirculator vc(v); !vc.end(); ++vc)
112
			{
158
			{
113
				int j = vc.get_vertex()->touched;
159
				int j = vc.get_vertex()->touched;
114
				double area_j = voronoi_area(vc.get_vertex());
160
				double area_j = voronoi_area(vc.get_vertex());
115
				HalfEdgeIter h = vc.get_halfedge();
161
				HalfEdgeIter h = vc.get_halfedge();
116
				Vec3d nbr(h->vert->pos);
162
				Vec3d nbr(h->vert->pos);
117
				Vec3d left(h->next->vert->pos);
163
				Vec3d left(h->next->vert->pos);
118
				Vec3d right(h->opp->prev->opp->vert->pos);
164
				Vec3d right(h->opp->prev->opp->vert->pos);
119
				
165
				
120
				double d_left = dot(normalize(nbr-left),
166
				double d_left = dot(normalize(nbr-left),
121
									normalize(vertex-left));
167
									normalize(vertex-left));
122
				double d_right = dot(normalize(nbr-right),
168
				double d_right = dot(normalize(nbr-right),
123
									 normalize(vertex-right));
169
									 normalize(vertex-right));
124
				double a_left  = acos(min(1.0, max(-1.0, d_left)));
170
				double a_left  = acos(min(1.0, max(-1.0, d_left)));
125
				double a_right = acos(min(1.0, max(-1.0, d_right)));
171
				double a_right = acos(min(1.0, max(-1.0, d_right)));
126
				
172
				
127
				double w = 1.0/tan(a_left) + 1.0/tan(a_right);
173
				double w = 1.0/tan(a_left) + 1.0/tan(a_right);
128
				
174
				
129
				Q[i][j] = -w/sqrt(area_i*area_j);						
175
				Q[i][j] = -w/sqrt(area_i*area_j);						
130
				//Q[i][j] = -1;						
176
				//Q[i][j] = -1;						
131
				a_sum += Q[i][j];
177
				a_sum += Q[i][j];
132
			}
178
			}
133
			Q[i][i] = -a_sum;
179
			Q[i][i] = -a_sum;
134
		}
180
		}
135
	EigenSolutionsSym(Q,V);
181
	EigenSolutionsSym(Q,V);
136
	
182
	
137
}
183
}
138
 
184
 
139
 
185
 
140
Harmonics::Harmonics(Manifold& _mani):mani(_mani)
186
Harmonics::Harmonics(Manifold& _mani):mani(_mani)
141
{
187
{
142
	assert(is_initialized);
188
	assert(is_initialized);
143
		
189
		
144
	triangulate(mani);
190
	triangulate(mani);
145
	mani.enumerate_vertices();
191
	mani.enumerate_vertices();
146
	maximum_eigenvalue = mani.no_vertices()-1;
192
	maximum_eigenvalue = mani.no_vertices()-1;
147
	make_laplace_operator();
193
	make_laplace_operator();
148
	
194
	
149
	proj.resize(maximum_eigenvalue);
195
	proj.resize(maximum_eigenvalue);
150
	max_eig_values.resize(maximum_eigenvalue, 1e-10);
196
	max_eig_values.resize(maximum_eigenvalue, 1e-10);
151
	for(int es=0; es<maximum_eigenvalue; ++es)
197
	for(int es=0; es<maximum_eigenvalue; ++es)
152
	{
198
	{
153
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
199
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
154
		{
200
		{
155
			int i= v->touched;
201
			int i= v->touched;
156
			proj[es] += Vec3d(v->pos) * Q[es][i];
202
			proj[es] += Vec3d(v->pos) * Q[es][i];
157
			max_eig_values[es] = max(max_eig_values[es], static_cast<float>(abs(Q[es][i])));
203
			max_eig_values[es] = max(max_eig_values[es], static_cast<float>(abs(Q[es][i])));
158
		}
204
		}
159
	}
205
	}
160
}
206
}
161
 
207
 
162
void Harmonics::add_frequency(int es, float scale)
208
void Harmonics::add_frequency(int es, float scale)
163
{
209
{
164
	if(es<maximum_eigenvalue)
210
	if(es<maximum_eigenvalue)
165
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
211
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
166
		{
212
		{
167
			Vec3f& p = v->pos; 
213
			Vec3f& p = v->pos; 
168
			v->pos += Vec3f(proj[es] * Q[es][v->touched] * scale);
214
			v->pos += Vec3f(proj[es] * Q[es][v->touched] * scale);
169
		}
215
		}
170
	
216
	
171
}
217
}
172
 
218
 
173
void Harmonics::reset_shape()
219
void Harmonics::reset_shape()
174
{
220
{
175
	for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
221
	for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
176
		v->pos = Vec3f(0);	
222
		v->pos = Vec3f(0);	
177
}
223
}
178
void Harmonics::partial_reconstruct(int E0, int E1, float scale)
224
void Harmonics::partial_reconstruct(int E0, int E1, float scale)
179
{
225
{
180
	for(int es=E0;es<=E1;++es)
226
	for(int es=E0;es<=E1;++es)
181
		add_frequency(es, scale);
227
		add_frequency(es, scale);
182
}
228
}
183
 
229
 
184
 
230
 
185
template<typename T>
231
template<typename T>
186
T& get_CVar_ref(const std::string& s)
232
T& get_CVar_ref(const std::string& s)
187
{
233
{
188
	return *reinterpret_cast<T*> (GetCVarData(s));
234
	return *reinterpret_cast<T*> (GetCVarData(s));
189
}
235
}
190
 
236
 
191
void Harmonics::parse_key(unsigned char key)
237
void Harmonics::parse_key(unsigned char key)
192
{
238
{
193
		int& display_eigenvalue = get_CVar_ref<int>("display.harmonics.eigenvalue");
239
		int& display_eigenvalue = get_CVar_ref<int>("display.harmonics.eigenvalue");
194
		int& display_diffuse = get_CVar_ref<int>("display.harmonics.diffuse");
240
		int& display_diffuse = get_CVar_ref<int>("display.harmonics.diffuse");
195
		int& display_highlight = get_CVar_ref<int>("display.harmonics.highlight");
241
		int& display_highlight = get_CVar_ref<int>("display.harmonics.highlight");
196
		switch(key) {
242
		switch(key) {
197
			case '+': 
243
			case '+': 
198
				display_eigenvalue = min(display_eigenvalue+1, maximum_eigenvalue); 
244
				display_eigenvalue = min(display_eigenvalue+1, maximum_eigenvalue); 
199
				break;
245
				break;
200
			case '-': 
246
			case '-': 
201
				display_eigenvalue = max(display_eigenvalue-1, 0); 
247
				display_eigenvalue = max(display_eigenvalue-1, 0); 
202
				break;
248
				break;
203
			case 'd':	
249
			case 'd':	
204
				display_diffuse = !display_diffuse; 
250
				display_diffuse = !display_diffuse; 
205
				break;
251
				break;
206
			case 'h':
252
			case 'h':
207
				display_highlight = !display_highlight;
253
				display_highlight = !display_highlight;
208
				break;			
254
				break;			
209
		}
255
		}
210
 
256
 
211
}
257
}
212
 
258
 
213
void Harmonics::draw()
259
void Harmonics::draw()
214
{
260
{
215
	int& display_eigen = get_CVar_ref<int>("display.harmonics.eigenvalue");
261
	int& display_eigen = get_CVar_ref<int>("display.harmonics.eigenvalue");
216
	int& display_eigen2 = get_CVar_ref<int>("display.harmonics.eigenvalue");
262
	int& display_eigen2 = get_CVar_ref<int>("display.harmonics.eigenvalue");
217
	int& do_diffuse = get_CVar_ref<int>("display.harmonics.diffuse");
263
	int& do_diffuse = get_CVar_ref<int>("display.harmonics.diffuse");
218
	int& do_highlight = get_CVar_ref<int>("display.harmonics.highlight");
264
	int& do_highlight = get_CVar_ref<int>("display.harmonics.highlight");
219
 
265
 
220
 
266
 
221
	glUseProgram(prog_P0);
267
	glUseProgram(prog_P0);
222
	glUniform1f(glGetUniformLocation(prog_P0,"eig_max"),max_eig_values[display_eigen]);
268
	glUniform1f(glGetUniformLocation(prog_P0,"eig_max"),max_eig_values[display_eigen]);
223
	glUniform1f(glGetUniformLocation(prog_P0,"eig_max2"),max_eig_values[display_eigen2]);
269
	glUniform1f(glGetUniformLocation(prog_P0,"eig_max2"),max_eig_values[display_eigen2]);
224
	glUniform1i(glGetUniformLocation(prog_P0,"do_diffuse"),do_diffuse);
270
	glUniform1i(glGetUniformLocation(prog_P0,"do_diffuse"),do_diffuse);
225
   	glUniform1i(glGetUniformLocation(prog_P0,"do_highlight"),do_highlight);
271
   	glUniform1i(glGetUniformLocation(prog_P0,"do_highlight"),do_highlight);
226
	GLuint attrib = glGetAttribLocationARB(prog_P0, "eigenvalue");
272
	GLuint attrib = glGetAttribLocationARB(prog_P0, "eigenvalue");
227
	GLuint attrib2 = glGetAttribLocationARB(prog_P0, "eigenvalue2");
273
	GLuint attrib2 = glGetAttribLocationARB(prog_P0, "eigenvalue2");
228
	
274
	
229
	glFrontFace(GL_CW);
275
	glFrontFace(GL_CW);
230
	for(FaceIter f=mani.faces_begin(); f != mani.faces_end(); ++f)
276
	for(FaceIter f=mani.faces_begin(); f != mani.faces_end(); ++f)
231
	{
277
	{
232
		FaceCirculator fc(f);
278
		FaceCirculator fc(f);
233
		glBegin(GL_TRIANGLES);
279
		glBegin(GL_TRIANGLES);
234
		while(!fc.end())
280
		while(!fc.end())
235
		{
281
		{
236
			int i = fc.get_vertex()->touched;
282
			int i = fc.get_vertex()->touched;
237
			glVertexAttrib1f(attrib,Q[display_eigen][i]);
283
			glVertexAttrib1f(attrib,Q[display_eigen][i]);
238
			glVertexAttrib1f(attrib2,Q[display_eigen2][i]);
284
			glVertexAttrib1f(attrib2,Q[display_eigen2][i]);
239
			glNormal3fv(normal(fc.get_vertex()).get());
285
			glNormal3fv(normal(fc.get_vertex()).get());
240
			glVertex3fv(fc.get_vertex()->pos.get());
286
			glVertex3fv(fc.get_vertex()->pos.get());
241
			++fc;
287
			++fc;
242
		}
288
		}
243
		glEnd();
289
		glEnd();
244
	}
290
	}
245
	glFrontFace(GL_CCW);
291
	glFrontFace(GL_CCW);
246
	glUseProgram(0);
292
	glUseProgram(0);
247
}
293
}
248
 
294
 
249
void Harmonics::init()
295
void Harmonics::init()
250
{
296
{
251
	is_initialized = true;
297
	is_initialized = true;
252
	string shader_path = "/Users/jab/GEL/apps/MeshEdit/";
298
	string shader_path = "/Users/jab/GEL/apps/MeshEdit/";
253
	GLuint vs = create_glsl_shader(GL_VERTEX_SHADER, shader_path, "tri.vert");
299
	GLuint vs = create_glsl_shader(GL_VERTEX_SHADER, vss);
254
	GLuint fs = create_glsl_shader(GL_FRAGMENT_SHADER, shader_path, "tri.frag");
300
	GLuint fs = create_glsl_shader(GL_FRAGMENT_SHADER, fss);
255
	
301
	
256
	// Create the program
302
	// Create the program
257
	prog_P0 = glCreateProgram();
303
	prog_P0 = glCreateProgram();
258
	
304
	
259
	// Attach all shaders
305
	// Attach all shaders
260
	if(vs) glAttachShader(prog_P0, vs);
306
	if(vs) glAttachShader(prog_P0, vs);
261
	if(fs) glAttachShader(prog_P0, fs);
307
	if(fs) glAttachShader(prog_P0, fs);
262
	
308
	
263
	// Link the program object and print out the info log
309
	// Link the program object and print out the info log
264
	glLinkProgram(prog_P0);
310
	glLinkProgram(prog_P0);
265
	print_glsl_program_log(prog_P0);
311
	print_glsl_program_log(prog_P0);
266
	
312
	
267
	// Install program object as part of current state
313
	// Install program object as part of current state
268
	glUseProgram(0);
314
	glUseProgram(0);
269
	
315
	
270
	static CVar<int> display_eigen("display.harmonics.eigenvalue",0);
316
	static CVar<int> display_eigen("display.harmonics.eigenvalue",0);
271
	static CVar<int> display_eigen2("display.harmonics.eigenvalue2",0);
317
	static CVar<int> display_eigen2("display.harmonics.eigenvalue2",0);
272
	static CVar<int> do_highlight("display.harmonics.highlight",1);
318
	static CVar<int> do_highlight("display.harmonics.highlight",1);
273
	static CVar<int> do_diffuse("display.harmonics.diffuse",1);
319
	static CVar<int> do_diffuse("display.harmonics.diffuse",1);
274
 
320
 
275
}
321
}
276
 
322