Subversion Repositories gelsvn

Rev

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

Rev 434 Rev 456
1
/*
1
/*
2
 *  MeshEdit is a small application which allows you to load and edit a mesh.
2
 *  MeshEdit is a small application which allows you to load and edit a mesh.
3
 *  The mesh will be stored in GEL's half edge based Manifold data structure.
3
 *  The mesh will be stored in GEL's half edge based Manifold data structure.
4
 *  A number of editing operations are supported. Most of these are accessible from the 
4
 *  A number of editing operations are supported. Most of these are accessible from the 
5
 *  console that pops up when you hit 'esc'.
5
 *  console that pops up when you hit 'esc'.
6
 *
6
 *
7
 *  Created by J. Andreas Bærentzen on 15/08/08.
7
 *  Created by J. Andreas Bærentzen on 15/08/08.
8
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
8
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
9
 *
9
 *
10
 */
10
 */
11
 
11
 
12
#include <string>
12
#include <string>
13
#include <iostream>
13
#include <iostream>
14
#include <CGLA/eigensolution.h>
14
#include <CGLA/eigensolution.h>
15
#include <CGLA/Vec2d.h>
15
#include <CGLA/Vec2d.h>
16
#include <CGLA/Vec3d.h>
16
#include <CGLA/Vec3d.h>
17
#include <CGLA/Mat3x3d.h>
17
#include <CGLA/Mat3x3d.h>
18
#include <CGLA/Mat2x2d.h>
18
#include <CGLA/Mat2x2d.h>
19
#include <CGLA/Mat2x3d.h>
19
#include <CGLA/Mat2x3d.h>
20
 
20
 
21
#include <LinAlg/Matrix.h>
21
#include <LinAlg/Matrix.h>
22
#include <LinAlg/Vector.h>
22
#include <LinAlg/Vector.h>
23
#include <LinAlg/LapackFunc.h>
23
#include <LinAlg/LapackFunc.h>
24
 
24
 
25
#include <Util/Timer.h>
25
#include <Util/Timer.h>
26
#include <Util/ArgExtracter.h>
26
#include <Util/ArgExtracter.h>
27
 
27
 
28
#include <GL/glew.h>
28
#include <GL/glew.h>
29
#include <GLGraphics/gel_glut.h>
29
#include <GLGraphics/gel_glut.h>
30
 
30
 
31
#include <HMesh/Manifold.h>
31
#include <HMesh/Manifold.h>
32
#include <HMesh/VertexCirculator.h>
32
#include <HMesh/VertexCirculator.h>
33
#include <HMesh/FaceCirculator.h>
33
#include <HMesh/FaceCirculator.h>
34
#include <HMesh/build_manifold.h>
34
#include <HMesh/build_manifold.h>
35
#include <HMesh/mesh_optimization.h>
35
#include <HMesh/mesh_optimization.h>
36
#include <HMesh/triangulate.h>
36
#include <HMesh/triangulate.h>
37
#include <HMesh/load.h>
37
#include <HMesh/load.h>
38
#include <HMesh/quadric_simplify.h>
38
#include <HMesh/quadric_simplify.h>
39
#include <HMesh/smooth.h>
39
#include <HMesh/smooth.h>
40
#include <HMesh/x3d_save.h>
40
#include <HMesh/x3d_save.h>
41
#include <HMesh/obj_save.h>
41
#include <HMesh/obj_save.h>
42
#include <HMesh/off_save.h>
42
#include <HMesh/off_save.h>
43
#include <HMesh/mesh_optimization.h>
43
#include <HMesh/mesh_optimization.h>
44
#include <HMesh/triangulate.h>
44
#include <HMesh/triangulate.h>
45
#include <HMesh/close_holes.h>
45
#include <HMesh/close_holes.h>
46
#include <HMesh/caps_and_needles.h>
46
#include <HMesh/caps_and_needles.h>
47
#include <HMesh/refine_edges.h>
47
#include <HMesh/refine_edges.h>
48
#include <HMesh/subdivision.h>
48
#include <HMesh/subdivision.h>
49
 
49
 
50
#include <GLConsole/GLConsole.h>
50
#include <GLConsole/GLConsole.h>
51
#include <Util/Timer.h>
51
#include <Util/Timer.h>
52
#include "harmonics.h"
52
#include "harmonics.h"
53
#include "curvature.h"
53
#include "curvature.h"
54
#include "Renderer.h"
54
#include "Renderer.h"
55
#include "VisObj.h"
55
#include "VisObj.h"
56
 
56
 
57
using namespace std;
57
using namespace std;
58
using namespace HMesh;
58
using namespace HMesh;
59
using namespace Geometry;
59
using namespace Geometry;
60
using namespace GLGraphics;
60
using namespace GLGraphics;
61
using namespace CGLA;
61
using namespace CGLA;
62
using namespace Util;
62
using namespace Util;
63
using namespace LinAlg;
63
using namespace LinAlg;
64
using namespace CVarUtils;
64
using namespace CVarUtils;
65
 
65
 
66
inline VisObj& get_vis_obj(int i)
66
inline VisObj& get_vis_obj(int i)
67
{
67
{
68
	static VisObj vo[9];
68
	static VisObj vo[9];
69
	return vo[i];
69
	return vo[i];
70
}
70
}
71
 
71
 
72
inline VisObj& avo()
72
inline VisObj& avo()
73
{
73
{
74
	static int& active = CreateCVar("active_mesh",0);
74
	static int& active = CreateCVar("active_mesh",0);
75
	return get_vis_obj(active);
75
	return get_vis_obj(active);
76
}
76
}
77
 
77
 
78
inline Manifold& active_mesh()
78
inline Manifold& active_mesh()
79
{
79
{
80
	return avo().mesh();
80
	return avo().mesh();
81
}
81
}
82
 
82
 
83
inline GLViewController& active_view_control()
83
inline GLViewController& active_view_control()
84
{
84
{
85
	return avo().view_control();
85
	return avo().view_control();
86
}
86
}
87
 
87
 
88
// Single global instance so glut can get access
88
// Single global instance so glut can get access
89
Trie CVarTrie;
89
Trie CVarTrie;
90
GLConsole theConsole;
90
GLConsole theConsole;
91
 
91
 
92
////////////////////////////////////////////////////////////////////////////////
92
////////////////////////////////////////////////////////////////////////////////
93
char* ConsoleHelp(std::vector<std::string> &args)
93
char* ConsoleHelp(std::vector<std::string> &args)
94
{
94
{
95
    theConsole.Printf("");
95
    theConsole.Printf("");
96
    theConsole.Printf("----------------- HELP -----------------");
96
    theConsole.Printf("----------------- HELP -----------------");
97
    theConsole.Printf("Press ESC key to open and close console");
97
    theConsole.Printf("Press ESC key to open and close console");
98
    theConsole.Printf("Press TAB to see the available commands and functions");
98
    theConsole.Printf("Press TAB to see the available commands and functions");
99
    theConsole.Printf("Functions are shown in green and variables in yellow");
99
    theConsole.Printf("Functions are shown in green and variables in yellow");
100
    theConsole.Printf("Setting a value: [command] = value");
100
    theConsole.Printf("Setting a value: [command] = value");
101
    theConsole.Printf("Getting a value: [command]");
101
    theConsole.Printf("Getting a value: [command]");
102
    theConsole.Printf("Functions: [function] [arg1] [arg2] ...");
102
    theConsole.Printf("Functions: [function] [arg1] [arg2] ...");
103
    theConsole.Printf("Entering arg1=? or arg1=help will give a description.");
103
    theConsole.Printf("Entering arg1=? or arg1=help will give a description.");
104
    theConsole.Printf("History: Up and Down arrow keys move through history.");
104
    theConsole.Printf("History: Up and Down arrow keys move through history.");
105
    theConsole.Printf("Tab Completion: TAB does tab completion and makes suggestions.");
105
    theConsole.Printf("Tab Completion: TAB does tab completion and makes suggestions.");
106
    theConsole.Printf("");
106
    theConsole.Printf("");
107
    theConsole.Printf("Keyboard commands (when console is not active):");
107
    theConsole.Printf("Keyboard commands (when console is not active):");
108
    theConsole.Printf("w   : switch to display.render_mode = wireframe");
108
    theConsole.Printf("w   : switch to display.render_mode = wireframe");
109
    theConsole.Printf("i   : switch to display.render_mode = isophotes");
109
    theConsole.Printf("i   : switch to display.render_mode = isophotes");
110
    theConsole.Printf("r   : switch to display.render_mode = reflection");
110
    theConsole.Printf("r   : switch to display.render_mode = reflection");
111
    theConsole.Printf("m   : switch to display.render_mode = metallic");
111
    theConsole.Printf("m   : switch to display.render_mode = metallic");
112
    theConsole.Printf("g   : switch to display.render_mode = glazed");
112
    theConsole.Printf("g   : switch to display.render_mode = glazed");
113
    theConsole.Printf("n   : switch to display.render_mode = normal");
113
    theConsole.Printf("n   : switch to display.render_mode = normal");
114
    theConsole.Printf("h   : switch to display.render_mode = harmonics");
114
    theConsole.Printf("h   : switch to display.render_mode = harmonics");
115
    theConsole.Printf("f   : toggle smooth/flat shading");
115
    theConsole.Printf("f   : toggle smooth/flat shading");
116
    theConsole.Printf("1-9 : switch between active meshes.");
116
    theConsole.Printf("1-9 : switch between active meshes.");
117
    theConsole.Printf("d   : (display.render_mode = harmonics) diffuse light on and off");
117
    theConsole.Printf("d   : (display.render_mode = harmonics) diffuse light on and off");
118
    theConsole.Printf("h   : (display.render_mode = harmonics) highlight on and off ");
118
    theConsole.Printf("h   : (display.render_mode = harmonics) highlight on and off ");
119
    theConsole.Printf("+/- : (display.render_mode = harmonics) which eigenvector to show");
119
    theConsole.Printf("+/- : (display.render_mode = harmonics) which eigenvector to show");
120
    theConsole.Printf("q   : quit program");
120
    theConsole.Printf("q   : quit program");
121
    theConsole.Printf("ESC : open console");
121
    theConsole.Printf("ESC : open console");
122
    theConsole.Printf("");
122
    theConsole.Printf("");
123
    theConsole.Printf("Mouse: Left button rotates, middle zooms, right pans");
123
    theConsole.Printf("Mouse: Left button rotates, middle zooms, right pans");
124
    theConsole.Printf("----------------- HELP -----------------");
124
    theConsole.Printf("----------------- HELP -----------------");
125
    theConsole.Printf("");
125
    theConsole.Printf("");
126
    return "";
126
    return "";
127
}
127
}
128
 
128
 
129
bool wantshelp(std::vector<std::string> &args)
129
bool wantshelp(std::vector<std::string> &args)
130
{
130
{
131
	if(args.size()==0) return false;
131
	if(args.size()==0) return false;
132
	string str = args[0];
132
	string str = args[0];
133
	if(str=="help" || str=="HELP" || str=="Help" || str=="?") return true;
133
	if(str=="help" || str=="HELP" || str=="Help" || str=="?") return true;
134
	return false;
134
	return false;
135
}
135
}
136
 
136
 
