Subversion Repositories gelsvn

Rev

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

Rev 406 Rev 411
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/mesh_optimization.h>
42
#include <HMesh/mesh_optimization.h>
43
#include <HMesh/triangulate.h>
43
#include <HMesh/triangulate.h>
44
#include <HMesh/close_holes.h>
44
#include <HMesh/close_holes.h>
45
#include <HMesh/caps_and_needles.h>
45
#include <HMesh/caps_and_needles.h>
46
#include <HMesh/refine_edges.h>
46
#include <HMesh/refine_edges.h>
47
#include <HMesh/subdivision.h>
47
#include <HMesh/subdivision.h>
48
 
48
 
49
#include <GLConsole/GLConsole.h>
49
#include <GLConsole/GLConsole.h>
50
#include <Util/Timer.h>
50
#include <Util/Timer.h>
51
#include "harmonics.h"
51
#include "harmonics.h"
52
#include "Renderer.h"
52
#include "Renderer.h"
53
#include "VisObj.h"
53
#include "VisObj.h"
54
 
54
 
55
using namespace std;
55
using namespace std;
56
using namespace HMesh;
56
using namespace HMesh;
57
using namespace Geometry;
57
using namespace Geometry;
58
using namespace GLGraphics;
58
using namespace GLGraphics;
59
using namespace CGLA;
59
using namespace CGLA;
60
using namespace Util;
60
using namespace Util;
61
using namespace LinAlg;
61
using namespace LinAlg;
62
 
62
 
63
template<typename T>
63
template<typename T>
64
T& get_CVar_ref(const std::string& s)
64
T& get_CVar_ref(const std::string& s)
65
{
65
{
66
	return *reinterpret_cast<T*> (GetCVarData(s));
66
	return *reinterpret_cast<T*> (GetCVarData(s));
67
}
67
}
68
 
68
 
69
inline VisObj& get_vis_obj(int i)
69
inline VisObj& get_vis_obj(int i)
70
{
70
{
71
	static VisObj vo[9];
71
	static VisObj vo[9];
72
	return vo[i];
72
	return vo[i];
73
}
73
}
74
 
74
 
75
inline VisObj& avo()
75
inline VisObj& avo()
76
{
76
{
77
	static CVar<int> active("active_mesh",0);
77
	static CVar<int> active("active_mesh",0);
78
	return get_vis_obj(active);
78
	return get_vis_obj(active);
79
}
79
}
80
 
80
 
81
inline Manifold& active_mesh()
81
inline Manifold& active_mesh()
82
{
82
{
83
	return avo().mesh();
83
	return avo().mesh();
84
}
84
}
85
 
85
 
86
inline GLViewController& active_view_control()
86
inline GLViewController& active_view_control()
87
{
87
{
88
	return avo().view_control();
88
	return avo().view_control();
89
}
89
}
90
 
90
 
91
// Single global instance so glut can get access
91
// Single global instance so glut can get access
92
GLConsole theConsole;
92
GLConsole theConsole;
93
 
93
 
94
////////////////////////////////////////////////////////////////////////////////
94
////////////////////////////////////////////////////////////////////////////////
95
char* ConsoleHelp(std::vector<std::string> &args)
95
char* ConsoleHelp(std::vector<std::string> &args)
96
{
96
{
97
    theConsole.Printf("");
97
    theConsole.Printf("");
98
    theConsole.Printf("----------------- HELP -----------------");
98
    theConsole.Printf("----------------- HELP -----------------");
99
    theConsole.Printf("Press ESC key to open and close console");
99
    theConsole.Printf("Press ESC key to open and close console");
100
    theConsole.Printf("Press TAB to see the available commands and functions");
100
    theConsole.Printf("Press TAB to see the available commands and functions");
101
    theConsole.Printf("Functions are shown in green and variables in yellow");
101
    theConsole.Printf("Functions are shown in green and variables in yellow");
102
    theConsole.Printf("Setting a value: [command] = value");
102
    theConsole.Printf("Setting a value: [command] = value");
103
    theConsole.Printf("Getting a value: [command]");
103
    theConsole.Printf("Getting a value: [command]");
104
    theConsole.Printf("Functions: [function] [arg1] [arg2] ...");
104
    theConsole.Printf("Functions: [function] [arg1] [arg2] ...");
105
    theConsole.Printf("Entering arg1=? or arg1=help will give a description.");
105
    theConsole.Printf("Entering arg1=? or arg1=help will give a description.");
106
    theConsole.Printf("History: Up and Down arrow keys move through history.");
106
    theConsole.Printf("History: Up and Down arrow keys move through history.");
107
    theConsole.Printf("Tab Completion: TAB does tab completion and makes suggestions.");
107
    theConsole.Printf("Tab Completion: TAB does tab completion and makes suggestions.");
108
    theConsole.Printf("");
108
    theConsole.Printf("");
109
    theConsole.Printf("Keyboard commands (when console is not active):");
109
    theConsole.Printf("Keyboard commands (when console is not active):");
110
    theConsole.Printf("w   : switch to display.render_mode = wireframe");
110
    theConsole.Printf("w   : switch to display.render_mode = wireframe");
111
    theConsole.Printf("i   : switch to display.render_mode = isophotes");
111
    theConsole.Printf("i   : switch to display.render_mode = isophotes");
112
    theConsole.Printf("r   : switch to display.render_mode = reflection");
112
    theConsole.Printf("r   : switch to display.render_mode = reflection");
113
    theConsole.Printf("m   : switch to display.render_mode = metallic");
113
    theConsole.Printf("m   : switch to display.render_mode = metallic");
114
    theConsole.Printf("g   : switch to display.render_mode = glazed");
114
    theConsole.Printf("g   : switch to display.render_mode = glazed");
115
    theConsole.Printf("n   : switch to display.render_mode = normal");
115
    theConsole.Printf("n   : switch to display.render_mode = normal");
116
    theConsole.Printf("h   : switch to display.render_mode = harmonics");
116
    theConsole.Printf("h   : switch to display.render_mode = harmonics");
117
    theConsole.Printf("f   : toggle smooth/flat shading");
117
    theConsole.Printf("f   : toggle smooth/flat shading");
118
    theConsole.Printf("1-9 : switch between active meshes.");
118
    theConsole.Printf("1-9 : switch between active meshes.");
119
    theConsole.Printf("d   : (display.render_mode = harmonics) diffuse light on and off");
119
    theConsole.Printf("d   : (display.render_mode = harmonics) diffuse light on and off");
120
    theConsole.Printf("h   : (display.render_mode = harmonics) highlight on and off ");
120
    theConsole.Printf("h   : (display.render_mode = harmonics) highlight on and off ");
121
    theConsole.Printf("+/- : (display.render_mode = harmonics) which eigenvector to show");
121
    theConsole.Printf("+/- : (display.render_mode = harmonics) which eigenvector to show");
122
    theConsole.Printf("q   : quit program");
122
    theConsole.Printf("q   : quit program");
123
    theConsole.Printf("ESC : open console");
123
    theConsole.Printf("ESC : open console");
124
    theConsole.Printf("");
124
    theConsole.Printf("");
125
    theConsole.Printf("Mouse: Left button rotates, middle zooms, right pans");
125
    theConsole.Printf("Mouse: Left button rotates, middle zooms, right pans");
126
    theConsole.Printf("----------------- HELP -----------------");
126
    theConsole.Printf("----------------- HELP -----------------");
127
    theConsole.Printf("");
127
    theConsole.Printf("");
128
    return "";
128
    return "";
129
}
129
}
130
 
130
 
