Subversion Repositories gelsvn

Rev

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

Rev 417 Rev 434
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/off_save.h>
42
#include <HMesh/mesh_optimization.h>
43
#include <HMesh/mesh_optimization.h>
43
#include <HMesh/triangulate.h>
44
#include <HMesh/triangulate.h>
44
#include <HMesh/close_holes.h>
45
#include <HMesh/close_holes.h>
45
#include <HMesh/caps_and_needles.h>
46
#include <HMesh/caps_and_needles.h>
46
#include <HMesh/refine_edges.h>
47
#include <HMesh/refine_edges.h>
47
#include <HMesh/subdivision.h>
48
#include <HMesh/subdivision.h>
48
 
49
 
49
#include <GLConsole/GLConsole.h>
50
#include <GLConsole/GLConsole.h>
50
#include <Util/Timer.h>
51
#include <Util/Timer.h>
51
#include "harmonics.h"
52
#include "harmonics.h"
52
#include "curvature.h"
53
#include "curvature.h"
53
#include "Renderer.h"
54
#include "Renderer.h"
54
#include "VisObj.h"
55
#include "VisObj.h"
55
 
56
 
56
using namespace std;
57
using namespace std;
57
using namespace HMesh;
58
using namespace HMesh;
58
using namespace Geometry;
59
using namespace Geometry;
59
using namespace GLGraphics;
60
using namespace GLGraphics;
60
using namespace CGLA;
61
using namespace CGLA;
61
using namespace Util;
62
using namespace Util;
62
using namespace LinAlg;
63
using namespace LinAlg;
63
using namespace CVarUtils;
64
using namespace CVarUtils;
64
 
65
 
65
inline VisObj& get_vis_obj(int i)
66
inline VisObj& get_vis_obj(int i)
66
{
67
{
67
	static VisObj vo[9];
68
	static VisObj vo[9];
68
	return vo[i];
69
	return vo[i];
69
}
70
}
70
 
71
 
71
inline VisObj& avo()
72
inline VisObj& avo()
72
{
73
{
73
	static int& active = CreateCVar("active_mesh",0);
74
	static int& active = CreateCVar("active_mesh",0);
74
	return get_vis_obj(active);
75
	return get_vis_obj(active);
75
}
76
}
76
 
77
 
77
inline Manifold& active_mesh()
78
inline Manifold& active_mesh()
78
{
79
{
79
	return avo().mesh();
80
	return avo().mesh();
80
}
81
}
81
 
82
 
82
inline GLViewController& active_view_control()
83
inline GLViewController& active_view_control()
83
{
84
{
84
	return avo().view_control();
85
	return avo().view_control();
85
}
86
}
86
 
87
 
87
// Single global instance so glut can get access
88
// Single global instance so glut can get access
88
Trie CVarTrie;
89
Trie CVarTrie;
89
GLConsole theConsole;
90
GLConsole theConsole;
90
 
91
 
91
////////////////////////////////////////////////////////////////////////////////
92
////////////////////////////////////////////////////////////////////////////////
92
char* ConsoleHelp(std::vector<std::string> &args)
93
char* ConsoleHelp(std::vector<std::string> &args)
93
{
94
{
94
    theConsole.Printf("");
95
    theConsole.Printf("");
95
    theConsole.Printf("----------------- HELP -----------------");
96
    theConsole.Printf("----------------- HELP -----------------");
96
    theConsole.Printf("Press ESC key to open and close console");
97
    theConsole.Printf("Press ESC key to open and close console");
97
    theConsole.Printf("Press TAB to see the available commands and functions");
98
    theConsole.Printf("Press TAB to see the available commands and functions");
98
    theConsole.Printf("Functions are shown in green and variables in yellow");
99
    theConsole.Printf("Functions are shown in green and variables in yellow");
99
    theConsole.Printf("Setting a value: [command] = value");
100
    theConsole.Printf("Setting a value: [command] = value");
100
    theConsole.Printf("Getting a value: [command]");
101
    theConsole.Printf("Getting a value: [command]");
101
    theConsole.Printf("Functions: [function] [arg1] [arg2] ...");
102
    theConsole.Printf("Functions: [function] [arg1] [arg2] ...");
102
    theConsole.Printf("Entering arg1=? or arg1=help will give a description.");
103
    theConsole.Printf("Entering arg1=? or arg1=help will give a description.");
103
    theConsole.Printf("History: Up and Down arrow keys move through history.");
104
    theConsole.Printf("History: Up and Down arrow keys move through history.");
104
    theConsole.Printf("Tab Completion: TAB does tab completion and makes suggestions.");
105
    theConsole.Printf("Tab Completion: TAB does tab completion and makes suggestions.");
105
    theConsole.Printf("");
106
    theConsole.Printf("");
106
    theConsole.Printf("Keyboard commands (when console is not active):");
107
    theConsole.Printf("Keyboard commands (when console is not active):");
107
    theConsole.Printf("w   : switch to display.render_mode = wireframe");
108
    theConsole.Printf("w   : switch to display.render_mode = wireframe");
108
    theConsole.Printf("i   : switch to display.render_mode = isophotes");
109
    theConsole.Printf("i   : switch to display.render_mode = isophotes");
109
    theConsole.Printf("r   : switch to display.render_mode = reflection");
110
    theConsole.Printf("r   : switch to display.render_mode = reflection");
110
    theConsole.Printf("m   : switch to display.render_mode = metallic");
111
    theConsole.Printf("m   : switch to display.render_mode = metallic");
111
    theConsole.Printf("g   : switch to display.render_mode = glazed");
112
    theConsole.Printf("g   : switch to display.render_mode = glazed");
112
    theConsole.Printf("n   : switch to display.render_mode = normal");
113
    theConsole.Printf("n   : switch to display.render_mode = normal");
113
    theConsole.Printf("h   : switch to display.render_mode = harmonics");
114
    theConsole.Printf("h   : switch to display.render_mode = harmonics");
114
    theConsole.Printf("f   : toggle smooth/flat shading");
115
    theConsole.Printf("f   : toggle smooth/flat shading");
115
    theConsole.Printf("1-9 : switch between active meshes.");
116
    theConsole.Printf("1-9 : switch between active meshes.");
116
    theConsole.Printf("d   : (display.render_mode = harmonics) diffuse light on and off");
117
    theConsole.Printf("d   : (display.render_mode = harmonics) diffuse light on and off");
117
    theConsole.Printf("h   : (display.render_mode = harmonics) highlight on and off ");
118
    theConsole.Printf("h   : (display.render_mode = harmonics) highlight on and off ");
118
    theConsole.Printf("+/- : (display.render_mode = harmonics) which eigenvector to show");
119
    theConsole.Printf("+/- : (display.render_mode = harmonics) which eigenvector to show");
119
    theConsole.Printf("q   : quit program");
120
    theConsole.Printf("q   : quit program");
120
    theConsole.Printf("ESC : open console");
121
    theConsole.Printf("ESC : open console");
121
    theConsole.Printf("");
122
    theConsole.Printf("");
122
    theConsole.Printf("Mouse: Left button rotates, middle zooms, right pans");
123
    theConsole.Printf("Mouse: Left button rotates, middle zooms, right pans");
123
    theConsole.Printf("----------------- HELP -----------------");
124
    theConsole.Printf("----------------- HELP -----------------");
124
    theConsole.Printf("");
125
    theConsole.Printf("");
125
    return "";
126
    return "";
126
}
127
}
127
 
128
 
128
bool wantshelp(std::vector<std::string> &args)
129
bool wantshelp(std::vector<std::string> &args)
129
{
130
{
130
	if(args.size()==0) return false;
131
	if(args.size()==0) return false;
131
	string str = args[0];
132
	string str = args[0];
132
	if(str=="help" || str=="HELP" || str=="Help" || str=="?") return true;
133
	if(str=="help" || str=="HELP" || str=="Help" || str=="?") return true;
133
	return false;
134
	return false;
134
}
135
}
135
 
136
 
136
/// Function that aligns two meshes.
137
/// Function that aligns two meshes.
137
char* console_align(std::vector<std::string> &args)
138
char* console_align(std::vector<std::string> &args)
138
{
139
{
139
	if(wantshelp(args)) 
140
	if(wantshelp(args)) 
140
	{
141
	{
141
		theConsole.Printf("usage: align <dest> <src>");
142
		theConsole.Printf("usage: align <dest> <src>");
142
		theConsole.Printf("This function aligns dest mesh with src");
143
		theConsole.Printf("This function aligns dest mesh with src");
143
		theConsole.Printf("In practice the GLViewController of src is copied to dst.");
144
		theConsole.Printf("In practice the GLViewController of src is copied to dst.");
144
		theConsole.Printf("both arguments are mandatory and must be numbers between 1 and 9.");
145
		theConsole.Printf("both arguments are mandatory and must be numbers between 1 and 9.");
145
		theConsole.Printf("Note that results might be unexpexted if the meshes are not on the same scale");
146
		theConsole.Printf("Note that results might be unexpexted if the meshes are not on the same scale");
146
		return "";
147
		return "";
147
	}
148
	}
148
	
149
	
149
	int dest = 0;
150
	int dest = 0;
150
	if(args.size()>0)
151
	if(args.size()>0)
151
	{
152
	{
152
		istringstream a0(args[0]);
153
		istringstream a0(args[0]);
153
		a0 >> dest;
154
		a0 >> dest;
154
		--dest;
155
		--dest;
155
		if(dest <0 || dest>8) return "dest mesh out of range (1-9)";
156
		if(dest <0 || dest>8) return "dest mesh out of range (1-9)";
156
	}
157
	}
157
	else return "neither source nor destination mesh?!";
158
	else return "neither source nor destination mesh?!";
158
	int src = 0;
159
	int src = 0;
159
	if(args.size()>1)
160
	if(args.size()>1)
160
	{
161
	{
161
		istringstream a1(args[1]);
162
		istringstream a1(args[1]);
162
		a1 >> src;
163
		a1 >> src;
163
		--src;
164
		--src;
164
		if(src <0 || src>8) return "src mesh out of range (1-9)";
165
		if(src <0 || src>8) return "src mesh out of range (1-9)";
165
	}	
166
	}	
166
	else return "no src mesh?";
167
	else return "no src mesh?";
167
	
168
	
168
	get_vis_obj(dest).view_control() = get_vis_obj(src).view_control();
169
	get_vis_obj(dest).view_control() = get_vis_obj(src).view_control();
169
	
170
	
170
	return "";
171
	return "";
171
}
172
}
172
 
173
 
-
 
174
char* console_flatten(std::vector<std::string> &args)
-
 
