Subversion Repositories gelsvn

Rev

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

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