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