Subversion Repositories gelsvn

Rev

Rev 416 | Rev 596 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
386 jab 1
/*
2
 *  harmonics.cpp
3
 *  GEL
4
 *
5
 *  Created by J. Andreas Bærentzen on 01/09/08.
6
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
7
 *
8
 */
9
 
10
#include <iostream>
457 jab 11
 
12
#include "harmonics.h"
13
 
14
#if USE_SPARSE_MATRIX
15
#include <arlgsym.h>
16
#endif
17
 
386 jab 18
#include <CGLA/Vec3f.h>
19
#include <CGLA/Vec3d.h>
457 jab 20
#include <CGLA/Mat2x2d.h>
386 jab 21
#include <LinAlg/Matrix.h>
22
#include <LinAlg/Vector.h>
23
#include <LinAlg/LapackFunc.h>
24
 
25
#include <GL/glew.h>
26
#include <GLGraphics/glsl_shader.h>
27
 
28
#include <HMesh/Manifold.h>
29
#include <HMesh/VertexCirculator.h>
30
#include <HMesh/FaceCirculator.h>
31
#include <HMesh/build_manifold.h>
32
#include <HMesh/mesh_optimization.h>
33
#include <HMesh/triangulate.h>
34
#include <HMesh/load.h>
35
#include <HMesh/x3d_save.h>
36
 
37
#include <GLConsole/GLConsole.h>
38
 
457 jab 39
#include "curvature.h"
40
#include "CSCMatrixBuilder.h"
386 jab 41
 
42
using namespace CGLA;
43
using namespace std;
44
using namespace HMesh;
45
using namespace Geometry;
46
using namespace GLGraphics;
47
using namespace LinAlg;
412 jab 48
using namespace CVarUtils;
386 jab 49
 
391 jab 50
bool Harmonics::is_initialized=false;
51
GLuint Harmonics::prog_P0;
386 jab 52
 
53
 
54
namespace
55
{
457 jab 56
 
397 jab 57
	string vss =
457 jab 58
	"#version 120\n"
59
	"#extension GL_EXT_gpu_shader4 : enable\n"
60
	"	\n"
61
	"	\n"
62
	"	attribute float eigenvalue;\n"
63
	"	attribute float eigenvalue2;\n"
64
	"	varying vec3 normal;\n"
65
	"	varying float eig;\n"
66
	"	varying float eig2;\n"
67
	"	\n"
68
	"	void main(void)\n"
69
	"	{\n"
70
	"		gl_Position =  ftransform();\n"
71
	"		normal = normalize(gl_NormalMatrix * gl_Normal);\n"
72
	"		eig = eigenvalue;\n"
73
	"		eig2 = eigenvalue2;\n"
74
	"	}\n";
386 jab 75
 
457 jab 76
	string fss = 	
77
	"#version 120\n"
78
	"#extension GL_EXT_gpu_shader4 : enable\n"
79
	"	\n"
80
	"	varying vec3 normal;\n"
81
	"	varying float eig;\n"
82
	"	varying float eig2;\n"
83
	"	uniform float eig_max;\n"
84
	"	uniform float eig_max2;\n"
85
	"	uniform bool do_highlight;\n"
86
	"	uniform bool do_diffuse;\n"
87
	"	const vec3 light_dir = vec3(0,0,1);\n"
88
	"	\n"
89
	" float basef(float x) {return max(0.0,min(1.0,2.0-4.0*abs(x)));\n}" 
90
	"	void main()\n"
91
	"	{\n"
92
	"		float dot_ln = max(0.0,dot(light_dir, normal));\n"
93
	"		\n"
94
	"		float eig_norm = eig/eig_max;\n"
95
	"		float stripe_signal = 250 * eig_norm;\n"
96
	//"		vec4 stripe_col = abs(stripe_signal) < 3.14 ? vec4(1,1,0,0) : vec4(.4,.4,.4,0);\n"
97
	"		vec4 stripe_col = -vec4(.4,.4,.4,0);\n"
98
	"		\n"
99
	"       float alpha = (1.0-eig_norm) * 2.0 * 3.1415926;\n"
100
	"       float offs = 2.0*3.1415/3.0;\n"
101
	"		gl_FragColor = vec4(0,0,1,0)*basef(eig_norm)+vec4(0,1,0,0)*basef(eig_norm-0.5)+vec4(1,0,0,0)* basef(eig_norm-1.0);\n"
102
	"		if(do_diffuse)   gl_FragColor *= dot_ln;\n"
103
	"		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"
104
	"		gl_FragColor -= vec4(.4,.4,.4,.4)*smoothstep(0.2,0.6,cos(stripe_signal));\n"
105
	"	}\n";
106
}
107
 