131
bool wantshelp(std::vector<std::string> &args)
131
bool wantshelp(std::vector<std::string> &args)
132
{
132
{
133
	if(args.size()==0) return false;
133
	if(args.size()==0) return false;
134
	string str = args[0];
134
	string str = args[0];
135
	if(str=="help" || str=="HELP" || str=="Help" || str=="?") return true;
135
	if(str=="help" || str=="HELP" || str=="Help" || str=="?") return true;
136
	return false;
136
	return false;
137
}
137
}
138
 
138
 
139
/// Function that aligns two meshes.
139
/// Function that aligns two meshes.
140
char* console_align(std::vector<std::string> &args)
140
char* console_align(std::vector<std::string> &args)
141
{
141
{
142
	if(wantshelp(args)) 
142
	if(wantshelp(args)) 
143
	{
143
	{
144
		theConsole.Printf("usage: align <dest> <src>");
144
		theConsole.Printf("usage: align <dest> <src>");
145
		theConsole.Printf("This function aligns dest mesh with src");
145
		theConsole.Printf("This function aligns dest mesh with src");
146
		theConsole.Printf("In practice the GLViewController of src is copied to dst.");
146
		theConsole.Printf("In practice the GLViewController of src is copied to dst.");
147
		theConsole.Printf("both arguments are mandatory and must be numbers between 1 and 9.");
147
		theConsole.Printf("both arguments are mandatory and must be numbers between 1 and 9.");
148
		theConsole.Printf("Note that results might be unexpexted if the meshes are not on the same scale");
148
		theConsole.Printf("Note that results might be unexpexted if the meshes are not on the same scale");
149
		return "";
149
		return "";
150
	}
150
	}
151
	
151
	
152
	int dest = 0;
152
	int dest = 0;
153
	if(args.size()>0)
153
	if(args.size()>0)
154
	{
154
	{
155
		istringstream a0(args[0]);
155
		istringstream a0(args[0]);
156
		a0 >> dest;
156
		a0 >> dest;
157
		--dest;
157
		--dest;
158
		if(dest <0 || dest>8) return "dest mesh out of range (1-9)";
158
		if(dest <0 || dest>8) return "dest mesh out of range (1-9)";
159
	}
159
	}
160
	else return "neither source nor destination mesh?!";
160
	else return "neither source nor destination mesh?!";
161
	int src = 0;
161
	int src = 0;
162
	if(args.size()>1)
162
	if(args.size()>1)
163
	{
163
	{
164
		istringstream a1(args[1]);
164
		istringstream a1(args[1]);
165
		a1 >> src;
165
		a1 >> src;
166
		--src;
166
		--src;
167
		if(src <0 || src>8) return "src mesh out of range (1-9)";
167
		if(src <0 || src>8) return "src mesh out of range (1-9)";
168
	}	
168
	}	
169
	else return "no src mesh?";
169
	else return "no src mesh?";
170
	
170
	
171
	get_vis_obj(dest).view_control() = get_vis_obj(src).view_control();
171
	get_vis_obj(dest).view_control() = get_vis_obj(src).view_control();
172
	
172
	
173
	return "";
173
	return "";
174
}
174
}
175
 
175
 
176
 
176
 
177
char* console_save(std::vector<std::string> &args)
177
char* console_save(std::vector<std::string> &args)
178
{
178
{
179
	if(wantshelp(args)) 
179
	if(wantshelp(args)) 
180
	{
180
	{
181
		theConsole.Printf("usage: save <name.x3d|name.obj> ");
181
		theConsole.Printf("usage: save <name.x3d|name.obj> ");
182
		return "";
182
		return "";
183
	}
183
	}
184
	string& file_name = args[0];
184
	string& file_name = args[0];
185
	if(args.size() == 1)
185
	if(args.size() == 1)
186
	{
186
	{
187
		if(file_name.substr(file_name.length()-4,file_name.length())==".obj")
187
		if(file_name.substr(file_name.length()-4,file_name.length())==".obj")
188
		{
188
		{
189
			obj_save(file_name, active_mesh());
189
			obj_save(file_name, active_mesh());
190
			return "";
190
			return "";
191
		}
191
		}
192
		else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d")
192
		else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d")
193
		{
193
		{
194
			x3d_save(file_name, active_mesh());
194
			x3d_save(file_name, active_mesh());
195
			return "";
195
			return "";
196
		}
196
		}
197
		return "unknown format";
197
		return "unknown format";
198
	}
198
	}
199
	return "usage: save <name.x3d|name.obj> ";
199
	return "usage: save <name.x3d|name.obj> ";
200
}
200
}
201
 
201
 
202
char* console_refine_edges(std::vector<std::string> &args)
202
char* console_refine_edges(std::vector<std::string> &args)
203
{
203
{
204
	if(wantshelp(args)) 
204
	if(wantshelp(args)) 
205
	{
205
	{
206
		theConsole.Printf("usage: refine.split_edges <length>");
206
		theConsole.Printf("usage: refine.split_edges <length>");
207
		theConsole.Printf("splits edges longer than <length>; default is 0.5 times average length");
207
		theConsole.Printf("splits edges longer than <length>; default is 0.5 times average length");
208
		return "";
208
		return "";
209
	}
209
	}
210
	
210
	
211
	float thresh = 0.5;
211
	float thresh = 0.5;
212
	if(args.size()>0)
212
	if(args.size()>0)
213
	{
213
	{
214
		istringstream a0(args[0]);
214
		istringstream a0(args[0]);
215
		a0 >> thresh;
215
		a0 >> thresh;
216
	}
216
	}
217
	float avg_length = average_edge_length(active_mesh());
217
	float avg_length = average_edge_length(active_mesh());
218
	refine_edges(active_mesh(), thresh * avg_length);
218
	refine_edges(active_mesh(), thresh * avg_length);
219
	return "";
219
	return "";
220
	
220
	
221
}
221
}
222
 
222
 
223
char* console_refine_faces(std::vector<std::string> &args)
223
char* console_refine_faces(std::vector<std::string> &args)
224
{
224
{
225
	if(wantshelp(args)) 
225
	if(wantshelp(args)) 
226
	{
226
	{
227
		theConsole.Printf("usage: refine.split_faces ");
227
		theConsole.Printf("usage: refine.split_faces ");
228
		theConsole.Printf("usage:  Takes no arguments. Inserts a vertex at the centre of each face.");
228
		theConsole.Printf("usage:  Takes no arguments. Inserts a vertex at the centre of each face.");
229
		return "";
229
		return "";
230
	}
230
	}
231
	
231
	
232
	safe_triangulate(active_mesh());
232
	safe_triangulate(active_mesh());
233
	return "";
233
	return "";
234
	
234
	
235
}
235
}
236
 
236
 
237
char* console_cc_subdivide(std::vector<std::string> &args)
237
char* console_cc_subdivide(std::vector<std::string> &args)
238
{
238
{
239
	if(wantshelp(args)) 
239
	if(wantshelp(args)) 
240
	{
240
	{
241
		theConsole.Printf("usage: refine.catmull_clark ");
241
		theConsole.Printf("usage: refine.catmull_clark ");
242
		theConsole.Printf("Splits each polygon into four (Catmull Clark style)");
242
		theConsole.Printf("Splits each polygon into four (Catmull Clark style)");
243
		return "";
243
		return "";
244
	}
244
	}
245
	cc_split(active_mesh(),active_mesh());
245
	cc_split(active_mesh(),active_mesh());
246
	return "";
246
	return "";
247
}
247
}
248
 
248
 
