Subversion Repositories gelsvn

Rev

Rev 412 | Rev 457 | 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>
11
#include <CGLA/Vec3f.h>
12
#include <CGLA/Vec3d.h>
13
#include <LinAlg/Matrix.h>
14
#include <LinAlg/Vector.h>
15
#include <LinAlg/LapackFunc.h>
16
 
17
#include <GL/glew.h>
18
#include <GLGraphics/glsl_shader.h>
19
 
20
#include <HMesh/Manifold.h>
21
#include <HMesh/VertexCirculator.h>
22
#include <HMesh/FaceCirculator.h>
23
#include <HMesh/build_manifold.h>
24
#include <HMesh/mesh_optimization.h>
25
#include <HMesh/triangulate.h>
26
#include <HMesh/load.h>
27
#include <HMesh/x3d_save.h>
28
 
29
#include <GLConsole/GLConsole.h>
30
 
31
#include "harmonics.h"
32
 
33
using namespace CGLA;
34
using namespace std;
35
using namespace HMesh;
36
using namespace Geometry;
37
using namespace GLGraphics;
38
using namespace LinAlg;
412 jab 39
using namespace CVarUtils;
386 jab 40
 
391 jab 41
bool Harmonics::is_initialized=false;
42
GLuint Harmonics::prog_P0;
386 jab 43
 
44
 
45
namespace
46
{
397 jab 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";
386 jab 66
 
397 jab 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";
93
 
386 jab 94
	double voronoi_area(VertexIter v)
95
	{
96
	double area_mixed = 0;
97
	//For each triangle T from the 1-ring neighborhood of x
98
	for(VertexCirculator vc(v); !vc.end(); ++vc)
99
	{
100
		FaceIter f = vc.get_face();
101
		double f_area = area(f);
102
 
103
		HalfEdgeIter he = vc.get_halfedge();
104
		Vec3d v1(he->vert->pos);
105
		Vec3d v2(he->next->vert->pos);
106
		Vec3d v0(he->next->next->vert->pos);
107
 
108
		double a0 = acos(dot(v1-v0, v2-v0)/(length(v1-v0)*length(v2-v0)));
109
		double a1 = acos(dot(v2-v1, v0-v1)/(length(v2-v1)*length(v0-v1)));
110
		double a2 = acos(dot(v0-v2, v1-v2)/(length(v0-v2)*length(v1-v2)));
111
 
112
		if(a0>(M_PI/2.0) && a1>(M_PI/2.0) && a2>(M_PI/2.0)) // f is non-obtuse
113
		{
114
			// Add Voronoi formula (see Section 3.3)
115
			area_mixed += (1.0/8) * 
116
			((1.0/tan(a1)) * sqr_length(v2-v0) + 
117
			 (1.0/tan(a2)) * sqr_length(v1-v0));
118
		}
119
		else // Voronoi inappropriate
120
		{
121
			// Add either area(f)/4 or area(f)/2
122
			if(a0>M_PI/2.0)// the angle of f at x is obtuse
123
				area_mixed += f_area/2;
124
			else
125
				area_mixed += f_area/4;
126
		}
127
	}
128
	return area_mixed;
129
}
130
 
131
	double barycentric_area(VertexIter v)
132
	{
133
	double barea = 0;
134
	//For each triangle T from the 1-ring neighborhood of x
135
	for(VertexCirculator vc(v); !vc.end(); ++vc)
136
	{
137
		FaceIter f = vc.get_face();
138
		barea += area(f)/3.0;
139
	}
140
	return barea;
141
}
142
 
143
}
144
 
