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