175
{
-
 
176
	if(wantshelp(args)) 
-
 
177
	{
-
 
178
		theConsole.Printf("usage: flatten <floater|harmonic|barycentric>");
-
 
179
		theConsole.Printf("This function flattens a meshs with a simple boundary. It is mostly for showing mesh");
-
 
180
		theConsole.Printf("parametrization methods. The current mesh MUST have a SINGLE boundary loop");
-
 
181
		theConsole.Printf("This loop is mapped to the unit circle in a regular fashion (equal angle intervals).");
-
 
182
		theConsole.Printf("All non boundary vertices are placed at the origin. Then the system is relaxed iteratively");
-
 
183
		theConsole.Printf("using the weight scheme given as argument.");
-
 
184
		return "";
-
 
185
	}
-
 
186
	enum WeightScheme {FLOATER_W, HARMONIC_W, BARYCENTRIC_W};
-
 
187
	WeightScheme ws = BARYCENTRIC_W;
-
 
188
	if(args.size()>0)
-
 
189
	{
-
 
190
		if(args[0] == "floater")
-
 
191
			ws = FLOATER_W;
-
 
192
		else if(args[0] == "harmonic")
-
 
193
			ws = HARMONIC_W;
-
 
194
	}
-
 
195
	else
-
 
196
		return "";
-
 
197
	
-
 
198
	active_mesh().enumerate_vertices();
-
 
199
	active_mesh().enumerate_halfedges();
-
 
200
	
-
 
201
	vector<float> edge_weights(active_mesh().no_halfedges());
-
 
202
	for(HalfEdgeIter h=active_mesh().halfedges_begin(); h != active_mesh().halfedges_end(); ++h)
-
 
203
		if(!is_boundary(h))
-
 
204
		{
-
 
205
			Vec3f p0 = h->vert->pos;
-
 
206
			Vec3f p1 = h->next->vert->pos;
-
 
207
			Vec3f p2 = h->opp->vert->pos;
-
 
208
			Vec3f p3 = h->opp->next->vert->pos;
-
 
209
			
-
 
210
			if(ws == FLOATER_W)
-
 
211
			{
-
 
212
				float d = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p0), normalize(p3-p0)))));
-
 
213
				float g = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p0), normalize(p1-p0)))));
-
 
214
				edge_weights[h->opp->touched]  = (tan(d/2) + tan(g/2)) / (p0-p2).length();
-
 
215
				
-
 
216
				
-
 
217
				d = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p2), normalize(p1-p2)))));
-
 
218
				g = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p2), normalize(p3-p2)))));
-
 
219
				edge_weights[h->touched]  = (tan(d/2) + tan(g/2)) / (p0-p2).length();
-
 
220
			}
-
 
221
			else if(ws == HARMONIC_W)
-
 
222
			{
-
 
223
				
-
 
224
				float a = acos(min(1.0f, max(-1.0f, dot(normalize(p0-p3), normalize(p2-p3)))));
-
 
225
				float b = acos(min(1.0f, max(-1.0f, dot(normalize(p2-p1), normalize(p0-p1)))));
-
 
226
				float w=0;
-
 
227
				if(a+b < M_PI)
-
 
228
					w = sin(a+b)/(sin(a)+sin(b));
-
 
229
				edge_weights[h->touched]  = w;
-
 
230
				edge_weights[h->opp->touched]  = w;
-
 
231
			}
-
 
232
			else
-
 
233
			{
-
 
234
				edge_weights[h->touched]  = valency(h->opp->vert);
-
 
235
				edge_weights[h->opp->touched]  = valency(h->vert);
-
 
236
			}	
-
 
237
		}
-
 
238
	
-
 
239
	ofstream ofs("parametrized.obj");
-
 
240
	
-
 
241
	ofs << "mtllib parametrized.mtl\nusemtl mat\n" << endl;
-
 
242
	
-
 
243
	VertexIter v;
-
 
244
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
-
 
245
		ofs << "v " << v->pos[0] << " " << v->pos[1] << " " << v->pos[2] << endl;
-
 
246
	ofs << endl;
-
 
247
	
-
 
248
	
-
 
249
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
-
 
250
	{
-
 
251
		if(is_boundary(v))
-
 
252
			break;
-
 
253
	}
-
 
254
	int n=0;
-
 
255
	VertexIter bv = v;
-
 
256
	do{
-
 
257
		++n;
-
 
258
		bv = bv->he->vert;
-
 
259
	}
-
 
260
	while(bv != v);
-
 
261
	
-
 
262
	int i=0;
-
 
263
	do{
-
 
264
		float a = 2.0*M_PI*float(i)/n;
-
 
265
		bv->pos = Vec3f(cos(a), sin(a), 0);
-
 
266
		++i;
-
 
267
		bv = bv->he->vert;
-
 
268
	}
-
 
269
	while(bv != v);
-
 
270
	
-
 
271
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
-
 
272
		if(!is_boundary(v))
-
 
273
			v->pos = Vec3f(0.0);
-
 
274
	
-
 
275
	for(int i=0;i<10000;++i)
-
 
276
		for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
-
 
277
			if(!is_boundary(v))
-
 
278
			{
-
 
279
				Vec3f p_new(0);
-
 
280
				float w_sum = 0;
-
 
281
				for(VertexCirculator vc(v); !vc.end(); ++vc)
-
 
282
				{
-
 
283
					float w = edge_weights[vc.get_halfedge()->touched];
-
 
284
					p_new += vc.get_vertex()->pos * w;
-
 
285
					w_sum += w;
-
 
286
				}
-
 
287
				v->pos = p_new/w_sum;
-
 
288
			}
-
 
289
	
-
 
290
	for(v=active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
-
 
291
		ofs << "vt " << (0.5*v->pos[0]+0.5) << " " << (0.5*v->pos[1]+0.5)  << endl;
-
 
292
	
-
 
293
	ofs << endl;
-
 
294
	
-
 
295
	for(FaceIter f = active_mesh().faces_begin(); f != active_mesh().faces_end(); ++f)
-
 
296
	{
-
 
297
		ofs << "f ";
-
 
298
		for(FaceCirculator fc(f); !fc.end(); ++fc)
-
 
299
		{
-
 
300
			int idx = fc.get_vertex()->touched + 1;
-
 
301
			ofs << idx << "/" << idx <<" ";
-
 
302
		}
-
 
303
		ofs << endl;
-
 
304
	}
-
 
305
	
-
 
306
	return "";
-
 
307
}
173
 
308
 
174
char* console_save(std::vector<std::string> &args)
309
char* console_save(std::vector<std::string> &args)
175
{
310
{
176
	if(wantshelp(args)) 
311
	if(wantshelp(args)) 
177
	{
312
	{
178
		theConsole.Printf("usage: save <name.x3d|name.obj> ");
313
		theConsole.Printf("usage: save <name.x3d|name.obj> ");
179
		return "";
314
		return "";
180
	}
315
	}
181
	string& file_name = args[0];
316
	string& file_name = args[0];
182
	if(args.size() == 1)
317
	if(args.size() == 1)
183
	{
318
	{
184
		if(file_name.substr(file_name.length()-4,file_name.length())==".obj")
319
		if(file_name.substr(file_name.length()-4,file_name.length())==".obj")
185
		{
320
		{
186
			obj_save(file_name, active_mesh());
321
			obj_save(file_name, active_mesh());
187
			return "";
322
			return "";
188
		}
323
		}
-
 
324
		else if(file_name.substr(file_name.length()-4,file_name.length())==".off")
-
 
325
		{
-
 
326
			off_save(file_name, active_mesh());
-
 
327
			return "";
-
 
328
		}
189
		else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d")
329
		else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d")
190
		{
330
		{
191
			x3d_save(file_name, active_mesh());
331
			x3d_save(file_name, active_mesh());
192
			return "";
332
			return "";
193
		}
333
		}
194
		return "unknown format";
334
		return "unknown format";
195
	}
335
	}
196
	return "usage: save <name.x3d|name.obj> ";
336
	return "usage: save <name.x3d|name.obj> ";
197
}
337
}
198
 
338
 
199
////////////////////////////////////////////////////////////////////////////////
339
////////////////////////////////////////////////////////////////////////////////
200
/**
340
/**
201
 */
341
 */
202
char* ConsoleSaveHistory( std::vector<std::string> &vArgs )
342
char* ConsoleSaveHistory( std::vector<std::string> &vArgs )
203
{
343
{
204
    if( vArgs.size() != 0 ) {
344
    if( vArgs.size() != 0 ) {
205
        theConsole.SaveHistory( vArgs[0] );
345
        theConsole.SaveHistory( vArgs[0] );
206
    }
346
    }
207
    else {
347
    else {
208
        theConsole.SaveHistory();
348
        theConsole.SaveHistory();
209
    }
349
    }
210
	return "";
350
	return "";
211
}
351
}
212
 
352
 
213
////////////////////////////////////////////////////////////////////////////////
353
////////////////////////////////////////////////////////////////////////////////
214
/**
354
/**
215
 */
355
 */
216
char* ConsoleLoadHistory( std::vector<std::string> &vArgs )
356
char* ConsoleLoadHistory( std::vector<std::string> &vArgs )
217
{
357
{
218
    if( vArgs.size() != 0 ) {
358
    if( vArgs.size() != 0 ) {
219
        theConsole.LoadHistory( vArgs[0] );
359
        theConsole.LoadHistory( vArgs[0] );
220
    }
360
    }
221
    else {
361
    else {
222
        theConsole.LoadHistory();
362
        theConsole.LoadHistory();
223
    }
363
    }
224
	return "";
364
	return "";
225
}
365
}
226
 
366
 
227
////////////////////////////////////////////////////////////////////////////////
367
////////////////////////////////////////////////////////////////////////////////
228
/**
368
/**
229
 */
369
 */
230
char* ConsoleClearHistory( std::vector<std::string> &vArgs )
370
char* ConsoleClearHistory( std::vector<std::string> &vArgs )
231
{
371
{
232
	theConsole.ClearHistory();
372
	theConsole.ClearHistory();
233
	return "";
373
	return "";
234
}
374
}
235
 
375
 
236
////////////////////////////////////////////////////////////////////////////////
376
////////////////////////////////////////////////////////////////////////////////
237
/**
377
/**
238
 */
378
 */
239
char* ConsoleStartScript( std::vector<std::string> &vArgs )
379
char* ConsoleStartScript( std::vector<std::string> &vArgs )
240
{
380
{
241
    theConsole.StartScript();
381
    theConsole.StartScript();
242
	return "";
382
	return "";
243
}
383
}
244
 
384
 
245
////////////////////////////////////////////////////////////////////////////////
385
////////////////////////////////////////////////////////////////////////////////
246
/**
386
/**
247
 */
387
 */
248
char* ConsoleStopScript( std::vector<std::string> &vArgs )
388
char* ConsoleStopScript( std::vector<std::string> &vArgs )
249
{
389
{
250
    theConsole.StopScript();
390
    theConsole.StopScript();
251
	return "";
391
	return "";
252
}
392
}
253
 
393
 
254
////////////////////////////////////////////////////////////////////////////////
394
////////////////////////////////////////////////////////////////////////////////
255
/**
395
/**
256
 */
396
 */
