Subversion Repositories gelsvn

Rev

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