Code cleanup: use bool for static methods
[blender.git] / source / blender / blenkernel / intern / editderivedmesh.c
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  * basic design:
32  *
33  * the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
34  * to three loops per triangle.  the derivedmesh stores a cache of tessellations
35  * for each face.  this cache will smartly update as needed (though at first
36  * it'll simply be more brute force).  keeping track of face/edge counts may
37  * be a small problem.
38  *
39  * this won't be the most efficient thing, considering that internal edges and
40  * faces of tessellations are exposed.  looking up an edge by index in particular
41  * is likely to be a little slow.
42  */
43
44 #include "GL/glew.h"
45
46 #include "BLI_math.h"
47 #include "BLI_jitter.h"
48 #include "BLI_bitmap.h"
49
50 #include "BKE_cdderivedmesh.h"
51 #include "BKE_mesh.h"
52 #include "BKE_editmesh.h"
53 #include "BKE_editmesh_bvh.h"
54
55 #include "DNA_mesh_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_object_types.h"
58
59 #include "MEM_guardedalloc.h"
60
61 #include "GPU_extensions.h"
62
63 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
64
65 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]);
66
67 typedef struct EditDerivedBMesh {
68         DerivedMesh dm;
69
70         BMEditMesh *em;
71
72         /** when set, \a vertexNos, polyNos are lazy initialized */
73         const float (*vertexCos)[3];
74
75         /** lazy initialize (when \a vertexCos is set) */
76         float const (*vertexNos)[3];
77         float const (*polyNos)[3];
78         /** also lazy init but dont depend on \a vertexCos */
79         const float (*polyCos)[3];
80 } EditDerivedBMesh;
81
82 /* -------------------------------------------------------------------- */
83 /* Lazy initialize datastructures */
84
85 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm);
86
87 static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm)
88 {
89         if (bmdm->vertexCos && (bmdm->vertexNos == NULL)) {
90
91                 BMesh *bm = bmdm->em->bm;
92                 const float (*vertexCos)[3], (*polyNos)[3];
93                 float (*vertexNos)[3];
94
95                 BMFace *efa;
96                 BMVert *eve;
97                 BMIter fiter;
98                 BMIter viter;
99                 int i;
100
101                 vertexCos = bmdm->vertexCos;
102                 vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__);
103
104                 /* calculate vertex normals from poly normals */
105                 emDM_ensurePolyNormals(bmdm);
106
107                 BM_mesh_elem_index_ensure(bm, BM_FACE);
108
109                 vertexCos = bmdm->vertexCos;
110                 polyNos = bmdm->polyNos;
111
112                 BM_ITER_MESH_INDEX (eve, &viter, bm, BM_VERTS_OF_MESH, i) {
113                         float *no = vertexNos[i];
114                         BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) {
115                                 add_v3_v3(no, polyNos[BM_elem_index_get(efa)]);
116                         }
117
118                         /* following Mesh convention; we use vertex coordinate itself
119                          * for normal in this case */
120                         if (UNLIKELY(normalize_v3(no) == 0.0f)) {
121                                 normalize_v3_v3(no, vertexCos[i]);
122                         }
123                 }
124
125                 bmdm->vertexNos = (const float (*)[3])vertexNos;
126         }
127 }
128
129 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm)
130 {
131         if (bmdm->vertexCos && (bmdm->polyNos == NULL)) {
132                 BMesh *bm = bmdm->em->bm;
133                 const float (*vertexCos)[3];
134                 float (*polyNos)[3];
135
136                 BMFace *efa;
137                 BMIter fiter;
138                 int i;
139
140                 BM_mesh_elem_index_ensure(bm, BM_VERT);
141
142                 polyNos = MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__);
143
144                 vertexCos = bmdm->vertexCos;
145
146                 BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
147                         BM_elem_index_set(efa, i); /* set_inline */
148                         BM_face_calc_normal_vcos(bm, efa, polyNos[i], vertexCos);
149                 }
150                 bm->elem_index_dirty &= ~BM_FACE;
151
152                 bmdm->polyNos = (const float (*)[3])polyNos;
153         }
154 }
155
156 static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm)
157 {
158         if (bmdm->polyCos == NULL) {
159                 BMesh *bm = bmdm->em->bm;
160                 float (*polyCos)[3];
161
162                 BMFace *efa;
163                 BMIter fiter;
164                 int i;
165
166                 polyCos = MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__);
167
168                 if (bmdm->vertexCos) {
169                         const float (*vertexCos)[3];
170                         vertexCos = bmdm->vertexCos;
171
172                         BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
173                                 BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos);
174                         }
175                 }
176                 else {
177                         BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
178                                 BM_face_calc_center_mean(efa, polyCos[i]);
179                         }
180                 }
181
182                 bmdm->polyCos = (const float (*)[3])polyCos;
183         }
184 }
185
186 static void emDM_calcNormals(DerivedMesh *dm)
187 {
188         /* Nothing to do: normals are already calculated and stored on the
189          * BMVerts and BMFaces */
190         dm->dirty &= ~DM_DIRTY_NORMALS;
191 }
192
193 static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
194 {
195         /* do nothing */
196 }
197
198 static void emDM_foreachMappedVert(
199         DerivedMesh *dm,
200         void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
201         void *userData,
202         DMForeachFlag flag)
203 {
204         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
205         BMesh *bm = bmdm->em->bm;
206         BMVert *eve;
207         BMIter iter;
208         int i;
209
210         if (bmdm->vertexCos) {
211                 const float (*vertexCos)[3] = bmdm->vertexCos;
212                 const float (*vertexNos)[3];
213
214                 if (flag & DM_FOREACH_USE_NORMAL) {
215                         emDM_ensureVertNormals(bmdm);
216                         vertexNos = bmdm->vertexNos;
217                 }
218                 else {
219                         vertexNos = NULL;
220                 }
221
222                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
223                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
224                         func(userData, i, vertexCos[i], no, NULL);
225                 }
226         }
227         else {
228                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
229                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? eve->no : NULL;
230                         func(userData, i, eve->co, no, NULL);
231                 }
232         }
233 }
234 static void emDM_foreachMappedEdge(DerivedMesh *dm,
235                                    void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
236                                    void *userData)
237 {
238         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
239         BMesh *bm = bmdm->em->bm;
240         BMEdge *eed;
241         BMIter iter;
242         int i;
243
244         if (bmdm->vertexCos) {
245
246                 BM_mesh_elem_index_ensure(bm, BM_VERT);
247
248                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
249                         func(userData, i,
250                              bmdm->vertexCos[BM_elem_index_get(eed->v1)],
251                              bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
252                 }
253         }
254         else {
255                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
256                         func(userData, i, eed->v1->co, eed->v2->co);
257                 }
258         }
259 }
260
261 static void emDM_drawMappedEdges(DerivedMesh *dm,
262                                  DMSetDrawOptions setDrawOptions,
263                                  void *userData)
264 {
265         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
266         BMesh *bm = bmdm->em->bm;
267         BMEdge *eed;
268         BMIter iter;
269         int i;
270
271         if (bmdm->vertexCos) {
272
273                 BM_mesh_elem_index_ensure(bm, BM_VERT);
274
275                 glBegin(GL_LINES);
276                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
277                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
278                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
279                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
280                         }
281                 }
282                 glEnd();
283         }
284         else {
285                 glBegin(GL_LINES);
286                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
287                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
288                                 glVertex3fv(eed->v1->co);
289                                 glVertex3fv(eed->v2->co);
290                         }
291                 }
292                 glEnd();
293         }
294 }
295 static void emDM_drawEdges(DerivedMesh *dm,
296                            int UNUSED(drawLooseEdges),
297                            int UNUSED(drawAllEdges))
298 {
299         emDM_drawMappedEdges(dm, NULL, NULL);
300 }
301
302 static void emDM_drawMappedEdgesInterp(DerivedMesh *dm,
303                                        DMSetDrawOptions setDrawOptions,
304                                        DMSetDrawInterpOptions setDrawInterpOptions,
305                                        void *userData)
306 {
307         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
308         BMesh *bm = bmdm->em->bm;
309         BMEdge *eed;
310         BMIter iter;
311         int i;
312
313         if (bmdm->vertexCos) {
314
315                 BM_mesh_elem_index_ensure(bm, BM_VERT);
316
317                 glBegin(GL_LINES);
318                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
319                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
320                                 setDrawInterpOptions(userData, i, 0.0);
321                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
322                                 setDrawInterpOptions(userData, i, 1.0);
323                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
324                         }
325                 }
326                 glEnd();
327         }
328         else {
329                 glBegin(GL_LINES);
330                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
331                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
332                                 setDrawInterpOptions(userData, i, 0.0);
333                                 glVertex3fv(eed->v1->co);
334                                 setDrawInterpOptions(userData, i, 1.0);
335                                 glVertex3fv(eed->v2->co);
336                         }
337                 }
338                 glEnd();
339         }
340 }
341
342 static void emDM_drawUVEdges(DerivedMesh *dm)
343 {
344         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
345         BMesh *bm = bmdm->em->bm;
346         BMFace *efa;
347         BMIter iter;
348
349         const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
350
351         if (UNLIKELY(cd_loop_uv_offset == -1)) {
352                 return;
353         }
354
355         glBegin(GL_LINES);
356         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
357                 BMLoop *l_iter, *l_first;
358                 const float *uv, *uv_prev;
359
360                 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
361                         continue;
362
363                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
364                 uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv;
365                 do {
366                         uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
367                         glVertex2fv(uv);
368                         glVertex2fv(uv_prev);
369                         uv_prev = uv;
370                 } while ((l_iter = l_iter->next) != l_first);
371         }
372         glEnd();
373 }
374
375 static void emDM_foreachMappedFaceCenter(
376         DerivedMesh *dm,
377         void (*func)(void *userData, int index, const float co[3], const float no[3]),
378         void *userData,
379         DMForeachFlag flag)
380 {
381         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
382         BMesh *bm = bmdm->em->bm;
383         const float (*polyNos)[3];
384         const float (*polyCos)[3];
385         BMFace *efa;
386         BMIter iter;
387         int i;
388
389         emDM_ensurePolyCenters(bmdm);
390         polyCos = bmdm->polyCos;  /* always set */
391
392         if (flag & DM_FOREACH_USE_NORMAL) {
393                 emDM_ensurePolyNormals(bmdm);
394                 polyNos = bmdm->polyNos;  /* maybe NULL */
395         }
396         else {
397                 polyNos = NULL;
398         }
399
400         if (polyNos) {
401                 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
402                         const float *no = polyNos[i];
403                         func(userData, i, polyCos[i], no);
404                 }
405         }
406         else {
407                 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
408                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? efa->no : NULL;
409                         func(userData, i, polyCos[i], no);
410                 }
411         }
412 }
413
414 static void emDM_drawMappedFaces(DerivedMesh *dm,
415                                  DMSetDrawOptions setDrawOptions,
416                                  DMSetMaterial setMaterial,
417                                  DMCompareDrawOptions compareDrawOptions,
418                                  void *userData,
419                                  DMDrawFlag flag)
420 {
421         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
422         BMEditMesh *em = bmdm->em;
423         BMesh *bm = em->bm;
424         BMFace *efa;
425         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
426         const int tottri = bmdm->em->tottri;
427         const int lasttri = tottri - 1; /* compare agasint this a lot */
428         DMDrawOption draw_option;
429         int i, flush;
430         const int skip_normals = !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
431
432         MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
433         unsigned char(*color_vert_array)[4] = em->derivedVertColor;
434         unsigned char(*color_face_array)[4] = em->derivedFaceColor;
435         bool has_vcol_preview = (color_vert_array != NULL) && !skip_normals;
436         bool has_fcol_preview = (color_face_array != NULL) && !skip_normals;
437         bool has_vcol_any = has_vcol_preview;
438
439         /* GL_ZERO is used to detect if drawing has started or not */
440         GLenum poly_prev = GL_ZERO;
441         GLenum shade_prev = GL_ZERO;
442
443         (void)setMaterial; /* UNUSED */
444
445         /* currently unused -- each original face is handled separately */
446         (void)compareDrawOptions;
447
448         /* call again below is ok */
449         if (has_vcol_preview) {
450                 BM_mesh_elem_index_ensure(bm, BM_VERT);
451         }
452         if (has_fcol_preview) {
453                 BM_mesh_elem_index_ensure(bm, BM_FACE);
454         }
455         if (has_vcol_preview || has_fcol_preview) {
456                 flag |= DM_DRAW_ALWAYS_SMOOTH;
457                 glDisable(GL_LIGHTING);  /* grr */
458         }
459
460         if (bmdm->vertexCos) {
461                 /* add direct access */
462                 const float (*vertexCos)[3] = bmdm->vertexCos;
463                 const float (*vertexNos)[3];
464                 const float (*polyNos)[3];
465
466                 if (skip_normals) {
467                         vertexNos = NULL;
468                         polyNos = NULL;
469                 }
470                 else {
471                         emDM_ensureVertNormals(bmdm);
472                         emDM_ensurePolyNormals(bmdm);
473                         vertexNos = bmdm->vertexNos;
474                         polyNos = bmdm->polyNos;
475                 }
476
477                 BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
478
479                 for (i = 0; i < tottri; i++) {
480                         BMLoop **ltri = looptris[i];
481                         int drawSmooth;
482
483                         efa = ltri[0]->f;
484                         drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
485
486                         draw_option = (!setDrawOptions ?
487                                        DM_DRAW_OPTION_NORMAL :
488                                        setDrawOptions(userData, BM_elem_index_get(efa)));
489                         if (draw_option != DM_DRAW_OPTION_SKIP) {
490                                 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
491                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
492
493                                         if (poly_prev != GL_ZERO) glEnd();
494                                         poly_prev = GL_ZERO; /* force glBegin */
495
496                                         glEnable(GL_POLYGON_STIPPLE);
497                                         glPolygonStipple(stipple_quarttone);
498                                 }
499
500                                 if      (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
501                                 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
502                                 if (skip_normals) {
503                                         if (poly_type != poly_prev) {
504                                                 if (poly_prev != GL_ZERO) glEnd();
505                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
506                                         }
507                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
508                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
509                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
510                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
511                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
512                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
513                                 }
514                                 else {
515                                         const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
516                                         if (shade_type != shade_prev) {
517                                                 if (poly_prev != GL_ZERO) glEnd();
518                                                 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
519                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
520                                         }
521                                         if (poly_type != poly_prev) {
522                                                 if (poly_prev != GL_ZERO) glEnd();
523                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
524                                         }
525
526                                         if (!drawSmooth) {
527                                                 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
528                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
529                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
530                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
531                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
532                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
533                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
534                                         }
535                                         else {
536                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
537                                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
538                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
539                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
540                                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
541                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
542                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
543                                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
544                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
545                                         }
546                                 }
547
548                                 flush = (draw_option == DM_DRAW_OPTION_STIPPLE);
549                                 if (!skip_normals && !flush && (i != lasttri))
550                                         flush |= efa->mat_nr != looptris[i + 1][0]->f->mat_nr;  /* TODO, make this neater */
551
552                                 if (flush) {
553                                         glEnd();
554                                         poly_prev = GL_ZERO; /* force glBegin */
555
556                                         glDisable(GL_POLYGON_STIPPLE);
557                                 }
558                         }
559                 }
560         }
561         else {
562                 BM_mesh_elem_index_ensure(bm, BM_FACE);
563
564                 for (i = 0; i < tottri; i++) {
565                         BMLoop **ltri = looptris[i];
566                         int drawSmooth;
567
568                         efa = ltri[0]->f;
569                         drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
570
571                         draw_option = (!setDrawOptions ?
572                                        DM_DRAW_OPTION_NORMAL :
573                                        setDrawOptions(userData, BM_elem_index_get(efa)));
574                         if (draw_option != DM_DRAW_OPTION_SKIP) {
575                                 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
576                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
577
578                                         if (poly_prev != GL_ZERO) glEnd();
579                                         poly_prev = GL_ZERO; /* force glBegin */
580
581                                         glEnable(GL_POLYGON_STIPPLE);
582                                         glPolygonStipple(stipple_quarttone);
583                                 }
584
585                                 if      (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
586                                 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
587
588                                 if (skip_normals) {
589                                         if (poly_type != poly_prev) {
590                                                 if (poly_prev != GL_ZERO) glEnd();
591                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
592                                         }
593                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
594                                         glVertex3fv(ltri[0]->v->co);
595                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
596                                         glVertex3fv(ltri[1]->v->co);
597                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
598                                         glVertex3fv(ltri[2]->v->co);
599                                 }
600                                 else {
601                                         const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
602                                         if (shade_type != shade_prev) {
603                                                 if (poly_prev != GL_ZERO) glEnd();
604                                                 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
605                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
606                                         }
607                                         if (poly_type != poly_prev) {
608                                                 if (poly_prev != GL_ZERO) glEnd();
609                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
610                                         }
611
612                                         if (!drawSmooth) {
613                                                 glNormal3fv(efa->no);
614                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
615                                                 glVertex3fv(ltri[0]->v->co);
616                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
617                                                 glVertex3fv(ltri[1]->v->co);
618                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
619                                                 glVertex3fv(ltri[2]->v->co);
620                                         }
621                                         else {
622                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
623                                                 glNormal3fv(ltri[0]->v->no);
624                                                 glVertex3fv(ltri[0]->v->co);
625                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
626                                                 glNormal3fv(ltri[1]->v->no);
627                                                 glVertex3fv(ltri[1]->v->co);
628                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
629                                                 glNormal3fv(ltri[2]->v->no);
630                                                 glVertex3fv(ltri[2]->v->co);
631                                         }
632                                 }
633
634                                 flush = (draw_option == DM_DRAW_OPTION_STIPPLE);
635                                 if (!skip_normals && !flush && (i != lasttri)) {
636                                         flush |= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
637                                 }
638
639                                 if (flush) {
640                                         glEnd();
641                                         poly_prev = GL_ZERO; /* force glBegin */
642
643                                         glDisable(GL_POLYGON_STIPPLE);
644                                 }
645                         }
646                 }
647         }
648
649         /* if non zero we know a face was rendered */
650         if (poly_prev != GL_ZERO) glEnd();
651 }
652
653 static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
654 {
655         luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset);
656         luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset);
657         luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset);
658 }
659
660 static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset)
661 {
662         lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset);
663         lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset);
664         lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset);
665 }
666
667 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4])
668 {
669         lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)];
670         lcol[1] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[1]->v)];
671         lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)];
672 }
673
674 static void emDM_drawFacesTex_common(DerivedMesh *dm,
675                                      DMSetDrawOptionsTex drawParams,
676                                      DMSetDrawOptions drawParamsMapped,
677                                      DMCompareDrawOptions compareDrawOptions,
678                                      void *userData)
679 {
680         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
681         BMEditMesh *em = bmdm->em;
682         BMesh *bm = em->bm;
683         struct BMLoop *(*looptris)[3] = em->looptris;
684         BMFace *efa;
685         MLoopUV *luv[3], dummyluv = {{0}};
686         MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
687         const int cd_loop_uv_offset    = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
688         const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
689         const int cd_poly_tex_offset   = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
690         unsigned char(*color_vert_array)[4] = em->derivedVertColor;
691         bool has_uv   = (cd_loop_uv_offset    != -1);
692         bool has_vcol_preview = (color_vert_array != NULL);
693         bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false);
694         bool has_vcol_any = (has_vcol_preview || has_vcol);
695         int i;
696
697         (void) compareDrawOptions;
698
699         luv[0] = luv[1] = luv[2] = &dummyluv;
700
701         // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255;  /* UNUSED */
702
703         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
704         glShadeModel(GL_SMOOTH);
705
706         BM_mesh_elem_index_ensure(bm, BM_FACE);
707
708         /* call again below is ok */
709         if (has_vcol_preview) {
710                 BM_mesh_elem_index_ensure(bm, BM_VERT);
711         }
712
713         if (bmdm->vertexCos) {
714                 /* add direct access */
715                 const float (*vertexCos)[3] = bmdm->vertexCos;
716                 const float (*vertexNos)[3];
717                 const float (*polyNos)[3];
718
719                 emDM_ensureVertNormals(bmdm);
720                 emDM_ensurePolyNormals(bmdm);
721                 vertexNos = bmdm->vertexNos;
722                 polyNos = bmdm->polyNos;
723
724                 BM_mesh_elem_index_ensure(bm, BM_VERT);
725
726                 for (i = 0; i < em->tottri; i++) {
727                         BMLoop **ltri = looptris[i];
728                         MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
729                         MTFace mtf = {{{0}}};
730                         /*unsigned char *cp = NULL;*/ /*UNUSED*/
731                         int drawSmooth = BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
732                         DMDrawOption draw_option;
733
734                         efa = ltri[0]->f;
735
736                         if (cd_poly_tex_offset != -1) {
737                                 ME_MTEXFACE_CPY(&mtf, tp);
738                         }
739
740                         if (drawParams)
741                                 draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
742                         else if (drawParamsMapped)
743                                 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
744                         else
745                                 draw_option = DM_DRAW_OPTION_NORMAL;
746
747                         if (draw_option != DM_DRAW_OPTION_SKIP) {
748
749                                 if      (has_uv)            bmdm_get_tri_uv(ltri,  luv,  cd_loop_uv_offset);
750                                 if      (has_vcol)          bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
751                                 else if (has_vcol_preview)  bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
752
753                                 glBegin(GL_TRIANGLES);
754                                 if (!drawSmooth) {
755                                         glNormal3fv(polyNos[BM_elem_index_get(efa)]);
756
757                                         glTexCoord2fv(luv[0]->uv);
758                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
759                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
760
761                                         glTexCoord2fv(luv[1]->uv);
762                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
763                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
764
765                                         glTexCoord2fv(luv[2]->uv);
766                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
767                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
768                                 }
769                                 else {
770                                         glTexCoord2fv(luv[0]->uv);
771                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
772                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
773                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
774
775                                         glTexCoord2fv(luv[1]->uv);
776                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
777                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
778                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
779
780                                         glTexCoord2fv(luv[2]->uv);
781                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
782                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
783                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
784                                 }
785                                 glEnd();
786                         }
787                 }
788         }
789         else {
790                 BM_mesh_elem_index_ensure(bm, BM_VERT);
791
792                 for (i = 0; i < em->tottri; i++) {
793                         BMLoop **ltri = looptris[i];
794                         MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
795                         MTFace mtf = {{{0}}};
796                         /*unsigned char *cp = NULL;*/ /*UNUSED*/
797                         int drawSmooth = BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
798                         DMDrawOption draw_option;
799
800                         efa = ltri[0]->f;
801
802                         if (cd_poly_tex_offset != -1) {
803                                 ME_MTEXFACE_CPY(&mtf, tp);
804                         }
805
806                         if (drawParams)
807                                 draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
808                         else if (drawParamsMapped)
809                                 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
810                         else
811                                 draw_option = DM_DRAW_OPTION_NORMAL;
812
813                         if (draw_option != DM_DRAW_OPTION_SKIP) {
814
815                                 if      (has_uv)            bmdm_get_tri_uv(ltri,  luv,  cd_loop_uv_offset);
816                                 if      (has_vcol)          bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
817                                 else if (has_vcol_preview)  bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
818
819                                 glBegin(GL_TRIANGLES);
820                                 if (!drawSmooth) {
821                                         glNormal3fv(efa->no);
822
823                                         glTexCoord2fv(luv[0]->uv);
824                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
825                                         glVertex3fv(ltri[0]->v->co);
826
827                                         glTexCoord2fv(luv[1]->uv);
828                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
829                                         glVertex3fv(ltri[1]->v->co);
830
831                                         glTexCoord2fv(luv[2]->uv);
832                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
833                                         glVertex3fv(ltri[2]->v->co);
834                                 }
835                                 else {
836                                         glTexCoord2fv(luv[0]->uv);
837                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
838                                         glNormal3fv(ltri[0]->v->no);
839                                         glVertex3fv(ltri[0]->v->co);
840
841                                         glTexCoord2fv(luv[1]->uv);
842                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
843                                         glNormal3fv(ltri[1]->v->no);
844                                         glVertex3fv(ltri[1]->v->co);
845
846                                         glTexCoord2fv(luv[2]->uv);
847                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
848                                         glNormal3fv(ltri[2]->v->no);
849                                         glVertex3fv(ltri[2]->v->co);
850                                 }
851                                 glEnd();
852                         }
853                 }
854         }
855
856         glShadeModel(GL_FLAT);
857 }
858
859 static void emDM_drawFacesTex(DerivedMesh *dm,
860                               DMSetDrawOptionsTex setDrawOptions,
861                               DMCompareDrawOptions compareDrawOptions,
862                               void *userData)
863 {
864         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
865 }
866
867 static void emDM_drawMappedFacesTex(DerivedMesh *dm,
868                                     DMSetDrawOptions setDrawOptions,
869                                     DMCompareDrawOptions compareDrawOptions,
870                                     void *userData)
871 {
872         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
873 }
874
875 /**
876  * \note
877  *
878  * For UV's:
879  *   const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
880  *
881  * This is intentionally different to calling:
882  *   CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i);
883  *
884  * ... because the material may use layer names to select different UV's
885  * see: [#34378]
886  */
887 static void emdm_pass_attrib_vertex_glsl(DMVertexAttribs *attribs, BMLoop *loop, int index_in_face)
888 {
889         BMVert *eve = loop->v;
890         int i;
891         const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
892
893         if (attribs->totorco) {
894                 int index = BM_elem_index_get(eve);
895                 const float *orco = (attribs->orco.array) ? attribs->orco.array[index] : zero;
896
897                 if (attribs->orco.gl_texco)
898                         glTexCoord3fv(orco);
899                 else
900                         glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
901         }
902         for (i = 0; i < attribs->tottface; i++) {
903                 const float *uv;
904
905                 if (attribs->tface[i].em_offset != -1) {
906                         const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
907                         uv = luv->uv;
908                 }
909                 else {
910                         uv = zero;
911                 }
912
913                 if (attribs->tface[i].gl_texco)
914                         glTexCoord2fv(uv);
915                 else
916                         glVertexAttrib2fvARB(attribs->tface[i].gl_index, uv);
917         }
918         for (i = 0; i < attribs->totmcol; i++) {
919                 GLubyte col[4];
920                 if (attribs->mcol[i].em_offset != -1) {
921                         const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
922                         col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
923                 }
924                 else {
925                         col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
926                 }
927                 glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col);
928         }
929         if (attribs->tottang) {
930                 int index = i * 4 + index_in_face;
931                 const float *tang = (attribs->tang.array) ? attribs->tang.array[index] : zero;
932                 glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
933         }
934 }
935
936 static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
937                                      DMSetMaterial setMaterial,
938                                      DMSetDrawOptions setDrawOptions,
939                                      void *userData)
940 {
941         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
942         BMEditMesh *em = bmdm->em;
943         BMesh *bm = em->bm;
944         struct BMLoop *(*looptris)[3] = em->looptris;
945         /* add direct access */
946         const float (*vertexCos)[3] = bmdm->vertexCos;
947         const float (*vertexNos)[3];
948         const float (*polyNos)[3];
949
950         BMFace *efa;
951         DMVertexAttribs attribs;
952         GPUVertexAttribs gattribs;
953
954         int i, matnr, new_matnr, do_draw;
955
956         do_draw = FALSE;
957         matnr = -1;
958
959         memset(&attribs, 0, sizeof(attribs));
960
961         emDM_ensureVertNormals(bmdm);
962         emDM_ensurePolyNormals(bmdm);
963         vertexNos = bmdm->vertexNos;
964         polyNos = bmdm->polyNos;
965
966         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
967         glShadeModel(GL_SMOOTH);
968         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
969
970         for (i = 0; i < em->tottri; i++) {
971                 BMLoop **ltri = looptris[i];
972                 int drawSmooth;
973
974                 efa = ltri[0]->f;
975                 drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
976
977                 if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
978                         continue;
979
980                 new_matnr = efa->mat_nr + 1;
981                 if (new_matnr != matnr) {
982                         do_draw = setMaterial(matnr = new_matnr, &gattribs);
983                         if (do_draw)
984                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
985                 }
986
987                 if (do_draw) {
988                         glBegin(GL_TRIANGLES);
989                         if (!drawSmooth) {
990                                 if (vertexCos) glNormal3fv(polyNos[BM_elem_index_get(efa)]);
991                                 else glNormal3fv(efa->no);
992
993                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
994                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
995                                 else glVertex3fv(ltri[0]->v->co);
996
997                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
998                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
999                                 else glVertex3fv(ltri[1]->v->co);
1000
1001                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
1002                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1003                                 else glVertex3fv(ltri[2]->v->co);
1004                         }
1005                         else {
1006                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
1007                                 if (vertexCos) {
1008                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1009                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1010                                 }
1011                                 else {
1012                                         glNormal3fv(ltri[0]->v->no);
1013                                         glVertex3fv(ltri[0]->v->co);
1014                                 }
1015
1016                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
1017                                 if (vertexCos) {
1018                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1019                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1020                                 }
1021                                 else {
1022                                         glNormal3fv(ltri[1]->v->no);
1023                                         glVertex3fv(ltri[1]->v->co);
1024                                 }
1025
1026                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
1027                                 if (vertexCos) {
1028                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1029                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1030                                 }
1031                                 else {
1032                                         glNormal3fv(ltri[2]->v->no);
1033                                         glVertex3fv(ltri[2]->v->co);
1034                                 }
1035                         }
1036                         glEnd();
1037                 }
1038         }
1039 }
1040
1041 static void emDM_drawFacesGLSL(DerivedMesh *dm,
1042                                int (*setMaterial)(int, void *attribs))
1043 {
1044         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1045 }
1046
1047 static void emDM_drawMappedFacesMat(DerivedMesh *dm,
1048                                     void (*setMaterial)(void *userData, int, void *attribs),
1049                                     bool (*setFace)(void *userData, int index), void *userData)
1050 {
1051         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1052         BMEditMesh *em = bmdm->em;
1053         BMesh *bm = em->bm;
1054         struct BMLoop *(*looptris)[3] = em->looptris;
1055         const float (*vertexCos)[3] = bmdm->vertexCos;
1056         const float (*vertexNos)[3];
1057         const float (*polyNos)[3];
1058         BMFace *efa;
1059         DMVertexAttribs attribs = {{{NULL}}};
1060         GPUVertexAttribs gattribs;
1061         int i, matnr, new_matnr;
1062
1063         matnr = -1;
1064
1065         emDM_ensureVertNormals(bmdm);
1066         emDM_ensurePolyNormals(bmdm);
1067
1068         vertexNos = bmdm->vertexNos;
1069         polyNos = bmdm->polyNos;
1070
1071         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1072         glShadeModel(GL_SMOOTH);
1073
1074         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
1075
1076         for (i = 0; i < em->tottri; i++) {
1077                 BMLoop **ltri = looptris[i];
1078                 int drawSmooth;
1079
1080                 efa = ltri[0]->f;
1081                 drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1082
1083                 /* face hiding */
1084                 if (setFace && !setFace(userData, BM_elem_index_get(efa)))
1085                         continue;
1086
1087                 /* material */
1088                 new_matnr = efa->mat_nr + 1;
1089                 if (new_matnr != matnr) {
1090                         setMaterial(userData, matnr = new_matnr, &gattribs);
1091                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1092                 }
1093
1094                 /* face */
1095                 glBegin(GL_TRIANGLES);
1096                 if (!drawSmooth) {
1097                         if (vertexCos) glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1098                         else glNormal3fv(efa->no);
1099
1100                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
1101                         if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1102                         else glVertex3fv(ltri[0]->v->co);
1103
1104                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
1105                         if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1106                         else glVertex3fv(ltri[1]->v->co);
1107
1108                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
1109                         if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1110                         else glVertex3fv(ltri[2]->v->co);
1111
1112                 }
1113                 else {
1114                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
1115                         if (vertexCos) {
1116                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1117                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1118                         }
1119                         else {
1120                                 glNormal3fv(ltri[0]->v->no);
1121                                 glVertex3fv(ltri[0]->v->co);
1122                         }
1123
1124                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
1125                         if (vertexCos) {
1126                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1127                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1128                         }
1129                         else {
1130                                 glNormal3fv(ltri[1]->v->no);
1131                                 glVertex3fv(ltri[1]->v->co);
1132                         }
1133
1134                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
1135                         if (vertexCos) {
1136                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1137                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1138                         }
1139                         else {
1140                                 glNormal3fv(ltri[2]->v->no);
1141                                 glVertex3fv(ltri[2]->v->co);
1142                         }
1143                 }
1144                 glEnd();
1145         }
1146 }
1147
1148 static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
1149 {
1150         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1151         BMesh *bm = bmdm->em->bm;
1152         BMVert *eve;
1153         BMIter iter;
1154         int i;
1155
1156         if (bm->totvert) {
1157                 if (bmdm->vertexCos) {
1158                         BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1159                                 minmax_v3v3_v3(r_min, r_max, bmdm->vertexCos[i]);
1160                         }
1161                 }
1162                 else {
1163                         BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1164                                 minmax_v3v3_v3(r_min, r_max, eve->co);
1165                         }
1166                 }
1167         }
1168         else {
1169                 zero_v3(r_min);
1170                 zero_v3(r_max);
1171         }
1172 }
1173 static int emDM_getNumVerts(DerivedMesh *dm)
1174 {
1175         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1176
1177         return bmdm->em->bm->totvert;
1178 }
1179
1180 static int emDM_getNumEdges(DerivedMesh *dm)
1181 {
1182         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1183
1184         return bmdm->em->bm->totedge;
1185 }
1186
1187 static int emDM_getNumTessFaces(DerivedMesh *dm)
1188 {
1189         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1190
1191         return bmdm->em->tottri;
1192 }
1193
1194 static int emDM_getNumLoops(DerivedMesh *dm)
1195 {
1196         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1197
1198         return bmdm->em->bm->totloop;
1199 }
1200
1201 static int emDM_getNumPolys(DerivedMesh *dm)
1202 {
1203         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1204
1205         return bmdm->em->bm->totface;
1206 }
1207
1208 static void bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *r_vert)
1209 {
1210         float *f;
1211
1212         copy_v3_v3(r_vert->co, ev->co);
1213
1214         normal_float_to_short_v3(r_vert->no, ev->no);
1215
1216         r_vert->flag = BM_vert_flag_to_mflag(ev);
1217
1218         if ((f = CustomData_bmesh_get(&bm->vdata, ev->head.data, CD_BWEIGHT))) {
1219                 r_vert->bweight = (unsigned char)((*f) * 255.0f);
1220         }
1221 }
1222
1223 static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
1224 {
1225         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1226         BMesh *bm = bmdm->em->bm;
1227         BMVert *ev;
1228
1229         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1230                 BLI_assert(!"error in emDM_getVert");
1231                 return;
1232         }
1233
1234         BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1235         ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1236         // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1237
1238         bmvert_to_mvert(bm, ev, r_vert);
1239         if (bmdm->vertexCos)
1240                 copy_v3_v3(r_vert->co, bmdm->vertexCos[index]);
1241 }
1242
1243 static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
1244 {
1245         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1246         BMesh *bm = bmdm->em->bm;
1247
1248         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1249                 BLI_assert(!"error in emDM_getVertCo");
1250                 return;
1251         }
1252
1253         if (bmdm->vertexCos) {
1254                 copy_v3_v3(r_co, bmdm->vertexCos[index]);
1255         }
1256         else {
1257                 BMVert *ev;
1258
1259                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1260                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1261                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1262                 copy_v3_v3(r_co, ev->co);
1263         }
1264 }
1265
1266 static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
1267 {
1268         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1269         BMesh *bm = bmdm->em->bm;
1270
1271         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1272                 BLI_assert(!"error in emDM_getVertNo");
1273                 return;
1274         }
1275
1276
1277         if (bmdm->vertexCos) {
1278                 emDM_ensureVertNormals(bmdm);
1279                 copy_v3_v3(r_no, bmdm->vertexNos[index]);
1280         }
1281         else {
1282                 BMVert *ev;
1283
1284                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1285                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1286                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1287                 copy_v3_v3(r_no, ev->no);
1288         }
1289 }
1290
1291 static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3])
1292 {
1293         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1294         BMesh *bm = bmdm->em->bm;
1295
1296         if (UNLIKELY(index < 0 || index >= bm->totface)) {
1297                 BLI_assert(!"error in emDM_getPolyNo");
1298                 return;
1299         }
1300
1301         if (bmdm->vertexCos) {
1302                 emDM_ensurePolyNormals(bmdm);
1303                 copy_v3_v3(r_no, bmdm->polyNos[index]);
1304         }
1305         else {
1306                 BMFace *efa;
1307
1308                 BLI_assert((bm->elem_table_dirty & BM_FACE) == 0);
1309                 efa = bm->ftable[index];  /* should be BM_vert_at_index() */
1310                 // efa = BM_face_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1311                 copy_v3_v3(r_no, efa->no);
1312         }
1313 }
1314
1315 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
1316 {
1317         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1318         BMesh *bm = bmdm->em->bm;
1319         BMEdge *e;
1320         float *f;
1321
1322         if (UNLIKELY(index < 0 || index >= bm->totedge)) {
1323                 BLI_assert(!"error in emDM_getEdge");
1324                 return;
1325         }
1326
1327         BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
1328         e = bm->etable[index];  /* should be BM_edge_at_index() */
1329         // e = BM_edge_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1330
1331         r_edge->flag = BM_edge_flag_to_mflag(e);
1332
1333         r_edge->v1 = BM_elem_index_get(e->v1);
1334         r_edge->v2 = BM_elem_index_get(e->v2);
1335
1336         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT))) {
1337                 r_edge->bweight = (unsigned char)((*f) * 255.0f);
1338         }
1339         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE))) {
1340                 r_edge->crease = (unsigned char)((*f) * 255.0f);
1341         }
1342 }
1343
1344 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
1345 {
1346         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1347         BMFace *ef;
1348         BMLoop **ltri;
1349
1350         if (UNLIKELY(index < 0 || index >= bmdm->em->tottri)) {
1351                 BLI_assert(!"error in emDM_getTessFace");
1352                 return;
1353         }
1354
1355         ltri = bmdm->em->looptris[index];
1356
1357         ef = ltri[0]->f;
1358
1359         r_face->mat_nr = (unsigned char) ef->mat_nr;
1360         r_face->flag = BM_face_flag_to_mflag(ef);
1361
1362         r_face->v1 = BM_elem_index_get(ltri[0]->v);
1363         r_face->v2 = BM_elem_index_get(ltri[1]->v);
1364         r_face->v3 = BM_elem_index_get(ltri[2]->v);
1365         r_face->v4 = 0;
1366
1367         test_index_face(r_face, NULL, 0, 3);
1368 }
1369
1370 static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
1371 {
1372         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1373         BMesh *bm = bmdm->em->bm;
1374         BMVert *eve;
1375         BMIter iter;
1376         const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
1377
1378         if (bmdm->vertexCos) {
1379                 int i;
1380
1381                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1382                         copy_v3_v3(r_vert->co, bmdm->vertexCos[i]);
1383                         normal_float_to_short_v3(r_vert->no, eve->no);
1384                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1385
1386                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1387
1388                         r_vert++;
1389                 }
1390         }
1391         else {
1392                 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1393                         copy_v3_v3(r_vert->co, eve->co);
1394                         normal_float_to_short_v3(r_vert->no, eve->no);
1395                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1396
1397                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1398
1399                         r_vert++;
1400                 }
1401         }
1402 }
1403
1404 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
1405 {
1406         BMesh *bm = ((EditDerivedBMesh *)dm)->em->bm;
1407         BMEdge *eed;
1408         BMIter iter;
1409
1410         const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
1411         const int cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
1412
1413         BM_mesh_elem_index_ensure(bm, BM_VERT);
1414
1415         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1416                 r_edge->v1 = BM_elem_index_get(eed->v1);
1417                 r_edge->v2 = BM_elem_index_get(eed->v2);
1418
1419                 r_edge->flag = BM_edge_flag_to_mflag(eed);
1420
1421                 r_edge->crease  = (cd_edge_crease_offset  != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset)  : 0;
1422                 r_edge->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0;
1423
1424                 r_edge++;
1425         }
1426 }
1427
1428 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
1429 {
1430         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1431         BMesh *bm = bmdm->em->bm;
1432         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
1433         BMFace *ef;
1434         int i;
1435
1436         BM_mesh_elem_index_ensure(bm, BM_VERT);
1437
1438         for (i = 0; i < bmdm->em->tottri; i++, r_face++) {
1439                 BMLoop **ltri = looptris[i];
1440                 ef = ltri[0]->f;
1441
1442                 r_face->mat_nr = (unsigned char) ef->mat_nr;
1443
1444                 r_face->flag = BM_face_flag_to_mflag(ef);
1445                 r_face->edcode = 0;
1446
1447                 r_face->v1 = BM_elem_index_get(ltri[0]->v);
1448                 r_face->v2 = BM_elem_index_get(ltri[1]->v);
1449                 r_face->v3 = BM_elem_index_get(ltri[2]->v);
1450                 r_face->v4 = 0;
1451
1452                 test_index_face(r_face, NULL, 0, 3);
1453         }
1454 }
1455
1456 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
1457 {
1458         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1459         BMesh *bm = bmdm->em->bm;
1460         BMIter iter;
1461         BMFace *efa;
1462
1463         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
1464
1465         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1466                 BMLoop *l_iter, *l_first;
1467                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
1468                 do {
1469                         r_loop->v = BM_elem_index_get(l_iter->v);
1470                         r_loop->e = BM_elem_index_get(l_iter->e);
1471                         r_loop++;
1472                 } while ((l_iter = l_iter->next) != l_first);
1473         }
1474 }
1475
1476 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
1477 {
1478         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1479         BMesh *bm = bmdm->em->bm;
1480         BMIter iter;
1481         BMFace *efa;
1482         int i;
1483
1484         i = 0;
1485         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1486                 r_poly->flag = BM_face_flag_to_mflag(efa);
1487                 r_poly->loopstart = i;
1488                 r_poly->totloop = efa->len;
1489                 r_poly->mat_nr = efa->mat_nr;
1490
1491                 r_poly++;
1492                 i += efa->len;
1493         }
1494 }
1495
1496 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1497 {
1498         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1499         BMesh *bm = bmdm->em->bm;
1500         void *datalayer;
1501
1502         datalayer = DM_get_tessface_data_layer(dm, type);
1503         if (datalayer)
1504                 return datalayer;
1505
1506         /* layers are store per face for editmesh, we convert to a temporary
1507          * data layer array in the derivedmesh when these are requested */
1508         if (type == CD_MTFACE || type == CD_MCOL) {
1509                 const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
1510                 int index;
1511                 char *data, *bmdata;
1512                 index = CustomData_get_layer_index(&bm->pdata, type_from);
1513
1514                 if (index != -1) {
1515                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1516                         BMLoop *(*looptris)[3] = bmdm->em->looptris;
1517                         const int size = CustomData_sizeof(type);
1518                         int i, j;
1519
1520                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1521                         index = CustomData_get_layer_index(&dm->faceData, type);
1522                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1523
1524                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1525
1526                         if (type == CD_MTFACE) {
1527                                 const int cd_loop_uv_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
1528                                 const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
1529
1530                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1531                                         BMFace *efa = looptris[i][0]->f;
1532
1533                                         // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
1534                                         bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
1535
1536                                         ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
1537                                         for (j = 0; j < 3; j++) {
1538                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
1539                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
1540                                                 copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
1541                                         }
1542                                 }
1543                         }
1544                         else {
1545                                 const int cd_loop_color_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
1546                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1547                                         for (j = 0; j < 3; j++) {
1548                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
1549                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
1550                                                 MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
1551                                         }
1552                                 }
1553                         }
1554                 }
1555         }
1556
1557         return datalayer;
1558 }
1559
1560 static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3])
1561 {
1562         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1563         BMesh *bm = bmdm->em->bm;
1564         BMVert *eve;
1565         BMIter iter;
1566         int i;
1567
1568         if (bmdm->vertexCos) {
1569                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1570                         copy_v3_v3(r_cos[i], bmdm->vertexCos[i]);
1571                 }
1572         }
1573         else {
1574                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1575                         copy_v3_v3(r_cos[i], eve->co);
1576                 }
1577         }
1578 }
1579
1580 static void emDM_release(DerivedMesh *dm)
1581 {
1582         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1583
1584         if (DM_release(dm)) {
1585                 if (bmdm->vertexCos) {
1586                         MEM_freeN((void *)bmdm->vertexCos);
1587                         if (bmdm->vertexNos) {
1588                                 MEM_freeN((void *)bmdm->vertexNos);
1589                         }
1590                         if (bmdm->polyNos) {
1591                                 MEM_freeN((void *)bmdm->polyNos);
1592                         }
1593                 }
1594
1595                 if (bmdm->polyCos) {
1596                         MEM_freeN((void *)bmdm->polyCos);
1597                 }
1598
1599                 MEM_freeN(bmdm);
1600         }
1601 }
1602
1603 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1604 {
1605         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1606
1607         return &bmdm->em->bm->vdata;
1608 }
1609
1610 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1611 {
1612         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1613
1614         return &bmdm->em->bm->edata;
1615 }
1616
1617 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1618 {
1619         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1620
1621         return &bmdm->dm.faceData;
1622 }
1623
1624 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1625 {
1626         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1627
1628         return &bmdm->em->bm->ldata;
1629 }
1630
1631 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1632 {
1633         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1634
1635         return &bmdm->em->bm->pdata;
1636 }
1637
1638
1639 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
1640                                  Object *UNUSED(ob),
1641                                  float (*vertexCos)[3])
1642 {
1643         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1644         BMesh *bm = em->bm;
1645         const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
1646         const int cd_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
1647
1648         bmdm->em = em;
1649
1650         DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, bm->totvert,
1651                 bm->totedge, em->tottri, bm->totloop, bm->totface);
1652
1653         /* could also get from the objects mesh directly */
1654         bmdm->dm.cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
1655
1656         bmdm->dm.getVertCos = emDM_getVertCos;
1657         bmdm->dm.getMinMax = emDM_getMinMax;
1658
1659         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1660         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1661         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1662         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1663         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1664
1665         bmdm->dm.getNumVerts = emDM_getNumVerts;
1666         bmdm->dm.getNumEdges = emDM_getNumEdges;
1667         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1668         bmdm->dm.getNumLoops = emDM_getNumLoops;
1669         bmdm->dm.getNumPolys = emDM_getNumPolys;
1670
1671         bmdm->dm.getVert = emDM_getVert;
1672         bmdm->dm.getVertCo = emDM_getVertCo;
1673         bmdm->dm.getVertNo = emDM_getVertNo;
1674         bmdm->dm.getPolyNo = emDM_getPolyNo;
1675         bmdm->dm.getEdge = emDM_getEdge;
1676         bmdm->dm.getTessFace = emDM_getTessFace;
1677         bmdm->dm.copyVertArray = emDM_copyVertArray;
1678         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1679         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1680         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1681         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1682
1683         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1684
1685         bmdm->dm.calcNormals = emDM_calcNormals;
1686         bmdm->dm.recalcTessellation = emDM_recalcTessellation;
1687
1688         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1689         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1690         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1691
1692         bmdm->dm.drawEdges = emDM_drawEdges;
1693         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1694         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1695         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1696         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1697         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1698         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1699         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1700         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1701         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1702
1703         bmdm->dm.release = emDM_release;
1704
1705         bmdm->vertexCos = (const float (*)[3])vertexCos;
1706         bmdm->dm.deformedOnly = (vertexCos != NULL);
1707
1708         if (cd_dvert_offset != -1) {
1709                 BMIter iter;
1710                 BMVert *eve;
1711                 int i;
1712
1713                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1714
1715                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1716                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1717                                          BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
1718                 }
1719         }
1720
1721         if (cd_skin_offset != -1) {
1722                 BMIter iter;
1723                 BMVert *eve;
1724                 int i;
1725
1726                 DM_add_vert_layer(&bmdm->dm, CD_MVERT_SKIN, CD_CALLOC, NULL);
1727
1728                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1729                         DM_set_vert_data(&bmdm->dm, i, CD_MVERT_SKIN,
1730                                          BM_ELEM_CD_GET_VOID_P(eve, cd_skin_offset));
1731                 }
1732         }
1733
1734         return (DerivedMesh *)bmdm;
1735 }
1736
1737
1738
1739 /* -------------------------------------------------------------------- */
1740 /* StatVis Functions */
1741
1742 static void axis_from_enum_v3(float v[3], const char axis)
1743 {
1744         zero_v3(v);
1745         if (axis < 3) v[axis]     =  1.0f;
1746         else          v[axis - 3] = -1.0f;
1747 }
1748
1749 static void statvis_calc_overhang(
1750         BMEditMesh *em,
1751         const float (*polyNos)[3],
1752         /* values for calculating */
1753         const float min, const float max, const char axis,
1754         /* result */
1755         unsigned char (*r_face_colors)[4])
1756 {
1757         BMIter iter;
1758         BMesh *bm = em->bm;
1759         BMFace *f;
1760         float dir[3];
1761         int index;
1762         const float minmax_irange = 1.0f / (max - min);
1763
1764         /* fallback */
1765         const char col_fallback[4] = {64, 64, 64, 255};
1766
1767         BLI_assert(min <= max);
1768
1769         axis_from_enum_v3(dir, axis);
1770
1771         if (LIKELY(em->ob)) {
1772                 mul_transposed_mat3_m4_v3(em->ob->obmat, dir);
1773                 normalize_v3(dir);
1774         }
1775
1776         /* now convert into global space */
1777         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
1778                 float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI;
1779
1780                 /* remap */
1781                 if (fac >= min && fac <= max) {
1782                         float fcol[3];
1783                         fac = (fac - min) * minmax_irange;
1784                         fac = 1.0f - fac;
1785                         CLAMP(fac, 0.0f, 1.0f);
1786                         weight_to_rgb(fcol, fac);
1787                         rgb_float_to_uchar(r_face_colors[index], fcol);
1788                 }
1789                 else {
1790                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
1791                 }
1792         }
1793 }
1794
1795 /* so we can use jitter values for face interpolation */
1796 static void uv_from_jitter_v2(float uv[2])
1797 {
1798         uv[0] += 0.5f;
1799         uv[1] += 0.5f;
1800         if (uv[0] + uv[1] > 1.0f) {
1801                 uv[0] = 1.0f - uv[0];
1802                 uv[1] = 1.0f - uv[1];
1803         }
1804
1805         CLAMP(uv[0], 0.0f, 1.0f);
1806         CLAMP(uv[1], 0.0f, 1.0f);
1807 }
1808
1809 static void statvis_calc_thickness(
1810         BMEditMesh *em,
1811         const float (*vertexCos)[3],
1812         /* values for calculating */
1813         const float min, const float max, const int samples,
1814         /* result */
1815         unsigned char (*r_face_colors)[4])
1816 {
1817         const float eps_offset = 0.00002f;  /* values <= 0.00001 give errors */
1818         float *face_dists = (float *)r_face_colors;  /* cheating */
1819         const bool use_jit = samples < 32;
1820         float jit_ofs[32][2];
1821         BMesh *bm = em->bm;
1822         const int tottri = em->tottri;
1823         const float minmax_irange = 1.0f / (max - min);
1824         int i;
1825
1826         struct BMLoop *(*looptris)[3] = em->looptris;
1827
1828         /* fallback */
1829         const char col_fallback[4] = {64, 64, 64, 255};
1830
1831         struct BMBVHTree *bmtree;
1832
1833         BLI_assert(min <= max);
1834
1835         fill_vn_fl(face_dists, em->bm->totface, max);
1836
1837         if (use_jit) {
1838                 int j;
1839                 BLI_assert(samples < 32);
1840                 BLI_jitter_init(jit_ofs[0], samples);
1841
1842                 for (j = 0; j < samples; j++) {
1843                         uv_from_jitter_v2(jit_ofs[j]);
1844                 }
1845         }
1846
1847         BM_mesh_elem_index_ensure(bm, BM_FACE);
1848         if (vertexCos) {
1849                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1850         }
1851
1852         bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
1853
1854         for (i = 0; i < tottri; i++) {
1855                 BMFace *f_hit;
1856                 BMLoop **ltri = looptris[i];
1857                 const int index = BM_elem_index_get(ltri[0]->f);
1858                 const float *cos[3];
1859                 float ray_co[3];
1860                 float ray_no[3];
1861
1862                 if (vertexCos) {
1863                         cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)];
1864                         cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)];
1865                         cos[2] = vertexCos[BM_elem_index_get(ltri[2]->v)];
1866                 }
1867                 else {
1868                         cos[0] = ltri[0]->v->co;
1869                         cos[1] = ltri[1]->v->co;
1870                         cos[2] = ltri[2]->v->co;
1871                 }
1872
1873                 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
1874
1875 #define FACE_RAY_TEST_ANGLE \
1876                 f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, \
1877                                            &dist, NULL, NULL); \
1878                 if (f_hit && dist < face_dists[index]) { \
1879                         float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
1880                         angle_fac = 1.0f - angle_fac; \
1881                         angle_fac = angle_fac * angle_fac * angle_fac; \
1882                         angle_fac = 1.0f - angle_fac; \
1883                         dist /= angle_fac; \
1884                         if (dist < face_dists[index]) { \
1885                                 face_dists[index] = dist; \
1886                         } \
1887                 } (void)0
1888
1889                 if (use_jit) {
1890                         int j;
1891                         for (j = 0; j < samples; j++) {
1892                                 float dist = face_dists[index];
1893                                 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
1894                                 madd_v3_v3fl(ray_co, ray_no, eps_offset);
1895
1896                                 FACE_RAY_TEST_ANGLE;
1897                         }
1898                 }
1899                 else {
1900                         float dist = face_dists[index];
1901                         mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]);
1902                         madd_v3_v3fl(ray_co, ray_no, eps_offset);
1903
1904                         FACE_RAY_TEST_ANGLE;
1905                 }
1906         }
1907
1908         BKE_bmbvh_free(bmtree);
1909
1910         /* convert floats into color! */
1911         for (i = 0; i < bm->totface; i++) {
1912                 float fac = face_dists[i];
1913
1914                 /* important not '<=' */
1915                 if (fac < max) {
1916                         float fcol[3];
1917                         fac = (fac - min) * minmax_irange;
1918                         fac = 1.0f - fac;
1919                         CLAMP(fac, 0.0f, 1.0f);
1920                         weight_to_rgb(fcol, fac);
1921                         rgb_float_to_uchar(r_face_colors[i], fcol);
1922                 }
1923                 else {
1924                         copy_v4_v4_char((char *)r_face_colors[i], (const char *)col_fallback);
1925                 }
1926         }
1927 }
1928
1929 static void statvis_calc_intersect(
1930         BMEditMesh *em,
1931         const float (*vertexCos)[3],
1932         /* result */
1933         unsigned char (*r_face_colors)[4])
1934 {
1935         BMIter iter;
1936         BMesh *bm = em->bm;
1937         BMEdge *e;
1938         int index;
1939
1940         /* fallback */
1941         // const char col_fallback[4] = {64, 64, 64, 255};
1942
1943         struct BMBVHTree *bmtree;
1944
1945         memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
1946
1947         BM_mesh_elem_index_ensure(bm, BM_FACE);
1948         if (vertexCos) {
1949                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1950         }
1951
1952         bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
1953
1954         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
1955                 BMFace *f_hit;
1956                 float cos[2][3];
1957                 float cos_mid[3];
1958                 float ray_no[3];
1959
1960                 if (e->l == NULL)
1961                         continue;
1962
1963                 if (vertexCos) {
1964                         copy_v3_v3(cos[0], vertexCos[BM_elem_index_get(e->v1)]);
1965                         copy_v3_v3(cos[1], vertexCos[BM_elem_index_get(e->v2)]);
1966                 }
1967                 else {
1968                         copy_v3_v3(cos[0], e->v1->co);
1969                         copy_v3_v3(cos[1], e->v2->co);
1970                 }
1971
1972                 mid_v3_v3v3(cos_mid, cos[0], cos[1]);
1973                 sub_v3_v3v3(ray_no, cos[1], cos[0]);
1974
1975                 f_hit = BKE_bmbvh_find_face_segment(bmtree, cos[0], cos[1],
1976                                                     NULL, NULL, NULL);
1977
1978                 if (f_hit) {
1979                         BMLoop *l_iter, *l_first;
1980                         float fcol[3];
1981
1982                         index = BM_elem_index_get(f_hit);
1983                         weight_to_rgb(fcol, 1.0f);
1984                         rgb_float_to_uchar(r_face_colors[index], fcol);
1985
1986                         l_iter = l_first = e->l;
1987                         do {
1988                                 index = BM_elem_index_get(l_iter->f);
1989                                 weight_to_rgb(fcol, 1.0f);
1990                                 rgb_float_to_uchar(r_face_colors[index], fcol);
1991                         } while ((l_iter = l_iter->radial_next) != l_first);
1992                 }
1993
1994         }
1995
1996         BKE_bmbvh_free(bmtree);
1997 }
1998
1999 static void statvis_calc_distort(
2000         BMEditMesh *em,
2001         const float (*vertexCos)[3], const float (*polyNos)[3],
2002         /* values for calculating */
2003         const float min, const float max,
2004         /* result */
2005         unsigned char (*r_face_colors)[4])
2006 {
2007         BMIter iter;
2008         BMesh *bm = em->bm;
2009         BMFace *f;
2010         const float *f_no;
2011         int index;
2012         const float minmax_irange = 1.0f / (max - min);
2013
2014         /* fallback */
2015         const char col_fallback[4] = {64, 64, 64, 255};
2016
2017         /* now convert into global space */
2018         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2019                 float fac;
2020
2021                 if (f->len == 3) {
2022                         fac = -1.0f;
2023                 }
2024                 else {
2025                         BMLoop *l_iter, *l_first;
2026                         if (vertexCos) {
2027                                 f_no = polyNos[index];
2028                         }
2029                         else {
2030                                 f_no = f->no;
2031                         }
2032
2033                         fac = 0.0f;
2034                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2035                         do {
2036                                 float no_corner[3];
2037                                 if (vertexCos) {
2038                                         normal_tri_v3(no_corner,
2039                                                       vertexCos[BM_elem_index_get(l_iter->prev->v)],
2040                                                       vertexCos[BM_elem_index_get(l_iter->v)],
2041                                                       vertexCos[BM_elem_index_get(l_iter->next->v)]);
2042                                 }
2043                                 else {
2044                                         BM_loop_calc_face_normal(l_iter, no_corner);
2045                                 }
2046                                 /* simple way to detect (what is most likely) concave */
2047                                 if (dot_v3v3(f_no, no_corner) < 0.0f) {
2048                                         negate_v3(no_corner);
2049                                 }
2050                                 fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
2051                         } while ((l_iter = l_iter->next) != l_first);
2052                         fac *= 2.0f;
2053                 }
2054
2055                 /* remap */
2056                 if (fac >= min) {
2057                         float fcol[3];
2058                         fac = (fac - min) * minmax_irange;
2059                         CLAMP(fac, 0.0f, 1.0f);
2060                         weight_to_rgb(fcol, fac);
2061                         rgb_float_to_uchar(r_face_colors[index], fcol);
2062                 }
2063                 else {
2064                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
2065                 }
2066         }
2067 }
2068
2069 static void statvis_calc_sharp(
2070         BMEditMesh *em,
2071         const float (*vertexCos)[3],
2072         /* values for calculating */
2073         const float min, const float max,
2074         /* result */
2075         unsigned char (*r_vert_colors)[4])
2076 {
2077         float *vert_angles = (float *)r_vert_colors;  /* cheating */
2078         BMIter iter;
2079         BMesh *bm = em->bm;
2080         BMEdge *e;
2081         //float f_no[3];
2082         const float minmax_irange = 1.0f / (max - min);
2083         int i;
2084
2085         /* fallback */
2086         const char col_fallback[4] = {64, 64, 64, 255};
2087
2088         (void)vertexCos;  /* TODO */
2089
2090         fill_vn_fl(vert_angles, em->bm->totvert, -M_PI);
2091
2092         /* first assign float values to verts */
2093         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2094                 float angle = BM_edge_calc_face_angle_signed(e);
2095                 float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
2096                 float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
2097                 *col1 = max_ff(*col1, angle);
2098                 *col2 = max_ff(*col2, angle);
2099         }
2100
2101         /* convert floats into color! */
2102         for (i = 0; i < bm->totvert; i++) {
2103                 float fac = vert_angles[i];
2104
2105                 /* important not '<=' */
2106                 if (fac > min) {
2107                         float fcol[3];
2108                         fac = (fac - min) * minmax_irange;
2109                         CLAMP(fac, 0.0f, 1.0f);
2110                         weight_to_rgb(fcol, fac);
2111                         rgb_float_to_uchar(r_vert_colors[i], fcol);
2112                 }
2113                 else {
2114                         copy_v4_v4_char((char *)r_vert_colors[i], (const char *)col_fallback);
2115                 }
2116         }
2117 }
2118
2119 void BKE_editmesh_statvis_calc(BMEditMesh *em, DerivedMesh *dm,
2120                                MeshStatVis *statvis)
2121 {
2122         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2123         BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH);
2124
2125         switch (statvis->type) {
2126                 case SCE_STATVIS_OVERHANG:
2127                 {
2128                         BKE_editmesh_color_ensure(em, BM_FACE);
2129                         statvis_calc_overhang(
2130                                     em, bmdm ? bmdm->polyNos : NULL,
2131                                     statvis->overhang_min / (float)M_PI,
2132                                     statvis->overhang_max / (float)M_PI,
2133                                     statvis->overhang_axis,
2134                                     em->derivedFaceColor);
2135                         break;
2136                 }
2137                 case SCE_STATVIS_THICKNESS:
2138                 {
2139                         const float scale = 1.0f / mat4_to_scale(em->ob->obmat);
2140                         BKE_editmesh_color_ensure(em, BM_FACE);
2141                         statvis_calc_thickness(
2142                                     em, bmdm ? bmdm->vertexCos : NULL,
2143                                     statvis->thickness_min * scale,
2144                                     statvis->thickness_max * scale,
2145                                     statvis->thickness_samples,
2146                                     em->derivedFaceColor);
2147                         break;
2148                 }
2149                 case SCE_STATVIS_INTERSECT:
2150                 {
2151                         BKE_editmesh_color_ensure(em, BM_FACE);
2152                         statvis_calc_intersect(
2153                                     em, bmdm ? bmdm->vertexCos : NULL,
2154                                     em->derivedFaceColor);
2155                         break;
2156                 }
2157                 case SCE_STATVIS_DISTORT:
2158                 {
2159                         BKE_editmesh_color_ensure(em, BM_FACE);
2160
2161                         if (bmdm)
2162                                 emDM_ensurePolyNormals(bmdm);
2163
2164                         statvis_calc_distort(
2165                                 em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL,
2166                                 statvis->distort_min,
2167                                 statvis->distort_max,
2168                                 em->derivedFaceColor);
2169                         break;
2170                 }
2171                 case SCE_STATVIS_SHARP:
2172                 {
2173                         BKE_editmesh_color_ensure(em, BM_VERT);
2174                         statvis_calc_sharp(
2175                                 em, bmdm ? bmdm->vertexCos : NULL,
2176                                 statvis->sharp_min,
2177                                 statvis->sharp_max,
2178                                 /* in this case they are vertex colors */
2179                                 em->derivedVertColor);
2180                         break;
2181                 }
2182         }
2183 }
2184
2185
2186
2187 /* -------------------------------------------------------------------- */
2188 /* Editmesh Vert Coords */
2189
2190 struct CageUserData {
2191         int totvert;
2192         float (*cos_cage)[3];
2193         BLI_bitmap *visit_bitmap;
2194 };
2195
2196 static void cage_mapped_verts_callback(void *userData, int index, const float co[3],
2197                                        const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2198 {
2199         struct CageUserData *data = userData;
2200
2201         if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_GET(data->visit_bitmap, index))) {
2202                 BLI_BITMAP_SET(data->visit_bitmap, index);
2203                 copy_v3_v3(data->cos_cage[index], co);
2204         }
2205 }
2206
2207 float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
2208 {
2209         DerivedMesh *cage, *final;
2210         BLI_bitmap *visit_bitmap;
2211         struct CageUserData data;
2212         float (*cos_cage)[3];
2213
2214         cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, &final, CD_MASK_BAREMESH);
2215         cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
2216
2217         /* when initializing cage verts, we only want the first cage coordinate for each vertex,
2218          * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
2219         visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2220
2221         data.totvert = em->bm->totvert;
2222         data.cos_cage = cos_cage;
2223         data.visit_bitmap = visit_bitmap;
2224
2225         cage->foreachMappedVert(cage, cage_mapped_verts_callback, &data, DM_FOREACH_NOP);
2226
2227         MEM_freeN(visit_bitmap);
2228
2229         if (r_numVerts) {
2230                 *r_numVerts = em->bm->totvert;
2231         }
2232
2233         return cos_cage;
2234 }