~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/bmesh/operators/bmo_fill_grid.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-02-19 11:24:23 UTC
  • mfrom: (14.2.23 sid)
  • Revision ID: package-import@ubuntu.com-20140219112423-rkmaz2m7ha06d4tk
Tags: 2.69-3ubuntu1
* Merge with Debian; remaining changes:
  - Configure without OpenImageIO on armhf, as it is not available on
    Ubuntu.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
#include "intern/bmesh_operators_private.h" /* own include */
39
39
 
 
40
#include "BLI_strict_flags.h"
 
41
 
40
42
#define EDGE_MARK       4
41
43
#define FACE_OUT        16
42
44
 
103
105
#endif
104
106
 
105
107
 
 
108
/* -------------------------------------------------------------------- */
 
109
/* Handle Loop Pairs */
 
110
 
 
111
/** \name Loop Pairs
 
112
 * \{ */
 
113
 
 
114
/**
 
115
 * Assign a loop pair from 2 verts (which _must_ share an edge)
 
116
 */
 
117
static void bm_loop_pair_from_verts(BMVert *v_a, BMVert *v_b,
 
118
                                    BMLoop *l_pair[2])
 
119
{
 
120
        BMEdge *e = BM_edge_exists(v_a, v_b);
 
121
        if (e->l) {
 
122
                if (e->l->v == v_a) {
 
123
                        l_pair[0] = e->l;
 
124
                        l_pair[1] = e->l->next;
 
125
                }
 
126
                else {
 
127
                        l_pair[0] = e->l->next;
 
128
                        l_pair[1] = e->l;
 
129
                }
 
130
        }
 
131
        else {
 
132
                l_pair[0] = NULL;
 
133
                l_pair[1] = NULL;
 
134
        }
 
135
}
 
136
 
 
137
/**
 
138
 * Copy loop pair from one side to the other if either is missing,
 
139
 * this simplifies interpolation code so we only need to check if x/y are missing,
 
140
 * rather then checking each loop.
 
141
 */
 
142
static void bm_loop_pair_test_copy(BMLoop *l_pair_a[2], BMLoop *l_pair_b[2])
 
143
{
 
144
        /* if the first one is set, we know the second is too */
 
145
        if (l_pair_a[0] && l_pair_b[0] == NULL)  {
 
146
                l_pair_b[0] = l_pair_a[1];
 
147
                l_pair_b[1] = l_pair_a[0];
 
148
        }
 
149
        else if (l_pair_b[0] && l_pair_a[0] == NULL)  {
 
150
                l_pair_a[0] = l_pair_b[1];
 
151
                l_pair_a[1] = l_pair_b[0];
 
152
        }
 
153
}
 
154
 
 
155
/**
 
156
 * Interpolate from boundary loops.
 
157
 *
 
158
 * \note These weights will be calculated multiple times per vertex.
 
159
 */
 
160
static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_bound[4], const float w[4])
 
161
{
 
162
        void *l_cdata[4] = {
 
163
            l_bound[0]->head.data,
 
164
            l_bound[1]->head.data,
 
165
            l_bound[2]->head.data,
 
166
            l_bound[3]->head.data};
 
167
 
 
168
        CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 4, l->head.data);
 
169
}
 
170
 
 
171
static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_bound[2], const float t)
 
172
{
 
173
 
 
174
        void *l_cdata[2] = {
 
175
            l_bound[0]->head.data,
 
176
            l_bound[1]->head.data};
 
177
 
 
178
        const float w[2] = {1.0f - t, t};
 
179
 
 
180
        CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 2, l->head.data);
 
181
}
 
182
 
 
183
/** \} */
 
184
 
 
185
 
 
186
/**
 
187
 * Avoids calling #barycentric_weights_v2_quad often by caching weights into an array.
 
188
 */
 
189
static void barycentric_weights_v2_grid_cache(const unsigned int xtot, const unsigned int ytot,
 
190
                                              float (*weight_table)[4])
 
