~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/blenkernel/intern/editderivedmesh.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-07-23 08:54:18 UTC
  • mfrom: (14.2.16 sid)
  • mto: (14.2.19 sid)
  • mto: This revision was merged to the branch mainline in revision 42.
  • Revision ID: package-import@ubuntu.com-20120723085418-9foz30v6afaf5ffs
Tags: 2.63a-2
* debian/: Cycles support added (Closes: #658075)
  For now, this top feature has been enabled only
  on [any-amd64 any-i386] architectures because
  of OpenImageIO failing on all others
* debian/: scripts installation path changed
  from /usr/lib to /usr/share:
  + debian/patches/: patchset re-worked for path changing
  + debian/control: "Breaks" field added on yafaray-exporter

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ***** BEGIN GPL LICENSE BLOCK *****
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License
 
6
 * as published by the Free Software Foundation; either version 2
 
7
 * of the License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software Foundation,
 
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 *
 
18
 * The Original Code is Copyright (C) 2005 Blender Foundation.
 
19
 * All rights reserved.
 
20
 *
 
21
 * The Original Code is: all of this file.
 
22
 *
 
23
 * Contributor(s): none yet.
 
24
 *
 
25
 * ***** END GPL LICENSE BLOCK *****
 
26
 */
 
27
 
 
28
/** \file blender/blenkernel/intern/editderivedmesh.c
 
29
 *  \ingroup bke
 
30
 */
 
31
 
 
32
#include <string.h>
 
33
#include <limits.h>
 
34
#include <math.h>
 
35
 
 
36
#include "GL/glew.h"
 
37
 
 
38
#include "BLI_utildefines.h"
 
39
#include "BLI_blenlib.h"
 
40
#include "BLI_edgehash.h"
 
41
#include "BLI_math.h"
 
42
#include "BLI_pbvh.h"
 
43
 
 
44
#include "BKE_cdderivedmesh.h"
 
45
#include "BKE_global.h"
 
46
#include "BKE_mesh.h"
 
47
#include "BKE_paint.h"
 
48
 
 
49
 
 
50
#include "DNA_mesh_types.h"
 
51
#include "DNA_meshdata_types.h"
 
52
#include "DNA_object_types.h"
 
53
 
 
54
#include "MEM_guardedalloc.h"
 
55
 
 
56
#include "GPU_buffers.h"
 
57
#include "GPU_draw.h"
 
58
#include "GPU_extensions.h"
 
59
#include "GPU_material.h"
 
60
 
 
61
/* bmesh */
 
62
#include "BKE_tessmesh.h"
 
63
#include "BLI_array.h"
 
64
#include "BLI_scanfill.h"
 
65
 
 
66
#include "bmesh.h"
 
67
/* end bmesh */
 
68
 
 
69
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
 
70
 
 
71
 
 
72
BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate)
 
73
{
 
74
        BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
 
75
 
 
76
        tm->bm = bm;
 
77
        if (do_tessellate) {
 
78
                BMEdit_RecalcTessellation(tm);
 
79
        }
 
80
 
 
81
        return tm;
 
82
}
 
83
 
 
84
BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
 
85
{
 
86
        BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
 
87
        *tm2 = *tm;
 
88
 
 
89
        tm2->derivedCage = tm2->derivedFinal = NULL;
 
90
 
 
91
        tm2->bm = BM_mesh_copy(tm->bm);
 
92
 
 
93
        /* The tessellation is NOT calculated on the copy here,
 
94
         * because currently all the callers of this function use
 
95
         * it to make a backup copy of the BMEditMesh to restore
 
96
         * it in the case of errors in an operation. For perf
 
97
         * reasons, in that case it makes more sense to do the
 
98
         * tessellation only when/if that copy ends up getting
 
99
         * used.*/
 
100
        tm2->looptris = NULL;
 
101
 
 
102
        tm2->vert_index = NULL;
 
103
        tm2->edge_index = NULL;
 
104
        tm2->face_index = NULL;
 
105
 
 
106
        return tm2;
 
107
}
 
108
 
 
109
static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
 
110
{
 
111
        /* use this to avoid locking pthread for _every_ polygon
 
112
         * and calling the fill function */
 
113
#define USE_TESSFACE_SPEEDUP
 
114
 
 
115
        BMesh *bm = tm->bm;
 
116
        BMLoop *(*looptris)[3]= NULL;
 
117
        BLI_array_declare(looptris);
 
118
        BMIter iter, liter;
 
119
        BMFace *f;
 
120
        BMLoop *l;
 
121
        int i = 0, j;
 
122
 
 
123
        ScanFillContext sf_ctx;
 
124
 
 
125
#if 0
 
126
        /* note, we could be clever and re-use this array but would need to ensure
 
127
         * its realloced at some point, for now just free it */
 
128
        if (tm->looptris) MEM_freeN(tm->looptris);
 
129
 
 
130
        /* Use tm->tottri when set, this means no reallocs while transforming,
 
131
         * (unless scanfill fails), otherwise... */
 
132
        /* allocate the length of totfaces, avoid many small reallocs,
 
133
         * if all faces are tri's it will be correct, quads == 2x allocs */
 
134
        BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
 
135
#else
 
136
 
 
137
        /* this means no reallocs for quad dominant models, for */
 
138
        if ( (tm->looptris != NULL) &&
 
139
             (tm->tottri != 0) &&
 
140
             /* (totrti <= bm->totface * 2) would be fine for all quads,
 
141
              * but in case there are some ngons, still re-use the array */
 
142
             (tm->tottri <= bm->totface * 3))
 
143
        {
 
144
                looptris = tm->looptris;
 
145
        }
 
146
        else {
 
147
                if (tm->looptris) MEM_freeN(tm->looptris);
 
148
                BLI_array_reserve(looptris, bm->totface);
 
149
        }
 
150
 
 
151
#endif
 
152
 
 
153
        f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL);
 
154
        for ( ; f; f=BM_iter_step(&iter)) {
 
155
                /*don't consider two-edged faces*/
 
156
                if (f->len < 3) {
 
157
                        /* do nothing */
 
158
                }
 
159
 
 
160
#ifdef USE_TESSFACE_SPEEDUP
 
161
 
 
162
                /* no need to ensure the loop order, we know its ok */
 
163
 
 
164
                else if (f->len == 3) {
 
165
                        BLI_array_growone(looptris);
 
166
                        l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
 
167
                        for (j=0; l; l=BM_iter_step(&liter), j++) {
 
168
                                looptris[i][j] = l;
 
169
                        }
 
170
                        i += 1;
 
171
                }
 
172
                else if (f->len == 4) {
 
173
                        BMLoop *ltmp[4];
 
174
                        BLI_array_growitems(looptris, 2);
 
175
 
 
176
                        l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
 
177
                        for (j=0; l; l=BM_iter_step(&liter), j++) {
 
178
                                ltmp[j] = l;
 
179
                        }
 
180
 
 
181
                        looptris[i][0] = ltmp[0];
 
182
                        looptris[i][1] = ltmp[1];
 
183
                        looptris[i][2] = ltmp[2];
 
184
                        i += 1;
 
185
 
 
186
                        looptris[i][0] = ltmp[0];
 
187
                        looptris[i][1] = ltmp[2];
 
188
                        looptris[i][2] = ltmp[3];
 
189
                        i += 1;
 
190
                }
 
191
 
 
192
#endif /* USE_TESSFACE_SPEEDUP */
 
193
 
 
194
                else {
 
195
                        ScanFillVert *v, *lastv=NULL, *firstv=NULL;
 
196
                        /* ScanFillEdge *e; */ /* UNUSED */
 
197
                        ScanFillFace *efa;
 
198
                        int totfilltri;
 
199
 
 
200
                        BLI_begin_edgefill(&sf_ctx);
 
201
                        /*scanfill time*/
 
202
                        l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
 
203
                        for (j=0; l; l=BM_iter_step(&liter), j++) {
 
204
                                /*mark order*/
 
205
                                BM_elem_index_set(l, j); /* set_loop */
 
206
 
 
207
                                v = BLI_addfillvert(&sf_ctx, l->v->co);
 
208
                                v->tmp.p = l;
 
209
 
 
210
                                if (lastv) {
 
211
                                        /* e = */ BLI_addfilledge(&sf_ctx, lastv, v);
 
212
                                }
 
213
 
 
214
                                lastv = v;
 
215
                                if (firstv==NULL) firstv = v;
 
216
                        }
 
217
 
 
218
                        /*complete the loop*/
 
219
                        BLI_addfilledge(&sf_ctx, firstv, v);
 
220
 
 
221
                        totfilltri = BLI_edgefill_ex(&sf_ctx, FALSE, f->no);
 
222
                        BLI_array_growitems(looptris, totfilltri);
 
223
 
 
224
                        for (efa = sf_ctx.fillfacebase.first; efa; efa=efa->next) {
 
225
                                BMLoop *l1= efa->v1->tmp.p;
 
226
                                BMLoop *l2= efa->v2->tmp.p;
 
227
                                BMLoop *l3= efa->v3->tmp.p;
 
228
 
 
229
                                if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop*, l1, l2); }
 
230
                                if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop*, l2, l3); }
 
