Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

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