191
{
 
192
        float x_step = 1.0f / (float)(xtot - 1);
 
193
        float y_step = 1.0f / (float)(ytot - 1);
 
194
        unsigned int i = 0;
 
195
        float xy_fl[2];
 
196
 
 
197
        unsigned int x, y;
 
198
        for (y = 0; y < ytot; y++) {
 
199
                xy_fl[1] = y_step * (float)y;
 
200
                for (x = 0; x < xtot; x++) {
 
201
                        xy_fl[0] = x_step * (float)x;
 
202
                        {
 
203
                                const float cos[4][2] = {
 
204
                                    {xy_fl[0], 0.0f},
 
205
                                    {0.0f, xy_fl[1]},
 
206
                                    {xy_fl[0], 1.0f},
 
207
                                    {1.0f, xy_fl[1]}};
 
208
                                barycentric_weights_v2_quad(UNPACK4(cos), xy_fl, weight_table[i++]);
 
209
                        }
 
210
                }
 
211
        }
 
212
}
 
213
 
 
214
 
106
215
/**
107
216
 * This may be useful outside the bmesh operator.
108
217
 *
109
218
 * \param v_grid  2d array of verts, all boundary verts must be set, we fill in the middle.
110
219
 */
111
 
static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const int ytot,
 
220
static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xtot, unsigned const int ytot,
112
221
                               const short mat_nr, const bool use_smooth,
113
 
                               const bool use_flip)
 
222
                               const bool use_flip, const bool use_interp_simple)
114
223
{
115
224
        const bool use_vert_interp = CustomData_has_interp(&bm->vdata);
116
 
        int x, y;
 
225
        const bool use_loop_interp = CustomData_has_interp(&bm->ldata);
 
226
        unsigned int x, y;
 
227
 
 
228
        /* for use_loop_interp */
 
229
        BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]);
 
230
 
 
231
        float (*weight_table)[4];
117
232
 
118
233
#define XY(_x, _y)  ((_x) + ((_y) * (xtot)))
119
234
 
141
256
                true);
142
257
#endif
143
258
 
 
259
        if (use_interp_simple || use_vert_interp || use_loop_interp) {
 
260
                weight_table = MEM_mallocN(sizeof(*weight_table) * (size_t)(xtot * ytot), __func__);
 
261
                barycentric_weights_v2_grid_cache(xtot, ytot, weight_table);
 
262
        }
 
263
        else {
 
264
                weight_table = NULL;
 
265
        }
 
266
 
 
267
 
 
268
        /* Store loops */
 
269
        if (use_loop_interp) {
 
270
                /* x2 because each edge connects 2 loops */
 
271
                larr_x_a = MEM_mallocN(sizeof(*larr_x_a) * (xtot - 1), __func__);
 
272
                larr_x_b = MEM_mallocN(sizeof(*larr_x_b) * (xtot - 1), __func__);
 
273
 
 
274
                larr_y_a = MEM_mallocN(sizeof(*larr_y_a) * (ytot - 1), __func__);
 
275
                larr_y_b = MEM_mallocN(sizeof(*larr_y_b) * (ytot - 1), __func__);
 
276
 
 
277
                /* fill in the loops */
 
278
                for (x = 0; x < xtot - 1; x++) {
 
279
                        bm_loop_pair_from_verts(v_grid[XY(x,        0)], v_grid[XY(x + 1,        0)], larr_x_a[x]);
 
280
                        bm_loop_pair_from_verts(v_grid[XY(x, ytot - 1)], v_grid[XY(x + 1, ytot - 1)], larr_x_b[x]);
 
281
                        bm_loop_pair_test_copy(larr_x_a[x], larr_x_b[x]);
 
282
                }
 
283
 
 
284
                for (y = 0; y < ytot - 1; y++) {
 
285
                        bm_loop_pair_from_verts(v_grid[XY(0,        y)], v_grid[XY(0,        y + 1)], larr_y_a[y]);
 
286
                        bm_loop_pair_from_verts(v_grid[XY(xtot - 1, y)], v_grid[XY(xtot - 1, y + 1)], larr_y_b[y]);
 
287
                        bm_loop_pair_test_copy(larr_y_a[y], larr_y_b[y]);
 
288
                }
 
289
        }
 
