Subversion Repositories gelsvn

Rev

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

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