231
                                if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop*, l1, l2); }
 
232
 
 
233
                                looptris[i][0] = l1;
 
234
                                looptris[i][1] = l2;
 
235
                                looptris[i][2] = l3;
 
236
                                i += 1;
 
237
                        }
 
238
 
 
239
                        BLI_end_edgefill(&sf_ctx);
 
240
                }
 
241
        }
 
242
 
 
243
        tm->tottri = i;
 
244
        tm->looptris = looptris;
 
245
 
 
246
#undef USE_TESSFACE_SPEEDUP
 
247
 
 
248
}
 
249
 
 
250
void BMEdit_RecalcTessellation(BMEditMesh *em)
 
251
{
 
252
        BMEdit_RecalcTessellation_intern(em);
 
253
 
 
254
        /* commented because editbmesh_build_data() ensures we get tessfaces */
 
255
#if 0
 
256
        if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
 
257
                if (em->derivedFinal->recalcTessellation)
 
258
                        em->derivedFinal->recalcTessellation(em->derivedFinal);
 
259
        }
 
260
        else if (em->derivedFinal) {
 
261
                if (em->derivedCage->recalcTessellation)
 
262
                        em->derivedCage->recalcTessellation(em->derivedCage);
 
263
                if (em->derivedFinal->recalcTessellation)
 
264
                        em->derivedFinal->recalcTessellation(em->derivedFinal);
 
265
        }
 
266
#endif
 
267
}
 
268
 
 
269
void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
 
270
{
 
271
        BMesh *bm = em->bm;
 
272
        int act;
 
273
 
 
274
        if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
 
275
                act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
 
276
                CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
 
277
 
 
278
                act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
 
279
                CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
 
280
 
 
281
                act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
 
282
                CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
 
283
 
 
284
                act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
 
285
                CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
 
286
        }
 
287
}
 
288
 
 
289
/*does not free the BMEditMesh struct itself*/
 
290
void BMEdit_Free(BMEditMesh *em)
 
291
{
 
292
        if (em->derivedFinal) {
 
293
                if (em->derivedFinal!=em->derivedCage) {
 
294
                        em->derivedFinal->needsFree= 1;
 
295
                        em->derivedFinal->release(em->derivedFinal);
 
296
                }
 
297
                em->derivedFinal= NULL;
 
298
        }
 
299
        if (em->derivedCage) {
 
300
                em->derivedCage->needsFree= 1;
 
301
                em->derivedCage->release(em->derivedCage);
 
302
                em->derivedCage= NULL;
 
303
        }
 
304
 
 
305
        if (em->looptris) MEM_freeN(em->looptris);
 
306
 
 
307
        if (em->vert_index) MEM_freeN(em->vert_index);
 
308
        if (em->edge_index) MEM_freeN(em->edge_index);
 
309
        if (em->face_index) MEM_freeN(em->face_index);
 
310
 
 
311
        if (em->bm)
 
312
                BM_mesh_free(em->bm);
 
313
}
 
314
 
 
315
/*
 
316
 * ok, basic design:
 
317
 *
 
318
 * the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
 
319
 * to three loops per triangle.  the derivedmesh stores a cache of tessellations
 
320
 * for each face.  this cache will smartly update as needed (though at first
 
321
 * it'll simply be more brute force).  keeping track of face/edge counts may
 
322
 * be a small problbm.
 
323
 *
 
324
 * this won't be the most efficient thing, considering that internal edges and
 
325
 * faces of tessellations are exposed.  looking up an edge by index in particular
 
326
 * is likely to be a little slow.
 
327
 */
 
328
 
 
329
typedef struct EditDerivedBMesh {
 
330
        DerivedMesh dm;
 
331
 
 
332
        Object *ob;
 
333
        BMEditMesh *tc;
 
334
 
 
335
        float (*vertexCos)[3];
 
336
        float (*vertexNos)[3];
 
337
        float (*polyNos)[3];
 
338
 
 
339
        /* private variables, for number of verts/edges/faces
 
340
         * within the above hash/table members*/
 
341
        int tv, te, tf;
 
342
} EditDerivedBMesh;
 
343
 
 
344
static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
 
345
{
 
346
        /* Nothing to do: normals are already calculated and stored on the
 
347
         * BMVerts and BMFaces */
 
348
}
 
349
 
 
350
static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
 
351
{
 
352
        /* do nothing */
 
353
}
 
354
 
 
355
static void emDM_foreachMappedVert(
 
356
        DerivedMesh *dm,
 
357
        void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
 
358
        void *userData)
 
359
{
 
360
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
361
        BMVert *eve;
 
362
        BMIter iter;
 
363
        int i;
 
364
 
 
365
        eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 
366
        for (i=0; eve; i++, eve=BM_iter_step(&iter)) {
 
367
                if (bmdm->vertexCos) {
 
368
                        func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
 
369
                }
 
370
                else {
 
371
                        func(userData, i, eve->co, eve->no, NULL);
 
372
                }
 
373
        }
 
374
}
 
375
static void emDM_foreachMappedEdge(
 
376
        DerivedMesh *dm,
 
377
        void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
 
378
        void *userData)
 
379
{
 
380
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
381
        BMEdge *eed;
 
382
        BMIter iter;
 
383
        int i;
 
384
 
 
385
        if (bmdm->vertexCos) {
 
386
 
 
387
                BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
 
388
 
 
389
                eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 
390
                for (i=0; eed; i++,eed=BM_iter_step(&iter))
 
391
                        func(userData, i,
 
392
                                 bmdm->vertexCos[BM_elem_index_get(eed->v1)],
 
393
                                 bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
 
394
        }
 
395
        else {
 
396
                eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 
397
                for (i=0; eed; i++,eed=BM_iter_step(&iter))
 
398
                        func(userData, i, eed->v1->co, eed->v2->co);
 
399
        }
 
400
}
 
401
 
 
402
static void emDM_drawMappedEdges(
 
403
                DerivedMesh *dm,
 
404
                DMSetDrawOptions setDrawOptions,
 
405
                void *userData)
 
406
{
 
407
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
408
        BMEdge *eed;
 
409
        BMIter iter;
 
410
        int i;
 
411
 
 
412
        if (bmdm->vertexCos) {
 
413
 
 
414
                BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
 
415
 
 
416
                glBegin(GL_LINES);
 
417
                eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 
418
                for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
 
419
                        if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
 
420
                                glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
 
421
                                glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
 
422
                        }
 
423
                }
 
424
                glEnd();
 
425
        }
 
426
        else {
 
427
                glBegin(GL_LINES);
 
428
                eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 
429
                for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
 
430
                        if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
 
431
                                glVertex3fv(eed->v1->co);
 
432
                                glVertex3fv(eed->v2->co);
 
433
                        }
 
434
                }
 
435
                glEnd();
 
436
        }
 
437
}
 
438
static void emDM_drawEdges(
 
439
                DerivedMesh *dm,
 
440
                int UNUSED(drawLooseEdges),
 
441
                int UNUSED(drawAllEdges))
 
442
{
 
443
        emDM_drawMappedEdges(dm, NULL, NULL);
 
444
}
 
445
 
 
446
static void emDM_drawMappedEdgesInterp(
 
447
                DerivedMesh *dm,
 
448
                DMSetDrawOptions setDrawOptions,
 
449
                DMSetDrawInterpOptions setDrawInterpOptions,
 
450
                void *userData)
 
