Subversion Repositories gelsvn

Rev

Rev 662 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
647 janba 1
//
2
//  MeshEditor.cpp
3
//  GEL
4
//
5
//  Created by J. Andreas Bærentzen on 09/10/13.
6
//
7
//
662 janba 8
#include <thread>
9
#include <unistd.h>
647 janba 10
#include <GL/glew.h>
11
#include <functional>
12
#include "MeshEditor.h"
13
#include <string>
14
#include <iostream>
15
#include <vector>
16
#include <algorithm>
17
#include <queue>
18
 
19
#include <GLGraphics/Console.h>
20
 
21
#include <CGLA/eigensolution.h>
22
#include <CGLA/Vec2d.h>
23
#include <CGLA/Vec3d.h>
24
#include <CGLA/Mat3x3d.h>
25
#include <CGLA/Mat2x2d.h>
26
#include <CGLA/Mat2x3d.h>
27
#include <CGLA/Mat4x4d.h>
28
 
29
#include <LinAlg/Matrix.h>
30
#include <LinAlg/Vector.h>
31
#include <LinAlg/LapackFunc.h>
32
 
33
#include <HMesh/Manifold.h>
34
#include <HMesh/AttributeVector.h>
35
#include <HMesh/mesh_optimization.h>
36
#include <HMesh/curvature.h>
37
#include <HMesh/triangulate.h>
38
#include <HMesh/flatten.h>
39
#include <HMesh/dual.h>
40
#include <HMesh/load.h>
41
#include <HMesh/quadric_simplify.h>
42
#include <HMesh/smooth.h>
43
#include <HMesh/x3d_save.h>
44
#include <HMesh/obj_save.h>
45
#include <HMesh/off_save.h>
46
#include <HMesh/mesh_optimization.h>
47
#include <HMesh/triangulate.h>
48
#include <HMesh/cleanup.h>
49
#include <HMesh/cleanup.h>
50
#include <HMesh/refine_edges.h>
51
#include <HMesh/subdivision.h>
52
#include <HMesh/harmonics.h>
53
 
54
#include <Util/Timer.h>
55
 
56
#include "VisObj.h"
57
 
58
using namespace std;
59
using namespace CGLA;
60
using namespace HMesh;
61
using namespace Util;
62
 
