Subversion Repositories gelsvn

Rev

Rev 614 | Details | Compare with Previous | 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;
218
    VertexAttributeVector<double> par;
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)) {
363
        theConsole.printf("usage: refine.catmull_clark ");
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
 
596 jab 376
void console_doosabin_subdivide(const std::vector<std::string> & args)
388 jab 377
{
596 jab 378
    if(wantshelp(args)) {
379
        theConsole.printf("usage: refine.doo_sabin ");
380
        theConsole.printf("Does one step of Doo-Sabin Subdivision");
381
 
382
        return;
383
    }
384
    avo().save_old();
385
 
386
    cc_split(active_mesh(),active_mesh());
387
    dual(active_mesh());
388
 
389
    return;
388 jab 390
}
391
 
596 jab 392
void console_dual(const std::vector<std::string> & args)
394 jab 393
{
596 jab 394
    if(wantshelp(args)) 
395
    {
396
        theConsole.printf("usage: dual ");
397
        theConsole.printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
398
        return;
399
    }
400
    avo().save_old();
394 jab 401
 
596 jab 402
    dual(active_mesh());
394 jab 403
 
596 jab 404
    return;
394 jab 405
}
388 jab 406
 
407
 
596 jab 408
void console_minimize_curvature(const std::vector<std::string> & args)
387 jab 409
{
596 jab 410
    if(wantshelp(args)) 
411
    {
412
        theConsole.printf("usage: optimize.minimize_curvature <anneal>");
413
        theConsole.printf("Flip edges to minimize mean curvature.");
414
        theConsole.printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
415
        return;
416
    }
417
    avo().save_old();
391 jab 418
 
596 jab 419
    bool anneal=false;
420
    if(args.size() > 0)
421
    {
422
        istringstream a0(args[0]);
423
        a0 >> anneal;
424
    }
425
 
426
    minimize_curvature(active_mesh(), anneal);
427
    avo().post_create_display_list();
428
    return;
387 jab 429
}
430
 
596 jab 431
void console_minimize_dihedral(const std::vector<std::string> & args)
387 jab 432
{
596 jab 433
    if(wantshelp(args))
434
    {
435
        theConsole.printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
436
        theConsole.printf("Flip edges to minimize dihedral angles.");
437
        theConsole.printf("Iter is the max number of iterations. anneal tells us whether to use ");
438
        theConsole.printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
439
        theConsole.printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
440
        theConsole.printf("to which we raise the dihedral angle");
441
        return;
442
    }
443
    avo().save_old();
391 jab 444
 
596 jab 445
    int iter = 1000;
446
    if(args.size() > 0)
447
    {
448
        istringstream a0(args[0]);
449
        a0 >> iter;
450
    }
391 jab 451
 
596 jab 452
    bool anneal = false;
453
    if(args.size() > 1)
454
    {
455
        istringstream a0(args[1]);
456
        a0 >> anneal;
457
    }
391 jab 458
 
596 jab 459
    bool use_alpha = true;
460
    if(args.size() > 2)
461
    {
462
        istringstream a0(args[2]);
463
        a0 >> use_alpha;
464
    }
387 jab 465
 
596 jab 466
    float gamma = 4.0f;
467
    if(args.size() > 3)
468
    {
469
        istringstream a0(args[3]);
470
        a0 >> gamma;
471
    }
387 jab 472
 
596 jab 473
 
474
    minimize_dihedral_angle(active_mesh(), iter, anneal, use_alpha, gamma);
475
    return;
387 jab 476
}
477
 
596 jab 478
void console_maximize_min_angle(const std::vector<std::string> & args)
388 jab 479
{
596 jab 480
    if(wantshelp(args)) 
481
    {
482
        theConsole.printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
483
        theConsole.printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
484
        theConsole.printf("If the dot product of the normals between adjacent faces < thresh");
485
        theConsole.printf("no flip will be made. anneal selects simulated annealing rather ");
486
        theConsole.printf("nthan greedy optimization.");
487
        return;
488
    }
489
    avo().save_old();
490
 
491
    float thresh = 0.0f;
492
    if(args.size() > 0)
493
    {
494
        istringstream a0(args[0]);
495
        a0 >> thresh;
496
    }
497
    bool anneal = false;
498
    if(args.size() > 1)
499
    {
500
        istringstream a0(args[1]);
501
        a0 >> anneal;
502
    }
503
    maximize_min_angle(active_mesh(),thresh,anneal);
504
    return;
388 jab 505
}
506
 
507
 
596 jab 508
void console_optimize_valency(const std::vector<std::string> & args)
387 jab 509
{
596 jab 510
    if(wantshelp(args)) 
511
    {
512
        theConsole.printf("usage: optimize.valency <anneal> ");
513
        theConsole.printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
514
        return;
515
    }
516
    avo().save_old();
517
 
518
    bool anneal = false;
519
    if(args.size() > 0)
520
    {
521
        istringstream a0(args[0]);
522
        a0 >> anneal;
523
    }
524
    optimize_valency(active_mesh(), anneal);
525
    return;
387 jab 526
}
527
 
596 jab 528
void console_analyze(const std::vector<std::string> & args)
388 jab 529
{
596 jab 530
    if(wantshelp(args)) 
531
    {
532
        theConsole.printf("usage:  harmonics.analyze");
533
        theConsole.printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
534
        theConsole.printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
535
        theConsole.printf("to this basis.");
536
        theConsole.printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
537
        return;
538
    }
614 jab 539
    avo().harmonics_analyze_mesh(theConsole);
596 jab 540
    return;
388 jab 541
}
542
 
543
 
596 jab 544
void console_partial_reconstruct(const std::vector<std::string> & args)
386 jab 545
{
596 jab 546
    if(args.size() != 3)
547
        theConsole.printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
434 jab 548
 
596 jab 549
    if(wantshelp(args)) {
550
        theConsole.printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
551
        theConsole.printf("the eigenvector interval that we reconstruct from. The last argument is the ");
552
        theConsole.printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
553
        theConsole.printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
554
        theConsole.printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
555
        theConsole.printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
556
        theConsole.printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
557
    }
558
    avo().save_old();
434 jab 559
 
596 jab 560
    if(args.size() != 3)
561
        return;
434 jab 562
 
596 jab 563
    int E0,E1;
564
    float scale;
565
    istringstream a0(args[0]);
566
    a0 >> E0;
567
    istringstream a1(args[1]);
568
    a1 >> E1;
569
    istringstream a2(args[2]);
570
    a2 >> scale;
571
    avo().harmonics_partial_reconstruct(E0,E1,scale);
572
    return;
386 jab 573
}
574
 
596 jab 575
void console_reset_shape(const std::vector<std::string> & args)
386 jab 576
{
596 jab 577
    if(wantshelp(args)) 
578
    {
579
        theConsole.printf("usage: harmonics.reset_shape ");
580
        theConsole.printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
581
        theConsole.printf("unless you know what you are doing.");
582
        return;
583
    }
584
    avo().save_old();
585
    avo().harmonics_reset_shape();
586
    return;
386 jab 587
}
588
 
589
 
596 jab 590
void console_close_holes(const std::vector<std::string> & args)
388 jab 591
{
596 jab 592
    if(wantshelp(args)) 
593
    {
594
        theConsole.printf("usage: cleanup.close_holes");
595
        theConsole.printf("This function closes holes. It simply follows the loop of halfvectors which");
596
        theConsole.printf("enclose the hole and add a face to which they all point.");
597
        return;
598
    }
599
    avo().save_old();
600
 
601
    close_holes(active_mesh());
602
    return;
388 jab 603
}
386 jab 604
 
596 jab 605
void console_reload(const std::vector<std::string> & args)
388 jab 606
{
596 jab 607
    if(wantshelp(args)) 
608
    {
609
        theConsole.printf("usage:  load <file>");
610
        theConsole.printf("(Re)loads the current file if no argument is given, but");
611
        theConsole.printf("if an argument is given, then that becomes the current file");
612
        return;
613
    }
614
    avo().save_old();
615
 
616
    if(!avo().reload(args.size() > 0 ? args[0]:""))
617
        theConsole.printf("failed to load");
618
 
619
    return;
388 jab 620
}
621
 
622
 
596 jab 623
void console_add_mesh(const std::vector<std::string> & args)
387 jab 624
{
596 jab 625
    if(wantshelp(args)) 
626
    {
627
        theConsole.printf("usage:  add_mesh <file>");
628
        theConsole.printf("Loads the file but without clearing the mesh. Thus, the loaded mesh is added to the");
629
        theConsole.printf("current model.");
630
        return;
631
    }
632
    avo().save_old();
391 jab 633
 
596 jab 634
    if(!avo().add_mesh(args.size() > 0 ? args[0]:""))
635
        theConsole.printf("failed to load");
636
 
637
    return;
387 jab 638
}
596 jab 639
void console_valid(const std::vector<std::string> & args)
640
{
641
    if(wantshelp(args)) 
642
    {
643
        theConsole.printf("usage:  validity");
644
        theConsole.printf("Tests validity of Manifold");
645
        return;
646
    }
647
	if(valid(active_mesh()))
648
		theConsole.printf("Mesh is valid");
649
	else
650
		theConsole.printf("Mesh is invalid - check console output");
651
	return;
652
}
387 jab 653
 
596 jab 654
void console_info(const std::vector<std::string> & args)
391 jab 655
{
596 jab 656
    if(wantshelp(args)) 
657
    {
658
        theConsole.printf("usage:  info");
659
        theConsole.printf("Provides information about mesh.");
660
        return;
661
    }
662
    Vec3d p0, p7;
663
    bbox(active_mesh(), p0, p7);
664
    stringstream bbox_corners;
665
    bbox_corners << p0 << " - " << p7 << endl;
666
	theConsole.printf("Bounding box corners : %s", bbox_corners.str().c_str());
667
    map<int,int> val_hist;
668
 
669
    for(VertexIDIterator vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
670
    {
671
        int val = valency(active_mesh(), *vi);
672
        if(val_hist.find(val) == val_hist.end())
673
            val_hist[val] = 0;
674
        ++val_hist[val];
675
    }
676
 
677
    theConsole.printf("Valency histogam");
678
    for(map<int,int>::iterator iter = val_hist.begin(); iter != val_hist.end(); ++iter)
679
    {
680
        stringstream vhl;
681
        vhl << iter->first << ", " << iter->second;
682
        theConsole.printf("%d, %d", iter->first, iter->second);
683
    }
684
 
685
	theConsole.printf("Mesh contains %d faces", active_mesh().no_faces());
686
	theConsole.printf("Mesh contains %d halfedges", active_mesh().no_halfedges());
687
	theConsole.printf("Mesh contains %d vertices", active_mesh().no_vertices());
688
	return;
391 jab 689
}
690
 
596 jab 691
 
692
void console_simplify(const std::vector<std::string> & args)
412 jab 693
{
596 jab 694
    if(wantshelp(args)) 
695
    {
696
        theConsole.printf("usage: simplify <fraction> ");
697
        theConsole.printf("Performs Garland Heckbert (quadric based) mesh simplification.");
698
        theConsole.printf("The only argument is the fraction of vertices to keep.");
699
        return;
700
    }
701
    avo().save_old();
412 jab 702
 
596 jab 703
    float keep_fraction;
704
    if(args.size() == 0)
705
    {
706
        theConsole.print("you must specify fraction of vertices to keep");
707
        return;
708
    }
709
    istringstream a0(args[0]);
710
    a0 >> keep_fraction;
412 jab 711
 
596 jab 712
    Vec3d p0, p7;
713
    bbox(active_mesh(), p0, p7);
714
    Vec3d d = p7-p0;
715
    float s = 1.0/d.max_coord();
716
    Vec3d pcentre = (p7+p0)/2.0;
717
    for(VertexIDIterator vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi){
718
        active_mesh().pos(*vi) = (active_mesh().pos(*vi) - pcentre) * s;
719
    }
720
    cout << "Timing the Garland Heckbert (quadric based) mesh simplication..." << endl;
721
    Timer timer;
722
    timer.start();
723
 
724
    //simplify
725
    quadric_simplify(active_mesh(),keep_fraction,0.0001f,true);
726
 
727
    cout << "Simplification complete, process time: " << timer.get_secs() << " seconds" << endl;
728
 
729
    //clean up the mesh, a lot of edges were just collapsed 
730
    active_mesh().cleanup();
731
 
732
    for(VertexIDIterator vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
733
        active_mesh().pos(*vi) = active_mesh().pos(*vi)*d.max_coord() + pcentre;
734
    return;
412 jab 735
}
736
 
596 jab 737
void console_vertex_noise(const std::vector<std::string> & args)
391 jab 738
{
596 jab 739
    if(wantshelp(args)) 
740
    {
741
        theConsole.printf("usage: noise.perturb_vertices <amplitude>");
742
        theConsole.printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
743
        theConsole.printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
744
        theConsole.printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
745
        theConsole.printf("If no amplitude is specified, the default (0.5) is used.");
746
        return;
747
    }
748
    avo().save_old();
391 jab 749
 
596 jab 750
    float avg_length = average_edge_length(active_mesh());
751
 
752
    float noise_amplitude = 0.5f;
753
    if(args.size() > 0) {
754
        istringstream a0(args[0]);
755
        a0 >> noise_amplitude;
756
    }
757
 
758
    gel_srand(0);
759
    for(VertexIDIterator vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi){
760
        Vec3d v;
761
        do{
762
            v = Vec3d(gel_rand(),gel_rand(),gel_rand());
763
            v /= (float)(GEL_RAND_MAX);
764
        } 
765
        while(sqr_length(v) > 1.0);
766
 
767
        v -= Vec3d(0.5);
768
        v *= 2.0;
769
        v *= noise_amplitude;
770
        v *= avg_length;
771
        active_mesh().pos(*vi) += v;
772
    }		
773
    return;
391 jab 774
}
775
 
596 jab 776
void console_perpendicular_vertex_noise(const std::vector<std::string> & args)
387 jab 777
{
596 jab 778
    if(wantshelp(args)) {
779
        theConsole.printf("usage: noise.perturb_vertices_perpendicular <amplitude>");
780
        theConsole.printf("adds the normal times a random scalar times amplitude times");
781
        theConsole.printf("times average edge length to the vertex. (default amplitude=0.5)");
782
        return;
783
    }
784
    avo().save_old();
412 jab 785
 
596 jab 786
    float avg_length = average_edge_length(active_mesh());
787
 
788
    float noise_amplitude = 0.5;
789
    if(args.size() > 0) 
790
    {
791
        istringstream a0(args[0]);
792
        a0 >> noise_amplitude;
793
    }
794
 
795
    VertexAttributeVector<Vec3d> normals(active_mesh().allocated_vertices());
796
    for(VertexIDIterator vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
797
        normals[*vi] = normal(active_mesh(), *vi);
798
 
799
    gel_srand(0);
800
    for(VertexIDIterator vi = active_mesh().vertices_begin(); vi != active_mesh().vertices_end(); ++vi)
801
    {
802
        float rval = 0.5-gel_rand() / float(GEL_RAND_MAX);
803
        active_mesh().pos(*vi) += normals[*vi]*rval*noise_amplitude*avg_length*2.0;
804
    }
805
    return;
387 jab 806
}
807
 
596 jab 808
void console_noisy_flips(const std::vector<std::string> & args)
412 jab 809
{
596 jab 810
    if(wantshelp(args)){
811
        theConsole.printf("usage:  noise.perturb_topology <iter>");
812
        theConsole.printf("Perform random flips. iter (default=1) is the number of iterations.");
813
        theConsole.printf("mostly for making nasty synthetic test cases.");
814
        return;
815
    }
816
    avo().save_old();
817
 
818
    int iter = 1;
819
    if(args.size() > 0){
820
        istringstream a0(args[0]);
821
        a0 >> iter;
822
    }
823
 
824
    randomize_mesh(active_mesh(),  iter);
825
    return;
412 jab 826
}
827
 
596 jab 828
void console_laplacian_smooth(const std::vector<std::string> & args)
434 jab 829
{
596 jab 830
    if(wantshelp(args)) {
831
        theConsole.printf("usage:  smooth.laplacian <weight> <iter>");
832
        theConsole.printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
833
        theConsole.printf("default weight = 1.0. Default number of iterations = 1");
834
        return;
835
    }
836
    avo().save_old();
837
 
838
    float t=1.0;
839
    if(args.size() > 0){
840
        istringstream a0(args[0]);
841
        a0 >> t;
842
    }
843
    int iter = 1;
844
    if(args.size()>1){
845
        istringstream a0(args[1]);
846
        a0 >> iter;
847
    }
848
    /// Simple laplacian smoothing with an optional weight.
849
    for(int i=0;i<iter;++i) 
850
        laplacian_smooth(active_mesh(), t);
851
    return;
434 jab 852
}
412 jab 853
 
434 jab 854
 
596 jab 855
void console_mean_curvature_smooth(const std::vector<std::string> & args){
856
    if(wantshelp(args)) {
857
        theConsole.printf("usage:  smooth.mean_curvature <weight> <iter>");
858
        theConsole.printf("Perform mean curvature smoothing. weight is the scaling factor for the");
859
        theConsole.printf("mean curvature vector which has been normalized by dividing by edge lengths");
860
        theConsole.printf("this allows for larger steps as suggested by Desbrun et al.");
861
        theConsole.printf("default weight = 1.0. Default number of iterations = 1");
862
        return;
863
    }
864
    avo().save_old();
434 jab 865
 
596 jab 866
    double t=1.0;
867
    if(args.size() > 0){
868
        istringstream a0(args[0]);
869
        a0 >> t;
870
    }
871
    int iter=1;
872
    if(args.size() > 1){
873
        istringstream a0(args[1]);
874
        a0 >> iter;
875
    }	
876
    VertexAttributeVector<Vec3d> new_pos(active_mesh().allocated_vertices());
877
    for(int j = 0; j < iter; ++j){
878
        for(VertexIDIterator v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v) {
879
            Vec3d m;
880
            double w_sum;
881
            unnormalized_mean_curvature_normal(active_mesh(), *v, m, w_sum);
882
            new_pos[*v] = Vec3d(active_mesh().pos(*v))  + (t * m/w_sum);
883
        }
884
        for(VertexIDIterator v = active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v)
885
            active_mesh().pos(*v) = new_pos[*v];
886
    }
887
    return;
434 jab 888
}
889
 
596 jab 890
void console_taubin_smooth(const std::vector<std::string> & args)
387 jab 891
{
596 jab 892
    if(wantshelp(args)){
893
        theConsole.printf("usage:  smooth.taubin <iter>");
894
        theConsole.printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
895
        return;
896
    }
897
    avo().save_old();
387 jab 898
 
596 jab 899
    int iter = 1;
900
    if(args.size() > 0){
901
        istringstream a0(args[0]);
902
        a0 >> iter;
903
    }
904
    /// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
905
    taubin_smooth(active_mesh(),  iter);
906
 
907
    return;
387 jab 908
}
909
 
596 jab 910
void console_fvm_smooth(const std::vector<std::string> & args)
387 jab 911
{	
596 jab 912
    if(wantshelp(args)){
913
        theConsole.printf("usage: smooth.fuzzy_vector_median <iter>");
914
        theConsole.printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
915
        theConsole.printf("This function does a very good job of preserving sharp edges.");
916
        return;
917
    }
918
    avo().save_old();
391 jab 919
 
596 jab 920
    int iter=1;
921
    if(args.size() > 0){
922
        istringstream a0(args[0]);
923
        a0 >> iter;
924
    }
925
    // Fuzzy vector median smoothing is effective when it comes to preserving sharp edges. 
926
    fvm_smooth(active_mesh(),  iter);
927
 
928
    return;
387 jab 929
}
930
 
596 jab 931
void console_triangulate(const std::vector<std::string> & args)
388 jab 932
{	
596 jab 933
    if(wantshelp(args)) {
934
        theConsole.printf("usage:  triangulate");
935
        theConsole.printf("This function triangulates all non triangular faces of the mesh.");
936
        theConsole.printf("you may want to call it after hole closing. For a polygon it simply connects");
937
        theConsole.printf("the two closest vertices in a recursive manner until only triangles remain");
938
        return;
939
    }
940
    avo().save_old();
941
 
942
    shortest_edge_triangulate(active_mesh());
943
    active_mesh().cleanup();
944
	valid(active_mesh());
945
    return;
388 jab 946
}
947
 
600 jab 948
void console_remove_faces(const std::vector<std::string> & args)
949
{
950
    avo().save_old();
951
 
952
    gel_srand(0);
388 jab 953
 
600 jab 954
//    for (FaceIDIterator f= active_mesh().faces_begin(); f != active_mesh().faces_end(); ++f) {
955
//        if(gel_rand() < 0.5 * GEL_RAND_MAX)
956
//        {
957
//            active_mesh().remove_face(*f);
958
//        }
959
//    }
960
 
961
//    for (VertexIDIterator v= active_mesh().vertices_begin(); v != active_mesh().vertices_end(); ++v) {
962
//        if(gel_rand() < 0.005 * GEL_RAND_MAX)
963
//        {
964
//            active_mesh().remove_vertex(*v);
965
//        }
966
//    }
967
    for (HalfEdgeIDIterator h= active_mesh().halfedges_begin(); h != active_mesh().halfedges_end(); ++h) {
968
        if(gel_rand() < 0.005 * GEL_RAND_MAX)
969
        {
970
            active_mesh().remove_edge(*h);
971
        }
972
    }
973
 
974
    active_mesh().cleanup();
975
    valid(active_mesh());
976
 
977
    return;
978
}
979
 
980
 
596 jab 981
void console_remove_caps(const std::vector<std::string> & args)
388 jab 982
{	
596 jab 983
    if(wantshelp(args)) {
984
        theConsole.printf("usage:  cleanup.remove_caps thresh");
985
        theConsole.printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
986
        theConsole.printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
987
        return;
988
    }
989
    avo().save_old();
399 jab 990
 
596 jab 991
    float t = 0.85f;
992
    if(args.size() > 0){
993
        istringstream a0(args[0]);
994
        a0 >> t;
995
    }
996
    remove_caps(active_mesh(), static_cast<float>(M_PI) *t);
997
    active_mesh().cleanup();
998
 
999
    return;
388 jab 1000
}
1001
 
596 jab 1002
void console_remove_needles(const std::vector<std::string> & args)
388 jab 1003
{	
596 jab 1004
    if(wantshelp(args)){
1005
        theConsole.printf("usage: cleanup.remove_needles <thresh>");
1006
        theConsole.printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
1007
        theConsole.printf("to get the length shorter than which we collapse. Default = 0.1");
1008
        return;
1009
    }
1010
    avo().save_old();
1011
 
1012
    float thresh = 0.1f;
1013
    if(args.size() > 0){
1014
        istringstream a0(args[0]);
1015
        a0 >> thresh;
1016
    }
1017
    float avg_length = average_edge_length(active_mesh());
1018
    remove_needles(active_mesh(), thresh * avg_length);
1019
    active_mesh().cleanup();
1020
 
1021
    return;
388 jab 1022
}
1023
 
596 jab 1024
void console_undo(const std::vector<std::string> & args)
1025
{	
1026
    if(wantshelp(args)) {
1027
        theConsole.printf("usage:  undo");
1028
        theConsole.printf("This function undoes one operation. Repeated undo does nothing");
1029
        return;
1030
    }
1031
    avo().restore_old();
618 jab 1032
    avo().refit();
596 jab 1033
    return;
1034
}
1035
 
1036
 
391 jab 1037
void reshape(int W, int H)
1038
{
596 jab 1039
    active_view_control().reshape(W,H);
391 jab 1040
}
1041
 
596 jab 1042
Console::variable<string> display_render_mode("normal");
618 jab 1043
Console::variable<int> display_smooth_shading(true);
596 jab 1044
Console::variable<float> display_gamma(2.2);
1045
 
1046
void display()
386 jab 1047
{
596 jab 1048
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
386 jab 1049
 
596 jab 1050
 
1051
    glPushMatrix();
1052
 
1053
    avo().display(display_render_mode, theConsole, display_smooth_shading, display_gamma);
386 jab 1054
 
596 jab 1055
    glPopMatrix();
386 jab 1056
 
596 jab 1057
    if(console_visible)
1058
    {
1059
        glUseProgram(0);
1060
        theConsole.display();
1061
	}
1062
 
1063
    glutSwapBuffers();
386 jab 1064
}
1065
 
1066
void animate() 
1067
{	
596 jab 1068
    //usleep( (int)1e4 );
1069
    active_view_control().try_spin();
1070
    glutPostRedisplay();
386 jab 1071
}
1072
 
1073
 
1074
void mouse(int button, int state, int x, int y) 
1075
{
596 jab 1076
    Vec2i pos(x,y);
1077
    if (state==GLUT_DOWN) 
1078
    {
600 jab 1079
        if (button==GLUT_LEFT_BUTTON && glutGetModifiers() == 0)
596 jab 1080
            active_view_control().grab_ball(ROTATE_ACTION,pos);
600 jab 1081
        else if (button==GLUT_MIDDLE_BUTTON || glutGetModifiers() == GLUT_ACTIVE_CTRL) 
596 jab 1082
            active_view_control().grab_ball(ZOOM_ACTION,pos);
600 jab 1083
        else if (button==GLUT_RIGHT_BUTTON || glutGetModifiers() == GLUT_ACTIVE_ALT)
596 jab 1084
            active_view_control().grab_ball(PAN_ACTION,pos);
1085
    }
1086
    else if (state==GLUT_UP)
1087
        active_view_control().release_ball();
386 jab 1088
}
1089
 
1090
void motion(int x, int y) {
596 jab 1091
    Vec2i pos(x,y);
1092
    active_view_control().roll_ball(Vec2i(x,y));
386 jab 1093
}
1094
 
596 jab 1095
 
386 jab 1096
void keyboard_spec(int key, int x, int y)
1097
{
596 jab 1098
    if (console_visible)
1099
        theConsole.special(key);
1100
    glutPostRedisplay();
386 jab 1101
}
1102
 
1103
 
1104
void keyboard(unsigned char key, int x, int y) 
596 jab 1105
{
1106
    //toggle console with ESC
1107
    if (key == 27)
1108
    {
1109
        console_visible = !console_visible;
1110
        glutPostRedisplay();
1111
        return;
1112
    }
1113
 
1114
    if (console_visible)
1115
    {
1116
        theConsole.keyboard(key);
1117
        if(key == 13)
1118
        {
1119
            avo().post_create_display_list();
1120
            glutPostRedisplay();
1121
        }
1122
        return;
1123
    }
1124
    else {		
391 jab 1125
 
596 jab 1126
        switch(key) {
386 jab 1127
			case 'q': exit(0);
1128
			case '\033':
596 jab 1129
                console_visible = false;
386 jab 1130
				break;
391 jab 1131
			case '1':
1132
			case '2':
1133
			case '3':
1134
			case '4':
1135
			case '5':
1136
			case '6':
1137
			case '7':
1138
			case '8':
1139
			case '9':
1140
				active = key - '1'; break;
596 jab 1141
			case 'f': display_smooth_shading = !display_smooth_shading; break;
386 jab 1142
			case 'w':
399 jab 1143
				display_render_mode = "wire"; break;
1144
			case 'n':
1145
				display_render_mode = "normal"; break;
1146
			case 'i':
1147
				display_render_mode = "isophotes"; break;
1148
			case 'r':
1149
				display_render_mode = "reflection"; break;
1150
			case 'h':
1151
				display_render_mode = "harmonics"; break;
403 jab 1152
			case 't':
1153
				display_render_mode = "toon"; break;
401 jab 1154
			case 'g':
1155
				display_render_mode = "glazed"; break;
406 jab 1156
			case 'a':
1157
				display_render_mode = "ambient_occlusion"; break;
1158
			case 'c':
1159
				display_render_mode = "copper"; break;
403 jab 1160
			case 'C':
1161
				display_render_mode = "curvature_lines"; break;
1162
			case 'M':
1163
				display_render_mode = "mean_curvature"; break;
1164
			case 'G':
1165
				display_render_mode = "gaussian_curvature"; break;
596 jab 1166
        }
391 jab 1167
 
596 jab 1168
        if(string(display_render_mode).substr(0,3) == "har")
1169
            avo().harmonics_parse_key(key);
391 jab 1170
 
596 jab 1171
        if(key != '\033') avo().post_create_display_list();
1172
    }
1173
 
1174
    glutPostRedisplay();
386 jab 1175
}
1176
 
1177
void init_glut(int argc, char** argv)
596 jab 1178
{  
1179
    glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
1180
    glutInitWindowSize(WINX, WINY);
1181
    glutInit(&argc, argv);
1182
    glutCreateWindow("MeshEdit");
1183
    glutDisplayFunc(display);
1184
    glutKeyboardFunc(keyboard);
1185
    glutSpecialFunc(keyboard_spec);
1186
    glutReshapeFunc(reshape);
1187
    glutMouseFunc(mouse);
1188
    glutMotionFunc(motion);
1189
    glutIdleFunc(animate);
386 jab 1190
}
1191
void init_gl()
1192
{
596 jab 1193
    glewInit();
1194
    glEnable(GL_LIGHTING);
1195
    glEnable(GL_LIGHT0);
1196
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
399 jab 1197
 
596 jab 1198
    // Set the value of a uniform
1199
    //glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
386 jab 1200
 
596 jab 1201
    glMatrixMode(GL_MODELVIEW);
1202
    glLoadIdentity();
1203
    glClearColor(1,1,1, 0.f);
1204
    glColor4f(1.0f, 1.0f, 1.0f, 0.f);
1205
    float material[4] = {1,1,1,1};
1206
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
1207
    glEnable(GL_DEPTH_TEST);
386 jab 1208
 
596 jab 1209
    theConsole.reg_cmdN("harmonics.reset_shape", console_reset_shape, "");
1210
    theConsole.reg_cmdN("harmonics.analyze", console_analyze, "");
1211
    theConsole.reg_cmdN("harmonics.partial_reconstruct", console_partial_reconstruct,"");
1212
    theConsole.reg_cmdN("simplify", console_simplify,"");
1213
    theConsole.reg_cmdN("smooth.mean_curvature", console_mean_curvature_smooth,"");
1214
    theConsole.reg_cmdN("smooth.laplacian", console_laplacian_smooth,"");
1215
    theConsole.reg_cmdN("smooth.taubin", console_taubin_smooth,"");
1216
    theConsole.reg_cmdN("smooth.fuzzy_vector_median", console_fvm_smooth,"");
391 jab 1217
 
596 jab 1218
    theConsole.reg_cmdN("optimize.valency", console_optimize_valency,"");
1219
    theConsole.reg_cmdN("optimize.minimize_dihedral_angles", console_minimize_dihedral,"");
1220
    theConsole.reg_cmdN("optimize.minimize_curvature", console_minimize_curvature,"");
1221
    theConsole.reg_cmdN("optimize.maximize_min_angle", console_maximize_min_angle,"");
1222
    theConsole.reg_cmdN("cleanup.close_holes", console_close_holes,"");
1223
    theConsole.reg_cmdN("load_mesh", console_reload,"");
1224
    theConsole.reg_cmdN("add_mesh", console_add_mesh,"");
391 jab 1225
 
596 jab 1226
    theConsole.reg_cmdN("cleanup.remove_caps", console_remove_caps,"");
1227
    theConsole.reg_cmdN("cleanup.remove_needles", console_remove_needles,"");
1228
    theConsole.reg_cmdN("triangulate", console_triangulate,"");
1229
    theConsole.reg_cmdN("refine.split_edges", console_refine_edges,"");
1230
    theConsole.reg_cmdN("refine.split_faces", console_refine_faces,"");
1231
    theConsole.reg_cmdN("refine.catmull_clark", console_cc_subdivide,"");
1232
    theConsole.reg_cmdN("refine.doo_sabin", console_doosabin_subdivide,"");
1233
    theConsole.reg_cmdN("save_mesh", console_save,"");
1234
    theConsole.reg_cmdN("noise.perturb_vertices", console_vertex_noise,"");
1235
    theConsole.reg_cmdN("noise.perturb_vertices_perpendicular", console_perpendicular_vertex_noise,"");
1236
    theConsole.reg_cmdN("noise.perturb_topology", console_noisy_flips,"");
1237
 
600 jab 1238
    theConsole.reg_cmdN("remove_faces", console_remove_faces,"");
1239
 
596 jab 1240
    theConsole.reg_cmdN("dual", console_dual,"");
1241
    theConsole.reg_cmdN("flatten", console_flatten,"");
399 jab 1242
 
596 jab 1243
    theConsole.reg_cmdN("align", console_align,"");
399 jab 1244
 
596 jab 1245
    theConsole.reg_cmdN("undo", console_undo,"");
387 jab 1246
 
596 jab 1247
	theConsole.reg_cmdN("validity", console_valid,"");
1248
	theConsole.reg_cmdN("info", console_info,"");
1249
 
1250
    theConsole.reg_cmdN("polarize", console_polarize ,"");
1251
 
618 jab 1252
    theConsole.reg_cmdN("transform.scale", console_scale, "Scale mesh");
1253
 
596 jab 1254
    active.reg(theConsole, "active_mesh", "The active mesh");
1255
    display_render_mode.reg(theConsole, "display.render_mode", "Display render mode");
1256
    display_smooth_shading.reg(theConsole, "display.smooth_shading", "1 for smooth shading 0 for flat");
1257
    display_gamma.reg(theConsole, "display.gamma", "The gamma setting for the display");
1258
 
386 jab 1259
}
1260
 
1261
int main(int argc, char** argv)
1262
{
596 jab 1263
    ArgExtracter ae(argc, argv);
391 jab 1264
 
596 jab 1265
    init_glut(argc, argv);
1266
    init_gl();
391 jab 1267
 
596 jab 1268
    theConsole.print("Welcome to MeshEdit");
1269
    theConsole.newline();
614 jab 1270
 
596 jab 1271
    if(argc>1){		
1272
        vector<string> files;
1273
		ae.get_all_args(files);
607 jrf 1274
		for(size_t i=1;i<files.size();++i)
596 jab 1275
			get_vis_obj(i-1).reload(files[i]);
1276
    }
1277
    glutMainLoop();
1278
    return 0;
386 jab 1279
}
1280
 
1281
 
596 jab 1282
 
1283
 
1284