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