257
char* ConsoleShowScript( std::vector<std::string> &vArgs )
397
char* ConsoleShowScript( std::vector<std::string> &vArgs )
258
{
398
{
259
    theConsole.ShowScript();
399
    theConsole.ShowScript();
260
	return "";
400
	return "";
261
}
401
}
262
 
402
 
263
////////////////////////////////////////////////////////////////////////////////
403
////////////////////////////////////////////////////////////////////////////////
264
/**
404
/**
265
 */
405
 */
266
char* ConsoleRunScript( std::vector<std::string> &vArgs )
406
char* ConsoleRunScript( std::vector<std::string> &vArgs )
267
{
407
{
268
    theConsole.RunScript();
408
    theConsole.RunScript();
269
    return "";
409
    return "";
270
}
410
}
271
 
411
 
272
////////////////////////////////////////////////////////////////////////////////
412
////////////////////////////////////////////////////////////////////////////////
273
/**
413
/**
274
 */
414
 */
275
char* ConsoleSaveScript( std::vector<std::string> &vArgs )
415
char* ConsoleSaveScript( std::vector<std::string> &vArgs )
276
{
416
{
277
    if( vArgs.size() != 0 ) {
417
    if( vArgs.size() != 0 ) {
278
        theConsole.SaveScript( vArgs[0] );
418
        theConsole.SaveScript( vArgs[0] );
279
    }
419
    }
280
    else {
420
    else {
281
        theConsole.SaveScript();
421
        theConsole.SaveScript();
282
    }
422
    }
283
	return "";
423
	return "";
284
}
424
}
285
 
425
 
286
////////////////////////////////////////////////////////////////////////////////
426
////////////////////////////////////////////////////////////////////////////////
287
/**
427
/**
288
 */
428
 */
289
char* ConsoleLaunchScript( std::vector<std::string> &vArgs )
429
char* ConsoleLaunchScript( std::vector<std::string> &vArgs )
290
{
430
{
291
    if( vArgs.size() != 0 ) {
431
    if( vArgs.size() != 0 ) {
292
        theConsole.LaunchScript( vArgs[0] );
432
        theConsole.LaunchScript( vArgs[0] );
293
    } 
433
    } 
294
    else {
434
    else {
295
        theConsole.LaunchScript();
435
        theConsole.LaunchScript();
296
    }
436
    }
297
	return "";
437
	return "";
298
}
438
}
299
 
439
 
300
 
440
 
301
////////////////////////////////////////////////////////////////////////////////
441
////////////////////////////////////////////////////////////////////////////////
302
/**
442
/**
303
 */
443
 */
304
char* ConsoleLoad( std::vector<std::string> &vArgs )
444
char* ConsoleLoad( std::vector<std::string> &vArgs )
305
{
445
{
306
    std::string sFile = "cvars.xml";
446
    std::string sFile = "cvars.xml";
307
    std::vector< std::string > vAcceptedSubstrings;
447
    std::vector< std::string > vAcceptedSubstrings;
308
    
448
    
309
    if( vArgs.size() > 0 ) {
449
    if( vArgs.size() > 0 ) {
310
        sFile = vArgs[0]; 
450
        sFile = vArgs[0]; 
311
        for( size_t i=1; i<vArgs.size(); i++ ) {
451
        for( size_t i=1; i<vArgs.size(); i++ ) {
312
            vAcceptedSubstrings.push_back( vArgs[i] );
452
            vAcceptedSubstrings.push_back( vArgs[i] );
313
        }
453
        }
314
    }
454
    }
315
    theConsole.Printf("Loading file from \"%s\".", sFile.c_str() );
455
    theConsole.Printf("Loading file from \"%s\".", sFile.c_str() );
316
    if( !CVarUtils::Load( sFile, vAcceptedSubstrings) ) {
456
    if( !CVarUtils::Load( sFile, vAcceptedSubstrings) ) {
317
        theConsole.Printf( "Error loading file.\n" );
457
        theConsole.Printf( "Error loading file.\n" );
318
    }
458
    }
319
    return "";
459
    return "";
320
}
460
}
321
 
461
 
322
 
462
 
323
char* console_refine_edges(std::vector<std::string> &args)
463
char* console_refine_edges(std::vector<std::string> &args)
324
{
464
{
325
	if(wantshelp(args)) 
465
	if(wantshelp(args)) 
326
	{
466
	{
327
		theConsole.Printf("usage: refine.split_edges <length>");
467
		theConsole.Printf("usage: refine.split_edges <length>");
328
		theConsole.Printf("splits edges longer than <length>; default is 0.5 times average length");
468
		theConsole.Printf("splits edges longer than <length>; default is 0.5 times average length");
329
		return "";
469
		return "";
330
	}
470
	}
331
	
471
	
332
	float thresh = 0.5;
472
	float thresh = 0.5;
333
	if(args.size()>0)
473
	if(args.size()>0)
334
	{
474
	{
335
		istringstream a0(args[0]);
475
		istringstream a0(args[0]);
336
		a0 >> thresh;
476
		a0 >> thresh;
337
	}
477
	}
338
	float avg_length = average_edge_length(active_mesh());
478
	float avg_length = average_edge_length(active_mesh());
339
	refine_edges(active_mesh(), thresh * avg_length);
479
	refine_edges(active_mesh(), thresh * avg_length);
340
	return "";
480
	return "";
341
	
481
	
342
}
482
}
343
 
483
 
344
char* console_refine_faces(std::vector<std::string> &args)
484
char* console_refine_faces(std::vector<std::string> &args)
345
{
485
{
346
	if(wantshelp(args)) 
486
	if(wantshelp(args)) 
347
	{
487
	{
348
		theConsole.Printf("usage: refine.split_faces ");
488
		theConsole.Printf("usage: refine.split_faces ");
349
		theConsole.Printf("usage:  Takes no arguments. Inserts a vertex at the centre of each face.");
489
		theConsole.Printf("usage:  Takes no arguments. Inserts a vertex at the centre of each face.");
350
		return "";
490
		return "";
351
	}
491
	}
352
	
492
	
353
	safe_triangulate(active_mesh());
493
	safe_triangulate(active_mesh());
354
	return "";
494
	return "";
355
	
495
	
356
}
496
}
357
 
497
 
358
char* console_cc_subdivide(std::vector<std::string> &args)
498
char* console_cc_subdivide(std::vector<std::string> &args)
359
{
499
{
360
	if(wantshelp(args)) 
500
	if(wantshelp(args)) 
361
	{
501
	{
362
		theConsole.Printf("usage: refine.catmull_clark ");
502
		theConsole.Printf("usage: refine.catmull_clark ");
363
		theConsole.Printf("Splits each polygon into four (Catmull Clark style)");
503
		theConsole.Printf("Splits each polygon into four (Catmull Clark style)");
364
		return "";
504
		return "";
365
	}
505
	}
366
	cc_split(active_mesh(),active_mesh());
506
	cc_split(active_mesh(),active_mesh());
367
	return "";
507
	return "";
368
}
508
}
369
 
509
 
370
char* console_dual(std::vector<std::string> &args)
510
char* console_dual(std::vector<std::string> &args)
371
{
511
{
372
	if(wantshelp(args)) 
512
	if(wantshelp(args)) 
373
	{
513
	{
374
		theConsole.Printf("usage: dual ");
514
		theConsole.Printf("usage: dual ");
375
		theConsole.Printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
515
		theConsole.Printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
376
		return "";
516
		return "";
377
	}
517
	}
378
	
518
	
379
	Manifold& m = active_mesh();
519
	Manifold& m = active_mesh();
380
	
520
	
381
	// make sure every face knows its number
521
	// make sure every face knows its number
382
	m.enumerate_faces();
522
	m.enumerate_faces();
383
	
523
	
384
	vector<Vec3f> vertices(m.no_faces());
524
	vector<Vec3f> vertices(m.no_faces());
385
	vector<int> faces;
525
	vector<int> faces;
386
	vector<int> indices;
526
	vector<int> indices;
387
	
527
	
388
	// Create new vertices. Each face becomes a vertex whose position
528
	// Create new vertices. Each face becomes a vertex whose position
389
	// is the centre of the face
529
	// is the centre of the face
390
	int i=0;
530
	int i=0;
391
	for(FaceIter f=m.faces_begin(); f!=m.faces_end(); ++f,++i)
531
	for(FaceIter f=m.faces_begin(); f!=m.faces_end(); ++f,++i)
392
		vertices[i] = centre(f);
532
		vertices[i] = centre(f);
393
	
533
	
394
	// Create new faces. Each vertex is a new face with N=valency of vertex
534
	// Create new faces. Each vertex is a new face with N=valency of vertex
395
	// edges.
535
	// edges.
396
	i=0;
536
	i=0;
397
	for(VertexIter v=m.vertices_begin(); v!= m.vertices_end(); ++v,++i)
537
	for(VertexIter v=m.vertices_begin(); v!= m.vertices_end(); ++v,++i)
398
		if(!is_boundary(v))
538
		if(!is_boundary(v))
399
		{
539
		{
400
			VertexCirculator vc(v);
540
			VertexCirculator vc(v);
401
			vector<int> index_tmp;
541
			vector<int> index_tmp;
402
			for(; !vc.end(); ++vc)
542
			for(; !vc.end(); ++vc)
403
				index_tmp.push_back(vc.get_face()->touched);
543
				index_tmp.push_back(vc.get_face()->touched);
404
			
544
			
405
			// Push vertex indices for this face onto indices vector.
545
			// Push vertex indices for this face onto indices vector.
406
			// The circulator moves around the face in a clockwise fashion
546
			// The circulator moves around the face in a clockwise fashion
407
			// so we just reverse the ordering.
547
			// so we just reverse the ordering.
408
			indices.insert(indices.end(), index_tmp.rbegin(), index_tmp.rend());
548
			indices.insert(indices.end(), index_tmp.rbegin(), index_tmp.rend());
409
			
549
			
410
			// Insert face valency in the face vector.
550
			// Insert face valency in the face vector.
411
			faces.push_back(vc.no_steps());
551
			faces.push_back(vc.no_steps());
412
		}
552
		}
413
	
553
	
414
	// Clear the manifold before new geometry is inserted.
554
	// Clear the manifold before new geometry is inserted.
415
	m.clear();
555
	m.clear();
416
	
556
	
417
	// And build
557
	// And build
418
	build_manifold(m, vertices.size(), &vertices[0], faces.size(),
558
	build_manifold(m, vertices.size(), &vertices[0], faces.size(),
419
				   &faces[0],&indices[0]);
559
				   &faces[0],&indices[0]);
420
	
560
	
421
	return "";
561
	return "";
422
}
562
}
423
 
563
 
424
 
564
 