249
char* console_dual(std::vector<std::string> &args)
249
char* console_dual(std::vector<std::string> &args)
250
{
250
{
251
	if(wantshelp(args)) 
251
	if(wantshelp(args)) 
252
	{
252
	{
253
		theConsole.Printf("usage: dual ");
253
		theConsole.Printf("usage: dual ");
254
		theConsole.Printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
254
		theConsole.Printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
255
		return "";
255
		return "";
256
	}
256
	}
257
	
257
	
258
	Manifold& m = active_mesh();
258
	Manifold& m = active_mesh();
259
	
259
	
260
	// make sure every face knows its number
260
	// make sure every face knows its number
261
	m.enumerate_faces();
261
	m.enumerate_faces();
262
	
262
	
263
	vector<Vec3f> vertices(m.no_faces());
263
	vector<Vec3f> vertices(m.no_faces());
264
	vector<int> faces;
264
	vector<int> faces;
265
	vector<int> indices;
265
	vector<int> indices;
266
	
266
	
267
	// Create new vertices. Each face becomes a vertex whose position
267
	// Create new vertices. Each face becomes a vertex whose position
268
	// is the centre of the face
268
	// is the centre of the face
269
	int i=0;
269
	int i=0;
270
	for(FaceIter f=m.faces_begin(); f!=m.faces_end(); ++f,++i)
270
	for(FaceIter f=m.faces_begin(); f!=m.faces_end(); ++f,++i)
271
		vertices[i] = centre(f);
271
		vertices[i] = centre(f);
272
	
272
	
273
	// Create new faces. Each vertex is a new face with N=valency of vertex
273
	// Create new faces. Each vertex is a new face with N=valency of vertex
274
	// edges.
274
	// edges.
275
	i=0;
275
	i=0;
276
	for(VertexIter v=m.vertices_begin(); v!= m.vertices_end(); ++v,++i)
276
	for(VertexIter v=m.vertices_begin(); v!= m.vertices_end(); ++v,++i)
277
		if(!is_boundary(v))
277
		if(!is_boundary(v))
278
		{
278
		{
279
			VertexCirculator vc(v);
279
			VertexCirculator vc(v);
280
			vector<int> index_tmp;
280
			vector<int> index_tmp;
281
			for(; !vc.end(); ++vc)
281
			for(; !vc.end(); ++vc)
282
				index_tmp.push_back(vc.get_face()->touched);
282
				index_tmp.push_back(vc.get_face()->touched);
283
			
283
			
284
			// Push vertex indices for this face onto indices vector.
284
			// Push vertex indices for this face onto indices vector.
285
			// The circulator moves around the face in a clockwise fashion
285
			// The circulator moves around the face in a clockwise fashion
286
			// so we just reverse the ordering.
286
			// so we just reverse the ordering.
287
			indices.insert(indices.end(), index_tmp.rbegin(), index_tmp.rend());
287
			indices.insert(indices.end(), index_tmp.rbegin(), index_tmp.rend());
288
			
288
			
289
			// Insert face valency in the face vector.
289
			// Insert face valency in the face vector.
290
			faces.push_back(vc.no_steps());
290
			faces.push_back(vc.no_steps());
291
		}
291
		}
292
	
292
	
293
	// Clear the manifold before new geometry is inserted.
293
	// Clear the manifold before new geometry is inserted.
294
	m.clear();
294
	m.clear();
295
	
295
	
296
	// And build
296
	// And build
297
	build_manifold(m, vertices.size(), &vertices[0], faces.size(),
297
	build_manifold(m, vertices.size(), &vertices[0], faces.size(),
298
				   &faces[0],&indices[0]);
298
				   &faces[0],&indices[0]);
299
	
299
	
300
	return "";
300
	return "";
301
}
301
}
302
 
302
 
303
 
303
 
304
char* console_minimize_curvature(std::vector<std::string> &args)
304
char* console_minimize_curvature(std::vector<std::string> &args)
305
{
305
{
306
	if(wantshelp(args)) 
306
	if(wantshelp(args)) 
307
	{
307
	{
308
		theConsole.Printf("usage: optimize.minimize_curvature <anneal>");
308
		theConsole.Printf("usage: optimize.minimize_curvature <anneal>");
309
		theConsole.Printf("Flip edges to minimize mean curvature.");
309
		theConsole.Printf("Flip edges to minimize mean curvature.");
310
		theConsole.Printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
310
		theConsole.Printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
311
		return "";
311
		return "";
312
	}
312
	}
313
	bool anneal=false;
313
	bool anneal=false;
314
	if(args.size()>0)
314
	if(args.size()>0)
315
	{
315
	{
316
		istringstream a0(args[0]);
316
		istringstream a0(args[0]);
317
		a0 >> anneal;
317
		a0 >> anneal;
318
	}
318
	}
319
	
319
	
320
	minimize_curvature(active_mesh(), anneal);
320
	minimize_curvature(active_mesh(), anneal);
321
	avo().post_create_display_list();
321
	avo().post_create_display_list();
322
	return "";
322
	return "";
323
}
323
}
324
 
324
 
325
char* console_minimize_dihedral(std::vector<std::string> &args)
325
char* console_minimize_dihedral(std::vector<std::string> &args)
326
{
326
{
327
	if(wantshelp(args)) 
327
	if(wantshelp(args)) 
328
	{
328
	{
329
		theConsole.Printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
329
		theConsole.Printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
330
		theConsole.Printf("Flip edges to minimize dihedral angles.");
330
		theConsole.Printf("Flip edges to minimize dihedral angles.");
331
		theConsole.Printf("Iter is the max number of iterations. anneal tells us whether to use ");
331
		theConsole.Printf("Iter is the max number of iterations. anneal tells us whether to use ");
332
		theConsole.Printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
332
		theConsole.Printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
333
		theConsole.Printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
333
		theConsole.Printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
334
		theConsole.Printf("to which we raise the dihedral angle");
334
		theConsole.Printf("to which we raise the dihedral angle");
335
		return "";
335
		return "";
336
	}
336
	}
337
	int iter = 1000;
337
	int iter = 1000;
338
	if(args.size()>0)
338
	if(args.size()>0)
339
	{
339
	{
340
		istringstream a0(args[0]);
340
		istringstream a0(args[0]);
341
		a0 >> iter;
341
		a0 >> iter;
342
	}
342
	}
343
	
343
	
344
	bool anneal = false;
344
	bool anneal = false;
345
	if(args.size()>1)
345
	if(args.size()>1)
346
	{
346
	{
347
		istringstream a0(args[0]);
347
		istringstream a0(args[0]);
348
		a0 >> anneal;
348
		a0 >> anneal;
349
	}
349
	}
350
	
350
	
351
	bool use_alpha = true;
351
	bool use_alpha = true;
352
	if(args.size()>2)
352
	if(args.size()>2)
353
	{
353
	{
354
		istringstream a0(args[0]);
354
		istringstream a0(args[0]);
355
		a0 >> use_alpha;
355
		a0 >> use_alpha;
356
	}
356
	}
357
	
357
	
358
	float gamma = 4.0;
358
	float gamma = 4.0;
359
	if(args.size()>3)
359
	if(args.size()>3)
360
	{
360
	{
361
		istringstream a0(args[0]);
361
		istringstream a0(args[0]);
362
		a0 >> gamma;
362
		a0 >> gamma;
363
	}
363
	}
364
	
364
	
365
	
365
	
366
	minimize_dihedral_angle(active_mesh(), iter, anneal, use_alpha, gamma);
366
	minimize_dihedral_angle(active_mesh(), iter, anneal, use_alpha, gamma);
367
	return "";
367
	return "";
368
}
368
}
369
 
369
 
