Subversion Repositories gelsvn

Rev

Rev 630 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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