425
char* console_minimize_curvature(std::vector<std::string> &args)
565
char* console_minimize_curvature(std::vector<std::string> &args)
426
{
566
{
427
	if(wantshelp(args)) 
567
	if(wantshelp(args)) 
428
	{
568
	{
429
		theConsole.Printf("usage: optimize.minimize_curvature <anneal>");
569
		theConsole.Printf("usage: optimize.minimize_curvature <anneal>");
430
		theConsole.Printf("Flip edges to minimize mean curvature.");
570
		theConsole.Printf("Flip edges to minimize mean curvature.");
431
		theConsole.Printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
571
		theConsole.Printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
432
		return "";
572
		return "";
433
	}
573
	}
434
	bool anneal=false;
574
	bool anneal=false;
435
	if(args.size()>0)
575
	if(args.size()>0)
436
	{
576
	{
437
		istringstream a0(args[0]);
577
		istringstream a0(args[0]);
438
		a0 >> anneal;
578
		a0 >> anneal;
439
	}
579
	}
440
	
580
	
441
	minimize_curvature(active_mesh(), anneal);
581
	minimize_curvature(active_mesh(), anneal);
442
	avo().post_create_display_list();
582
	avo().post_create_display_list();
443
	return "";
583
	return "";
444
}
584
}
445
 
585
 
446
char* console_minimize_dihedral(std::vector<std::string> &args)
586
char* console_minimize_dihedral(std::vector<std::string> &args)
447
{
587
{
448
	if(wantshelp(args)) 
588
	if(wantshelp(args)) 
449
	{
589
	{
450
		theConsole.Printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
590
		theConsole.Printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
451
		theConsole.Printf("Flip edges to minimize dihedral angles.");
591
		theConsole.Printf("Flip edges to minimize dihedral angles.");
452
		theConsole.Printf("Iter is the max number of iterations. anneal tells us whether to use ");
592
		theConsole.Printf("Iter is the max number of iterations. anneal tells us whether to use ");
453
		theConsole.Printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
593
		theConsole.Printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
454
		theConsole.Printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
594
		theConsole.Printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
455
		theConsole.Printf("to which we raise the dihedral angle");
595
		theConsole.Printf("to which we raise the dihedral angle");
456
		return "";
596
		return "";
457
	}
597
	}
458
	int iter = 1000;
598
	int iter = 1000;
459
	if(args.size()>0)
599
	if(args.size()>0)
460
	{
600
	{
461
		istringstream a0(args[0]);
601
		istringstream a0(args[0]);
462
		a0 >> iter;
602
		a0 >> iter;
463
	}
603
	}
464
	
604
	
465
	bool anneal = false;
605
	bool anneal = false;
466
	if(args.size()>1)
606
	if(args.size()>1)
467
	{
607
	{
468
		istringstream a0(args[0]);
608
		istringstream a0(args[0]);
469
		a0 >> anneal;
609
		a0 >> anneal;
470
	}
610
	}
471
	
611
	
472
	bool use_alpha = true;
612
	bool use_alpha = true;
473
	if(args.size()>2)
613
	if(args.size()>2)
474
	{
614
	{
475
		istringstream a0(args[0]);
615
		istringstream a0(args[0]);
476
		a0 >> use_alpha;
616
		a0 >> use_alpha;
477
	}
617
	}
478
	
618
	
479
	float gamma = 4.0;
619
	float gamma = 4.0;
480
	if(args.size()>3)
620
	if(args.size()>3)
481
	{
621
	{
482
		istringstream a0(args[0]);
622
		istringstream a0(args[0]);
483
		a0 >> gamma;
623
		a0 >> gamma;
484
	}
624
	}
485
	
625
	
486
	
626
	
487
	minimize_dihedral_angle(active_mesh(), iter, anneal, use_alpha, gamma);
627
	minimize_dihedral_angle(active_mesh(), iter, anneal, use_alpha, gamma);
488
	return "";
628
	return "";
489
}
629
}
490
 
630
 
491
char* console_maximize_min_angle(std::vector<std::string> &args)
631
char* console_maximize_min_angle(std::vector<std::string> &args)
492
{
632
{
493
	if(wantshelp(args)) 
633
	if(wantshelp(args)) 
494
	{
634
	{
495
		theConsole.Printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
635
		theConsole.Printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
496
		theConsole.Printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
636
		theConsole.Printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
497
		theConsole.Printf("If the dot product of the normals between adjacent faces < thresh");
637
		theConsole.Printf("If the dot product of the normals between adjacent faces < thresh");
498
		theConsole.Printf("no flip will be made. anneal selects simulated annealing rather ");
638
		theConsole.Printf("no flip will be made. anneal selects simulated annealing rather ");
499
		theConsole.Printf("nthan greedy optimization.");
639
		theConsole.Printf("nthan greedy optimization.");
500
		return "";
640
		return "";
501
	}
641
	}
502
	float thresh=0.0;
642
	float thresh=0.0;
503
	if(args.size()>0)
643
	if(args.size()>0)
504
	{
644
	{
505
		istringstream a0(args[0]);
645
		istringstream a0(args[0]);
506
		a0 >> thresh;
646
		a0 >> thresh;
507
	}
647
	}
508
	bool anneal=false;
648
	bool anneal=false;
509
	if(args.size()>1)
649
	if(args.size()>1)
510
	{
650
	{
511
		istringstream a0(args[0]);
651
		istringstream a0(args[0]);
512
		a0 >> anneal;
652
		a0 >> anneal;
513
	}
653
	}
514
	maximize_min_angle(active_mesh(),thresh,anneal);
654
	maximize_min_angle(active_mesh(),thresh,anneal);
515
	return "";
655
	return "";
516
}
656
}
517
 
657
 
518
 
658
 
519
char* console_optimize_valency(std::vector<std::string> &args)
659
char* console_optimize_valency(std::vector<std::string> &args)
520
{
660
{
521
	if(wantshelp(args)) 
661
	if(wantshelp(args)) 
522
	{
662
	{
523
		theConsole.Printf("usage: optimize.valency <anneal> ");
663
		theConsole.Printf("usage: optimize.valency <anneal> ");
524
		theConsole.Printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
664
		theConsole.Printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
525
		return "";
665
		return "";
526
	}
666
	}
527
	bool anneal=false;
667
	bool anneal=false;
528
	if(args.size()>0)
668
	if(args.size()>0)
529
	{
669
	{
530
		istringstream a0(args[0]);
670
		istringstream a0(args[0]);
531
		a0 >> anneal;
671
		a0 >> anneal;
532
	}
672
	}
533
	optimize_valency(active_mesh(), anneal);
673
	optimize_valency(active_mesh(), anneal);
534
	return "";
674
	return "";
535
}
675
}
536
 
676
 
537
char* console_analyze(std::vector<std::string> &args)
677
char* console_analyze(std::vector<std::string> &args)
538
{
678
{
539
	if(wantshelp(args)) 
679
	if(wantshelp(args)) 
540
	{
680
	{
541
		theConsole.Printf("usage:  harmonics.analyze");
681
		theConsole.Printf("usage:  harmonics.analyze");
542
		theConsole.Printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
682
		theConsole.Printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
543
		theConsole.Printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
683
		theConsole.Printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
544
		theConsole.Printf("to this basis.");
684
		theConsole.Printf("to this basis.");
545
		theConsole.Printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
685
		theConsole.Printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
546
		return "";
686
		return "";
547
	}
687
	}
548
	avo().harmonics_analyze_mesh();
688
	avo().harmonics_analyze_mesh();
549
	return "";
689
	return "";
550
}
690
}
551
 
691
 
552
 
692
 
553
char* console_partial_reconstruct(std::vector<std::string> &args)
693
char* console_partial_reconstruct(std::vector<std::string> &args)
554
{
694
{
555
  if(args.size() != 3)
695
	if(args.size() != 3)
556
		theConsole.Printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
696
		theConsole.Printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
557
 
697
	
558
  if(wantshelp(args)) 
698
	if(wantshelp(args)) 
559
	{
699
	{
560
		theConsole.Printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
700
		theConsole.Printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
561
		theConsole.Printf("the eigenvector interval that we reconstruct from. The last argument is the ");
701
		theConsole.Printf("the eigenvector interval that we reconstruct from. The last argument is the ");
562
		theConsole.Printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
702
		theConsole.Printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
563
		theConsole.Printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
703
		theConsole.Printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
564
		theConsole.Printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
704
		theConsole.Printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
565
		theConsole.Printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
705
		theConsole.Printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
566
		theConsole.Printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
706
		theConsole.Printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
567
	}
707
	}
568
 
708
	
569
  if(args.size() != 3)
709
	if(args.size() != 3)
570
		return "";
710
		return "";
571
 
711
	
572
  int E0,E1;
712
	int E0,E1;
573
	float scale;
713
	float scale;
574
	istringstream a0(args[0]);
714
	istringstream a0(args[0]);
575
	a0 >> E0;
715
	a0 >> E0;
576
	istringstream a1(args[1]);
716
	istringstream a1(args[1]);
577
	a1 >> E1;
717
	a1 >> E1;
578
	istringstream a2(args[2]);
718
	istringstream a2(args[2]);
579
	a2 >> scale;
719
	a2 >> scale;
580
	avo().harmonics_partial_reconstruct(E0,E1,scale);
720
	avo().harmonics_partial_reconstruct(E0,E1,scale);
581
	return "";
721
	return "";
582
}
722
}
583
 
723
 
584
char* console_reset_shape(std::vector<std::string> &args)
724
char* console_reset_shape(std::vector<std::string> &args)
585
{
725
{
586
	if(wantshelp(args)) 
726
	if(wantshelp(args)) 
587
	{
727
	{
588
		theConsole.Printf("usage: harmonics.reset_shape ");
728
		theConsole.Printf("usage: harmonics.reset_shape ");
589
		theConsole.Printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
729
		theConsole.Printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
590
		theConsole.Printf("unless you know what you are doing.");
730
		theConsole.Printf("unless you know what you are doing.");
591
		return "";
731
		return "";
592
	}
732
	}
593
	avo().harmonics_reset_shape();
733
	avo().harmonics_reset_shape();
594
	return "";
734
	return "";
595
}
735
}
596
 
736
 
597
 
737
 
598
char* console_close_holes(std::vector<std::string> &args)
738
char* console_close_holes(std::vector<std::string> &args)
599
{
739
{
600
	if(wantshelp(args)) 
740
	if(wantshelp(args)) 
601
	{
741
	{
602
		theConsole.Printf("usage: cleanup.close_holes");
742
		theConsole.Printf("usage: cleanup.close_holes");
603
		theConsole.Printf("This function closes holes. It simply follows the loop of halfvectors which");
743
		theConsole.Printf("This function closes holes. It simply follows the loop of halfvectors which");
604
		theConsole.Printf("enclose the hole and add a face to which they all point.");
744
		theConsole.Printf("enclose the hole and add a face to which they all point.");
605
		return "";
745
		return "";
606
	}
746
	}
607
	close_holes(active_mesh());
747
	close_holes(active_mesh());
608
	return "";
748
	return "";
609
}
749
}
610
 
750
 