137
/// Function that aligns two meshes.
137
/// Function that aligns two meshes.
138
char* console_align(std::vector<std::string> &args)
138
char* console_align(std::vector<std::string> &args)
139
{
139
{
140
	if(wantshelp(args)) 
140
	if(wantshelp(args)) 
141
	{
141
	{
142
		theConsole.Printf("usage: align <dest> <src>");
142
		theConsole.Printf("usage: align <dest> <src>");
143
		theConsole.Printf("This function aligns dest mesh with src");
143
		theConsole.Printf("This function aligns dest mesh with src");
144
		theConsole.Printf("In practice the GLViewController of src is copied to dst.");
144
		theConsole.Printf("In practice the GLViewController of src is copied to dst.");
145
		theConsole.Printf("both arguments are mandatory and must be numbers between 1 and 9.");
145
		theConsole.Printf("both arguments are mandatory and must be numbers between 1 and 9.");
146
		theConsole.Printf("Note that results might be unexpexted if the meshes are not on the same scale");
146
		theConsole.Printf("Note that results might be unexpexted if the meshes are not on the same scale");
147
		return "";
147
		return "";
148
	}
148
	}
149
	
149
	
150
	int dest = 0;
150
	int dest = 0;
151
	if(args.size()>0)
151
	if(args.size()>0)
152
	{
152
	{
153
		istringstream a0(args[0]);
153
		istringstream a0(args[0]);
154
		a0 >> dest;
154
		a0 >> dest;
155
		--dest;
155
		--dest;
156
		if(dest <0 || dest>8) return "dest mesh out of range (1-9)";
156
		if(dest <0 || dest>8) return "dest mesh out of range (1-9)";
157
	}
157
	}
158
	else return "neither source nor destination mesh?!";
158
	else return "neither source nor destination mesh?!";
159
	int src = 0;
159
	int src = 0;
160
	if(args.size()>1)
160
	if(args.size()>1)
161
	{
161
	{
162
		istringstream a1(args[1]);
162
		istringstream a1(args[1]);
163
		a1 >> src;
163
		a1 >> src;
164
		--src;
164
		--src;
165
		if(src <0 || src>8) return "src mesh out of range (1-9)";
165
		if(src <0 || src>8) return "src mesh out of range (1-9)";
166
	}	
166
	}	
167
	else return "no src mesh?";
167
	else return "no src mesh?";
168
	
168
	
169
	get_vis_obj(dest).view_control() = get_vis_obj(src).view_control();
169
	get_vis_obj(dest).view_control() = get_vis_obj(src).view_control();
170
	
170
	
171
	return "";
171
	return "";
172
}
172
}
173
 
173
 
174
char* console_flatten(std::vector<std::string> &args)
174
char* console_flatten(std::vector<std::string> &args)
175
{
175
{
176
	if(wantshelp(args)) 
176
	if(wantshelp(args)) 
177
	{
177
	{
178
		theConsole.Printf("usage: flatten <floater|harmonic|barycentric>");
178
		theConsole.Printf("usage: flatten <floater|harmonic|barycentric>");
179
		theConsole.Printf("This function flattens a meshs with a simple boundary. It is mostly for showing mesh");
179
		theConsole.Printf("This function flattens a meshs with a simple boundary. It is mostly for showing mesh");
180
		theConsole.Printf("parametrization methods. The current mesh MUST have a SINGLE boundary loop");
180
		theConsole.Printf("parametrization methods. The current mesh MUST have a SINGLE boundary loop");
181
		theConsole.Printf("This loop is mapped to the unit circle in a regular fashion (equal angle intervals).");
181
		theConsole.Printf("This loop is mapped to the unit circle in a regular fashion (equal angle intervals).");
182
		theConsole.Printf("All non boundary vertices are placed at the origin. Then the system is relaxed iteratively");
182
		theConsole.Printf("All non boundary vertices are placed at the origin. Then the system is relaxed iteratively");
183
		theConsole.Printf("using the weight scheme given as argument.");
183
		theConsole.Printf("using the weight scheme given as argument.");
184
		return "";
184
		return "";
185
	}
185
	}
186
	enum WeightScheme {FLOATER_W, HARMONIC_W, BARYCENTRIC_W};
186
	enum WeightScheme {FLOATER_W, HARMONIC_W, BARYCENTRIC_W};
187
	WeightScheme ws = BARYCENTRIC_W;
187
	WeightScheme ws = BARYCENTRIC_W;
188
	if(args.size()>0)
188
	if(args.size()>0)
189
	{
189
	{
190
		if(args[0] == "floater")
190
		if(args[0] == "floater")
191
			ws = FLOATER_W;
191
			ws = FLOATER_W;
192
		else if(args[0] == "harmonic")
192
		else if(args[0] == "harmonic")
193
			ws = HARMONIC_W;
193
			ws = HARMONIC_W;
194
	}
194
	}
195
	else
195
	else
196
		return "";
196
		return "";
197
	
197
	
198
	active_mesh().enumerate_vertices();
198
	active_mesh().enumerate_vertices();
199
	active_mesh().enumerate_halfedges();
199
	active_mesh().enumerate_halfedges();
200
	
200
	
201
	vector<float> edge_weights(active_mesh().no_halfedges());
201
	vector<float> edge_weights(active_mesh().no_halfedges());
202
	for(HalfEdgeIter h=active_mesh().halfedges_begin(); h != active_mesh().halfedges_end(); ++h)
202
	for(HalfEdgeIter h=active_mesh().halfedges_begin(); h != active_mesh().halfedges_end(); ++h)
203
		if(!is_boundary(h))
203
		if(!is_boundary(h))
204
		{
204
		{
205
			Vec3f p0 = h->vert->pos;
205
			Vec3f p0 = h->vert->pos;
206
			Vec3f p1 = h->next->vert->pos;
206
			Vec3f p1 = h->next->vert->pos;
207
			Vec3f p2 = h->opp->vert->pos;
207
			Vec3f p2 = h->opp->vert->pos;
208
			Vec3f p3 = h->opp->next->vert->pos;
208
			Vec3f p3 = h->opp->next->vert->pos;
209
			
209
			
210
			if(ws == FLOATER_W)
210
			if(ws == FLOATER_W)
211
			{
211
			{
212
				float d = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p0), normalize(p3-p0)))));
212
				float d = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p0), normalize(p3-p0)))));
213
				float g = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p0), normalize(p1-p0)))));
213
				float g = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p0), normalize(p1-p0)))));
214
				edge_weights[h->opp->touched]  = (tan(d/2) + tan(g/2)) / (p0-p2).length();
214
				edge_weights[h->opp->touched]  = (tan(d/2) + tan(g/2)) / (p0-p2).length();
215
				
215
				
216
				
216
				
217
				d = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p2), normalize(p1-p2)))));
217
				d = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p2), normalize(p1-p2)))));
218
				g = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p2), normalize(p3-p2)))));
218
				g = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p2), normalize(p3-p2)))));
219
				edge_weights[h->touched]  = (tan(d/2) + tan(g/2)) / (p0-p2).length();
219
				edge_weights[h->touched]  = (tan(d/2) + tan(g/2)) / (p0-p2).length();
220
			}
220
			}
221
			else if(ws == HARMONIC_W)
221
			else if(ws == HARMONIC_W)
222
			{
222
			{
223
				
223
				
224
				float a = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p3), normalize(p2-p3)))));
224
				float a = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p3), normalize(p2-p3)))));
225
				float b = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p1), normalize(p0-p1)))));
225
				float b = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p1), normalize(p0-p1)))));
226
				float w=0;
226
				float w=0;
227
				if(a+b < M_PI)
227
				if(a+b < M_PI)
228
					w = sin(a+b)/(sin(a)+sin(b));
228
					w = sin(a+b)/(sin(a)+sin(b));
229
				edge_weights[h->touched]  = w;
229
				edge_weights[h->touched]  = w;
230
				edge_weights[h->opp->touched]  = w;
230
				edge_weights[h->opp->touched]  = w;
231
			}
231
			}
232
			else
232
			else
233
			{
233
			{
234
				edge_weights[h->touched]  = valency(h->opp->vert);
234
				edge_weights[h->touched]  = valency(h->opp->vert);
235
				edge_weights[h->opp->touched]  = valency(h->vert);
235
				edge_weights[h->opp->touched]  = valency(h->vert);
236
			}	
236
			}	
237
		}
237
		}
238
	
238
	
239
	ofstream ofs("parametrized.obj");
239
	ofstream ofs("parametrized.obj");
240
	
240
	
241
	ofs << "mtllib parametrized.mtl\nusemtl mat\n" << endl;
241
	ofs << "mtllib parametrized.mtl\nusemtl mat\n" << endl;
242
	
242
	
243
	VertexIter v;
243
	VertexIter v;
244
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
244
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
245
		ofs << "v " << v->pos[0] << " " << v->pos[1] << " " << v->pos[2] << endl;
245
		ofs << "v " << v->pos[0] << " " << v->pos[1] << " " << v->pos[2] << endl;
246
	ofs << endl;
246
	ofs << endl;
247
	
247
	
248
	
248
	
249
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
249
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
250
	{
250
	{
251
		if(is_boundary(v))
251
		if(is_boundary(v))
252
			break;
252
			break;
253
	}
253
	}
254
	int n=0;
254
	int n=0;
255
	VertexIter bv = v;
255
	VertexIter bv = v;
256
	do{
256
	do{
257
		++n;
257
		++n;
258
		bv = bv->he->vert;
258
		bv = bv->he->vert;
259
	}
259
	}
260
	while(bv != v);
260
	while(bv != v);
261
	
261
	
262
	int i=0;
262
	int i=0;
263
	do{
263
	do{
264
		float a = 2.0*M_PI*float(i)/n;
264
		float a = 2.0*M_PI*float(i)/n;
265
		bv->pos = Vec3f(cos(a), sin(a), 0);
265
		bv->pos = Vec3f(cos(a), sin(a), 0);
266
		++i;
266
		++i;
267
		bv = bv->he->vert;
267
		bv = bv->he->vert;
268
	}
268
	}
269
	while(bv != v);
269
	while(bv != v);
270
	
270
	
271
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
271
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
272
		if(!is_boundary(v))
272
		if(!is_boundary(v))
273
			v->pos = Vec3f(0.0);
273
			v->pos = Vec3f(0.0);
274
	
274
	
275
	for(int i=0;i<10000;++i)
275
	for(int i=0;i<10000;++i)
276
		for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
276
		for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
277
			if(!is_boundary(v))
277
			if(!is_boundary(v))
278
			{
278
			{
279
				Vec3f p_new(0);
279
				Vec3f p_new(0);
280
				float w_sum = 0;
280
				float w_sum = 0;
281
				for(VertexCirculator vc(v); !vc.end(); ++vc)
281
				for(VertexCirculator vc(v); !vc.end(); ++vc)
282
				{
282
				{
283
					float w = edge_weights[vc.get_halfedge()->touched];
283
					float w = edge_weights[vc.get_halfedge()->touched];
284
					p_new += vc.get_vertex()->pos * w;
284
					p_new += vc.get_vertex()->pos * w;
285
					w_sum += w;
285
					w_sum += w;
286
				}
286
				}
287
				v->pos = p_new/w_sum;
287
				v->pos = p_new/w_sum;
288
			}
288
			}
289
	
289
	
290
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
290
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
291
		ofs << "vt " << (0.5*v->pos[0]+0.5) << " " << (0.5*v->pos[1]+0.5)  << endl;
291
		ofs << "vt " << (0.5*v->pos[0]+0.5) << " " << (0.5*v->pos[1]+0.5)  << endl;
292
	
292
	
293
	ofs << endl;
293
	ofs << endl;
294
	
294
	
295
	for(FaceIter f = active_mesh().faces_begin(); f != active_mesh().faces_end(); ++f)
295
	for(FaceIter f = active_mesh().faces_begin(); f != active_mesh().faces_end(); ++f)
296
	{
296
	{
297
		ofs << "f ";
297
		ofs << "f ";
298
		for(FaceCirculator fc(f); !fc.end(); ++fc)
298
		for(FaceCirculator fc(f); !fc.end(); ++fc)
299
		{
299
		{
300
			int idx = fc.get_vertex()->touched + 1;
300
			int idx = fc.get_vertex()->touched + 1;
301
			ofs << idx << "/" << idx <<" ";
301
			ofs << idx << "/" << idx <<" ";
302
		}
302
		}
303
		ofs << endl;
303
		ofs << endl;
304
	}
304
	}
305
	
305
	
306
	return "";
306
	return "";
307
}
307
}
308
 
308
 
