Subversion Repositories gelsvn

Rev

Rev 458 | Rev 600 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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