451
{
 
452
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
453
        BMEdge *eed;
 
454
        BMIter iter;
 
455
        int i;
 
456
 
 
457
        if (bmdm->vertexCos) {
 
458
 
 
459
                BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
 
460
 
 
461
                glBegin(GL_LINES);
 
462
                eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 
463
                for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
 
464
                        if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
 
465
                                setDrawInterpOptions(userData, i, 0.0);
 
466
                                glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
 
467
                                setDrawInterpOptions(userData, i, 1.0);
 
468
                                glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
 
469
                        }
 
470
                }
 
471
                glEnd();
 
472
        }
 
473
        else {
 
474
                glBegin(GL_LINES);
 
475
                eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 
476
                for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
 
477
                        if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
 
478
                                setDrawInterpOptions(userData, i, 0.0);
 
479
                                glVertex3fv(eed->v1->co);
 
480
                                setDrawInterpOptions(userData, i, 1.0);
 
481
                                glVertex3fv(eed->v2->co);
 
482
                        }
 
483
                }
 
484
                glEnd();
 
485
        }
 
486
}
 
487
 
 
488
static void emDM_drawUVEdges(DerivedMesh *dm)
 
489
{
 
490
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
491
        BMEditMesh *em = bmdm->tc;
 
492
        BMFace *efa;
 
493
        BMIter iter;
 
494
 
 
495
        glBegin(GL_LINES);
 
496
        BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
 
497
                BMIter liter;
 
498
                BMLoop *l;
 
499
                MLoopUV *lastluv = NULL, *firstluv = NULL;
 
500
 
 
501
                if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
 
502
                        continue;
 
503
 
 
504
                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
 
505
                        MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
506
 
 
507
                        if (luv) {
 
508
                                if (lastluv)
 
509
                                        glVertex2fv(luv->uv);
 
510
                                glVertex2fv(luv->uv);
 
511
 
 
512
                                lastluv = luv;
 
513
                                if (!firstluv)
 
514
                                        firstluv = luv;
 
515
                        }
 
516
                }
 
517
 
 
518
                if (lastluv) {
 
519
                        glVertex2fv(lastluv->uv);
 
520
                        glVertex2fv(firstluv->uv);
 
521
                }
 
522
        }
 
523
        glEnd();
 
524
}
 
525
 
 
526
static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3])
 
527
{
 
528
        BMIter iter;
 
529
        BMLoop *l;
 
530
        int tot = 0;
 
531
 
 
532
        zero_v3(cent);
 
533
 
 
534
        /*simple (and stupid) median (average) based method :/ */
 
535
 
 
536
        if (vertexCos) {
 
537
                l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, efa);
 
538
                for (; l; l=BM_iter_step(&iter)) {
 
539
                        add_v3_v3(cent, vertexCos[BM_elem_index_get(l->v)]);
 
540
                        tot++;
 
541
                }
 
542
        }
 
543
        else {
 
544
                l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, efa);
 
545
                for (; l; l=BM_iter_step(&iter)) {
 
546
                        add_v3_v3(cent, l->v->co);
 
547
                        tot++;
 
548
                }
 
549
        }
 
550
 
 
551
        if (tot==0) return;
 
552
        mul_v3_fl(cent, 1.0f/(float)tot);
 
553
}
 
554
 
 
555
static void emDM_foreachMappedFaceCenter(
 
556
        DerivedMesh *dm,
 
557
        void (*func)(void *userData, int index, const float co[3], const float no[3]),
 
558
        void *userData)
 
559
{
 
560
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
561
        float (*polyNos)[3] = NULL;
 
562
        BMFace *efa;
 
563
        BMIter iter;
 
564
        float cent[3];
 
565
        int i;
 
566
 
 
567
        /* ensure for face center calculation */
 
568
        if (bmdm->vertexCos) {
 
569
                BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
 
570
                polyNos = bmdm->polyNos;
 
571
 
 
572
                BLI_assert(polyNos != NULL);
 
573
        }
 
574
 
 
575
        efa = BM_iter_new(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
 
576
        for (i=0; efa; efa=BM_iter_step(&iter), i++) {
 
577
                emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
 
578
                func(userData, i, cent, polyNos ? polyNos[i] : efa->no);
 
579
        }
 
580
}
 
581
 
 
582
static void emDM_drawMappedFaces(
 
583
                DerivedMesh *dm,
 
584
                DMSetDrawOptions setDrawOptions,
 
585
                DMSetMaterial setMaterial,
 
586
                DMCompareDrawOptions compareDrawOptions,
 
587
                void *userData,
 
588
                DMDrawFlag flag)
 
589
{
 
590
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
591
        BMFace *efa;
 
592
        struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
 
593
        const int tottri= bmdm->tc->tottri;
 
594
        const int lasttri= tottri - 1; /* compare agasint this a lot */
 
595
        DMDrawOption draw_option;
 
596
        int i, flush;
 
597
        const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
 
598
 
 
599
        /* GL_ZERO is used to detect if drawing has started or not */
 
600
        GLenum poly_prev= GL_ZERO;
 
601
        GLenum shade_prev= GL_ZERO;
 
602
 
 
603
        (void)setMaterial; /* UNUSED */
 
604
 
 
605
        /* currently unused -- each original face is handled separately */
 
606
        (void)compareDrawOptions;
 
607
 
 
608
        if (bmdm->vertexCos) {
 
609
                /* add direct access */
 
610
                float (*vertexCos)[3]= bmdm->vertexCos;
 
611
                float (*vertexNos)[3]= bmdm->vertexNos;
 
612
                float (*polyNos)[3]=   bmdm->polyNos;
 
613
                // int *triPolyMap= bmdm->triPolyMap;
 
614
 
 
615
                BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
 
616
 
 
617
                for (i=0; i < tottri; i++) {
 
618
                        BMLoop **l = looptris[i];
 
619
                        int drawSmooth;
 
620
 
 
621
                        efa = l[0]->f;
 
622
                        drawSmooth= (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
 
623
 
 
624
                        draw_option = (!setDrawOptions ?
 
625
                                                   DM_DRAW_OPTION_NORMAL :
 
626
                                                   setDrawOptions(userData, BM_elem_index_get(efa)));
 
627
                        if (draw_option != DM_DRAW_OPTION_SKIP) {
 
628
                                const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
 
629
                                if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
 
630
 
 
631
                                        if (poly_prev != GL_ZERO) glEnd();
 
632
                                        poly_prev= GL_ZERO; /* force glBegin */
 
633
 
 
634
                                        glEnable(GL_POLYGON_STIPPLE);
 
635
                                        glPolygonStipple(stipple_quarttone);
 
636
                                }
 
637
 
 
638
                                if (skip_normals) {
 
639
                                        if (poly_type != poly_prev) {
 
640
                                                if (poly_prev != GL_ZERO) glEnd();
 
641
                                                glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
 
642
                                        }
 
643
                                        glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
 
644
                                        glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
 
645
                                        glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
 
646
                                }
 
647
                                else {
 
648
                                        const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
 
649
                                        if (shade_type != shade_prev) {
 
650
                                                if (poly_prev != GL_ZERO) glEnd();
 
651
                                                glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
 
652
                                                glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
 
653
                                        }
 
654
                                        if (poly_type != poly_prev) {
 
655
                                                if (poly_prev != GL_ZERO) glEnd();
 
656
                                                glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
 
657
                                        }
 
658
 
 
659
                                        if (!drawSmooth) {
 
660
                                                glNormal3fv(polyNos[BM_elem_index_get(efa)]);
 
661
                                                glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
 
662
                                                glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
 
663
                                                glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
 
664
                                        }
 
665
                                        else {
 
666
                                                glNormal3fv(vertexNos[BM_elem_index_get(l[0]->v)]);
 
667
                                                glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
 
668
                                                glNormal3fv(vertexNos[BM_elem_index_get(l[1]->v)]);
 
669
                                                glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
 
670
                                                glNormal3fv(vertexNos[BM_elem_index_get(l[2]->v)]);
 
671
                                                glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
 
672
                                        }
 
673
                                }
 
674
 
 
675
                                flush= (draw_option == DM_DRAW_OPTION_STIPPLE);
 
676
                                if (!skip_normals && !flush && (i != lasttri))
 
677
                                        flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
 
678
 
 
679
                                if (flush) {
 
680
                                        glEnd();
 
681
                                        poly_prev= GL_ZERO; /* force glBegin */
 
682
 
 
683
                                        glDisable(GL_POLYGON_STIPPLE);
 
684
                                }
 
685
                        }
 
686
                }
 
687
        }
 
688
        else {
 
689
                BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_FACE);
 
690
 
 
691
                for (i=0; i < tottri; i++) {
 
692
                        BMLoop **l = looptris[i];
 
693
                        int drawSmooth;
 
694
 
 
695
                        efa = l[0]->f;
 
696
                        drawSmooth= (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
 
697
 
 
698
                        draw_option = (!setDrawOptions ?
 
699
                                                   DM_DRAW_OPTION_NORMAL :
 
700
                                                   setDrawOptions(userData, BM_elem_index_get(efa)));
 
701
                        if (draw_option != DM_DRAW_OPTION_SKIP) {
 
702
                                const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
 
703
                                if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
 
704
 
 
705
                                        if (poly_prev != GL_ZERO) glEnd();
 
706
                                        poly_prev= GL_ZERO; /* force glBegin */
 
707
 
 
708
                                        glEnable(GL_POLYGON_STIPPLE);
 
709
                                        glPolygonStipple(stipple_quarttone);
 
710
                                }
 
711
 
 
712
                                if (skip_normals) {
 
713
                                        if (poly_type != poly_prev) {
 
714
                                                if (poly_prev != GL_ZERO) glEnd();
 
715
                                                glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
 
716
                                        }
 
717
                                        glVertex3fv(l[0]->v->co);
 
718
                                        glVertex3fv(l[1]->v->co);
 
719
                                        glVertex3fv(l[2]->v->co);
 
720
                                }
 
721
                                else {
 
722
                                        const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
 
723
                                        if (shade_type != shade_prev) {
 
724
                                                if (poly_prev != GL_ZERO) glEnd();
 
725
                                                glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
 
726
                                                glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
 
727
                                        }
 
728
                                        if (poly_type != poly_prev) {
 
729
                                                if (poly_prev != GL_ZERO) glEnd();
 
730
                                                glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
 
731
                                        }
 
732
 
 
733
                                        if (!drawSmooth) {
 
734
                                                glNormal3fv(efa->no);
 
735
                                                glVertex3fv(l[0]->v->co);
 
736
                                                glVertex3fv(l[1]->v->co);
 
737
                                                glVertex3fv(l[2]->v->co);
 
738
                                        }
 
739
                                        else {
 
740
                                                glNormal3fv(l[0]->v->no);
 
741
                                                glVertex3fv(l[0]->v->co);
 
742
                                                glNormal3fv(l[1]->v->no);
 
743
                                                glVertex3fv(l[1]->v->co);
 
744
                                                glNormal3fv(l[2]->v->no);
 
745
                                                glVertex3fv(l[2]->v->co);
 
746
                                        }
 
747
                                }
 
748
 
 
749
                                flush= (draw_option == DM_DRAW_OPTION_STIPPLE);
 
750
                                if (!skip_normals && !flush && (i != lasttri)) {
 
751
                                        flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
 
752
                                }
 
753
 
 
754
                                if (flush) {
 
755
                                        glEnd();
 
756
                                        poly_prev= GL_ZERO; /* force glBegin */
 
757
 
 
758
                                        glDisable(GL_POLYGON_STIPPLE);
 
759
                                }
 
760
                        }
 
761
                }
 
762
        }
 
763
 
 
764
        /* if non zero we know a face was rendered */
 
765
        if (poly_prev != GL_ZERO) glEnd();
 
766
}
 
