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