611
char* console_reload(std::vector<std::string> &args)
751
char* console_reload(std::vector<std::string> &args)
612
{
752
{
613
	if(wantshelp(args)) 
753
	if(wantshelp(args)) 
614
	{
754
	{
615
		theConsole.Printf("usage:  load <file>");
755
		theConsole.Printf("usage:  load <file>");
616
		theConsole.Printf("(Re)loads the current file if no argument is given, but");
756
		theConsole.Printf("(Re)loads the current file if no argument is given, but");
617
		theConsole.Printf("if an argument is given, then that becomes the current file");
757
		theConsole.Printf("if an argument is given, then that becomes the current file");
618
		return "";
758
		return "";
619
	}
759
	}
620
	if(!avo().reload(args.size()>0 ? args[0]:""))
760
	if(!avo().reload(args.size()>0 ? args[0]:""))
621
		return "failed to load";
761
		return "failed to load";
622
	return "";
762
	return "";
623
}
763
}
624
 
764
 
625
 
765
 
626
char* console_simplify(std::vector<std::string> &args)
766
char* console_simplify(std::vector<std::string> &args)
627
{
767
{
628
	if(wantshelp(args)) 
768
	if(wantshelp(args)) 
629
	{
769
	{
630
		theConsole.Printf("usage: simplify <fraction> ");
770
		theConsole.Printf("usage: simplify <fraction> ");
631
		theConsole.Printf("Performs Garland Heckbert (quadric based) mesh simplification.");
771
		theConsole.Printf("Performs Garland Heckbert (quadric based) mesh simplification.");
632
		theConsole.Printf("The only argument is the fraction of vertices to keep.");
772
		theConsole.Printf("The only argument is the fraction of vertices to keep.");
633
		return "";
773
		return "";
634
	}
774
	}
635
	float keep_fraction;
775
	float keep_fraction;
636
	if(args.size()==0) return "you must specify fraction of vertices to keep";
776
	if(args.size()==0) return "you must specify fraction of vertices to keep";
637
	istringstream a0(args[0]);
777
	istringstream a0(args[0]);
638
	a0 >> keep_fraction;
778
	a0 >> keep_fraction;
639
	
779
	
640
	Vec3f p0, p7;
780
	Vec3f p0, p7;
641
	active_mesh().get_bbox(p0, p7);
781
	active_mesh().get_bbox(p0, p7);
642
	Vec3f d = p7-p0;
782
	Vec3f d = p7-p0;
643
	float s = 1.0/d.max_coord();
783
	float s = 1.0/d.max_coord();
644
	Vec3f pcentre = (p7+p0)/2.0;
784
	Vec3f pcentre = (p7+p0)/2.0;
645
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
785
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
646
		vi->pos = (vi->pos - pcentre) * s;
786
		vi->pos = (vi->pos - pcentre) * s;
647
	quadric_simplify(active_mesh(),keep_fraction,0.0001f,true);
787
	quadric_simplify(active_mesh(),keep_fraction,0.0001f,true);
648
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
788
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
649
		vi->pos = vi->pos*d.max_coord() + pcentre;
789
		vi->pos = vi->pos*d.max_coord() + pcentre;
650
	return "";
790
	return "";
651
}
791
}
652
 
792
 
653
char* console_vertex_noise(std::vector<std::string> &args)
793
char* console_vertex_noise(std::vector<std::string> &args)
654
{
794
{
655
	if(wantshelp(args)) 
795
	if(wantshelp(args)) 
656
	{
796
	{
657
		theConsole.Printf("usage: noise.perturb_vertices <amplitude>");
797
		theConsole.Printf("usage: noise.perturb_vertices <amplitude>");
658
		theConsole.Printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
798
		theConsole.Printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
659
		theConsole.Printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
799
		theConsole.Printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
660
		theConsole.Printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
800
		theConsole.Printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
661
		theConsole.Printf("If no amplitude is specified, the default (0.5) is used.");
801
		theConsole.Printf("If no amplitude is specified, the default (0.5) is used.");
662
		return "";
802
		return "";
663
	}
803
	}
664
	float avg_length = average_edge_length(active_mesh());
804
	float avg_length = average_edge_length(active_mesh());
665
	
805
	
666
	float noise_amplitude = 0.5;
806
	float noise_amplitude = 0.5;
667
	if(args.size()>0) 
807
	if(args.size()>0) 
668
	{
808
	{
669
		istringstream a0(args[0]);
809
		istringstream a0(args[0]);
670
		a0 >> noise_amplitude;
810
		a0 >> noise_amplitude;
671
	}
811
	}
672
	
812
	
673
	gel_srand(0);
813
	gel_srand(0);
674
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
814
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
675
	{
815
	{
676
		Vec3f v;
816
		Vec3f v;
677
		do {
817
		do {
678
			v = Vec3f(gel_rand(),gel_rand(),gel_rand());
818
			v = Vec3f(gel_rand(),gel_rand(),gel_rand());
679
			v /= GEL_RAND_MAX;
819
			v /= GEL_RAND_MAX;
680
		} while(sqr_length(v) > 1.0);
820
		} while(sqr_length(v) > 1.0);
681
		v -= Vec3f(0.5);
821
		v -= Vec3f(0.5);
682
		v *= 2.0;
822
		v *= 2.0;
683
		v *= noise_amplitude;
823
		v *= noise_amplitude;
684
		v *= avg_length;
824
		v *= avg_length;
685
		vi->pos += v;
825
		vi->pos += v;
686
	}		
826
	}		
687
	return "";
827
	return "";
688
}
828
}
689
 
829
 
690
char* console_perpendicular_vertex_noise(std::vector<std::string> &args)
830
char* console_perpendicular_vertex_noise(std::vector<std::string> &args)
691
{
831
{
692
	if(wantshelp(args)) 
832
	if(wantshelp(args)) 
693
	{
833
	{
694
		theConsole.Printf("usage: noise.perturb_vertices_perpendicular <amplitude>");
834
		theConsole.Printf("usage: noise.perturb_vertices_perpendicular <amplitude>");
695
		theConsole.Printf("adds the normal times a random scalar times amplitude times");
835
		theConsole.Printf("adds the normal times a random scalar times amplitude times");
696
		theConsole.Printf("times average edge length to the vertex. (default amplitude=0.5)");
836
		theConsole.Printf("times average edge length to the vertex. (default amplitude=0.5)");
697
		return "";
837
		return "";
698
	}
838
	}
699
	float avg_length = average_edge_length(active_mesh());
839
	float avg_length = average_edge_length(active_mesh());
700
	
840
	
701
	float noise_amplitude = 0.5;
841
	float noise_amplitude = 0.5;
702
	if(args.size()>0) 
842
	if(args.size()>0) 
703
	{
843
	{
704
		istringstream a0(args[0]);
844
		istringstream a0(args[0]);
705
		a0 >> noise_amplitude;
845
		a0 >> noise_amplitude;
706
	}
846
	}
707
	
847
	
708
	vector<Vec3f> normals(active_mesh().no_vertices());
848
	vector<Vec3f> normals(active_mesh().no_vertices());
709
	int i=0;
849
	int i=0;
710
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
850
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
711
		normals[i] = normal(vi);
851
		normals[i] = normal(vi);
712
	i=0;
852
	i=0;
713
	gel_srand(0);
853
	gel_srand(0);
714
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
854
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi,++i)
715
	{
855
	{
716
		float rval = 0.5-gel_rand()/float(GEL_RAND_MAX);
856
		float rval = 0.5-gel_rand()/float(GEL_RAND_MAX);
717
		vi->pos += normals[i]*rval*noise_amplitude*avg_length*2.0;
857
		vi->pos += normals[i]*rval*noise_amplitude*avg_length*2.0;
718
	}
858
	}
719
	return "";
859
	return "";
720
}
860
}
721
 
861
 
722
char* console_noisy_flips(std::vector<std::string> &args)
862
char* console_noisy_flips(std::vector<std::string> &args)
723
{
863
{
724
	if(wantshelp(args)) 
864
	if(wantshelp(args)) 
725
	{
865
	{
726
		theConsole.Printf("usage:  noise.perturb_topology <iter>");
866
		theConsole.Printf("usage:  noise.perturb_topology <iter>");
727
		theConsole.Printf("Perform random flips. iter (default=1) is the number of iterations.");
867
		theConsole.Printf("Perform random flips. iter (default=1) is the number of iterations.");
728
		theConsole.Printf("mostly for making nasty synthetic test cases.");
868
		theConsole.Printf("mostly for making nasty synthetic test cases.");
729
		return "";
869
		return "";
730
	}
870
	}
731
	int iter=1;
871
	int iter=1;
732
	if(args.size()>0)
872
	if(args.size()>0)
733
	{
873
	{
734
		istringstream a0(args[0]);
874
		istringstream a0(args[0]);
735
		a0 >> iter;
875
		a0 >> iter;
736
	}
876
	}
737
	
877
	
738
	randomize_mesh(active_mesh(),  iter);
878
	randomize_mesh(active_mesh(),  iter);
739
	return "";
879
	return "";
740
}
880
}
741
 
881
 
742
char* console_laplacian_smooth(std::vector<std::string> &args)
882
char* console_laplacian_smooth(std::vector<std::string> &args)
743
{
883
{
744
	if(wantshelp(args)) 
884
	if(wantshelp(args)) 
745
	{
885
	{
746
		theConsole.Printf("usage:  smooth.laplacian <weight> <iter>");
886
		theConsole.Printf("usage:  smooth.laplacian <weight> <iter>");
747
		theConsole.Printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
887
		theConsole.Printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
748
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
888
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
749
		return "";
889
		return "";
750
	}
890
	}
751
	float t=1.0;
891
	float t=1.0;
752
	if(args.size()>0)
892
	if(args.size()>0)
753
	{
893
	{
754
		istringstream a0(args[0]);
894
		istringstream a0(args[0]);
755
		a0 >> t;
895
		a0 >> t;
756
	}
896
	}
757
	int iter=1;
897
	int iter=1;
758
	if(args.size()>1)
898
	if(args.size()>1)
759
	{
899
	{
760
		istringstream a0(args[1]);
900
		istringstream a0(args[1]);
761
		a0 >> iter;
901
		a0 >> iter;
762
	}
902
	}
763
	
903
	
764
	/// Simple laplacian smoothing with an optional weight.
904
	/// Simple laplacian smoothing with an optional weight.
765
	for(int i=0;i<iter;++i) laplacian_smooth(active_mesh(), t);
905
	for(int i=0;i<iter;++i) laplacian_smooth(active_mesh(), t);
766
	return "";
906
	return "";
767
}
907
}
768
 
908
 