767
 
 
768
static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
 
769
                                 int has_uv, int has_col)
 
770
{
 
771
        if (has_uv) {
 
772
                luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
 
773
                luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
 
774
                luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
 
775
        }
 
776
 
 
777
        if (has_col) {
 
778
                lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
 
779
                lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
 
780
                lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
 
781
        }
 
782
 
 
783
 
 
784
}
 
785
 
 
786
static void emDM_drawFacesTex_common(
 
787
                DerivedMesh *dm,
 
788
                DMSetDrawOptionsTex drawParams,
 
789
                DMSetDrawOptions drawParamsMapped,
 
790
                DMCompareDrawOptions compareDrawOptions,
 
791
                void *userData)
 
792
{
 
793
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
794
        BMEditMesh *em = bmdm->tc;
 
795
        BMesh *bm= bmdm->tc->bm;
 
796
        float (*vertexCos)[3]= bmdm->vertexCos;
 
797
        float (*vertexNos)[3]= bmdm->vertexNos;
 
798
        BMFace *efa;
 
799
        MLoopUV *luv[3], dummyluv = {{0}};
 
800
        MLoopCol *lcol[3] = {NULL}, dummylcol = {0};
 
801
        int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
 
802
        int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
 
803
 
 
804
        (void) compareDrawOptions;
 
805
 
 
806
        luv[0] = luv[1] = luv[2] = &dummyluv;
 
807
 
 
808
        dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255;
 
809
 
 
810
        /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
 
811
        glShadeModel(GL_SMOOTH);
 
812
 
 
813
        BM_mesh_elem_index_ensure(bm, BM_FACE);
 
814
 
 
815
        if (vertexCos) {
 
816
                BM_mesh_elem_index_ensure(bm, BM_VERT);
 
817
 
 
818
                for (i=0; i<em->tottri; i++) {
 
819
                        BMLoop **ls = em->looptris[i];
 
820
                        MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
 
821
                        MTFace mtf = {{{0}}};
 
822
                        /*unsigned char *cp= NULL;*/ /*UNUSED*/
 
823
                        int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
 
824
                        DMDrawOption draw_option;
 
825
 
 
826
                        efa = ls[0]->f;
 
827
 
 
828
                        if (has_uv) {
 
829
                                ME_MTEXFACE_CPY(&mtf, tp);
 
830
                        }
 
831
 
 
832
                        if (drawParams)
 
833
                                draw_option= drawParams(&mtf, has_vcol, efa->mat_nr);
 
834
                        else if (drawParamsMapped)
 
835
                                draw_option= drawParamsMapped(userData, BM_elem_index_get(efa));
 
836
                        else
 
837
                                draw_option= DM_DRAW_OPTION_NORMAL;
 
838
 
 
839
                        if (draw_option != DM_DRAW_OPTION_SKIP) {
 
840
 
 
841
                                glBegin(GL_TRIANGLES);
 
842
                                if (!drawSmooth) {
 
843
                                        glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
 
844
 
 
845
                                        bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 
846
 
 
847
                                        glTexCoord2fv(luv[0]->uv);
 
848
                                        if (lcol[0])
 
849
                                                glColor3ubv((const GLubyte *)&(lcol[0]->r));
 
850
                                        glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
 
851
 
 
852
                                        glTexCoord2fv(luv[1]->uv);
 
853
                                        if (lcol[1])
 
854
                                                glColor3ubv((const GLubyte *)&(lcol[1]->r));
 
855
                                        glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
 
856
 
 
857
                                        glTexCoord2fv(luv[2]->uv);
 
858
                                        if (lcol[2])
 
859
                                                glColor3ubv((const GLubyte *)&(lcol[2]->r));
 
860
                                        glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
 
861
                                }
 
862
                                else {
 
863
                                        bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 
864
 
 
865
                                        glTexCoord2fv(luv[0]->uv);
 
866
                                        if (lcol[0])
 
867
                                                glColor3ubv((const GLubyte *)&(lcol[0]->r));
 
868
                                        glNormal3fv(vertexNos[BM_elem_index_get(ls[0]->v)]);
 
869
                                        glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
 
870
 
 
871
                                        glTexCoord2fv(luv[1]->uv);
 
872
                                        if (lcol[1])
 
873
                                                glColor3ubv((const GLubyte *)&(lcol[1]->r));
 
874
                                        glNormal3fv(vertexNos[BM_elem_index_get(ls[1]->v)]);
 
875
                                        glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
 
876
 
 
877
                                        glTexCoord2fv(luv[2]->uv);
 
878
                                        if (lcol[2])
 
879
                                                glColor3ubv((const GLubyte *)&(lcol[2]->r));
 
880
                                        glNormal3fv(vertexNos[BM_elem_index_get(ls[2]->v)]);
 
881
                                        glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
 
882
                                }
 
883
                                glEnd();
 
884
                        }
 
885
                }
 
886
        }
 
887
        else {
 
888
                BM_mesh_elem_index_ensure(bm, BM_VERT);
 
889
 
 
890
                for (i=0; i<em->tottri; i++) {
 
891
                        BMLoop **ls = em->looptris[i];
 
892
                        MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
 
893
                        MTFace mtf = {{{0}}};
 
894
                        /*unsigned char *cp= NULL;*/ /*UNUSED*/
 
895
                        int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
 
896
                        DMDrawOption draw_option;
 
897
 
 
898
                        efa = ls[0]->f;
 
899
 
 
900
                        if (has_uv) {
 
901
                                ME_MTEXFACE_CPY(&mtf, tp);
 
902
                        }
 
903
 
 
904
                        if (drawParams)
 
905
                                draw_option= drawParams(&mtf, has_vcol, efa->mat_nr);
 
906
                        else if (drawParamsMapped)
 
907
                                draw_option= drawParamsMapped(userData, BM_elem_index_get(efa));
 
908
                        else
 
909
                                draw_option= DM_DRAW_OPTION_NORMAL;
 
910
 
 
911
                        if (draw_option != DM_DRAW_OPTION_SKIP) {
 
912
 
 
913
                                glBegin(GL_TRIANGLES);
 
914
                                if (!drawSmooth) {
 
915
                                        glNormal3fv(efa->no);
 
916
 
 
917
                                        bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 
918
 
 
919
                                        if (luv[0])
 
920
                                                glTexCoord2fv(luv[0]->uv);
 
921
                                        if (lcol[0])
 
922
                                                glColor3ubv((const GLubyte *)&(lcol[0]->r));
 
923
                                        glVertex3fv(ls[0]->v->co);
 
924
 
 
925
                                        if (luv[1])
 
926
                                                glTexCoord2fv(luv[1]->uv);
 
927
                                        if (lcol[1])
 
928
                                                glColor3ubv((const GLubyte *)&(lcol[1]->r));
 
929
                                        glVertex3fv(ls[1]->v->co);
 
930
 
 
931
                                        if (luv[2])
 
932
                                                glTexCoord2fv(luv[2]->uv);
 
933
                                        if (lcol[2])
 
934
                                                glColor3ubv((const GLubyte *)&(lcol[2]->r));
 
935
                                        glVertex3fv(ls[2]->v->co);
 
936
                                }
 
937
                                else {
 
938
                                        bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 
939
 
 
940
                                        if (luv[0])
 
941
                                                glTexCoord2fv(luv[0]->uv);
 
942
                                        if (lcol[0])
 
943
                                                glColor3ubv((const GLubyte *)&(lcol[0]->r));
 
944
                                        glNormal3fv(ls[0]->v->no);
 
945
                                        glVertex3fv(ls[0]->v->co);
 
946
 
 
947
                                        if (luv[1])
 
948
                                                glTexCoord2fv(luv[1]->uv);
 
949
                                        if (lcol[1])
 
950
                                                glColor3ubv((const GLubyte *)&(lcol[1]->r));
 
951
                                        glNormal3fv(ls[1]->v->no);
 
952
                                        glVertex3fv(ls[1]->v->co);
 
953
 
 
954
                                        if (luv[2])
 
955
                                                glTexCoord2fv(luv[2]->uv);
 
956
                                        if (lcol[2])
 
957
                                                glColor3ubv((const GLubyte *)&(lcol[2]->r));
 
958
                                        glNormal3fv(ls[2]->v->no);
 
959
                                        glVertex3fv(ls[2]->v->co);
 
960
                                }
 
961
                                glEnd();
 
962
                        }
 
963
                }
 
964
        }
 
965
 
 
966
        glShadeModel(GL_FLAT);
 
967
}
 
