Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
595 jab 1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
6
 
631 janba 7
#include <thread>
149 jab 8
#include "smooth.h"
9
 
635 janba 10
#include <future>
595 jab 11
#include <vector>
12
#include <algorithm>
631 janba 13
#include "../CGLA/Mat3x3d.h"
601 jab 14
#include "../CGLA/Vec3d.h"
631 janba 15
#include "../CGLA/Quatd.h"
16
#include "../Util/Timer.h"
149 jab 17
 
595 jab 18
#include "Manifold.h"
19
#include "AttributeVector.h"
20
 
150 jab 21
namespace HMesh
149 jab 22
{
595 jab 23
    using namespace std;
24
    using namespace CGLA;
631 janba 25
 
633 janba 26
 
27
    class range {
28
    public:
29
        class iterator {
30
            friend class range;
31
        public:
32
            long int operator *() const { return i_; }
33
            const iterator &operator ++() { ++i_; return *this; }
34
            iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
35
 
36
            bool operator ==(const iterator &other) const { return i_ == other.i_; }
37
            bool operator !=(const iterator &other) const { return i_ != other.i_; }
38
 
39
        protected:
40
            iterator(long int start) : i_ (start) { }
41
 
42
        private:
43
            unsigned long i_;
44
        };
45
 
46
        iterator begin() const { return begin_; }
47
        iterator end() const { return end_; }
48
        range(long int  begin, long int end) : begin_(begin), end_(end) {}
49
    private:
50
        iterator begin_;
51
        iterator end_;
52
    };
149 jab 53
 
646 janba 54
    typedef std::vector<std::vector<VertexID>> VertexIDBatches;
55
 
631 janba 56
 
57
 
58
    void for_each_vertex(Manifold& m, function<void(VertexID)> f) { for(auto v : m.vertices()) f(v); }
59
    void for_each_face(Manifold& m, function<void(FaceID)> f) { for(auto p : m.faces()) f(p); }
60
    void for_each_halfedge(Manifold& m, function<void(HalfEdgeID)> f) { for(auto h : m.halfedges()) f(h); }
61
 
62
 
633 janba 63
    inline Vec3d laplacian(const Manifold& m, VertexID v)
595 jab 64
    {
633 janba 65
        Vec3d p(0);
636 khor 66
        int n = circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID v){ p += m.pos(v); });
633 janba 67
        return p / n - m.pos(v);
595 jab 68
    }
631 janba 69
 
70
 
632 janba 71
    int CORES = 8;
631 janba 72
 
635 janba 73
    void laplacian_smooth_example(Manifold& m)
74
    {
75
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
76
        for(VertexID v : m.vertices())
77
            if(!boundary(m, v))
78
            {
79
                Vec3d L(0);
638 khor 80
                int n = circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID v){ L += m.pos(v); });
635 janba 81
                new_pos[v] = L/n;
82
            }
83
        m.positions_attribute_vector() = new_pos;
84
 
85
    }
86
 
631 janba 87
    void laplacian_smooth0(Manifold& m,float weight, int max_iter)
88
    {
89
        for(int iter=0;iter<max_iter; ++iter) {
90
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
91
 
92
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
93
                if(!boundary(m, *v))
94
                    L_attr[*v] =laplacian(m, *v);
95
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
96
                if(!boundary(m, *v))
97
                    m.pos(*v) += weight*L_attr[*v];
98
            }
99
        }
100
    }
101
 
102
    void laplacian_smooth1(Manifold& m,float weight, int max_iter)
103
    {
104
        for(int iter=0;iter<max_iter; ++iter) {
105
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
106
 
107
            for(VertexID v : m.vertices())
108
                if(!boundary(m, v))
109
                    L_attr[v] =laplacian(m, v);
110
            for(VertexID v : m.vertices()){
111
                if(!boundary(m, v))
112
                    m.pos(v) += weight*L_attr[v];
113
            }
114
        }
115
    }
116
 
117
    void laplacian_smooth2(Manifold& m,float weight, int max_iter)
118
    {
119
        auto new_pos = m.positions_attribute_vector();
120
        for(int iter=0;iter<max_iter; ++iter) {
121
            for(auto v : m.vertices())
122
                if(!boundary(m, v))
123
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
124
            m.positions_attribute_vector() = new_pos;
125
        }
126
    }
149 jab 127
 
631 janba 128
 
129
 
130
    void laplacian_smooth3(Manifold& m, float weight, int max_iter)