309
char* console_save(std::vector<std::string> &args)
309
char* console_save(std::vector<std::string> &args)
310
{
310
{
311
	if(wantshelp(args)) 
311
	if(wantshelp(args)) 
312
	{
312
	{
313
		theConsole.Printf("usage: save <name.x3d|name.obj> ");
313
		theConsole.Printf("usage: save <name.x3d|name.obj> ");
314
		return "";
314
		return "";
315
	}
315
	}
316
	string& file_name = args[0];
316
	string& file_name = args[0];
317
	if(args.size() == 1)
317
	if(args.size() == 1)
318
	{
318
	{
319
		if(file_name.substr(file_name.length()-4,file_name.length())==".obj")
319
		if(file_name.substr(file_name.length()-4,file_name.length())==".obj")
320
		{
320
		{
321
			obj_save(file_name, active_mesh());
321
			obj_save(file_name, active_mesh());
322
			return "";
322
			return "";
323
		}
323
		}
324
		else if(file_name.substr(file_name.length()-4,file_name.length())==".off")
324
		else if(file_name.substr(file_name.length()-4,file_name.length())==".off")
325
		{
325
		{
326
			off_save(file_name, active_mesh());
326
			off_save(file_name, active_mesh());
327
			return "";
327
			return "";
328
		}
328
		}
329
		else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d")
329
		else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d")
330
		{
330
		{
331
			x3d_save(file_name, active_mesh());
331
			x3d_save(file_name, active_mesh());
332
			return "";
332
			return "";
333
		}
333
		}
334
		return "unknown format";
334
		return "unknown format";
335
	}
335
	}
336
	return "usage: save <name.x3d|name.obj> ";
336
	return "usage: save <name.x3d|name.obj> ";
337
}
337
}
338
 
338
 
339
////////////////////////////////////////////////////////////////////////////////
339
////////////////////////////////////////////////////////////////////////////////
340
/**
340
/**
341
 */
341
 */
342
char* ConsoleSaveHistory( std::vector<std::string> &vArgs )
342
char* ConsoleSaveHistory( std::vector<std::string> &vArgs )
343
{
343
{
344
    if( vArgs.size() != 0 ) {
344
    if( vArgs.size() != 0 ) {
345
        theConsole.SaveHistory( vArgs[0] );
345
        theConsole.SaveHistory( vArgs[0] );
346
    }
346
    }
347
    else {
347
    else {
348
        theConsole.SaveHistory();
348
        theConsole.SaveHistory();
349
    }
349
    }
350
	return "";
350
	return "";
351
}
351
}
352
 
352
 
353
////////////////////////////////////////////////////////////////////////////////
353
////////////////////////////////////////////////////////////////////////////////
354
/**
354
/**
355
 */
355
 */
356
char* ConsoleLoadHistory( std::vector<std::string> &vArgs )
356
char* ConsoleLoadHistory( std::vector<std::string> &vArgs )
357
{
357
{
358
    if( vArgs.size() != 0 ) {
358
    if( vArgs.size() != 0 ) {
359
        theConsole.LoadHistory( vArgs[0] );
359
        theConsole.LoadHistory( vArgs[0] );
360
    }
360
    }
361
    else {
361
    else {
362
        theConsole.LoadHistory();
362
        theConsole.LoadHistory();
363
    }
363
    }
364
	return "";
364
	return "";
365
}
365
}
366
 
366
 
367
////////////////////////////////////////////////////////////////////////////////
367
////////////////////////////////////////////////////////////////////////////////
368
/**
368
/**
369
 */
369
 */
370
char* ConsoleClearHistory( std::vector<std::string> &vArgs )
370
char* ConsoleClearHistory( std::vector<std::string> &vArgs )
371
{
371
{
372
	theConsole.ClearHistory();
372
	theConsole.ClearHistory();
373
	return "";
373
	return "";
374
}
374
}
375
 
375
 
376
////////////////////////////////////////////////////////////////////////////////
376
////////////////////////////////////////////////////////////////////////////////
377
/**
377
/**
378
 */
378
 */
379
char* ConsoleStartScript( std::vector<std::string> &vArgs )
379
char* ConsoleStartScript( std::vector<std::string> &vArgs )
380
{
380
{
381
    theConsole.StartScript();
381
    theConsole.StartScript();
382
	return "";
382
	return "";
383
}
383
}
384
 
384
 
385
////////////////////////////////////////////////////////////////////////////////
385
////////////////////////////////////////////////////////////////////////////////
386
/**
386
/**
387
 */
387
 */
388
char* ConsoleStopScript( std::vector<std::string> &vArgs )
388
char* ConsoleStopScript( std::vector<std::string> &vArgs )
389
{
389
{
390
    theConsole.StopScript();
390
    theConsole.StopScript();
391
	return "";
391
	return "";
392
}
392
}
393
 
393
 
394
////////////////////////////////////////////////////////////////////////////////
394
////////////////////////////////////////////////////////////////////////////////
395
/**
395
/**
396
 */
396
 */
397
char* ConsoleShowScript( std::vector<std::string> &vArgs )
397
char* ConsoleShowScript( std::vector<std::string> &vArgs )
398
{
398
{
399
    theConsole.ShowScript();
399
    theConsole.ShowScript();
400
	return "";
400
	return "";
401
}
401
}
402
 
402
 
403
////////////////////////////////////////////////////////////////////////////////
403
////////////////////////////////////////////////////////////////////////////////
404
/**
404
/**
405
 */
405
 */
406
char* ConsoleRunScript( std::vector<std::string> &vArgs )
406
char* ConsoleRunScript( std::vector<std::string> &vArgs )
407
{
407
{
408
    theConsole.RunScript();
408
    theConsole.RunScript();
409
    return "";
409
    return "";
410
}
410
}
411
 
411
 
412
////////////////////////////////////////////////////////////////////////////////
412
////////////////////////////////////////////////////////////////////////////////
413
/**
413
/**
414
 */
414
 */
415
char* ConsoleSaveScript( std::vector<std::string> &vArgs )
415
char* ConsoleSaveScript( std::vector<std::string> &vArgs )
416
{
416
{
417
    if( vArgs.size() != 0 ) {
417
    if( vArgs.size() != 0 ) {
418
        theConsole.SaveScript( vArgs[0] );
418
        theConsole.SaveScript( vArgs[0] );
419
    }
419
    }
420
    else {
420
    else {
421
        theConsole.SaveScript();
421
        theConsole.SaveScript();
422
    }
422
    }
423
	return "";
423
	return "";
424
}
424
}
425
 
425
 
426
////////////////////////////////////////////////////////////////////////////////
426
////////////////////////////////////////////////////////////////////////////////
427
/**
427
/**
428
 */
428
 */
429
char* ConsoleLaunchScript( std::vector<std::string> &vArgs )
429
char* ConsoleLaunchScript( std::vector<std::string> &vArgs )
430
{
430
{
431
    if( vArgs.size() != 0 ) {
431
    if( vArgs.size() != 0 ) {
432
        theConsole.LaunchScript( vArgs[0] );
432
        theConsole.LaunchScript( vArgs[0] );
433
    } 
433
    } 
434
    else {
434
    else {
435
        theConsole.LaunchScript();
435
        theConsole.LaunchScript();
436
    }
436
    }
437
	return "";
437
	return "";
438
}
438
}
439
 
439
 
440
 
440
 
441
////////////////////////////////////////////////////////////////////////////////
441
////////////////////////////////////////////////////////////////////////////////
442
/**
442
/**
443
 */
443
 */
444
char* ConsoleLoad( std::vector<std::string> &vArgs )
444
char* ConsoleLoad( std::vector<std::string> &vArgs )
445
{
445
{
446
    std::string sFile = "cvars.xml";
446
    std::string sFile = "cvars.xml";
447
    std::vector< std::string > vAcceptedSubstrings;
447
    std::vector< std::string > vAcceptedSubstrings;
448
    
448
    
449
    if( vArgs.size() > 0 ) {
449
    if( vArgs.size() > 0 ) {
450
        sFile = vArgs[0]; 
450
        sFile = vArgs[0]; 
451
        for( size_t i=1; i<vArgs.size(); i++ ) {
451
        for( size_t i=1; i<vArgs.size(); i++ ) {
452
            vAcceptedSubstrings.push_back( vArgs[i] );
452
            vAcceptedSubstrings.push_back( vArgs[i] );
453
        }
453
        }
454
    }
454
    }
455
    theConsole.Printf("Loading file from \"%s\".", sFile.c_str() );
455
    theConsole.Printf("Loading file from \"%s\".", sFile.c_str() );
456
    if( !CVarUtils::Load( sFile, vAcceptedSubstrings) ) {
456
    if( !CVarUtils::Load( sFile, vAcceptedSubstrings) ) {
457
        theConsole.Printf( "Error loading file.\n" );
457
        theConsole.Printf( "Error loading file.\n" );
458
    }
458
    }
459
    return "";
459
    return "";
460
}
460
}
461
 
461
 
462
 
462
 
463
char* console_refine_edges(std::vector<std::string> &args)
463
char* console_refine_edges(std::vector<std::string> &args)
464
{
464
{
465
	if(wantshelp(args)) 
465
	if(wantshelp(args)) 
466
	{
466
	{
467
		theConsole.Printf("usage: refine.split_edges <length>");
467
		theConsole.Printf("usage: refine.split_edges <length>");
468
		theConsole.Printf("splits edges longer than <length>; default is 0.5 times average length");
468
		theConsole.Printf("splits edges longer than <length>; default is 0.5 times average length");
469
		return "";
469
		return "";
470
	}
470
	}
471
	
471
	
472
	float thresh = 0.5;
472
	float thresh = 0.5;
473
	if(args.size()>0)
473
	if(args.size()>0)
474
	{
474
	{
475
		istringstream a0(args[0]);
475
		istringstream a0(args[0]);
476
		a0 >> thresh;
476
		a0 >> thresh;
477
	}
477
	}
478
	float avg_length = average_edge_length(active_mesh());
478
	float avg_length = average_edge_length(active_mesh());
479
	refine_edges(active_mesh(), thresh * avg_length);
479
	refine_edges(active_mesh(), thresh * avg_length);
480
	return "";
480
	return "";
481
	
481
	
482
}
482
}
483
 
483
 
484
char* console_refine_faces(std::vector<std::string> &args)
484
char* console_refine_faces(std::vector<std::string> &args)
485
{
485
{
486
	if(wantshelp(args)) 
486
	if(wantshelp(args)) 
487
	{
487
	{
488
		theConsole.Printf("usage: refine.split_faces ");
488
		theConsole.Printf("usage: refine.split_faces ");
489
		theConsole.Printf("usage:  Takes no arguments. Inserts a vertex at the centre of each face.");
489
		theConsole.Printf("usage:  Takes no arguments. Inserts a vertex at the centre of each face.");
490
		return "";
490
		return "";
491
	}
491
	}
492
	
492
	
493
	safe_triangulate(active_mesh());
493
	safe_triangulate(active_mesh());
494
	return "";
494
	return "";
495
	
495
	
496
}
496
}
497
 
497
 
498
char* console_cc_subdivide(std::vector<std::string> &args)
498
char* console_cc_subdivide(std::vector<std::string> &args)
499
{
499
{
500
	if(wantshelp(args)) 
500
	if(wantshelp(args)) 
501
	{
501
	{
502
		theConsole.Printf("usage: refine.catmull_clark ");
502
		theConsole.Printf("usage: refine.catmull_clark ");
503
		theConsole.Printf("Splits each polygon into four (Catmull Clark style)");
503
		theConsole.Printf("Splits each polygon into four (Catmull Clark style)");
504
		return "";
504
		return "";
505
	}
505
	}
506
	cc_split(active_mesh(),active_mesh());
506
	cc_split(active_mesh(),active_mesh());
507
	return "";
507
	return "";
508
}
508
}
509
 
509
 