769
char* console_mean_curvature_smooth(std::vector<std::string> &args)
909
char* console_mean_curvature_smooth(std::vector<std::string> &args)
770
{
910
{
771
	if(wantshelp(args)) 
911
	if(wantshelp(args)) 
772
	{
912
	{
773
		theConsole.Printf("usage:  smooth.mean_curvature <weight> <iter>");
913
		theConsole.Printf("usage:  smooth.mean_curvature <weight> <iter>");
774
		theConsole.Printf("Perform mean curvature smoothing. weight is the scaling factor for the");
914
		theConsole.Printf("Perform mean curvature smoothing. weight is the scaling factor for the");
775
		theConsole.Printf("mean curvature vector which has been normalized by dividing by edge lengths");
915
		theConsole.Printf("mean curvature vector which has been normalized by dividing by edge lengths");
776
		theConsole.Printf("this allows for larger steps as suggested by Desbrun et al.");
916
		theConsole.Printf("this allows for larger steps as suggested by Desbrun et al.");
777
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
917
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
778
		return "";
918
		return "";
779
	}
919
	}
780
	float t=1.0;
920
	float t=1.0;
781
	if(args.size()>0)
921
	if(args.size()>0)
782
	{
922
	{
783
		istringstream a0(args[0]);
923
		istringstream a0(args[0]);
784
		a0 >> t;
924
		a0 >> t;
785
	}
925
	}
786
	int iter=1;
926
	int iter=1;
787
	if(args.size()>1)
927
	if(args.size()>1)
788
	{
928
	{
789
		istringstream a0(args[1]);
929
		istringstream a0(args[1]);
790
		a0 >> iter;
930
		a0 >> iter;
791
	}	
931
	}	
792
	vector<Vec3d> new_pos(active_mesh().no_vertices());
932
	vector<Vec3d> new_pos(active_mesh().no_vertices());
793
	for(int j=0;j<iter;++j)
933
	for(int j=0;j<iter;++j)
794
	{
934
	{
795
		int i=0;
935
		int i=0;
796
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i) {
936
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i) {
797
			Vec3d m;
937
			Vec3d m;
798
			double w_sum;
938
			double w_sum;
799
			unnormalized_mean_curvature_normal(v, m, w_sum);
939
			unnormalized_mean_curvature_normal(v, m, w_sum);
800
			new_pos[i] = Vec3d(v->pos)  - (t * m/w_sum);
940
			new_pos[i] = Vec3d(v->pos)  - (t * m/w_sum);
801
		}
941
		}
802
		i=0;
942
		i=0;
803
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i)
943
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i)
804
			v->pos = Vec3f(new_pos[i]);
944
			v->pos = Vec3f(new_pos[i]);
805
	}
945
	}
806
	return "";
946
	return "";
807
}
947
}
808
 
948
 
-
 
949
const double angle_defect(VertexIter v)
-
 
950
{
-
 
951
	if(!is_boundary(v))
-
 
952
	{
-
 
953
		Vec3f vertex(v->pos);
-
 
954
		vector<Vec3d> edges;
-
 
955
		for(VertexCirculator vc(v); !vc.end(); ++vc)
-
 
956
		{
-
 
957
			Vec3d e(normalize(vc.get_vertex()->pos-vertex));
-
 
958
			edges.push_back(e);
-
 
959
		}
-
 
960
		int N=edges.size();
-
 
961
		double angle_sum = 0;
-
 
962
		for(int i=0;i<N;++i)
-
 
963
		{
-
 
964
			double dot_prod = 
-
 
965
			s_max(-1.0, s_min(1.0, dot(edges[i],edges[(i+1)%N])));
-
 
966
			angle_sum += acos(dot_prod);
-
 
967
		}
-
 
968
		return fabs(2*M_PI - angle_sum);
-
 
969
	}
-
 
970
	return 1000;
-
 
971
}
-
 
972
 
-
 
973
char* console_experimental_smooth(std::vector<std::string> &args)
-
 
974
{
-
 
975
	if(wantshelp(args)) 
-
 
976
	{
-
 
977
		theConsole.Printf("usage:  smooth.experimental <weight> <iter>");
-
 
978
		theConsole.Printf("Perform experimental smoothing. weight is the scaling factor for the");
-
 
979
		theConsole.Printf("experimetnal vector which has been normalized by dividing by edge lengths");
-
 
980
		theConsole.Printf("this allows for larger steps as suggested by Desbrun et al.");
-
 
981
		theConsole.Printf("default weight = 1.0. Default number of iterations = 1");
-
 
982
		return "";
-
 
983
	}
-
 
984
	float t=1.0;
-
 
985
	if(args.size()>0)
-
 
986
	{
-
 
987
		istringstream a0(args[0]);
-
 
988
		a0 >> t;
-
 
989
	}
-
 
990
	int iter=1;
-
 
991
	if(args.size()>1)
-
 
992
	{
-
 
993
		istringstream a0(args[1]);
-
 
994
		a0 >> iter;
-
 
995
	}	
-
 
996
	
-
 
997
	Vec3f p0_before, p7_before;
-
 
998
	active_mesh().get_bbox(p0_before, p7_before);
-
 
999
 
-
 
1000
	double avg_area=0.0;
-
 
1001
	for(FaceIter f=active_mesh().faces_begin(); f != active_mesh().faces_end(); ++f)
-
 
1002
		avg_area += area(f);
-
 
1003
	avg_area /= active_mesh().no_faces();
-
 
1004
		
-
 
1005
	for(int j=0;j<iter;++j)
-
 
1006
	{
-
 
1007
		
-
 
1008
		vector<Vec3d> new_pos(active_mesh().no_vertices());
-
 
1009
 
-
 
1010
		int i=0;
-
 
1011
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i) 
-
 
1012
			{
-
 
1013
				double w_sum=0;
-
 
1014
				Vec3d m(0);
-
 
1015
				VertexCirculator vc(v);
-
 
1016
				for(; !vc.end(); ++vc)
-
 
1017
				{
-
 
1018
					HalfEdgeIter h = vc.get_halfedge();
-
 
1019
					double area_left  = area(h->face);
-
 
1020
					double area_right = area(h->opp->face);
-
 
1021
					
-
 
1022
					double w = 0.5 * (area_left + area_right);
-
 
1023
					m += w * Vec3d(vc.get_vertex()->pos-v->pos);
-
 
1024
					w_sum += w;
-
 
1025
				}
-
 
1026
				double t2 = pow((w_sum/vc.no_steps())/avg_area,.25);
-
 
1027
				if(t2 > 1e-10)
-
 
1028
					new_pos[i] = Vec3d(v->pos)  + (t * t2 * m/w_sum);
-
 
1029
			}
-
 
1030
		i=0;
-
 
1031
		for(VertexIter v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v,++i)
-
 
1032
			v->pos = Vec3f(new_pos[i]);
-
 
1033
		
-
 
1034
		active_mesh().delayed_erase();
-
 
1035
		for(HalfEdgeIter h=active_mesh().halfedges_begin(); h!=active_mesh().halfedges_end(); ++h)
-
 
1036
			if(active_mesh().is_used(h))
-
 
1037
		{
-
 
1038
			Vec3d mcna,mcnb;
-
 
1039
			double ws;
-
 
1040
			
-
 
1041
			unnormalized_mean_curvature_normal(h->vert, mcna, ws);
-
 
1042
			unnormalized_mean_curvature_normal(h->opp->vert, mcnb, ws);
-
 
1043
			if(sqr_length(mcna) < 1 && sqr_length(mcnb) < 1)
-
 
1044
				if(active_mesh().collapse_precond(h))
-
 
1045
				{
-
 
1046
					active_mesh().collapse_halfedge(h, false);
-
 
1047
				}
-
 
1048
		}
-
 
1049
		active_mesh().immediate_erase();
-
 
1050
		maximize_min_angle(active_mesh(), 0.95, false);
-
 
1051
	}
-
 
1052
	
-
 
1053
	Vec3f p0, p7;
-
 
1054
	active_mesh().get_bbox(p0, p7);
-
 
1055
	for(VertexIter vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
-
 
1056
		vi->pos = (p7_before-p0_before)*(vi->pos - p0)/(p7-p0)+p0_before;
-
 
1057
	
-
 
1058
	return "";
-
 
1059
}
-
 
1060
 
809
 
1061
 
810
char* console_taubin_smooth(std::vector<std::string> &args)
1062
char* console_taubin_smooth(std::vector<std::string> &args)
811
{
1063
{
812
	if(wantshelp(args)) 
1064
	if(wantshelp(args)) 
813
	{
1065
	{
814
		theConsole.Printf("usage:  smooth.taubin <iter>");
1066
		theConsole.Printf("usage:  smooth.taubin <iter>");
815
		theConsole.Printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
1067
		theConsole.Printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
816
		return "";
1068
		return "";
817
	}
1069
	}
818
	int iter=1;
1070
	int iter=1;
819
	if(args.size()>0)
1071
	if(args.size()>0)
820
	{
1072
	{
821
		istringstream a0(args[0]);
1073
		istringstream a0(args[0]);
822
		a0 >> iter;
1074
		a0 >> iter;
823
	}
1075
	}
824
	
1076
	
825
	/// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
1077
	/// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
826
	taubin_smooth(active_mesh(),  iter);
1078
	taubin_smooth(active_mesh(),  iter);
827
	return "";
1079
	return "";
828
}
1080
}
829
 
1081
 
830
char* console_fvm_smooth(std::vector<std::string> &args)
1082
char* console_fvm_smooth(std::vector<std::string> &args)
831
{	
1083
{	
832
	if(wantshelp(args)) 
1084
	if(wantshelp(args)) 
833
	{
1085
	{
834
		theConsole.Printf("usage: smooth.fuzzy_vector_median <iter>");
1086
		theConsole.Printf("usage: smooth.fuzzy_vector_median <iter>");
835
		theConsole.Printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
1087
		theConsole.Printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
836
		theConsole.Printf("This function does a very good job of preserving sharp edges.");
1088
		theConsole.Printf("This function does a very good job of preserving sharp edges.");
837
		return "";
1089
		return "";
838
	}
1090
	}
839
	int iter=1;
1091
	int iter=1;
840
	if(args.size()>0)
1092
	if(args.size()>0)
841
	{
1093
	{
842
		istringstream a0(args[0]);
1094
		istringstream a0(args[0]);
843
		a0 >> iter;
1095
		a0 >> iter;
844
	}
1096
	}
845
	/** Fuzzy vector median smoothing is effective when it comes to
1097
	/** Fuzzy vector median smoothing is effective when it comes to
846
	 preserving sharp edges. */
1098
	 preserving sharp edges. */
847
	fvm_smooth(active_mesh(),  iter);
1099
	fvm_smooth(active_mesh(),  iter);
848
	return "";
1100
	return "";
849
	
1101
	
850
}
1102
}
851
 
1103
 