595 jab 131
    {
631 janba 132
        for(int iter=0;iter<max_iter; ++iter) {
133
            auto new_pos = m.positions_attribute_vector();
134
            for(auto v : m.vertices())
135
                if(!boundary(m, v))
136
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
137
            m.positions_attribute_vector() = move(new_pos);
138
        }
139
    }
149 jab 140
 
631 janba 141
    void laplacian_smooth4(Manifold& m,float weight, int max_iter)
142
    {
143
        auto new_pos = m.positions_attribute_vector();
144
        for(int iter=0;iter<max_iter; ++iter) {
632 janba 145
            for(VertexID v : m.vertices())
631 janba 146
                if(!boundary(m, v))
147
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
148
            swap(m.positions_attribute_vector(),new_pos);
595 jab 149
        }
631 janba 150
    }
151
 
152
    void laplacian_smooth4_5(Manifold& m,float weight, int max_iter)
153
    {
154
        auto new_pos = m.positions_attribute_vector();
155
        for(int iter=0;iter<max_iter; ++iter) {
156
            for_each_vertex(m, [&](VertexID v) {new_pos[v] = weight*laplacian(m, v)+m.pos(v);});
157
            swap(m.positions_attribute_vector(),new_pos);
158
        }
159
    }
149 jab 160
 
631 janba 161
 
162
 
163
    void laplacian_smooth5(Manifold& m, float weight, int max_iter)
164
    {
165
        for(int iter=0;iter<max_iter; ++iter) {
166
            auto new_pos = m.positions_attribute_vector();
167
            vector<thread> t_vec;
168
            for(auto v : m.vertices())
169
                if(!boundary(m, v))
170
                    t_vec.push_back(thread([&](VertexID vid){
171
                        if(!boundary(m, vid))
172
                            new_pos[vid] = weight*laplacian(m, vid)+ m.pos(vid);},v));
173
            for(int i=0;i<t_vec.size();++i)
174
                t_vec[i].join();
175
            m.positions_attribute_vector() = move(new_pos);
595 jab 176
        }
177
    }
631 janba 178
 
179
 
180
 
633 janba 181
    inline void laplacian_smooth_vertex(Manifold& m, const vector<VertexID>& vids,
631 janba 182
                                        VertexAttributeVector<Vec3d>& new_pos,
183
                                        float weight){
632 janba 184
        for(VertexID v: vids)
631 janba 185
            new_pos[v] = m.pos(v)+weight*laplacian(m, v);
186
    }
187
 
633 janba 188
 
631 janba 189
    void laplacian_smooth6(Manifold& m, float weight, int max_iter)
190
    {
191
        vector<vector<VertexID>> vertex_ids(CORES);
192
        auto batch_size = m.no_vertices()/CORES;
193
        int cnt = 0;
194
        for_each_vertex(m, [&](VertexID v) {
195
            if (!boundary(m, v))
196
                vertex_ids[(cnt++/batch_size)%CORES].push_back(v);
197
        });
198
        vector<thread> t_vec(CORES);
199
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
200
        for(int iter=0;iter<max_iter; ++iter) {
201
            for(int thread_no=0;thread_no<CORES;++thread_no)
202
                t_vec[thread_no] = thread(laplacian_smooth_vertex,
203
                                          ref(m), ref(vertex_ids[thread_no]),
204
                                          ref(new_pos), weight);
205
            for(int thread_no=0;thread_no<CORES;++thread_no)
206
                t_vec[thread_no].join();
207
            swap(m.positions_attribute_vector(), new_pos);
208
        }
209
 
210
    }
211
 
633 janba 212
 
635 janba 213
//    template<typename  T>
214
//    void for_each_vertex_parallel(int no_threads, const VertexIDBatches& batches, const T& f) {
215
//        vector<future<void>> f_vec(no_threads);
216
//        for(auto t : range(0, no_threads))
217
//            f_vec[t] = async(launch::async, f, ref(batches[t]));
218
//    }
633 janba 219
    template<typename  T>
220
    void for_each_vertex_parallel(int no_threads, const VertexIDBatches& batches, const T& f) {
221
        vector<thread> t_vec(no_threads);
222
        for(auto t : range(0, no_threads))
223
            t_vec[t] = thread(f, ref(batches[t]));
224
        for(auto t : range(0, no_threads))
225
            t_vec[t].join();
226
    }
227
 