370
char* console_maximize_min_angle(std::vector<std::string> &args)
370
char* console_maximize_min_angle(std::vector<std::string> &args)
371
{
371
{
372
	if(wantshelp(args)) 
372
	if(wantshelp(args)) 
373
	{
373
	{
374
		theConsole.Printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
374
		theConsole.Printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
375
		theConsole.Printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
375
		theConsole.Printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
376
		theConsole.Printf("If the dot product of the normals between adjacent faces < thresh");
376
		theConsole.Printf("If the dot product of the normals between adjacent faces < thresh");
377
		theConsole.Printf("no flip will be made. anneal selects simulated annealing rather ");
377
		theConsole.Printf("no flip will be made. anneal selects simulated annealing rather ");
378
		theConsole.Printf("nthan greedy optimization.");
378
		theConsole.Printf("nthan greedy optimization.");
379
		return "";
379
		return "";
380
	}
380
	}
381
	float thresh=0.0;
381
	float thresh=0.0;
382
	if(args.size()>0)
382
	if(args.size()>0)
383
	{
383
	{
384
		istringstream a0(args[0]);
384
		istringstream a0(args[0]);
385
		a0 >> thresh;
385
		a0 >> thresh;
386
	}
386
	}
387
	bool anneal=false;
387
	bool anneal=false;
388
	if(args.size()>1)
388
	if(args.size()>1)
389
	{
389
	{
390
		istringstream a0(args[0]);
390
		istringstream a0(args[0]);
391
		a0 >> anneal;
391
		a0 >> anneal;
392
	}
392
	}
393
	maximize_min_angle(active_mesh(),thresh,anneal);
393
	maximize_min_angle(active_mesh(),thresh,anneal);
394
	return "";
394
	return "";
395
}
395
}
396
 
396
 
397
 
397
 
398
char* console_optimize_valency(std::vector<std::string> &args)
398
char* console_optimize_valency(std::vector<std::string> &args)
399
{
399
{
400
	if(wantshelp(args)) 
400
	if(wantshelp(args)) 
401
	{
401
	{
402
		theConsole.Printf("usage: optimize.valency <anneal> ");
402
		theConsole.Printf("usage: optimize.valency <anneal> ");
403
		theConsole.Printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
403
		theConsole.Printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
404
		return "";
404
		return "";
405
	}
405
	}
406
	bool anneal=false;
406
	bool anneal=false;
407
	if(args.size()>0)
407
	if(args.size()>0)
408
	{
408
	{
409
		istringstream a0(args[0]);
409
		istringstream a0(args[0]);
410
		a0 >> anneal;
410
		a0 >> anneal;
411
	}
411
	}
412
	optimize_valency(active_mesh(), anneal);
412
	optimize_valency(active_mesh(), anneal);
413
	return "";
413
	return "";
414
}
414
}
415
 
415
 
416
char* console_analyze(std::vector<std::string> &args)
416
char* console_analyze(std::vector<std::string> &args)
417
{
417
{
418
	if(wantshelp(args)) 
418
	if(wantshelp(args)) 
419
	{
419
	{
420
		theConsole.Printf("usage:  harmonics.analyze");
420
		theConsole.Printf("usage:  harmonics.analyze");
421
		theConsole.Printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
421
		theConsole.Printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
422
		theConsole.Printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
422
		theConsole.Printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
423
		theConsole.Printf("to this basis.");
423
		theConsole.Printf("to this basis.");
424
		theConsole.Printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
424
		theConsole.Printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
425
		return "";
425
		return "";
426
	}
426
	}
427
	avo().harmonics_analyze_mesh();
427
	avo().harmonics_analyze_mesh();
428
	return "";
428
	return "";
429
}
429
}
430
 
430
 
431
 
431
 
432
char* console_partial_reconstruct(std::vector<std::string> &args)
432
char* console_partial_reconstruct(std::vector<std::string> &args)
433
{
433
{
434
	if(wantshelp(args)) 
434
  if(args.size() != 3)
435
	{
-
 
436
		theConsole.Printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
435
		theConsole.Printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
-
 
436
 
-
 
437
  if(wantshelp(args)) 
-
 
438
	{
437
		theConsole.Printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
439
		theConsole.Printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
438
		theConsole.Printf("the eigenvector interval that we reconstruct from. The last argument is the ");
440
		theConsole.Printf("the eigenvector interval that we reconstruct from. The last argument is the ");
439
		theConsole.Printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
441
		theConsole.Printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
440
		theConsole.Printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
442
		theConsole.Printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
441
		theConsole.Printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
443
		theConsole.Printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
442
		theConsole.Printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
444
		theConsole.Printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
443
		theConsole.Printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
445
		theConsole.Printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
444
		return "";
-
 
445
	}
446
	}
-
 
447
 
-
 
448
  if(args.size() != 3)
-
 
449
		return "";
-
 
450
 
446
	int E0,E1;
451
  int E0,E1;
447
	float scale;
452
	float scale;
448
	istringstream a0(args[0]);
453
	istringstream a0(args[0]);
449
	a0 >> E0;
454
	a0 >> E0;
450
	istringstream a1(args[1]);
455
	istringstream a1(args[1]);
451
	a1 >> E1;
456
	a1 >> E1;
452
	istringstream a2(args[2]);
457
	istringstream a2(args[2]);
453
	a2 >> scale;
458
	a2 >> scale;
454
	avo().harmonics_partial_reconstruct(E0,E1,scale);
459
	avo().harmonics_partial_reconstruct(E0,E1,scale);
455
	return "";
460
	return "";
456
}
461
}
457
 
462
 
458
char* console_reset_shape(std::vector<std::string> &args)
463
char* console_reset_shape(std::vector<std::string> &args)
459
{
464
{
460
	if(wantshelp(args)) 
465
	if(wantshelp(args)) 
461
	{
466
	{
462
		theConsole.Printf("usage: harmonics.reset_shape ");
467
		theConsole.Printf("usage: harmonics.reset_shape ");
463
		theConsole.Printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
468
		theConsole.Printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
464
		theConsole.Printf("unless you know what you are doing.");
469
		theConsole.Printf("unless you know what you are doing.");
465
		return "";
470
		return "";
466
	}
471
	}
467
	avo().harmonics_reset_shape();
472
	avo().harmonics_reset_shape();
468
	return "";
473
	return "";
469
}
474
}
470
 
475
 
471
 
476
 
472
char* console_close_holes(std::vector<std::string> &args)
477
char* console_close_holes(std::vector<std::string> &args)
473
{
478
{
474
	if(wantshelp(args)) 
479
	if(wantshelp(args)) 
475
	{
480
	{
476
		theConsole.Printf("usage: cleanup.close_holes");
481
		theConsole.Printf("usage: cleanup.close_holes");
477
		theConsole.Printf("This function closes holes. It simply follows the loop of halfvectors which");
482
		theConsole.Printf("This function closes holes. It simply follows the loop of halfvectors which");
478
		theConsole.Printf("enclose the hole and add a face to which they all point.");
483
		theConsole.Printf("enclose the hole and add a face to which they all point.");
479
		return "";
484
		return "";
480
	}
485
	}
481
	close_holes(active_mesh());
486
	close_holes(active_mesh());
482
	return "";
487
	return "";
483
}
488
}
484
 
489
 
485
char* console_reload(std::vector<std::string> &args)
490
char* console_reload(std::vector<std::string> &args)
486
{
491
{
487
	if(wantshelp(args)) 
492
	if(wantshelp(args)) 
488
	{
493
	{
489
		theConsole.Printf("usage:  reload <file>");
494
		theConsole.Printf("usage:  reload <file>");
490
		theConsole.Printf("Reloads the current file if no argument is given, but");
495
		theConsole.Printf("Reloads the current file if no argument is given, but");
491
		theConsole.Printf("if an argument is given, then that becomes the current file");
496
		theConsole.Printf("if an argument is given, then that becomes the current file");
492
		return "";
497
		return "";
493
	}
498
	}
494
	if(!avo().reload(args.size()>0 ? args[0]:""))
499
	if(!avo().reload(args.size()>0 ? args[0]:""))
495
		return "failed to load";
500
		return "failed to load";
496
	return "";
501
	return "";
497
}
502
}
498
 