63
namespace GLGraphics {
64
 
65
    namespace {
66
 
67
        bool wantshelp(const std::vector<std::string> & args)
68
        {
69
            if(args.size() == 0)
70
                return false;
71
 
72
            string str = args[0];
73
 
74
            if(str=="help" || str=="HELP" || str=="Help" || str=="?")
75
                return true;
76
 
77
            return false;
78
        }
79
 
80
 
81
        bool wantshelp(MeshEditor* me, const std::vector<std::string> & args)
82
        {
83
            if(args.size() == 0)
84
                return false;
85
 
86
            string str = args[0];
87
 
88
            if(str=="help" || str=="HELP" || str=="Help" || str=="?")
89
                return true;
90
 
91
            return false;
92
        }
93
 
94
        /// Function that aligns two meshes.
95
        void console_align(MeshEditor* me, const std::vector<std::string> & args)
96
        {
97
            if(wantshelp(args)) {
98
                me->printf("usage: align <dest> <src>");
99
                me->printf("This function aligns dest mesh with src");
100
                me->printf("In practice the GLViewController of src is copied to dst.");
101
                me->printf("both arguments are mandatory and must be numbers between 1 and 9.");
102
                me->printf("Note that results might be unexpexted if the meshes are not on the same scale");
103
            }
104
 
105
            int dest = 0;
106
 
107
            if(args.size()>0){
108
                istringstream a0(args[0]);
109
                a0 >> dest;
110
                --dest;
111
 
112
                if(dest <0 || dest>8)
113
                {
114
                    me->printf("dest mesh out of range (1-9)");
115
                    return;
116
                }
117
            }
118
            else
119
            {
120
                me->printf("neither source nor destination mesh?!");
121
                return;
122
            }
123
 
124
            int src = 0;
125
            if(args.size()>1){
126
                istringstream a1(args[1]);
127
                a1 >> src;
128
                --src;
129
 
130
                if(src <0 || src>8)
131
                {
132
                    me->printf("src mesh out of range (1-9)");
133
                    return;
134
                }
135
            }
136
            else
137
            {
138
                me->printf("no src mesh?");
139
                return;
140
            }
141
            me->align(src,dest);
142
        }
143
 
144
 
145
 
146
 
147
        void console_ridge_lines(MeshEditor* me, const std::vector<std::string> & args)
148
        {
149
            if(wantshelp(args)) {
150
                me->printf("usage: ridge_lines");
151
                return;
152
            }
153
 
154
            me->save_active_mesh();
155
 
156
            Manifold& mani = me->active_mesh();
157
 
158
            VertexAttributeVector<Mat3x3d> curvature_tensors(mani.allocated_vertices());
159
            VertexAttributeVector<Vec3d> min_curv_direction(mani.allocated_vertices());
160
            VertexAttributeVector<Vec3d> max_curv_direction(mani.allocated_vertices());
161
            VertexAttributeVector<Vec2d> curvature(mani.allocated_vertices());
162
 
163
 
164
 
165
            curvature_paraboloids(mani,
166
                                  min_curv_direction,
167
                                  max_curv_direction,
168
                                  curvature);
169
 
170
            for(auto vid : mani.vertices())
171
            {
172
                Vec3d max_curv_dir = normalize(max_curv_direction[vid]);
173
                Vec3d min_curv_dir = normalize(min_curv_direction[vid]);
174
                double vid_min_pc = curvature[vid][0];
175
                double vid_max_pc = curvature[vid][1];
176
                bool ridge = true;
177
                bool ravine = true;
178
                Walker w = mani.walker(vid);
179
                Vec3d r(0);
180
                for(; !w.full_circle();w = w.circulate_vertex_ccw())
181
                {
182
                    Vec3d e = (mani.pos(w.vertex()) - mani.pos(vid));
183
 
184
                    if(abs(dot(min_curv_dir,e)) > abs(dot(max_curv_dir,e)))
185
                    {
186
                        if(curvature[w.vertex()][0]<vid_min_pc+20)
187
                            ravine = false;
188
 
189
                    }
190
                    else
191
                    {
192
                        if(curvature[w.vertex()][1]>vid_max_pc-20)
193
                            ridge = false;
194
                    }
195
                }
196
                DebugRenderer::vertex_colors[vid] = Vec3f(ridge,ravine,0.0);
197
            }
198
            for(auto fid : mani.faces())
199
                DebugRenderer::face_colors[fid] = Vec3f(.3,.3,.6);
200
            for(auto hid : mani.halfedges()) {
201
 
202
                Walker w = mani.walker(hid);
203
                Vec3f c0 = DebugRenderer::vertex_colors[w.opp().vertex()];
204
                Vec3f c1 = DebugRenderer::vertex_colors[w.vertex()];
205
 
206
                DebugRenderer::edge_colors[hid] = (c0==c1) ? c0 : Vec3f(0.1,0.1,0.3);
207
 
208
            }
209
        }
210
 
211
        void transform_mesh(Manifold& mani, const Mat4x4d& m)
212
        {
213
            for(VertexIDIterator vid = mani.vertices_begin(); vid != mani.vertices_end(); ++vid)
214
                mani.pos(*vid) = m.mul_3D_point(mani.pos(*vid));
215
        }
216
 
217
        void console_scale(MeshEditor* me, const std::vector<std::string> & args)
218
        {
219
            if(wantshelp(args)) {
220
                me->printf("usage: scale sx sy sz");
221
                return;
222
            }
223
 
224
            Vec3d s;
225
 
226
            if(args.size() > 0){
227
                istringstream a0(args[0]);
228
                a0 >> s[0];
229
            }
230
            if(args.size() > 1){
231
                istringstream a0(args[0]);
232
                a0 >> s[1];
233
            }
234
            if(args.size() > 2){
235
                istringstream a0(args[0]);
236
                a0 >> s[2];
237
            }
238
 
239
            me->save_active_mesh();
240
            transform_mesh(me->active_mesh(),scaling_Mat4x4d(s));
241
            me->refit();
242
        }
243
 
657 janba 244
        void console_test(MeshEditor* me, const std::vector<std::string> & args)
245
        {
246
            if(wantshelp(args)) {
247
                me->printf("usage: test");
248
                return;
249
            }
250
 
251
            me->save_active_mesh();
252
            me->active_mesh().slit_edges(me->get_vertex_selection());
253
        }
254
 
647 janba 255
 
256
        void console_flatten(MeshEditor* me, const std::vector<std::string> & args)
257
        {
258
            if(wantshelp(args)) {
259
                me->printf("usage: flatten <floater|harmonic|barycentric>");
260
                me->printf("This function flattens a meshs with a simple boundary. It is mostly for showing mesh");
261
                me->printf("parametrization methods. The current mesh MUST have a SINGLE boundary loop");
262
                me->printf("This loop is mapped to the unit circle in a regular fashion (equal angle intervals).");
263
                me->printf("All non boundary vertices are placed at the origin. Then the system is relaxed iteratively");
264
                me->printf("using the weight scheme given as argument.");
265
                return;
266
            }
267
 
268
            me->save_active_mesh();
269
 
270
            WeightScheme ws = BARYCENTRIC_W;
271
            if(args.size()>0){
272
                if(args[0] == "floater")
273
                    ws = FLOATER_W;
274
                else if(args[0] == "harmonic")
275
                    ws = HARMONIC_W;
276
                else if(args[0] == "lscm")
277
                    ws = LSCM_W;
278
            }
279
            else
280
                return;
281
 
282
            flatten(me->active_mesh(), ws);
283
 
284
            return;
285
        }
286
 
287
        void console_save(MeshEditor* me, const std::vector<std::string> & args)
288
        {
289
            if(wantshelp(args)) {
290
                me->printf("usage: save <name->x3d|name->obj> ");
291
 
292
                return;
293
            }
294
            const string& file_name = args[0];
295
            if(args.size() == 1){
296
                if(file_name.substr(file_name.length()-4,file_name.length())==".obj"){
297
                    obj_save(file_name, me->active_mesh());
298
 
299
                    return;
300
                }
301
                else if(file_name.substr(file_name.length()-4,file_name.length())==".off"){
302
                    off_save(file_name, me->active_mesh());
303
 
304
                    return;
305
                }
306
                else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d"){
307
                    x3d_save(file_name, me->active_mesh());
308
 
309
                    return;
310
                }
311
                me->printf("unknown format");
312
                return;
313
            }
314
            me->printf("usage: save <name->x3d|name->obj> ");
315
        }
316
 
317
 
318
        void console_refine_edges(MeshEditor* me, const std::vector<std::string> & args)
319
        {
320
            if(wantshelp(args)) {
321
                me->printf("usage: refine.split_edges <length>");
322
                me->printf("splits edges longer than <length>; default is 0.5 times average length");
323
                return;
324
            }
325
 
326
            me->save_active_mesh();
327
 
328
            float thresh = 0.5f;
329
 
330
            if(args.size() > 0){
331
                istringstream a0(args[0]);
332
                a0 >> thresh;
333
            }
334
 
335
            float avg_length = average_edge_length(me->active_mesh());
336
 
337
            refine_edges(me->active_mesh(), thresh * avg_length);
338
 
339
            return;
340
 
341
        }
342
 
343
        void console_refine_faces(MeshEditor* me, const std::vector<std::string> & args)
344
        {
345
            if(wantshelp(args)) {
346
                me->printf("usage: refine.split_faces ");
347
                me->printf("usage:  Takes no arguments. Inserts a vertex at the centre of each face.");
348
 
349
                return;
350
            }
351
            me->save_active_mesh();
352
 
353
            triangulate_by_vertex_face_split(me->active_mesh());
354
 
355
            return;
356
 
357
        }
358
 
359
        void console_cc_subdivide(MeshEditor* me, const std::vector<std::string> & args)
360
        {
361
            if(wantshelp(args)) {
362
                me->printf("usage: subdivide.catmull_clark ");
363
                me->printf("Does one step of Catmull-Clark subdivision");
364
 
365
                return;
366
            }
367
            me->save_active_mesh();
368
 
369
            cc_split(me->active_mesh(),me->active_mesh());
370
            cc_smooth(me->active_mesh());
371
 
372
            return;
373
        }
374
 
375
        void console_loop_subdivide(MeshEditor* me, const std::vector<std::string> & args)
376
        {
377
            if(wantshelp(args)) {
378
                me->printf("usage: subdivide.loop");
379
                me->printf("Does one step of Loop subdivision");
380
 
381
                return;
382
            }
383
            me->save_active_mesh();
384
 
385
            loop_split(me->active_mesh(),me->active_mesh());
386
            loop_smooth(me->active_mesh());
387
 
388
            return;
389
        }
663 janba 390
        void console_stitch(MeshEditor* me, const std::vector<std::string> & args)
391
        {
392
            if(wantshelp(args)) {
393
                me->printf("usage: cleanup.stitch");
394
                me->printf("Stitches faces");
395
 
396
                return;
397
            }
398
            me->save_active_mesh();
399
 
400
            stitch_mesh(me->active_mesh());
401
            return;
402
        }
647 janba 403
 
404
        void console_root3_subdivide(MeshEditor* me, const std::vector<std::string> & args)
405
        {
406
            if(wantshelp(args)) {
407
                me->printf("usage: subdivide.root3");
408
                me->printf("Does one step of sqrt(3) subdivision");
409
 
410
                return;
411
            }
412
            me->save_active_mesh();
413
 
414
            root3_subdivide(me->active_mesh(),me->active_mesh());
415
 
416
            return;
417
        }
418
 
419
 
420
        void console_doosabin_subdivide(MeshEditor* me, const std::vector<std::string> & args)
421
        {
422
            if(wantshelp(args)) {
423
                me->printf("usage: subdivide.doo_sabin ");
424
                me->printf("Does one step of Doo-Sabin Subdivision");
425
 
426
                return;
427
            }
428
            me->save_active_mesh();
429
 
430
            cc_split(me->active_mesh(),me->active_mesh());
431
            dual(me->active_mesh());
432
 
433
            return;
434
        }
435
 
436
        void console_butterfly_subdivide(MeshEditor* me, const std::vector<std::string> & args)
437
        {
438
            if(wantshelp(args)) {
439
                me->printf("usage: subdivide.butterfly ");
440
                me->printf("Does one step of Modified Butterfly Subdivision");
441
 
442
                return;
443
            }
444
            me->save_active_mesh();
445
 
446
            butterfly_subdivide(me->active_mesh(),me->active_mesh());
447
 
448
            return;
449
        }
450
 
451
        void console_dual(MeshEditor* me, const std::vector<std::string> & args)
452
        {
453
            if(wantshelp(args))
454
            {
455
                me->printf("usage: dual ");
456
                me->printf("Produces the dual by converting each face to a vertex placed at the barycenter.");
457
                return;
458
            }
459
            me->save_active_mesh();
460
 
461
            dual(me->active_mesh());
462
 
463
            return;
464
        }
465
 
466
 
467
        void console_minimize_curvature(MeshEditor* me, const std::vector<std::string> & args)
468
        {
469
            if(wantshelp(args))
470
            {
471
                me->printf("usage: optimize.minimize_curvature <anneal>");
472
                me->printf("Flip edges to minimize mean curvature.");
473
                me->printf("If anneal is true, simulated annealing (slow) is used rather than a greedy scheme");
474
                return;
475
            }
476
            me->save_active_mesh();
477
 
478
            bool anneal=false;
479
            if(args.size() > 0)
480
            {
481
                istringstream a0(args[0]);
482
                a0 >> anneal;
483
            }
484
 
485
            minimize_curvature(me->active_mesh(), anneal);
486
            me->post_create_display_list();
487
            return;
488
        }
489
 
490
        void console_minimize_dihedral(MeshEditor* me, const std::vector<std::string> & args)
491
        {
492
            if(wantshelp(args))
493
            {
494
                me->printf("usage: optimize.minimize_dihedral <iter> <anneal> <use_alpha> <gamma> ");
495
                me->printf("Flip edges to minimize dihedral angles.");
496
                me->printf("Iter is the max number of iterations. anneal tells us whether to use ");
497
                me->printf("simulated annealing and not greedy optimization. use_alpha (default=true) ");
498
                me->printf("means to use angle and not cosine of anglegamma (default=4) is the power ");
499
                me->printf("to which we raise the dihedral angle");
500
                return;
501
            }
502
            me->save_active_mesh();
503
 
504
            int iter = 1000;
505
            if(args.size() > 0)
506
            {
507
                istringstream a0(args[0]);
508
                a0 >> iter;
509
            }
510
 
511
            bool anneal = false;
512
            if(args.size() > 1)
513
            {
514
                istringstream a0(args[1]);
515
                a0 >> anneal;
516
            }
517
 
518
            bool use_alpha = true;
519
            if(args.size() > 2)
520
            {
521
                istringstream a0(args[2]);
522
                a0 >> use_alpha;
523
            }
524
 
525
            float gamma = 4.0f;
526
            if(args.size() > 3)
527
            {
528
                istringstream a0(args[3]);
529
                a0 >> gamma;
530
            }
531
 
532
 
533
            minimize_dihedral_angle(me->active_mesh(), iter, anneal, use_alpha, gamma);
534
            return;
535
        }
536
 
537
        void console_maximize_min_angle(MeshEditor* me, const std::vector<std::string> & args)
538
        {
539
            if(wantshelp(args))
540
            {
541
                me->printf("usage: optimize.maximize_min_angle <thresh> <anneal>");
542
                me->printf("Flip edges to maximize min angle - to make mesh more Delaunay.");
543
                me->printf("If the dot product of the normals between adjacent faces < thresh");
544
                me->printf("no flip will be made. anneal selects simulated annealing rather ");
545
                me->printf("nthan greedy optimization.");
546
                return;
547
            }
548
            me->save_active_mesh();
549
 
550
            float thresh = 0.0f;
551
            if(args.size() > 0)
552
            {
553
                istringstream a0(args[0]);
554
                a0 >> thresh;
555
            }
556
            bool anneal = false;
557
            if(args.size() > 1)
558
            {
559
                istringstream a0(args[1]);
560
                a0 >> anneal;
561
            }
562
            maximize_min_angle(me->active_mesh(),thresh,anneal);
563
            return;
564
        }
565
 
566
 
567
        void console_optimize_valency(MeshEditor* me, const std::vector<std::string> & args)
568
        {
569
            if(wantshelp(args))
570
            {
571
                me->printf("usage: optimize.valency <anneal> ");
572
                me->printf("Optimizes valency for triangle meshes. Anneal selects simulated annealing rather than greedy optim.");
573
                return;
574
            }
575
            me->save_active_mesh();
576
 
577
            bool anneal = false;
578
            if(args.size() > 0)
579
            {
580
                istringstream a0(args[0]);
581
                a0 >> anneal;
582
            }
583
            optimize_valency(me->active_mesh(), anneal);
584
            return;
585
        }
586
 
587
            void console_analyze(MeshEditor* me, const std::vector<std::string> & args)
588
            {
589
                if(wantshelp(args))
590
                {
591
                    me->printf("usage:  harmonics.analyze");
592
                    me->printf("Creates the Laplace Beltrami operator for the mesh and finds all eigensolutions.");
593
                    me->printf("It also projects the vertices onto the eigenvectors - thus transforming the mesh");
594
                    me->printf("to this basis.");
595
                    me->printf("Note that this will stall the computer for a large mesh - as long as we use Lapack.");
596
                    return;
597
                }
598
                me->harmonics_analyze_mesh();
599
                return;
600
            }
601
 
602
 
663 janba 603
        void console_partial_reconstruct(MeshEditor* me, const std::vector<std::string> & args)
604
        {
605
            if(args.size() != 3)
606
                me->printf("usage: haramonics.partial_reconstruct <e0> <e1> <s>");
607
 
608
            if(wantshelp(args)) {
609
                me->printf("Reconstruct from projections onto eigenvectors. The two first arguments indicate");
610
                me->printf("the eigenvector interval that we reconstruct from. The last argument is the ");
611
                me->printf("scaling factor. Thus, for a vertex, v, the formula for computing the position, p, is:");
612
                me->printf("for (i=e0; i<=e1;++i) p += proj[i] * Q[i][v] * s;");
613
                me->printf("where proj[i] is the 3D vector containing the x, y, and z projections of the mesh onto");
614
                me->printf("eigenvector i. Q[i][v] is the v'th coordinate of the i'th eigenvector.");
615
                me->printf("Note that if vertex coordinates are not first reset, the result is probably unexpected.");
616
            }
617
            me->save_active_mesh();
618
 
619
            if(args.size() != 3)
620
                return;
621
 
622
            int E0,E1;
623
            float scale;
624
            istringstream a0(args[0]);
625
            a0 >> E0;
626
            istringstream a1(args[1]);
627
            a1 >> E1;
628
            istringstream a2(args[2]);
629
            a2 >> scale;
630
            me->harmonics_partial_reconstruct(E0,E1,scale);
631
            return;
632
        }
647 janba 633
 
663 janba 634
        void console_reset_shape(MeshEditor* me, const std::vector<std::string> & args)
635
        {
636
            if(wantshelp(args))
637
            {
638
                me->printf("usage: harmonics.reset_shape ");
639
                me->printf("Simply sets all vertices to 0,0,0. Call this before doing partial_reconstruct");
640
                me->printf("unless you know what you are doing.");
641
                return;
642
            }
643
            me->save_active_mesh();
644
            me->harmonics_reset_shape();
645
            return;
646
        }
647 janba 647
 
663 janba 648
 
647 janba 649
        void console_close_holes(MeshEditor* me, const std::vector<std::string> & args)
650
        {
651
            if(wantshelp(args))
652
            {
653
                me->printf("usage: cleanup.close_holes");
654
                me->printf("This function closes holes. It simply follows the loop of halfvectors which");
655
                me->printf("enclose the hole and add a face to which they all point.");
656
                return;
657
            }
658
            me->save_active_mesh();
659
 
660
            close_holes(me->active_mesh());
661
            return;
662
        }
663
 
664
        void console_reload(MeshEditor* me, const std::vector<std::string> & args)
665
        {
666
            if(wantshelp(args))
667
            {
668
                me->printf("usage:  load <file>");
669
                me->printf("(Re)loads the current file if no argument is given, but");
670
                me->printf("if an argument is given, then that becomes the current file");
671
                return;
672
            }
673
            me->save_active_mesh();
674
 
675
            if(!me->reload_active_from_file(args.size() > 0 ? args[0]:""))
676
                me->printf("failed to load");
677
 
678
            return;
679
        }
680
 
681
 
682
        void console_add_mesh(MeshEditor* me, const std::vector<std::string> & args)
683
        {
684
            if(wantshelp(args))
685
            {
686
                me->printf("usage:  add_mesh <file>");
687
                me->printf("Loads the file but without clearing the mesh. Thus, the loaded mesh is added to the");
688
                me->printf("current model.");
689
                return;
690
            }
691
            me->save_active_mesh();
692
 
693
            if(!me->add_to_active_from_file(args.size() > 0 ? args[0]:""))
694
                me->printf("failed to load");
695
 
696
            return;
697
        }
698
 
699
        void console_valid(MeshEditor* me, const std::vector<std::string> & args)
700
        {
701
            if(wantshelp(args))
702
            {
703
                me->printf("usage:  validity");
704
                me->printf("Tests validity of Manifold");
705
                return;
706
            }
707
            if(valid(me->active_mesh()))
708
                me->printf("Mesh is valid");
709
            else
710
                me->printf("Mesh is invalid - check console output");
711
            return;
712
        }
713
 
714
        void console_Dijkstra(MeshEditor* me, const std::vector<std::string> & args)
715
        {
716
            if(wantshelp(args))
717
            {
718
                me->printf("usage:  Dijkstra");
719
                return;
720
            }
721
 
722
            Manifold& m = me->active_mesh();
723
 
724
 
725
            VertexAttributeVector<double> dist(m.allocated_vertices(), DBL_MAX);
726
            VertexAttributeVector<int> visited(m.allocated_vertices(), 0);
727
            VertexID v = *m.vertices_begin();
728
            dist[v]=0;
729
            priority_queue<pair<double,VertexID>> pq;
730
            pq.push(make_pair(-dist[v], v));
731
            double max_dist;
732
            while(!pq.empty())
733
            {
734
                VertexID v = pq.top().second;
735
                max_dist = dist[v];
736
                pq.pop();
737
 
738
                if(!visited[v]){
739
                    visited[v]=1;
740
 
741
                    for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_ccw())
742
                        if(!visited[w.vertex()])
743
                        {
744
                            double d = dist[v] + length(m, w.halfedge());
745
                            if(d<dist[w.vertex()]) {
746
                                dist[w.vertex()] = d;
747
                                pq.push(make_pair(-d, w.vertex()));
748
                            }
749
                        }
750
                }
751
            }
752
 
753
            for(auto vid : m.vertices()) {
754
                DebugRenderer::vertex_colors[vid] = Vec3f(1-dist[vid]/max_dist,0,0);
755
                cout << dist[vid] << endl;
756
            }
757
            for(auto fid : m.faces())
758
                DebugRenderer::face_colors[fid] = Vec3f(0.3);
759
 
760
            for(auto hid : m.halfedges()) {
761
                Walker w = m.walker(hid);
762
                DebugRenderer::edge_colors[hid] = Vec3f(1.0-max(dist[w.vertex()],dist[w.opp().vertex()])/max_dist,0,0);
763
            }
764
            return;
765
        }