228
    VertexIDBatches batch_vertices(Manifold& m) {
229
        VertexIDBatches vertex_ids(CORES);
230
        auto batch_size = m.no_vertices()/CORES;
231
        int cnt = 0;
232
        for_each_vertex(m, [&](VertexID v) {
233
            if (!boundary(m, v))
234
                vertex_ids[(cnt++/batch_size)%CORES].push_back(v);
235
        });
236
        return vertex_ids;
237
    }
238
 
239
    void laplacian_smooth7(Manifold& m, float weight, int max_iter)
240
    {
241
        auto vertex_ids = batch_vertices(m);
242
        auto new_pos = m.positions_attribute_vector();
243
        auto f = [&](const vector<VertexID>& vids) {
244
            for(VertexID v: vids)
245
                new_pos[v] = m.pos(v)+weight*laplacian(m, v);
246
        };
247
 
248
        for(auto _ : range(0, max_iter)) {
249
            for_each_vertex_parallel(CORES, vertex_ids, f);
250
            swap(m.positions_attribute_vector(), new_pos);
251
        }
252
    }
253
 
646 janba 254
 
633 janba 255
 
256
 
631 janba 257
    void laplacian_smooth(Manifold& m,float weight, int max_iter)
258
    {
637 janba 259
//        laplacian_smooth_example(m);
643 janba 260
        laplacian_smooth7(m,weight,max_iter);
637 janba 261
 
631 janba 262
//        Util::Timer tim;
263
//        cout << "Method 0: ";
264
//        for(int i=0;i<5;++i) {
265
//            Manifold m2 = m;
266
//            tim.start();
267
//            laplacian_smooth0(m2, 1, 1000);
268
//            cout << tim.get_secs() << ", ";
269
//        }
270
//        cout << endl;
271
//
272
//        cout << "Method 1: ";
273
//        for(int i=0;i<5;++i) {
274
//            Manifold m2 = m;
275
//            tim.start();
276
//            laplacian_smooth1(m2, 1, 1000);
277
//            cout << tim.get_secs() << ", ";
278
//        }
279
//        cout << endl;
280
//
281
//        cout << "Method 2: ";
282
//        for(int i=0;i<5;++i) {
283
//            Manifold m2 = m;
284
//            tim.start();
285
//            laplacian_smooth2(m2, 1, 1000);
286
//            cout << tim.get_secs() << ", ";
287
//        }
288
//        cout << endl;
289
//
290
//        cout << "Method 3: ";
291
//        for(int i=0;i<5;++i) {
292
//            Manifold m2 = m;
293
//            tim.start();
294
//            laplacian_smooth3(m2, 1, 1000);
295
//            cout << tim.get_secs() << ", ";
296
//        }
297
//        cout << endl;
298
//
299
//        cout << "Method 4: ";
300
//        for(int i=0;i<5;++i) {
301
//            Manifold m2 = m;
302
//            tim.start();
303
//            laplacian_smooth4(m2, 1, 1000);
304
//            cout << tim.get_secs() << ", ";
305
//        }
306
//        cout << endl;
307
//
637 janba 308
//        cout << "Method 5: ";
309
//        for(int i=0;i<3;++i) {
310
//            Manifold m2 = m;
311
//            tim.start();
312
//            laplacian_smooth5(m2, 1, 1000);
313
//            cout << " sec: "<< tim.get_secs() << ",";
314
//        }
315
//        cout << endl;
631 janba 316
//
317
//        CORES = 2;
318
//        cout << "Method 6 (2): ";
319
//        for(int i=0;i<5;++i) {
320
//            Manifold m2 = m;
321
//            tim.start();
322
//            laplacian_smooth6(m2, 1, 1000);
323
//            cout << tim.get_secs() << ", ";
324
//        }
325
//        cout << endl;
326
//        
327
//        CORES = 4;
637 janba 328
//        cout << "Method 7 (4): ";
631 janba 329
//        for(int i=0;i<5;++i) {
330
//            Manifold m2 = m;
331
//            tim.start();
332
//            laplacian_smooth6(m2, 1, 1000);
333
//            cout << tim.get_secs() << ", ";
334
//        }
335
//        cout << endl;
336
//
337
//        CORES = 8;
637 janba 338
//        cout << "Method 7 (8): ";
631 janba 339
//        for(int i=0;i<5;++i) {
340
//            Manifold m2 = m;
341
//            tim.start();
342
//            laplacian_smooth6(m2, 1, 1000);
343
//            cout << tim.get_secs() << ", ";
344
//        }
345
//        cout << endl;
215 jab 346
 
631 janba 347
 
348
    }