503
 
499
 
504
 
500
char* console_simplify(std::vector<std::string> &args)
505
char* console_simplify(std::vector<std::string> &args)
501
{
506
{
502
	if(wantshelp(args)) 
507
	if(wantshelp(args)) 
503
	{
508
	{
504
		theConsole.Printf("usage: simplify <fraction> ");
509
		theConsole.Printf("usage: simplify <fraction> ");
505
		theConsole.Printf("Performs Garland Heckbert (quadric based) mesh simplification.");
510
		theConsole.Printf("Performs Garland Heckbert (quadric based) mesh simplification.");
506
		theConsole.Printf("The only argument is the fraction of vertices to keep.");
511
		theConsole.Printf("The only argument is the fraction of vertices to keep.");
507
		return "";
512
		return "";
508
	}
513
	}
509
	float keep_fraction;
514
	float keep_fraction;
510
	if(args.size()==0) return "you must specify fraction of vertices to keep";
515
	if(args.size()==0) return "you must specify fraction of vertices to keep";
511
	istringstream a0(args[0]);
516
	istringstream a0(args[0]);
512
	a0 >> keep_fraction;
517
	a0 >> keep_fraction;
513
	
518
	
514
	Vec3f p0, p7;
519
	Vec3f p0, p7;
515
	active_mesh().get_bbox(p0, p7);
520
	active_mesh().get_bbox(p0, p7);
516
	Vec3f d = p7-p0;
521
	Vec3f d = p7-p0;
517
	float s = 1.0/d.max_coord();
522
	float s = 1.0/d.max_coord();
518
	Vec3f pcentre = (p7+p0)/2.0;
523
	Vec3f pcentre = (p7+p0)/2.0;
519
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
524
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
520
		vi->pos = (vi->pos - pcentre) * s;
525
		vi->pos = (vi->pos - pcentre) * s;
521
	quadric_simplify(active_mesh(),keep_fraction,0.0001f,true);
526
	quadric_simplify(active_mesh(),keep_fraction,0.0001f,true);
522
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
527
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
523
		vi->pos = vi->pos*d.max_coord() + pcentre;
528
		vi->pos = vi->pos*d.max_coord() + pcentre;
524
	return "";
529
	return "";
525
}
530
}
526
 
531
 
527
char* console_vertex_noise(std::vector<std::string> &args)
532
char* console_vertex_noise(std::vector<std::string> &args)
528
{
533
{
529
	if(wantshelp(args)) 
534
	if(wantshelp(args)) 
530
	{
535
	{
531
		theConsole.Printf("usage: noise.perturb_vertices <amplitude>");
536
		theConsole.Printf("usage: noise.perturb_vertices <amplitude>");
532
		theConsole.Printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
537
		theConsole.Printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
533
		theConsole.Printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
538
		theConsole.Printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
534
		theConsole.Printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
539
		theConsole.Printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
535
		theConsole.Printf("If no amplitude is specified, the default (0.5) is used.");
540
		theConsole.Printf("If no amplitude is specified, the default (0.5) is used.");
536
		return "";
541
		return "";
537
	}
542
	}
538
	float avg_length = average_edge_length(active_mesh());
543
	float avg_length = average_edge_length(active_mesh());
539
	
544
	
540
	float noise_amplitude = 0.5;
545
	float noise_amplitude = 0.5;
541
	if(args.size()>0) 
546
	if(args.size()>0) 
542
	{
547
	{
543
		istringstream a0(args[0]);
548
		istringstream a0(args[0]);
544
		a0 >> noise_amplitude;
549
		a0 >> noise_amplitude;
545
	}
550
	}
546
	
551
	
547
	srand(0);
552
	srand(0);
548
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
553
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
549
	{
554
	{
550
		Vec3f v;
555
		Vec3f v;
551
		do {
556
		do {
552
			v = Vec3f(rand(),rand(),rand());
557
			v = Vec3f(rand(),rand(),rand());
553
			v /= RAND_MAX;
558
			v /= RAND_MAX;
554
		} while(sqr_length(v) > 1.0);
559
		} while(sqr_length(v) > 1.0);
555
		v -= Vec3f(0.5);
560
		v -= Vec3f(0.5);
556
		v *= 2.0;
561
		v *= 2.0;
557
		v *= noise_amplitude;
562
		v *= noise_amplitude;
558
		v *= avg_length;
563
		v *= avg_length;
559
		vi->pos += v;
564
		vi->pos += v;
560
	}		
565
	}		
561
	return "";
566
	return "";
562
}
567
}
563
 
568
 
564
char* console_noisy_flips(std::vector<std::string> &args)
569
char* console_noisy_flips(std::vector<std::string> &args)
565
{
570
{
566
	if(wantshelp(args)) 
571
	if(wantshelp(args)) 
567
	{
572
	{
568
		theConsole.Printf("usage:  noise.perturb_topology <iter>");
573
		theConsole.Printf("usage:  noise.perturb_topology <iter>");
569
		theConsole.Printf("Perform random flips. iter (default=1) is the number of iterations.");
574
		theConsole.Printf("Perform random flips. iter (default=1) is the number of iterations.");
570
		theConsole.Printf("mostly for making nasty synthetic test cases.");
575
		theConsole.Printf("mostly for making nasty synthetic test cases.");
571
		return "";
576
		return "";
572
	}
577
	}
573
	int iter=1;
578
	int iter=1;
574
	if(args.size()>0)
579
	if(args.size()>0)
575
	{
580
	{
576
		istringstream a0(args[0]);
581
		istringstream a0(args[0]);
577
		a0 >> iter;
582
		a0 >> iter;
578
	}
583
	}
579
	
584
	
580
	randomize_mesh(active_mesh(),  iter);
585
	randomize_mesh(active_mesh(),  iter);
581
	return "";
586
	return "";
582
}
587
}
583
 
588
 
584
char* console_laplacian_smooth(std::vector<std::string> &args)
589
char* console_laplacian_smooth(std::vector<std::string> &args)
585
{
590
{
586
	if(wantshelp(args)) 
591
	if(wantshelp(args)) 
587
	{
592
	{
588
		theConsole.Printf("usage:  smooth.laplacian <weight>");
593
		theConsole.Printf("usage:  smooth.laplacian <weight>");
589
		theConsole.Printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
594
		theConsole.Printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
590
		return "";
595
		return "";
591
	}
596
	}
592
	float t=1.0;
597
	float t=1.0;
593
	if(args.size()>0)
598
	if(args.size()>0)
594
	{
599
	{
595
		istringstream a0(args[0]);
600
		istringstream a0(args[0]);
596
		a0 >> t;
601
		a0 >> t;
597
	}
602
	}
598
	/// Simple laplacian smoothing with an optional weight.
603
	/// Simple laplacian smoothing with an optional weight.
599
	laplacian_smooth(active_mesh(), t);
604
	laplacian_smooth(active_mesh(), t);
600
	return "";
605
	return "";
601
}
606
}
602
 
607
 
