Subversion Repositories gelsvn

Rev

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

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