349
 
350
 
646 janba 351
 
631 janba 352
 
353
 
595 jab 354
    void taubin_smooth(Manifold& m, int max_iter)
355
    {
631 janba 356
        auto new_pos = m.positions_attribute_vector();
357
        for(int iter = 0; iter < 2*max_iter; ++iter) {
358
            for(VertexID v : m.vertices())
359
                if(!boundary(m, v))
360
                    new_pos[v] = (iter%2 == 0 ? 0.5 : -0.52) * laplacian(m, v) + m.pos(v);
361
            swap(m.positions_attribute_vector(), new_pos);
595 jab 362
        }
363
    }
631 janba 364
 
365
    void face_neighbourhood(Manifold& m, FaceID f, vector<FaceID>& nbrs)
366
    {
367
        FaceAttributeVector<int> touched(m.allocated_faces(), -1);
368
        touched[f] = 1;
369
        nbrs.push_back(f);
595 jab 370
        for(Walker wf = m.walker(f); !wf.full_circle(); wf = wf.circulate_face_cw()){
371
            for(Walker wv = m.walker(wf.vertex()); !wv.full_circle(); wv = wv.circulate_vertex_cw()){
372
                FaceID fn = wv.face();
373
                if(fn != InvalidFaceID && touched[fn] != touched[f]){
631 janba 374
                    nbrs.push_back(fn);
375
                    touched[fn] = 1;
595 jab 376
                }
377
            }
378
        }
379
    }
631 janba 380
 
381
 
382
 
383
    Vec3d fvm_filtered_normal(Manifold& m, FaceID f)
595 jab 384
    {
385
        const float sigma = .1f;
631 janba 386
 
387
        vector<FaceID> nbrs;
388
        face_neighbourhood(m, f, nbrs);
595 jab 389
        float min_dist_sum=1e32f;
390
        long int median=-1;
631 janba 391
 
392
        vector<Vec3d> normals(nbrs.size());
393
        for(size_t i=0;i<nbrs.size();++i)
595 jab 394
        {
631 janba 395
            normals[i] = normal(m, nbrs[i]);
595 jab 396
            float dist_sum = 0;
631 janba 397
            for(size_t j=0;j<nbrs.size(); ++j)
398
                dist_sum += 1.0f - dot(normals[i], normals[j]);
595 jab 399
            if(dist_sum < min_dist_sum)
400
            {
401
                min_dist_sum = dist_sum;
402
                median = i;
403
            }
404
        }
405
        assert(median != -1);
631 janba 406
        Vec3d median_norm = normals[median];
595 jab 407
        Vec3d avg_norm(0);
631 janba 408
        for(size_t i=0;i<nbrs.size();++i)
595 jab 409
        {
631 janba 410
            float w = exp((dot(median_norm, normals[i])-1)/sigma);
595 jab 411
            if(w<1e-2) w = 0;
631 janba 412
            avg_norm += w*normals[i];
595 jab 413
        }
414
        return normalize(avg_norm);
415
    }
631 janba 416
    Vec3d bilateral_filtered_normal(Manifold& m, FaceID f, double avg_len)
595 jab 417
    {
631 janba 418
        vector<FaceID> nbrs;
419
        face_neighbourhood(m, f, nbrs);
420
        Vec3d p0 = centre(m, f);
421
        Vec3d n0 = normal(m, f);
422
        vector<Vec3d> normals(nbrs.size());
423
        vector<Vec3d> pos(nbrs.size());
424
        Vec3d fn(0);
425
        for(FaceID nbr : nbrs)
426
        {
427
            Vec3d n = normal(m, nbr);
428
            Vec3d p = centre(m, nbr);
429
            double w_a = exp(-acos(max(-1.0,min(1.0,dot(n,n0))))/(M_PI/32.0));
430
            double w_s = exp(-length(p-p0)/avg_len);
431
 
432
            fn += area(m, nbr)* w_a * w_s * n;
433
 
434
        }
435
        return normalize(fn);
436
    }
437
 
438
    void anisotropic_smooth(HMesh::Manifold& m, int max_iter, NormalSmoothMethod nsm)