391 jab 145
void Harmonics::make_laplace_operator()
386 jab 146
{
147
	Q.Resize(mani.no_vertices(), mani.no_vertices());
148
 
149
	for(VertexIter v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
150
		if(!is_boundary(v))
151
		{
152
			int i = v->touched;
153
			double area_i = voronoi_area(v);
154
			Vec3d vertex(v->pos);
155
			Vec3d curv_normal(0);
156
			double a_sum = 0;
157
			for(VertexCirculator vc(v); !vc.end(); ++vc)
158
			{
159
				int j = vc.get_vertex()->touched;
160
				double area_j = voronoi_area(vc.get_vertex());
161
				HalfEdgeIter h = vc.get_halfedge();
162
				Vec3d nbr(h->vert->pos);
163
				Vec3d left(h->next->vert->pos);
164
				Vec3d right(h->opp->prev->opp->vert->pos);
165
 
166
				double d_left = dot(normalize(nbr-left),
167
									normalize(vertex-left));
168
				double d_right = dot(normalize(nbr-right),
169
									 normalize(vertex-right));
170
				double a_left  = acos(min(1.0, max(-1.0, d_left)));
171
				double a_right = acos(min(1.0, max(-1.0, d_right)));
172
 
173
				double w = 1.0/tan(a_left) + 1.0/tan(a_right);
174
 
175
				Q[i][j] = -w/sqrt(area_i*area_j);						
176
				//Q[i][j] = -1;						
177
				a_sum += Q[i][j];
178
			}
179
			Q[i][i] = -a_sum;
180
		}
181
	EigenSolutionsSym(Q,V);
182
}
183
 
184
 
391 jab 185
Harmonics::Harmonics(Manifold& _mani):mani(_mani)
386 jab 186
{
391 jab 187
	assert(is_initialized);
188
 
189
	triangulate(mani);
190
	mani.enumerate_vertices();
191
	maximum_eigenvalue = mani.no_vertices()-1;
192
	make_laplace_operator();
193
 
194
	proj.resize(maximum_eigenvalue);
409 jrf 195
	max_eig_values.resize(maximum_eigenvalue, 1e-10f);
399 jab 196
 
391 jab 197
	for(int es=0; es<maximum_eigenvalue; ++es)
386 jab 198
	{
399 jab 199
		proj[es] = Vec3d(0.0);
386 jab 200
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
201
		{
399 jab 202
 
203
			proj[es] +=  Vec3d(v->pos) * Q[es][v->touched];
204
			max_eig_values[es] = max(max_eig_values[es], static_cast<float>(abs(Q[es][v->touched])));
386 jab 205
		}
206
	}
207
}
208
 
391 jab 209
void Harmonics::add_frequency(int es, float scale)
386 jab 210
{
391 jab 211
	if(es<maximum_eigenvalue)
386 jab 212
		for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
213
		{
399 jab 214
			Vec3f p = Vec3f(proj[es]);
215
			double Qval = Q[es][v->touched];
216
 
403 jab 217
			v->pos += p * Qval * scale; 	
386 jab 218
		}
219
}
220
 
391 jab 221
void Harmonics::reset_shape()
386 jab 222
{
223
	for(VertexIter v=mani.vertices_begin(); v != mani.vertices_end(); ++v)
391 jab 224
		v->pos = Vec3f(0);	
386 jab 225
}
391 jab 226
void Harmonics::partial_reconstruct(int E0, int E1, float scale)
386 jab 227
{
228
	for(int es=E0;es<=E1;++es)
391 jab 229
		add_frequency(es, scale);
386 jab 230
}
231
 
391 jab 232
void Harmonics::parse_key(unsigned char key)
386 jab 233
{
412 jab 234
		int& display_eigenvalue = GetCVarRef<int>("display.harmonics.eigenvalue");
235
		int& display_diffuse = GetCVarRef<int>("display.harmonics.diffuse");
236
		int& display_highlight = GetCVarRef<int>("display.harmonics.highlight");
391 jab 237
		switch(key) {
238
			case '+': 
239
				display_eigenvalue = min(display_eigenvalue+1, maximum_eigenvalue); 
240
				break;
241
			case '-': 
242
				display_eigenvalue = max(display_eigenvalue-1, 0); 
243
				break;
244
			case 'd':	
245
				display_diffuse = !display_diffuse; 
246
				break;
247
			case 'h':
248
				display_highlight = !display_highlight;
249
				break;			
250
		}
251
 
252
}
253
 
254
void Harmonics::draw()
255
{
412 jab 256
	int& display_eigen = GetCVarRef<int>("display.harmonics.eigenvalue");
257
	int& display_eigen2 = GetCVarRef<int>("display.harmonics.eigenvalue");
258
	int& do_diffuse = GetCVarRef<int>("display.harmonics.diffuse");
259
	int& do_highlight = GetCVarRef<int>("display.harmonics.highlight");
386 jab 260
 
388 jab 261
 
386 jab 262
	glUseProgram(prog_P0);
263
	glUniform1f(glGetUniformLocation(prog_P0,"eig_max"),max_eig_values[display_eigen]);
264
	glUniform1f(glGetUniformLocation(prog_P0,"eig_max2"),max_eig_values[display_eigen2]);
265
	glUniform1i(glGetUniformLocation(prog_P0,"do_diffuse"),do_diffuse);
266
   	glUniform1i(glGetUniformLocation(prog_P0,"do_highlight"),do_highlight);
267
	GLuint attrib = glGetAttribLocationARB(prog_P0, "eigenvalue");
268
	GLuint attrib2 = glGetAttribLocationARB(prog_P0, "eigenvalue2");
269
 
270
	glFrontFace(GL_CW);
391 jab 271
	for(FaceIter f=mani.faces_begin(); f != mani.faces_end(); ++f)
386 jab 272
	{
273
		FaceCirculator fc(f);
274
		glBegin(GL_TRIANGLES);
275
		while(!fc.end())
276
		{
277
			int i = fc.get_vertex()->touched;
278
			glVertexAttrib1f(attrib,Q[display_eigen][i]);
279
			glVertexAttrib1f(attrib2,Q[display_eigen2][i]);
280
			glNormal3fv(normal(fc.get_vertex()).get());
391 jab 281
			glVertex3fv(fc.get_vertex()->pos.get());
386 jab 282
			++fc;
283
		}
284
		glEnd();
285
	}
286
	glFrontFace(GL_CCW);
287
	glUseProgram(0);
288
}
289
 
391 jab 290
void Harmonics::init()
386 jab 291
{
391 jab 292
	is_initialized = true;
386 jab 293
	string shader_path = "/Users/jab/GEL/apps/MeshEdit/";
397 jab 294
	GLuint vs = create_glsl_shader(GL_VERTEX_SHADER, vss);
295
	GLuint fs = create_glsl_shader(GL_FRAGMENT_SHADER, fss);
386 jab 296
 
297
	// Create the program
298
	prog_P0 = glCreateProgram();
299
 
300
	// Attach all shaders
301
	if(vs) glAttachShader(prog_P0, vs);
302
	if(fs) glAttachShader(prog_P0, fs);
303
 
304
	// Link the program object and print out the info log
305
	glLinkProgram(prog_P0);
306
	print_glsl_program_log(prog_P0);
307
 
308
	// Install program object as part of current state
394 jab 309
	glUseProgram(0);
388 jab 310
 
412 jab 311
	CreateCVar("display.harmonics.eigenvalue",0);
312
	CreateCVar("display.harmonics.eigenvalue2",0);
313
	CreateCVar("display.harmonics.highlight",1);
314
	CreateCVar("display.harmonics.diffuse",1);
386 jab 315
 
316
}