Subversion Repositories gelsvn

Rev

Rev 636 | Rev 638 | 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
 
633 janba 54
 
631 janba 55
 
56
 
57
    void for_each_vertex(Manifold& m, function<void(VertexID)> f) { for(auto v : m.vertices()) f(v); }
58
    void for_each_face(Manifold& m, function<void(FaceID)> f) { for(auto p : m.faces()) f(p); }
59
    void for_each_halfedge(Manifold& m, function<void(HalfEdgeID)> f) { for(auto h : m.halfedges()) f(h); }
60
 
61
 
633 janba 62
    inline Vec3d laplacian(const Manifold& m, VertexID v)
595 jab 63
    {
633 janba 64
        Vec3d p(0);
636 khor 65
        int n = circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID v){ p += m.pos(v); });
633 janba 66
        return p / n - m.pos(v);
595 jab 67
    }
631 janba 68
 
69
 
632 janba 70
    int CORES = 8;
631 janba 71
 
635 janba 72
    void laplacian_smooth_example(Manifold& m)
73
    {
74
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
75
        for(VertexID v : m.vertices())
76
            if(!boundary(m, v))
77
            {
78
                Vec3d L(0);
79
                int n = circulate_vertex_ccw(m, v, [&](VertexID v){ L += m.pos(v); });
80
                new_pos[v] = L/n;
81
            }
82
        m.positions_attribute_vector() = new_pos;
83
 
84
    }
85
 
631 janba 86
    void laplacian_smooth0(Manifold& m,float weight, int max_iter)
87
    {
88
        for(int iter=0;iter<max_iter; ++iter) {
89
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
90
 
91
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
92
                if(!boundary(m, *v))
93
                    L_attr[*v] =laplacian(m, *v);
94
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
95
                if(!boundary(m, *v))
96
                    m.pos(*v) += weight*L_attr[*v];
97
            }
98
        }
99
    }
100
 
101
    void laplacian_smooth1(Manifold& m,float weight, int max_iter)
102
    {
103
        for(int iter=0;iter<max_iter; ++iter) {
104
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
105
 
106
            for(VertexID v : m.vertices())
107
                if(!boundary(m, v))
108
                    L_attr[v] =laplacian(m, v);
109
            for(VertexID v : m.vertices()){
110
                if(!boundary(m, v))
111
                    m.pos(v) += weight*L_attr[v];
112
            }
113
        }
114
    }
115
 
116
    void laplacian_smooth2(Manifold& m,float weight, int max_iter)
117
    {
118
        auto new_pos = m.positions_attribute_vector();
119
        for(int iter=0;iter<max_iter; ++iter) {
120
            for(auto v : m.vertices())
121
                if(!boundary(m, v))
122
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
123
            m.positions_attribute_vector() = new_pos;
124
        }
125
    }
149 jab 126
 
631 janba 127
 
128
 
129
    void laplacian_smooth3(Manifold& m, float weight, int max_iter)
595 jab 130
    {
631 janba 131
        for(int iter=0;iter<max_iter; ++iter) {
132
            auto new_pos = m.positions_attribute_vector();
133
            for(auto v : m.vertices())
134
                if(!boundary(m, v))
135
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
136
            m.positions_attribute_vector() = move(new_pos);
137
        }
138
    }
149 jab 139
 
631 janba 140
    void laplacian_smooth4(Manifold& m,float weight, int max_iter)
141
    {
142
        auto new_pos = m.positions_attribute_vector();
143
        for(int iter=0;iter<max_iter; ++iter) {
632 janba 144
            for(VertexID v : m.vertices())
631 janba 145
                if(!boundary(m, v))
146
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
147
            swap(m.positions_attribute_vector(),new_pos);
595 jab 148
        }
631 janba 149
    }
150
 
151
    void laplacian_smooth4_5(Manifold& m,float weight, int max_iter)
152
    {
153
        auto new_pos = m.positions_attribute_vector();
154
        for(int iter=0;iter<max_iter; ++iter) {
155
            for_each_vertex(m, [&](VertexID v) {new_pos[v] = weight*laplacian(m, v)+m.pos(v);});
156
            swap(m.positions_attribute_vector(),new_pos);
157
        }
158
    }
149 jab 159
 
631 janba 160
 
161
 
162
    void laplacian_smooth5(Manifold& m, float weight, int max_iter)