968
 
 
969
static void emDM_drawFacesTex(
 
970
                DerivedMesh *dm,
 
971
                DMSetDrawOptionsTex setDrawOptions,
 
972
                DMCompareDrawOptions compareDrawOptions,
 
973
                void *userData)
 
974
{
 
975
        emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
 
976
}
 
977
 
 
978
static void emDM_drawMappedFacesTex(
 
979
                DerivedMesh *dm,
 
980
                DMSetDrawOptions setDrawOptions,
 
981
                DMCompareDrawOptions compareDrawOptions,
 
982
                void *userData)
 
983
{
 
984
        emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
 
985
}
 
986
 
 
987
static void emDM_drawMappedFacesGLSL(
 
988
                DerivedMesh *dm,
 
989
                DMSetMaterial setMaterial,
 
990
                DMSetDrawOptions setDrawOptions,
 
991
                void *userData)
 
992
{
 
993
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
994
        BMesh *bm= bmdm->tc->bm;
 
995
        BMEditMesh *em = bmdm->tc;
 
996
        float (*vertexCos)[3]= bmdm->vertexCos;
 
997
        float (*vertexNos)[3]= bmdm->vertexNos;
 
998
        BMFace *efa;
 
999
        BMLoop **ltri;
 
1000
        DMVertexAttribs attribs;
 
1001
        GPUVertexAttribs gattribs;
 
1002
 
 
1003
        int i, b, matnr, new_matnr, dodraw;
 
1004
 
 
1005
        dodraw = 0;
 
1006
        matnr = -1;
 
1007
 
 
1008
        memset(&attribs, 0, sizeof(attribs));
 
1009
 
 
1010
        /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
 
1011
        glShadeModel(GL_SMOOTH);
 
1012
        BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
 
1013
 
 
1014
#define PASSATTRIB(loop, eve, vert) {                                                                                   \
 
1015
        if (attribs.totorco) {                                                                                                          \
 
1016
                float *orco = attribs.orco.array[BM_elem_index_get(eve)];                                               \
 
1017
                glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
 
1018
        }                                                                                                                                                       \
 
1019
        for (b = 0; b < attribs.tottface; b++) {                                                                        \
 
1020
                MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
 
1021
                glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
 
1022
        }                                                                                                                                                       \
 
1023
        for (b = 0; b < attribs.totmcol; b++) {                                                                         \
 
1024
                MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
 
1025
                GLubyte _col[4];                                                                                                                \
 
1026
                _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
 
1027
                glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
 
1028
        }                                                                                                                                                       \
 
1029
        if (attribs.tottang) {                                                                                                          \
 
1030
                float *tang = attribs.tang.array[i*4 + vert];                                                   \
 
1031
                glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
 
1032
        }                                                                                                                                                       \
 
1033
        }
 
1034
 
 
1035
 
 
1036
        for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
 
1037
                int drawSmooth;
 
1038
 
 
1039
                efa = ltri[0]->f;
 
1040
                drawSmooth= BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
 
1041
 
 
1042
                if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
 
1043
                        continue;
 
1044
 
 
1045
                new_matnr = efa->mat_nr + 1;
 
1046
                if (new_matnr != matnr) {
 
1047
                        dodraw = setMaterial(matnr = new_matnr, &gattribs);
 
1048
                        if (dodraw)
 
1049
                                DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
 
1050
                }
 
1051
 
 
1052
                if (dodraw) {
 
1053
                        glBegin(GL_TRIANGLES);
 
1054
                        if (!drawSmooth) {
 
1055
                                if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
 
1056
                                else glNormal3fv(efa->no);
 
1057
 
 
1058
                                PASSATTRIB(ltri[0], ltri[0]->v, 0);
 
1059
                                if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
 
1060
                                else glVertex3fv(ltri[0]->v->co);
 
1061
 
 
1062
                                PASSATTRIB(ltri[1], ltri[1]->v, 1);
 
1063
                                if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
 
1064
                                else glVertex3fv(ltri[1]->v->co);
 
1065
 
 
1066
                                PASSATTRIB(ltri[2], ltri[2]->v, 2);
 
1067
                                if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
 
1068
                                else glVertex3fv(ltri[2]->v->co);
 
1069
                        }
 
1070
                        else {
 
1071
                                PASSATTRIB(ltri[0], ltri[0]->v, 0);
 
1072
                                if (vertexCos) {
 
1073
                                        glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
 
1074
                                        glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
 
1075
                                }
 
1076
                                else {
 
1077
                                        glNormal3fv(ltri[0]->v->no);
 
1078
                                        glVertex3fv(ltri[0]->v->co);
 
1079
                                }
 
1080
 
 
1081
                                PASSATTRIB(ltri[1], ltri[1]->v, 1);
 
1082
                                if (vertexCos) {
 
1083
                                        glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
 
1084
                                        glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
 
1085
                                }
 
1086
                                else {
 
1087
                                        glNormal3fv(ltri[1]->v->no);
 
1088
                                        glVertex3fv(ltri[1]->v->co);
 
1089
                                }
 
1090
 
 
1091
                                PASSATTRIB(ltri[2], ltri[2]->v, 2);
 
1092
                                if (vertexCos) {
 
1093
                                        glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
 
1094
                                        glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
 
1095
                                }
 
1096
                                else {
 
1097
                                        glNormal3fv(ltri[2]->v->no);
 
1098
                                        glVertex3fv(ltri[2]->v->co);
 
1099
                                }
 
1100
                        }
 
1101
                        glEnd();
 
1102
                }
 