766
 
767
        void console_info(MeshEditor* me, const std::vector<std::string> & args)
768
        {
769
            if(wantshelp(args))
770
            {
771
                me->printf("usage:  info");
772
                me->printf("Provides information about mesh.");
773
                return;
774
            }
775
            Vec3d p0, p7;
776
            bbox(me->active_mesh(), p0, p7);
777
            stringstream bbox_corners;
778
            bbox_corners << p0 << " - " << p7 << endl;
779
            me->printf("Bounding box corners : %s", bbox_corners.str().c_str());
780
            map<int,int> val_hist;
781
 
782
            for(VertexIDIterator vi = me->active_mesh().vertices_begin(); vi != me->active_mesh().vertices_end(); ++vi)
783
            {
784
                int val = valency(me->active_mesh(), *vi);
785
                if(val_hist.find(val) == val_hist.end())
786
                    val_hist[val] = 0;
787
                ++val_hist[val];
788
            }
789
 
790
            me->printf("Valency histogam");
791
            for(map<int,int>::iterator iter = val_hist.begin(); iter != val_hist.end(); ++iter)
792
            {
793
                stringstream vhl;
794
                vhl << iter->first << ", " << iter->second;
795
                me->printf("%d, %d", iter->first, iter->second);
796
            }
797
 
798
            me->printf("Mesh contains %d faces", me->active_mesh().no_faces());
799
            me->printf("Mesh contains %d halfedges", me->active_mesh().no_halfedges());
800
            me->printf("Mesh contains %d vertices", me->active_mesh().no_vertices());
801
            return;
802
        }
