Subversion Repositories gelsvn

Rev

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

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