1103
        }
 
1104
#undef PASSATTRIB
 
1105
}
 
1106
 
 
1107
static void emDM_drawFacesGLSL(
 
1108
                DerivedMesh *dm,
 
1109
                int (*setMaterial)(int, void *attribs))
 
1110
{
 
1111
        dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
 
1112
}
 
1113
 
 
1114
static void emDM_drawMappedFacesMat(
 
1115
                DerivedMesh *dm,
 
1116
                void (*setMaterial)(void *userData, int, void *attribs),
 
1117
                int (*setFace)(void *userData, int index), void *userData)
 
1118
{
 
1119
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1120
        BMesh *bm= bmdm->tc->bm;
 
1121
        BMEditMesh *em = bmdm->tc;
 
1122
        float (*vertexCos)[3]= bmdm->vertexCos;
 
1123
        float (*vertexNos)[3]= bmdm->vertexNos;
 
1124
        BMFace *efa;
 
1125
        BMLoop **ltri;
 
1126
        DMVertexAttribs attribs= {{{0}}};
 
1127
        GPUVertexAttribs gattribs;
 
1128
        int i, b, matnr, new_matnr;
 
1129
 
 
1130
        matnr = -1;
 
1131
 
 
1132
        /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
 
1133
        glShadeModel(GL_SMOOTH);
 
1134
 
 
1135
        BM_mesh_elem_index_ensure(bm, BM_VERT|BM_FACE);
 
1136
 
 
1137
#define PASSATTRIB(loop, eve, vert) {                                                                                   \
 
1138
        if (attribs.totorco) {                                                                                                          \
 
1139
                float *orco = attribs.orco.array[BM_elem_index_get(eve)];                               \
 
1140
                if (attribs.orco.glTexco)                                                                                               \
 
1141
                        glTexCoord3fv(orco);                                                                                            \
 
1142
                else                                                                                                                                    \
 
1143
                        glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                       \
 
1144
        }                                                                                                                                                       \
 
1145
        for (b = 0; b < attribs.tottface; b++) {                                                                        \
 
1146
                MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
 
1147
                if (attribs.tface[b].glTexco)                                                                                   \
 
1148
                        glTexCoord2fv(_luv->uv);                                                                                        \
 
1149
                else                                                                                                                                    \
 
1150
                        glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                       \
 
1151
        }                                                                                                                                                       \
 
1152
        for (b = 0; b < attribs.totmcol; b++) {                                                                         \
 
1153
                MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
 
1154
                GLubyte _col[4];                                                                                                                \
 
1155
                _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
 
1156
                glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
 
1157
        }                                                                                                                                                       \
 
1158
        if (attribs.tottang) {                                                                                                          \
 
1159
                float *tang = attribs.tang.array[i*4 + vert];                                                   \
 
1160
                glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
 
1161
        }                                                                                                                                                       \
 
1162
}
 
1163
 
 
1164
        for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
 
1165
                int drawSmooth;
 
1166
 
 
1167
                efa = ltri[0]->f;
 
1168
                drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
 
1169
 
 
1170
                /* face hiding */
 
1171
                if (setFace && !setFace(userData, BM_elem_index_get(efa)))
 
1172
                        continue;
 
1173
 
 
1174
                /* material */
 
1175
                new_matnr = efa->mat_nr + 1;
 
1176
                if (new_matnr != matnr) {
 
1177
                        setMaterial(userData, matnr = new_matnr, &gattribs);
 
1178
                        DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
 
1179
                }
 
1180
 
 
1181
                /* face */
 
1182
                glBegin(GL_TRIANGLES);
 
1183
                if (!drawSmooth) {
 
1184
                        if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
 
1185
                        else glNormal3fv(efa->no);
 
1186
 
 
1187
                        PASSATTRIB(ltri[0], ltri[0]->v, 0);
 
1188
                        if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
 
1189
                        else glVertex3fv(ltri[0]->v->co);
 
1190
 
 
1191
                        PASSATTRIB(ltri[1], ltri[1]->v, 1);
 
1192
                        if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
 
1193
                        else glVertex3fv(ltri[1]->v->co);
 
1194
 
 
1195
                        PASSATTRIB(ltri[2], ltri[2]->v, 2);
 
1196
                        if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
 
1197
                        else glVertex3fv(ltri[2]->v->co);
 
1198
 
 
1199
                }
 
1200
                else {
 
1201
                        PASSATTRIB(ltri[0], ltri[0]->v, 0);
 
1202
                        if (vertexCos) {
 
1203
                                glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
 
1204
                                glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
 
1205
                        }
 
1206
                        else {
 
1207
                                glNormal3fv(ltri[0]->v->no);
 
1208
                                glVertex3fv(ltri[0]->v->co);
 
1209
                        }
 
1210
 
 
1211
                        PASSATTRIB(ltri[1], ltri[1]->v, 1);
 
1212
                        if (vertexCos) {
 
1213
                                glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
 
1214
                                glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
 
1215
                        }
 
1216
                        else {
 
1217
                                glNormal3fv(ltri[1]->v->no);
 
1218
                                glVertex3fv(ltri[1]->v->co);
 
1219
                        }
 
1220
 
 
1221
                        PASSATTRIB(ltri[2], ltri[2]->v, 2);
 
1222
                        if (vertexCos) {
 
1223
                                glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
 
1224
                                glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
 
1225
                        }
 
1226
                        else {
 
1227
                                glNormal3fv(ltri[2]->v->no);
 
1228
                                glVertex3fv(ltri[2]->v->co);
 
1229
                        }
 
1230
                }
 
1231
                glEnd();
 
1232
        }
 
1233
#undef PASSATTRIB
 
1234
}
 
1235
 
 
1236
static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 
1237
{
 
1238
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1239
        BMVert *eve;
 
1240
        BMIter iter;
 
1241
        int i;
 
1242
 
 
1243
        if (bmdm->tc->bm->totvert) {
 
1244
                eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 
1245
                for (i=0; eve; eve=BM_iter_step(&iter), i++) {
 
1246
                        if (bmdm->vertexCos) {
 
1247
                                DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
 
1248
                        }
 
1249
                        else {
 
1250
                                DO_MINMAX(eve->co, min_r, max_r);
 
1251
                        }
 
1252
                }
 
1253
        }
 
1254
        else {
 
1255
                zero_v3(min_r);
 
1256
                zero_v3(max_r);
 
1257
        }
 
1258
}
 
1259
static int emDM_getNumVerts(DerivedMesh *dm)
 
1260
{
 
1261
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1262
 
 
1263
        return bmdm->tc->bm->totvert;
 
1264
}
 
1265
 
 
1266
static int emDM_getNumEdges(DerivedMesh *dm)
 
1267
{
 
1268
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1269
 
 
1270
        return bmdm->tc->bm->totedge;
 
1271
}
 
1272
 
 
1273
static int emDM_getNumTessFaces(DerivedMesh *dm)
 
1274
{
 
1275
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1276
 
 
1277
        return bmdm->tc->tottri;
 
1278
}
 
1279
 
 
1280
static int emDM_getNumLoops(DerivedMesh *dm)
 
1281
{
 
1282
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1283
 
 
1284
        return bmdm->tc->bm->totloop;
 
1285
}
 
1286
 
 
1287
static int emDM_getNumPolys(DerivedMesh *dm)
 
1288
{
 
1289
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1290
 
 
1291
        return bmdm->tc->bm->totface;
 
1292
}
 
1293
 
 
1294
static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
 
1295
{
 
1296
        copy_v3_v3(vert_r->co, ev->co);
 
1297
 
 
1298
        normal_float_to_short_v3(vert_r->no, ev->no);
 
1299
 
 
1300
        vert_r->flag = BM_vert_flag_to_mflag(ev);
 
1301
 
 
1302
        if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
 
1303
                vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
 
1304
        }
 