803
 
804
 
805
        void console_simplify(MeshEditor* me, const std::vector<std::string> & args)
806
        {
807
            if(wantshelp(args))
808
            {
809
                me->printf("usage: simplify <fraction> ");
810
                me->printf("Performs Garland Heckbert (quadric based) mesh simplification.");
811
                me->printf("The only argument is the fraction of vertices to keep.");
812
                return;
813
            }
814
            me->save_active_mesh();
815
 
816
            float keep_fraction;
817
            if(args.size() == 0)
818
            {
819
                me->printf("you must specify fraction of vertices to keep");
820
                return;
821
            }
822
            istringstream a0(args[0]);
823
            a0 >> keep_fraction;
824
 
825
            Vec3d p0, p7;
826
            bbox(me->active_mesh(), p0, p7);
827
            Vec3d d = p7-p0;
828
            float s = 1.0/d.max_coord();
829
            Vec3d pcentre = (p7+p0)/2.0;
830
            for(VertexIDIterator vi = me->active_mesh().vertices_begin(); vi != me->active_mesh().vertices_end(); ++vi){
831
                me->active_mesh().pos(*vi) = (me->active_mesh().pos(*vi) - pcentre) * s;
832
            }
833
            cout << "Timing the Garland Heckbert (quadric based) mesh simplication..." << endl;
834
            Timer timer;
835
            timer.start();
836
 
837
            //simplify
838
            quadric_simplify(me->active_mesh(),keep_fraction,0.0001f,true);
839
 
840
            cout << "Simplification complete, process time: " << timer.get_secs() << " seconds" << endl;
841
 
842
            //clean up the mesh, a lot of edges were just collapsed
843
            me->active_mesh().cleanup();
844
 
845
            for(VertexIDIterator vi = me->active_mesh().vertices_begin(); vi != me->active_mesh().vertices_end(); ++vi)
846
                me->active_mesh().pos(*vi) = me->active_mesh().pos(*vi)*d.max_coord() + pcentre;
847
            return;
848
        }