510
char* console_dual(std::vector<std::string> &args)
510
char* console_dual(std::vector<std::string> &args)
511
{
511
{
512
	if(wantshelp(args)) 
512
	if(wantshelp(args)) 
513
	{
513
	{
514
		theConsole.Printf("usage: dual ");
514
		theConsole.Printf("usage: dual ");
515
		theConsole.Printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
515
		theConsole.Printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
516
		return "";
516
		return "";
517
	}
517
	}
518
	
518
	
519
	Manifold& m = active_mesh();
519
	Manifold& m = active_mesh();
520
	
520
	
521
	// make sure every face knows its number
521
	// make sure every face knows its number
522
	m.enumerate_faces();
522
	m.enumerate_faces();
523
	
523
	
524
	vector<Vec3f> vertices(m.no_faces());
524
	vector<Vec3f> vertices(m.no_faces());
525
	vector<int> faces;
525
	vector<int> faces;
526
	vector<int> indices;
526
	vector<int> indices;
527
	
527
	
528
	// Create new vertices. Each face becomes a vertex whose position
528
	// Create new vertices. Each face becomes a vertex whose position
529
	// is the centre of the face
529
	// is the centre of the face
530
	int i=0;
530
	int i=0;
531
	for(FaceIter f=m.faces_begin(); f!=m.faces_end(); ++f,++i)
531
	for(FaceIter f=m.faces_begin(); f!=m.faces_end(); ++f,++i)
532
		vertices[i] = centre(f);
532
		vertices[i] = centre(f);
533
	
533
	
534
	// Create new faces. Each vertex is a new face with N=valency of vertex
534
	// Create new faces. Each vertex is a new face with N=valency of vertex
535
	// edges.
535
	// edges.
536
	i=0;
536
	i=0;
537
	for(VertexIter v=m.vertices_begin(); v!= m.vertices_end(); ++v,++i)
537
	for(VertexIter v=m.vertices_begin(); v!= m.vertices_end(); ++v,++i)
538
		if(!is_boundary(v))
538
		if(!is_boundary(v))
539
		{
539
		{
540
			VertexCirculator vc(v);
540
			VertexCirculator vc(v);
541
			vector<int> index_tmp;
541
			vector<int> index_tmp;
542
			for(; !vc.end(); ++vc)
542
			for(; !vc.end(); ++vc)
543
				index_tmp.push_back(vc.get_face()->touched);
543
				index_tmp.push_back(vc.get_face()->touched);
544
			
544
			
545
			// Push vertex indices for this face onto indices vector.
545
			// Push vertex indices for this face onto indices vector.
546
			// The circulator moves around the face in a clockwise fashion
546
			// The circulator moves around the face in a clockwise fashion
547
			// so we just reverse the ordering.
547
			// so we just reverse the ordering.
548
			indices.insert(indices.end(), index_tmp.rbegin(), index_tmp.rend());
548
			indices.insert(indices.end(), index_tmp.rbegin(), index_tmp.rend());
549
			
549
			
550
			// Insert face valency in the face vector.
550
			// Insert face valency in the face vector.
551
			faces.push_back(vc.no_steps());
551
			faces.push_back(vc.no_steps());
552
		}
552
		}
553
	
553
	
554
	// Clear the manifold before new geometry is inserted.
554
	// Clear the manifold before new geometry is inserted.
555
	m.clear();
555
	m.clear();
556
	
556
	
557
	// And build
557
	// And build
558
	build_manifold(m, vertices.size(), &vertices[0], faces.size(),
558
	build_manifold(m, vertices.size(), &vertices[0], faces.size(),
559
				   &faces[0],&indices[0]);
559
				   &faces[0],&indices[0]);
560
	
560
	
561
	return "";
561
	return "";
562
}
562
}
563
 
563
 
564
 
564
 
565
char* console_minimize_curvature(std::vector<std::string> &args)
565
char* console_minimize_curvature(std::vector<std::string> &args)
566
{
566
{
567
	if(wantshelp(args)) 
567
	if(wantshelp(args)) 
568
	{
568
	{
569
		theConsole.Printf("usage: optimize.minimize_curvature <anneal>");
569
		theConsole.Printf("usage: optimize.minimize_curvature <anneal>");
570
		theConsole.Printf("Flip edges to minimize mean curvature.");
570
		theConsole.Printf("Flip edges to minimize mean curvature.");
571
		theConsole.Printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
571
		theConsole.Printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
572
		return "";
572
		return "";
573
	}
573
	}
574
	bool anneal=false;
574
	bool anneal=false;
575
	if(args.size()>0)
575
	if(args.size()>0)
576
	{
576
	{
577
		istringstream a0(args[0]);
577
		istringstream a0(args[0]);
578
		a0 >> anneal;
578
		a0 >> anneal;
579
	}
579
	}
580
	
580
	
581
	minimize_curvature(active_mesh(), anneal);
581
	minimize_curvature(active_mesh(), anneal);
582
	avo().post_create_display_list();
582
	avo().post_create_display_list();
583
	return "";
583
	return "";
584
}
584
}
585
 
585
 
586
char* console_minimize_dihedral(std::vector<std::string> &args)
586
char* console_minimize_dihedral(std::vector<std::string> &args)
587
{
587
{
588
	if(wantshelp(args)) 
588
	if(wantshelp(args)) 
589
	{
589
	{
590
		theConsole.Printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
590
		theConsole.Printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
591
		theConsole.Printf("Flip edges to minimize dihedral angles.");
591
		theConsole.Printf("Flip edges to minimize dihedral angles.");
592
		theConsole.Printf("Iter is the max number of iterations. anneal tells us whether to use ");
592
		theConsole.Printf("Iter is the max number of iterations. anneal tells us whether to use ");
593
		theConsole.Printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
593
		theConsole.Printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
594
		theConsole.Printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
594
		theConsole.Printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
595
		theConsole.Printf("to which we raise the dihedral angle");
595
		theConsole.Printf("to which we raise the dihedral angle");
596
		return "";
596
		return "";
597
	}
597
	}
598
	int iter = 1000;
598
	int iter = 1000;
599
	if(args.size()>0)
599
	if(args.size()>0)
600
	{
600
	{
601
		istringstream a0(args[0]);
601
		istringstream a0(args[0]);
602
		a0 >> iter;
602
		a0 >> iter;
603
	}
603
	}
604
	
604
	
605
	bool anneal = false;
605
	bool anneal = false;
606
	if(args.size()>1)
606
	if(args.size()>1)
607
	{
607
	{
608
		istringstream a0(args[0]);
608
		istringstream a0(args[0]);
609
		a0 >> anneal;
609
		a0 >> anneal;
610
	}
610
	}
611
	
611
	
612
	bool use_alpha = true;
612
	bool use_alpha = true;
613
	if(args.size()>2)
613
	if(args.size()>2)
614
	{
614
	{
615
		istringstream a0(args[0]);
615
		istringstream a0(args[0]);
616
		a0 >> use_alpha;
616
		a0 >> use_alpha;
617
	}
617
	}
618
	
618
	
619
	float gamma = 4.0;
619
	float gamma = 4.0;
620
	if(args.size()>3)
620
	if(args.size()>3)
621
	{
621
	{
622
		istringstream a0(args[0]);
622
		istringstream a0(args[0]);
623
		a0 >> gamma;
623
		a0 >> gamma;
624
	}
624
	}
625
	
625
	
626
	
626
	
627
	minimize_dihedral_angle(active_mesh(), iter, anneal, use_alpha, gamma);
627
	minimize_dihedral_angle(active_mesh(), iter, anneal, use_alpha, gamma);
628
	return "";
628
	return "";
629
}
629
}
630
 
630
 
631
char* console_maximize_min_angle(std::vector<std::string> &args)
631
char* console_maximize_min_angle(std::vector<std::string> &args)
632
{
632
{
633
	if(wantshelp(args)) 
633
	if(wantshelp(args)) 
634
	{
634
	{
635
		theConsole.Printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
635
		theConsole.Printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
636
		theConsole.Printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
636
		theConsole.Printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
637
		theConsole.Printf("If the dot product of the normals between adjacent faces < thresh");
637
		theConsole.Printf("If the dot product of the normals between adjacent faces < thresh");
638
		theConsole.Printf("no flip will be made. anneal selects simulated annealing rather ");
638
		theConsole.Printf("no flip will be made. anneal selects simulated annealing rather ");
639
		theConsole.Printf("nthan greedy optimization.");
639
		theConsole.Printf("nthan greedy optimization.");
640
		return "";
640
		return "";
641
	}
641
	}
642
	float thresh=0.0;
642
	float thresh=0.0;
643
	if(args.size()>0)
643
	if(args.size()>0)
644
	{
644
	{
645
		istringstream a0(args[0]);
645
		istringstream a0(args[0]);
646
		a0 >> thresh;
646
		a0 >> thresh;
647
	}
647
	}
648
	bool anneal=false;
648
	bool anneal=false;
649
	if(args.size()>1)
649
	if(args.size()>1)
650
	{
650
	{
651
		istringstream a0(args[0]);
651
		istringstream a0(args[0]);
652
		a0 >> anneal;
652
		a0 >> anneal;
653
	}
653
	}
654
	maximize_min_angle(active_mesh(),thresh,anneal);
654
	maximize_min_angle(active_mesh(),thresh,anneal);
655
	return "";
655
	return "";
656
}
656
}
657
 
657
 
658
 
658
 
659
char* console_optimize_valency(std::vector<std::string> &args)
659
char* console_optimize_valency(std::vector<std::string> &args)
660
{
660
{
661
	if(wantshelp(args)) 
661
	if(wantshelp(args)) 
662
	{
662
	{
663
		theConsole.Printf("usage: optimize.valency <anneal> ");
663
		theConsole.Printf("usage: optimize.valency <anneal> ");
664
		theConsole.Printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
664
		theConsole.Printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
665
		return "";
665
		return "";
666
	}
666
	}
667
	bool anneal=false;
667
	bool anneal=false;
668
	if(args.size()>0)
668
	if(args.size()>0)
669
	{
669
	{
670
		istringstream a0(args[0]);
670
		istringstream a0(args[0]);
671
		a0 >> anneal;
671
		a0 >> anneal;
672
	}
672
	}
673
	optimize_valency(active_mesh(), anneal);
673
	optimize_valency(active_mesh(), anneal);
674
	return "";
674
	return "";
675
}
675
}
676
 
676
 
677
char* console_analyze(std::vector<std::string> &args)
677
char* console_analyze(std::vector<std::string> &args)
678
{
678
{
679
	if(wantshelp(args)) 
679
	if(wantshelp(args)) 
680
	{
680
	{
681
		theConsole.Printf("usage:  harmonics.analyze");
681
		theConsole.Printf("usage:  harmonics.analyze");
682
		theConsole.Printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
682
		theConsole.Printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
683
		theConsole.Printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
683
		theConsole.Printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
684
		theConsole.Printf("to this basis.");
684
		theConsole.Printf("to this basis.");
685
		theConsole.Printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
685
		theConsole.Printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
686
		return "";
686
		return "";
687
	}
687
	}
688
	avo().harmonics_analyze_mesh();
688
	avo().harmonics_analyze_mesh();
689
	return "";
689
	return "";
690
}
690
}
691
 
691
 
692
 
692
 
693
char* console_partial_reconstruct(std::vector<std::string> &args)
693
char* console_partial_reconstruct(std::vector<std::string> &args)
694
{
694
{
695
	if(args.size() != 3)
695
	if(args.size() != 3)
696
		theConsole.Printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
696
		theConsole.Printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
697
	
697
	
698
	if(wantshelp(args)) 
698
	if(wantshelp(args)) 
699
	{
699
	{
700
		theConsole.Printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
700
		theConsole.Printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
701
		theConsole.Printf("the eigenvector interval that we reconstruct from. The last argument is the ");
701
		theConsole.Printf("the eigenvector interval that we reconstruct from. The last argument is the ");
702
		theConsole.Printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
702
		theConsole.Printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
703
		theConsole.Printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
703
		theConsole.Printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
704
		theConsole.Printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
704
		theConsole.Printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
705
		theConsole.Printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
705
		theConsole.Printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
706
		theConsole.Printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
706
		theConsole.Printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
707
	}
707
	}
708
	
708
	
709
	if(args.size() != 3)
709
	if(args.size() != 3)
710
		return "";
710
		return "";
711
	
711
	
712
	int E0,E1;
712
	int E0,E1;
713
	float scale;
713
	float scale;
714
	istringstream a0(args[0]);
714
	istringstream a0(args[0]);
715
	a0 >> E0;
715
	a0 >> E0;
716
	istringstream a1(args[1]);
716
	istringstream a1(args[1]);
717
	a1 >> E1;
717
	a1 >> E1;
718
	istringstream a2(args[2]);
718
	istringstream a2(args[2]);
719
	a2 >> scale;
719
	a2 >> scale;
720
	avo().harmonics_partial_reconstruct(E0,E1,scale);
720
	avo().harmonics_partial_reconstruct(E0,E1,scale);
721
	return "";
721
	return "";
722
}
722
}
723
 
723
 