1305
 
 
1306
        return 1;
 
1307
}
 
1308
 
 
1309
static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
 
1310
{
 
1311
        EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 
1312
        BMVert *ev;
 
1313
 
 
1314
        if (index < 0 || index >= bmdm->tv) {
 
1315
                printf("error in emDM_getVert.\n");
 
1316
                return;
 
1317
        }
 
1318
 
 
1319
        // ev = EDBM_vert_at_index(bmdm->tc, index);
 
1320
        ev = BM_vert_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
 
1321
 
 
1322
        bmvert_to_mvert(bmdm->tc->bm, ev, vert_r);
 
1323
        if (bmdm->vertexCos)
 
1324
                copy_v3_v3(vert_r->co, bmdm->vertexCos[index]);
 
1325
}
 
1326
 
 
1327
static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
 
1328
{
 
1329
        EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 
1330
        BMesh *bm = bmdm->tc->bm;
 
1331
        BMEdge *e;
 
1332
 
 
1333
        if (index < 0 || index >= bmdm->te) {
 
1334
                printf("error in emDM_getEdge.\n");
 
1335
                return;
 
1336
        }
 
1337
 
 
1338
        // e = EDBM_edge_at_index(bmdm->tc, index);
 
1339
        e = BM_edge_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
 
1340
 
 
1341
        if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
 
1342
                edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT)*255.0f);
 
1343
        }
 
1344
 
 
1345
        if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
 
1346
                edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_CREASE)*255.0f);
 
1347
        }
 
1348
 
 
1349
        edge_r->flag = BM_edge_flag_to_mflag(e);
 
1350
 
 
1351
        edge_r->v1 = BM_elem_index_get(e->v1);
 
1352
        edge_r->v2 = BM_elem_index_get(e->v2);
 
1353
}
 
1354
 
 
1355
static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
 
1356
{
 
1357
        EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 
1358
        BMFace *ef;
 
1359
        BMLoop **l;
 
1360
 
 
1361
        if (index < 0 || index >= bmdm->tf) {
 
1362
                printf("error in emDM_getTessFace.\n");
 
1363
                return;
 
1364
        }
 
1365
 
 
1366
        l = bmdm->tc->looptris[index];
 
1367
 
 
1368
        ef = l[0]->f;
 
1369
 
 
1370
        face_r->mat_nr = (unsigned char) ef->mat_nr;
 
1371
        face_r->flag = BM_face_flag_to_mflag(ef);
 
1372
 
 
1373
        face_r->v1 = BM_elem_index_get(l[0]->v);
 
1374
        face_r->v2 = BM_elem_index_get(l[1]->v);
 
1375
        face_r->v3 = BM_elem_index_get(l[2]->v);
 
1376
        face_r->v4 = 0;
 
1377
 
 
1378
        test_index_face(face_r, NULL, 0, 3);
 
1379
}
 
1380
 
 
1381
static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
 
1382
{
 
1383
        EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 
1384
        BMesh *bm = bmdm->tc->bm;
 
1385
        BMVert *ev;
 
1386
        BMIter iter;
 
1387
        int i;
 
1388
 
 
1389
        ev = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
 
1390
        for (i = 0 ; ev; ev = BM_iter_step(&iter), ++vert_r, ++i) {
 
1391
                if (bmdm->vertexCos)
 
1392
                        copy_v3_v3(vert_r->co, bmdm->vertexCos[i]);
 
1393
                else
 
1394
                        copy_v3_v3(vert_r->co, ev->co);
 
1395
 
 
1396
                normal_float_to_short_v3(vert_r->no, ev->no);
 
1397
 
 
1398
                vert_r->flag = BM_vert_flag_to_mflag(ev);
 
1399
 
 
1400
                if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
 
1401
                        vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
 
1402
                }
 
1403
        }
 
1404
}
 
1405
 
 
1406
static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
 
1407
{
 
1408
        BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
 
1409
        BMEdge *ee;
 
1410
        BMIter iter;
 
1411
        int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
 
1412
        int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
 
1413
 
 
1414
        BM_mesh_elem_index_ensure(bm, BM_VERT);
 
1415
 
 
1416
        ee = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL);
 
1417
        for ( ; ee; ee=BM_iter_step(&iter), edge_r++) {
 
1418
                if (has_bweight) {
 
1419
                        edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, ee, CD_BWEIGHT)*255.0f);
 
1420
                }
 
1421
 
 
1422
                if (has_crease) {
 
1423
                        edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, ee, CD_CREASE)*255.0f);
 
1424
                }
 
1425
 
 
1426
                edge_r->flag = BM_edge_flag_to_mflag(ee);
 
1427
 
 
1428
                edge_r->v1 = BM_elem_index_get(ee->v1);
 
1429
                edge_r->v2 = BM_elem_index_get(ee->v2);
 
1430
        }
 
1431
}
 
1432
 
 
1433
static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
 
1434
{
 
1435
        EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 
1436
        BMesh *bm = bmdm->tc->bm;
 
1437
        BMFace *ef;
 
1438
        BMLoop **l;
 
1439
        int i;
 
1440
 
 
1441
        BM_mesh_elem_index_ensure(bm, BM_VERT);
 
1442
 
 
1443
        for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
 
1444
                l = bmdm->tc->looptris[i];
 
1445
                ef = l[0]->f;
 
1446
 
 
1447
                face_r->mat_nr = (unsigned char) ef->mat_nr;
 
1448
 
 
1449
                face_r->flag = BM_face_flag_to_mflag(ef);
 
1450
 
 
1451
                face_r->v1 = BM_elem_index_get(l[0]->v);
 
1452
                face_r->v2 = BM_elem_index_get(l[1]->v);
 
1453
                face_r->v3 = BM_elem_index_get(l[2]->v);
 
1454
                face_r->v4 = 0;
 
1455
 
 
1456
                test_index_face(face_r, NULL, 0, 3);
 
1457
        }
 
1458
}
 
1459
 
 
1460
 
 
1461
static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
 
1462
{
 
1463
        EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 
1464
        BMesh *bm = bmdm->tc->bm;
 
1465
        BMIter iter, liter;
 
1466
        BMFace *f;
 
1467
        BMLoop *l;
 
1468
 
 
1469
        BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
 
1470
 
 
1471
        BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
 
1472
                BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
 
1473
                        loop_r->v = BM_elem_index_get(l->v);
 
1474
                        loop_r->e = BM_elem_index_get(l->e);
 
1475
                        loop_r++;
 
1476
                }
 
1477
        }
 
1478
}
 
1479
 
 
1480
static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
 
1481
{
 
1482
        EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 
1483
        BMesh *bm = bmdm->tc->bm;
 
1484
        BMIter iter;
 
1485
        BMFace *f;
 
1486
        int i;
 
1487
 
 
1488
        i = 0;
 
1489
        BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
 
1490
                poly_r->flag = BM_face_flag_to_mflag(f);
 
1491
                poly_r->loopstart = i;
 
1492
                poly_r->totloop = f->len;
 
1493
                poly_r->mat_nr = f->mat_nr;
 
1494
 
 
1495
                poly_r++;
 
1496
                i += f->len;
 
1497
        }
 
1498
}
 
1499
 
 
1500
static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
 