849
 
850
        void console_vertex_noise(MeshEditor* me, const std::vector<std::string> & args)
851
        {
852
            if(wantshelp(args))
853
            {
854
                me->printf("usage: noise.perturb_vertices <amplitude>");
855
                me->printf("adds a random vector to each vertex. A random vector in the unit cube is generated and");
856
                me->printf("to ensure an isotropic distribution, vectors outside the unit ball are discarded.");
857
                me->printf("The vector is multiplied by the average edge length and then by the amplitude specified.");
858
                me->printf("If no amplitude is specified, the default (0.5) is used.");
859
                return;
860
            }
861
            me->save_active_mesh();
862
 
863
            float avg_length = average_edge_length(me->active_mesh());
864
 
865
            float noise_amplitude = 0.5f;
866
            if(args.size() > 0) {
867
                istringstream a0(args[0]);
868
                a0 >> noise_amplitude;
869
            }
870
 
871
            gel_srand(0);
872
            for(VertexIDIterator vi = me->active_mesh().vertices_begin(); vi != me->active_mesh().vertices_end(); ++vi){
873
                Vec3d v;
874
                do{
875
                    v = Vec3d(gel_rand(),gel_rand(),gel_rand());
876
                    v /= (float)(GEL_RAND_MAX);
877
                    v -= Vec3d(0.5);
878
                    v *= 2.0;
879
                }
880
                while(sqr_length(v) > 1.0);
881
 
882
                v *= noise_amplitude;
883
                v *= avg_length;
884
                me->active_mesh().pos(*vi) += v;
885
            }
886
            return;
887
        }
888
 
889
        void console_perpendicular_vertex_noise(MeshEditor* me, const std::vector<std::string> & args)
890
        {
891
            if(wantshelp(args)) {
892
                me->printf("usage: noise.perturb_vertices_perpendicular <amplitude>");
893
                me->printf("adds the normal times a random scalar times amplitude times");
894
                me->printf("times average edge length to the vertex. (default amplitude=0.5)");
895
                return;
896
            }
897
            me->save_active_mesh();
898
 
899
            float avg_length = average_edge_length(me->active_mesh());
900
 
901
            float noise_amplitude = 0.5;
902
            if(args.size() > 0)
903
            {
904
                istringstream a0(args[0]);
905
                a0 >> noise_amplitude;
906
            }
907
 
908
            VertexAttributeVector<Vec3d> normals(me->active_mesh().allocated_vertices());
909
            for(VertexIDIterator vi = me->active_mesh().vertices_begin(); vi != me->active_mesh().vertices_end(); ++vi)
910
                normals[*vi] = normal(me->active_mesh(), *vi);
911
 
912
            gel_srand(0);
913
            for(VertexIDIterator vi = me->active_mesh().vertices_begin(); vi != me->active_mesh().vertices_end(); ++vi)
914
            {
915
                float rval = 0.5-gel_rand() / float(GEL_RAND_MAX);
916
                me->active_mesh().pos(*vi) += normals[*vi]*rval*noise_amplitude*avg_length*2.0;
917
            }
918
            return;
919
        }
920
 
921
        void console_noisy_flips(MeshEditor* me, const std::vector<std::string> & args)
922
        {
923
            if(wantshelp(args)){
924
                me->printf("usage:  noise.perturb_topology <iter>");
925
                me->printf("Perform random flips. iter (default=1) is the number of iterations.");
926
                me->printf("mostly for making nasty synthetic test cases.");
927
                return;
928
            }
929
            me->save_active_mesh();
930
 
931
            int iter = 1;
932
            if(args.size() > 0){
933
                istringstream a0(args[0]);
934
                a0 >> iter;
935
            }
936
 
937
            randomize_mesh(me->active_mesh(),  iter);
938
            return;
939
        }
940
 
941
        void console_laplacian_smooth(MeshEditor* me, const std::vector<std::string> & args)
942
        {
943
            if(wantshelp(args)) {
944
                me->printf("usage:  smooth.laplacian <weight> <iter>");
945
                me->printf("Perform Laplacian smoothing. weight is the scaling factor for the Laplacian.");
946
                me->printf("default weight = 1.0. Default number of iterations = 1");
947
                return;
948
            }
949
            me->save_active_mesh();
950
 
951
            float t=1.0;
952
            if(args.size() > 0){
953
                istringstream a0(args[0]);
954
                a0 >> t;
955
            }
956
            int iter = 1;
957
            if(args.size()>1){
958
                istringstream a0(args[1]);
959
                a0 >> iter;
960
            }
961
            Util::Timer tim;
962
            tim.start();
963
            /// Simple laplacian smoothing with an optional weight.
964
            laplacian_smooth(me->active_mesh(), t, iter);
965
            cout << "It took "<< tim.get_secs();
966
            return;
967
        }
968
 
969
 