724
char* console_reset_shape(std::vector<std::string> &args)
724
char* console_reset_shape(std::vector<std::string> &args)
725
{
725
{
726
	if(wantshelp(args)) 
726
	if(wantshelp(args)) 
727
	{
727
	{
728
		theConsole.Printf("usage: harmonics.reset_shape ");
728
		theConsole.Printf("usage: harmonics.reset_shape ");
729
		theConsole.Printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
729
		theConsole.Printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
730
		theConsole.Printf("unless you know what you are doing.");
730
		theConsole.Printf("unless you know what you are doing.");
731
		return "";
731
		return "";
732
	}
732
	}
733
	avo().harmonics_reset_shape();
733
	avo().harmonics_reset_shape();
734
	return "";
734
	return "";
735
}
735
}
736
 
736
 
737
 
737
 
738
char* console_close_holes(std::vector<std::string> &args)
738
char* console_close_holes(std::vector<std::string> &args)
739
{
739
{
740
	if(wantshelp(args)) 
740
	if(wantshelp(args)) 
741
	{
741
	{
742
		theConsole.Printf("usage: cleanup.close_holes");
742
		theConsole.Printf("usage: cleanup.close_holes");
743
		theConsole.Printf("This function closes holes. It simply follows the loop of halfvectors which");
743
		theConsole.Printf("This function closes holes. It simply follows the loop of halfvectors which");
744
		theConsole.Printf("enclose the hole and add a face to which they all point.");
744
		theConsole.Printf("enclose the hole and add a face to which they all point.");
745
		return "";
745
		return "";
746
	}
746
	}
747
	close_holes(active_mesh());
747
	close_holes(active_mesh());
748
	return "";
748
	return "";
749
}
749
}
750
 
750
 
751
char* console_reload(std::vector<std::string> &args)
751
char* console_reload(std::vector<std::string> &args)
752
{
752
{
753
	if(wantshelp(args)) 
753
	if(wantshelp(args)) 
754
	{
754
	{
755
		theConsole.Printf("usage:  load <file>");
755
		theConsole.Printf("usage:  load <file>");
756
		theConsole.Printf("(Re)loads the current file if no argument is given, but");
756
		theConsole.Printf("(Re)loads the current file if no argument is given, but");
757
		theConsole.Printf("if an argument is given, then that becomes the current file");
757
		theConsole.Printf("if an argument is given, then that becomes the current file");
758
		return "";
758
		return "";
759
	}
759
	}
760
	if(!avo().reload(args.size()>0 ? args[0]:""))
760
	if(!avo().reload(args.size()>0 ? args[0]:""))
761
		return "failed to load";
761
		return "failed to load";
762
	return "";
762
	return "";
763
}
763
}
764
 
764
 
765
 
765
 
766
char* console_simplify(std::vector<std::string> &args)
766
char* console_simplify(std::vector<std::string> &args)
767
{
767
{
768
	if(wantshelp(args)) 
768
	if(wantshelp(args)) 
769
	{
769
	{
770
		theConsole.Printf("usage: simplify <fraction> ");
770
		theConsole.Printf("usage: simplify <fraction> ");
771
		theConsole.Printf("Performs Garland Heckbert (quadric based) mesh simplification.");
771
		theConsole.Printf("Performs Garland Heckbert (quadric based) mesh simplification.");
772
		theConsole.Printf("The only argument is the fraction of vertices to keep.");
772
		theConsole.Printf("The only argument is the fraction of vertices to keep.");
773
		return "";
773
		return "";
774
	}
774
	}
775
	float keep_fraction;
775
	float keep_fraction;
776
	if(args.size()==0) return "you must specify fraction of vertices to keep";
776
	if(args.size()==0) return "you must specify fraction of vertices to keep";
777
	istringstream a0(args[0]);
777
	istringstream a0(args[0]);
778
	a0 >> keep_fraction;
778
	a0 >> keep_fraction;
779
	
779
	
780
	Vec3f p0, p7;
780
	Vec3f p0, p7;
781
	active_mesh().get_bbox(p0, p7);
781
	active_mesh().get_bbox(p0, p7);
782
	Vec3f d = p7-p0;
782
	Vec3f d = p7-p0;
783
	float s = 1.0/d.max_coord();
783
	float s = 1.0/d.max_coord();
784
	Vec3f pcentre = (p7+p0)/2.0;
784
	Vec3f pcentre = (p7+p0)/2.0;
785
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
785
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
786
		vi->pos = (vi->pos - pcentre) * s;
786
		vi->pos = (vi->pos - pcentre) * s;
787
	quadric_simplify(active_mesh(),keep_fraction,0.0001f,true);
787
	quadric_simplify(active_mesh(),keep_fraction,0.0001f,true);
788
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
788
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
789
		vi->pos = vi->pos*d.max_coord() + pcentre;
789
		vi->pos = vi->pos*d.max_coord() + pcentre;
790
	return "";
790
	return "";
791
}
791
}
792
 
792
 
793
char* console_vertex_noise(std::vector<std::string> &args)
793
char* console_vertex_noise(std::vector<std::string> &args)
794
{
794
{
795
	if(wantshelp(args)) 
795
	if(wantshelp(args)) 
796
	{
796
	{
797
		theConsole.Printf("usage: noise.perturb_vertices <amplitude>");
797
		theConsole.Printf("usage: noise.perturb_vertices <amplitude>");
798
		theConsole.Printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
798
		theConsole.Printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
799
		theConsole.Printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
799
		theConsole.Printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
800
		theConsole.Printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
800
		theConsole.Printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
801
		theConsole.Printf("If no amplitude is specified, the default (0.5) is used.");
801
		theConsole.Printf("If no amplitude is specified, the default (0.5) is used.");
802
		return "";
802
		return "";
803
	}
803
	}
804
	float avg_length = average_edge_length(active_mesh());
804
	float avg_length = average_edge_length(active_mesh());
805
	
805
	
806
	float noise_amplitude = 0.5;
806
	float noise_amplitude = 0.5;
807
	if(args.size()>0) 
807
	if(args.size()>0) 
808
	{
808
	{
809
		istringstream a0(args[0]);
809
		istringstream a0(args[0]);
810
		a0 >> noise_amplitude;
810
		a0 >> noise_amplitude;
811
	}
811
	}
812
	
812
	
813
	gel_srand(0);
813
	gel_srand(0);
814
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
814
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
815
	{
815
	{
816
		Vec3f v;
816
		Vec3f v;
817
		do {
817
		do {
818
			v = Vec3f(gel_rand(),gel_rand(),gel_rand());
818
			v = Vec3f(gel_rand(),gel_rand(),gel_rand());
819
			v /= GEL_RAND_MAX;
819
			v /= GEL_RAND_MAX;
820
		} while(sqr_length(v) > 1.0);
820
		} while(sqr_length(v) > 1.0);
821
		v -= Vec3f(0.5);
821
		v -= Vec3f(0.5);
822
		v *= 2.0;
822
		v *= 2.0;
823
		v *= noise_amplitude;
823
		v *= noise_amplitude;
824
		v *= avg_length;
824
		v *= avg_length;
825
		vi->pos += v;
825
		vi->pos += v;
826
	}		
826
	}		
827
	return "";
827
	return "";
828
}
828
}
829
 
829
 
830
char* console_perpendicular_vertex_noise(std::vector<std::string> &args)
830
char* console_perpendicular_vertex_noise(std::vector<std::string> &args)
831
{
831
{
832
	if(wantshelp(args)) 
832
	if(wantshelp(args)) 
833
	{
833
	{
834
		theConsole.Printf("usage: noise.perturb_vertices_perpendicular <amplitude>");
834
		theConsole.Printf("usage: noise.perturb_vertices_perpendicular <amplitude>");
835
		theConsole.Printf("adds the normal times a random scalar times amplitude times");
835
		theConsole.Printf("adds the normal times a random scalar times amplitude times");
836
		theConsole.Printf("times average edge length to the vertex. (default amplitude=0.5)");
836
		theConsole.Printf("times average edge length to the vertex. (default amplitude=0.5)");
837
		return "";
837
		return "";
838
	}
838
	}
839
	float avg_length = average_edge_length(active_mesh());
839
	float avg_length = average_edge_length(active_mesh());
840
	
840
	
841
	float noise_amplitude = 0.5;
841
	float noise_amplitude = 0.5;
842
	if(args.size()>0) 
842
	if(args.size()>0) 
843
	{
843
	{
844
		istringstream a0(args[0]);
844
		istringstream a0(args[0]);
845
		a0 >> noise_amplitude;
845
		a0 >> noise_amplitude;
846
	}
846
	}
847
	
847
	
848
	vector<Vec3f> normals(active_mesh().no_vertices());
848
	vector<Vec3f> normals(active_mesh().no_vertices());
849
	int i=0;
849
	int i=0;
850
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
850
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
851
		normals[i] = normal(vi);
851
		normals[i] = normal(vi);
852
	i=0;
852
	i=0;
853
	gel_srand(0);
853
	gel_srand(0);
854
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
854
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
855
	{
855
	{
856
		float rval = 0.5-gel_rand()/float(GEL_RAND_MAX);
856
		float rval = 0.5-gel_rand()/float(GEL_RAND_MAX);
857
		vi->pos += normals[i]*rval*noise_amplitude*avg_length*2.0;
857
		vi->pos += normals[i]*rval*noise_amplitude*avg_length*2.0;
858
	}
858
	}
859
	return "";
859
	return "";
860
}
860
}
861
 
861
 
862
char* console_noisy_flips(std::vector<std::string> &args)
862
char* console_noisy_flips(std::vector<std::string> &args)
863
{
863
{
864
	if(wantshelp(args)) 
864
	if(wantshelp(args)) 
865
	{
865
	{
866
		theConsole.Printf("usage:  noise.perturb_topology <iter>");
866
		theConsole.Printf("usage:  noise.perturb_topology <iter>");
867
		theConsole.Printf("Perform random flips. iter (default=1) is the number of iterations.");
867
		theConsole.Printf("Perform random flips. iter (default=1) is the number of iterations.");
868
		theConsole.Printf("mostly for making nasty synthetic test cases.");
868
		theConsole.Printf("mostly for making nasty synthetic test cases.");
869
		return "";
869
		return "";
870
	}
870
	}
871
	int iter=1;
871
	int iter=1;
872
	if(args.size()>0)
872
	if(args.size()>0)
873
	{
873
	{
874
		istringstream a0(args[0]);
874
		istringstream a0(args[0]);
875
		a0 >> iter;
875
		a0 >> iter;
876
	}
876
	}
877
	
877
	
878
	randomize_mesh(active_mesh(),  iter);
878
	randomize_mesh(active_mesh(),  iter);
879
	return "";
879
	return "";
880
}
880
}
881
 
881
 
-
 
882
 
882
char* console_laplacian_smooth(std::vector<std::string> &args)
883
char* console_laplacian_smooth(std::vector<std::string> &args)
883
{
884
{
884
	if(wantshelp(args)) 
885
	if(wantshelp(args)) 
885
	{
886
	{
886
		theConsole.Printf("usage:  smooth.laplacian <weight> <iter>");
887
		theConsole.Printf("usage:  smooth.laplacian <weight> <iter>");
887
		theConsole.Printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
888
		theConsole.Printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
888
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
889
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
889
		return "";
890
		return "";
890
	}
891
	}
891
	float t=1.0;
892
	float t=1.0;
892
	if(args.size()>0)
893
	if(args.size()>0)
893
	{
894
	{
894
		istringstream a0(args[0]);
895
		istringstream a0(args[0]);
895
		a0 >> t;
896
		a0 >> t;
896
	}
897
	}
897
	int iter=1;
898
	int iter=1;
898
	if(args.size()>1)
899
	if(args.size()>1)
899
	{
900
	{
900
		istringstream a0(args[1]);
901
		istringstream a0(args[1]);
901
		a0 >> iter;
902
		a0 >> iter;
902
	}
903
	}
903
	
904
	
904
	/// Simple laplacian smoothing with an optional weight.
905
	/// Simple laplacian smoothing with an optional weight.
905
	for(int i=0;i<iter;++i) laplacian_smooth(active_mesh(), t);
906
	for(int i=0;i<iter;++i) laplacian_smooth(active_mesh(), t);
906
	return "";
907
	return "";
907
}
908
}
908
 
909
 
