Merging r58475 through r58700 from trunk into soc-2013-depsgraph_mt
[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 problbm.
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
892         if (attribs->totorco) {
893                 const float *orco = attribs->orco.array[BM_elem_index_get(eve)];
894                 glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
895         }
896         for (i = 0; i < attribs->tottface; i++) {
897                 const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
898                 glVertexAttrib2fvARB(attribs->tface[i].gl_index, luv->uv);
899         }
900         for (i = 0; i < attribs->totmcol; i++) {
901                 const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
902                 GLubyte col[4];
903                 col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
904                 glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col);
905         }
906         if (attribs->tottang) {
907                 const float *tang = attribs->tang.array[i * 4 + index_in_face];
908                 glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
909         }
910 }
911
912 static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
913                                      DMSetMaterial setMaterial,
914                                      DMSetDrawOptions setDrawOptions,
915                                      void *userData)
916 {
917         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
918         BMEditMesh *em = bmdm->em;
919         BMesh *bm = em->bm;
920         struct BMLoop *(*looptris)[3] = em->looptris;
921         /* add direct access */
922         const float (*vertexCos)[3] = bmdm->vertexCos;
923         const float (*vertexNos)[3];
924         const float (*polyNos)[3];
925
926         BMFace *efa;
927         DMVertexAttribs attribs;
928         GPUVertexAttribs gattribs;
929
930         int i, matnr, new_matnr, do_draw;
931
932         do_draw = FALSE;
933         matnr = -1;
934
935         memset(&attribs, 0, sizeof(attribs));
936
937         emDM_ensureVertNormals(bmdm);
938         emDM_ensurePolyNormals(bmdm);
939         vertexNos = bmdm->vertexNos;
940         polyNos = bmdm->polyNos;
941
942         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
943         glShadeModel(GL_SMOOTH);
944         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
945
946         for (i = 0; i < em->tottri; i++) {
947                 BMLoop **ltri = looptris[i];
948                 int drawSmooth;
949
950                 efa = ltri[0]->f;
951                 drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
952
953                 if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
954                         continue;
955
956                 new_matnr = efa->mat_nr + 1;
957                 if (new_matnr != matnr) {
958                         do_draw = setMaterial(matnr = new_matnr, &gattribs);
959                         if (do_draw)
960                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
961                 }
962
963                 if (do_draw) {
964                         glBegin(GL_TRIANGLES);
965                         if (!drawSmooth) {
966                                 if (vertexCos) glNormal3fv(polyNos[BM_elem_index_get(efa)]);
967                                 else glNormal3fv(efa->no);
968
969                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
970                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
971                                 else glVertex3fv(ltri[0]->v->co);
972
973                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
974                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
975                                 else glVertex3fv(ltri[1]->v->co);
976
977                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
978                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
979                                 else glVertex3fv(ltri[2]->v->co);
980                         }
981                         else {
982                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
983                                 if (vertexCos) {
984                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
985                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
986                                 }
987                                 else {
988                                         glNormal3fv(ltri[0]->v->no);
989                                         glVertex3fv(ltri[0]->v->co);
990                                 }
991
992                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
993                                 if (vertexCos) {
994                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
995                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
996                                 }
997                                 else {
998                                         glNormal3fv(ltri[1]->v->no);
999                                         glVertex3fv(ltri[1]->v->co);
1000                                 }
1001
1002                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
1003                                 if (vertexCos) {
1004                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1005                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1006                                 }
1007                                 else {
1008                                         glNormal3fv(ltri[2]->v->no);
1009                                         glVertex3fv(ltri[2]->v->co);
1010                                 }
1011                         }
1012                         glEnd();
1013                 }
1014         }
1015 }
1016
1017 static void emDM_drawFacesGLSL(DerivedMesh *dm,
1018                                int (*setMaterial)(int, void *attribs))
1019 {
1020         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1021 }
1022
1023 /* emdm_pass_attrib_vertex_glsl's note about em_offset use applies here */
1024 static void emdm_pass_attrib_vertex_mat(DMVertexAttribs *attribs, BMLoop *loop, int index_in_face)
1025 {
1026         BMVert *eve = loop->v;
1027         int i;
1028
1029         if (attribs->totorco) {
1030                 float *orco = attribs->orco.array[BM_elem_index_get(eve)];
1031                 if (attribs->orco.gl_texco)
1032                         glTexCoord3fv(orco);
1033                 else
1034                         glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
1035         }
1036         for (i = 0; i < attribs->tottface; i++) {
1037                 const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
1038                 if (attribs->tface[i].gl_texco)
1039                         glTexCoord2fv(luv->uv);
1040                 else
1041                         glVertexAttrib2fvARB(attribs->tface[i].gl_index, luv->uv);
1042         }
1043         for (i = 0; i < attribs->totmcol; i++) {
1044                 const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
1045                 GLubyte col[4];
1046                 col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
1047                 glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col);
1048         }
1049         if (attribs->tottang) {
1050                 float *tang = attribs->tang.array[i * 4 + index_in_face];
1051                 glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
1052         }
1053 }
1054
1055 static void emDM_drawMappedFacesMat(DerivedMesh *dm,
1056                                     void (*setMaterial)(void *userData, int, void *attribs),
1057                                     bool (*setFace)(void *userData, int index), void *userData)
1058 {
1059         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1060         BMEditMesh *em = bmdm->em;
1061         BMesh *bm = em->bm;
1062         struct BMLoop *(*looptris)[3] = em->looptris;
1063         const float (*vertexCos)[3] = bmdm->vertexCos;
1064         const float (*vertexNos)[3];
1065         const float (*polyNos)[3];
1066         BMFace *efa;
1067         DMVertexAttribs attribs = {{{0}}};
1068         GPUVertexAttribs gattribs;
1069         int i, matnr, new_matnr;
1070
1071         matnr = -1;
1072
1073         emDM_ensureVertNormals(bmdm);
1074         emDM_ensurePolyNormals(bmdm);
1075
1076         vertexNos = bmdm->vertexNos;
1077         polyNos = bmdm->polyNos;
1078
1079         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1080         glShadeModel(GL_SMOOTH);
1081
1082         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
1083
1084         for (i = 0; i < em->tottri; i++) {
1085                 BMLoop **ltri = looptris[i];
1086                 int drawSmooth;
1087
1088                 efa = ltri[0]->f;
1089                 drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1090
1091                 /* face hiding */
1092                 if (setFace && !setFace(userData, BM_elem_index_get(efa)))
1093                         continue;
1094
1095                 /* material */
1096                 new_matnr = efa->mat_nr + 1;
1097                 if (new_matnr != matnr) {
1098                         setMaterial(userData, matnr = new_matnr, &gattribs);
1099                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1100                 }
1101
1102                 /* face */
1103                 glBegin(GL_TRIANGLES);
1104                 if (!drawSmooth) {
1105                         if (vertexCos) glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1106                         else glNormal3fv(efa->no);
1107
1108                         emdm_pass_attrib_vertex_mat(&attribs, ltri[0], 0);
1109                         if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1110                         else glVertex3fv(ltri[0]->v->co);
1111
1112                         emdm_pass_attrib_vertex_mat(&attribs, ltri[1], 1);
1113                         if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1114                         else glVertex3fv(ltri[1]->v->co);
1115
1116                         emdm_pass_attrib_vertex_mat(&attribs, ltri[2], 2);
1117                         if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1118                         else glVertex3fv(ltri[2]->v->co);
1119
1120                 }
1121                 else {
1122                         emdm_pass_attrib_vertex_mat(&attribs, ltri[0], 0);
1123                         if (vertexCos) {
1124                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1125                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1126                         }
1127                         else {
1128                                 glNormal3fv(ltri[0]->v->no);
1129                                 glVertex3fv(ltri[0]->v->co);
1130                         }
1131
1132                         emdm_pass_attrib_vertex_mat(&attribs, ltri[1], 1);
1133                         if (vertexCos) {
1134                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1135                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1136                         }
1137                         else {
1138                                 glNormal3fv(ltri[1]->v->no);
1139                                 glVertex3fv(ltri[1]->v->co);
1140                         }
1141
1142                         emdm_pass_attrib_vertex_mat(&attribs, ltri[2], 2);
1143                         if (vertexCos) {
1144                                 glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1145                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1146                         }
1147                         else {
1148                                 glNormal3fv(ltri[2]->v->no);
1149                                 glVertex3fv(ltri[2]->v->co);
1150                         }
1151                 }
1152                 glEnd();
1153         }
1154 }
1155
1156 static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
1157 {
1158         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1159         BMesh *bm = bmdm->em->bm;
1160         BMVert *eve;
1161         BMIter iter;
1162         int i;
1163
1164         if (bm->totvert) {
1165                 if (bmdm->vertexCos) {
1166                         BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1167                                 minmax_v3v3_v3(r_min, r_max, bmdm->vertexCos[i]);
1168                         }
1169                 }
1170                 else {
1171                         BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1172                                 minmax_v3v3_v3(r_min, r_max, eve->co);
1173                         }
1174                 }
1175         }
1176         else {
1177                 zero_v3(r_min);
1178                 zero_v3(r_max);
1179         }
1180 }
1181 static int emDM_getNumVerts(DerivedMesh *dm)
1182 {
1183         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1184
1185         return bmdm->em->bm->totvert;
1186 }
1187
1188 static int emDM_getNumEdges(DerivedMesh *dm)
1189 {
1190         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1191
1192         return bmdm->em->bm->totedge;
1193 }
1194
1195 static int emDM_getNumTessFaces(DerivedMesh *dm)
1196 {
1197         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1198
1199         return bmdm->em->tottri;
1200 }
1201
1202 static int emDM_getNumLoops(DerivedMesh *dm)
1203 {
1204         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1205
1206         return bmdm->em->bm->totloop;
1207 }
1208
1209 static int emDM_getNumPolys(DerivedMesh *dm)
1210 {
1211         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1212
1213         return bmdm->em->bm->totface;
1214 }
1215
1216 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *r_vert)
1217 {
1218         float *f;
1219
1220         copy_v3_v3(r_vert->co, ev->co);
1221
1222         normal_float_to_short_v3(r_vert->no, ev->no);
1223
1224         r_vert->flag = BM_vert_flag_to_mflag(ev);
1225
1226         if ((f = CustomData_bmesh_get(&bm->vdata, ev->head.data, CD_BWEIGHT))) {
1227                 r_vert->bweight = (unsigned char)((*f) * 255.0f);
1228         }
1229
1230         return 1;
1231 }
1232
1233 static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
1234 {
1235         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1236         BMesh *bm = bmdm->em->bm;
1237         BMVert *ev;
1238
1239         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1240                 BLI_assert(!"error in emDM_getVert");
1241                 return;
1242         }
1243
1244         ev = bmdm->em->vert_index[index];  /* should be EDBM_vert_at_index() */
1245         // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1246
1247         bmvert_to_mvert(bm, ev, r_vert);
1248         if (bmdm->vertexCos)
1249                 copy_v3_v3(r_vert->co, bmdm->vertexCos[index]);
1250 }
1251
1252 static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
1253 {
1254         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1255         BMesh *bm = bmdm->em->bm;
1256
1257         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1258                 BLI_assert(!"error in emDM_getVertCo");
1259                 return;
1260         }
1261
1262         if (bmdm->vertexCos) {
1263                 copy_v3_v3(r_co, bmdm->vertexCos[index]);
1264         }
1265         else {
1266                 BMVert *ev = bmdm->em->vert_index[index];  /* should be EDBM_vert_at_index() */
1267                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1268                 copy_v3_v3(r_co, ev->co);
1269         }
1270 }
1271
1272 static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
1273 {
1274         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1275         BMesh *bm = bmdm->em->bm;
1276
1277         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1278                 BLI_assert(!"error in emDM_getVertNo");
1279                 return;
1280         }
1281
1282
1283         if (bmdm->vertexCos) {
1284                 emDM_ensureVertNormals(bmdm);
1285                 copy_v3_v3(r_no, bmdm->vertexNos[index]);
1286         }
1287         else {
1288                 BMVert *ev = bmdm->em->vert_index[index];  /* should be EDBM_vert_at_index() */
1289                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1290                 copy_v3_v3(r_no, ev->no);
1291         }
1292 }
1293
1294 static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3])
1295 {
1296         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1297         BMesh *bm = bmdm->em->bm;
1298
1299         if (UNLIKELY(index < 0 || index >= bm->totface)) {
1300                 BLI_assert(!"error in emDM_getPolyNo");
1301                 return;
1302         }
1303
1304         if (bmdm->vertexCos) {
1305                 emDM_ensurePolyNormals(bmdm);
1306                 copy_v3_v3(r_no, bmdm->polyNos[index]);
1307         }
1308         else {
1309                 BMFace *efa = bmdm->em->face_index[index];  /* should be EDBM_vert_at_index() */
1310                 // efa = BM_face_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1311                 copy_v3_v3(r_no, efa->no);
1312         }
1313 }
1314
1315 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
1316 {
1317         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1318         BMesh *bm = bmdm->em->bm;
1319         BMEdge *e;
1320         float *f;
1321
1322         if (UNLIKELY(index < 0 || index >= bm->totedge)) {
1323                 BLI_assert(!"error in emDM_getEdge");
1324                 return;
1325         }
1326
1327         e = bmdm->em->edge_index[index];  /* should be EDBM_edge_at_index() */
1328         // e = BM_edge_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1329
1330         r_edge->flag = BM_edge_flag_to_mflag(e);
1331
1332         r_edge->v1 = BM_elem_index_get(e->v1);
1333         r_edge->v2 = BM_elem_index_get(e->v2);
1334
1335         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT))) {
1336                 r_edge->bweight = (unsigned char)((*f) * 255.0f);
1337         }
1338         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE))) {
1339                 r_edge->crease = (unsigned char)((*f) * 255.0f);
1340         }
1341 }
1342
1343 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
1344 {
1345         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1346         BMFace *ef;
1347         BMLoop **ltri;
1348
1349         if (UNLIKELY(index < 0 || index >= bmdm->em->tottri)) {
1350                 BLI_assert(!"error in emDM_getTessFace");
1351                 return;
1352         }
1353
1354         ltri = bmdm->em->looptris[index];
1355
1356         ef = ltri[0]->f;
1357
1358         r_face->mat_nr = (unsigned char) ef->mat_nr;
1359         r_face->flag = BM_face_flag_to_mflag(ef);
1360
1361         r_face->v1 = BM_elem_index_get(ltri[0]->v);
1362         r_face->v2 = BM_elem_index_get(ltri[1]->v);
1363         r_face->v3 = BM_elem_index_get(ltri[2]->v);
1364         r_face->v4 = 0;
1365
1366         test_index_face(r_face, NULL, 0, 3);
1367 }
1368
1369 static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
1370 {
1371         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1372         BMesh *bm = bmdm->em->bm;
1373         BMVert *eve;
1374         BMIter iter;
1375         const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
1376
1377         if (bmdm->vertexCos) {
1378                 int i;
1379
1380                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1381                         copy_v3_v3(r_vert->co, bmdm->vertexCos[i]);
1382                         normal_float_to_short_v3(r_vert->no, eve->no);
1383                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1384
1385                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1386
1387                         r_vert++;
1388                 }
1389         }
1390         else {
1391                 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1392                         copy_v3_v3(r_vert->co, eve->co);
1393                         normal_float_to_short_v3(r_vert->no, eve->no);
1394                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1395
1396                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1397
1398                         r_vert++;
1399                 }
1400         }
1401 }
1402
1403 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
1404 {
1405         BMesh *bm = ((EditDerivedBMesh *)dm)->em->bm;
1406         BMEdge *eed;
1407         BMIter iter;
1408
1409         const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
1410         const int cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
1411
1412         BM_mesh_elem_index_ensure(bm, BM_VERT);
1413
1414         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1415                 r_edge->v1 = BM_elem_index_get(eed->v1);
1416                 r_edge->v2 = BM_elem_index_get(eed->v2);
1417
1418                 r_edge->flag = BM_edge_flag_to_mflag(eed);
1419
1420                 r_edge->crease  = (cd_edge_crease_offset  != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset)  : 0;
1421                 r_edge->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0;
1422
1423                 r_edge++;
1424         }
1425 }
1426
1427 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
1428 {
1429         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1430         BMesh *bm = bmdm->em->bm;
1431         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
1432         BMFace *ef;
1433         int i;
1434
1435         BM_mesh_elem_index_ensure(bm, BM_VERT);
1436
1437         for (i = 0; i < bmdm->em->tottri; i++, r_face++) {
1438                 BMLoop **ltri = looptris[i];
1439                 ef = ltri[0]->f;
1440
1441                 r_face->mat_nr = (unsigned char) ef->mat_nr;
1442
1443                 r_face->flag = BM_face_flag_to_mflag(ef);
1444                 r_face->edcode = 0;
1445
1446                 r_face->v1 = BM_elem_index_get(ltri[0]->v);
1447                 r_face->v2 = BM_elem_index_get(ltri[1]->v);
1448                 r_face->v3 = BM_elem_index_get(ltri[2]->v);
1449                 r_face->v4 = 0;
1450
1451                 test_index_face(r_face, NULL, 0, 3);
1452         }
1453 }
1454
1455 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
1456 {
1457         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1458         BMesh *bm = bmdm->em->bm;
1459         BMIter iter;
1460         BMFace *efa;
1461
1462         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
1463
1464         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1465                 BMLoop *l_iter, *l_first;
1466                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
1467                 do {
1468                         r_loop->v = BM_elem_index_get(l_iter->v);
1469                         r_loop->e = BM_elem_index_get(l_iter->e);
1470                         r_loop++;
1471                 } while ((l_iter = l_iter->next) != l_first);
1472         }
1473 }
1474
1475 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
1476 {
1477         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1478         BMesh *bm = bmdm->em->bm;
1479         BMIter iter;
1480         BMFace *efa;
1481         int i;
1482
1483         i = 0;
1484         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1485                 r_poly->flag = BM_face_flag_to_mflag(efa);
1486                 r_poly->loopstart = i;
1487                 r_poly->totloop = efa->len;
1488                 r_poly->mat_nr = efa->mat_nr;
1489
1490                 r_poly++;
1491                 i += efa->len;
1492         }
1493 }
1494
1495 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1496 {
1497         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1498         BMesh *bm = bmdm->em->bm;
1499         void *datalayer;
1500
1501         datalayer = DM_get_tessface_data_layer(dm, type);
1502         if (datalayer)
1503                 return datalayer;
1504
1505         /* layers are store per face for editmesh, we convert to a temporary
1506          * data layer array in the derivedmesh when these are requested */
1507         if (type == CD_MTFACE || type == CD_MCOL) {
1508                 const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
1509                 int index;
1510                 char *data, *bmdata;
1511                 index = CustomData_get_layer_index(&bm->pdata, type_from);
1512
1513                 if (index != -1) {
1514                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1515                         BMLoop *(*looptris)[3] = bmdm->em->looptris;
1516                         const int size = CustomData_sizeof(type);
1517                         int i, j;
1518
1519                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1520                         index = CustomData_get_layer_index(&dm->faceData, type);
1521                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1522
1523                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1524
1525                         if (type == CD_MTFACE) {
1526                                 const int cd_loop_uv_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
1527                                 const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
1528
1529                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1530                                         BMFace *efa = looptris[i][0]->f;
1531
1532                                         // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
1533                                         bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
1534
1535                                         ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
1536                                         for (j = 0; j < 3; j++) {
1537                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
1538                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
1539                                                 copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
1540                                         }
1541                                 }
1542                         }
1543                         else {
1544                                 const int cd_loop_color_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
1545                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1546                                         for (j = 0; j < 3; j++) {
1547                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
1548                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
1549                                                 MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
1550                                         }
1551                                 }
1552                         }
1553                 }
1554         }
1555
1556         return datalayer;
1557 }
1558
1559 static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3])
1560 {
1561         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1562         BMesh *bm = bmdm->em->bm;
1563         BMVert *eve;
1564         BMIter iter;
1565         int i;
1566
1567         if (bmdm->vertexCos) {
1568                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1569                         copy_v3_v3(r_cos[i], bmdm->vertexCos[i]);
1570                 }
1571         }
1572         else {
1573                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1574                         copy_v3_v3(r_cos[i], eve->co);
1575                 }
1576         }
1577 }
1578
1579 static void emDM_release(DerivedMesh *dm)
1580 {
1581         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1582
1583         if (DM_release(dm)) {
1584                 if (bmdm->vertexCos) {
1585                         MEM_freeN((void *)bmdm->vertexCos);
1586                         if (bmdm->vertexNos) {
1587                                 MEM_freeN((void *)bmdm->vertexNos);
1588                         }
1589                         if (bmdm->polyNos) {
1590                                 MEM_freeN((void *)bmdm->polyNos);
1591                         }
1592                 }
1593
1594                 if (bmdm->polyCos) {
1595                         MEM_freeN((void *)bmdm->polyCos);
1596                 }
1597
1598                 MEM_freeN(bmdm);
1599         }
1600 }
1601
1602 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1603 {
1604         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1605
1606         return &bmdm->em->bm->vdata;
1607 }
1608
1609 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1610 {
1611         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1612
1613         return &bmdm->em->bm->edata;
1614 }
1615
1616 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1617 {
1618         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1619
1620         return &bmdm->dm.faceData;
1621 }
1622
1623 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1624 {
1625         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1626
1627         return &bmdm->em->bm->ldata;
1628 }
1629
1630 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1631 {
1632         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1633
1634         return &bmdm->em->bm->pdata;
1635 }
1636
1637
1638 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
1639                                  Object *UNUSED(ob),
1640                                  float (*vertexCos)[3])
1641 {
1642         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1643         BMesh *bm = em->bm;
1644         const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
1645         const int cd_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
1646
1647         bmdm->em = em;
1648
1649         DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, bm->totvert,
1650                 bm->totedge, em->tottri, bm->totloop, bm->totface);
1651
1652         /* could also get from the objects mesh directly */
1653         bmdm->dm.cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
1654
1655         bmdm->dm.getVertCos = emDM_getVertCos;
1656         bmdm->dm.getMinMax = emDM_getMinMax;
1657
1658         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1659         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1660         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1661         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1662         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1663
1664         bmdm->dm.getNumVerts = emDM_getNumVerts;
1665         bmdm->dm.getNumEdges = emDM_getNumEdges;
1666         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1667         bmdm->dm.getNumLoops = emDM_getNumLoops;
1668         bmdm->dm.getNumPolys = emDM_getNumPolys;
1669
1670         bmdm->dm.getVert = emDM_getVert;
1671         bmdm->dm.getVertCo = emDM_getVertCo;
1672         bmdm->dm.getVertNo = emDM_getVertNo;
1673         bmdm->dm.getPolyNo = emDM_getPolyNo;
1674         bmdm->dm.getEdge = emDM_getEdge;
1675         bmdm->dm.getTessFace = emDM_getTessFace;
1676         bmdm->dm.copyVertArray = emDM_copyVertArray;
1677         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1678         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1679         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1680         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1681
1682         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1683
1684         bmdm->dm.calcNormals = emDM_calcNormals;
1685         bmdm->dm.recalcTessellation = emDM_recalcTessellation;
1686
1687         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1688         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1689         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1690
1691         bmdm->dm.drawEdges = emDM_drawEdges;
1692         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1693         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1694         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1695         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1696         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1697         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1698         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1699         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1700         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1701
1702         bmdm->dm.release = emDM_release;
1703
1704         bmdm->vertexCos = (const float (*)[3])vertexCos;
1705         bmdm->dm.deformedOnly = (vertexCos != NULL);
1706
1707         if (cd_dvert_offset != -1) {
1708                 BMIter iter;
1709                 BMVert *eve;
1710                 int i;
1711
1712                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1713
1714                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1715                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1716                                          BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
1717                 }
1718         }
1719
1720         if (cd_skin_offset != -1) {
1721                 BMIter iter;
1722                 BMVert *eve;
1723                 int i;
1724
1725                 DM_add_vert_layer(&bmdm->dm, CD_MVERT_SKIN, CD_CALLOC, NULL);
1726
1727                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1728                         DM_set_vert_data(&bmdm->dm, i, CD_MVERT_SKIN,
1729                                          BM_ELEM_CD_GET_VOID_P(eve, cd_skin_offset));
1730                 }
1731         }
1732
1733         return (DerivedMesh *)bmdm;
1734 }
1735
1736
1737
1738 /* -------------------------------------------------------------------- */
1739 /* StatVis Functions */
1740
1741 static void axis_from_enum_v3(float v[3], const char axis)
1742 {
1743         zero_v3(v);
1744         if (axis < 3) v[axis]     =  1.0f;
1745         else          v[axis - 3] = -1.0f;
1746 }
1747
1748 static void statvis_calc_overhang(
1749         BMEditMesh *em,
1750         const float (*polyNos)[3],
1751         /* values for calculating */
1752         const float min, const float max, const char axis,
1753         /* result */
1754         unsigned char (*r_face_colors)[4])
1755 {
1756         BMIter iter;
1757         BMesh *bm = em->bm;
1758         BMFace *f;
1759         float dir[3];
1760         int index;
1761         const float minmax_irange = 1.0f / (max - min);
1762
1763         /* fallback */
1764         const char col_fallback[4] = {64, 64, 64, 255};
1765
1766         BLI_assert(min <= max);
1767
1768         axis_from_enum_v3(dir, axis);
1769
1770         if (LIKELY(em->ob)) {
1771                 mul_transposed_mat3_m4_v3(em->ob->obmat, dir);
1772                 normalize_v3(dir);
1773         }
1774
1775         /* now convert into global space */
1776         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
1777                 float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI;
1778
1779                 /* remap */
1780                 if (fac >= min && fac <= max) {
1781                         float fcol[3];
1782                         fac = (fac - min) * minmax_irange;
1783                         fac = 1.0f - fac;
1784                         CLAMP(fac, 0.0f, 1.0f);
1785                         weight_to_rgb(fcol, fac);
1786                         rgb_float_to_uchar(r_face_colors[index], fcol);
1787                 }
1788                 else {
1789                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
1790                 }
1791         }
1792 }
1793
1794 /* so we can use jitter values for face interpolation */
1795 static void uv_from_jitter_v2(float uv[2])
1796 {
1797         uv[0] += 0.5f;
1798         uv[1] += 0.5f;
1799         if (uv[0] + uv[1] > 1.0f) {
1800                 uv[0] = 1.0f - uv[0];
1801                 uv[1] = 1.0f - uv[1];
1802         }
1803
1804         CLAMP(uv[0], 0.0f, 1.0f);
1805         CLAMP(uv[1], 0.0f, 1.0f);
1806 }
1807
1808 static void statvis_calc_thickness(
1809         BMEditMesh *em,
1810         const float (*vertexCos)[3],
1811         /* values for calculating */
1812         const float min, const float max, const int samples,
1813         /* result */
1814         unsigned char (*r_face_colors)[4])
1815 {
1816         const float eps_offset = 0.00002f;  /* values <= 0.00001 give errors */
1817         float *face_dists = (float *)r_face_colors;  /* cheating */
1818         const bool use_jit = samples < 32;
1819         float jit_ofs[32][2];
1820         BMesh *bm = em->bm;
1821         const int tottri = em->tottri;
1822         const float minmax_irange = 1.0f / (max - min);
1823         int i;
1824
1825         struct BMLoop *(*looptris)[3] = em->looptris;
1826
1827         /* fallback */
1828         const char col_fallback[4] = {64, 64, 64, 255};
1829
1830         struct BMBVHTree *bmtree;
1831
1832         BLI_assert(min <= max);
1833
1834         fill_vn_fl(face_dists, em->bm->totface, max);
1835
1836         if (use_jit) {
1837                 int j;
1838                 BLI_assert(samples < 32);
1839                 BLI_jitter_init(jit_ofs[0], samples);
1840
1841                 for (j = 0; j < samples; j++) {
1842                         uv_from_jitter_v2(jit_ofs[j]);
1843                 }
1844         }
1845
1846         BM_mesh_elem_index_ensure(bm, BM_FACE);
1847         if (vertexCos) {
1848                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1849         }
1850
1851         bmtree = BKE_bmbvh_new(em, 0, vertexCos, false);
1852
1853         for (i = 0; i < tottri; i++) {
1854                 BMFace *f_hit;
1855                 BMLoop **ltri = looptris[i];
1856                 const int index = BM_elem_index_get(ltri[0]->f);
1857                 const float *cos[3];
1858                 float ray_co[3];
1859                 float ray_no[3];
1860
1861                 if (vertexCos) {
1862                         cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)];
1863                         cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)];
1864                         cos[2] = vertexCos[BM_elem_index_get(ltri[2]->v)];
1865                 }
1866                 else {
1867                         cos[0] = ltri[0]->v->co;
1868                         cos[1] = ltri[1]->v->co;
1869                         cos[2] = ltri[2]->v->co;
1870                 }
1871
1872                 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
1873
1874 #define FACE_RAY_TEST_ANGLE \
1875                 f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, \
1876                                            &dist, NULL, NULL); \
1877                 if (f_hit && dist < face_dists[index]) { \
1878                         float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
1879                         angle_fac = 1.0f - angle_fac; \
1880                         angle_fac = angle_fac * angle_fac * angle_fac; \
1881                         angle_fac = 1.0f - angle_fac; \
1882                         dist /= angle_fac; \
1883                         if (dist < face_dists[index]) { \
1884                                 face_dists[index] = dist; \
1885                         } \
1886                 } (void)0
1887
1888                 if (use_jit) {
1889                         int j;
1890                         for (j = 0; j < samples; j++) {
1891                                 float dist = face_dists[index];
1892                                 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
1893                                 madd_v3_v3fl(ray_co, ray_no, eps_offset);
1894
1895                                 FACE_RAY_TEST_ANGLE;
1896                         }
1897                 }
1898                 else {
1899                         float dist = face_dists[index];
1900                         mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]);
1901                         madd_v3_v3fl(ray_co, ray_no, eps_offset);
1902
1903                         FACE_RAY_TEST_ANGLE;
1904                 }
1905         }
1906
1907         BKE_bmbvh_free(bmtree);
1908
1909         /* convert floats into color! */
1910         for (i = 0; i < bm->totface; i++) {
1911                 float fac = face_dists[i];
1912
1913                 /* important not '<=' */
1914                 if (fac < max) {
1915                         float fcol[3];
1916                         fac = (fac - min) * minmax_irange;
1917                         fac = 1.0f - fac;
1918                         CLAMP(fac, 0.0f, 1.0f);
1919                         weight_to_rgb(fcol, fac);
1920                         rgb_float_to_uchar(r_face_colors[i], fcol);
1921                 }
1922                 else {
1923                         copy_v4_v4_char((char *)r_face_colors[i], (const char *)col_fallback);
1924                 }
1925         }
1926 }
1927
1928 static void statvis_calc_intersect(
1929         BMEditMesh *em,
1930         const float (*vertexCos)[3],
1931         /* result */
1932         unsigned char (*r_face_colors)[4])
1933 {
1934         BMIter iter;
1935         BMesh *bm = em->bm;
1936         BMEdge *e;
1937         int index;
1938
1939         /* fallback */
1940         // const char col_fallback[4] = {64, 64, 64, 255};
1941
1942         struct BMBVHTree *bmtree;
1943
1944         memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
1945
1946         BM_mesh_elem_index_ensure(bm, BM_FACE);
1947         if (vertexCos) {
1948                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1949         }
1950
1951         bmtree = BKE_bmbvh_new(em, 0, vertexCos, false);
1952
1953         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
1954                 BMFace *f_hit;
1955                 float cos[2][3];
1956                 float cos_mid[3];
1957                 float ray_no[3];
1958
1959                 if (e->l == NULL)
1960                         continue;
1961
1962                 if (vertexCos) {
1963                         copy_v3_v3(cos[0], vertexCos[BM_elem_index_get(e->v1)]);
1964                         copy_v3_v3(cos[1], vertexCos[BM_elem_index_get(e->v2)]);
1965                 }
1966                 else {
1967                         copy_v3_v3(cos[0], e->v1->co);
1968                         copy_v3_v3(cos[1], e->v2->co);
1969                 }
1970
1971                 mid_v3_v3v3(cos_mid, cos[0], cos[1]);
1972                 sub_v3_v3v3(ray_no, cos[1], cos[0]);
1973
1974                 f_hit = BKE_bmbvh_find_face_segment(bmtree, cos[0], cos[1],
1975                                                     NULL, NULL, NULL);
1976
1977                 if (f_hit) {
1978                         BMLoop *l_iter, *l_first;
1979                         float fcol[3];
1980
1981                         index = BM_elem_index_get(f_hit);
1982                         weight_to_rgb(fcol, 1.0f);
1983                         rgb_float_to_uchar(r_face_colors[index], fcol);
1984
1985                         l_iter = l_first = e->l;
1986                         do {
1987                                 index = BM_elem_index_get(l_iter->f);
1988                                 weight_to_rgb(fcol, 1.0f);
1989                                 rgb_float_to_uchar(r_face_colors[index], fcol);
1990                         } while ((l_iter = l_iter->radial_next) != l_first);
1991                 }
1992
1993         }
1994
1995         BKE_bmbvh_free(bmtree);
1996 }
1997
1998 static void statvis_calc_distort(
1999         BMEditMesh *em,
2000         const float (*vertexCos)[3], const float (*polyNos)[3],
2001         /* values for calculating */
2002         const float min, const float max,
2003         /* result */
2004         unsigned char (*r_face_colors)[4])
2005 {
2006         BMIter iter;
2007         BMesh *bm = em->bm;
2008         BMFace *f;
2009         const float *f_no;
2010         int index;
2011         const float minmax_irange = 1.0f / (max - min);
2012
2013         /* fallback */
2014         const char col_fallback[4] = {64, 64, 64, 255};
2015
2016         /* now convert into global space */
2017         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2018                 float fac;
2019
2020                 if (f->len == 3) {
2021                         fac = -1.0f;
2022                 }
2023                 else {
2024                         BMLoop *l_iter, *l_first;
2025                         if (vertexCos) {
2026                                 f_no = polyNos[index];
2027                         }
2028                         else {
2029                                 f_no = f->no;
2030                         }
2031
2032                         fac = 0.0f;
2033                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2034                         do {
2035                                 float no_corner[3];
2036                                 if (vertexCos) {
2037                                         normal_tri_v3(no_corner,
2038                                                       vertexCos[BM_elem_index_get(l_iter->prev->v)],
2039                                                       vertexCos[BM_elem_index_get(l_iter->v)],
2040                                                       vertexCos[BM_elem_index_get(l_iter->next->v)]);
2041                                 }
2042                                 else {
2043                                         BM_loop_calc_face_normal(l_iter, no_corner);
2044                                 }
2045                                 /* simple way to detect (what is most likely) concave */
2046                                 if (dot_v3v3(f_no, no_corner) < 0.0f) {
2047                                         negate_v3(no_corner);
2048                                 }
2049                                 fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
2050                         } while ((l_iter = l_iter->next) != l_first);
2051                         fac *= 2.0f;
2052                 }
2053
2054                 /* remap */
2055                 if (fac >= min) {
2056                         float fcol[3];
2057                         fac = (fac - min) * minmax_irange;
2058                         CLAMP(fac, 0.0f, 1.0f);
2059                         weight_to_rgb(fcol, fac);
2060                         rgb_float_to_uchar(r_face_colors[index], fcol);
2061                 }
2062                 else {
2063                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
2064                 }
2065         }
2066 }
2067
2068 static void statvis_calc_sharp(
2069         BMEditMesh *em,
2070         const float (*vertexCos)[3],
2071         /* values for calculating */
2072         const float min, const float max,
2073         /* result */
2074         unsigned char (*r_vert_colors)[4])
2075 {
2076         float *vert_angles = (float *)r_vert_colors;  /* cheating */
2077         BMIter iter;
2078         BMesh *bm = em->bm;
2079         BMEdge *e;
2080         //float f_no[3];
2081         const float minmax_irange = 1.0f / (max - min);
2082         int i;
2083
2084         /* fallback */
2085         const char col_fallback[4] = {64, 64, 64, 255};
2086
2087         (void)vertexCos;  /* TODO */
2088
2089         fill_vn_fl(vert_angles, em->bm->totvert, -M_PI);
2090
2091         /* first assign float values to verts */
2092         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2093                 float angle = BM_edge_calc_face_angle_signed(e);
2094                 float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
2095                 float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
2096                 *col1 = max_ff(*col1, angle);
2097                 *col2 = max_ff(*col2, angle);
2098         }
2099
2100         /* convert floats into color! */
2101         for (i = 0; i < bm->totvert; i++) {
2102                 float fac = vert_angles[i];
2103
2104                 /* important not '<=' */
2105                 if (fac > min) {
2106                         float fcol[3];
2107                         fac = (fac - min) * minmax_irange;
2108                         CLAMP(fac, 0.0f, 1.0f);
2109                         weight_to_rgb(fcol, fac);
2110                         rgb_float_to_uchar(r_vert_colors[i], fcol);
2111                 }
2112                 else {
2113                         copy_v4_v4_char((char *)r_vert_colors[i], (const char *)col_fallback);
2114                 }
2115         }
2116 }
2117
2118 void BKE_editmesh_statvis_calc(BMEditMesh *em, DerivedMesh *dm,
2119                                MeshStatVis *statvis)
2120 {
2121         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2122         BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH);
2123
2124         switch (statvis->type) {
2125                 case SCE_STATVIS_OVERHANG:
2126                 {
2127                         BKE_editmesh_color_ensure(em, BM_FACE);
2128                         statvis_calc_overhang(
2129                                     em, bmdm ? bmdm->polyNos : NULL,
2130                                     statvis->overhang_min / (float)M_PI,
2131                                     statvis->overhang_max / (float)M_PI,
2132                                     statvis->overhang_axis,
2133                                     em->derivedFaceColor);
2134                         break;
2135                 }
2136                 case SCE_STATVIS_THICKNESS:
2137                 {
2138                         const float scale = 1.0f / mat4_to_scale(em->ob->obmat);
2139                         BKE_editmesh_color_ensure(em, BM_FACE);
2140                         statvis_calc_thickness(
2141                                     em, bmdm ? bmdm->vertexCos : NULL,
2142                                     statvis->thickness_min * scale,
2143                                     statvis->thickness_max * scale,
2144                                     statvis->thickness_samples,
2145                                     em->derivedFaceColor);
2146                         break;
2147                 }
2148                 case SCE_STATVIS_INTERSECT:
2149                 {
2150                         BKE_editmesh_color_ensure(em, BM_FACE);
2151                         statvis_calc_intersect(
2152                                     em, bmdm ? bmdm->vertexCos : NULL,
2153                                     em->derivedFaceColor);
2154                         break;
2155                 }
2156                 case SCE_STATVIS_DISTORT:
2157                 {
2158                         BKE_editmesh_color_ensure(em, BM_FACE);
2159
2160                         if (bmdm)
2161                                 emDM_ensurePolyNormals(bmdm);
2162
2163                         statvis_calc_distort(
2164                                 em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL,
2165                                 statvis->distort_min,
2166                                 statvis->distort_max,
2167                                 em->derivedFaceColor);
2168                         break;
2169                 }
2170                 case SCE_STATVIS_SHARP:
2171                 {
2172                         BKE_editmesh_color_ensure(em, BM_VERT);
2173                         statvis_calc_sharp(
2174                                 em, bmdm ? bmdm->vertexCos : NULL,
2175                                 statvis->sharp_min,
2176                                 statvis->sharp_max,
2177                                 /* in this case they are vertex colors */
2178                                 em->derivedVertColor);
2179                         break;
2180                 }
2181         }
2182 }
2183
2184
2185
2186 /* -------------------------------------------------------------------- */
2187 /* Editmesh Vert Coords */
2188
2189 struct CageUserData {
2190         int totvert;
2191         float (*cos_cage)[3];
2192         BLI_bitmap *visit_bitmap;
2193 };
2194
2195 static void cage_mapped_verts_callback(void *userData, int index, const float co[3],
2196                                        const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2197 {
2198         struct CageUserData *data = userData;
2199
2200         if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_GET(data->visit_bitmap, index))) {
2201                 BLI_BITMAP_SET(data->visit_bitmap, index);
2202                 copy_v3_v3(data->cos_cage[index], co);
2203         }
2204 }
2205
2206 float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
2207 {
2208         DerivedMesh *cage, *final;
2209         BLI_bitmap *visit_bitmap;
2210         struct CageUserData data;
2211         float (*cos_cage)[3];
2212
2213         cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, &final, CD_MASK_BAREMESH);
2214         cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
2215
2216         /* when initializing cage verts, we only want the first cage coordinate for each vertex,
2217          * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
2218         visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2219
2220         data.totvert = em->bm->totvert;
2221         data.cos_cage = cos_cage;
2222         data.visit_bitmap = visit_bitmap;
2223
2224         cage->foreachMappedVert(cage, cage_mapped_verts_callback, &data, DM_FOREACH_NOP);
2225
2226         MEM_freeN(visit_bitmap);
2227
2228         if (r_numVerts) {
2229                 *r_numVerts = em->bm->totvert;
2230         }
2231
2232         return cos_cage;
2233 }