Subversion Repositories gelsvn

Rev

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