163
    {
164
        for(int iter=0;iter<max_iter; ++iter) {
165
            auto new_pos = m.positions_attribute_vector();
166
            vector<thread> t_vec;
167
            for(auto v : m.vertices())
168
                if(!boundary(m, v))
169
                    t_vec.push_back(thread([&](VertexID vid){
170
                        if(!boundary(m, vid))
171
                            new_pos[vid] = weight*laplacian(m, vid)+ m.pos(vid);},v));
172
            for(int i=0;i<t_vec.size();++i)
173
                t_vec[i].join();
174
            m.positions_attribute_vector() = move(new_pos);
595 jab 175
        }
176
    }
631 janba 177
 
178
 
179
 
633 janba 180
    inline void laplacian_smooth_vertex(Manifold& m, const vector<VertexID>& vids,
631 janba 181
                                        VertexAttributeVector<Vec3d>& new_pos,
182
                                        float weight){
632 janba 183
        for(VertexID v: vids)
631 janba 184
            new_pos[v] = m.pos(v)+weight*laplacian(m, v);
185
    }
186
 
633 janba 187
 
631 janba 188
    void laplacian_smooth6(Manifold& m, float weight, int max_iter)
189
    {
190
        vector<vector<VertexID>> vertex_ids(CORES);
191
        auto batch_size = m.no_vertices()/CORES;
192
        int cnt = 0;
193
        for_each_vertex(m, [&](VertexID v) {
194
            if (!boundary(m, v))
195
                vertex_ids[(cnt++/batch_size)%CORES].push_back(v);
196
        });
197
        vector<thread> t_vec(CORES);
198
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
199
        for(int iter=0;iter<max_iter; ++iter) {
200
            for(int thread_no=0;thread_no<CORES;++thread_no)
201
                t_vec[thread_no] = thread(laplacian_smooth_vertex,
202
                                          ref(m), ref(vertex_ids[thread_no]),
203
                                          ref(new_pos), weight);
204
            for(int thread_no=0;thread_no<CORES;++thread_no)
205
                t_vec[thread_no].join();
206
            swap(m.positions_attribute_vector(), new_pos);
207
        }
208
 
209
    }
210
 
633 janba 211
    typedef vector<vector<VertexID>> VertexIDBatches;
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
 
254
 
255
 
256
 
631 janba 257
    void laplacian_smooth(Manifold& m,float weight, int max_iter)