909
char* console_mean_curvature_smooth(std::vector<std::string> &args)
910
char* console_mean_curvature_smooth(std::vector<std::string> &args)
910
{
911
{
911
	if(wantshelp(args)) 
912
	if(wantshelp(args)) 
912
	{
913
	{
913
		theConsole.Printf("usage:  smooth.mean_curvature <weight> <iter>");
914
		theConsole.Printf("usage:  smooth.mean_curvature <weight> <iter>");
914
		theConsole.Printf("Perform mean curvature smoothing. weight is the scaling factor for the");
915
		theConsole.Printf("Perform mean curvature smoothing. weight is the scaling factor for the");
915
		theConsole.Printf("mean curvature vector which has been normalized by dividing by edge lengths");
916
		theConsole.Printf("mean curvature vector which has been normalized by dividing by edge lengths");
916
		theConsole.Printf("this allows for larger steps as suggested by Desbrun et al.");
917
		theConsole.Printf("this allows for larger steps as suggested by Desbrun et al.");
917
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
918
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
918
		return "";
919
		return "";
919
	}
920
	}
920
	float t=1.0;
921
	float t=1.0;
921
	if(args.size()>0)
922
	if(args.size()>0)
922
	{
923
	{
923
		istringstream a0(args[0]);
924
		istringstream a0(args[0]);
924
		a0 >> t;
925
		a0 >> t;
925
	}
926
	}
926
	int iter=1;
927
	int iter=1;
927
	if(args.size()>1)
928
	if(args.size()>1)
928
	{
929
	{
929
		istringstream a0(args[1]);
930
		istringstream a0(args[1]);
930
		a0 >> iter;
931
		a0 >> iter;
931
	}	
932
	}	
932
	vector<Vec3d> new_pos(active_mesh().no_vertices());
933
	vector<Vec3d> new_pos(active_mesh().no_vertices());
933
	for(int j=0;j<iter;++j)
934
	for(int j=0;j<iter;++j)
934
	{
935
	{
935
		int i=0;
936
		int i=0;
936
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i) {
937
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i) {
937
			Vec3d m;
938
			Vec3d m;
938
			double w_sum;
939
			double w_sum;
939
			unnormalized_mean_curvature_normal(v, m, w_sum);
940
			unnormalized_mean_curvature_normal(v, m, w_sum);
940
			new_pos[i] = Vec3d(v->pos)  - (t * m/w_sum);
941
			new_pos[i] = Vec3d(v->pos)  - (t * m/w_sum);
941
		}
942
		}
942
		i=0;
943
		i=0;
943
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i)
944
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i)
944
			v->pos = Vec3f(new_pos[i]);
945
			v->pos = Vec3f(new_pos[i]);
945
	}
946
	}
946
	return "";
947
	return "";
947
}
948
}
948
 
949
 
949
const double angle_defect(VertexIter v)
950
const double angle_defect(VertexIter v)
950
{
951
{
951
	if(!is_boundary(v))
952
	if(!is_boundary(v))
952
	{
953
	{
953
		Vec3f vertex(v->pos);
954
		Vec3f vertex(v->pos);
954
		vector<Vec3d> edges;
955
		vector<Vec3d> edges;
955
		for(VertexCirculator vc(v); !vc.end(); ++vc)
956
		for(VertexCirculator vc(v); !vc.end(); ++vc)
956
		{
957
		{
957
			Vec3d e(normalize(vc.get_vertex()->pos-vertex));
958
			Vec3d e(normalize(vc.get_vertex()->pos-vertex));
958
			edges.push_back(e);
959
			edges.push_back(e);
959
		}
960
		}
960
		int N=edges.size();
961
		int N=edges.size();
961
		double angle_sum = 0;
962
		double angle_sum = 0;
962
		for(int i=0;i<N;++i)
963
		for(int i=0;i<N;++i)
963
		{
964
		{
964
			double dot_prod = 
965
			double dot_prod = 
965
			s_max(-1.0, s_min(1.0, dot(edges[i],edges[(i+1)%N])));
966
			s_max(-1.0, s_min(1.0, dot(edges[i],edges[(i+1)%N])));
966
			angle_sum += acos(dot_prod);
967
			angle_sum += acos(dot_prod);
967
		}
968
		}
968
		return fabs(2*M_PI - angle_sum);
969
		return fabs(2*M_PI - angle_sum);
969
	}
970
	}
970
	return 1000;
971
	return 1000;
971
}
972
}
972
 
973
 
973
char* console_experimental_smooth(std::vector<std::string> &args)
974
char* console_experimental_smooth(std::vector<std::string> &args)
974
{
975
{
975
	if(wantshelp(args)) 
976
	if(wantshelp(args)) 
976
	{
977
	{
977
		theConsole.Printf("usage:  smooth.experimental <weight> <iter>");
978
		theConsole.Printf("usage:  smooth.experimental <weight> <iter>");
978
		theConsole.Printf("Perform experimental smoothing. weight is the scaling factor for the");
979
		theConsole.Printf("Perform experimental smoothing. weight is the scaling factor for the");
979
		theConsole.Printf("experimetnal vector which has been normalized by dividing by edge lengths");
980
		theConsole.Printf("experimetnal vector which has been normalized by dividing by edge lengths");
980
		theConsole.Printf("this allows for larger steps as suggested by Desbrun et al.");
981
		theConsole.Printf("this allows for larger steps as suggested by Desbrun et al.");
981
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
982
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
982
		return "";
983
		return "";
983
	}
984
	}
984
	float t=1.0;
985
	float t=1.0;
985
	if(args.size()>0)
986
	if(args.size()>0)
986
	{
987
	{
987
		istringstream a0(args[0]);
988
		istringstream a0(args[0]);
988
		a0 >> t;
989
		a0 >> t;
989
	}
990
	}
990
	int iter=1;
991
	int iter=1;
991
	if(args.size()>1)
992
	if(args.size()>1)
992
	{
993
	{
993
		istringstream a0(args[1]);
994
		istringstream a0(args[1]);
994
		a0 >> iter;
995
		a0 >> iter;
995
	}	
996
	}	
996
	
997
	
997
	Vec3f p0_before, p7_before;
998
	Vec3f p0_before, p7_before;
998
	active_mesh().get_bbox(p0_before, p7_before);
999
	active_mesh().get_bbox(p0_before, p7_before);
999
 
1000
 
1000
	double avg_area=0.0;
1001
	double avg_area=0.0;
1001
	for(FaceIter f=active_mesh().faces_begin(); f != active_mesh().faces_end(); ++f)
1002
	for(FaceIter f=active_mesh().faces_begin(); f != active_mesh().faces_end(); ++f)
1002
		avg_area += area(f);
1003
		avg_area += area(f);
1003
	avg_area /= active_mesh().no_faces();
1004
	avg_area /= active_mesh().no_faces();
1004
		
1005
		
1005
	for(int j=0;j<iter;++j)
1006
	for(int j=0;j<iter;++j)
1006
	{
1007
	{
1007
		
1008
		
1008
		vector<Vec3d> new_pos(active_mesh().no_vertices());
1009
		vector<Vec3d> new_pos(active_mesh().no_vertices());
1009
 
1010
 
1010
		int i=0;
1011
		int i=0;
1011
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i) 
1012
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i) 
1012
			{
1013
			{
1013
				double w_sum=0;
1014
				double w_sum=0;
1014
				Vec3d m(0);
1015
				Vec3d m(0);
1015
				VertexCirculator vc(v);
1016
				VertexCirculator vc(v);
1016
				for(; !vc.end(); ++vc)
1017
				for(; !vc.end(); ++vc)
1017
				{
1018
				{
1018
					HalfEdgeIter h = vc.get_halfedge();
1019
					HalfEdgeIter h = vc.get_halfedge();
1019
					double area_left  = area(h->face);
1020
					double area_left  = area(h->face);
1020
					double area_right = area(h->opp->face);
1021
					double area_right = area(h->opp->face);
1021
					
1022
					
1022
					double w = 0.5 * (area_left + area_right);
1023
					double w = 0.5 * (area_left + area_right);
1023
					m += w * Vec3d(vc.get_vertex()->pos-v->pos);
1024
					m += w * Vec3d(vc.get_vertex()->pos-v->pos);
1024
					w_sum += w;
1025
					w_sum += w;
1025
				}
1026
				}
1026
				double t2 = pow((w_sum/vc.no_steps())/avg_area,.25);
1027
				double t2 = pow((w_sum/vc.no_steps())/avg_area,.25);
1027
				if(t2 > 1e-10)
1028
				if(t2 > 1e-10)
1028
					new_pos[i] = Vec3d(v->pos)  + (t * t2 * m/w_sum);
1029
					new_pos[i] = Vec3d(v->pos)  + (t * t2 * m/w_sum);
1029
			}
1030
			}
1030
		i=0;
1031
		i=0;
1031
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i)
1032
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i)
1032
			v->pos = Vec3f(new_pos[i]);
1033
			v->pos = Vec3f(new_pos[i]);
1033
		
1034
		
1034
		active_mesh().delayed_erase();
1035
		active_mesh().delayed_erase();
1035
		for(HalfEdgeIter h=active_mesh().halfedges_begin(); h!=active_mesh().halfedges_end(); ++h)
1036
		for(HalfEdgeIter h=active_mesh().halfedges_begin(); h!=active_mesh().halfedges_end(); ++h)
1036
			if(active_mesh().is_used(h))
1037
			if(active_mesh().is_used(h))
1037
		{
1038
		{
1038
			Vec3d mcna,mcnb;
1039
			Vec3d mcna,mcnb;
1039
			double ws;
1040
			double ws;
1040
			
1041
			
1041
			unnormalized_mean_curvature_normal(h->vert, mcna, ws);
1042
			unnormalized_mean_curvature_normal(h->vert, mcna, ws);
1042
			unnormalized_mean_curvature_normal(h->opp->vert, mcnb, ws);
1043
			unnormalized_mean_curvature_normal(h->opp->vert, mcnb, ws);
1043
			if(sqr_length(mcna) < 1 && sqr_length(mcnb) < 1)
1044
			if(sqr_length(mcna) < 1 && sqr_length(mcnb) < 1)
1044
				if(active_mesh().collapse_precond(h))
1045
				if(active_mesh().collapse_precond(h))
1045
				{
1046
				{
1046
					active_mesh().collapse_halfedge(h, false);
1047
					active_mesh().collapse_halfedge(h, false);
1047
				}
1048
				}
1048
		}
1049
		}
1049
		active_mesh().immediate_erase();
1050
		active_mesh().immediate_erase();
1050
		maximize_min_angle(active_mesh(), 0.95, false);
1051
		maximize_min_angle(active_mesh(), 0.95, false);
1051
	}
1052
	}
1052
	
1053
	
1053
	Vec3f p0, p7;
1054
	Vec3f p0, p7;
1054
	active_mesh().get_bbox(p0, p7);
1055
	active_mesh().get_bbox(p0, p7);
1055
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
1056
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
1056
		vi->pos = (p7_before-p0_before)*(vi->pos - p0)/(p7-p0)+p0_before;
1057
		vi->pos = (p7_before-p0_before)*(vi->pos - p0)/(p7-p0)+p0_before;
1057
	
1058
	
1058
	return "";
1059
	return "";
1059
}
1060
}
1060
 
1061
 
1061
 
1062
 
1062
char* console_taubin_smooth(std::vector<std::string> &args)
1063
char* console_taubin_smooth(std::vector<std::string> &args)
1063
{
1064
{
1064
	if(wantshelp(args)) 
1065
	if(wantshelp(args)) 
1065
	{
1066
	{
1066
		theConsole.Printf("usage:  smooth.taubin <iter>");
1067
		theConsole.Printf("usage:  smooth.taubin <iter>");
1067
		theConsole.Printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
1068
		theConsole.Printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
1068
		return "";
1069
		return "";
1069
	}
1070
	}
1070
	int iter=1;
1071
	int iter=1;
1071
	if(args.size()>0)
1072
	if(args.size()>0)
1072
	{
1073
	{
1073
		istringstream a0(args[0]);
1074
		istringstream a0(args[0]);
1074
		a0 >> iter;
1075
		a0 >> iter;
1075
	}
1076
	}
1076
	
1077
	
1077
	/// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
1078
	/// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
1078
	taubin_smooth(active_mesh(),  iter);
1079
	taubin_smooth(active_mesh(),  iter);
1079
	return "";
1080
	return "";
1080
}
1081
}
1081
 