970
        void console_mean_curvature_smooth(MeshEditor* me, const std::vector<std::string> & args){
971
            if(wantshelp(args)) {
972
                me->printf("usage:  smooth.mean_curvature <weight> <iter>");
973
                me->printf("Perform mean curvature smoothing. weight is the scaling factor for the");
974
                me->printf("mean curvature vector which has been normalized by dividing by edge lengths");
975
                me->printf("this allows for larger steps as suggested by Desbrun et al.");
976
                me->printf("default weight = 1.0. Default number of iterations = 1");
977
                return;
978
            }
979
            me->save_active_mesh();
980
 
981
            double t=1.0;
982
            if(args.size() > 0){
983
                istringstream a0(args[0]);
984
                a0 >> t;
985
            }
986
            int iter=1;
987
            if(args.size() > 1){
988
                istringstream a0(args[1]);
989
                a0 >> iter;
990
            }
991
            VertexAttributeVector<Vec3d> new_pos(me->active_mesh().allocated_vertices());
992
            for(int j = 0; j < iter; ++j){
993
                for(VertexIDIterator v = me->active_mesh().vertices_begin(); v != me->active_mesh().vertices_end(); ++v) {
994
                    Vec3d m;
995
                    double w_sum;
996
                    unnormalized_mean_curvature_normal(me->active_mesh(), *v, m, w_sum);
997
                    new_pos[*v] = Vec3d(me->active_mesh().pos(*v))  + (t * m/w_sum);
998
                }
999
                for(VertexIDIterator v = me->active_mesh().vertices_begin(); v != me->active_mesh().vertices_end(); ++v)
1000
                    me->active_mesh().pos(*v) = new_pos[*v];
1001
            }
1002
            return;
1003
        }
1004
 
1005
        void console_taubin_smooth(MeshEditor* me, const std::vector<std::string> & args)
1006
        {
1007
            if(wantshelp(args)){
1008
                me->printf("usage:  smooth.taubin <iter>");
1009
                me->printf("Perform Taubin smoothing. iter (default=1) is the number of iterations.");
1010
                return;
1011
            }
1012
            me->save_active_mesh();
1013
 
1014
            int iter = 1;
1015
            if(args.size() > 0){
1016
                istringstream a0(args[0]);
1017
                a0 >> iter;
1018
            }
1019
            /// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
1020
            taubin_smooth(me->active_mesh(),  iter);
1021
 
1022
            return;
1023
        }
1024
 
1025
        void console_fvm_anisotropic_smooth(MeshEditor* me, const std::vector<std::string> & args)
1026
        {
1027
            if(wantshelp(args)){
1028
                me->printf("usage: smooth.fuzzy_vector_median <iter>");
1029
                me->printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
1030
                me->printf("This function does a very good job of preserving sharp edges.");
1031
                return;
1032
            }
1033
            me->save_active_mesh();
1034
 
1035
            int iter=1;
1036
            if(args.size() > 0){
1037
                istringstream a0(args[0]);
1038
                a0 >> iter;
1039
            }
1040
            // Fuzzy vector median smoothing is effective when it comes to preserving sharp edges.
1041
            anisotropic_smooth(me->active_mesh(),  iter, FVM_NORMAL_SMOOTH);
1042
 
1043
            return;
1044
        }
1045
 
1046
        void console_bilateral_anisotropic_smooth(MeshEditor* me, const std::vector<std::string> & args)
1047
        {
1048
            if(wantshelp(args)){
1049
                me->printf("usage: smooth.fuzzy_vector_median <iter>");
1050
                me->printf("Smooth normals using fuzzy vector median smoothing. iter (default=1) is the number of iterations");
1051
                me->printf("This function does a very good job of preserving sharp edges.");
1052
                return;
1053
            }
1054
            me->save_active_mesh();
1055
 
1056
            int iter=1;
1057
            if(args.size() > 0){
1058
                istringstream a0(args[0]);
1059
                a0 >> iter;
1060
            }
1061
 
1062
            anisotropic_smooth(me->active_mesh(),  iter, BILATERAL_NORMAL_SMOOTH);
1063
 
1064
            return;
1065
        }
1066
 
1067
        void console_triangulate(MeshEditor* me, const std::vector<std::string> & args)
1068
        {
1069
            if(wantshelp(args)) {
1070
                me->printf("usage:  triangulate");
1071
                me->printf("This function triangulates all non triangular faces of the mesh.");
1072
                me->printf("you may want to call it after hole closing. For a polygon it simply connects");
1073
                me->printf("the two closest vertices in a recursive manner until only triangles remain");
1074
                return;
1075
            }
1076
            me->save_active_mesh();
1077
 
1078
            shortest_edge_triangulate(me->active_mesh());
1079
            me->active_mesh().cleanup();
1080
            valid(me->active_mesh());
1081
            return;
1082
        }
1083
 
1084
 
1085
        void console_remove_caps(MeshEditor* me, const std::vector<std::string> & args)
1086
        {
1087
            if(wantshelp(args)) {
1088
                me->printf("usage:  cleanup.remove_caps thresh");
1089
                me->printf("Remove caps (triangles with one very big angle). The thresh argument is the fraction of PI to");
1090
                me->printf("use as threshold for big angle. Default is 0.85. Caps are removed by flipping.");
1091
                return;
1092
            }
1093
            me->save_active_mesh();
1094
 
1095
            float t = 0.85f;
1096
            if(args.size() > 0){
1097
                istringstream a0(args[0]);
1098
                a0 >> t;
1099
            }
1100
            remove_caps(me->active_mesh(), static_cast<float>(M_PI) *t);
1101
            me->active_mesh().cleanup();
1102
 
1103
            return;
1104
        }
1105
 
1106
        void console_remove_needles(MeshEditor* me, const std::vector<std::string> & args)
1107
        {
1108
            if(wantshelp(args)){
1109
                me->printf("usage: cleanup.remove_needles <thresh>");
1110
                me->printf("Removes very short edges by collapse. thresh is multiplied by the average edge length");
1111
                me->printf("to get the length shorter than which we collapse. Default = 0.1");
1112
                return;
1113
            }
1114
            me->save_active_mesh();
1115
 
1116
            float thresh = 0.1f;
1117
            if(args.size() > 0){
1118
                istringstream a0(args[0]);
1119
                a0 >> thresh;
1120
            }
1121
            float avg_length = average_edge_length(me->active_mesh());
1122
            remove_needles(me->active_mesh(), thresh * avg_length);
1123
            me->active_mesh().cleanup();
1124
 
1125
            return;
1126
        }
1127
 
1128
        void console_undo(MeshEditor* me, const std::vector<std::string> & args)
1129
        {
1130
            if(wantshelp(args)) {
1131
                me->printf("usage:  undo");
1132
                me->printf("This function undoes one operation. Repeated undo does nothing");
1133
                return;
1134
            }
1135
            me->restore_active_mesh();
1136
            return;
1137
        }
1138
 
662 janba 1139
        void console_save_trackball(MeshEditor* me, const std::vector<std::string> & args)
1140
        {
1141
            if(wantshelp(args)) {
1142
                me->printf("usage:  display.save_trackball");
1143
                me->printf("This function saves the trackball to disk");
1144
                return;
1145
            }
1146
            me->save_ball();
1147
            return;
1148
        }
1149
 
