Subversion Repositories gelsvn

Rev

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