852
char* console_triangulate(std::vector<std::string> &args)
1104
char* console_triangulate(std::vector<std::string> &args)
853
{	
1105
{	
854
	if(wantshelp(args)) 
1106
	if(wantshelp(args)) 
855
	{
1107
	{
856
		theConsole.Printf("usage:  triangulate");
1108
		theConsole.Printf("usage:  triangulate");
857
		theConsole.Printf("This function triangulates all non triangular faces of the mesh.");
1109
		theConsole.Printf("This function triangulates all non triangular faces of the mesh.");
858
		theConsole.Printf("you may want to call it after hole closing. For a polygon it simply connects");
1110
		theConsole.Printf("you may want to call it after hole closing. For a polygon it simply connects");
859
		theConsole.Printf("the two closest vertices in a recursive manner until only triangles remain");
1111
		theConsole.Printf("the two closest vertices in a recursive manner until only triangles remain");
860
		return "";
1112
		return "";
861
	}
1113
	}
862
	shortest_edge_triangulate(active_mesh());
1114
	shortest_edge_triangulate(active_mesh());
863
	return "";
1115
	return "";
864
}
1116
}
865
 
1117
 
866
 
1118
 
867
char* console_remove_caps(std::vector<std::string> &args)
1119
char* console_remove_caps(std::vector<std::string> &args)
868
{	
1120
{	
869
	if(wantshelp(args)) 
1121
	if(wantshelp(args)) 
870
	{
1122
	{
871
		theConsole.Printf("usage:  cleanup.remove_caps thresh");
1123
		theConsole.Printf("usage:  cleanup.remove_caps thresh");
872
		theConsole.Printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
1124
		theConsole.Printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
873
		theConsole.Printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
1125
		theConsole.Printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
874
		return "";
1126
		return "";
875
	}
1127
	}
876
	float t=0.85;
1128
	float t=0.85;
877
	if(args.size()>0)
1129
	if(args.size()>0)
878
	{
1130
	{
879
		istringstream a0(args[0]);
1131
		istringstream a0(args[0]);
880
		a0 >> t;
1132
		a0 >> t;
881
	}
1133
	}
882
	
1134
	
883
	remove_caps_from_trimesh(active_mesh(), static_cast<float>(M_PI) *t);
1135
	remove_caps_from_trimesh(active_mesh(), static_cast<float>(M_PI) *t);
884
	return "";
1136
	return "";
885
}
1137
}
886
 
1138
 
887
char* console_remove_needles(std::vector<std::string> &args)
1139
char* console_remove_needles(std::vector<std::string> &args)
888
{	
1140
{	
889
	if(wantshelp(args)) 
1141
	if(wantshelp(args)) 
890
	{
1142
	{
891
		theConsole.Printf("usage: cleanup.remove_needles <thresh>");
1143
		theConsole.Printf("usage: cleanup.remove_needles <thresh>");
892
		theConsole.Printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
1144
		theConsole.Printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
893
		theConsole.Printf("to get the length shorter than which we collapse. Default = 0.1");
1145
		theConsole.Printf("to get the length shorter than which we collapse. Default = 0.1");
894
		return "";
1146
		return "";
895
	}
1147
	}
896
	float thresh = 0.1;
1148
	float thresh = 0.1;
897
	if(args.size()>0)
1149
	if(args.size()>0)
898
	{
1150
	{
899
		istringstream a0(args[0]);
1151
		istringstream a0(args[0]);
900
		a0 >> thresh;
1152
		a0 >> thresh;
901
	}
1153
	}
902
	float avg_length = average_edge_length(active_mesh());
1154
	float avg_length = average_edge_length(active_mesh());
903
	remove_needles_from_trimesh(active_mesh(), thresh * avg_length);
1155
	remove_needles_from_trimesh(active_mesh(), thresh * avg_length);
904
	return "";
1156
	return "";
905
}
1157
}
906
 
1158
 
907
void reshape(int W, int H)
1159
void reshape(int W, int H)
908
{
1160
{
909
	active_view_control().reshape(W,H);
1161
	active_view_control().reshape(W,H);
910
}
1162
}
911
 
1163
 
912
void display() 
1164
void display() 
913
{
1165
{
914
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1166
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
915
	
1167
	
916
	static string& display_render_mode = CreateCVar<string>("display.render_mode","");
1168
	static string& display_render_mode = CreateCVar<string>("display.render_mode","");
917
	static int& display_smooth= CreateCVar<int>("display.smooth_shading",1);
1169
	static int& display_smooth= CreateCVar<int>("display.smooth_shading",1);
918
	
1170
	
919
	glPushMatrix();
1171
	glPushMatrix();
920
	
1172
	
921
	avo().display(display_render_mode, display_smooth);
1173
	avo().display(display_render_mode, display_smooth);
922
	
1174
	
923
	glPopMatrix();
1175
	glPopMatrix();
924
	
1176
	
925
	glUseProgram(0);
1177
	glUseProgram(0);
926
	theConsole.RenderConsole();
1178
	theConsole.RenderConsole();
927
	
1179
	
928
	glutSwapBuffers();
1180
	glutSwapBuffers();
929
}
1181
}
930
 
1182
 
931
void animate() 
1183
void animate() 
932
{	
1184
{	
933
	//usleep( (int)1e4 );
1185
	//usleep( (int)1e4 );
934
	active_view_control().try_spin();
1186
	active_view_control().try_spin();
935
	glutPostRedisplay();
1187
	glutPostRedisplay();
936
}
1188
}
937
 
1189
 
938
 
1190
 
939
void mouse(int button, int state, int x, int y) 
1191
void mouse(int button, int state, int x, int y) 
940
{
1192
{
941
	Vec2i pos(x,y);
1193
	Vec2i pos(x,y);
942
	if (state==GLUT_DOWN) 
1194
	if (state==GLUT_DOWN) 
943
	{
1195
	{
944
		if (button==GLUT_LEFT_BUTTON) 
1196
		if (button==GLUT_LEFT_BUTTON) 
945
			active_view_control().grab_ball(ROTATE_ACTION,pos);
1197
			active_view_control().grab_ball(ROTATE_ACTION,pos);
946
		else if (button==GLUT_MIDDLE_BUTTON) 
1198
		else if (button==GLUT_MIDDLE_BUTTON) 
947
			active_view_control().grab_ball(ZOOM_ACTION,pos);
1199
			active_view_control().grab_ball(ZOOM_ACTION,pos);
948
		else if (button==GLUT_RIGHT_BUTTON) 
1200
		else if (button==GLUT_RIGHT_BUTTON) 
949
			active_view_control().grab_ball(PAN_ACTION,pos);
1201
			active_view_control().grab_ball(PAN_ACTION,pos);
950
	}
1202
	}
951
	else if (state==GLUT_UP)
1203
	else if (state==GLUT_UP)
952
		active_view_control().release_ball();
1204
		active_view_control().release_ball();
953
}
1205
}
954
 
1206
 
955
void motion(int x, int y) {
1207
void motion(int x, int y) {
956
	Vec2i pos(x,y);
1208
	Vec2i pos(x,y);
957
	active_view_control().roll_ball(Vec2i(x,y));
1209
	active_view_control().roll_ball(Vec2i(x,y));
958
}
1210
}
959
 
1211
 
960
void keyboard_spec(int key, int x, int y)
1212
void keyboard_spec(int key, int x, int y)
961
{
1213
{
962
	int mod = glutGetModifiers();
1214
	int mod = glutGetModifiers();
963
	if( theConsole.IsOpen() ) {
1215
	if( theConsole.IsOpen() ) {
964
		// If shift held, scroll the console
1216
		// If shift held, scroll the console
965
		if( mod == GLUT_ACTIVE_SHIFT ) {
1217
		if( mod == GLUT_ACTIVE_SHIFT ) {
966
			switch (key){
1218
			switch (key){
967
				case GLUT_KEY_UP:
1219
				case GLUT_KEY_UP:
968
					theConsole.ScrollDownLine();
1220
					theConsole.ScrollDownLine();
969
					break;
1221
					break;
970
				case GLUT_KEY_DOWN: 
1222
				case GLUT_KEY_DOWN: 
971
					theConsole.ScrollUpLine();
1223
					theConsole.ScrollUpLine();
972
					break;
1224
					break;
973
			}
1225
			}
974
		} else {
1226
		} else {
975
			theConsole.StandardKeyBindings( key );
1227
			theConsole.StandardKeyBindings( key );
976
		}
1228
		}
977
	}
1229
	}
978
}
1230
}
979
 
1231
 
980
 
1232
 
981
void keyboard(unsigned char key, int x, int y) 
1233
void keyboard(unsigned char key, int x, int y) 
982
{	
1234
{	
983
	if(theConsole.IsOpen())
1235
	if(theConsole.IsOpen())
984
	{
1236
	{
985
		switch(key) {
1237
		switch(key) {
986
			case '\033': 
1238
			case '\033': 
987
				theConsole.ToggleConsole();
1239
				theConsole.ToggleConsole();
988
			default:
1240
			default:
989
				theConsole.EnterCommandCharacter(key);
1241
				theConsole.EnterCommandCharacter(key);
990
			break;
1242
				break;
991
		}
1243
		}
992
		if(key == 13)	avo().post_create_display_list();
1244
		if(key == 13)	avo().post_create_display_list();
993
		
1245
		
994
	}	
1246
	}	
995
	else {
1247
	else {
996
		string& display_render_mode = GetCVarRef<string>("display.render_mode");
1248
		string& display_render_mode = GetCVarRef<string>("display.render_mode");
997
		int& display_smooth = GetCVarRef<int>("display.smooth_shading");
1249
		int& display_smooth = GetCVarRef<int>("display.smooth_shading");
998
		int& active  = GetCVarRef<int>("active_mesh");
1250
		int& active  = GetCVarRef<int>("active_mesh");
999
		
1251
		
1000
		
1252
		
1001
		switch(key) {
1253
		switch(key) {
1002
			case 'q': exit(0);
1254
			case 'q': exit(0);
1003
			case '\033':
1255
			case '\033':
1004
				theConsole.ToggleConsole();
1256
				theConsole.ToggleConsole();
1005
				break;
1257
				break;
1006
			case '1':
1258
			case '1':
1007
			case '2':
1259
			case '2':
1008
			case '3':
1260
			case '3':
1009
			case '4':
1261
			case '4':
1010
			case '5':
1262
			case '5':
1011
			case '6':
1263
			case '6':
1012
			case '7':
1264
			case '7':
1013
			case '8':
1265
			case '8':
1014
			case '9':
1266
			case '9':
1015
				active = key - '1'; break;
1267
				active = key - '1'; break;
1016
			case 'f': display_smooth = !display_smooth; break;
1268
			case 'f': display_smooth = !display_smooth; break;
1017
			case 'w':
1269
			case 'w':
1018
				display_render_mode = "wire"; break;
1270
				display_render_mode = "wire"; break;
1019
			case 'n':
1271
			case 'n':
1020
				display_render_mode = "normal"; break;
1272
				display_render_mode = "normal"; break;
1021
			case 'i':
1273
			case 'i':
1022
				display_render_mode = "isophotes"; break;
1274
				display_render_mode = "isophotes"; break;
1023
			case 'r':
1275
			case 'r':
1024
				display_render_mode = "reflection"; break;
1276
				display_render_mode = "reflection"; break;
1025
			case 'h':
1277
			case 'h':
1026
				display_render_mode = "harmonics"; break;
1278
				display_render_mode = "harmonics"; break;
1027
			case 't':
1279
			case 't':
1028
				display_render_mode = "toon"; break;
1280
				display_render_mode = "toon"; break;
1029
			case 'g':
1281
			case 'g':
1030
				display_render_mode = "glazed"; break;
1282
				display_render_mode = "glazed"; break;
1031
			case 'a':
1283
			case 'a':
1032
				display_render_mode = "ambient_occlusion"; break;
1284
				display_render_mode = "ambient_occlusion"; break;
1033
			case 'c':
1285
			case 'c':
1034
				display_render_mode = "copper"; break;
1286
				display_render_mode = "copper"; break;
1035
			case 'C':
1287
			case 'C':
1036
				display_render_mode = "curvature_lines"; break;
1288
				display_render_mode = "curvature_lines"; break;
1037
			case 'M':
1289
			case 'M':
1038
				display_render_mode = "mean_curvature"; break;
1290
				display_render_mode = "mean_curvature"; break;
1039
			case 'G':
1291
			case 'G':
1040
				display_render_mode = "gaussian_curvature"; break;
1292
				display_render_mode = "gaussian_curvature"; break;
1041
		}
1293
		}
1042
		
1294
		
1043
		if(display_render_mode.substr(0,4) == "harm")
1295
		if(display_render_mode.substr(0,4) == "harm")
1044
			avo().harmonics_parse_key(key);
1296
			avo().harmonics_parse_key(key);
1045
		
1297
		
1046
		if(key != '\033') avo().post_create_display_list();		
1298
		if(key != '\033') avo().post_create_display_list();		
1047
	}
1299
	}
1048
}
1300
}
1049
 
