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