dc1d762d9049ca49377bb2aadaa000881779ded1
[blender.git] / source / blender / editors / space_view3d / drawobject.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) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_camera_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_constraint_types.h"  /* for drawing constraint */
35 #include "DNA_lamp_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meta_types.h"
40 #include "DNA_rigidbody_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_smoke_types.h"
43 #include "DNA_world_types.h"
44 #include "DNA_object_types.h"
45
46 #include "BLI_listbase.h"
47 #include "BLI_link_utils.h"
48 #include "BLI_string.h"
49 #include "BLI_rect.h"
50 #include "BLI_math.h"
51 #include "BLI_memarena.h"
52
53 #include "BKE_anim.h"  /* for the where_on_path function */
54 #include "BKE_armature.h"
55 #include "BKE_camera.h"
56 #include "BKE_constraint.h"  /* for the get_constraint_target function */
57 #include "BKE_curve.h"
58 #include "BKE_DerivedMesh.h"
59 #include "BKE_deform.h"
60 #include "BKE_displist.h"
61 #include "BKE_font.h"
62 #include "BKE_global.h"
63 #include "BKE_image.h"
64 #include "BKE_key.h"
65 #include "BKE_lattice.h"
66 #include "BKE_main.h"
67 #include "BKE_mesh.h"
68 #include "BKE_material.h"
69 #include "BKE_mball.h"
70 #include "BKE_modifier.h"
71 #include "BKE_movieclip.h"
72 #include "BKE_object.h"
73 #include "BKE_paint.h"
74 #include "BKE_particle.h"
75 #include "BKE_pointcache.h"
76 #include "BKE_scene.h"
77 #include "BKE_unit.h"
78 #include "BKE_tracking.h"
79
80 #include "BKE_editmesh.h"
81
82 #include "IMB_imbuf.h"
83 #include "IMB_imbuf_types.h"
84
85 #include "BIF_gl.h"
86 #include "BIF_glutil.h"
87
88 #include "GPU_draw.h"
89 #include "GPU_extensions.h"
90
91 #include "ED_mesh.h"
92 #include "ED_particle.h"
93 #include "ED_screen.h"
94 #include "ED_sculpt.h"
95 #include "ED_types.h"
96
97 #include "UI_resources.h"
98 #include "UI_interface_icons.h"
99
100 #include "WM_api.h"
101 #include "BLF_api.h"
102
103 #include "view3d_intern.h"  /* bad level include */
104
105 /* Workaround for sequencer scene render mode.
106  *
107  * Strips doesn't use DAG to update objects or so, which
108  * might lead to situations when object is drawing without
109  * curve cache ready.
110  *
111  * Ideally we don't want to evaluate objects from drawing,
112  * but it'll require some major sequencer re-design. So
113  * for now just fallback to legacy behaior with calling
114  * display ist creating from draw().
115  */
116 #define SEQUENCER_DAG_WORKAROUND
117
118 typedef enum eWireDrawMode {
119         OBDRAW_WIRE_OFF = 0,
120         OBDRAW_WIRE_ON = 1,
121         OBDRAW_WIRE_ON_DEPTH = 2
122 } eWireDrawMode;
123
124 typedef struct drawDMVerts_userData {
125         BMesh *bm;
126
127         BMVert *eve_act;
128         char sel;
129
130         /* cached theme values */
131         unsigned char th_editmesh_active[4];
132         unsigned char th_vertex_select[4];
133         unsigned char th_vertex[4];
134         unsigned char th_skin_root[4];
135         float th_vertex_size;
136
137         /* for skin node drawing */
138         int cd_vskin_offset;
139         float imat[4][4];
140 } drawDMVerts_userData;
141
142 typedef struct drawDMEdgesSel_userData {
143         BMesh *bm;
144
145         unsigned char *baseCol, *selCol, *actCol;
146         BMEdge *eed_act;
147 } drawDMEdgesSel_userData;
148
149 typedef struct drawDMFacesSel_userData {
150 #ifdef WITH_FREESTYLE
151         unsigned char *cols[4];
152 #else
153         unsigned char *cols[3];
154 #endif
155
156         DerivedMesh *dm;
157         BMesh *bm;
158
159         BMFace *efa_act;
160         int *orig_index_mf_to_mpoly;
161         int *orig_index_mp_to_orig;
162 } drawDMFacesSel_userData;
163
164 typedef struct drawDMNormal_userData {
165         BMesh *bm;
166         int uniform_scale;
167         float normalsize;
168         float tmat[3][3];
169         float imat[3][3];
170 } drawDMNormal_userData;
171
172 typedef struct bbsObmodeMeshVerts_userData {
173         void *offset;
174         MVert *mvert;
175 } bbsObmodeMeshVerts_userData;
176
177 typedef struct drawDMLayer_userData {
178         BMesh *bm;
179         int cd_layer_offset;
180 } drawDMLayer_userData;
181
182 static void draw_bounding_volume(Object *ob, char type);
183
184 static void drawcube_size(float size);
185 static void drawcircle_size(float size);
186 static void draw_empty_sphere(float size);
187 static void draw_empty_cone(float size);
188
189 static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
190 {
191         float col_wire[3], col_bg[3], col[3];
192
193         rgb_uchar_to_float(col_wire, ob_wire_col);
194
195         UI_GetThemeColor3fv(theme_id, col_bg);
196         interp_v3_v3v3(col, col_bg, col_wire, fac);
197         glColor3fv(col);
198 }
199
200 /* this condition has been made more complex since editmode can draw textures */
201 bool check_object_draw_texture(Scene *scene, View3D *v3d, const char drawtype)
202 {
203         /* texture and material draw modes */
204         if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) {
205                 return true;
206         }
207
208         /* textured solid */
209         if ((v3d->drawtype == OB_SOLID) &&
210             (v3d->flag2 & V3D_SOLID_TEX) &&
211             (BKE_scene_use_new_shading_nodes(scene) == false))
212         {
213                 return true;
214         }
215         
216         if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) {
217                 return true;
218         }
219         
220         return false;
221 }
222
223 static bool check_object_draw_editweight(Mesh *me, DerivedMesh *finalDM)
224 {
225         if (me->drawflag & ME_DRAWEIGHT) {
226                 /* editmesh handles its own weight drawing */
227                 if (finalDM->type != DM_TYPE_EDITBMESH) {
228                         return true;
229                 }
230         }
231
232         return false;
233 }
234
235 static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
236 {
237         if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
238                 return false;
239
240         if (G.f & G_BACKBUFSEL)
241                 return false;
242
243         if ((vd->flag & V3D_ZBUF_SELECT) == 0)
244                 return true;
245
246         /* if its drawing textures with zbuf sel, then don't draw dots */
247         if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
248                 return false;
249
250         if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
251                 return false;
252
253         return true;
254 }
255
256 /* ************************ */
257
258 /* check for glsl drawing */
259
260 bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
261 {
262         if (!GPU_glsl_support())
263                 return false;
264         if (G.f & G_PICKSEL)
265                 return false;
266         if (!check_object_draw_texture(scene, v3d, dt))
267                 return false;
268         if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
269                 return false;
270         
271         if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
272                 return true;
273         
274         if (BKE_scene_use_new_shading_nodes(scene))
275                 return false;
276         
277         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
278 }
279
280 static bool check_alpha_pass(Base *base)
281 {
282         if (base->flag & OB_FROMDUPLI)
283                 return false;
284
285         if (G.f & G_PICKSEL)
286                 return false;
287
288         if (base->object->mode & OB_MODE_ALL_PAINT)
289                 return false;
290
291         return (base->object->dtx & OB_DRAWTRANSP);
292 }
293
294 /***/
295 static const unsigned int colortab[] = {
296         0x0, 0x403000, 0xFFFF88
297 };
298
299 /* ----------------- OpenGL Circle Drawing - Tables for Optimized Drawing Speed ------------------ */
300 /* 32 values of sin function (still same result!) */
301 #define CIRCLE_RESOL 32
302
303 static const float sinval[CIRCLE_RESOL] = {
304         0.00000000,
305         0.20129852,
306         0.39435585,
307         0.57126821,
308         0.72479278,
309         0.84864425,
310         0.93775213,
311         0.98846832,
312         0.99871650,
313         0.96807711,
314         0.89780453,
315         0.79077573,
316         0.65137248,
317         0.48530196,
318         0.29936312,
319         0.10116832,
320         -0.10116832,
321         -0.29936312,
322         -0.48530196,
323         -0.65137248,
324         -0.79077573,
325         -0.89780453,
326         -0.96807711,
327         -0.99871650,
328         -0.98846832,
329         -0.93775213,
330         -0.84864425,
331         -0.72479278,
332         -0.57126821,
333         -0.39435585,
334         -0.20129852,
335         0.00000000
336 };
337
338 /* 32 values of cos function (still same result!) */
339 static const float cosval[CIRCLE_RESOL] = {
340         1.00000000,
341         0.97952994,
342         0.91895781,
343         0.82076344,
344         0.68896691,
345         0.52896401,
346         0.34730525,
347         0.15142777,
348         -0.05064916,
349         -0.25065253,
350         -0.44039415,
351         -0.61210598,
352         -0.75875812,
353         -0.87434661,
354         -0.95413925,
355         -0.99486932,
356         -0.99486932,
357         -0.95413925,
358         -0.87434661,
359         -0.75875812,
360         -0.61210598,
361         -0.44039415,
362         -0.25065253,
363         -0.05064916,
364         0.15142777,
365         0.34730525,
366         0.52896401,
367         0.68896691,
368         0.82076344,
369         0.91895781,
370         0.97952994,
371         1.00000000
372 };
373
374 static void draw_xyz_wire(const float c[3], float size, int axis)
375 {
376         float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
377         float dim = size * 0.1f;
378         float dx[3], dy[3], dz[3];
379
380         dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f;
381         dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f;
382         dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim;
383
384         switch (axis) {
385                 case 0:     /* x axis */
386                         glBegin(GL_LINES);
387                         
388                         /* bottom left to top right */
389                         sub_v3_v3v3(v1, c, dx);
390                         sub_v3_v3(v1, dy);
391                         add_v3_v3v3(v2, c, dx);
392                         add_v3_v3(v2, dy);
393                         
394                         glVertex3fv(v1);
395                         glVertex3fv(v2);
396                         
397                         /* top left to bottom right */
398                         mul_v3_fl(dy, 2.f);
399                         add_v3_v3(v1, dy);
400                         sub_v3_v3(v2, dy);
401                         
402                         glVertex3fv(v1);
403                         glVertex3fv(v2);
404                         
405                         glEnd();
406                         break;
407                 case 1:     /* y axis */
408                         glBegin(GL_LINES);
409                         
410                         /* bottom left to top right */
411                         mul_v3_fl(dx, 0.75f);
412                         sub_v3_v3v3(v1, c, dx);
413                         sub_v3_v3(v1, dy);
414                         add_v3_v3v3(v2, c, dx);
415                         add_v3_v3(v2, dy);
416                         
417                         glVertex3fv(v1);
418                         glVertex3fv(v2);
419                         
420                         /* top left to center */
421                         mul_v3_fl(dy, 2.f);
422                         add_v3_v3(v1, dy);
423                         copy_v3_v3(v2, c);
424                         
425                         glVertex3fv(v1);
426                         glVertex3fv(v2);
427                         
428                         glEnd();
429                         break;
430                 case 2:     /* z axis */
431                         glBegin(GL_LINE_STRIP);
432                         
433                         /* start at top left */
434                         sub_v3_v3v3(v1, c, dx);
435                         add_v3_v3v3(v1, c, dz);
436                         
437                         glVertex3fv(v1);
438                         
439                         mul_v3_fl(dx, 2.f);
440                         add_v3_v3(v1, dx);
441
442                         glVertex3fv(v1);
443                         
444                         mul_v3_fl(dz, 2.f);
445                         sub_v3_v3(v1, dx);
446                         sub_v3_v3(v1, dz);
447                         
448                         glVertex3fv(v1);
449                         
450                         add_v3_v3(v1, dx);
451                 
452                         glVertex3fv(v1);
453                         
454                         glEnd();
455                         break;
456         }
457         
458 }
459
460 void drawaxes(float size, char drawtype)
461 {
462         int axis;
463         float v1[3] = {0.0, 0.0, 0.0};
464         float v2[3] = {0.0, 0.0, 0.0};
465         float v3[3] = {0.0, 0.0, 0.0};
466         
467         switch (drawtype) {
468
469                 case OB_PLAINAXES:
470                         for (axis = 0; axis < 3; axis++) {
471                                 glBegin(GL_LINES);
472
473                                 v1[axis] = size;
474                                 v2[axis] = -size;
475                                 glVertex3fv(v1);
476                                 glVertex3fv(v2);
477
478                                 /* reset v1 & v2 to zero */
479                                 v1[axis] = v2[axis] = 0.0f;
480
481                                 glEnd();
482                         }
483                         break;
484                 case OB_SINGLE_ARROW:
485
486                         glBegin(GL_LINES);
487                         /* in positive z direction only */
488                         v1[2] = size;
489                         glVertex3fv(v1);
490                         glVertex3fv(v2);
491                         glEnd();
492
493                         /* square pyramid */
494                         glBegin(GL_TRIANGLES);
495
496                         v2[0] = size * 0.035f; v2[1] = size * 0.035f;
497                         v3[0] = size * -0.035f; v3[1] = size * 0.035f;
498                         v2[2] = v3[2] = size * 0.75f;
499
500                         for (axis = 0; axis < 4; axis++) {
501                                 if (axis % 2 == 1) {
502                                         v2[0] = -v2[0];
503                                         v3[1] = -v3[1];
504                                 }
505                                 else {
506                                         v2[1] = -v2[1];
507                                         v3[0] = -v3[0];
508                                 }
509
510                                 glVertex3fv(v1);
511                                 glVertex3fv(v2);
512                                 glVertex3fv(v3);
513
514                         }
515                         glEnd();
516
517                         break;
518                 case OB_CUBE:
519                         drawcube_size(size);
520                         break;
521
522                 case OB_CIRCLE:
523                         drawcircle_size(size);
524                         break;
525
526                 case OB_EMPTY_SPHERE:
527                         draw_empty_sphere(size);
528                         break;
529
530                 case OB_EMPTY_CONE:
531                         draw_empty_cone(size);
532                         break;
533
534                 case OB_ARROWS:
535                 default:
536                 {
537                         for (axis = 0; axis < 3; axis++) {
538                                 const int arrow_axis = (axis == 0) ? 1 : 0;
539
540                                 glBegin(GL_LINES);
541
542                                 v2[axis] = size;
543                                 glVertex3fv(v1);
544                                 glVertex3fv(v2);
545                                 
546                                 v1[axis] = size * 0.85f;
547                                 v1[arrow_axis] = -size * 0.08f;
548                                 glVertex3fv(v1);
549                                 glVertex3fv(v2);
550                                 
551                                 v1[arrow_axis] = size * 0.08f;
552                                 glVertex3fv(v1);
553                                 glVertex3fv(v2);
554
555                                 glEnd();
556                                 
557                                 v2[axis] += size * 0.125f;
558
559                                 draw_xyz_wire(v2, size, axis);
560
561
562                                 /* reset v1 & v2 to zero */
563                                 v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
564                         }
565                         break;
566                 }
567         }
568 }
569
570
571 /* Function to draw an Image on a empty Object */
572 static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
573 {
574         Image *ima = (Image *)ob->data;
575         ImBuf *ibuf = BKE_image_acquire_ibuf(ima, ob->iuser, NULL);
576
577         float scale, ofs_x, ofs_y, sca_x, sca_y;
578         int ima_x, ima_y;
579
580         if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
581                 IMB_rect_from_float(ibuf);
582         }
583
584         /* Get the buffer dimensions so we can fallback to fake ones */
585         if (ibuf && ibuf->rect) {
586                 ima_x = ibuf->x;
587                 ima_y = ibuf->y;
588         }
589         else {
590                 ima_x = 1;
591                 ima_y = 1;
592         }
593
594         /* Get the image aspect even if the buffer is invalid */
595         if (ima) {
596                 if (ima->aspx > ima->aspy) {
597                         sca_x = 1.0f;
598                         sca_y = ima->aspy / ima->aspx;
599                 }
600                 else if (ima->aspx < ima->aspy) {
601                         sca_x = ima->aspx / ima->aspy;
602                         sca_y = 1.0f;
603                 }
604                 else {
605                         sca_x = 1.0f;
606                         sca_y = 1.0f;
607                 }
608         }
609         else {
610                 sca_x = 1.0f;
611                 sca_y = 1.0f;
612         }
613
614         /* Calculate the scale center based on objects origin */
615         ofs_x = ob->ima_ofs[0] * ima_x;
616         ofs_y = ob->ima_ofs[1] * ima_y;
617
618         glMatrixMode(GL_MODELVIEW);
619         glPushMatrix();
620
621         /* Make sure we are drawing at the origin */
622         glTranslatef(0.0f,  0.0f,  0.0f);
623
624         /* Calculate Image scale */
625         scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y));
626
627         /* Set the object scale */
628         glScalef(scale * sca_x, scale * sca_y, 1.0f);
629
630         if (ibuf && ibuf->rect) {
631                 const bool use_clip = (U.glalphaclip != 1.0f);
632                 int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP ) ? GL_NEAREST : GL_LINEAR;
633                 /* Setup GL params */
634                 glEnable(GL_BLEND);
635                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
636
637                 if (use_clip) {
638                         glEnable(GL_ALPHA_TEST);
639                         glAlphaFunc(GL_GREATER, U.glalphaclip);
640                 }
641
642                 /* Use the object color and alpha */
643                 glColor4fv(ob->col);
644
645                 /* Draw the Image on the screen */
646                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect);
647                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
648
649                 glDisable(GL_BLEND);
650
651                 if (use_clip) {
652                         glDisable(GL_ALPHA_TEST);
653                         glAlphaFunc(GL_GREATER, 0.0f);
654                 }
655         }
656
657         if ((dflag & DRAW_CONSTCOLOR) == 0) {
658                 glColor3ubv(ob_wire_col);
659         }
660
661         /* Calculate the outline vertex positions */
662         glBegin(GL_LINE_LOOP);
663         glVertex2f(ofs_x, ofs_y);
664         glVertex2f(ofs_x + ima_x, ofs_y);
665         glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
666         glVertex2f(ofs_x, ofs_y + ima_y);
667         glEnd();
668
669
670         /* Reset GL settings */
671         glMatrixMode(GL_MODELVIEW);
672         glPopMatrix();
673
674         BKE_image_release_ibuf(ima, ibuf, NULL);
675 }
676
677 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[4][4])
678 {
679         float vx[3], vy[3];
680         float *viter = (float *)verts;
681         unsigned int a;
682
683         mul_v3_v3fl(vx, tmat[0], rad);
684         mul_v3_v3fl(vy, tmat[1], rad);
685
686         for (a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
687                 viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
688                 viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
689                 viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
690         }
691 }
692
693 void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4])
694 {
695         float verts[CIRCLE_RESOL][3];
696
697         circball_array_fill(verts, cent, rad, tmat);
698
699         glEnableClientState(GL_VERTEX_ARRAY);
700         glVertexPointer(3, GL_FLOAT, 0, verts);
701         glDrawArrays(mode, 0, CIRCLE_RESOL);
702         glDisableClientState(GL_VERTEX_ARRAY);
703 }
704
705 /* circle for object centers, special_color is for library or ob users */
706 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
707 {
708         const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
709         float verts[CIRCLE_RESOL][3];
710
711         /* using gldepthfunc guarantees that it does write z values,
712          * but not checks for it, so centers remain visible independent order of drawing */
713         if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
714         glEnable(GL_BLEND);
715         
716         if (special_color) {
717                 if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
718
719                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
720         }
721         else {
722                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
723                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
724                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
725         }
726
727         circball_array_fill(verts, co, size, rv3d->viewinv);
728
729         /* enable vertex array */
730         glEnableClientState(GL_VERTEX_ARRAY);
731         glVertexPointer(3, GL_FLOAT, 0, verts);
732
733         /* 1. draw filled, blended polygon */
734         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
735
736         /* 2. draw outline */
737         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
738         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
739
740         /* finish up */
741         glDisableClientState(GL_VERTEX_ARRAY);
742
743         glDisable(GL_BLEND);
744
745         if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
746 }
747
748 /* *********** text drawing for object/particles/armature ************* */
749
750 typedef struct ViewCachedString {
751         struct ViewCachedString *next;
752         float vec[3];
753         union {
754                 unsigned char ub[4];
755                 int pack;
756         } col;
757         short sco[2];
758         short xoffs;
759         short flag;
760         int str_len, pad;
761         /* str is allocated past the end */
762 } ViewCachedString;
763
764 /* one arena for all 3 string lists */
765 static MemArena         *g_v3d_strings_arena = NULL;
766 static ViewCachedString *g_v3d_strings[3] = {NULL, NULL, NULL};
767 static int g_v3d_string_level = -1;
768
769 void view3d_cached_text_draw_begin(void)
770 {
771         g_v3d_string_level++;
772
773         BLI_assert(g_v3d_string_level >= 0);
774
775         if (g_v3d_string_level == 0) {
776                 BLI_assert(g_v3d_strings_arena == NULL);
777         }
778 }
779
780 void view3d_cached_text_draw_add(const float co[3],
781                                  const char *str, const size_t str_len,
782                                  short xoffs, short flag,
783                                  const unsigned char col[4])
784 {
785         int alloc_len = str_len + 1;
786         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
787         ViewCachedString *vos;
788
789         BLI_assert(str_len == strlen(str));
790
791         if (g_v3d_strings_arena == NULL) {
792                 g_v3d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
793         }
794
795         vos = BLI_memarena_alloc(g_v3d_strings_arena, sizeof(ViewCachedString) + alloc_len);
796
797         BLI_LINKS_PREPEND(g_v3d_strings[g_v3d_string_level], vos);
798
799         copy_v3_v3(vos->vec, co);
800         copy_v4_v4_char((char *)vos->col.ub, (const char *)col);
801         vos->xoffs = xoffs;
802         vos->flag = flag;
803         vos->str_len = str_len;
804
805         /* allocate past the end */
806         memcpy(vos + 1, str, alloc_len);
807 }
808
809 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4])
810 {
811         RegionView3D *rv3d = ar->regiondata;
812         ViewCachedString *vos;
813         int tot = 0;
814         
815         BLI_assert(g_v3d_string_level >= 0 && g_v3d_string_level <= 2);
816
817         /* project first and test */
818         for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
819                 if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
820                         mul_m4_v3(mat, vos->vec);
821
822                 if (ED_view3d_project_short_ex(ar,
823                                                (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
824                                                (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
825                                                vos->vec, vos->sco,
826                                                V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
827                 {
828                         tot++;
829                 }
830                 else {
831                         vos->sco[0] = IS_CLIPPED;
832                 }
833         }
834
835         if (tot) {
836                 int col_pack_prev = 0;
837
838 #if 0
839                 bglMats mats; /* ZBuffer depth vars */
840                 double ux, uy, uz;
841                 float depth;
842
843                 if (v3d->zbuf)
844                         bgl_get_mats(&mats);
845 #endif
846                 if (rv3d->rflag & RV3D_CLIPPING) {
847                         ED_view3d_clipping_disable();
848                 }
849
850                 glMatrixMode(GL_PROJECTION);
851                 glPushMatrix();
852                 glMatrixMode(GL_MODELVIEW);
853                 glPushMatrix();
854                 ED_region_pixelspace(ar);
855                 
856                 if (depth_write) {
857                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
858                 }
859                 else {
860                         glDepthMask(0);
861                 }
862                 
863                 for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
864                         if (vos->sco[0] != IS_CLIPPED) {
865                                 const char *str = (char *)(vos + 1);
866
867                                 if (col_pack_prev != vos->col.pack) {
868                                         glColor3ubv(vos->col.ub);
869                                         col_pack_prev = vos->col.pack;
870                                 }
871
872                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
873                                  BLF_draw_default_ascii :
874                                  BLF_draw_default
875                                 )( (float)vos->sco[0] + vos->xoffs,
876                                    (float)vos->sco[1],
877                                    (depth_write) ? 0.0f : 2.0f,
878                                    str,
879                                    vos->str_len);
880                         }
881                 }
882
883                 if (depth_write) {
884                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
885                 }
886                 else {
887                         glDepthMask(1);
888                 }
889                 
890                 glMatrixMode(GL_PROJECTION);
891                 glPopMatrix();
892                 glMatrixMode(GL_MODELVIEW);
893                 glPopMatrix();
894
895                 if (rv3d->rflag & RV3D_CLIPPING) {
896                         ED_view3d_clipping_enable();
897                 }
898         }
899
900         g_v3d_strings[g_v3d_string_level] = NULL;
901
902         if (g_v3d_string_level == 0) {
903                 if (g_v3d_strings_arena) {
904                         BLI_memarena_free(g_v3d_strings_arena);
905                         g_v3d_strings_arena = NULL;
906                 }
907         }
908
909         g_v3d_string_level--;
910 }
911
912 /* ******************** primitive drawing ******************* */
913
914 /* draws a cube on given the scaling of the cube, assuming that
915  * all required matrices have been set (used for drawing empties)
916  */
917 static void drawcube_size(float size)
918 {
919         glBegin(GL_LINE_STRIP);
920         glVertex3f(-size, -size, -size); glVertex3f(-size, -size, size);
921         glVertex3f(-size, size, size); glVertex3f(-size, size, -size);
922
923         glVertex3f(-size, -size, -size); glVertex3f(size, -size, -size);
924         glVertex3f(size, -size, size); glVertex3f(size, size, size);
925
926         glVertex3f(size, size, -size); glVertex3f(size, -size, -size);
927         glEnd();
928
929         glBegin(GL_LINE_STRIP);
930         glVertex3f(-size, -size, size); glVertex3f(size, -size, size);
931         glEnd();
932
933         glBegin(GL_LINE_STRIP);
934         glVertex3f(-size, size, size); glVertex3f(size, size, size);
935         glEnd();
936
937         glBegin(GL_LINE_STRIP);
938         glVertex3f(-size, size, -size); glVertex3f(size, size, -size);
939         glEnd();
940 }
941
942 /* this is an unused (old) cube-drawing function based on a given size */
943 #if 0
944 static void drawcube_size(const float size[3])
945 {
946
947         glPushMatrix();
948         glScalef(size[0],  size[1],  size[2]);
949         
950
951         glBegin(GL_LINE_STRIP);
952         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
953         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
954         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
955         glEnd();
956
957         glBegin(GL_LINE_STRIP);
958         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
959         glEnd();
960
961         glBegin(GL_LINE_STRIP);
962         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
963         glEnd();
964
965         glBegin(GL_LINE_STRIP);
966         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
967         glEnd();
968         
969         glPopMatrix();
970 }
971 #endif
972
973 static void drawshadbuflimits(Lamp *la, float mat[4][4])
974 {
975         float sta[3], end[3], lavec[3];
976
977         negate_v3_v3(lavec, mat[2]);
978         normalize_v3(lavec);
979
980         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
981         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
982
983         glBegin(GL_LINE_STRIP);
984         glVertex3fv(sta);
985         glVertex3fv(end);
986         glEnd();
987
988         glPointSize(3.0);
989         bglBegin(GL_POINTS);
990         bglVertex3fv(sta);
991         bglVertex3fv(end);
992         bglEnd();
993         glPointSize(1.0);
994 }
995
996
997
998 static void spotvolume(float lvec[3], float vvec[3], const float inp)
999 {
1000         /* camera is at 0,0,0 */
1001         float temp[3], plane[3], mat1[3][3], mat2[3][3], mat3[3][3], mat4[3][3], q[4], co, si, angle;
1002
1003         normalize_v3(lvec);
1004         normalize_v3(vvec);             /* is this the correct vector ? */
1005
1006         cross_v3_v3v3(temp, vvec, lvec);      /* equation for a plane through vvec en lvec */
1007         cross_v3_v3v3(plane, lvec, temp);     /* a plane perpendicular to this, parrallel with lvec */
1008
1009         /* vectors are exactly aligned, use the X axis, this is arbitrary */
1010         if (normalize_v3(plane) == 0.0f)
1011                 plane[1] = 1.0f;
1012
1013         /* now we've got two equations: one of a cone and one of a plane, but we have
1014          * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
1015
1016         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1017         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1018
1019         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1020         
1021         q[1] =  plane[1];
1022         q[2] = -plane[0];
1023         q[3] =  0;
1024         normalize_v3(&q[1]);
1025
1026         angle = saacos(plane[2]) / 2.0f;
1027         co = cosf(angle);
1028         si = sqrtf(1 - co * co);
1029
1030         q[0] =  co;
1031         q[1] *= si;
1032         q[2] *= si;
1033         q[3] =  0;
1034
1035         quat_to_mat3(mat1, q);
1036
1037         /* rotate lamp vector now over acos(inp) degrees */
1038         copy_v3_v3(vvec, lvec);
1039
1040         unit_m3(mat2);
1041         co = inp;
1042         si = sqrtf(1.0f - inp * inp);
1043
1044         mat2[0][0] =  co;
1045         mat2[1][0] = -si;
1046         mat2[0][1] =  si;
1047         mat2[1][1] =  co;
1048         mul_m3_m3m3(mat3, mat2, mat1);
1049
1050         mat2[1][0] =  si;
1051         mat2[0][1] = -si;
1052         mul_m3_m3m3(mat4, mat2, mat1);
1053         transpose_m3(mat1);
1054
1055         mul_m3_m3m3(mat2, mat1, mat3);
1056         mul_m3_v3(mat2, lvec);
1057         mul_m3_m3m3(mat2, mat1, mat4);
1058         mul_m3_v3(mat2, vvec);
1059
1060         return;
1061 }
1062
1063 static void draw_spot_cone(Lamp *la, float x, float z)
1064 {
1065         z = fabsf(z);
1066
1067         glBegin(GL_TRIANGLE_FAN);
1068         glVertex3f(0.0f, 0.0f, -x);
1069
1070         if (la->mode & LA_SQUARE) {
1071                 glVertex3f(z, z, 0);
1072                 glVertex3f(-z, z, 0);
1073                 glVertex3f(-z, -z, 0);
1074                 glVertex3f(z, -z, 0);
1075                 glVertex3f(z, z, 0);
1076         }
1077         else {
1078                 float angle;
1079                 int a;
1080
1081                 for (a = 0; a < 33; a++) {
1082                         angle = a * M_PI * 2 / (33 - 1);
1083                         glVertex3f(z * cosf(angle), z * sinf(angle), 0);
1084                 }
1085         }
1086
1087         glEnd();
1088 }
1089
1090 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1091 {
1092         glEnable(GL_CULL_FACE);
1093         glEnable(GL_BLEND);
1094         glDepthMask(0);
1095
1096         /* draw backside darkening */
1097         glCullFace(GL_FRONT);
1098
1099         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1100         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1101
1102         draw_spot_cone(la, x, z);
1103
1104         /* draw front side lighting */
1105         glCullFace(GL_BACK);
1106
1107         glBlendFunc(GL_ONE, GL_ONE);
1108         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1109
1110         draw_spot_cone(la, x, z);
1111
1112         /* restore state */
1113         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1114         glDisable(GL_BLEND);
1115         glDepthMask(1);
1116         glDisable(GL_CULL_FACE);
1117         glCullFace(GL_BACK);
1118 }
1119
1120 static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
1121                      const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact)
1122 {
1123         Object *ob = base->object;
1124         const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1125         Lamp *la = ob->data;
1126         float vec[3], lvec[3], vvec[3], circrad, x, y, z;
1127         float lampsize;
1128         float imat[4][4];
1129
1130         unsigned char curcol[4];
1131         unsigned char col[4];
1132         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1133         /* the moment of view3d_draw_transp() call */
1134         const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
1135         const bool drawcone = ((dt > OB_WIRE) &&
1136                                !(G.f & G_PICKSEL) &&
1137                                (la->type == LA_SPOT) &&
1138                                (la->mode & LA_SHOW_CONE) &&
1139                                !(base->flag & OB_FROMDUPLI) &&
1140                                !is_view);
1141
1142         if (drawcone && !v3d->transp) {
1143                 /* in this case we need to draw delayed */
1144                 ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
1145                 return;
1146         }
1147         
1148         /* we first draw only the screen aligned & fixed scale stuff */
1149         glPushMatrix();
1150         glLoadMatrixf(rv3d->viewmat);
1151
1152         /* lets calculate the scale: */
1153         lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
1154
1155         /* and view aligned matrix: */
1156         copy_m4_m4(imat, rv3d->viewinv);
1157         normalize_v3(imat[0]);
1158         normalize_v3(imat[1]);
1159
1160         /* lamp center */
1161         copy_v3_v3(vec, ob->obmat[3]);
1162
1163         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1164                 /* for AA effects */
1165                 curcol[0] = ob_wire_col[0];
1166                 curcol[1] = ob_wire_col[1];
1167                 curcol[2] = ob_wire_col[2];
1168                 curcol[3] = 154;
1169                 glColor4ubv(curcol);
1170         }
1171
1172         if (lampsize > 0.0f) {
1173
1174                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1175                         if (ob->id.us > 1) {
1176                                 if (is_obact || (ob->flag & SELECT)) {
1177                                         glColor4ub(0x88, 0xFF, 0xFF, 155);
1178                                 }
1179                                 else {
1180                                         glColor4ub(0x77, 0xCC, 0xCC, 155);
1181                                 }
1182                         }
1183                 }
1184                 
1185                 /* Inner Circle */
1186                 glEnable(GL_BLEND);
1187                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1188                 glDisable(GL_BLEND);
1189                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1190                 
1191                 /* restore */
1192                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1193                         if (ob->id.us > 1)
1194                                 glColor4ubv(curcol);
1195                 }
1196
1197                 /* Outer circle */
1198                 circrad = 3.0f * lampsize;
1199                 setlinestyle(3);
1200
1201                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1202
1203                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1204                 if (la->type != LA_HEMI) {
1205                         if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1206                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
1207                         }
1208                 }
1209         }
1210         else {
1211                 setlinestyle(3);
1212                 circrad = 0.0f;
1213         }
1214         
1215         /* draw the pretty sun rays */
1216         if (la->type == LA_SUN) {
1217                 float v1[3], v2[3], mat[3][3];
1218                 short axis;
1219                 
1220                 /* setup a 45 degree rotation matrix */
1221                 axis_angle_normalized_to_mat3(mat, imat[2], (float)M_PI / 4.0f);
1222
1223                 /* vectors */
1224                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1225                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1226                 
1227                 /* center */
1228                 glTranslatef(vec[0], vec[1], vec[2]);
1229                 
1230                 setlinestyle(3);
1231                 
1232                 glBegin(GL_LINES);
1233                 for (axis = 0; axis < 8; axis++) {
1234                         glVertex3fv(v1);
1235                         glVertex3fv(v2);
1236                         mul_m3_v3(mat, v1);
1237                         mul_m3_v3(mat, v2);
1238                 }
1239                 glEnd();
1240                 
1241                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1242
1243         }
1244         
1245         if (la->type == LA_LOCAL) {
1246                 if (la->mode & LA_SPHERE) {
1247                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1248                 }
1249         }
1250         
1251         glPopMatrix();  /* back in object space */
1252         zero_v3(vec);
1253         
1254         if (is_view) {
1255                 /* skip drawing extra info */
1256         }
1257         else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
1258
1259                 copy_v3_fl3(lvec, 0.0f, 0.0f, 1.0f);
1260                 copy_v3_fl3(vvec, rv3d->persmat[0][2], rv3d->persmat[1][2], rv3d->persmat[2][2]);
1261                 mul_mat3_m4_v3(ob->obmat, vvec);
1262
1263                 x = -la->dist;
1264                 y = cosf(la->spotsize * 0.5f);
1265                 z = x * sqrtf(1.0f - y * y);
1266
1267                 spotvolume(lvec, vvec, y);
1268                 mul_v3_fl(lvec, x);
1269                 mul_v3_fl(vvec, x);
1270
1271                 /* draw the angled sides of the cone */
1272                 glBegin(GL_LINE_STRIP);
1273                 glVertex3fv(vvec);
1274                 glVertex3fv(vec);
1275                 glVertex3fv(lvec);
1276                 glEnd();
1277                 
1278                 x *= y;
1279
1280                 /* draw the circle/square at the end of the cone */
1281                 glTranslatef(0.0, 0.0,  x);
1282                 if (la->mode & LA_SQUARE) {
1283                         float tvec[3];
1284                         float z_abs = fabsf(z);
1285
1286                         tvec[0] = tvec[1] = z_abs;
1287                         tvec[2] = 0.0;
1288
1289                         glBegin(GL_LINE_LOOP);
1290                         glVertex3fv(tvec);
1291                         tvec[1] = -z_abs; /* neg */
1292                         glVertex3fv(tvec);
1293                         tvec[0] = -z_abs; /* neg */
1294                         glVertex3fv(tvec);
1295                         tvec[1] = z_abs; /* pos */
1296                         glVertex3fv(tvec);
1297                         glEnd();
1298                 }
1299                 else {
1300                         circ(0.0, 0.0, fabsf(z));
1301                 }
1302
1303                 /* draw the circle/square representing spotbl */
1304                 if (la->type == LA_SPOT) {
1305                         float spotblcirc = fabsf(z) * (1.0f - powf(la->spotblend, 2));
1306                         /* hide line if it is zero size or overlaps with outer border,
1307                          * previously it adjusted to always to show it but that seems
1308                          * confusing because it doesn't show the actual blend size */
1309                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1310                                 circ(0.0, 0.0, spotblcirc);
1311                 }
1312
1313                 if (drawcone)
1314                         draw_transp_spot_volume(la, x, z);
1315
1316                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1317                 glTranslatef(0.0, 0.0, -x);  /* reverse translation above */
1318                 if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) {
1319                         float lvec_clip[3];
1320                         float vvec_clip[3];
1321                         float clipsta_fac = la->clipsta / -x;
1322
1323                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1324                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1325
1326                         glBegin(GL_LINE_STRIP);
1327                         glVertex3fv(lvec_clip);
1328                         glVertex3fv(vvec_clip);
1329                         glEnd();
1330                 }
1331                 /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */
1332                 else {
1333                         glBegin(GL_LINE_STRIP);
1334                         glVertex3f(0.0, 0.0, -circrad);
1335                         glVertex3f(0.0, 0.0, -la->dist);
1336                         glEnd();
1337                 }
1338         }
1339         else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1340                 
1341                 /* draw the line from the circle along the dist */
1342                 glBegin(GL_LINE_STRIP);
1343                 vec[2] = -circrad;
1344                 glVertex3fv(vec);
1345                 vec[2] = -la->dist;
1346                 glVertex3fv(vec);
1347                 glEnd();
1348                 
1349                 if (la->type == LA_HEMI) {
1350                         /* draw the hemisphere curves */
1351                         short axis, steps, dir;
1352                         float outdist, zdist, mul;
1353                         zero_v3(vec);
1354                         outdist = 0.14; mul = 1.4; dir = 1;
1355                         
1356                         setlinestyle(4);
1357                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1358                         for (axis = 0; axis < 4; axis++) {
1359                                 float v[3] = {0.0, 0.0, 0.0};
1360                                 zdist = 0.02;
1361                                 
1362                                 glBegin(GL_LINE_STRIP);
1363                                 
1364                                 for (steps = 0; steps < 6; steps++) {
1365                                         if (axis == 0 || axis == 1) {       /* x axis up, x axis down */
1366                                                 /* make the arcs start at the edge of the energy circle */
1367                                                 if (steps == 0) v[0] = dir * circrad;
1368                                                 else v[0] = v[0] + dir * (steps * outdist);
1369                                         }
1370                                         else if (axis == 2 || axis == 3) {      /* y axis up, y axis down */
1371                                                 /* make the arcs start at the edge of the energy circle */
1372                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1373                                         }
1374
1375                                         v[2] = v[2] - steps * zdist;
1376                                         
1377                                         glVertex3fv(v);
1378                                         
1379                                         zdist = zdist * mul;
1380                                 }
1381                                 
1382                                 glEnd();
1383                                 /* flip the direction */
1384                                 dir = -dir;
1385                         }
1386                 }
1387         }
1388         else if (la->type == LA_AREA) {
1389                 setlinestyle(3);
1390                 if (la->area_shape == LA_AREA_SQUARE)
1391                         fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1392                 else if (la->area_shape == LA_AREA_RECT)
1393                         fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1394
1395                 glBegin(GL_LINE_STRIP);
1396                 glVertex3f(0.0, 0.0, -circrad);
1397                 glVertex3f(0.0, 0.0, -la->dist);
1398                 glEnd();
1399         }
1400         
1401         /* and back to viewspace */
1402         glPushMatrix();
1403         glLoadMatrixf(rv3d->viewmat);
1404         copy_v3_v3(vec, ob->obmat[3]);
1405
1406         setlinestyle(0);
1407         
1408         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) {
1409                 drawshadbuflimits(la, ob->obmat);
1410         }
1411         
1412         UI_GetThemeColor4ubv(TH_LAMP, col);
1413         glColor4ubv(col);
1414
1415         glEnable(GL_BLEND);
1416         
1417         if (vec[2] > 0) vec[2] -= circrad;
1418         else vec[2] += circrad;
1419         
1420         glBegin(GL_LINE_STRIP);
1421         glVertex3fv(vec);
1422         vec[2] = 0;
1423         glVertex3fv(vec);
1424         glEnd();
1425         
1426         glPointSize(2.0);
1427         glBegin(GL_POINTS);
1428         glVertex3fv(vec);
1429         glEnd();
1430         glPointSize(1.0);
1431         
1432         glDisable(GL_BLEND);
1433         
1434         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1435                 /* restore for drawing extra stuff */
1436                 glColor3ubv(ob_wire_col);
1437         }
1438         /* and finally back to org object space! */
1439         glPopMatrix();
1440 }
1441
1442 static void draw_limit_line(float sta, float end, const short dflag, unsigned int col)
1443 {
1444         glBegin(GL_LINES);
1445         glVertex3f(0.0, 0.0, -sta);
1446         glVertex3f(0.0, 0.0, -end);
1447         glEnd();
1448
1449         if (!(dflag & DRAW_PICKING)) {
1450                 glPointSize(3.0);
1451                 glBegin(GL_POINTS);
1452                 cpack(col);
1453                 glVertex3f(0.0, 0.0, -sta);
1454                 glVertex3f(0.0, 0.0, -end);
1455                 glEnd();
1456                 glPointSize(1.0);
1457         }
1458 }
1459
1460
1461 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1462 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1463 static void draw_focus_cross(float dist, float size)
1464 {
1465         glBegin(GL_LINES);
1466         glVertex3f(-size, 0.f, -dist);
1467         glVertex3f(size, 0.f, -dist);
1468         glVertex3f(0.f, -size, -dist);
1469         glVertex3f(0.f, size, -dist);
1470         glEnd();
1471 }
1472
1473 #ifdef VIEW3D_CAMERA_BORDER_HACK
1474 unsigned char view3d_camera_border_hack_col[3];
1475 bool view3d_camera_border_hack_test = false;
1476 #endif
1477
1478 /* ****************** draw clip data *************** */
1479
1480 static void draw_bundle_sphere(void)
1481 {
1482         static GLuint displist = 0;
1483
1484         if (displist == 0) {
1485                 GLUquadricObj *qobj;
1486
1487                 displist = glGenLists(1);
1488                 glNewList(displist, GL_COMPILE);
1489
1490                 qobj = gluNewQuadric();
1491                 gluQuadricDrawStyle(qobj, GLU_FILL);
1492                 glShadeModel(GL_SMOOTH);
1493                 gluSphere(qobj, 0.05, 8, 8);
1494                 glShadeModel(GL_FLAT);
1495                 gluDeleteQuadric(qobj);
1496
1497                 glEndList();
1498         }
1499
1500         glCallList(displist);
1501 }
1502
1503 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1504                                                 MovieClip *clip, MovieTrackingObject *tracking_object,
1505                                                 const short dflag, const unsigned char ob_wire_col[4],
1506                                                 int *global_track_index, bool draw_selected)
1507 {
1508         MovieTracking *tracking = &clip->tracking;
1509         MovieTrackingTrack *track;
1510         float mat[4][4], imat[4][4];
1511         unsigned char col_unsel[4], col_sel[4];
1512         int tracknr = *global_track_index;
1513         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
1514         float camera_size[3];
1515
1516         UI_GetThemeColor4ubv(TH_TEXT, col_unsel);
1517         UI_GetThemeColor4ubv(TH_SELECT, col_sel);
1518
1519         BKE_tracking_get_camera_object_matrix(scene, base->object, mat);
1520
1521         /* we're compensating camera size for bundles size,
1522          * to make it so bundles are always displayed with the same size
1523          */
1524         copy_v3_v3(camera_size, base->object->size);
1525         if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0)
1526                 mul_v3_fl(camera_size, tracking_object->scale);
1527
1528         glPushMatrix();
1529
1530         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1531                 /* current ogl matrix is translated in camera space, bundles should
1532                  * be rendered in world space, so camera matrix should be "removed"
1533                  * from current ogl matrix */
1534                 invert_m4_m4(imat, base->object->obmat);
1535
1536                 glMultMatrixf(imat);
1537                 glMultMatrixf(mat);
1538         }
1539         else {
1540                 float obmat[4][4];
1541                 int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
1542
1543                 BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat);
1544
1545                 invert_m4_m4(imat, obmat);
1546                 glMultMatrixf(imat);
1547         }
1548
1549         for (track = tracksbase->first; track; track = track->next) {
1550                 bool selected = TRACK_SELECTED(track);
1551
1552                 if (draw_selected && !selected)
1553                         continue;
1554
1555                 if ((track->flag & TRACK_HAS_BUNDLE) == 0)
1556                         continue;
1557
1558                 if (dflag & DRAW_PICKING)
1559                         glLoadName(base->selcol + (tracknr << 16));
1560
1561                 glPushMatrix();
1562                 glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1563                 glScalef(v3d->bundle_size / 0.05f / camera_size[0],
1564                          v3d->bundle_size / 0.05f / camera_size[1],
1565                          v3d->bundle_size / 0.05f / camera_size[2]);
1566
1567                 if (v3d->drawtype == OB_WIRE) {
1568                         glDisable(GL_LIGHTING);
1569
1570                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1571                                 if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
1572                                         glColor3ubv(ob_wire_col);
1573                                 }
1574                                 else {
1575                                         glColor3fv(track->color);
1576                                 }
1577                         }
1578
1579                         drawaxes(0.05f, v3d->bundle_drawtype);
1580
1581                         glEnable(GL_LIGHTING);
1582                 }
1583                 else if (v3d->drawtype > OB_WIRE) {
1584                         if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
1585                                 /* selection outline */
1586                                 if (selected) {
1587                                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1588                                                 glColor3ubv(ob_wire_col);
1589                                         }
1590
1591                                         glLineWidth(2.f);
1592                                         glDisable(GL_LIGHTING);
1593                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1594
1595                                         draw_bundle_sphere();
1596
1597                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1598                                         glEnable(GL_LIGHTING);
1599                                         glLineWidth(1.f);
1600                                 }
1601
1602                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1603                                         if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1604                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1605                                 }
1606
1607                                 draw_bundle_sphere();
1608                         }
1609                         else {
1610                                 glDisable(GL_LIGHTING);
1611
1612                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1613                                         if (selected) {
1614                                                 glColor3ubv(ob_wire_col);
1615                                         }
1616                                         else {
1617                                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1618                                                 else UI_ThemeColor(TH_WIRE);
1619                                         }
1620                                 }
1621
1622                                 drawaxes(0.05f, v3d->bundle_drawtype);
1623
1624                                 glEnable(GL_LIGHTING);
1625                         }
1626                 }
1627
1628                 glPopMatrix();
1629
1630                 if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1631                         float pos[3];
1632
1633                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1634                         view3d_cached_text_draw_add(pos,
1635                                                     track->name, strlen(track->name),
1636                                                     10, V3D_CACHE_TEXT_GLOBALSPACE,
1637                                                     selected ? col_sel : col_unsel);
1638                 }
1639
1640                 tracknr++;
1641         }
1642
1643         if ((dflag & DRAW_PICKING) == 0) {
1644                 if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
1645                         MovieTrackingReconstruction *reconstruction;
1646                         reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
1647
1648                         if (reconstruction->camnr) {
1649                                 MovieReconstructedCamera *camera = reconstruction->cameras;
1650                                 int a = 0;
1651
1652                                 glDisable(GL_LIGHTING);
1653                                 UI_ThemeColor(TH_CAMERA_PATH);
1654                                 glLineWidth(2.0f);
1655
1656                                 glBegin(GL_LINE_STRIP);
1657                                 for (a = 0; a < reconstruction->camnr; a++, camera++) {
1658                                         glVertex3fv(camera->mat[3]);
1659                                 }
1660                                 glEnd();
1661
1662                                 glLineWidth(1.0f);
1663                                 glEnable(GL_LIGHTING);
1664                         }
1665                 }
1666         }
1667
1668         glPopMatrix();
1669
1670         *global_track_index = tracknr;
1671 }
1672
1673 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1674                                          const short dflag, const unsigned char ob_wire_col[4],
1675                                          const bool draw_selected)
1676 {
1677         MovieTracking *tracking = &clip->tracking;
1678         MovieTrackingObject *tracking_object;
1679         int global_track_index = 1;
1680
1681         if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
1682                 return;
1683
1684         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1685                 return;
1686
1687         glEnable(GL_LIGHTING);
1688         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1689         glEnable(GL_COLOR_MATERIAL);
1690         glShadeModel(GL_SMOOTH);
1691
1692         tracking_object = tracking->objects.first;
1693         while (tracking_object) {
1694                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1695                                                     dflag, ob_wire_col, &global_track_index, draw_selected);
1696
1697                 tracking_object = tracking_object->next;
1698         }
1699
1700         /* restore */
1701         glShadeModel(GL_FLAT);
1702         glDisable(GL_COLOR_MATERIAL);
1703         glDisable(GL_LIGHTING);
1704
1705         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1706                 glColor3ubv(ob_wire_col);
1707         }
1708
1709         if (dflag & DRAW_PICKING)
1710                 glLoadName(base->selcol);
1711 }
1712
1713 /* flag similar to draw_object() */
1714 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1715                        const short dflag, const unsigned char ob_wire_col[4])
1716 {
1717         /* a standing up pyramid with (0,0,0) as top */
1718         Camera *cam;
1719         Object *ob = base->object;
1720         float tvec[3];
1721         float vec[4][3], asp[2], shift[2], scale[3];
1722         int i;
1723         float drawsize;
1724         const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
1725         MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false);
1726
1727         /* draw data for movie clip set as active for scene */
1728         if (clip) {
1729                 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, false);
1730                 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, true);
1731         }
1732
1733 #ifdef VIEW3D_CAMERA_BORDER_HACK
1734         if (is_view && !(G.f & G_PICKSEL)) {
1735                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1736                         view3d_camera_border_hack_col[0] = ob_wire_col[0];
1737                         view3d_camera_border_hack_col[1] = ob_wire_col[1];
1738                         view3d_camera_border_hack_col[2] = ob_wire_col[2];
1739                 }
1740                 else {
1741                         float col[4];
1742                         glGetFloatv(GL_CURRENT_COLOR, col);
1743                         rgb_float_to_uchar(view3d_camera_border_hack_col, col);
1744                 }
1745                 view3d_camera_border_hack_test = true;
1746                 return;
1747         }
1748 #endif
1749
1750         cam = ob->data;
1751
1752         scale[0] = 1.0f / len_v3(ob->obmat[0]);
1753         scale[1] = 1.0f / len_v3(ob->obmat[1]);
1754         scale[2] = 1.0f / len_v3(ob->obmat[2]);
1755
1756         BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1757                                  asp, shift, &drawsize, vec);
1758
1759         glDisable(GL_LIGHTING);
1760         glDisable(GL_CULL_FACE);
1761
1762         /* camera frame */
1763         glBegin(GL_LINE_LOOP);
1764         glVertex3fv(vec[0]);
1765         glVertex3fv(vec[1]);
1766         glVertex3fv(vec[2]);
1767         glVertex3fv(vec[3]);
1768         glEnd();
1769
1770         if (is_view)
1771                 return;
1772
1773         zero_v3(tvec);
1774
1775         /* center point to camera frame */
1776         glBegin(GL_LINE_STRIP);
1777         glVertex3fv(vec[1]);
1778         glVertex3fv(tvec);
1779         glVertex3fv(vec[0]);
1780         glVertex3fv(vec[3]);
1781         glVertex3fv(tvec);
1782         glVertex3fv(vec[2]);
1783         glEnd();
1784
1785
1786         /* arrow on top */
1787         tvec[2] = vec[1][2]; /* copy the depth */
1788
1789
1790         /* draw an outline arrow for inactive cameras and filled
1791          * for active cameras. We actually draw both outline+filled
1792          * for active cameras so the wire can be seen side-on */
1793         for (i = 0; i < 2; i++) {
1794                 if (i == 0) glBegin(GL_LINE_LOOP);
1795                 else if (i == 1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1796                 else break;
1797
1798                 tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
1799                 tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1800                 glVertex3fv(tvec); /* left */
1801                 
1802                 tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
1803                 glVertex3fv(tvec); /* right */
1804                 
1805                 tvec[0] = shift[0];
1806                 tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1807                 glVertex3fv(tvec); /* top */
1808
1809                 glEnd();
1810         }
1811
1812         if ((dflag & DRAW_SCENESET) == 0) {
1813                 if (cam->flag & (CAM_SHOWLIMITS | CAM_SHOWMIST)) {
1814                         float nobmat[4][4];
1815
1816                         /* draw in normalized object matrix space */
1817                         copy_m4_m4(nobmat, ob->obmat);
1818                         normalize_m4(nobmat);
1819
1820                         glPushMatrix();
1821                         glLoadMatrixf(rv3d->viewmat);
1822                         glMultMatrixf(nobmat);
1823
1824                         if (cam->flag & CAM_SHOWLIMITS) {
1825                                 draw_limit_line(cam->clipsta, cam->clipend, dflag, 0x77FFFF);
1826                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1827                                 draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
1828                         }
1829
1830                         if (cam->flag & CAM_SHOWMIST) {
1831                                 World *world = scene->world;
1832                                 if (world) {
1833                                         draw_limit_line(world->miststa, world->miststa + world->mistdist, dflag, 0xFFFFFF);
1834                                 }
1835                         }
1836                         glPopMatrix();
1837                 }
1838         }
1839 }
1840
1841 /* flag similar to draw_object() */
1842 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1843                         Object *UNUSED(ob), int UNUSED(flag))
1844 {
1845         //Speaker *spk = ob->data;
1846
1847         float vec[3];
1848         int i, j;
1849
1850         glEnable(GL_BLEND);
1851
1852         for (j = 0; j < 3; j++) {
1853                 vec[2] = 0.25f * j - 0.125f;
1854
1855                 glBegin(GL_LINE_LOOP);
1856                 for (i = 0; i < 16; i++) {
1857                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1858                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1859                         glVertex3fv(vec);
1860                 }
1861                 glEnd();
1862         }
1863
1864         for (j = 0; j < 4; j++) {
1865                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1866                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1867                 glBegin(GL_LINE_STRIP);
1868                 for (i = 0; i < 3; i++) {
1869                         if (i == 1) {
1870                                 vec[0] *= 0.5f;
1871                                 vec[1] *= 0.5f;
1872                         }
1873
1874                         vec[2] = 0.25f * i - 0.125f;
1875                         glVertex3fv(vec);
1876                 }
1877                 glEnd();
1878         }
1879
1880         glDisable(GL_BLEND);
1881 }
1882
1883 static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel)
1884 {
1885         BPoint *bp = lt->def;
1886         float *co = dl ? dl->verts : NULL;
1887         int u, v, w;
1888
1889         const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
1890         UI_ThemeColor(color);
1891
1892         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1893         bglBegin(GL_POINTS);
1894
1895         for (w = 0; w < lt->pntsw; w++) {
1896                 int wxt = (w == 0 || w == lt->pntsw - 1);
1897                 for (v = 0; v < lt->pntsv; v++) {
1898                         int vxt = (v == 0 || v == lt->pntsv - 1);
1899                         for (u = 0; u < lt->pntsu; u++, bp++, co += 3) {
1900                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1901                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1902                                         if (bp->hide == 0) {
1903                                                 /* check for active BPoint and ensure selected */
1904                                                 if ((bp == actbp) && (bp->f1 & SELECT)) {
1905                                                         UI_ThemeColor(TH_ACTIVE_VERT);
1906                                                         bglVertex3fv(dl ? co : bp->vec);
1907                                                         UI_ThemeColor(color);
1908                                                 }
1909                                                 else if ((bp->f1 & SELECT) == sel) {
1910                                                         bglVertex3fv(dl ? co : bp->vec);
1911                                                 }
1912                                         }
1913                                 }
1914                         }
1915                 }
1916         }
1917         
1918         glPointSize(1.0);
1919         bglEnd();
1920 }
1921
1922 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
1923 {
1924         int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
1925
1926         if (actdef_wcol) {
1927                 float col[3];
1928                 MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1);
1929                 
1930                 weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
1931                 glColor3fv(col);
1932
1933         }
1934         
1935         if (dl) {
1936                 glVertex3fv(&dl->verts[index * 3]);
1937         }
1938         else {
1939                 glVertex3fv(lt->def[index].vec);
1940         }
1941 }
1942
1943 #ifdef SEQUENCER_DAG_WORKAROUND
1944 static void ensure_curve_cache(Scene *scene, Object *object)
1945 {
1946         if (object->curve_cache == NULL) {
1947                 switch (object->type) {
1948                         case OB_CURVE:
1949                         case OB_SURF:
1950                         case OB_FONT:
1951                                 BKE_displist_make_curveTypes(scene, object, false);
1952                                 break;
1953                         case OB_MBALL:
1954                                 BKE_displist_make_mball(G.main->eval_ctx, scene, object);
1955                                 break;
1956                         case OB_LATTICE:
1957                                 BKE_lattice_modifiers_calc(scene, object);
1958                                 break;
1959                 }
1960         }
1961 }
1962 #endif
1963
1964 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1965 static void drawlattice(View3D *v3d, Object *ob)
1966 {
1967         Lattice *lt = ob->data;
1968         DispList *dl;
1969         int u, v, w;
1970         int actdef_wcol = 0;
1971         const bool is_edit = (lt->editlatt != NULL);
1972
1973         dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
1974         
1975         if (is_edit) {
1976                 lt = lt->editlatt->latt;
1977
1978                 UI_ThemeColor(TH_WIRE_EDIT);
1979                 
1980                 if (ob->defbase.first && lt->dvert) {
1981                         actdef_wcol = ob->actdef;
1982                         glShadeModel(GL_SMOOTH);
1983                 }
1984         }
1985         
1986         glBegin(GL_LINES);
1987         for (w = 0; w < lt->pntsw; w++) {
1988                 int wxt = (w == 0 || w == lt->pntsw - 1);
1989                 for (v = 0; v < lt->pntsv; v++) {
1990                         int vxt = (v == 0 || v == lt->pntsv - 1);
1991                         for (u = 0; u < lt->pntsu; u++) {
1992                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1993
1994                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1995                                         drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol);
1996                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
1997                                 }
1998                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1999                                         drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol);
2000                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
2001                                 }
2002                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
2003                                         drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol);
2004                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
2005                                 }
2006                         }
2007                 }
2008         }
2009         glEnd();
2010         
2011         /* restoration for weight colors */
2012         if (actdef_wcol)
2013                 glShadeModel(GL_FLAT);
2014
2015         if (is_edit) {
2016                 BPoint *actbp = BKE_lattice_active_point_get(lt);
2017
2018                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2019                 
2020                 lattice_draw_verts(lt, dl, actbp, 0);
2021                 lattice_draw_verts(lt, dl, actbp, 1);
2022                 
2023                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2024         }
2025 }
2026
2027 /* ***************** ******************** */
2028
2029 /*  draw callback */
2030
2031 typedef struct drawDMVertSel_userData {
2032         MVert *mvert;
2033         int active;
2034         unsigned char *col[3];  /* (base, sel, act) */
2035         char sel_prev;
2036 } drawDMVertSel_userData;
2037
2038 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
2039                                           const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2040 {
2041         drawDMVertSel_userData *data = userData;
2042         MVert *mv = &data->mvert[index];
2043
2044         if (!(mv->flag & ME_HIDE)) {
2045                 const char sel = (index == data->active) ? 2 : (mv->flag & SELECT);
2046                 if (sel != data->sel_prev) {
2047                         glColor3ubv(data->col[sel]);
2048                         data->sel_prev = sel;
2049                 }
2050
2051                 glVertex3fv(co);
2052         }
2053 }
2054
2055 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2056 {
2057         drawDMVertSel_userData data;
2058
2059         /* TODO define selected color */
2060         unsigned char base_col[3] = {0x0, 0x0, 0x0};
2061         unsigned char sel_col[3] = {0xd8, 0xb8, 0x0};
2062         unsigned char act_col[3] = {0xff, 0xff, 0xff};
2063
2064         data.mvert = me->mvert;
2065         data.active = BKE_mesh_mselect_active_get(me, ME_VSEL);
2066         data.sel_prev = 0xff;
2067
2068         data.col[0] = base_col;
2069         data.col[1] = sel_col;
2070         data.col[2] = act_col;
2071
2072         glBegin(GL_POINTS);
2073         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP);
2074         glEnd();
2075 }
2076
2077 /* ************** DRAW MESH ****************** */
2078
2079 /* First section is all the "simple" draw routines,
2080  * ones that just pass some sort of primitive to GL,
2081  * with perhaps various options to control lighting,
2082  * color, etc.
2083  *
2084  * These routines should not have user interface related
2085  * logic!!!
2086  */
2087
2088 static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
2089 {
2090         float obmat[3][3];
2091
2092         copy_m3_m4(obmat, ob->obmat);
2093
2094         data->uniform_scale = is_uniform_scaled_m3(obmat);
2095
2096         if (!data->uniform_scale) {
2097                 /* inverted matrix */
2098                 invert_m3_m3(data->imat, obmat);
2099
2100                 /* transposed inverted matrix */
2101                 copy_m3_m3(data->tmat, data->imat);
2102                 transpose_m3(data->tmat);
2103         }
2104 }
2105
2106 static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
2107 {
2108         drawDMNormal_userData *data = userData;
2109         BMFace *efa = BM_face_at_index(data->bm, index);
2110         float n[3];
2111
2112         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2113                 if (!data->uniform_scale) {
2114                         mul_v3_m3v3(n, data->tmat, no);
2115                         normalize_v3(n);
2116                         mul_m3_v3(data->imat, n);
2117                 }
2118                 else {
2119                         copy_v3_v3(n, no);
2120                 }
2121
2122                 glVertex3fv(cent);
2123                 glVertex3f(cent[0] + n[0] * data->normalsize,
2124                            cent[1] + n[1] * data->normalsize,
2125                            cent[2] + n[2] * data->normalsize);
2126         }
2127 }
2128
2129 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2130 {
2131         drawDMNormal_userData data;
2132
2133         data.bm = em->bm;
2134         data.normalsize = scene->toolsettings->normalsize;
2135
2136         calcDrawDMNormalScale(ob, &data);
2137
2138         glBegin(GL_LINES);
2139         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
2140         glEnd();
2141 }
2142
2143 static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2144 {
2145         BMFace *efa = BM_face_at_index(((void **)userData)[0], index);
2146         const char sel = *(((char **)userData)[1]);
2147         
2148         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
2149             (BM_elem_flag_test(efa, BM_ELEM_SELECT) == sel))
2150         {
2151                 bglVertex3fv(cent);
2152         }
2153 }
2154 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, char sel)
2155 {
2156         void *ptrs[2] = {em->bm, &sel};
2157
2158         bglBegin(GL_POINTS);
2159         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs, DM_FOREACH_NOP);
2160         bglEnd();
2161 }
2162
2163 static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
2164 {
2165         drawDMNormal_userData *data = userData;
2166         BMVert *eve = BM_vert_at_index(data->bm, index);
2167
2168         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2169                 float no[3], n[3];
2170
2171                 if (no_f) {
2172                         copy_v3_v3(no, no_f);
2173                 }
2174                 else {
2175                         normal_short_to_float_v3(no, no_s);
2176                 }
2177
2178                 if (!data->uniform_scale) {
2179                         mul_v3_m3v3(n, data->tmat, no);
2180                         normalize_v3(n);
2181                         mul_m3_v3(data->imat, n);
2182                 }
2183                 else {
2184                         copy_v3_v3(n, no);
2185                 }
2186
2187                 glVertex3fv(co);
2188                 glVertex3f(co[0] + n[0] * data->normalsize,
2189                            co[1] + n[1] * data->normalsize,
2190                            co[2] + n[2] * data->normalsize);
2191         }
2192 }
2193
2194 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2195 {
2196         drawDMNormal_userData data;
2197
2198         data.bm = em->bm;
2199         data.normalsize = scene->toolsettings->normalsize;
2200
2201         calcDrawDMNormalScale(ob, &data);
2202
2203         glBegin(GL_LINES);
2204         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
2205         glEnd();
2206 }
2207
2208 /* Draw verts with color set based on selection */
2209 static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
2210                                    const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2211 {
2212         drawDMVerts_userData *data = userData;
2213         BMVert *eve = BM_vert_at_index(data->bm, index);
2214
2215         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
2216                 /* skin nodes: draw a red circle around the root
2217                  * node(s) */
2218                 if (data->cd_vskin_offset != -1) {
2219                         const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
2220                         if (vs->flag & MVERT_SKIN_ROOT) {
2221                                 float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
2222                                 bglEnd();
2223                         
2224                                 glColor4ubv(data->th_skin_root);
2225                                 drawcircball(GL_LINES, co, radius, data->imat);
2226
2227                                 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2228                                 bglBegin(GL_POINTS);
2229                         }
2230                 }
2231
2232                 /* draw active larger - need to stop/start point drawing for this :/ */
2233                 if (eve == data->eve_act) {
2234                         glColor4ubv(data->th_editmesh_active);
2235                         
2236                         bglEnd();
2237                         
2238                         glPointSize(data->th_vertex_size);
2239                         bglBegin(GL_POINTS);
2240                         bglVertex3fv(co);
2241                         bglEnd();
2242
2243                         glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2244                         glPointSize(data->th_vertex_size);
2245                         bglBegin(GL_POINTS);
2246                 }
2247                 else {
2248                         bglVertex3fv(co);
2249                 }
2250         }
2251 }
2252
2253 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act,
2254                           RegionView3D *rv3d)
2255 {
2256         drawDMVerts_userData data;
2257         data.sel = sel;
2258         data.eve_act = eve_act;
2259         data.bm = em->bm;
2260
2261         /* Cache theme values */
2262         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
2263         UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
2264         UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
2265         UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
2266         data.th_vertex_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2267
2268         /* For skin root drawing */
2269         data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN);
2270         /* view-aligned matrix */
2271         mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
2272         invert_m4(data.imat);
2273
2274         bglBegin(GL_POINTS);
2275         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP);
2276         bglEnd();
2277 }
2278
2279 /* Draw edges with color set based on selection */
2280 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2281 {
2282         BMEdge *eed;
2283         //unsigned char **cols = userData, *col;
2284         drawDMEdgesSel_userData *data = userData;
2285         unsigned char *col;
2286
2287         eed = BM_edge_at_index(data->bm, index);
2288
2289         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2290                 if (eed == data->eed_act) {
2291                         glColor4ubv(data->actCol);
2292                 }
2293                 else {
2294                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2295                                 col = data->selCol;
2296                         }
2297                         else {
2298                                 col = data->baseCol;
2299                         }
2300                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2301                         if (col[3] == 0)
2302                                 return DM_DRAW_OPTION_SKIP;
2303                         
2304                         glColor4ubv(col);
2305                 }
2306                 return DM_DRAW_OPTION_NORMAL;
2307         }
2308         else {
2309                 return DM_DRAW_OPTION_SKIP;
2310         }
2311 }
2312 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2313                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2314 {
2315         drawDMEdgesSel_userData data;
2316         
2317         data.baseCol = baseCol;
2318         data.selCol = selCol;
2319         data.actCol = actCol;
2320         data.bm = em->bm;
2321         data.eed_act = eed_act;
2322         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2323 }
2324
2325 /* Draw edges */
2326 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2327 {
2328         if (BM_elem_flag_test(BM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
2329                 return DM_DRAW_OPTION_SKIP;
2330         else
2331                 return DM_DRAW_OPTION_NORMAL;
2332 }
2333
2334 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
2335 {
2336         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em->bm);
2337 }
2338
2339 /* Draw edges with color interpolated based on selection */
2340 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2341 {
2342         if (BM_elem_flag_test(BM_edge_at_index(((void **)userData)[0], index), BM_ELEM_HIDDEN))
2343                 return DM_DRAW_OPTION_SKIP;
2344         else
2345                 return DM_DRAW_OPTION_NORMAL;
2346 }
2347 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2348 {
2349         BMEdge *eed = BM_edge_at_index(((void **)userData)[0], index);
2350         unsigned char **cols = userData;
2351         unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1];
2352         unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1];
2353
2354         glColor4ub(col0[0] + (col1[0] - col0[0]) * t,
2355                    col0[1] + (col1[1] - col0[1]) * t,
2356                    col0[2] + (col1[2] - col0[2]) * t,
2357                    col0[3] + (col1[3] - col0[3]) * t);
2358 }
2359
2360 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2361 {
2362         void *cols[3] = {em->bm, baseCol, selCol};
2363
2364         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2365 }
2366
2367 /* Draw only seam edges */
2368 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2369 {
2370         BMEdge *eed = BM_edge_at_index(userData, index);
2371
2372         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2373                 return DM_DRAW_OPTION_NORMAL;
2374         else
2375                 return DM_DRAW_OPTION_SKIP;
2376 }
2377
2378 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2379 {
2380         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em->bm);
2381 }
2382
2383 /* Draw only sharp edges */
2384 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2385 {
2386         BMEdge *eed = BM_edge_at_index(userData, index);
2387
2388         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2389                 return DM_DRAW_OPTION_NORMAL;
2390         else
2391                 return DM_DRAW_OPTION_SKIP;
2392 }
2393
2394 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2395 {
2396         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em->bm);
2397 }
2398
2399 #ifdef WITH_FREESTYLE
2400
2401 static int draw_dm_test_freestyle_edge_mark(BMesh *bm, BMEdge *eed)
2402 {
2403         FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
2404         if (!fed)
2405                 return 0;
2406         return (fed->flag & FREESTYLE_EDGE_MARK) != 0;
2407 }
2408
2409 /* Draw only Freestyle feature edges */
2410 static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
2411 {
2412         BMEdge *eed = BM_edge_at_index(userData, index);
2413
2414         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && draw_dm_test_freestyle_edge_mark(userData, eed))
2415                 return DM_DRAW_OPTION_NORMAL;
2416         else
2417                 return DM_DRAW_OPTION_SKIP;
2418 }
2419
2420 static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
2421 {
2422         dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em->bm);
2423 }
2424
2425 static int draw_dm_test_freestyle_face_mark(BMesh *bm, BMFace *efa)
2426 {
2427         FreestyleFace *ffa = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
2428         if (!ffa)
2429                 return 0;
2430         return (ffa->flag & FREESTYLE_FACE_MARK) != 0;
2431 }
2432
2433 #endif
2434
2435 /* Draw loop normals. */
2436 static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2437 {
2438         /* XXX Would it be worth adding a dm->foreachMappedLoop func just for this? I doubt it... */
2439
2440         /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
2441          * return loop data from bmesh itself. */
2442         float (*lnors)[3] = DM_get_loop_data_layer(dm, CD_NORMAL);
2443
2444         if (lnors) {
2445                 drawDMNormal_userData data;
2446                 const MLoop *mloops = dm->getLoopArray(dm);
2447                 const MVert *mverts = dm->getVertArray(dm);
2448                 int i, totloops = dm->getNumLoops(dm);
2449
2450                 data.bm = em->bm;
2451                 data.normalsize = scene->toolsettings->normalsize;
2452
2453                 calcDrawDMNormalScale(ob, &data);
2454
2455                 glBegin(GL_LINES);
2456                 for (i = 0; i < totloops; i++, mloops++, lnors++) {
2457                         float no[3];
2458                         const float *co = mverts[mloops->v].co;
2459
2460                         if (!data.uniform_scale) {
2461                                 mul_v3_m3v3(no, data.tmat, (float *)lnors);
2462                                 normalize_v3(no);
2463                                 mul_m3_v3(data.imat, no);
2464                         }
2465                         else {
2466                                 copy_v3_v3(no, (float *)lnors);
2467                         }
2468                         mul_v3_fl(no, data.normalsize);
2469                         add_v3_v3(no, co);
2470                         glVertex3fv(co);
2471                         glVertex3fv(no);
2472                 }
2473                 glEnd();
2474         }
2475 }
2476
2477 /* Draw faces with color set based on selection
2478  * return 2 for the active face so it renders with stipple enabled */
2479 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2480 {
2481         drawDMFacesSel_userData *data = userData;
2482         BMFace *efa = BM_face_at_index(data->bm, index);
2483         unsigned char *col;
2484         
2485         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2486                 if (efa == data->efa_act) {
2487                         glColor4ubv(data->cols[2]);
2488                         return DM_DRAW_OPTION_STIPPLE;
2489                 }
2490                 else {
2491 #ifdef WITH_FREESTYLE
2492                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
2493 #else
2494                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2495 #endif
2496                         if (col[3] == 0)
2497                                 return DM_DRAW_OPTION_SKIP;
2498                         glColor4ubv(col);
2499                         return DM_DRAW_OPTION_NORMAL;
2500                 }
2501         }
2502         return DM_DRAW_OPTION_SKIP;
2503 }
2504
2505 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2506 {
2507
2508         drawDMFacesSel_userData *data = userData;
2509         int i;
2510         BMFace *efa;
2511         BMFace *next_efa;
2512
2513         unsigned char *col, *next_col;
2514
2515         if (!data->orig_index_mf_to_mpoly)
2516                 return 0;
2517
2518         i = DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index);
2519         efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
2520         i = DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, next_index);
2521         next_efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
2522
2523         if (ELEM(NULL, efa, next_efa))
2524                 return 0;
2525
2526         if (efa == next_efa)
2527                 return 1;
2528
2529         if (efa == data->efa_act || next_efa == data->efa_act)
2530                 return 0;
2531
2532 #ifdef WITH_FREESTYLE
2533         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
2534         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
2535 #else
2536         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2537         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
2538 #endif
2539
2540         if (col[3] == 0 || next_col[3] == 0)
2541                 return 0;
2542
2543         return col == next_col;
2544 }
2545
2546 /* also draws the active face */
2547 #ifdef WITH_FREESTYLE
2548 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2549                               unsigned char *selCol, unsigned char *actCol, unsigned char *markCol, BMFace *efa_act)
2550 #else
2551 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2552                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2553 #endif
2554 {
2555         drawDMFacesSel_userData data;
2556         data.dm = dm;
2557         data.cols[0] = baseCol;
2558         data.bm = em->bm;
2559         data.cols[1] = selCol;
2560         data.cols[2] = actCol;
2561 #ifdef WITH_FREESTYLE
2562         data.cols[3] = markCol;
2563 #endif
2564         data.efa_act = efa_act;
2565         /* double lookup */
2566         data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2567         data.orig_index_mp_to_orig  = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
2568         if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == false) {
2569                 data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
2570         }
2571
2572         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2573 }
2574
2575 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2576 {
2577         drawDMLayer_userData *data = userData;
2578         BMesh *bm = data->bm;
2579         BMEdge *eed = BM_edge_at_index(bm, index);
2580         
2581         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2582                 const float crease = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
2583                 if (crease != 0.0f) {
2584                         UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_CREASE, crease);
2585                         return DM_DRAW_OPTION_NORMAL;
2586                 }
2587         }
2588         return DM_DRAW_OPTION_SKIP;
2589 }
2590 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2591 {
2592         drawDMLayer_userData data;
2593
2594         data.bm = em->bm;
2595         data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
2596
2597         if (data.cd_layer_offset != -1) {
2598                 glLineWidth(3.0);
2599                 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data);
2600                 glLineWidth(1.0);
2601         }
2602 }
2603
2604 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2605 {
2606         drawDMLayer_userData *data = userData;
2607         BMesh *bm = data->bm;
2608         BMEdge *eed = BM_edge_at_index(bm, index);
2609
2610         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2611                 const float bweight = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
2612                 if (bweight != 0.0f) {
2613                         UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, bweight);
2614                         return DM_DRAW_OPTION_NORMAL;
2615                 }
2616         }
2617         return DM_DRAW_OPTION_SKIP;
2618 }
2619 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
2620                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2621 {
2622         drawDMLayer_userData *data = userData;
2623         BMesh *bm = data->bm;
2624         BMVert *eve = BM_vert_at_index(bm, index);
2625
2626         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2627                 const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset);
2628                 if (bweight != 0.0f) {
2629                         UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, bweight);
2630                         bglVertex3fv(co);
2631                 }
2632         }
2633 }
2634 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2635 {
2636         ToolSettings *ts = scene->toolsettings;
2637
2638         if (ts->selectmode & SCE_SELECT_VERTEX) {
2639                 drawDMLayer_userData data;
2640
2641                 data.bm = em->bm;
2642                 data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT);
2643
2644                 if (data.cd_layer_offset != -1) {
2645                         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2646                         bglBegin(GL_POINTS);
2647                         dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP);
2648                         bglEnd();
2649                 }
2650         }
2651         else {
2652                 drawDMLayer_userData data;
2653
2654                 data.bm = em->bm;
2655                 data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
2656
2657                 if (data.cd_layer_offset != -1) {
2658                         glLineWidth(3.0);
2659                         dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data);
2660                         glLineWidth(1.0);
2661                 }
2662         }
2663 }
2664
2665 static int draw_dm_override_material_color(int UNUSED(nr), void *UNUSED(attribs))
2666 {
2667         return 1;
2668 }
2669
2670 /* Second section of routines: Combine first sets to form fancy
2671  * drawing routines (for example rendering twice to get overlays).
2672  *
2673  * Also includes routines that are basic drawing but are too
2674  * specialized to be split out (like drawing creases or measurements).
2675  */
2676
2677 /* EditMesh drawing routines*/
2678
2679 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2680                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
2681                                 RegionView3D *rv3d)
2682 {
2683         ToolSettings *ts = scene->toolsettings;
2684         int sel;
2685
2686         if (v3d->zbuf) glDepthMask(0);  /* disable write in zbuffer, zbuf select */
2687
2688         for (sel = 0; sel < 2; sel++) {
2689                 unsigned char col[4], fcol[4];
2690                 int pass;
2691
2692                 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
2693                 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE_EDIT, fcol);
2694
2695                 for (pass = 0; pass < 2; pass++) {
2696                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2697                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2698
2699                         if (pass == 0) {
2700                                 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
2701                                         glDisable(GL_DEPTH_TEST);
2702
2703                                         glEnable(GL_BLEND);
2704                                 }
2705                                 else {
2706                                         continue;
2707                                 }
2708
2709                                 size = (size > 2.1f ? size / 2.0f : size);
2710                                 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
2711                                 col[3] = fcol[3] = 100;
2712                         }
2713                         else {
2714                                 col[3] = fcol[3] = 255;
2715                         }
2716
2717                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2718                                 glPointSize(size);
2719                                 glColor4ubv(col);
2720                                 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
2721                         }
2722                         
2723                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2724                                 glPointSize(fsize);
2725                                 glColor4ubv(fcol);
2726                                 draw_dm_face_centers(em, cageDM, sel);
2727                         }
2728                         
2729                         if (pass == 0) {
2730                                 glDisable(GL_BLEND);
2731                                 glEnable(GL_DEPTH_TEST);
2732                         }
2733                 }
2734         }
2735
2736         if (v3d->zbuf) glDepthMask(1);
2737         glPointSize(1.0);
2738 }
2739
2740 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2741                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2742                                 BMEdge *eed_act)
2743 {
2744         ToolSettings *ts = scene->toolsettings;
2745         int pass;
2746         unsigned char wireCol[4], selCol[4], actCol[4];
2747
2748         /* since this function does transparent... */
2749         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2750         UI_GetThemeColor4ubv(TH_WIRE_EDIT, wireCol);
2751         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2752         
2753         /* when sel only is used, don't render wire, only selected, this is used for
2754          * textured draw mode when the 'edges' option is disabled */
2755         if (sel_only)
2756                 wireCol[3] = 0;
2757
2758         for (pass = 0; pass < 2; pass++) {
2759                 /* show wires in transparent when no zbuf clipping for select */
2760                 if (pass == 0) {
2761                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
2762                                 glEnable(GL_BLEND);
2763                                 glDisable(GL_DEPTH_TEST);
2764                                 selCol[3] = 85;
2765                                 if (!sel_only) wireCol[3] = 85;
2766                         }
2767                         else {
2768                                 continue;
2769                         }
2770                 }
2771                 else {
2772                         selCol[3] = 255;
2773                         if (!sel_only) wireCol[3] = 255;
2774                 }
2775
2776                 if (ts->selectmode == SCE_SELECT_FACE) {
2777                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2778                 }
2779                 else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
2780                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2781                                 glShadeModel(GL_SMOOTH);
2782                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2783                                 glShadeModel(GL_FLAT);
2784                         }
2785                         else {
2786                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2787                         }
2788                 }
2789                 else {
2790                         if (!sel_only) {
2791                                 glColor4ubv(wireCol);
2792                                 draw_dm_edges(em, cageDM);
2793                         }
2794                 }
2795
2796                 if (pass == 0) {
2797                         glDisable(GL_BLEND);
2798                         glEnable(GL_DEPTH_TEST);
2799                 }
2800         }
2801 }
2802
2803 static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2804 {
2805         /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, etc.).
2806          * See bug #36090.
2807          */
2808         const short txt_flag = V3D_CACHE_TEXT_LOCALCLIP | (unit->system ? 0 : V3D_CACHE_TEXT_ASCII);
2809         Mesh *me = ob->data;
2810         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2811         char numstr[32]; /* Stores the measurement display text here */
2812         size_t numstr_len;
2813         const char *conv_float; /* Use a float conversion matching the grid size */
2814         unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
2815         float area; /* area of the face */
2816         float grid = unit->system ? unit->scale_length : v3d->grid;
2817         const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
2818         const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0;
2819         const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0;
2820         /* when 2 edge-info options are enabled, space apart */
2821         const bool do_edge_textpair = (me->drawflag & ME_DRAWEXTRA_EDGELEN) && (me->drawflag & ME_DRAWEXTRA_EDGEANG);
2822         const float edge_texpair_sep = 0.4f;
2823         float clip_planes[4][4];
2824         /* allow for displaying shape keys and deform mods */
2825         DerivedMesh *dm = EDBM_mesh_deform_dm_get(em);
2826         BMIter iter;
2827         int i;
2828
2829         /* make the precision of the display value proportionate to the gridsize */
2830
2831         if (grid <= 0.01f) conv_float = "%.6g";
2832         else if (grid <= 0.1f) conv_float = "%.5g";
2833         else if (grid <= 1.0f) conv_float = "%.4g";
2834         else if (grid <= 10.0f) conv_float = "%.3g";
2835         else conv_float = "%.2g";
2836
2837         if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) {
2838                 BoundBox bb;
2839                 bglMats mats = {{0}};
2840                 const rcti rect = {0, ar->winx, 0, ar->winy};
2841
2842                 view3d_get_transformation(ar, ar->regiondata, em->ob, &mats);
2843                 ED_view3d_clipping_calc(&bb, clip_planes, &mats, &rect);
2844         }
2845
2846         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2847                 BMEdge *eed;
2848
2849                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2850
2851                 if (dm) {
2852                         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
2853                 }
2854
2855                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
2856                         /* draw selected edges, or edges next to selected verts while draging */
2857                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2858                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2859                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2860                         {
2861                                 float v1_clip[3], v2_clip[3];
2862
2863                                 if (dm) {
2864                                         dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
2865                                         dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
2866                                 }
2867                                 else {
2868                                         copy_v3_v3(v1, eed->v1->co);
2869                                         copy_v3_v3(v2, eed->v2->co);
2870                                 }
2871
2872                                 copy_v3_v3(v1_clip, v1);
2873                                 copy_v3_v3(v2_clip, v2);
2874
2875                                 if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
2876
2877                                         if (do_edge_textpair) {
2878                                                 interp_v3_v3v3(vmid, v1, v2, edge_texpair_sep);
2879                                         }
2880                                         else {
2881                                                 mid_v3_v3v3(vmid, v1_clip, v2_clip);
2882                                         }
2883
2884                                         if (do_global) {
2885                                                 mul_mat3_m4_v3(ob->obmat, v1);
2886                                                 mul_mat3_m4_v3(ob->obmat, v2);
2887                                         }
2888
2889                                         if (unit->system) {
2890                                                 numstr_len = bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2891                                                                             unit->system, B_UNIT_LENGTH, do_split, false);
2892                                         }
2893                                         else {
2894                                                 numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
2895                                         }
2896
2897                                         view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
2898                                 }
2899                         }
2900                 }
2901         }
2902
2903         if (me->drawflag & ME_DRAWEXTRA_EDGEANG) {
2904                 const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
2905                 BMEdge *eed;
2906
2907                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col);
2908
2909                 if (dm) {
2910                         BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
2911                 }
2912
2913                 // invert_m4_m4(ob->imat, ob->obmat);  // this is already called
2914
2915                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
2916                         BMLoop *l_a, *l_b;
2917                         if (BM_edge_loop_pair(eed, &l_a, &l_b)) {
2918                                 /* draw selected edges, or edges next to selected verts while draging */
2919                                 if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2920                                     (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2921                                                    BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) ||
2922                                                    /* special case, this is useful to show when vertes connected to this edge via a
2923                                                     * face are being transformed */
2924                                                    BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) ||
2925                                                    BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT)       ||
2926                                                    BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) ||
2927                                                    BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT)
2928                                                    )))
2929                                 {
2930                                         float v1_clip[3], v2_clip[3];
2931
2932                                         if (dm) {
2933                                                 dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
2934                                                 dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
2935                                         }
2936                                         else {
2937                                                 copy_v3_v3(v1, eed->v1->co);
2938                                                 copy_v3_v3(v2, eed->v2->co);
2939                                         }
2940
2941                                         copy_v3_v3(v1_clip, v1);
2942                                         copy_v3_v3(v2_clip, v2);
2943
2944                                         if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
2945                                                 float no_a[3], no_b[3];
2946                                                 float angle;
2947
2948                                                 if (do_edge_textpair) {
2949                                                         interp_v3_v3v3(vmid, v2_clip, v1_clip, edge_texpair_sep);
2950                                                 }
2951                                                 else {
2952                                                         mid_v3_v3v3(vmid, v1_clip, v2_clip);
2953                                                 }
2954
2955                                                 if (dm) {
2956                                                         dm->getPolyNo(dm, BM_elem_index_get(l_a->f), no_a);
2957                                                         dm->getPolyNo(dm, BM_elem_index_get(l_b->f), no_b);
2958                                                 }
2959                                                 else {
2960                                                         copy_v3_v3(no_a, l_a->f->no);
2961                                                         copy_v3_v3(no_b, l_b->f->no);
2962                                                 }
2963
2964                                                 if (do_global) {
2965                                                         mul_mat3_m4_v3(ob->imat, no_a);
2966                                                         mul_mat3_m4_v3(ob->imat, no_b);
2967                                                         normalize_v3(no_a);
2968                                                         normalize_v3(no_b);
2969                                                 }
2970
2971                                                 angle = angle_normalized_v3v3(no_a, no_b);
2972
2973                                                 numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
2974
2975                                                 view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
2976                                         }
2977                                 }
2978                         }
2979                 }
2980         }
2981
2982         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2983                 /* would be nice to use BM_face_calc_area, but that is for 2d faces
2984                  * so instead add up tessellation triangle areas */
2985                 BMFace *f;
2986                 int n;
2987
2988 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                                 \
2989         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                                          \
2990                 mul_v3_fl(vmid, 1.0f / (float)n);                                                \
2991                 if (unit->system) {                                                              \
2992                         numstr_len = bUnit_AsString(                                                 \
2993                                 numstr, sizeof(numstr),                                              \
2994                                 (double)(area * unit->scale_length * unit->scale_length),            \
2995                                 3, unit->system, B_UNIT_AREA, do_split, false);                      \
2996                 }                                                                                \
2997                 else {                                                                           \
2998                         numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area);         \
2999                 }                                                                                \
3000                 view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);         \
3001         } (void)0
3002
3003                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
3004                 
3005                 if (dm) {
3006                         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
3007                 }
3008
3009                 f = NULL;
3010                 area = 0.0;
3011                 zero_v3(vmid);
3012                 n = 0;
3013                 for (i = 0; i < em->tottri; i++) {
3014                         BMLoop **l = em->looptris[i];
3015                         if (f && l[0]->f != f) {
3016                                 DRAW_EM_MEASURE_STATS_FACEAREA();
3017                                 zero_v3(vmid);
3018                                 area = 0.0;
3019                                 n = 0;
3020                         }
3021
3022                         f = l[0]->f;
3023
3024                         if (dm) {
3025                                 dm->getVertCo(dm, BM_elem_index_get(l[0]->v), v1);
3026                                 dm->getVertCo(dm, BM_elem_index_get(l[1]->v), v2);
3027                                 dm->getVertCo(dm, BM_elem_index_get(l[2]->v), v3);
3028                         }
3029                         else {
3030                                 copy_v3_v3(v1, l[0]->v->co);
3031                                 copy_v3_v3(v2, l[1]->v->co);
3032                                 copy_v3_v3(v3, l[2]->v->co);
3033                         }
3034
3035                         add_v3_v3(vmid, v1);
3036                         add_v3_v3(vmid, v2);
3037                         add_v3_v3(vmid, v3);
3038                         n += 3;
3039                         if (do_global) {
3040                                 mul_mat3_m4_v3(ob->obmat, v1);
3041                                 mul_mat3_m4_v3(ob->obmat, v2);
3042                                 mul_mat3_m4_v3(ob->obmat, v3);
3043                         }
3044                         area += area_tri_v3(v1, v2, v3);
3045                 }
3046
3047                 if (f) {
3048                         DRAW_EM_MEASURE_STATS_FACEAREA();
3049                 }
3050 #undef DRAW_EM_MEASURE_STATS_FACEAREA
3051         }
3052
3053         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
3054                 BMFace *efa;
3055                 const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
3056
3057                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
3058
3059                 if (dm) {
3060                         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
3061                 }
3062
3063                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
3064                         const bool is_face_sel = BM_elem_flag_test_bool(efa, BM_ELEM_SELECT);
3065
3066                         if (is_face_sel || do_moving) {
3067                                 BMIter liter;
3068                                 BMLoop *loop;
3069                                 bool is_first = true;
3070
3071                                 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
3072                                         if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
3073                                                 float angle;
3074                                                 float v2_local[3];
3075
3076                                                 /* lazy init center calc */
3077                                                 if (is_first) {
3078                                                         if (dm) {
3079                                                                 BMLoop *l_iter, *l_first;
3080                                                                 float tvec[3];
3081                                                                 zero_v3(vmid);
3082                                                                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
3083                                                                 do {
3084                                                                         dm->getVertCo(dm, BM_elem_index_get(l_iter->v), tvec);
3085                                                                         add_v3_v3(vmid, tvec);
3086                                                                 } while ((l_iter = l_iter->next) != l_first);
3087                                                                 mul_v3_fl(vmid, 1.0f / (float)efa->len);
3088                                                         }
3089                                                         else {
3090                                                                 BM_face_calc_center_bounds(efa, vmid);
3091                                                         }
3092                                                         is_first = false;
3093                                                 }
3094
3095                                                 if (dm) {
3096                                                         dm->getVertCo(dm, BM_elem_index_get(loop->prev->v), v1);
3097                                                         dm->getVertCo(dm, BM_elem_index_get(loop->v),       v2);
3098                                                         dm->getVertCo(dm, BM_elem_index_get(loop->next->v), v3);
3099                                                 }
3100                                                 else {
3101           &n