1150
        void console_load_trackball(MeshEditor* me, const std::vector<std::string> & args)
1151
        {
1152
            if(wantshelp(args)) {
1153
                me->printf("usage:  display.load_trackball");
1154
                me->printf("This function loads the trackball from disk");
1155
                return;
1156
            }
1157
            me->load_ball();
1158
            return;
1159
        }
1160
 
647 janba 1161
 
1162
    }
1163
 
1164
 
1165
    void MeshEditor::register_console_function(const std::string& name,
1166
                                               const std::function<void(MeshEditor*, const std::vector<std::string>&)>& con_fun,
1167
                                               const std::string& help_txt)
1168
    {
1169
        std::function<void (const std::vector<std::string>&)> f = bind(con_fun, this, placeholders::_1);
1170
        theConsole.reg_cmdN(name, f, help_txt);
1171
    }
1172
 
1173
    void MeshEditor::keyparse(unsigned short key){
1174
        //toggle console with ESC
1175
        if (key == 27)
1176
        {
1177
            console_visible = !console_visible;
1178
            return;
1179
        }
1180
 
1181
        if (console_visible)
1182
        {
662 janba 1183
            static Timer tim;
1184
            if(key==13)
1185
                tim.start();
647 janba 1186
            theConsole.keyboard(key);
1187
            if(key == 13)
1188
            {
1189
                active_visobj().post_create_display_list();
662 janba 1190
                double t = tim.get_secs();
1191
                printf("%f seconds",t);
647 janba 1192
            }
1193
            return;
1194
        }
1195
        else {
1196
 
1197
            switch(key) {
1198
                case 'q': exit(0);
1199
                case '\033':
1200
                    console_visible = false;
1201
                    break;
1202
                case '1':
1203
                case '2':
1204
                case '3':
1205
                case '4':
1206
                case '5':
1207
                case '6':
1208
                case '7':
1209
                case '8':
1210
                case '9':
1211
                {
1212
                    int w[4];
1213
                    glGetIntegerv(GL_VIEWPORT, w);
1214
                    active = key - '1';
1215
                    active_view_control().reshape(w[2],w[3]);
1216
                }
1217
                    break;
1218
                case 'f': display_smooth_shading = !display_smooth_shading; break;
1219
                case 'w':
1220
                    display_render_mode = "wire"; break;
1221
                case 'n':
1222
                    display_render_mode = "normal"; break;
1223
                case 'i':
1224
                    display_render_mode = "isophotes"; break;
1225
                case 'r':
1226
                    display_render_mode = "reflection"; break;
1227
                case 'h':
1228
                    display_render_mode = "harmonics"; break;
1229
                case 't':
1230
                    display_render_mode = "toon"; break;
1231
                case 'g':
1232
                    display_render_mode = "glazed"; break;
1233
                case 'a':
1234
                    display_render_mode = "ambient_occlusion"; break;
1235
                case 'c':
1236
                    display_render_mode = "copper"; break;
1237
                case 'C':
1238
                    display_render_mode = "curvature_lines"; break;
1239
                case 'M':
1240
                    display_render_mode = "mean_curvature"; break;
1241
                case 'G':
1242
                    display_render_mode = "gaussian_curvature"; break;
657 janba 1243
                case ' ':
1244
                    active_visobj().clear_selection();
1245
                    break;
1246
 
647 janba 1247
            }
1248
 
1249
            if(key != '\033') post_create_display_list();
1250
        }
1251
 
1252
    }
1253
 
1254
    void MeshEditor::printf(const char* format, ...)
1255
    {
1256
        //format text
1257
        char buffer[1024];
1258
        va_list args;
1259
        va_start(args, format);
1260
        vsprintf(buffer, format, args);
1261
        va_end(args);
1262
        theConsole.print(buffer);
1263
    }
1264
 
1265
    void MeshEditor::key_up(){theConsole.key_up();}
1266
    void MeshEditor::key_down(){theConsole.key_down();}
1267
    void MeshEditor::key_left(){theConsole.key_left();}
1268
    void MeshEditor::key_right(){theConsole.key_right();}
1269
    void MeshEditor::key_home(){theConsole.key_home();}
1270
    void MeshEditor::key_end(){theConsole.key_end();}
1271
 
662 janba 1272
 
1273
 
647 janba 1274
    void MeshEditor::grab_ball(TrackBallAction action, const CGLA::Vec2i& pos){
1275
        active_view_control().grab_ball(action, pos);
1276
    }
1277
    void MeshEditor::roll_ball(const CGLA::Vec2i& pos){
1278
        active_view_control().roll_ball(pos);
1279
    }
1280
    void MeshEditor::release_ball(){
1281
        active_view_control().release_ball();
1282
    }
1283
    bool MeshEditor::try_spinning_ball(){
1284
        return active_view_control().try_spin();
1285
    }
1286
 
662 janba 1287
    void MeshEditor::save_ball() {
1288
        ofstream ofs("trackball.bin", ios_base::binary);
1289
        active_view_control().save(ofs);
1290
 
1291
    }
1292
    void MeshEditor::load_ball() {
1293
        ifstream ifs("trackball.bin", ios_base::binary);
1294
        active_view_control().load(ifs);
1295
 
1296
    }
1297
 
1298
 
656 janba 1299
    bool MeshEditor::grab_mesh(const CGLA::Vec2i& pos)
1300
    {
1301
        if(depth_pick(pos[0], pos[1], depth))
1302
        {
1303
            dragging = true;
1304
            mouse_x = pos[0];
1305
            mouse_y = pos[1];
1306
            Vec3d p0 = screen2world(mouse_x, mouse_y, depth);
1307
            Manifold& m = active_mesh();
1308
            active_visobj().save_old();
1309
            Vec3d c;
1310
            float r;
1311
            bsphere(m, c, r);
1312
            for(auto vid : m.vertices())
1313
            {
1314
                double l = sqr_length(p0-m.pos(vid));
657 janba 1315
                weight_vector[vid] = exp(-l/(brush_size*r*r));
656 janba 1316
            }
1317
            return true;
1318
        }
1319
        return false;
1320
    }
1321
 
1322
    bool MeshEditor::drag_mesh(const CGLA::Vec2i& pos)
1323
    {
1324
        if(dragging)
1325
        {
1326
            Vec3d p0 = screen2world(mouse_x, mouse_y, depth);
1327
            Vec3d p1 = screen2world(pos[0], pos[1], depth);
1328
            Vec3d v = p1-p0;
1329
            Manifold& m = active_mesh();
1330
            for(auto vid : m.vertices())
1331
                m.pos(vid) = active_visobj().mesh_old().pos(vid) + weight_vector[vid] * v;
1332
            post_create_display_list();
1333
            return true;
1334
        }
1335
        return false;
1336
    }
1337
 
1338
    void MeshEditor::release_mesh()
1339
    {
1340
        dragging = false;
1341
    }
647 janba 1342
 
656 janba 1343
 
662 janba 1344
    mutex parallel_work;