258
    {
637 janba 259
//        laplacian_smooth_example(m);
260
        laplacian_smooth2(m,weight,max_iter);
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
 
351
 
352
 
595 jab 353
    void taubin_smooth(Manifold& m, int max_iter)
354
    {
631 janba 355
        auto new_pos = m.positions_attribute_vector();
356
        for(int iter = 0; iter < 2*max_iter; ++iter) {
357
            for(VertexID v : m.vertices())
358
                if(!boundary(m, v))
359
                    new_pos[v] = (iter%2 == 0 ? 0.5 : -0.52) * laplacian(m, v) + m.pos(v);
360
            swap(m.positions_attribute_vector(), new_pos);
595 jab 361
        }
362
    }
631 janba 363
 
364
    void face_neighbourhood(Manifold& m, FaceID f, vector<FaceID>& nbrs)
365
    {
366
        FaceAttributeVector<int> touched(m.allocated_faces(), -1);
367
        touched[f] = 1;
368
        nbrs.push_back(f);
595 jab 369
        for(Walker wf = m.walker(f); !wf.full_circle(); wf = wf.circulate_face_cw()){
370
            for(Walker wv = m.walker(wf.vertex()); !wv.full_circle(); wv = wv.circulate_vertex_cw()){
371
                FaceID fn = wv.face();
372
                if(fn != InvalidFaceID && touched[fn] != touched[f]){
631 janba 373
                    nbrs.push_back(fn);
374
                    touched[fn] = 1;
595 jab 375
                }
376
            }
377
        }
378
    }
631 janba 379
 
380
 
381
 
382
    Vec3d fvm_filtered_normal(Manifold& m, FaceID f)
595 jab 383
    {
384
        const float sigma = .1f;
631 janba 385
 
386
        vector<FaceID> nbrs;
387
        face_neighbourhood(m, f, nbrs);
595 jab 388
        float min_dist_sum=1e32f;
389
        long int median=-1;
631 janba 390
 
391
        vector<Vec3d> normals(nbrs.size());
392
        for(size_t i=0;i<nbrs.size();++i)
595 jab 393
        {
631 janba 394
            normals[i] = normal(m, nbrs[i]);
595 jab 395
            float dist_sum = 0;
631 janba 396
            for(size_t j=0;j<nbrs.size(); ++j)
397
                dist_sum += 1.0f - dot(normals[i], normals[j]);
595 jab 398
            if(dist_sum < min_dist_sum)
399
            {
400
                min_dist_sum = dist_sum;
401
                median = i;
402
            }
403
        }
404
        assert(median != -1);
631 janba 405
        Vec3d median_norm = normals[median];
595 jab 406
        Vec3d avg_norm(0);
631 janba 407
        for(size_t i=0;i<nbrs.size();++i)
595 jab 408
        {
631 janba 409
            float w = exp((dot(median_norm, normals[i])-1)/sigma);
595 jab 410
            if(w<1e-2) w = 0;
631 janba 411
            avg_norm += w*normals[i];
595 jab 412
        }
413
        return normalize(avg_norm);
414
    }
631 janba 415
    Vec3d bilateral_filtered_normal(Manifold& m, FaceID f, double avg_len)
595 jab 416
    {
631 janba 417
        vector<FaceID> nbrs;
418
        face_neighbourhood(m, f, nbrs);
419
        Vec3d p0 = centre(m, f);
420
        Vec3d n0 = normal(m, f);
421
        vector<Vec3d> normals(nbrs.size());
422
        vector<Vec3d> pos(nbrs.size());
423
        Vec3d fn(0);
424
        for(FaceID nbr : nbrs)
425
        {
426
            Vec3d n = normal(m, nbr);
427
            Vec3d p = centre(m, nbr);
428
            double w_a = exp(-acos(max(-1.0,min(1.0,dot(n,n0))))/(M_PI/32.0));
429
            double w_s = exp(-length(p-p0)/avg_len);
430
 
431
            fn += area(m, nbr)* w_a * w_s * n;
432
 
433
        }
434
        return normalize(fn);
435
    }
436
 
437
    void anisotropic_smooth(HMesh::Manifold& m, int max_iter, NormalSmoothMethod nsm)
438
    {
439
        double avg_len=0;
440
        for(HalfEdgeID hid : m.halfedges())
441
            avg_len += length(m, hid);
442
        avg_len /= 2.0;
595 jab 443
        for(int iter = 0;iter<max_iter; ++iter)
444
        {
631 janba 445
 
595 jab 446
            FaceAttributeVector<Vec3d> filtered_norms(m.allocated_faces());
631 janba 447
 
448
            for(FaceID f: m.faces()){
449
                filtered_norms[f] = (nsm == BILATERAL_NORMAL_SMOOTH)?
450
                bilateral_filtered_normal(m, f, avg_len):
451
                fvm_filtered_normal(m, f);
595 jab 452
            }
631 janba 453
 
454
            VertexAttributeVector<Vec3d> vertex_positions(m.allocated_vertices(), Vec3d(0));
455
            VertexAttributeVector<int> count(m.allocated_vertices(), 0);
456
            for(int sub_iter=0;sub_iter<100;++sub_iter)
595 jab 457
            {
631 janba 458
                for(HalfEdgeID hid : m.halfedges())
459
                {
460
                    Walker w = m.walker(hid);
461
                    FaceID f = w.face();
462
 
463
                    if(f != InvalidFaceID){
464
                        VertexID v = w.vertex();
465
                        Vec3d dir = m.pos(w.opp().vertex()) - m.pos(v);
466
                        Vec3d n = filtered_norms[f];
467
                        vertex_positions[v] += m.pos(v) + 0.5 * n * dot(n, dir);
468
                        count[v] += 1;
595 jab 469
                    }
631 janba 470
 
595 jab 471
                }
631 janba 472
                double max_move= 0;
473
                for(VertexID v : m.vertices())
474
                {
475
                    Vec3d npos = vertex_positions[v] / double(count[v]);
476
                    double move = sqr_length(npos - m.pos(v));
477
                    if(move > max_move)
478
                        max_move = move;
479
 
480
                    m.pos(v) = npos;
481
                }
482
                if(max_move<sqr(1e-8*avg_len))
483
                {
484
                    cout << "iters " << sub_iter << endl;
485
                    break;
486
                }
595 jab 487
            }
488
        }
489
    }
631 janba 490
 
491
 
149 jab 492
}