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