603
char* console_taubin_smooth(std::vector<std::string> &args)
608
char* console_taubin_smooth(std::vector<std::string> &args)
604
{
609
{
605
	if(wantshelp(args)) 
610
	if(wantshelp(args)) 
606
	{
611
	{
607
		theConsole.Printf("usage:  smooth.taubin <iter>");
612
		theConsole.Printf("usage:  smooth.taubin <iter>");
608
		theConsole.Printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
613
		theConsole.Printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
609
		return "";
614
		return "";
610
	}
615
	}
611
	int iter=1;
616
	int iter=1;
612
	if(args.size()>0)
617
	if(args.size()>0)
613
	{
618
	{
614
		istringstream a0(args[0]);
619
		istringstream a0(args[0]);
615
		a0 >> iter;
620
		a0 >> iter;
616
	}
621
	}
617
	
622
	
618
	/// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
623
	/// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
619
	taubin_smooth(active_mesh(),  iter);
624
	taubin_smooth(active_mesh(),  iter);
620
	return "";
625
	return "";
621
}
626
}
622
 
627
 
623
char* console_fvm_smooth(std::vector<std::string> &args)
628
char* console_fvm_smooth(std::vector<std::string> &args)
624
{	
629
{	
625
	if(wantshelp(args)) 
630
	if(wantshelp(args)) 
626
	{
631
	{
627
		theConsole.Printf("usage: smooth.fuzzy_vector_median <iter>");
632
		theConsole.Printf("usage: smooth.fuzzy_vector_median <iter>");
628
		theConsole.Printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
633
		theConsole.Printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
629
		theConsole.Printf("This function does a very good job of preserving sharp edges.");
634
		theConsole.Printf("This function does a very good job of preserving sharp edges.");
630
		return "";
635
		return "";
631
	}
636
	}
632
	int iter=1;
637
	int iter=1;
633
	if(args.size()>0)
638
	if(args.size()>0)
634
	{
639
	{
635
		istringstream a0(args[0]);
640
		istringstream a0(args[0]);
636
		a0 >> iter;
641
		a0 >> iter;
637
	}
642
	}
638
	/** Fuzzy vector median smoothing is effective when it comes to
643
	/** Fuzzy vector median smoothing is effective when it comes to
639
	 preserving sharp edges. */
644
	 preserving sharp edges. */
640
	fvm_smooth(active_mesh(),  iter);
645
	fvm_smooth(active_mesh(),  iter);
641
	return "";
646
	return "";
642
	
647
	
643
}
648
}
644
 
649
 
645
char* console_triangulate(std::vector<std::string> &args)
650
char* console_triangulate(std::vector<std::string> &args)
646
{	
651
{	
647
	if(wantshelp(args)) 
652
	if(wantshelp(args)) 
648
	{
653
	{
649
		theConsole.Printf("usage:  triangulate");
654
		theConsole.Printf("usage:  triangulate");
650
		theConsole.Printf("This function triangulates all non triangular faces of the mesh.");
655
		theConsole.Printf("This function triangulates all non triangular faces of the mesh.");
651
		theConsole.Printf("you may want to call it after hole closing. For a polygon it simply connects");
656
		theConsole.Printf("you may want to call it after hole closing. For a polygon it simply connects");
652
		theConsole.Printf("the two closest vertices in a recursive manner until only triangles remain");
657
		theConsole.Printf("the two closest vertices in a recursive manner until only triangles remain");
653
		return "";
658
		return "";
654
	}
659
	}
655
	shortest_edge_triangulate(active_mesh());
660
	shortest_edge_triangulate(active_mesh());
656
	return "";
661
	return "";
657
}
662
}
658
 
663
 
659
 
664
 
660
char* console_remove_caps(std::vector<std::string> &args)
665
char* console_remove_caps(std::vector<std::string> &args)
661
{	
666
{	
662
	if(wantshelp(args)) 
667
	if(wantshelp(args)) 
663
	{
668
	{
664
		theConsole.Printf("usage:  cleanup.remove_caps thresh");
669
		theConsole.Printf("usage:  cleanup.remove_caps thresh");
665
		theConsole.Printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
670
		theConsole.Printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
666
		theConsole.Printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
671
		theConsole.Printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
667
		return "";
672
		return "";
668
	}
673
	}
669
	float t=0.85;
674
	float t=0.85;
670
	if(args.size()>0)
675
	if(args.size()>0)
671
	{
676
	{
672
		istringstream a0(args[0]);
677
		istringstream a0(args[0]);
673
		a0 >> t;
678
		a0 >> t;
674
	}
679
	}
675
	
680
	
676
	remove_caps_from_trimesh(active_mesh(), static_cast<float>(M_PI) *t);
681
	remove_caps_from_trimesh(active_mesh(), static_cast<float>(M_PI) *t);
677
	return "";
682
	return "";
678
}
683
}
679
 
684
 
680
char* console_remove_needles(std::vector<std::string> &args)
685
char* console_remove_needles(std::vector<std::string> &args)
681
{	
686
{	
682
	if(wantshelp(args)) 
687
	if(wantshelp(args)) 
683
	{
688
	{
684
		theConsole.Printf("usage: cleanup.remove_needles <thresh>");
689
		theConsole.Printf("usage: cleanup.remove_needles <thresh>");
685
		theConsole.Printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
690
		theConsole.Printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
686
		theConsole.Printf("to get the length shorter than which we collapse. Default = 0.1");
691
		theConsole.Printf("to get the length shorter than which we collapse. Default = 0.1");
687
		return "";
692
		return "";
688
	}
693
	}
689
	float thresh = 0.1;
694
	float thresh = 0.1;
690
	if(args.size()>0)
695
	if(args.size()>0)
691
	{
696
	{
692
		istringstream a0(args[0]);
697
		istringstream a0(args[0]);
693
		a0 >> thresh;
698
		a0 >> thresh;
694
	}
699
	}
695
	float avg_length = average_edge_length(active_mesh());
700
	float avg_length = average_edge_length(active_mesh());
696
	remove_needles_from_trimesh(active_mesh(), thresh * avg_length);
701
	remove_needles_from_trimesh(active_mesh(), thresh * avg_length);
697
	return "";
702
	return "";
698
}
703
}
699
 
704
 
700
void reshape(int W, int H)
705
void reshape(int W, int H)
701
{
706
{
702
	active_view_control().reshape(W,H);
707
	active_view_control().reshape(W,H);
703
}
708
}
704
 
709
 
705
void display() 
710
void display() 
706
{
711
{
707
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
712
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
708
	
713
	
709
	static CVar<string> display_render_mode("display.render_mode","");
714
	static CVar<string> display_render_mode("display.render_mode","");
710
	static CVar<int> display_smooth("display.smooth_shading",1);
715
	static CVar<int> display_smooth("display.smooth_shading",1);
711
	
716
	
712
	glPushMatrix();
717
	glPushMatrix();
713
	
718
	
714
	avo().display(display_render_mode, display_smooth);
719
	avo().display(display_render_mode, display_smooth);
715
	
720
	
716
	glPopMatrix();
721
	glPopMatrix();
717
	
722
	
718
	glUseProgram(0);
723
	glUseProgram(0);
719
	theConsole.RenderConsole();
724
	theConsole.RenderConsole();
720
	
725
	
721
	glutSwapBuffers();
726
	glutSwapBuffers();
722
}
727
}
723
 
728
 
724
void animate() 
729
void animate() 
725
{	
730
{	
726
	//usleep( (int)1e4 );
731
	//usleep( (int)1e4 );
727
	active_view_control().try_spin();
732
	active_view_control().try_spin();
728
	glutPostRedisplay();
733
	glutPostRedisplay();
729
}
734
}
730
 
735
 
731
 
736
 