1501
{
 
1502
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
1503
        BMesh *bm= bmdm->tc->bm;
 
1504
        void *datalayer;
 
1505
 
 
1506
        datalayer = DM_get_tessface_data_layer(dm, type);
 
1507
        if (datalayer)
 
1508
                return datalayer;
 
1509
 
 
1510
        /* layers are store per face for editmesh, we convert to a temporary
 
1511
         * data layer array in the derivedmesh when these are requested */
 
1512
        if (type == CD_MTFACE || type == CD_MCOL) {
 
1513
                const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
 
1514
                int index;
 
1515
                char *data, *bmdata;
 
1516
                index = CustomData_get_layer_index(&bm->pdata, type_from);
 
1517
 
 
1518
                if (index != -1) {
 
1519
                        /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
 
1520
                        const int size = CustomData_sizeof(type);
 
1521
                        int i, j;
 
1522
 
 
1523
                        DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
 
1524
                        index = CustomData_get_layer_index(&dm->faceData, type);
 
1525
                        dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
 
1526
 
 
1527
                        data = datalayer = DM_get_tessface_data_layer(dm, type);
 
1528
 
 
1529
                        if (type == CD_MTFACE) {
 
1530
                                for (i = 0; i < bmdm->tc->tottri; i++, data += size) {
 
1531
                                        BMFace *efa = bmdm->tc->looptris[i][0]->f;
 
1532
                                        bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
 
1533
                                        ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
 
1534
                                        for (j = 0; j < 3; j++) {
 
1535
                                                bmdata = CustomData_bmesh_get(&bm->ldata, bmdm->tc->looptris[i][j]->head.data, CD_MLOOPUV);
 
1536
                                                copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
 
1537
                                        }
 
1538
                                }
 
1539
                        }
 
1540
                        else {
 
1541
                                for (i = 0; i < bmdm->tc->tottri; i++, data += size) {
 
1542
                                        for (j = 0; j < 3; j++) {
 
1543
                                                bmdata = CustomData_bmesh_get(&bm->ldata, bmdm->tc->looptris[i][j]->head.data, CD_MLOOPCOL);
 
1544
                                                MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
 
1545
                                        }
 
1546
                                }
 
1547
                        }
 
1548
                }
 
1549
        }
 
1550
 
 
1551
        return datalayer;
 
1552
}
 
1553
 
 
1554
static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
 
1555
{
 
1556
        EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
 
1557
        BMVert *eve;
 
1558
        BMIter iter;
 
1559
        int i;
 
1560
 
 
1561
        i= 0;
 
1562
        BM_ITER_MESH (eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH) {
 
1563
                if (emdm->vertexCos) {
 
1564
                        copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
 
1565
                }
 
1566
                else {
 
1567
                        copy_v3_v3(cos_r[i], eve->co);
 
1568
                }
 
1569
 
 
1570
                i++;
 
1571
        }
 
1572
}
 
1573
 
 
1574
static void emDM_release(DerivedMesh *dm)
 
1575
{
 
1576
        EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
 
1577
 
 
1578
        if (DM_release(dm)) {
 
1579
                if (bmdm->vertexCos) {
 
1580
                        MEM_freeN(bmdm->vertexCos);
 
1581
                        MEM_freeN(bmdm->vertexNos);
 
1582
                        MEM_freeN(bmdm->polyNos);
 
1583
                }
 
1584
 
 
1585
                MEM_freeN(bmdm);
 
1586
        }
 
1587
}
 
1588
 
 
1589
static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
 
1590
{
 
1591
        EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
1592
 
 
1593
        return &bmdm->tc->bm->vdata;
 
1594
}
 
1595
 
 
1596
static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
 
1597
{
 
1598
        EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
1599
 
 
1600
        return &bmdm->tc->bm->edata;
 
1601
}
 
1602
 
 
1603
static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
 
1604
{
 
1605
        EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
1606
 
 
1607
        return &bmdm->dm.faceData;
 
1608
}
 
1609
 
 
1610
static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
 
1611
{
 
1612
        EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
1613
 
 
1614
        return &bmdm->tc->bm->ldata;
 
1615
}
 
1616
 
 
1617
static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
 
1618
{
 
1619
        EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
1620
 
 
1621
        return &bmdm->tc->bm->pdata;
 
1622
}
 
1623
 
 
1624
 
 
1625
DerivedMesh *getEditDerivedBMesh(
 
1626
                BMEditMesh *em,
 
1627
                Object *UNUSED(ob),
 
1628
                float (*vertexCos)[3])
 
1629
{
 
1630
        EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
 
1631
        BMesh *bm = em->bm;
 
1632
 
 
1633
        bmdm->tc = em;
 
1634
 
 
1635
        DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
 
1636
                 em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
 
1637
 
 
1638
        bmdm->dm.getVertCos = emDM_getVertCos;
 
1639
        bmdm->dm.getMinMax = emDM_getMinMax;
 
1640
 
 
1641
        bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
 
1642
        bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
 
1643
        bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
 
1644
        bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
 
1645
        bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
 
1646
 
 
1647
        bmdm->dm.getNumVerts = emDM_getNumVerts;
 
1648
        bmdm->dm.getNumEdges = emDM_getNumEdges;
 
1649
        bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
 
1650
        bmdm->dm.getNumLoops = emDM_getNumLoops;
 
1651
        bmdm->dm.getNumPolys = emDM_getNumPolys;
 
1652
 
 
1653
        bmdm->dm.getVert = emDM_getVert;
 
1654
        bmdm->dm.getEdge = emDM_getEdge;
 
1655
        bmdm->dm.getTessFace = emDM_getTessFace;
 
1656
        bmdm->dm.copyVertArray = emDM_copyVertArray;
 
1657
        bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
 
1658
        bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
 
1659
        bmdm->dm.copyLoopArray = emDM_copyLoopArray;
 
1660
        bmdm->dm.copyPolyArray = emDM_copyPolyArray;
 
1661
 
 
1662
        bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
 
1663
 
 
1664
        bmdm->dm.calcNormals = emDM_calcNormals;
 
1665
        bmdm->dm.recalcTessellation = emDM_recalcTessellation;
 
1666
 
 
1667
        bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
 
1668
        bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
 
1669
        bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
 
1670
 
 
1671
        bmdm->dm.drawEdges = emDM_drawEdges;
 
1672
        bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
 
1673
        bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
 
1674
        bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
 
1675
        bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
 
1676
        bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
 
1677
        bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
 
1678
        bmdm->dm.drawFacesTex = emDM_drawFacesTex;
 
1679
        bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
 
1680
        bmdm->dm.drawUVEdges = emDM_drawUVEdges;
 
1681
 
 
1682
        bmdm->dm.release = emDM_release;
 
1683
 
 
1684
        bmdm->vertexCos = vertexCos;
 
1685
 
 
1686
        if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
 
1687
                BMIter iter;
 
1688
                BMVert *eve;
 
1689
                int i;
 
1690
 
 
1691
                DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
 
1692
 
 
1693
                eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 
1694
                for (i=0; eve; eve=BM_iter_step(&iter), i++)
 
1695
                        DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
 
1696
                                                         CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
 
1697
        }
 
1698
 
 
1699
        if (vertexCos) {
 
1700
                BMFace *efa;
 
1701
                BMVert *eve;
 
1702
                BMIter fiter;
 
1703
                BMIter viter;
 
1704
                int i;
 
1705
 
 
1706
                BM_mesh_elem_index_ensure(bm, BM_VERT);
 
1707
 
 
1708
                bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
 
1709
                bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos)*bm->totface, "bmdm_pno");
 
1710
 
 
1711
                i = 0;
 
1712
                BM_ITER_MESH (efa, &fiter, bm, BM_FACES_OF_MESH) {
 
1713
                        BM_elem_index_set(efa, i); /* set_inline */
 
1714
                        BM_face_normal_update_vcos(bm, efa, bmdm->polyNos[i], (float const (*)[3])vertexCos);
 
1715
                        i++;
 
1716
                }
 
1717
                bm->elem_index_dirty &= ~BM_FACE;
 
1718
 
 
1719
                eve=BM_iter_new(&viter, bm, BM_VERTS_OF_MESH, NULL);
 
1720
                for (i=0; eve; eve=BM_iter_step(&viter), i++) {
 
1721
                        float *no = bmdm->vertexNos[i];
 
1722
                        BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) {
 
1723
                                add_v3_v3(no, bmdm->polyNos[BM_elem_index_get(efa)]);
 
1724
                        }
 
1725
 
 
1726
                        /* following Mesh convention; we use vertex coordinate itself
 
1727
                         * for normal in this case */
 
1728
                        if (normalize_v3(no)==0.0) {
 
1729
                                copy_v3_v3(no, vertexCos[i]);
 
1730
                                normalize_v3(no);
 
1731
                        }
 
1732
                }
 
1733
        }
 
1734
 
 
1735
        return (DerivedMesh*) bmdm;
 
1736
}
 
1737
 
 
1738
/**
 
1739
 * \brief Return the BMEditMesh for a given object
 
1740
 *
 
1741
 * \note this function assumes this is a mesh object,
 
1742
 * don't add NULL data check here. caller must do that
 
1743
 */
 
1744
BMEditMesh *BMEdit_FromObject(Object *ob)
 
1745
{
 
1746
        BLI_assert(ob->type == OB_MESH);
 
1747
        return ((Mesh *)ob->data)->edit_btmesh;
 
1748
}