290
 
 
291
 
144
292
        /* Build Verts */
145
293
        for (y = 1; y < ytot - 1; y++) {
146
294
#ifdef BARYCENTRIC_INTERP
162
310
 
163
311
                        /* place the vertex */
164
312
#ifdef BARYCENTRIC_INTERP
165
 
                        {
 
313
                        if (use_interp_simple == false) {
166
314
                                float co_a[3], co_b[3];
167
315
 
168
316
                                barycentric_transform(
178
326
 
179
327
                                interp_v3_v3v3(co, co_a, co_b, (float)y / ((float)ytot - 1));
180
328
                        }
181
 
 
182
 
#else
183
 
                        interp_v3_v3v3(
184
 
                                co,
185
 
                                v_grid[x]->co,
186
 
                                v_grid[(xtot * ytot) + (x - xtot)]->co,
187
 
                                (float)y / ((float)ytot - 1));
 
329
                        else
188
330
#endif
189
 
 
190
 
                        v = BM_vert_create(bm, co, NULL, 0);
 
331
                        {
 
332
                                const float *w = weight_table[XY(x, y)];
 
333
 
 
334
                                zero_v3(co);
 
335
                                madd_v3_v3fl(co, v_grid[XY(x,        0)]->co, w[0]);
 
336
                                madd_v3_v3fl(co, v_grid[XY(0,        y)]->co, w[1]);
 
337
                                madd_v3_v3fl(co, v_grid[XY(x, ytot - 1)]->co, w[2]);
 
338
                                madd_v3_v3fl(co, v_grid[XY(xtot - 1, y)]->co, w[3]);
 
339
                        }
 
340
 
 
341
                        v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
191
342
                        v_grid[(y * xtot) + x] = v;
192
343
 
193
344
                        /* interpolate only along one axis, this could be changed
194
345
                         * but from user pov gives predictable results since these are selected loop */
195
346
                        if (use_vert_interp) {
196
 
                                void *v_cdata[2] = {
197
 
                                    v_grid[XY(x,          0)]->head.data,
198
 
                                    v_grid[XY(x, (ytot - 1))]->head.data,
 
347
                                const float *w = weight_table[XY(x, y)];
 
348
 
 
349
                                void *v_cdata[4] = {
 
350
                                    v_grid[XY(x,        0)]->head.data,
 
351
                                    v_grid[XY(0,        y)]->head.data,
 
352
                                    v_grid[XY(x, ytot - 1)]->head.data,
 
353
                                    v_grid[XY(xtot - 1, y)]->head.data,
199
354
                                };
200
 
                                const float t = (float)y / ((float)ytot - 1);
201
 
                                const float w[2] = {1.0f - t, t};
202
 
                                CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 2, v->head.data);
 
355
 
 
356
                                CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 4, v->head.data);
203
357
                        }
204
358
 
205
359
                }
218
372
                                        v_grid[XY(x + 1, y + 1)],  /* TR */
219
373
                                        v_grid[XY(x + 1, y + 0)],  /* BR */
220
374
                                        NULL,
221
 
                                        false);
 
375
                                        BM_CREATE_NOP);
222
376
                        }
223
377
                        else {
224
378
                                f = BM_face_create_quad_tri(
228
382
                                        v_grid[XY(x,     y + 1)],  /* TL */
229
383
                                        v_grid[XY(x,     y + 0)],  /* BL */
230
384
                                        NULL,
231
 
                                        false);
232
 
                        }
 
385
                                        BM_CREATE_NOP);
 
386
                        }
 
