Subversion Repositories gelsvn

Rev

Rev 586 | Details | Compare with Previous | Last modification | View Log | RSS feed

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