439
    {
440
        double avg_len=0;
441
        for(HalfEdgeID hid : m.halfedges())
442
            avg_len += length(m, hid);
443
        avg_len /= 2.0;
595 jab 444
        for(int iter = 0;iter<max_iter; ++iter)
445
        {
631 janba 446
 
595 jab 447
            FaceAttributeVector<Vec3d> filtered_norms(m.allocated_faces());
631 janba 448
 
449
            for(FaceID f: m.faces()){
450
                filtered_norms[f] = (nsm == BILATERAL_NORMAL_SMOOTH)?
451
                bilateral_filtered_normal(m, f, avg_len):
452
                fvm_filtered_normal(m, f);
595 jab 453
            }
631 janba 454
 
455
            VertexAttributeVector<Vec3d> vertex_positions(m.allocated_vertices(), Vec3d(0));
456
            VertexAttributeVector<int> count(m.allocated_vertices(), 0);
457
            for(int sub_iter=0;sub_iter<100;++sub_iter)
595 jab 458
            {
631 janba 459
                for(HalfEdgeID hid : m.halfedges())
460
                {
461
                    Walker w = m.walker(hid);
462
                    FaceID f = w.face();
463
 
464
                    if(f != InvalidFaceID){
465
                        VertexID v = w.vertex();
466
                        Vec3d dir = m.pos(w.opp().vertex()) - m.pos(v);
467
                        Vec3d n = filtered_norms[f];
468
                        vertex_positions[v] += m.pos(v) + 0.5 * n * dot(n, dir);
469
                        count[v] += 1;
595 jab 470
                    }
631 janba 471
 
595 jab 472
                }
631 janba 473
                double max_move= 0;
474
                for(VertexID v : m.vertices())
475
                {
476
                    Vec3d npos = vertex_positions[v] / double(count[v]);
477
                    double move = sqr_length(npos - m.pos(v));
478
                    if(move > max_move)
479
                        max_move = move;
480
 
481
                    m.pos(v) = npos;
482
                }
483
                if(max_move<sqr(1e-8*avg_len))
484
                {
485
                    cout << "iters " << sub_iter << endl;
486
                    break;
487
                }
595 jab 488
            }
489
        }
490
    }
631 janba 491
 
652 janba 492
    void TAL_smoothing(Manifold& m, float w, int max_iter)
493
    {
494
        for(int iter=0;iter<max_iter;++iter) {
495
            VertexAttributeVector<float> vertex_areas;
496
            VertexAttributeVector<Vec3d> laplacians;
497
 
498
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
499
            {
500
                vertex_areas[*vid] = 0;
501
                for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
502
                    if(w.face() != InvalidFaceID)
503
                        vertex_areas[*vid] += area(m, w.face());
504
            }
505
 
506
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
507
            {
508
                laplacians[*vid] = Vec3d(0);
509
                double weight_sum = 0.0;
510
                if(boundary(m, *vid))
511
                {
512
                    double angle_sum = 0;
513
                    for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
514
                    {
515
                        if (w.face() != InvalidFaceID)
516
                        {
517
                            Vec3d vec_a = normalize(m.pos(w.vertex()) - m.pos(*vid));
518
                            Vec3d vec_b = normalize(m.pos(w.circulate_vertex_ccw().vertex()) -
519
                                                    m.pos(*vid));
520
                            angle_sum += acos(max(-1.0,min(1.0,dot(vec_a,vec_b))));
521
                        }
522
                        if(boundary(m,w.vertex()))
523
                        {
524
                            laplacians[*vid] += m.pos(w.vertex()) - m.pos(*vid);
525
                            weight_sum += 1.0;
526
                        }
527
                    }
528
                    laplacians[*vid] /= weight_sum;
529
                    laplacians[*vid] *= exp(-3.0*sqr(max(0.0, M_PI-angle_sum)));
530
                }
531
                else
532
                {
533
                    for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
534
                    {
535
                        float weight = vertex_areas[w.vertex()];
536
                        Vec3d l = m.pos(w.vertex()) - m.pos(*vid);
537
                        laplacians[*vid] +=  weight * l;
538
                        weight_sum += weight;
539
                    }
540
                    laplacians[*vid] /= weight_sum;
541
                    //                Vec3d n = normal(m, *vid);
542
                    //                if(sqr_length(n)>0.9)
543
                    //                    laplacians[*vid] -= n * dot(n, laplacians[*vid]);
544
                }
545
            }
546
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
547
                m.pos(*vid) += w*laplacians[*vid];
548
        }
549
    }
550
 
631 janba 551
 
652 janba 552
 
149 jab 553
}