1301
 
1050
void init_glut(int argc, char** argv)
1302
void init_glut(int argc, char** argv)
1051
{
1303
{
1052
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
1304
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
1053
	glutInitWindowSize(WINX, WINY);
1305
	glutInitWindowSize(WINX, WINY);
1054
	glutInit(&argc, argv);
1306
	glutInit(&argc, argv);
1055
	glutCreateWindow("Shape Harmonics");
1307
	glutCreateWindow("Shape Harmonics");
1056
	glutDisplayFunc(display);
1308
	glutDisplayFunc(display);
1057
	glutKeyboardFunc(keyboard);
1309
	glutKeyboardFunc(keyboard);
1058
	glutSpecialFunc(keyboard_spec);
1310
	glutSpecialFunc(keyboard_spec);
1059
	glutReshapeFunc(reshape);
1311
	glutReshapeFunc(reshape);
1060
	glutMouseFunc(mouse);
1312
	glutMouseFunc(mouse);
1061
	glutMotionFunc(motion);
1313
	glutMotionFunc(motion);
1062
	glutIdleFunc(animate);
1314
	glutIdleFunc(animate);
1063
}
1315
}
1064
 
1316
 
1065
void init_gl()
1317
void init_gl()
1066
{
1318
{
1067
	glewInit();
1319
	glewInit();
1068
	glEnable(GL_LIGHTING);
1320
	glEnable(GL_LIGHTING);
1069
	glEnable(GL_LIGHT0);
1321
	glEnable(GL_LIGHT0);
1070
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
1322
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
1071
	
1323
	
1072
	// Set the value of a uniform
1324
	// Set the value of a uniform
1073
	//glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
1325
	//glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
1074
	
1326
	
1075
	glMatrixMode(GL_MODELVIEW);
1327
	glMatrixMode(GL_MODELVIEW);
1076
	glLoadIdentity();
1328
	glLoadIdentity();
1077
	glClearColor(0.50f, 0.50f, 0.50f, 0.f);
1329
	glClearColor(0.50f, 0.50f, 0.50f, 0.f);
1078
	glColor4f(1.0f, 1.0f, 1.0f, 0.f);
1330
	glColor4f(1.0f, 1.0f, 1.0f, 0.f);
1079
	float material[4] = {1,1,1,1};
1331
	float material[4] = {1,1,1,1};
1080
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
1332
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
1081
	glEnable(GL_DEPTH_TEST);
1333
	glEnable(GL_DEPTH_TEST);
1082
	
1334
	
1083
	CreateCVar( "help", ConsoleHelp );
1335
	CreateCVar( "help", ConsoleHelp );
1084
	CreateCVar("harmonics.reset_shape", console_reset_shape);
1336
	CreateCVar("harmonics.reset_shape", console_reset_shape);
1085
	CreateCVar("harmonics.analyze", console_analyze);
1337
	CreateCVar("harmonics.analyze", console_analyze);
1086
	CreateCVar("harmonics.partial_reconstruct", console_partial_reconstruct);
1338
	CreateCVar("harmonics.partial_reconstruct", console_partial_reconstruct);
1087
	CreateCVar("simplify", console_simplify);
1339
	CreateCVar("simplify", console_simplify);
1088
	CreateCVar("smooth.mean_curvature", console_mean_curvature_smooth);
1340
	CreateCVar("smooth.mean_curvature", console_mean_curvature_smooth);
-
 
1341
	CreateCVar("smooth.experimental", console_experimental_smooth);
1089
	CreateCVar("smooth.laplacian", console_laplacian_smooth);
1342
	CreateCVar("smooth.laplacian", console_laplacian_smooth);
1090
	CreateCVar("smooth.taubin", console_taubin_smooth);
1343
	CreateCVar("smooth.taubin", console_taubin_smooth);
1091
	CreateCVar("smooth.fuzzy_vector_median", console_fvm_smooth);
1344
	CreateCVar("smooth.fuzzy_vector_median", console_fvm_smooth);
1092
	
1345
	
1093
	CreateCVar("optimize.valency", console_optimize_valency);
1346
	CreateCVar("optimize.valency", console_optimize_valency);
1094
	CreateCVar("optimize.minimize_dihedral_angles", console_minimize_dihedral);
1347
	CreateCVar("optimize.minimize_dihedral_angles", console_minimize_dihedral);
1095
	CreateCVar("optimize.minimize_curvature", console_minimize_curvature);
1348
	CreateCVar("optimize.minimize_curvature", console_minimize_curvature);
1096
	CreateCVar("optimize.maximize_min_angle", console_maximize_min_angle);
1349
	CreateCVar("optimize.maximize_min_angle", console_maximize_min_angle);
1097
	CreateCVar("cleanup.close_holes", console_close_holes);
1350
	CreateCVar("cleanup.close_holes", console_close_holes);
1098
	CreateCVar("load", console_reload);
1351
	CreateCVar("load", console_reload);
1099
	
1352
	
1100
	CreateCVar("cleanup.remove_caps", console_remove_caps);
1353
	CreateCVar("cleanup.remove_caps", console_remove_caps);
1101
	CreateCVar("cleanup.remove_needles", console_remove_needles);
1354
	CreateCVar("cleanup.remove_needles", console_remove_needles);
1102
	CreateCVar("triangulate", console_triangulate);
1355
	CreateCVar("triangulate", console_triangulate);
1103
	CreateCVar("refine.split_edges", console_refine_edges);
1356
	CreateCVar("refine.split_edges", console_refine_edges);
1104
	CreateCVar("refine.split_faces", console_refine_faces);
1357
	CreateCVar("refine.split_faces", console_refine_faces);
1105
	CreateCVar("refine.catmull_clark", console_cc_subdivide);
1358
	CreateCVar("refine.catmull_clark", console_cc_subdivide);
1106
	CreateCVar("save", console_save);
1359
	CreateCVar("save", console_save);
1107
	CreateCVar("noise.perturb_vertices", console_vertex_noise);
1360
	CreateCVar("noise.perturb_vertices", console_vertex_noise);
1108
	CreateCVar("noise.perturb_vertices_perpendicular", console_perpendicular_vertex_noise);
1361
	CreateCVar("noise.perturb_vertices_perpendicular", console_perpendicular_vertex_noise);
1109
	CreateCVar("noise.perturb_topology", console_noisy_flips);
1362
	CreateCVar("noise.perturb_topology", console_noisy_flips);
1110
	
1363
	
1111
	CreateCVar("dual", console_dual);
1364
	CreateCVar("dual", console_dual);
-
 
1365
	CreateCVar("flatten", console_flatten);
1112
	
1366
	
1113
	CreateCVar("align", console_align);
1367
	CreateCVar("align", console_align);
1114
	
1368
	
1115
	CVarUtils::CreateCVar( "history.load", ConsoleLoadHistory );
1369
	CVarUtils::CreateCVar( "history.load", ConsoleLoadHistory );
1116
    CVarUtils::CreateCVar( "history.save", ConsoleSaveHistory );
1370
    CVarUtils::CreateCVar( "history.save", ConsoleSaveHistory );
1117
    CVarUtils::CreateCVar( "history.clear", ConsoleClearHistory );
1371
    CVarUtils::CreateCVar( "history.clear", ConsoleClearHistory );
1118
	
1372
	
1119
    CVarUtils::CreateCVar( "script.start", ConsoleStartScript );
1373
    CVarUtils::CreateCVar( "script.start", ConsoleStartScript );
1120
    CVarUtils::CreateCVar(	"script.stop", ConsoleStopScript );
1374
    CVarUtils::CreateCVar(	"script.stop", ConsoleStopScript );
1121
    CVarUtils::CreateCVar( "script.show", ConsoleShowScript );
1375
    CVarUtils::CreateCVar( "script.show", ConsoleShowScript );
1122
    CVarUtils::CreateCVar( "script.run", ConsoleRunScript );
1376
    CVarUtils::CreateCVar( "script.run", ConsoleRunScript );
1123
    CVarUtils::CreateCVar( "script.save", ConsoleSaveScript );
1377
    CVarUtils::CreateCVar( "script.save", ConsoleSaveScript );
1124
    CVarUtils::CreateCVar( "script.launch", ConsoleLaunchScript );
1378
    CVarUtils::CreateCVar( "script.launch", ConsoleLaunchScript );
1125
	
1379
	
1126
	
1380
	
1127
}
1381
}
1128
 
1382
 
1129
int main(int argc, char** argv)
1383
int main(int argc, char** argv)
1130
{
1384
{
1131
	ArgExtracter ae(argc, argv);
1385
	ArgExtracter ae(argc, argv);
1132
	
1386
	
1133
	init_glut(argc,argv);
1387
	init_glut(argc,argv);
1134
	init_gl();
1388
	init_gl();
1135
	
1389
	
1136
	Harmonics::init();
1390
	Harmonics::init();
1137
	
1391
	
1138
	if(argc>1)
1392
	if(argc>1)
1139
	{		
1393
	{		
1140
		string file = ae.get_last_arg();
1394
		string file = ae.get_last_arg();
1141
		avo().reload(file);
1395
		avo().reload(file);
1142
	}
1396
	}
1143
	
1397
	
1144
	
1398
	
1145
	glutMainLoop();
1399
	glutMainLoop();
1146
}
1400
}
1147
 
1401
 
1148
 
1402
 
1149
 
1403