1082
 
1082
char* console_fvm_smooth(std::vector<std::string> &args)
1083
char* console_fvm_smooth(std::vector<std::string> &args)
1083
{	
1084
{	
1084
	if(wantshelp(args)) 
1085
	if(wantshelp(args)) 
1085
	{
1086
	{
1086
		theConsole.Printf("usage: smooth.fuzzy_vector_median <iter>");
1087
		theConsole.Printf("usage: smooth.fuzzy_vector_median <iter>");
1087
		theConsole.Printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
1088
		theConsole.Printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
1088
		theConsole.Printf("This function does a very good job of preserving sharp edges.");
1089
		theConsole.Printf("This function does a very good job of preserving sharp edges.");
1089
		return "";
1090
		return "";
1090
	}
1091
	}
1091
	int iter=1;
1092
	int iter=1;
1092
	if(args.size()>0)
1093
	if(args.size()>0)
1093
	{
1094
	{
1094
		istringstream a0(args[0]);
1095
		istringstream a0(args[0]);
1095
		a0 >> iter;
1096
		a0 >> iter;
1096
	}
1097
	}
1097
	/** Fuzzy vector median smoothing is effective when it comes to
1098
	/** Fuzzy vector median smoothing is effective when it comes to
1098
	 preserving sharp edges. */
1099
	 preserving sharp edges. */
1099
	fvm_smooth(active_mesh(),  iter);
1100
	fvm_smooth(active_mesh(),  iter);
1100
	return "";
1101
	return "";
1101
	
1102
	
1102
}
1103
}
1103
 
1104
 
1104
char* console_triangulate(std::vector<std::string> &args)
1105
char* console_triangulate(std::vector<std::string> &args)
1105
{	
1106
{	
1106
	if(wantshelp(args)) 
1107
	if(wantshelp(args)) 
1107
	{
1108
	{
1108
		theConsole.Printf("usage:  triangulate");
1109
		theConsole.Printf("usage:  triangulate");
1109
		theConsole.Printf("This function triangulates all non triangular faces of the mesh.");
1110
		theConsole.Printf("This function triangulates all non triangular faces of the mesh.");
1110
		theConsole.Printf("you may want to call it after hole closing. For a polygon it simply connects");
1111
		theConsole.Printf("you may want to call it after hole closing. For a polygon it simply connects");
1111
		theConsole.Printf("the two closest vertices in a recursive manner until only triangles remain");
1112
		theConsole.Printf("the two closest vertices in a recursive manner until only triangles remain");
1112
		return "";
1113
		return "";
1113
	}
1114
	}
1114
	shortest_edge_triangulate(active_mesh());
1115
	shortest_edge_triangulate(active_mesh());
1115
	return "";
1116
	return "";
1116
}
1117
}
1117
 
1118
 
1118
 
1119
 
1119
char* console_remove_caps(std::vector<std::string> &args)
1120
char* console_remove_caps(std::vector<std::string> &args)
1120
{	
1121
{	
1121
	if(wantshelp(args)) 
1122
	if(wantshelp(args)) 
1122
	{
1123
	{
1123
		theConsole.Printf("usage:  cleanup.remove_caps thresh");
1124
		theConsole.Printf("usage:  cleanup.remove_caps thresh");
1124
		theConsole.Printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
1125
		theConsole.Printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
1125
		theConsole.Printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
1126
		theConsole.Printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
1126
		return "";
1127
		return "";
1127
	}
1128
	}
1128
	float t=0.85;
1129
	float t=0.85;
1129
	if(args.size()>0)
1130
	if(args.size()>0)
1130
	{
1131
	{
1131
		istringstream a0(args[0]);
1132
		istringstream a0(args[0]);
1132
		a0 >> t;
1133
		a0 >> t;
1133
	}
1134
	}
1134
	
1135
	
1135
	remove_caps_from_trimesh(active_mesh(), static_cast<float>(M_PI) *t);
1136
	remove_caps_from_trimesh(active_mesh(), static_cast<float>(M_PI) *t);
1136
	return "";
1137
	return "";
1137
}
1138
}
1138
 
1139
 
1139
char* console_remove_needles(std::vector<std::string> &args)
1140
char* console_remove_needles(std::vector<std::string> &args)
1140
{	
1141
{	
1141
	if(wantshelp(args)) 
1142
	if(wantshelp(args)) 
1142
	{
1143
	{
1143
		theConsole.Printf("usage: cleanup.remove_needles <thresh>");
1144
		theConsole.Printf("usage: cleanup.remove_needles <thresh>");
1144
		theConsole.Printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
1145
		theConsole.Printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
1145
		theConsole.Printf("to get the length shorter than which we collapse. Default = 0.1");
1146
		theConsole.Printf("to get the length shorter than which we collapse. Default = 0.1");
1146
		return "";
1147
		return "";
1147
	}
1148
	}
1148
	float thresh = 0.1;
1149
	float thresh = 0.1;
1149
	if(args.size()>0)
1150
	if(args.size()>0)
1150
	{
1151
	{
1151
		istringstream a0(args[0]);
1152
		istringstream a0(args[0]);
1152
		a0 >> thresh;
1153
		a0 >> thresh;
1153
	}
1154
	}
1154
	float avg_length = average_edge_length(active_mesh());
1155
	float avg_length = average_edge_length(active_mesh());
1155
	remove_needles_from_trimesh(active_mesh(), thresh * avg_length);
1156
	remove_needles_from_trimesh(active_mesh(), thresh * avg_length);
1156
	return "";
1157
	return "";
1157
}
1158
}
1158
 
1159
 
1159
void reshape(int W, int H)
1160
void reshape(int W, int H)
1160
{
1161
{
1161
	active_view_control().reshape(W,H);
1162
	active_view_control().reshape(W,H);
1162
}
1163
}
1163
 
1164
 
1164
void display() 
1165
void display() 
1165
{
1166
{
1166
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1167
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1167
	
1168
	
1168
	static string& display_render_mode = CreateCVar<string>("display.render_mode","");
1169
	static string& display_render_mode = CreateCVar<string>("display.render_mode","");
1169
	static int& display_smooth= CreateCVar<int>("display.smooth_shading",1);
1170
	static int& display_smooth= CreateCVar<int>("display.smooth_shading",1);
1170
	
1171
	
1171
	glPushMatrix();
1172
	glPushMatrix();
1172
	
1173
	
1173
	avo().display(display_render_mode, display_smooth);
1174
	avo().display(display_render_mode, display_smooth);
1174
	
1175
	
1175
	glPopMatrix();
1176
	glPopMatrix();
1176
	
1177
	
1177
	glUseProgram(0);
1178
	glUseProgram(0);
1178
	theConsole.RenderConsole();
1179
	theConsole.RenderConsole();
1179
	
1180
	
1180
	glutSwapBuffers();
1181
	glutSwapBuffers();
1181
}
1182
}
1182
 
1183
 
1183
void animate() 
1184
void animate() 
1184
{	
1185
{	
1185
	//usleep( (int)1e4 );
1186
	//usleep( (int)1e4 );
1186
	active_view_control().try_spin();
1187
	active_view_control().try_spin();
1187
	glutPostRedisplay();
1188
	glutPostRedisplay();
1188
}
1189
}
1189
 
1190
 
1190
 
1191
 
1191
void mouse(int button, int state, int x, int y) 
1192
void mouse(int button, int state, int x, int y) 
1192
{
1193
{
1193
	Vec2i pos(x,y);
1194
	Vec2i pos(x,y);
1194
	if (state==GLUT_DOWN) 
1195
	if (state==GLUT_DOWN) 
1195
	{
1196
	{
1196
		if (button==GLUT_LEFT_BUTTON) 
1197
		if (button==GLUT_LEFT_BUTTON) 
1197
			active_view_control().grab_ball(ROTATE_ACTION,pos);
1198
			active_view_control().grab_ball(ROTATE_ACTION,pos);
1198
		else if (button==GLUT_MIDDLE_BUTTON) 
1199
		else if (button==GLUT_MIDDLE_BUTTON) 
1199
			active_view_control().grab_ball(ZOOM_ACTION,pos);
1200
			active_view_control().grab_ball(ZOOM_ACTION,pos);
1200
		else if (button==GLUT_RIGHT_BUTTON) 
1201
		else if (button==GLUT_RIGHT_BUTTON) 
1201
			active_view_control().grab_ball(PAN_ACTION,pos);
1202
			active_view_control().grab_ball(PAN_ACTION,pos);
1202
	}
1203
	}
1203
	else if (state==GLUT_UP)
1204
	else if (state==GLUT_UP)
1204
		active_view_control().release_ball();
1205
		active_view_control().release_ball();
1205
}
1206
}
1206
 
1207
 
1207
void motion(int x, int y) {
1208
void motion(int x, int y) {
1208
	Vec2i pos(x,y);
1209
	Vec2i pos(x,y);
1209
	active_view_control().roll_ball(Vec2i(x,y));
1210
	active_view_control().roll_ball(Vec2i(x,y));
1210
}
1211
}
1211
 
1212
 
1212
void keyboard_spec(int key, int x, int y)
1213
void keyboard_spec(int key, int x, int y)
1213
{
1214
{
1214
	int mod = glutGetModifiers();
1215
	int mod = glutGetModifiers();
1215
	if( theConsole.IsOpen() ) {
1216
	if( theConsole.IsOpen() ) {
1216
		// If shift held, scroll the console
1217
		// If shift held, scroll the console
1217
		if( mod == GLUT_ACTIVE_SHIFT ) {
1218
		if( mod == GLUT_ACTIVE_SHIFT ) {
1218
			switch (key){
1219
			switch (key){
1219
				case GLUT_KEY_UP:
1220
				case GLUT_KEY_UP:
1220
					theConsole.ScrollDownLine();
1221
					theConsole.ScrollDownLine();
1221
					break;
1222
					break;
1222
				case GLUT_KEY_DOWN: 
1223
				case GLUT_KEY_DOWN: 
1223
					theConsole.ScrollUpLine();
1224
					theConsole.ScrollUpLine();
1224
					break;
1225
					break;
1225
			}
1226
			}
1226
		} else {
1227
		} else {
1227
			theConsole.StandardKeyBindings( key );
1228
			theConsole.StandardKeyBindings( key );
1228
		}
1229
		}
1229
	}
1230
	}
1230
}
1231
}
1231
 
1232
 
1232
 
1233
 