108
 
109
 
110
#if USE_SPARSE_MATRIX
111
 
112
double calculate_laplace_entry(VertexCirculator vc,Vec3d vertex)
113
{
114
	//* this piece of code is taken from the orginal make_laplace_operator...
115
	HalfEdgeIter h = vc.get_halfedge();
116
	Vec3d nbr(h->vert->pos);
117
	Vec3d left(h->next->vert->pos);
118
	Vec3d right(h->opp->prev->opp->vert->pos);
397 jab 119
 
457 jab 120
	double d_left = dot(normalize(nbr-left),normalize(vertex-left));
121
	double d_right = dot(normalize(nbr-right),normalize(vertex-right));
122
	double a_left  = acos(min(1.0, max(-1.0, d_left))); // w positive...?
123
	double a_right = acos(min(1.0, max(-1.0, d_right)));
124
 
125
	double w = 1.0/tan(a_left) + 1.0/tan(a_right);
126
	return -w;
127
}
128
 
129
void Harmonics::make_laplace_operator_sparse()
130
{
131
	bool is_generalized=true;
132
	CSCMatrixBuilder<double> mb_M;
133
	//+GENERALIZED
134
	CSCMatrixBuilder<double> mb_S;
135
	// S has the same type as V
136
	S.Resize(mani.no_vertices());
137
 
138
	for(VertexIter v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
139
		if(!is_boundary(v))
140
		{
141
			int i = v->touched;
142
			double area_i = voronoi_area(v);
143
			Vec3d vertex(v->pos);
144
			double a_sum = 0;
145
			for(VertexCirculator vc(v); !vc.end(); ++vc)
146
			{
147
				int j = vc.get_vertex()->touched;
148
				double entry = calculate_laplace_entry(vc,vertex);
149
				if(!is_generalized)
150
				{
151
					double area_j = voronoi_area(vc.get_vertex());
152
					entry /= sqrt(area_i*area_j);
153
				}
154
				if(j > i)
155
					mb_M.insert_entry(j,entry);
156
				a_sum += entry;
157
			}
158
			//cout << a_sum << " ";
159
			mb_M.insert_entry(i,-a_sum);
160
			mb_M.next_column();
161
 
162
			if(!is_generalized)
163
				area_i = 1; // if standard S is an identity matrix;
164
			mb_S.insert_entry(i,area_i);
165
			mb_S.next_column_nonsort();
166
			S[i] = area_i;
167
		}     
168
 
169
	cout << "solving generalized problem... i = " << mani.no_vertices()<< endl;
170
 
171
 
172
	//+STANDARD
173
	//ArpackPP::ARluSymStdEig<double> dprob(50L, mb_M.get_Matrix(), "SA");
174
	//+GENERALIZED (shifted inv mode)
175
	ARluSymGenEig<double> dprob('S',maximum_eigenvalue, mb_M.get_Matrix(), mb_S.get_Matrix(), 0.0);
176
	//ArpackPP::ARluSymGenEig<double> dprob(number_of_eigenvalues, mb_M.get_Matrix(), mb_S.get_Matrix());
177
 
178
	dprob.FindEigenvectors();
179
	int conv = dprob.ConvergedEigenvalues();
180
	cout << conv << " eigenvectors found" << endl;
181
	Q.Resize(conv, dprob.GetN());
182
	V.Resize(conv);
183
 
184
	qnorm.Resize(conv);
185
	for(int i = 0; i < conv; i++)
386 jab 186
	{
457 jab 187
		V[i] = dprob.Eigenvalue(i);
188
		qnorm[i] = 0;
189
		for(int j = 0; j < dprob.GetN(); j++)
386 jab 190
		{
457 jab 191
			Q[i][j] = dprob.Eigenvector(i,j);
192
			qnorm[i] += Q[i][j]*Q[i][j];
386 jab 193
		}
457 jab 194
 
195
		cout << "(" << i << ":" << sqrt(V[i]/V[1]
196
										) << ")" << V[i]/V[1] << "V= "<< V[i] << " exp " << exp(-0.01*V[i]/V[1]) << " Qnorm " << qnorm[i]<< endl;
386 jab 197
	}
457 jab 198
 
199
	cout  << endl;
386 jab 200
}
201
 
457 jab 202
Harmonics::Harmonics(Manifold& _mani):mani(_mani)
203
{
204
	assert(is_initialized);
205
 
206
	maximum_eigenvalue = min(size_t(500),mani.no_vertices());
207
 
208
	triangulate(mani);
209
	mani.enumerate_vertices();
210
	make_laplace_operator_sparse();
211
 
212
	if(maximum_eigenvalue == -1)
386 jab 213
	{
457 jab 214
		cout << "not found" << endl;
215
		return;
216
	}
217
 
218
	proj.resize(maximum_eigenvalue);
219
 
220
	max_eig_values.resize(maximum_eigenvalue, 1e-10f);
221
 
222
	cout << endl << "Proj" << endl;
223
	for(int es=0; es<maximum_eigenvalue; ++es)  //o(n^2)
386 jab 224
	{
457 jab 225
		proj[es] = Vec3d(0.0);
226
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
227
		{
228
			proj[es] +=  Vec3d(v->pos) * Q[es][v->touched] * S[v->touched];
229
			max_eig_values[es] = max(max_eig_values[es], static_cast<float>(abs(Q[es][v->touched])));     
230
		}     
386 jab 231
	}
457 jab 232
	cout << endl;
386 jab 233
}
234
 
457 jab 235
#else
391 jab 236
void Harmonics::make_laplace_operator()
386 jab 237
{
238
	Q.Resize(mani.no_vertices(), mani.no_vertices());
239
 
240
	for(VertexIter v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
241
		if(!is_boundary(v))
242
		{
243
			int i = v->touched;
244
			double area_i = voronoi_area(v);
245
			Vec3d vertex(v->pos);
246
			Vec3d curv_normal(0);
247
			double a_sum = 0;
248
			for(VertexCirculator vc(v); !vc.end(); ++vc)
249
			{
250
				int j = vc.get_vertex()->touched;
251
				double area_j = voronoi_area(vc.get_vertex());
252
				HalfEdgeIter h = vc.get_halfedge();
253
				Vec3d nbr(h->vert->pos);
254
				Vec3d left(h->next->vert->pos);
255
				Vec3d right(h->opp->prev->opp->vert->pos);
256
 
257
				double d_left = dot(normalize(nbr-left),
258
									normalize(vertex-left));
259
				double d_right = dot(normalize(nbr-right),
260
									 normalize(vertex-right));
261
				double a_left  = acos(min(1.0, max(-1.0, d_left)));
262
				double a_right = acos(min(1.0, max(-1.0, d_right)));
263
 
264
				double w = 1.0/tan(a_left) + 1.0/tan(a_right);
265
 
266
				Q[i][j] = -w/sqrt(area_i*area_j);						
267
				//Q[i][j] = -1;						
268
				a_sum += Q[i][j];
269
			}
270
			Q[i][i] = -a_sum;
271
		}
272
	EigenSolutionsSym(Q,V);
273
}
274
 
391 jab 275
Harmonics::Harmonics(Manifold& _mani):mani(_mani)
386 jab 276
{
391 jab 277
	assert(is_initialized);
457 jab 278
 
391 jab 279
	triangulate(mani);
280
	mani.enumerate_vertices();
281
	maximum_eigenvalue = mani.no_vertices()-1;
282
	make_laplace_operator();
283
 
284
	proj.resize(maximum_eigenvalue);
409 jrf 285
	max_eig_values.resize(maximum_eigenvalue, 1e-10f);
457 jab 286
 
287
	cout << "Projection magnitude" << endl;
391 jab 288
	for(int es=0; es<maximum_eigenvalue; ++es)
386 jab 289
	{
399 jab 290
		proj[es] = Vec3d(0.0);
386 jab 291
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
292
		{
399 jab 293
			proj[es] +=  Vec3d(v->pos) * Q[es][v->touched];
294
			max_eig_values[es] = max(max_eig_values[es], static_cast<float>(abs(Q[es][v->touched])));
386 jab 295
		}
296
	}
297
}
298
 
457 jab 299
#endif
300
 
391 jab 301
void Harmonics::add_frequency(int es, float scale)
386 jab 302
{
391 jab 303
	if(es<maximum_eigenvalue)
386 jab 304
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
305
		{
399 jab 306
			Vec3f p = Vec3f(proj[es]);
307
			double Qval = Q[es][v->touched];
308
 
403 jab 309
			v->pos += p * Qval * scale; 	
386 jab 310
		}
311
}
312
 
391 jab 313
void Harmonics::reset_shape()
386 jab 314
{
315
	for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
391 jab 316
		v->pos = Vec3f(0);	
386 jab 317
}
391 jab 318
void Harmonics::partial_reconstruct(int E0, int E1, float scale)
386 jab 319
{
320
	for(int es=E0;es<=E1;++es)
391 jab 321
		add_frequency(es, scale);
386 jab 322
}
323
 
391 jab 324
void Harmonics::parse_key(unsigned char key)
386 jab 325
{
457 jab 326
	float& display_t = GetCVarRef<float>("display.harmonics.time");
327
	int& display_diffuse = GetCVarRef<int>("display.harmonics.diffuse");
328
	int& display_highlight = GetCVarRef<int>("display.harmonics.highlight");
329
	switch(key) {
330
		case '+': 
331
			display_t = display_t+0.001; 
332
			break;
333
		case '-': 
334
			display_t = display_t-0.001; 
335
			break;
336
		case 'd':	
337
			display_diffuse = !display_diffuse; 
338
			break;
339
		case 'h':
340
			display_highlight = !display_highlight;
341
			break;			
342
	}
343
 
391 jab 344
}
345
 
457 jab 346
 
347
void Harmonics::draw_adf()
391 jab 348
{
457 jab 349
	float& t = GetCVarRef<float>("display.harmonics.time");
412 jab 350
	int& do_diffuse = GetCVarRef<int>("display.harmonics.diffuse");
351
	int& do_highlight = GetCVarRef<int>("display.harmonics.highlight");
457 jab 352
 
353
	vector<double> F(mani.no_vertices(),0);
354
	double F_max = 0;
355
	for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
356
	{
357
		int v_idx = v->touched;
358
		for(int e=1;e<V.Length();++e)
359
			F[v_idx] += sqr(Q[e][v_idx])*exp(-(t)*V[e]/V[1]);
360
		F_max = max(F[v_idx], F_max);
361
	}
362
	cout << "F max" <<  F_max << endl;
386 jab 363
	glUseProgram(prog_P0);
457 jab 364
	glUniform1f(glGetUniformLocation(prog_P0,"eig_max"),F_max);//2*M_PI);
386 jab 365
	glUniform1i(glGetUniformLocation(prog_P0,"do_diffuse"),do_diffuse);
366
   	glUniform1i(glGetUniformLocation(prog_P0,"do_highlight"),do_highlight);
367
	GLuint attrib = glGetAttribLocationARB(prog_P0, "eigenvalue");
368
 
369
	glFrontFace(GL_CW);
391 jab 370
	for(FaceIter f=mani.faces_begin(); f != mani.faces_end(); ++f)
386 jab 371
	{
372
		FaceCirculator fc(f);
373
		glBegin(GL_TRIANGLES);
374
		while(!fc.end())
375
		{
376
			int i = fc.get_vertex()->touched;
457 jab 377
			glVertexAttrib1f(attrib,F[i]);
386 jab 378
			glNormal3fv(normal(fc.get_vertex()).get());
391 jab 379
			glVertex3fv(fc.get_vertex()->pos.get());
386 jab 380
			++fc;
381
		}
382
		glEnd();
383
	}
384
	glFrontFace(GL_CCW);
385
	glUseProgram(0);
386
}
387
 
391 jab 388
void Harmonics::init()
386 jab 389
{
391 jab 390
	is_initialized = true;
386 jab 391
	string shader_path = "/Users/jab/GEL/apps/MeshEdit/";
397 jab 392
	GLuint vs = create_glsl_shader(GL_VERTEX_SHADER, vss);
393
	GLuint fs = create_glsl_shader(GL_FRAGMENT_SHADER, fss);
386 jab 394
 
395
	// Create the program
396
	prog_P0 = glCreateProgram();
397
 
398
	// Attach all shaders
399
	if(vs) glAttachShader(prog_P0, vs);
400
	if(fs) glAttachShader(prog_P0, fs);
401
 
402
	// Link the program object and print out the info log
403
	glLinkProgram(prog_P0);
404
	print_glsl_program_log(prog_P0);
405
 
406
	// Install program object as part of current state
394 jab 407
	glUseProgram(0);
388 jab 408
 
457 jab 409
	CreateCVar("display.harmonics.time",0.0f);
412 jab 410
	CreateCVar("display.harmonics.eigenvalue2",0);
411
	CreateCVar("display.harmonics.highlight",1);
412
	CreateCVar("display.harmonics.diffuse",1);
457 jab 413
	CreateCVar("display.harmonics.diffusion_distance_init_vertex",0);
414
 
386 jab 415
}