647 janba 1345
    void MeshEditor::display(int scale){
1346
        glClearColor(1, 1, 1, 0);
1347
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
662 janba 1348
 
1349
//        parallel_work.lock();
1350
//        active_visobj().post_create_display_list();
647 janba 1351
        active_visobj().display(display_render_mode, theConsole, display_smooth_shading, display_gamma);
1352
        if(console_visible)
1353
        {
1354
            glUseProgram(0);
1355
            theConsole.display(scale);
1356
        }
662 janba 1357
//        parallel_work.unlock();
1358
//        std::this_thread::sleep_for(std::chrono::milliseconds(10));
647 janba 1359
    }
1360
 
1361
    void MeshEditor::reshape(int w, int h) {
1362
        for(VisObj& v : vo)
1363
            v.view_control().reshape(w, h);
1364
    }
1365
 
1366
    void MeshEditor::init() {
1367
        glewInit();
1368
 
1369
        GLint vp[4];
1370
        glGetIntegerv(GL_VIEWPORT, vp);
1371
        for(VisObj& vis_obj : vo)
1372
            vis_obj.view_control().reshape(vp[2], vp[3]);
1373
 
1374
        glEnable(GL_CULL_FACE);
1375
        glCullFace(GL_BACK);
1376
        glEnable(GL_LIGHTING);
1377
        glEnable(GL_LIGHT0);
1378
        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
1379
 
1380
        glMatrixMode(GL_MODELVIEW);
1381
        glLoadIdentity();
1382
        glClearColor(1,1,0, 0.f);
1383
        glColor4f(1.0f, 1.0f, 1.0f, 0.f);
1384
        float material[4] = {1,1,1,1};
1385
        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material);
1386
        glEnable(GL_DEPTH_TEST);
1387
 
1388
        register_console_function("simplify", console_simplify,"");
1389
 
1390
        register_console_function("ridge_lines", console_ridge_lines,"");
1391
 
1392
        register_console_function("smooth.mean_curvature", console_mean_curvature_smooth,"");
1393
        register_console_function("smooth.laplacian", console_laplacian_smooth,"");
1394
        register_console_function("smooth.taubin", console_taubin_smooth,"");
1395
        register_console_function("smooth.fuzzy_vector_median_anisotropic", console_fvm_anisotropic_smooth ,"");
1396
        register_console_function("smooth.bilateral_anisotropic", console_bilateral_anisotropic_smooth ,"");
1397
 
1398
        register_console_function("optimize.valency", console_optimize_valency,"");
1399
        register_console_function("optimize.minimize_dihedral_angles", console_minimize_dihedral,"");
1400
        register_console_function("optimize.minimize_curvature", console_minimize_curvature,"");
1401
        register_console_function("optimize.maximize_min_angle", console_maximize_min_angle,"");
1402
        register_console_function("cleanup.close_holes", console_close_holes,"");
1403
        register_console_function("load_mesh", console_reload,"");
1404
        register_console_function("add_mesh", console_add_mesh,"");
1405
 
663 janba 1406
        register_console_function("cleanup.stitch", console_stitch,"");
647 janba 1407
        register_console_function("cleanup.remove_caps", console_remove_caps,"");
1408
        register_console_function("cleanup.remove_needles", console_remove_needles,"");
1409
        register_console_function("triangulate", console_triangulate,"");
1410
        register_console_function("refine.split_edges", console_refine_edges,"");
1411
        register_console_function("refine.split_faces", console_refine_faces,"");
1412
        register_console_function("subdivide.catmull_clark", console_cc_subdivide,"");
1413
        register_console_function("subdivide.loop", console_loop_subdivide,"");
1414
        register_console_function("subdivide.root3", console_root3_subdivide,"");
1415
        register_console_function("subdivide.doo_sabin", console_doosabin_subdivide,"");
1416
        register_console_function("subdivide.butterfly", console_butterfly_subdivide,"");
1417
        register_console_function("save_mesh", console_save,"");
1418
        register_console_function("noise.perturb_vertices", console_vertex_noise,"");
1419
        register_console_function("noise.perturb_vertices_perpendicular", console_perpendicular_vertex_noise,"");
1420
        register_console_function("noise.perturb_topology", console_noisy_flips,"");
1421
 
1422
        register_console_function("dual", console_dual,"");
1423
        register_console_function("flatten", console_flatten,"");
1424
 
1425
        register_console_function("align", console_align,"");
1426
        register_console_function("undo", console_undo,"");
1427
 
1428
        register_console_function("validity", console_valid,"");
1429
        register_console_function("info", console_info,"");
1430
 
663 janba 1431
        register_console_function("harmonics.reset_shape", console_reset_shape, "");
647 janba 1432
        register_console_function("harmonics.analyze", console_analyze, "");
663 janba 1433
        register_console_function("harmonics.partial_reconstruct", console_partial_reconstruct,"");
647 janba 1434
 
1435
        register_console_function("Dijkstra", console_Dijkstra,"");
1436
 
662 janba 1437
        register_console_function("display.save_trackball", console_save_trackball, "Saves trackball to disk");
1438
        register_console_function("display.load_trackball", console_load_trackball, "Load trackball to disk");
1439
 
647 janba 1440
        register_console_function("transform.scale", console_scale, "Scale mesh");
657 janba 1441
        register_console_function("test", console_test, "Test some shit");
647 janba 1442
        active.reg(theConsole, "active_mesh", "The active mesh");
1443
        display_render_mode.reg(theConsole, "display.render_mode", "Display render mode");
657 janba 1444
        brush_size.reg(theConsole, "brush_size", "Size of brush used for editing");
647 janba 1445
        display_smooth_shading.reg(theConsole, "display.smooth_shading", "1 for smooth shading 0 for flat");
1446
        display_gamma.reg(theConsole, "display.gamma", "The gamma setting for the display");
1447
 
1448
        theConsole.print("Welcome to MeshEdit");
1449
        theConsole.newline();
1450
    }
1451
 
1452
    bool MeshEditor::add_file(const std::string& str)
1453
    {
1454
        while (active_mesh().no_vertices()>0 && active<NO_MESHES)
1455
            active  = active + 1;
1456
        if(active == NO_MESHES)
1457
            active = 0;
1458
        if(active_visobj().reload(str)) {
1459
            active_visobj().post_create_display_list();
1460
            return true;
1461
        }
1462
        return false;
1463
    }
1464
 
1465
    bool MeshEditor::reload_active_from_file(const std::string& str)
1466
    {
1467
        if(active_visobj().reload(str)) {
1468
            active_visobj().post_create_display_list();
1469
            return true;
1470
        }
1471
        return false;
1472
    }
1473
 
1474
    bool MeshEditor::add_to_active_from_file(const std::string& str)
1475
    {
1476
        if(active_visobj().add_mesh(str)) {
1477
            active_visobj().post_create_display_list();
1478
            return  true;
1479
        }
1480
        return false;
1481
    }
1482
 
1483
 
1484
}