1233
void keyboard(unsigned char key, int x, int y) 
1234
void keyboard(unsigned char key, int x, int y) 
1234
{	
1235
{	
1235
	if(theConsole.IsOpen())
1236
	if(theConsole.IsOpen())
1236
	{
1237
	{
1237
		switch(key) {
1238
		switch(key) {
1238
			case '\033': 
1239
			case '\033': 
1239
				theConsole.ToggleConsole();
1240
				theConsole.ToggleConsole();
1240
			default:
1241
			default:
1241
				theConsole.EnterCommandCharacter(key);
1242
				theConsole.EnterCommandCharacter(key);
1242
				break;
1243
				break;
1243
		}
1244
		}
1244
		if(key == 13)	avo().post_create_display_list();
1245
		if(key == 13)	avo().post_create_display_list();
1245
		
1246
		
1246
	}	
1247
	}	
1247
	else {
1248
	else {
1248
		string& display_render_mode = GetCVarRef<string>("display.render_mode");
1249
		string& display_render_mode = GetCVarRef<string>("display.render_mode");
1249
		int& display_smooth = GetCVarRef<int>("display.smooth_shading");
1250
		int& display_smooth = GetCVarRef<int>("display.smooth_shading");
1250
		int& active  = GetCVarRef<int>("active_mesh");
1251
		int& active  = GetCVarRef<int>("active_mesh");
1251
		
1252
		
1252
		
1253
		
1253
		switch(key) {
1254
		switch(key) {
1254
			case 'q': exit(0);
1255
			case 'q': exit(0);
1255
			case '\033':
1256
			case '\033':
1256
				theConsole.ToggleConsole();
1257
				theConsole.ToggleConsole();
1257
				break;
1258
				break;
1258
			case '1':
1259
			case '1':
1259
			case '2':
1260
			case '2':
1260
			case '3':
1261
			case '3':
1261
			case '4':
1262
			case '4':
1262
			case '5':
1263
			case '5':
1263
			case '6':
1264
			case '6':
1264
			case '7':
1265
			case '7':
1265
			case '8':
1266
			case '8':
1266
			case '9':
1267
			case '9':
1267
				active = key - '1'; break;
1268
				active = key - '1'; break;
1268
			case 'f': display_smooth = !display_smooth; break;
1269
			case 'f': display_smooth = !display_smooth; break;
1269
			case 'w':
1270
			case 'w':
1270
				display_render_mode = "wire"; break;
1271
				display_render_mode = "wire"; break;
1271
			case 'n':
1272
			case 'n':
1272
				display_render_mode = "normal"; break;
1273
				display_render_mode = "normal"; break;
1273
			case 'i':
1274
			case 'i':
1274
				display_render_mode = "isophotes"; break;
1275
				display_render_mode = "isophotes"; break;
1275
			case 'r':
1276
			case 'r':
1276
				display_render_mode = "reflection"; break;
1277
				display_render_mode = "reflection"; break;
1277
			case 'h':
1278
			case 'h':
1278
				display_render_mode = "harmonics"; break;
1279
				display_render_mode = "harmonics"; break;
1279
			case 't':
1280
			case 't':
1280
				display_render_mode = "toon"; break;
1281
				display_render_mode = "toon"; break;
1281
			case 'g':
1282
			case 'g':
1282
				display_render_mode = "glazed"; break;
1283
				display_render_mode = "glazed"; break;
1283
			case 'a':
1284
			case 'a':
1284
				display_render_mode = "ambient_occlusion"; break;
1285
				display_render_mode = "ambient_occlusion"; break;
1285
			case 'c':
1286
			case 'c':
1286
				display_render_mode = "copper"; break;
1287
				display_render_mode = "copper"; break;
1287
			case 'C':
1288
			case 'C':
1288
				display_render_mode = "curvature_lines"; break;
1289
				display_render_mode = "curvature_lines"; break;
1289
			case 'M':
1290
			case 'M':
1290
				display_render_mode = "mean_curvature"; break;
1291
				display_render_mode = "mean_curvature"; break;
1291
			case 'G':
1292
			case 'G':
1292
				display_render_mode = "gaussian_curvature"; break;
1293
				display_render_mode = "gaussian_curvature"; break;
1293
		}
1294
		}
1294
		
1295
		
1295
		if(display_render_mode.substr(0,4) == "harm")
1296
		if(display_render_mode.substr(0,3) == "har")
1296
			avo().harmonics_parse_key(key);
1297
			avo().harmonics_parse_key(key);
1297
		
1298
		
1298
		if(key != '\033') avo().post_create_display_list();		
1299
		if(key != '\033') avo().post_create_display_list();		
1299
	}
1300
	}
1300
}
1301
}
1301
 
1302
 
1302
void init_glut(int argc, char** argv)
1303
void init_glut(int argc, char** argv)
1303
{
1304
{
1304
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
1305
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
1305
	glutInitWindowSize(WINX, WINY);
1306
	glutInitWindowSize(WINX, WINY);
1306
	glutInit(&argc, argv);
1307
	glutInit(&argc, argv);
1307
	glutCreateWindow("Shape Harmonics");
1308
	glutCreateWindow("Shape Harmonics");
1308
	glutDisplayFunc(display);
1309
	glutDisplayFunc(display);
1309
	glutKeyboardFunc(keyboard);
1310
	glutKeyboardFunc(keyboard);
1310
	glutSpecialFunc(keyboard_spec);
1311
	glutSpecialFunc(keyboard_spec);
1311
	glutReshapeFunc(reshape);
1312
	glutReshapeFunc(reshape);
1312
	glutMouseFunc(mouse);
1313
	glutMouseFunc(mouse);
1313
	glutMotionFunc(motion);
1314
	glutMotionFunc(motion);
1314
	glutIdleFunc(animate);
1315
	glutIdleFunc(animate);
1315
}
1316
}
1316
 
1317
 
1317
void init_gl()
1318
void init_gl()
1318
{
1319
{
1319
	glewInit();
1320
	glewInit();
1320
	glEnable(GL_LIGHTING);
1321
	glEnable(GL_LIGHTING);
1321
	glEnable(GL_LIGHT0);
1322
	glEnable(GL_LIGHT0);
1322
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
1323
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
1323
	
1324
	
1324
	// Set the value of a uniform
1325
	// Set the value of a uniform
1325
	//glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
1326
	//glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
1326
	
1327
	
1327
	glMatrixMode(GL_MODELVIEW);
1328
	glMatrixMode(GL_MODELVIEW);
1328
	glLoadIdentity();
1329
	glLoadIdentity();
1329
	glClearColor(0.50f, 0.50f, 0.50f, 0.f);
1330
	glClearColor(0.50f, 0.50f, 0.50f, 0.f);
1330
	glColor4f(1.0f, 1.0f, 1.0f, 0.f);
1331
	glColor4f(1.0f, 1.0f, 1.0f, 0.f);
1331
	float material[4] = {1,1,1,1};
1332
	float material[4] = {1,1,1,1};
1332
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
1333
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
1333
	glEnable(GL_DEPTH_TEST);
1334
	glEnable(GL_DEPTH_TEST);
1334
	
1335
	
1335
	CreateCVar( "help", ConsoleHelp );
1336
	CreateCVar( "help", ConsoleHelp );
1336
	CreateCVar("harmonics.reset_shape", console_reset_shape);
1337
	CreateCVar("harmonics.reset_shape", console_reset_shape);
1337
	CreateCVar("harmonics.analyze", console_analyze);
1338
	CreateCVar("harmonics.analyze", console_analyze);
1338
	CreateCVar("harmonics.partial_reconstruct", console_partial_reconstruct);
1339
	CreateCVar("harmonics.partial_reconstruct", console_partial_reconstruct);
1339
	CreateCVar("simplify", console_simplify);
1340
	CreateCVar("simplify", console_simplify);
1340
	CreateCVar("smooth.mean_curvature", console_mean_curvature_smooth);
1341
	CreateCVar("smooth.mean_curvature", console_mean_curvature_smooth);
1341
	CreateCVar("smooth.experimental", console_experimental_smooth);
1342
	CreateCVar("smooth.experimental", console_experimental_smooth);
1342
	CreateCVar("smooth.laplacian", console_laplacian_smooth);
1343
	CreateCVar("smooth.laplacian", console_laplacian_smooth);
1343
	CreateCVar("smooth.taubin", console_taubin_smooth);
1344
	CreateCVar("smooth.taubin", console_taubin_smooth);
1344
	CreateCVar("smooth.fuzzy_vector_median", console_fvm_smooth);
1345
	CreateCVar("smooth.fuzzy_vector_median", console_fvm_smooth);
1345
	
1346
	
1346
	CreateCVar("optimize.valency", console_optimize_valency);
1347
	CreateCVar("optimize.valency", console_optimize_valency);
1347
	CreateCVar("optimize.minimize_dihedral_angles", console_minimize_dihedral);
1348
	CreateCVar("optimize.minimize_dihedral_angles", console_minimize_dihedral);
1348
	CreateCVar("optimize.minimize_curvature", console_minimize_curvature);
1349
	CreateCVar("optimize.minimize_curvature", console_minimize_curvature);
1349
	CreateCVar("optimize.maximize_min_angle", console_maximize_min_angle);
1350
	CreateCVar("optimize.maximize_min_angle", console_maximize_min_angle);
1350
	CreateCVar("cleanup.close_holes", console_close_holes);
1351
	CreateCVar("cleanup.close_holes", console_close_holes);
1351
	CreateCVar("load", console_reload);
1352
	CreateCVar("load", console_reload);
1352
	
1353
	
1353
	CreateCVar("cleanup.remove_caps", console_remove_caps);
1354
	CreateCVar("cleanup.remove_caps", console_remove_caps);
1354
	CreateCVar("cleanup.remove_needles", console_remove_needles);
1355
	CreateCVar("cleanup.remove_needles", console_remove_needles);
1355
	CreateCVar("triangulate", console_triangulate);
1356
	CreateCVar("triangulate", console_triangulate);
1356
	CreateCVar("refine.split_edges", console_refine_edges);
1357
	CreateCVar("refine.split_edges", console_refine_edges);
1357
	CreateCVar("refine.split_faces", console_refine_faces);
1358
	CreateCVar("refine.split_faces", console_refine_faces);
1358
	CreateCVar("refine.catmull_clark", console_cc_subdivide);
1359
	CreateCVar("refine.catmull_clark", console_cc_subdivide);
1359
	CreateCVar("save", console_save);
1360
	CreateCVar("save", console_save);
1360
	CreateCVar("noise.perturb_vertices", console_vertex_noise);
1361
	CreateCVar("noise.perturb_vertices", console_vertex_noise);
1361
	CreateCVar("noise.perturb_vertices_perpendicular", console_perpendicular_vertex_noise);
1362
	CreateCVar("noise.perturb_vertices_perpendicular", console_perpendicular_vertex_noise);
1362
	CreateCVar("noise.perturb_topology", console_noisy_flips);
1363
	CreateCVar("noise.perturb_topology", console_noisy_flips);
1363
	
1364
	
1364
	CreateCVar("dual", console_dual);
1365
	CreateCVar("dual", console_dual);
1365
	CreateCVar("flatten", console_flatten);
1366
	CreateCVar("flatten", console_flatten);
1366
	
1367
	
1367
	CreateCVar("align", console_align);
1368
	CreateCVar("align", console_align);
1368
	
1369
	
1369
	CVarUtils::CreateCVar( "history.load", ConsoleLoadHistory );
1370
	CVarUtils::CreateCVar( "history.load", ConsoleLoadHistory );
1370
    CVarUtils::CreateCVar( "history.save", ConsoleSaveHistory );
1371
    CVarUtils::CreateCVar( "history.save", ConsoleSaveHistory );
1371
    CVarUtils::CreateCVar( "history.clear", ConsoleClearHistory );
1372
    CVarUtils::CreateCVar( "history.clear", ConsoleClearHistory );
1372
	
1373
	
1373
    CVarUtils::CreateCVar( "script.start", ConsoleStartScript );
1374
    CVarUtils::CreateCVar( "script.start", ConsoleStartScript );
1374
    CVarUtils::CreateCVar(	"script.stop", ConsoleStopScript );
1375
    CVarUtils::CreateCVar(	"script.stop", ConsoleStopScript );
1375
    CVarUtils::CreateCVar( "script.show", ConsoleShowScript );
1376
    CVarUtils::CreateCVar( "script.show", ConsoleShowScript );
1376
    CVarUtils::CreateCVar( "script.run", ConsoleRunScript );
1377
    CVarUtils::CreateCVar( "script.run", ConsoleRunScript );
1377
    CVarUtils::CreateCVar( "script.save", ConsoleSaveScript );
1378
    CVarUtils::CreateCVar( "script.save", ConsoleSaveScript );
1378
    CVarUtils::CreateCVar( "script.launch", ConsoleLaunchScript );
1379
    CVarUtils::CreateCVar( "script.launch", ConsoleLaunchScript );
1379
	
1380
	
1380
	
1381
	
1381
}
1382
}
1382
 
1383
 
1383
int main(int argc, char** argv)
1384
int main(int argc, char** argv)
1384
{
1385
{
1385
	ArgExtracter ae(argc, argv);
1386
	ArgExtracter ae(argc, argv);
1386
	
1387
	
1387
	init_glut(argc,argv);
1388
	init_glut(argc,argv);
1388
	init_gl();
1389
	init_gl();
1389
	
1390
	
1390
	Harmonics::init();
1391
	Harmonics::init();
1391
	
1392
	
1392
	if(argc>1)
1393
	if(argc>1)
1393
	{		
1394
	{		
1394
		string file = ae.get_last_arg();
1395
		string file = ae.get_last_arg();
1395
		avo().reload(file);
1396
		avo().reload(file);
1396
	}
1397
	}
1397
	
1398
	
1398
	
1399
	
1399
	glutMainLoop();
1400
	glutMainLoop();
1400
}
1401
}
1401
 
1402
 
1402
 
1403
 
1403
 
1404