code cleanup: spelling
[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 int 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         return 1;
1223 }
1224
1225 static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
1226 {
1227         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1228         BMesh *bm = bmdm->em->bm;
1229         BMVert *ev;
1230
1231         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1232                 BLI_assert(!"error in emDM_getVert");
1233                 return;
1234         }
1235
1236         BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1237         ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1238         // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1239
1240         bmvert_to_mvert(bm, ev, r_vert);
1241         if (bmdm->vertexCos)
1242                 copy_v3_v3(r_vert->co, bmdm->vertexCos[index]);
1243 }
1244
1245 static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
1246 {
1247         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1248         BMesh *bm = bmdm->em->bm;
1249
1250         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1251                 BLI_assert(!"error in emDM_getVertCo");
1252                 return;
1253         }
1254
1255         if (bmdm->vertexCos) {
1256                 copy_v3_v3(r_co, bmdm->vertexCos[index]);
1257         }
1258         else {
1259                 BMVert *ev;
1260
1261                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1262                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1263                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1264                 copy_v3_v3(r_co, ev->co);
1265         }
1266 }
1267
1268 static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
1269 {
1270         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1271         BMesh *bm = bmdm->em->bm;
1272
1273         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1274                 BLI_assert(!"error in emDM_getVertNo");
1275                 return;
1276         }
1277
1278
1279         if (bmdm->vertexCos) {
1280                 emDM_ensureVertNormals(bmdm);
1281                 copy_v3_v3(r_no, bmdm->vertexNos[index]);
1282         }
1283         else {
1284                 BMVert *ev;
1285
1286                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1287                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1288                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1289                 copy_v3_v3(r_no, ev->no);
1290         }
1291 }
1292
1293 static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3])
1294 {
1295         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1296         BMesh *bm = bmdm->em->bm;
1297
1298         if (UNLIKELY(index < 0 || index >= bm->totface)) {
1299                 BLI_assert(!"error in emDM_getPolyNo");
1300                 return;
1301         }
1302
1303         if (bmdm->vertexCos) {
1304                 emDM_ensurePolyNormals(bmdm);
1305                 copy_v3_v3(r_no, bmdm->polyNos[index]);
1306         }
1307         else {
1308                 BMFace *efa;
1309
1310                 BLI_assert((bm->elem_table_dirty & BM_FACE) == 0);
1311                 efa = bm->ftable[index];  /* should be BM_vert_at_index() */
1312                 // efa = BM_face_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1313                 copy_v3_v3(r_no, efa->no);
1314         }
1315 }
1316
1317 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
1318 {
1319         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1320         BMesh *bm = bmdm->em->bm;
1321         BMEdge *e;
1322         float *f;
1323
1324         if (UNLIKELY(index < 0 || index >= bm->totedge)) {
1325                 BLI_assert(!"error in emDM_getEdge");
1326                 return;
1327         }
1328
1329         BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
1330         e = bm->etable[index];  /* should be BM_edge_at_index() */
1331         // e = BM_edge_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1332
1333         r_edge->flag = BM_edge_flag_to_mflag(e);
1334
1335         r_edge->v1 = BM_elem_index_get(e->v1);
1336         r_edge->v2 = BM_elem_index_get(e->v2);
1337
1338         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT))) {
1339                 r_edge->bweight = (unsigned char)((*f) * 255.0f);
1340         }
1341         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE))) {
1342                 r_edge->crease = (unsigned char)((*f) * 255.0f);
1343         }
1344 }
1345
1346 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
1347 {
1348         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1349         BMFace *ef;
1350         BMLoop **ltri;
1351
1352         if (UNLIKELY(index < 0 || index >= bmdm->em->tottri)) {
1353                 BLI_assert(!"error in emDM_getTessFace");
1354                 return;
1355         }
1356
1357         ltri = bmdm->em->looptris[index];
1358
1359         ef = ltri[0]->f;
1360
1361         r_face->mat_nr = (unsigned char) ef->mat_nr;
1362         r_face->flag = BM_face_flag_to_mflag(ef);
1363
1364         r_face->v1 = BM_elem_index_get(ltri[0]->v);
1365         r_face->v2 = BM_elem_index_get(ltri[1]->v);
1366         r_face->v3 = BM_elem_index_get(ltri[2]->v);
1367         r_face->v4 = 0;
1368
1369         test_index_face(r_face, NULL, 0, 3);
1370 }
1371
1372 static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
1373 {
1374         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1375         BMesh *bm = bmdm->em->bm;
1376         BMVert *eve;
1377         BMIter iter;
1378         const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
1379
1380         if (bmdm->vertexCos) {
1381                 int i;
1382
1383                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1384                         copy_v3_v3(r_vert->co, bmdm->vertexCos[i]);
1385                         normal_float_to_short_v3(r_vert->no, eve->no);
1386                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1387
1388                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1389
1390                         r_vert++;
1391                 }
1392         }
1393         else {
1394                 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1395                         copy_v3_v3(r_vert->co, eve->co);
1396                         normal_float_to_short_v3(r_vert->no, eve->no);
1397                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1398
1399                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1400
1401                         r_vert++;
1402                 }
1403         }
1404 }
1405
1406 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
1407 {
1408         BMesh *bm = ((EditDerivedBMesh *)dm)->em->bm;
1409         BMEdge *eed;
1410         BMIter iter;
1411
1412         const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
1413         const int cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
1414
1415         BM_mesh_elem_index_ensure(bm, BM_VERT);
1416
1417         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1418                 r_edge->v1 = BM_elem_index_get(eed->v1);
1419                 r_edge->v2 = BM_elem_index_get(eed->v2);
1420
1421                 r_edge->flag = BM_edge_flag_to_mflag(eed);
1422
1423                 r_edge->crease  = (cd_edge_crease_offset  != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset)  : 0;
1424                 r_edge->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0;
1425
1426                 r_edge++;
1427         }
1428 }
1429
1430 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
1431 {
1432         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1433         BMesh *bm = bmdm->em->bm;
1434         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
1435         BMFace *ef;
1436         int i;
1437
1438         BM_mesh_elem_index_ensure(bm, BM_VERT);
1439
1440         for (i = 0; i < bmdm->em->tottri; i++, r_face++) {
1441                 BMLoop **ltri = looptris[i];
1442                 ef = ltri[0]->f;
1443
1444                 r_face->mat_nr = (unsigned char) ef->mat_nr;
1445
1446                 r_face->flag = BM_face_flag_to_mflag(ef);
1447                 r_face->edcode = 0;
1448
1449                 r_face->v1 = BM_elem_index_get(ltri[0]->v);
1450                 r_face->v2 = BM_elem_index_get(ltri[1]->v);
1451                 r_face->v3 = BM_elem_index_get(ltri[2]->v);
1452                 r_face->v4 = 0;
1453
1454                 test_index_face(r_face, NULL, 0, 3);
1455         }
1456 }
1457
1458 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
1459 {
1460         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1461         BMesh *bm = bmdm->em->bm;
1462         BMIter iter;
1463         BMFace *efa;
1464
1465         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
1466
1467         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1468                 BMLoop *l_iter, *l_first;
1469                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
1470                 do {
1471                         r_loop->v = BM_elem_index_get(l_iter->v);
1472                         r_loop->e = BM_elem_index_get(l_iter->e);
1473                         r_loop++;
1474                 } while ((l_iter = l_iter->next) != l_first);
1475         }
1476 }
1477
1478 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
1479 {
1480         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1481         BMesh *bm = bmdm->em->bm;
1482         BMIter iter;
1483         BMFace *efa;
1484         int i;
1485
1486         i = 0;
1487         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1488                 r_poly->flag = BM_face_flag_to_mflag(efa);
1489                 r_poly->loopstart = i;
1490                 r_poly->totloop = efa->len;
1491                 r_poly->mat_nr = efa->mat_nr;
1492
1493                 r_poly++;
1494                 i += efa->len;
1495         }
1496 }
1497
1498 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1499 {
1500         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1501         BMesh *bm = bmdm->em->bm;
1502         void *datalayer;
1503
1504         datalayer = DM_get_tessface_data_layer(dm, type);
1505         if (datalayer)
1506                 return datalayer;
1507
1508         /* layers are store per face for editmesh, we convert to a temporary
1509          * data layer array in the derivedmesh when these are requested */
1510         if (type == CD_MTFACE || type == CD_MCOL) {
1511                 const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
1512                 int index;
1513                 char *data, *bmdata;
1514                 index = CustomData_get_layer_index(&bm->pdata, type_from);
1515
1516                 if (index != -1) {
1517                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1518                         BMLoop *(*looptris)[3] = bmdm->em->looptris;
1519                         const int size = CustomData_sizeof(type);
1520                         int i, j;
1521
1522                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1523                         index = CustomData_get_layer_index(&dm->faceData, type);
1524                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1525
1526                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1527
1528                         if (type == CD_MTFACE) {
1529                                 const int cd_loop_uv_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
1530                                 const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
1531
1532                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1533                                         BMFace *efa = looptris[i][0]->f;
1534
1535                                         // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
1536                                         bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
1537
1538                                         ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
1539                                         for (j = 0; j < 3; j++) {
1540                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
1541                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
1542                                                 copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
1543                                         }
1544                                 }
1545                         }
1546                         else {
1547                                 const int cd_loop_color_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
1548                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1549                                         for (j = 0; j < 3; j++) {
1550                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
1551                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
1552                                                 MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
1553                                         }
1554                                 }
1555                         }
1556                 }
1557         }
1558
1559         return datalayer;
1560 }
1561
1562 static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3])
1563 {
1564         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1565         BMesh *bm = bmdm->em->bm;
1566         BMVert *eve;
1567         BMIter iter;
1568         int i;
1569
1570         if (bmdm->vertexCos) {
1571                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1572                         copy_v3_v3(r_cos[i], bmdm->vertexCos[i]);
1573                 }
1574         }
1575         else {
1576                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1577                         copy_v3_v3(r_cos[i], eve->co);
1578                 }
1579         }
1580 }
1581
1582 static void emDM_release(DerivedMesh *dm)
1583 {
1584         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1585
1586         if (DM_release(dm)) {
1587                 if (bmdm->vertexCos) {
1588                         MEM_freeN((void *)bmdm->vertexCos);
1589                         if (bmdm->vertexNos) {
1590                                 MEM_freeN((void *)bmdm->vertexNos);
1591                         }
1592                         if (bmdm->polyNos) {
1593                                 MEM_freeN((void *)bmdm->polyNos);
1594                         }
1595                 }
1596
1597                 if (bmdm->polyCos) {
1598                         MEM_freeN((void *)bmdm->polyCos);
1599                 }
1600
1601                 MEM_freeN(bmdm);
1602         }
1603 }
1604
1605 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1606 {
1607         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1608
1609         return &bmdm->em->bm->vdata;
1610 }
1611
1612 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1613 {
1614         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1615
1616         return &bmdm->em->bm->edata;
1617 }
1618
1619 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1620 {
1621         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1622
1623         return &bmdm->dm.faceData;
1624 }
1625
1626 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1627 {
1628         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1629
1630         return &bmdm->em->bm->ldata;
1631 }
1632
1633 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1634 {
1635         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1636
1637         return &bmdm->em->bm->pdata;
1638 }
1639
1640
1641 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
1642                                  Object *UNUSED(ob),
1643                                  float (*vertexCos)[3])
1644 {
1645         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1646         BMesh *bm = em->bm;
1647         const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
1648         const int cd_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
1649
1650         bmdm->em = em;
1651
1652         DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, bm->totvert,
1653                 bm->totedge, em->tottri, bm->totloop, bm->totface);
1654
1655         /* could also get from the objects mesh directly */
1656         bmdm->dm.cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
1657
1658         bmdm->dm.getVertCos = emDM_getVertCos;
1659         bmdm->dm.getMinMax = emDM_getMinMax;
1660
1661         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1662         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1663         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1664         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1665         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1666
1667         bmdm->dm.getNumVerts = emDM_getNumVerts;
1668         bmdm->dm.getNumEdges = emDM_getNumEdges;
1669         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1670         bmdm->dm.getNumLoops = emDM_getNumLoops;
1671         bmdm->dm.getNumPolys = emDM_getNumPolys;
1672
1673         bmdm->dm.getVert = emDM_getVert;
1674         bmdm->dm.getVertCo = emDM_getVertCo;
1675         bmdm->dm.getVertNo = emDM_getVertNo;
1676         bmdm->dm.getPolyNo = emDM_getPolyNo;
1677         bmdm->dm.getEdge = emDM_getEdge;
1678         bmdm->dm.getTessFace = emDM_getTessFace;
1679         bmdm->dm.copyVertArray = emDM_copyVertArray;
1680         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1681         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1682         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1683         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1684
1685         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1686
1687         bmdm->dm.calcNormals = emDM_calcNormals;
1688         bmdm->dm.recalcTessellation = emDM_recalcTessellation;
1689
1690         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1691         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1692         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1693
1694         bmdm->dm.drawEdges = emDM_drawEdges;
1695         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1696         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1697         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1698         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1699         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1700         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1701         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1702         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1703         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1704
1705         bmdm->dm.release = emDM_release;
1706
1707         bmdm->vertexCos = (const float (*)[3])vertexCos;
1708         bmdm->dm.deformedOnly = (vertexCos != NULL);
1709
1710         if (cd_dvert_offset != -1) {
1711                 BMIter iter;
1712                 BMVert *eve;
1713                 int i;
1714
1715                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1716
1717                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1718                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1719                                          BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
1720                 }
1721         }
1722
1723         if (cd_skin_offset != -1) {
1724                 BMIter iter;
1725                 BMVert *eve;
1726                 int i;
1727
1728                 DM_add_vert_layer(&bmdm->dm, CD_MVERT_SKIN, CD_CALLOC, NULL);
1729
1730                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1731                         DM_set_vert_data(&bmdm->dm, i, CD_MVERT_SKIN,
1732                                          BM_ELEM_CD_GET_VOID_P(eve, cd_skin_offset));
1733                 }
1734         }
1735
1736         return (DerivedMesh *)bmdm;
1737 }
1738
1739
1740
1741 /* -------------------------------------------------------------------- */
1742 /* StatVis Functions */
1743
1744 static void axis_from_enum_v3(float v[3], const char axis)
1745 {
1746         zero_v3(v);
1747         if (axis < 3) v[axis]     =  1.0f;
1748         else          v[axis - 3] = -1.0f;
1749 }
1750
1751 static void statvis_calc_overhang(
1752         BMEditMesh *em,
1753         const float (*polyNos)[3],
1754         /* values for calculating */
1755         const float min, const float max, const char axis,
1756         /* result */
1757         unsigned char (*r_face_colors)[4])
1758 {
1759         BMIter iter;
1760         BMesh *bm = em->bm;
1761         BMFace *f;
1762         float dir[3];
1763         int index;
1764         const float minmax_irange = 1.0f / (max - min);
1765
1766         /* fallback */
1767         const char col_fallback[4] = {64, 64, 64, 255};
1768
1769         BLI_assert(min <= max);
1770
1771         axis_from_enum_v3(dir, axis);
1772
1773         if (LIKELY(em->ob)) {
1774                 mul_transposed_mat3_m4_v3(em->ob->obmat, dir);
1775                 normalize_v3(dir);
1776         }
1777
1778         /* now convert into global space */
1779         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
1780                 float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI;
1781
1782                 /* remap */
1783                 if (fac >= min && fac <= max) {
1784                         float fcol[3];
1785                         fac = (fac - min) * minmax_irange;
1786                         fac = 1.0f - fac;
1787                         CLAMP(fac, 0.0f, 1.0f);
1788                         weight_to_rgb(fcol, fac);
1789                         rgb_float_to_uchar(r_face_colors[index], fcol);
1790                 }
1791                 else {
1792                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
1793                 }
1794         }
1795 }
1796
1797 /* so we can use jitter values for face interpolation */
1798 static void uv_from_jitter_v2(float uv[2])
1799 {
1800         uv[0] += 0.5f;
1801         uv[1] += 0.5f;
1802         if (uv[0] + uv[1] > 1.0f) {
1803                 uv[0] = 1.0f - uv[0];
1804                 uv[1] = 1.0f - uv[1];
1805         }
1806
1807         CLAMP(uv[0], 0.0f, 1.0f);
1808         CLAMP(uv[1], 0.0f, 1.0f);
1809 }
1810
1811 static void statvis_calc_thickness(
1812         BMEditMesh *em,
1813         const float (*vertexCos)[3],
1814         /* values for calculating */
1815         const float min, const float max, const int samples,
1816         /* result */
1817         unsigned char (*r_face_colors)[4])
1818 {
1819         const float eps_offset = 0.00002f;  /* values <= 0.00001 give errors */
1820         float *face_dists = (float *)r_face_colors;  /* cheating */
1821         const bool use_jit = samples < 32;
1822         float jit_ofs[32][2];
1823         BMesh *bm = em->bm;
1824         const int tottri = em->tottri;
1825         const float minmax_irange = 1.0f / (max - min);
1826         int i;
1827
1828         struct BMLoop *(*looptris)[3] = em->looptris;
1829
1830         /* fallback */
1831         const char col_fallback[4] = {64, 64, 64, 255};
1832
1833         struct BMBVHTree *bmtree;
1834
1835         BLI_assert(min <= max);
1836
1837         fill_vn_fl(face_dists, em->bm->totface, max);
1838
1839         if (use_jit) {
1840                 int j;
1841                 BLI_assert(samples < 32);
1842                 BLI_jitter_init(jit_ofs[0], samples);
1843
1844                 for (j = 0; j < samples; j++) {
1845                         uv_from_jitter_v2(jit_ofs[j]);
1846                 }
1847         }
1848
1849         BM_mesh_elem_index_ensure(bm, BM_FACE);
1850         if (vertexCos) {
1851                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1852         }
1853
1854         bmtree = BKE_bmbvh_new(em, 0, vertexCos, false);
1855
1856         for (i = 0; i < tottri; i++) {
1857                 BMFace *f_hit;
1858                 BMLoop **ltri = looptris[i];
1859                 const int index = BM_elem_index_get(ltri[0]->f);
1860                 const float *cos[3];
1861                 float ray_co[3];
1862                 float ray_no[3];
1863
1864                 if (vertexCos) {
1865                         cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)];
1866                         cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)];
1867                         cos[2] = vertexCos[BM_elem_index_get(ltri[2]->v)];
1868                 }
1869                 else {
1870                         cos[0] = ltri[0]->v->co;
1871                         cos[1] = ltri[1]->v->co;
1872                         cos[2] = ltri[2]->v->co;
1873                 }
1874
1875                 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
1876
1877 #define FACE_RAY_TEST_ANGLE \
1878                 f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, \
1879                                            &dist, NULL, NULL); \
1880                 if (f_hit && dist < face_dists[index]) { \
1881                         float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
1882                         angle_fac = 1.0f - angle_fac; \
1883                         angle_fac = angle_fac * angle_fac * angle_fac; \
1884                         angle_fac = 1.0f - angle_fac; \
1885                         dist /= angle_fac; \
1886                         if (dist < face_dists[index]) { \
1887                                 face_dists[index] = dist; \
1888                         } \
1889                 } (void)0
1890
1891                 if (use_jit) {
1892                         int j;
1893                         for (j = 0; j < samples; j++) {
1894                                 float dist = face_dists[index];
1895                                 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
1896                                 madd_v3_v3fl(ray_co, ray_no, eps_offset);
1897
1898                                 FACE_RAY_TEST_ANGLE;
1899                         }
1900                 }
1901                 else {
1902                         float dist = face_dists[index];
1903                         mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]);
1904                         madd_v3_v3fl(ray_co, ray_no, eps_offset);
1905
1906                         FACE_RAY_TEST_ANGLE;
1907                 }
1908         }
1909
1910         BKE_bmbvh_free(bmtree);
1911
1912         /* convert floats into color! */
1913         for (i = 0; i < bm->totface; i++) {
1914                 float fac = face_dists[i];
1915
1916                 /* important not '<=' */
1917                 if (fac < max) {
1918                         float fcol[3];
1919                         fac = (fac - min) * minmax_irange;
1920                         fac = 1.0f - fac;
1921                         CLAMP(fac, 0.0f, 1.0f);
1922                         weight_to_rgb(fcol, fac);
1923                         rgb_float_to_uchar(r_face_colors[i], fcol);
1924                 }
1925                 else {
1926                         copy_v4_v4_char((char *)r_face_colors[i], (const char *)col_fallback);
1927                 }
1928         }
1929 }
1930
1931 static void statvis_calc_intersect(
1932         BMEditMesh *em,
1933         const float (*vertexCos)[3],
1934         /* result */
1935         unsigned char (*r_face_colors)[4])
1936 {
1937         BMIter iter;
1938         BMesh *bm = em->bm;
1939         BMEdge *e;
1940         int index;
1941
1942         /* fallback */
1943         // const char col_fallback[4] = {64, 64, 64, 255};
1944
1945         struct BMBVHTree *bmtree;
1946
1947         memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
1948
1949         BM_mesh_elem_index_ensure(bm, BM_FACE);
1950         if (vertexCos) {
1951                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1952         }
1953
1954         bmtree = BKE_bmbvh_new(em, 0, vertexCos, false);
1955
1956         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
1957                 BMFace *f_hit;
1958                 float cos[2][3];
1959                 float cos_mid[3];
1960                 float ray_no[3];
1961
1962                 if (e->l == NULL)
1963                         continue;
1964
1965                 if (vertexCos) {
1966                         copy_v3_v3(cos[0], vertexCos[BM_elem_index_get(e->v1)]);
1967                         copy_v3_v3(cos[1], vertexCos[BM_elem_index_get(e->v2)]);
1968                 }
1969                 else {
1970                         copy_v3_v3(cos[0], e->v1->co);
1971                         copy_v3_v3(cos[1], e->v2->co);
1972                 }
1973
1974                 mid_v3_v3v3(cos_mid, cos[0], cos[1]);
1975                 sub_v3_v3v3(ray_no, cos[1], cos[0]);
1976
1977                 f_hit = BKE_bmbvh_find_face_segment(bmtree, cos[0], cos[1],
1978                                                     NULL, NULL, NULL);
1979
1980                 if (f_hit) {
1981                         BMLoop *l_iter, *l_first;
1982                         float fcol[3];
1983
1984                         index = BM_elem_index_get(f_hit);
1985                         weight_to_rgb(fcol, 1.0f);
1986                         rgb_float_to_uchar(r_face_colors[index], fcol);
1987
1988                         l_iter = l_first = e->l;
1989                         do {
1990                                 index = BM_elem_index_get(l_iter->f);
1991                                 weight_to_rgb(fcol, 1.0f);
1992                                 rgb_float_to_uchar(r_face_colors[index], fcol);
1993                         } while ((l_iter = l_iter->radial_next) != l_first);
1994                 }
1995
1996         }
1997
1998         BKE_bmbvh_free(bmtree);
1999 }
2000
2001 static void statvis_calc_distort(
2002         BMEditMesh *em,
2003         const float (*vertexCos)[3], const float (*polyNos)[3],
2004         /* values for calculating */
2005         const float min, const float max,
2006         /* result */
2007         unsigned char (*r_face_colors)[4])
2008 {
2009         BMIter iter;
2010         BMesh *bm = em->bm;
2011         BMFace *f;
2012         const float *f_no;
2013         int index;
2014         const float minmax_irange = 1.0f / (max - min);
2015
2016         /* fallback */
2017         const char col_fallback[4] = {64, 64, 64, 255};
2018
2019         /* now convert into global space */
2020         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2021                 float fac;
2022
2023                 if (f->len == 3) {
2024                         fac = -1.0f;
2025                 }
2026                 else {
2027                         BMLoop *l_iter, *l_first;
2028                         if (vertexCos) {
2029                                 f_no = polyNos[index];
2030                         }
2031                         else {
2032                                 f_no = f->no;
2033                         }
2034
2035                         fac = 0.0f;
2036                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2037                         do {
2038                                 float no_corner[3];
2039                                 if (vertexCos) {
2040                                         normal_tri_v3(no_corner,
2041                                                       vertexCos[BM_elem_index_get(l_iter->prev->v)],
2042                                                       vertexCos[BM_elem_index_get(l_iter->v)],
2043                                                       vertexCos[BM_elem_index_get(l_iter->next->v)]);
2044                                 }
2045                                 else {
2046                                         BM_loop_calc_face_normal(l_iter, no_corner);
2047                                 }
2048                                 /* simple way to detect (what is most likely) concave */
2049                                 if (dot_v3v3(f_no, no_corner) < 0.0f) {
2050                                         negate_v3(no_corner);
2051                                 }
2052                                 fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
2053                         } while ((l_iter = l_iter->next) != l_first);
2054                         fac *= 2.0f;
2055                 }
2056
2057                 /* remap */
2058                 if (fac >= min) {
2059                         float fcol[3];
2060                         fac = (fac - min) * minmax_irange;
2061                         CLAMP(fac, 0.0f, 1.0f);
2062                         weight_to_rgb(fcol, fac);
2063                         rgb_float_to_uchar(r_face_colors[index], fcol);
2064                 }
2065                 else {
2066                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
2067                 }
2068         }
2069 }
2070
2071 static void statvis_calc_sharp(
2072         BMEditMesh *em,
2073         const float (*vertexCos)[3],
2074         /* values for calculating */
2075         const float min, const float max,
2076         /* result */
2077         unsigned char (*r_vert_colors)[4])
2078 {
2079         float *vert_angles = (float *)r_vert_colors;  /* cheating */
2080         BMIter iter;
2081         BMesh *bm = em->bm;
2082         BMEdge *e;
2083         //float f_no[3];
2084         const float minmax_irange = 1.0f / (max - min);
2085         int i;
2086
2087         /* fallback */
2088         const char col_fallback[4] = {64, 64, 64, 255};
2089
2090         (void)vertexCos;  /* TODO */
2091
2092         fill_vn_fl(vert_angles, em->bm->totvert, -M_PI);
2093
2094         /* first assign float values to verts */
2095         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2096                 float angle = BM_edge_calc_face_angle_signed(e);
2097                 float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
2098                 float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
2099                 *col1 = max_ff(*col1, angle);
2100                 *col2 = max_ff(*col2, angle);
2101         }
2102
2103         /* convert floats into color! */
2104         for (i = 0; i < bm->totvert; i++) {
2105                 float fac = vert_angles[i];
2106
2107                 /* important not '<=' */
2108                 if (fac > min) {
2109                         float fcol[3];
2110                         fac = (fac - min) * minmax_irange;
2111                         CLAMP(fac, 0.0f, 1.0f);
2112                         weight_to_rgb(fcol, fac);
2113                         rgb_float_to_uchar(r_vert_colors[i], fcol);
2114                 }
2115                 else {
2116                         copy_v4_v4_char((char *)r_vert_colors[i], (const char *)col_fallback);
2117                 }
2118         }
2119 }
2120
2121 void BKE_editmesh_statvis_calc(BMEditMesh *em, DerivedMesh *dm,
2122                                MeshStatVis *statvis)
2123 {
2124         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2125         BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH);
2126
2127         switch (statvis->type) {
2128                 case SCE_STATVIS_OVERHANG:
2129                 {
2130                         BKE_editmesh_color_ensure(em, BM_FACE);
2131                         statvis_calc_overhang(
2132                                     em, bmdm ? bmdm->polyNos : NULL,
2133                                     statvis->overhang_min / (float)M_PI,
2134                                     statvis->overhang_max / (float)M_PI,
2135                                     statvis->overhang_axis,
2136                                     em->derivedFaceColor);
2137                         break;
2138                 }
2139                 case SCE_STATVIS_THICKNESS:
2140                 {
2141                         const float scale = 1.0f / mat4_to_scale(em->ob->obmat);
2142                         BKE_editmesh_color_ensure(em, BM_FACE);
2143                         statvis_calc_thickness(
2144                                     em, bmdm ? bmdm->vertexCos : NULL,
2145                                     statvis->thickness_min * scale,
2146                                     statvis->thickness_max * scale,
2147                                     statvis->thickness_samples,
2148                                     em->derivedFaceColor);
2149                         break;
2150                 }
2151                 case SCE_STATVIS_INTERSECT:
2152                 {
2153                         BKE_editmesh_color_ensure(em, BM_FACE);
2154                         statvis_calc_intersect(
2155                                     em, bmdm ? bmdm->vertexCos : NULL,
2156                                     em->derivedFaceColor);
2157                         break;
2158                 }
2159                 case SCE_STATVIS_DISTORT:
2160                 {
2161                         BKE_editmesh_color_ensure(em, BM_FACE);
2162
2163                         if (bmdm)
2164                                 emDM_ensurePolyNormals(bmdm);
2165
2166                         statvis_calc_distort(
2167                                 em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL,
2168                                 statvis->distort_min,
2169                                 statvis->distort_max,
2170                                 em->derivedFaceColor);
2171                         break;
2172                 }
2173                 case SCE_STATVIS_SHARP:
2174                 {
2175                         BKE_editmesh_color_ensure(em, BM_VERT);
2176                         statvis_calc_sharp(
2177                                 em, bmdm ? bmdm->vertexCos : NULL,
2178                                 statvis->sharp_min,
2179                                 statvis->sharp_max,
2180                                 /* in this case they are vertex colors */
2181                                 em->derivedVertColor);
2182                         break;
2183                 }
2184         }
2185 }
2186
2187
2188
2189 /* -------------------------------------------------------------------- */
2190 /* Editmesh Vert Coords */
2191
2192 struct CageUserData {
2193         int totvert;
2194         float (*cos_cage)[3];
2195         BLI_bitmap *visit_bitmap;
2196 };
2197
2198 static void cage_mapped_verts_callback(void *userData, int index, const float co[3],
2199                                        const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2200 {
2201         struct CageUserData *data = userData;
2202
2203         if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_GET(data->visit_bitmap, index))) {
2204                 BLI_BITMAP_SET(data->visit_bitmap, index);
2205                 copy_v3_v3(data->cos_cage[index], co);
2206         }
2207 }
2208
2209 float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
2210 {
2211         DerivedMesh *cage, *final;
2212         BLI_bitmap *visit_bitmap;
2213         struct CageUserData data;
2214         float (*cos_cage)[3];
2215
2216         cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, &final, CD_MASK_BAREMESH);
2217         cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
2218
2219         /* when initializing cage verts, we only want the first cage coordinate for each vertex,
2220          * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
2221         visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2222
2223         data.totvert = em->bm->totvert;
2224         data.cos_cage = cos_cage;
2225         data.visit_bitmap = visit_bitmap;
2226
2227         cage->foreachMappedVert(cage, cage_mapped_verts_callback, &data, DM_FOREACH_NOP);
2228
2229         MEM_freeN(visit_bitmap);
2230
2231         if (r_numVerts) {
2232                 *r_numVerts = em->bm->totvert;
2233         }
2234
2235         return cos_cage;
2236 }