732
void mouse(int button, int state, int x, int y) 
737
void mouse(int button, int state, int x, int y) 
733
{
738
{
734
	Vec2i pos(x,y);
739
	Vec2i pos(x,y);
735
	if (state==GLUT_DOWN) 
740
	if (state==GLUT_DOWN) 
736
	{
741
	{
737
		if (button==GLUT_LEFT_BUTTON) 
742
		if (button==GLUT_LEFT_BUTTON) 
738
			active_view_control().grab_ball(ROTATE_ACTION,pos);
743
			active_view_control().grab_ball(ROTATE_ACTION,pos);
739
		else if (button==GLUT_MIDDLE_BUTTON) 
744
		else if (button==GLUT_MIDDLE_BUTTON) 
740
			active_view_control().grab_ball(ZOOM_ACTION,pos);
745
			active_view_control().grab_ball(ZOOM_ACTION,pos);
741
		else if (button==GLUT_RIGHT_BUTTON) 
746
		else if (button==GLUT_RIGHT_BUTTON) 
742
			active_view_control().grab_ball(PAN_ACTION,pos);
747
			active_view_control().grab_ball(PAN_ACTION,pos);
743
	}
748
	}
744
	else if (state==GLUT_UP)
749
	else if (state==GLUT_UP)
745
		active_view_control().release_ball();
750
		active_view_control().release_ball();
746
}
751
}
747
 
752
 
748
void motion(int x, int y) {
753
void motion(int x, int y) {
749
	Vec2i pos(x,y);
754
	Vec2i pos(x,y);
750
	active_view_control().roll_ball(Vec2i(x,y));
755
	active_view_control().roll_ball(Vec2i(x,y));
751
}
756
}
752
 
757
 
753
void keyboard_spec(int key, int x, int y)
758
void keyboard_spec(int key, int x, int y)
754
{
759
{
755
	int mod = glutGetModifiers();
760
	int mod = glutGetModifiers();
756
	if( theConsole.isOpen() ) {
761
	if( theConsole.isOpen() ) {
757
		// If shift held, scroll the console
762
		// If shift held, scroll the console
758
		if( mod == GLUT_ACTIVE_SHIFT ) {
763
		if( mod == GLUT_ACTIVE_SHIFT ) {
759
			switch (key){
764
			switch (key){
760
				case GLUT_KEY_UP:
765
				case GLUT_KEY_UP:
761
					theConsole.ScrollDownLine();
766
					theConsole.ScrollDownLine();
762
					break;
767
					break;
763
				case GLUT_KEY_DOWN: 
768
				case GLUT_KEY_DOWN: 
764
					theConsole.ScrollUpLine();
769
					theConsole.ScrollUpLine();
765
					break;
770
					break;
766
			}
771
			}
767
		} else {
772
		} else {
768
			theConsole.StandardKeyBindings( key );
773
			theConsole.StandardKeyBindings( key );
769
		}
774
		}
770
	}
775
	}
771
}
776
}
772
 
777
 
773
 
778
 
774
void keyboard(unsigned char key, int x, int y) 
779
void keyboard(unsigned char key, int x, int y) 
775
{	
780
{	
776
	if(theConsole.isOpen())
781
	if(theConsole.isOpen())
777
	{
782
	{
778
		switch(key) {
783
		switch(key) {
779
			case '\033': 
784
			case '\033': 
780
				theConsole.ToggleConsole();
785
				theConsole.ToggleConsole();
781
			default:      
786
			default:      
782
				//send keystroke to console
787
				//send keystroke to console
783
				if( theConsole.isOpen() ){
788
				if( theConsole.isOpen() ){
784
					theConsole.EnterCommandCharacter(key);
789
					theConsole.EnterCommandCharacter(key);
785
				}
790
				}
786
				break;
791
				break;
787
		}
792
		}
788
		if(key == 13)	avo().post_create_display_list();
793
		if(key == 13)	avo().post_create_display_list();
789
		
794
		
790
	}	
795
	}	
791
	else {
796
	else {
792
		string& display_render_mode = get_CVar_ref<string>("display.render_mode");
797
		string& display_render_mode = get_CVar_ref<string>("display.render_mode");
793
		int& display_smooth = get_CVar_ref<int>("display.smooth_shading");
798
		int& display_smooth = get_CVar_ref<int>("display.smooth_shading");
794
		int& active  = get_CVar_ref<int>("active_mesh");
799
		int& active  = get_CVar_ref<int>("active_mesh");
795
		
800
		
796
		
801
		
797
		switch(key) {
802
		switch(key) {
798
			case 'q': exit(0);
803
			case 'q': exit(0);
799
			case '\033':
804
			case '\033':
800
				theConsole.ToggleConsole();
805
				theConsole.ToggleConsole();
801
				break;
806
				break;
802
			case '1':
807
			case '1':
803
			case '2':
808
			case '2':
804
			case '3':
809
			case '3':
805
			case '4':
810
			case '4':
806
			case '5':
811
			case '5':
807
			case '6':
812
			case '6':
808
			case '7':
813
			case '7':
809
			case '8':
814
			case '8':
810
			case '9':
815
			case '9':
811
				active = key - '1'; break;
816
				active = key - '1'; break;
812
			case 'f': display_smooth = !display_smooth; break;
817
			case 'f': display_smooth = !display_smooth; break;
813
			case 'w':
818
			case 'w':
814
				display_render_mode = "wire"; break;
819
				display_render_mode = "wire"; break;
815
			case 'n':
820
			case 'n':
816
				display_render_mode = "normal"; break;
821
				display_render_mode = "normal"; break;
817
			case 'i':
822
			case 'i':
818
				display_render_mode = "isophotes"; break;
823
				display_render_mode = "isophotes"; break;
819
			case 'r':
824
			case 'r':
820
				display_render_mode = "reflection"; break;
825
				display_render_mode = "reflection"; break;
821
			case 'h':
826
			case 'h':
822
				display_render_mode = "harmonics"; break;
827
				display_render_mode = "harmonics"; break;
823
			case 't':
828
			case 't':
824
				display_render_mode = "toon"; break;
829
				display_render_mode = "toon"; break;
825
			case 'g':
830
			case 'g':
826
				display_render_mode = "glazed"; break;
831
				display_render_mode = "glazed"; break;
827
			case 'a':
832
			case 'a':
828
				display_render_mode = "ambient_occlusion"; break;
833
				display_render_mode = "ambient_occlusion"; break;
829
			case 'c':
834
			case 'c':
830
				display_render_mode = "copper"; break;
835
				display_render_mode = "copper"; break;
831
			case 'C':
836
			case 'C':
832
				display_render_mode = "curvature_lines"; break;
837
				display_render_mode = "curvature_lines"; break;
833
			case 'M':
838
			case 'M':
834
				display_render_mode = "mean_curvature"; break;
839
				display_render_mode = "mean_curvature"; break;
835
			case 'G':
840
			case 'G':
836
				display_render_mode = "gaussian_curvature"; break;
841
				display_render_mode = "gaussian_curvature"; break;
837
		}
842
		}
838
		
843
		
839
		if(display_render_mode.substr(0,4) == "harm")
844
		if(display_render_mode.substr(0,4) == "harm")
840
			avo().harmonics_parse_key(key);
845
			avo().harmonics_parse_key(key);
841
		
846
		
842
		if(key != '\033') avo().post_create_display_list();		
847
		if(key != '\033') avo().post_create_display_list();		
843
	}
848
	}
844
}
849
}
845
 
850
 
846
void init_glut(int argc, char** argv)
851
void init_glut(int argc, char** argv)
847
{
852
{
848
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
853
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
849
	glutInitWindowSize(WINX, WINY);
854
	glutInitWindowSize(WINX, WINY);
850
	glutInit(&argc, argv);
855
	glutInit(&argc, argv);
851
	glutCreateWindow("Shape Harmonics");
856
	glutCreateWindow("Shape Harmonics");
852
	glutDisplayFunc(display);
857
	glutDisplayFunc(display);
853
	glutKeyboardFunc(keyboard);
858
	glutKeyboardFunc(keyboard);
854
	glutSpecialFunc(keyboard_spec);
859
	glutSpecialFunc(keyboard_spec);
855
	glutReshapeFunc(reshape);
860
	glutReshapeFunc(reshape);
856
	glutMouseFunc(mouse);
861
	glutMouseFunc(mouse);
857
	glutMotionFunc(motion);
862
	glutMotionFunc(motion);
858
	glutIdleFunc(animate);
863
	glutIdleFunc(animate);
859
}
864
}
860
 
