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