387
 
 
388
 
 
389
                        if (use_loop_interp && (larr_x_a[x][0] || larr_y_a[y][0])) {
 
390
                                /* bottom/left/top/right */
 
391
                                BMLoop *l_quad[4];
 
392
                                BMLoop *l_bound[4];
 
393
                                BMLoop *l_tmp;
 
394
                                unsigned int x_side, y_side, i;
 
395
                                char interp_from;
 
396
 
 
397
 
 
398
                                if (larr_x_a[x][0] && larr_y_a[y][0]) {
 
399
                                        interp_from = 'B';  /* B == both */
 
400
                                        l_tmp = larr_x_a[x][0];
 
401
                                }
 
402
                                else if (larr_x_a[x][0]) {
 
403
                                        interp_from = 'X';
 
404
                                        l_tmp = larr_x_a[x][0];
 
405
                                }
 
406
                                else {
 
407
                                        interp_from = 'Y';
 
408
                                        l_tmp = larr_y_a[y][0];
 
409
                                }
 
410
 
 
411
                                BM_elem_attrs_copy(bm, bm, l_tmp->f, f);
 
412
 
 
413
 
 
414
                                BM_face_as_array_loop_quad(f, l_quad);
 
415
 
 
416
                                l_tmp = BM_FACE_FIRST_LOOP(f);
 
417
 
 
418
                                if (use_flip) {
 
419
                                        l_quad[0] = l_tmp; l_tmp = l_tmp->next;
 
420
                                        l_quad[1] = l_tmp; l_tmp = l_tmp->next;
 
421
                                        l_quad[3] = l_tmp; l_tmp = l_tmp->next;
 
422
                                        l_quad[2] = l_tmp;
 
423
                                }
 
424
                                else {
 
425
                                        l_quad[2] = l_tmp; l_tmp = l_tmp->next;
 
426
                                        l_quad[3] = l_tmp; l_tmp = l_tmp->next;
 
427
                                        l_quad[1] = l_tmp; l_tmp = l_tmp->next;
 
428
                                        l_quad[0] = l_tmp;
 
429
                                }
 
430
 
 
431
                                i = 0;
 
432
 
 
433
                                for (x_side = 0; x_side < 2; x_side++) {
 
434
                                        for (y_side = 0; y_side < 2; y_side++) {
 
435
                                                if (interp_from == 'B') {
 
436
                                                        const float *w = weight_table[XY(x + x_side, y + y_side)];
 
437
                                                        l_bound[0] = larr_x_a[x][x_side];  /* B */
 
438
                                                        l_bound[1] = larr_y_a[y][y_side];  /* L */
 
439
                                                        l_bound[2] = larr_x_b[x][x_side];  /* T */
 
440
                                                        l_bound[3] = larr_y_b[y][y_side];  /* R */
 
441
 
 
442
                                                        bm_loop_interp_from_grid_boundary_4(bm, l_quad[i++], l_bound, w);
 
443
                                                }
 
444
                                                else if (interp_from == 'X') {
 
445
                                                        const float t = (float)(y + y_side) / (float)(ytot - 1);
 
446
                                                        l_bound[0] = larr_x_a[x][x_side];  /* B */
 
447
                                                        l_bound[1] = larr_x_b[x][x_side];  /* T */
 
448
 
 
449
                                                        bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
 
450
                                                }
 
451
                                                else if (interp_from == 'Y') {
 
452
                                                        const float t = (float)(x + x_side) / (float)(xtot - 1);
 
453
                                                        l_bound[0] = larr_y_a[y][y_side];  /* L */
 
454
                                                        l_bound[1] = larr_y_b[y][y_side];  /* R */
 
455
 
 
456
                                                        bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
 
457
                                                }
 
458
                                                else {
 
459
                                                        BLI_assert(0);
 
460
                                                }
 
461
                                        }
 
462
                                }
 
463
                        }
 
464
                        /* end interp */
 
465
 
 
466
 
233
467
                        BMO_elem_flag_enable(bm, f, FACE_OUT);
234
468
                        f->mat_nr = mat_nr;
235
469
                        if (use_smooth) {
237
471
                        }
238
472
                }
