Subversion Repositories gelsvn

Rev

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

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