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