865
 
861
void init_gl()
866
void init_gl()
862
{
867
{
863
	glewInit();
868
	glewInit();
864
	glEnable(GL_LIGHTING);
869
	glEnable(GL_LIGHTING);
865
	glEnable(GL_LIGHT0);
870
	glEnable(GL_LIGHT0);
866
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
871
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
867
	
872
	
868
	// Set the value of a uniform
873
	// Set the value of a uniform
869
	//glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
874
	//glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
870
	
875
	
871
	glMatrixMode(GL_MODELVIEW);
876
	glMatrixMode(GL_MODELVIEW);
872
	glLoadIdentity();
877
	glLoadIdentity();
873
	glClearColor(0.50f, 0.50f, 0.50f, 0.f);
878
	glClearColor(0.50f, 0.50f, 0.50f, 0.f);
874
	glColor4f(1.0f, 1.0f, 1.0f, 0.f);
879
	glColor4f(1.0f, 1.0f, 1.0f, 0.f);
875
	float material[4] = {1,1,1,1};
880
	float material[4] = {1,1,1,1};
876
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
881
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
877
	glEnable(GL_DEPTH_TEST);
882
	glEnable(GL_DEPTH_TEST);
878
	
883
	
879
	static CVar<ConsoleFunc> help( "help", ConsoleHelp );
884
	static CVar<ConsoleFunc> help( "help", ConsoleHelp );
880
	static CVar<ConsoleFunc> rs("harmonics.reset_shape", console_reset_shape);
885
	static CVar<ConsoleFunc> rs("harmonics.reset_shape", console_reset_shape);
881
	static CVar<ConsoleFunc> ha("harmonics.analyze", console_analyze);
886
	static CVar<ConsoleFunc> ha("harmonics.analyze", console_analyze);
882
	static CVar<ConsoleFunc> pr("harmonics.partial_reconstruct", console_partial_reconstruct);
887
	static CVar<ConsoleFunc> pr("harmonics.partial_reconstruct", console_partial_reconstruct);
883
	static CVar<ConsoleFunc> simpl("simplify", console_simplify);
888
	static CVar<ConsoleFunc> simpl("simplify", console_simplify);
884
	static CVar<ConsoleFunc> lsmooth("smooth.laplacian", console_laplacian_smooth);
889
	static CVar<ConsoleFunc> lsmooth("smooth.laplacian", console_laplacian_smooth);
885
	static CVar<ConsoleFunc> tsmooth("smooth.taubin", console_taubin_smooth);
890
	static CVar<ConsoleFunc> tsmooth("smooth.taubin", console_taubin_smooth);
886
	static CVar<ConsoleFunc> fsmooth("smooth.fuzzy_vector_median", console_fvm_smooth);
891
	static CVar<ConsoleFunc> fsmooth("smooth.fuzzy_vector_median", console_fvm_smooth);
887
	
892
	
888
	static CVar<ConsoleFunc> opt_val("optimize.valency", console_optimize_valency);
893
	static CVar<ConsoleFunc> opt_val("optimize.valency", console_optimize_valency);
889
	static CVar<ConsoleFunc> min_dih("optimize.minimize_dihedral_angles", console_minimize_dihedral);
894
	static CVar<ConsoleFunc> min_dih("optimize.minimize_dihedral_angles", console_minimize_dihedral);
890
	static CVar<ConsoleFunc> min_curv("optimize.minimize_curvature", console_minimize_curvature);
895
	static CVar<ConsoleFunc> min_curv("optimize.minimize_curvature", console_minimize_curvature);
891
	static CVar<ConsoleFunc> max_min_angle("optimize.maximize_min_angle", console_maximize_min_angle);
896
	static CVar<ConsoleFunc> max_min_angle("optimize.maximize_min_angle", console_maximize_min_angle);
892
	static CVar<ConsoleFunc> close_holes_fun("cleanup.close_holes", console_close_holes);
897
	static CVar<ConsoleFunc> close_holes_fun("cleanup.close_holes", console_close_holes);
893
	static CVar<ConsoleFunc> reload_fun("reload", console_reload);
898
	static CVar<ConsoleFunc> reload_fun("reload", console_reload);
894
	
899
	
895
	static CVar<ConsoleFunc> rem_caps_fun("cleanup.remove_caps", console_remove_caps);
900
	static CVar<ConsoleFunc> rem_caps_fun("cleanup.remove_caps", console_remove_caps);
896
	static CVar<ConsoleFunc> rem_needles_fun("cleanup.remove_needles", console_remove_needles);
901
	static CVar<ConsoleFunc> rem_needles_fun("cleanup.remove_needles", console_remove_needles);
897
	static CVar<ConsoleFunc> triangulate_fun("triangulate", console_triangulate);
902
	static CVar<ConsoleFunc> triangulate_fun("triangulate", console_triangulate);
898
	static CVar<ConsoleFunc> refine_fun("refine.split_edges", console_refine_edges);
903
	static CVar<ConsoleFunc> refine_fun("refine.split_edges", console_refine_edges);
899
	static CVar<ConsoleFunc> refine_face_fun("refine.split_faces", console_refine_faces);
904
	static CVar<ConsoleFunc> refine_face_fun("refine.split_faces", console_refine_faces);
900
	static CVar<ConsoleFunc> subd_fun("refine.catmull_clark", console_cc_subdivide);
905
	static CVar<ConsoleFunc> subd_fun("refine.catmull_clark", console_cc_subdivide);
901
	static CVar<ConsoleFunc> save_fun("save", console_save);
906
	static CVar<ConsoleFunc> save_fun("save", console_save);
902
	static CVar<ConsoleFunc> noise_fun("noise.perturb_vertices", console_vertex_noise);
907
	static CVar<ConsoleFunc> noise_fun("noise.perturb_vertices", console_vertex_noise);
903
	static CVar<ConsoleFunc> noise_fun2("noise.perturb_topology", console_noisy_flips);
908
	static CVar<ConsoleFunc> noise_fun2("noise.perturb_topology", console_noisy_flips);
904
	
909
	
905
	static CVar<ConsoleFunc> dualize("dual", console_dual);
910
	static CVar<ConsoleFunc> dualize("dual", console_dual);
906
	
911
	
907
	static CVar<ConsoleFunc> align_fun("align", console_align);
912
	static CVar<ConsoleFunc> align_fun("align", console_align);
908
	
913
	
909
	
914
	
910
}
915
}
911
 
916
 
912
int main(int argc, char** argv)
917
int main(int argc, char** argv)
913
{
918
{
914
	ArgExtracter ae(argc, argv);
919
	ArgExtracter ae(argc, argv);
915
	
920
	
916
	init_glut(argc,argv);
921
	init_glut(argc,argv);
917
	init_gl();
922
	init_gl();
918
	
923
	
919
	Harmonics::init();
924
	Harmonics::init();
920
	
925
	
921
	if(argc>1)
926
	if(argc>1)
922
	{		
927
	{		
923
		string file = ae.get_last_arg();
928
		string file = ae.get_last_arg();
924
		avo().reload(file);
929
		avo().reload(file);
925
	}
930
	}
926
	
931
	
927
	
932
	
928
	glutMainLoop();
933
	glutMainLoop();
929
}
934
}
930
 
935
 
931
 
936
 
932
 
937