Subversion Repositories gelsvn

Rev

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

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