239
473
        }
 
474
 
 
475
        if (use_loop_interp) {
 
476
                MEM_freeN(larr_x_a);
 
477
                MEM_freeN(larr_y_a);
 
478
                MEM_freeN(larr_x_b);
 
479
                MEM_freeN(larr_y_b);
 
480
        }
 
481
 
 
482
        if (weight_table) {
 
483
                MEM_freeN(weight_table);
 
484
        }
 
485
 
240
486
#undef XY
241
487
}
242
488
 
243
489
static void bm_grid_fill(BMesh *bm,
244
490
                         struct BMEdgeLoopStore *estore_a,      struct BMEdgeLoopStore *estore_b,
245
491
                         struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b,
246
 
                         const short mat_nr, const bool use_smooth)
 
492
                         const short mat_nr, const bool use_smooth, const bool use_interp_simple)
247
493
{
248
494
#define USE_FLIP_DETECT
249
495
 
250
 
        const int xtot = BM_edgeloop_length_get(estore_a);
251
 
        const int ytot = BM_edgeloop_length_get(estore_rail_a);
 
496
        const unsigned int xtot = (unsigned int)BM_edgeloop_length_get(estore_a);
 
497
        const unsigned int ytot = (unsigned int)BM_edgeloop_length_get(estore_rail_a);
252
498
        //BMVert *v;
253
 
        int i;
 
499
        unsigned int i;
254
500
#ifdef DEBUG
255
 
        int x, y;
 
501
        unsigned int x, y;
256
502
#endif
257
503
        LinkData *el;
258
504
        bool use_flip = false;
263
509
        ListBase *lb_rail_a = BM_edgeloop_verts_get(estore_rail_a);
264
510
        ListBase *lb_rail_b = BM_edgeloop_verts_get(estore_rail_b);
265
511
 
266
 
        BMVert **v_grid = MEM_callocN(sizeof(BMVert *) * xtot * ytot, __func__);
 
512
        BMVert **v_grid = MEM_callocN(sizeof(BMVert *) * (size_t)(xtot * ytot), __func__);
267
513
        /**
268
514
         * <pre>
269
515
         *           estore_b
314
560
#endif
315
561
 
316
562
 
317
 
        bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip);
 
563
        bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip, use_interp_simple);
318
564
        MEM_freeN(v_grid);
319
565
 
320
566
#undef USE_FLIP_DETECT
322
568
 
323
569
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
324
570
{
325
 
        return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK);
 
571
        return BMO_elem_flag_test_bool((BMesh *)bm_v, e, EDGE_MARK);
326
572
}
327
573
 
328
574
static bool bm_edge_test_rail_cb(BMEdge *e, void *UNUSED(bm_v))
343
589
        struct BMEdgeLoopStore *estore_rail_a, *estore_rail_b;
344
590
        BMVert *v_a_first, *v_a_last;
345
591
        BMVert *v_b_first, *v_b_last;
346
 
        const short mat_nr     = BMO_slot_int_get(op->slots_in,  "mat_nr");
347
 
        const bool use_smooth  = BMO_slot_bool_get(op->slots_in, "use_smooth");
 
592
        const short mat_nr = (short)BMO_slot_int_get(op->slots_in,  "mat_nr");
 
593
        const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
 
594
        const bool use_interp_simple = BMO_slot_bool_get(op->slots_in, "use_interp_simple");
348
595
 
349
596
        int count;
350
597
        bool change = false;
436
683
 
437
684
        /* finally we have all edge loops needed */
438
685
        bm_grid_fill(bm, estore_a, estore_b, estore_rail_a, estore_rail_b,
439
 
                     mat_nr, use_smooth);
 
686
                     mat_nr, use_smooth, use_interp_simple);
440
687
 
441
688
        change = true;
 
689
 
 
690
 
442
691
cleanup:
443
692
        BM_mesh_edgeloops_free(&eloops);
444
693
        BM_mesh_edgeloops_free(&eloops_rail);