Rename any instance of scene layer or render layer in code with view layer
[blender.git] / source / blender / editors / space_view3d / drawarmature.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_view3d/drawarmature.c
29  *  \ingroup spview3d
30  */
31
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #include "DNA_anim_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_constraint_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_view3d_types.h"
43 #include "DNA_object_types.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_math.h"
47 #include "BLI_dlrbTree.h"
48 #include "BLI_utildefines.h"
49
50 #include "BKE_animsys.h"
51 #include "BKE_action.h"
52 #include "BKE_armature.h"
53 #include "BKE_global.h"
54 #include "BKE_modifier.h"
55 #include "BKE_nla.h"
56 #include "BKE_curve.h"
57 #include "BKE_context.h"
58
59 #include "DEG_depsgraph.h"
60
61 #include "BIF_glutil.h"
62
63 #include "ED_armature.h"
64 #include "ED_keyframes_draw.h"
65
66 #include "GPU_basic_shader.h"
67 #include "GPU_batch.h"
68 #include "GPU_immediate.h"
69 #include "GPU_immediate_util.h"
70 #include "GPU_matrix.h"
71
72 #include "UI_resources.h"
73
74 #include "view3d_intern.h"
75
76 #include "GPU_select.h"
77
78 /* *************** Armature Drawing - Coloring API ***************************** */
79
80 /* global here is reset before drawing each bone */
81 static ThemeWireColor *bcolor = NULL;
82 static float fcolor[4] = {0.0f};
83 static bool flat_color;
84
85 /* values of colCode for set_pchan_color */
86 enum {
87         PCHAN_COLOR_NORMAL  = 0,        /* normal drawing */
88         PCHAN_COLOR_SOLID,              /* specific case where "solid" color is needed */
89         PCHAN_COLOR_CONSTS,             /* "constraint" colors (which may/may-not be suppressed) */
90
91         PCHAN_COLOR_SPHEREBONE_BASE,    /* for the 'stick' of sphere (envelope) bones */
92         PCHAN_COLOR_SPHEREBONE_END,     /* for the ends of sphere (envelope) bones */
93         PCHAN_COLOR_LINEBONE            /* for the middle of line-bones */
94 };
95
96 /* This function sets the color-set for coloring a certain bone */
97 static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
98 {
99         bPose *pose = (ob) ? ob->pose : NULL;
100         bArmature *arm = (ob) ? ob->data : NULL;
101         bActionGroup *grp = NULL;
102         short color_index = 0;
103         
104         /* sanity check */
105         if (ELEM(NULL, ob, arm, pose, pchan)) {
106                 bcolor = NULL;
107                 return;
108         }
109         
110         /* only try to set custom color if enabled for armature */
111         if (arm->flag & ARM_COL_CUSTOM) {
112                 /* currently, a bone can only use a custom color set if it's group (if it has one),
113                  * has been set to use one
114                  */
115                 if (pchan->agrp_index) {
116                         grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
117                         if (grp)
118                                 color_index = grp->customCol;
119                 }
120         }
121         
122         /* bcolor is a pointer to the color set to use. If NULL, then the default
123          * color set (based on the theme colors for 3d-view) is used. 
124          */
125         if (color_index > 0) {
126                 bTheme *btheme = UI_GetTheme();
127                 bcolor = &btheme->tarm[(color_index - 1)];
128         }
129         else if (color_index == -1) {
130                 /* use the group's own custom color set (grp is always != NULL here) */
131                 bcolor = &grp->cs;
132         }
133         else {
134                 bcolor = NULL;
135         }
136 }
137
138 /* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */
139 static void cp_shade_color3ub(unsigned char cp[3], const int offset)
140 {
141         int r, g, b;
142         
143         r = offset + (int) cp[0];
144         CLAMP(r, 0, 255);
145         g = offset + (int) cp[1];
146         CLAMP(g, 0, 255);
147         b = offset + (int) cp[2];
148         CLAMP(b, 0, 255);
149         
150         cp[0] = r;
151         cp[1] = g;
152         cp[2] = b;
153 }
154
155 /* This function sets the gl-color for coloring a certain bone (based on bcolor) */
156 static bool set_pchan_color(short colCode, int boneflag, short constflag)
157 {
158         switch (colCode) {
159                 case PCHAN_COLOR_NORMAL:
160                 {
161                         if (bcolor) {
162                                 unsigned char cp[4] = {255};
163                         
164                                 if (boneflag & BONE_DRAW_ACTIVE) {
165                                         copy_v3_v3_char((char *)cp, bcolor->active);
166                                         if (!(boneflag & BONE_SELECTED)) {
167                                                 cp_shade_color3ub(cp, -80);
168                                         }
169                                 }
170                                 else if (boneflag & BONE_SELECTED) {
171                                         copy_v3_v3_char((char *)cp, bcolor->select);
172                                 }
173                                 else {
174                                         /* a bit darker than solid */
175                                         copy_v3_v3_char((char *)cp, bcolor->solid);
176                                         cp_shade_color3ub(cp, -50);
177                                 }
178                         
179                                 rgb_uchar_to_float(fcolor, cp);
180                         }
181                         else {
182                                 if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
183                                         UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor);
184                                 }
185                                 else if (boneflag & BONE_DRAW_ACTIVE) {
186                                         UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor);
187                                 }
188                                 else if (boneflag & BONE_SELECTED) {
189                                         UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
190                                 }
191                                 else {
192                                         UI_GetThemeColor4fv(TH_WIRE, fcolor);
193                                 }
194                         }
195         
196                         return true;
197                 }
198                 case PCHAN_COLOR_SOLID:
199                 {
200                         if (bcolor) {
201                                 rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid);
202                         }
203                         else {
204                                 UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
205                         }
206                         
207                         return true;
208                 }
209                 case PCHAN_COLOR_CONSTS:
210                 {
211                         if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) {
212                                 unsigned char cp[4];
213                                 if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80);
214                                 else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80);
215                                 else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80);
216                                 else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80);
217
218                                 rgba_uchar_to_float(fcolor, cp);
219
220                                 return true;
221                         }
222                         return false;
223                 }
224                 case PCHAN_COLOR_SPHEREBONE_BASE:
225                 {
226                         if (bcolor) {
227                                 unsigned char cp[4] = {255};
228
229                                 if (boneflag & BONE_DRAW_ACTIVE) {
230                                         copy_v3_v3_char((char *)cp, bcolor->active);
231                                 }
232                                 else if (boneflag & BONE_SELECTED) {
233                                         copy_v3_v3_char((char *)cp, bcolor->select);
234                                 }
235                                 else {
236                                         copy_v3_v3_char((char *)cp, bcolor->solid);
237                                 }
238
239                                 rgb_uchar_to_float(fcolor, cp);
240                         }
241                         else {
242                                 if (boneflag & BONE_DRAW_ACTIVE) {
243                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor);
244                                 }
245                                 else if (boneflag & BONE_SELECTED) {
246                                         UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
247                                 }
248                                 else {
249                                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
250                                 }
251                         }
252                         
253                         return true;
254                 }
255                 case PCHAN_COLOR_SPHEREBONE_END:
256                 {
257                         if (bcolor) {
258                                 unsigned char cp[4] = {255};
259
260                                 if (boneflag & BONE_DRAW_ACTIVE) {
261                                         copy_v3_v3_char((char *)cp, bcolor->active);
262                                         cp_shade_color3ub(cp, 10);
263                                 }
264                                 else if (boneflag & BONE_SELECTED) {
265                                         copy_v3_v3_char((char *)cp, bcolor->select);
266                                         cp_shade_color3ub(cp, -30);
267                                 }
268                                 else {
269                                         copy_v3_v3_char((char *)cp, bcolor->solid);
270                                         cp_shade_color3ub(cp, -30);
271                                 }
272                         
273                                 rgb_uchar_to_float(fcolor, cp);
274                         }
275                         else {
276                                 if (boneflag & BONE_DRAW_ACTIVE) {
277                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor);
278                                 }
279                                 else if (boneflag & BONE_SELECTED) {
280                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor);
281                                 }
282                                 else {
283                                         UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
284                                 }
285                         }
286                         break;
287                 }
288                 case PCHAN_COLOR_LINEBONE:
289                 {
290                         /* inner part in background color or constraint */
291                         if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) {
292                                 unsigned char cp[4];
293                                 if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255);
294                                 else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255);
295                                 else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255);
296                                 else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255);
297                                 else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp);  /* PCHAN_HAS_ACTION */
298
299                                 rgb_uchar_to_float(fcolor, cp);
300                         }
301                         else {
302                                 if (bcolor) {
303                                         const char *cp = bcolor->solid;
304                                         rgb_uchar_to_float(fcolor, (unsigned char *)cp);
305                                         fcolor[3] = 204.f / 255.f;
306                                 }
307                                 else {
308                                         UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
309                                 }
310                         }
311                 
312                         return true;
313                 }
314         }
315         
316         return false;
317 }
318
319 static void set_ebone_color(const unsigned int boneflag)
320 {
321         if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
322                 UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor);
323         }
324         else if (boneflag & BONE_DRAW_ACTIVE) {
325                 UI_GetThemeColorBlendShade4fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, fcolor);
326         }
327         else if (boneflag & BONE_SELECTED) {
328                 UI_GetThemeColorShade4fv(TH_EDGE_SELECT, -20, fcolor);
329         }
330         else {
331                 UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
332         }
333 }
334
335 /* *************** Armature drawing, helper calls for parts ******************* */
336
337 static void add_solid_flat_triangle(Gwn_VertBuf *vbo, unsigned int *vertex, unsigned int pos, unsigned int nor,
338                                     const float p1[3], const float p2[3], const float p3[3], const float n[3])
339 {
340         GWN_vertbuf_attr_set(vbo, nor, *vertex, n);
341         GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p1);
342         GWN_vertbuf_attr_set(vbo, nor, *vertex, n);
343         GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p2);
344         GWN_vertbuf_attr_set(vbo, nor, *vertex, n);
345         GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p3);
346 }
347
348 /* half the cube, in Y */
349 static const float cube_vert[8][3] = {
350         {-1.0,  0.0, -1.0},
351         {-1.0,  0.0,  1.0},
352         {-1.0,  1.0,  1.0},
353         {-1.0,  1.0, -1.0},
354         { 1.0,  0.0, -1.0},
355         { 1.0,  0.0,  1.0},
356         { 1.0,  1.0,  1.0},
357         { 1.0,  1.0, -1.0},
358 };
359
360 static const float cube_wire[24] = {
361         0, 1, 1, 2, 2, 3, 3, 0,
362         4, 5, 5, 6, 6, 7, 7, 4,
363         0, 4, 1, 5, 2, 6, 3, 7,
364 };
365
366 static void drawsolidcube_size(float xsize, float ysize, float zsize)
367 {
368         static Gwn_VertFormat format = {0};
369         static Gwn_VertBuf vbo = {{0}};
370         static Gwn_Batch batch = {{0}};
371         const float light_vec[3] = {0.0f, 0.0f, 1.0f};
372
373         if (format.attrib_ct == 0) {
374                 unsigned int i = 0;
375                 float n[3] = {0.0f};
376                 /* Vertex format */
377                 unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
378                 unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
379
380                 /* Vertices */
381                 GWN_vertbuf_init_with_format(&vbo, &format);
382                 GWN_vertbuf_data_alloc(&vbo, 36);
383
384                 n[0] = -1.0;
385                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[1], cube_vert[2], n);
386                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[3], cube_vert[0], n);
387                 n[0] = 0;
388                 n[1] = -1.0;
389                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[4], cube_vert[5], n);
390                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[5], cube_vert[1], cube_vert[0], n);
391                 n[1] = 0;
392                 n[0] = 1.0;
393                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[4], cube_vert[7], cube_vert[6], n);
394                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[5], cube_vert[4], n);
395                 n[0] = 0;
396                 n[1] = 1.0;
397                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[3], cube_vert[2], n);
398                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[6], cube_vert[7], n);
399                 n[1] = 0;
400                 n[2] = 1.0;
401                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[1], cube_vert[5], cube_vert[6], n);
402                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[2], cube_vert[1], n);
403                 n[2] = -1.0;
404                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[4], cube_vert[0], n);
405                 add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[3], cube_vert[7], n);
406
407                 GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL);
408         }
409
410         gpuPushMatrix();
411         gpuScale3f(xsize, ysize, zsize);
412
413         if (flat_color) {
414                 GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
415         }
416         else {
417                 /* TODO replace with good default lighting shader ? */
418                 GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING);
419                 GWN_batch_uniform_3fv(&batch, "light", light_vec);
420         }
421         GWN_batch_uniform_4fv(&batch, "color", fcolor);
422         GWN_batch_draw(&batch);
423
424         gpuPopMatrix();
425 }
426
427 static void drawcube_size(float xsize, float ysize, float zsize)
428 {
429         static Gwn_VertFormat format = {0};
430         static Gwn_VertBuf vbo = {{0}};
431         static Gwn_IndexBufBuilder elb = {0};
432         static Gwn_IndexBuf el = {0};
433         static Gwn_Batch batch = {{0}};
434
435         if (format.attrib_ct == 0) {
436                 /* Vertex format */
437                 unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
438
439                 /* Elements */
440                 GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 8);
441                 for (int i = 0; i < 12; ++i) {
442                         GWN_indexbuf_add_line_verts(&elb, cube_wire[i * 2], cube_wire[i * 2 + 1]);
443                 }
444                 GWN_indexbuf_build_in_place(&elb, &el);
445
446                 /* Vertices */
447                 GWN_vertbuf_init_with_format(&vbo, &format);
448                 GWN_vertbuf_data_alloc(&vbo, 8);
449                 for (int i = 0; i < 8; ++i) {
450                         GWN_vertbuf_attr_set(&vbo, pos, i, cube_vert[i]);
451                 }
452
453                 GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el);
454                 GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
455         }
456
457         gpuPushMatrix();
458         gpuScale3f(xsize, ysize, zsize);
459
460         GWN_batch_program_use_begin(&batch);
461         GWN_batch_uniform_4fv(&batch, "color", fcolor);
462         GWN_batch_draw(&batch);
463
464         gpuPopMatrix();
465 }
466
467
468 static void draw_bonevert(void)
469 {
470         static Gwn_VertFormat format = {0};
471         static Gwn_VertBuf vbo = {{0}};
472         static Gwn_Batch batch = {{0}};
473
474         if (format.attrib_ct == 0) {
475                 /* Vertex format */
476                 unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
477
478                 /* Vertices */
479                 GWN_vertbuf_init_with_format(&vbo, &format);
480                 GWN_vertbuf_data_alloc(&vbo, 96);
481                 for (int i = 0; i < 16; ++i) {
482                         float vert[3] = {0.f, 0.f, 0.f};
483                         const float r = 0.05f;
484
485                         vert[0] = r * cosf(2 * M_PI * i / 16.f);
486                         vert[1] = r * sinf(2 * M_PI * i / 16.f);
487                         GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 0, vert);
488                         vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f);
489                         vert[1] = r * sinf(2 * M_PI * (i + 1) / 16.f);
490                         GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 1, vert);
491
492                         vert[0] = 0.f;
493                         vert[1] = r * cosf(2 * M_PI * i / 16.f);
494                         vert[2] = r * sinf(2 * M_PI * i / 16.f);
495                         GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 2, vert);
496                         vert[1] = r * cosf(2 * M_PI * (i + 1) / 16.f);
497                         vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f);
498                         GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 3, vert);
499
500                         vert[1] = 0.f;
501                         vert[0] = r * cosf(2 * M_PI * i / 16.f);
502                         vert[2] = r * sinf(2 * M_PI * i / 16.f);
503                         GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 4, vert);
504                         vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f);
505                         vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f);
506                         GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 5, vert);
507                 }
508
509                 GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, NULL);
510                 GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
511         }
512
513         GWN_batch_program_use_begin(&batch);
514         GWN_batch_uniform_4fv(&batch, "color", fcolor);
515         GWN_batch_draw(&batch);
516 }
517
518 static void draw_bonevert_solid(void)
519 {
520         Gwn_Batch *batch = GPU_batch_preset_sphere(0);
521         const float light_vec[3] = {0.0f, 0.0f, 1.0f};
522
523         gpuPushMatrix();
524         gpuScaleUniform(0.05);
525
526         if (flat_color) {
527                 GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
528         }
529         else {
530                 /* TODO replace with good default lighting shader ? */
531                 GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING);
532                 GWN_batch_uniform_3fv(batch, "light", light_vec);
533         }
534         GWN_batch_uniform_4fv(batch, "color", fcolor);
535         GWN_batch_draw(batch);
536
537         gpuPopMatrix();
538 }
539
540 static const float bone_octahedral_verts[6][3] = {
541         { 0.0f, 0.0f,  0.0f},
542         { 0.1f, 0.1f,  0.1f},
543         { 0.1f, 0.1f, -0.1f},
544         {-0.1f, 0.1f, -0.1f},
545         {-0.1f, 0.1f,  0.1f},
546         { 0.0f, 1.0f,  0.0f}
547 };
548
549 static const unsigned int bone_octahedral_wire[24] = {
550         0, 1,  1, 5,  5, 3,  3, 0,
551         0, 4,  4, 5,  5, 2,  2, 0,
552         1, 2,  2, 3,  3, 4,  4, 1,
553 };
554
555 static const unsigned int bone_octahedral_solid_tris[8][3] = {
556         {2, 1, 0}, /* bottom */
557         {3, 2, 0},
558         {4, 3, 0},
559         {1, 4, 0},
560
561         {5, 1, 2}, /* top */
562         {5, 2, 3},
563         {5, 3, 4},
564         {5, 4, 1}
565 };
566
567 /* aligned with bone_octahedral_solid_tris */
568 static const float bone_octahedral_solid_normals[8][3] = {
569         { M_SQRT1_2,   -M_SQRT1_2,    0.00000000f},
570         {-0.00000000f, -M_SQRT1_2,   -M_SQRT1_2},
571         {-M_SQRT1_2,   -M_SQRT1_2,    0.00000000f},
572         { 0.00000000f, -M_SQRT1_2,    M_SQRT1_2},
573         { 0.99388373f,  0.11043154f, -0.00000000f},
574         { 0.00000000f,  0.11043154f, -0.99388373f},
575         {-0.99388373f,  0.11043154f,  0.00000000f},
576         { 0.00000000f,  0.11043154f,  0.99388373f}
577 };
578
579 static void draw_bone_octahedral(void)
580 {
581         static Gwn_VertFormat format = {0};
582         static Gwn_VertBuf vbo = {{0}};
583         static Gwn_IndexBufBuilder elb = {0};
584         static Gwn_IndexBuf el = {0};
585         static Gwn_Batch batch = {{0}};
586
587         if (format.attrib_ct == 0) {
588                 /* Vertex format */
589                 unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
590
591                 /* Elements */
592                 GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 6);
593                 for (int i = 0; i < 12; ++i) {
594                         GWN_indexbuf_add_line_verts(&elb, bone_octahedral_wire[i * 2], bone_octahedral_wire[i * 2 + 1]);
595                 }
596                 GWN_indexbuf_build_in_place(&elb, &el);
597
598                 /* Vertices */
599                 GWN_vertbuf_init_with_format(&vbo, &format);
600                 GWN_vertbuf_data_alloc(&vbo, 6);
601                 for (int i = 0; i < 6; ++i) {
602                         GWN_vertbuf_attr_set(&vbo, pos, i, bone_octahedral_verts[i]);
603                 }
604
605                 GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el);
606                 GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
607         }
608
609         GWN_batch_program_use_begin(&batch);
610         GWN_batch_uniform_4fv(&batch, "color", fcolor);
611         GWN_batch_draw(&batch);
612 }
613
614 static void draw_bone_solid_octahedral(void)
615 {
616         static Gwn_VertFormat format = {0};
617         static Gwn_VertBuf vbo = {{0}};
618         static Gwn_Batch batch = {{0}};
619         const float light_vec[3] = {0.0f, 0.0f, 1.0f};
620
621         if (format.attrib_ct == 0) {
622                 unsigned int v_idx = 0;
623                 /* Vertex format */
624                 unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
625                 unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
626
627                 /* Vertices */
628                 GWN_vertbuf_init_with_format(&vbo, &format);
629                 GWN_vertbuf_data_alloc(&vbo, 24);
630
631                 for (int i = 0; i < 8; i++) {
632                         add_solid_flat_triangle(&vbo, &v_idx, pos, nor,
633                                                 bone_octahedral_verts[bone_octahedral_solid_tris[i][0]],
634                                                 bone_octahedral_verts[bone_octahedral_solid_tris[i][1]],
635                                                 bone_octahedral_verts[bone_octahedral_solid_tris[i][2]],
636                                                 bone_octahedral_solid_normals[i]);
637                 }
638
639                 GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL);
640         }
641
642         if (flat_color) {
643                 GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
644         }
645         else {
646                 /* TODO replace with good default lighting shader ? */
647                 GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING);
648                 GWN_batch_uniform_3fv(&batch, "light", light_vec);
649         }
650         GWN_batch_uniform_4fv(&batch, "color", fcolor);
651         GWN_batch_draw(&batch);
652 }
653
654 /* *************** Armature drawing, bones ******************* */
655
656
657 static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, int id)
658 {
659         /*      Draw root point if we are not connected */
660         if ((boneflag & BONE_CONNECTED) == 0) {
661                 if (id != -1)
662                         GPU_select_load_id(id | BONESEL_ROOT);
663                 
664                 if (dt <= OB_WIRE) {
665                         if (armflag & ARM_EDITMODE) {
666                                 if (boneflag & BONE_ROOTSEL) {
667                                         UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
668                                 }
669                                 else {
670                                         UI_GetThemeColor4fv(TH_VERTEX, fcolor);
671                                 }
672                         }
673                 }
674                 else {
675                         if (armflag & ARM_POSEMODE) 
676                                 set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0);
677                         else {
678                                 UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
679                         }
680                 }
681                 
682                 if (dt > OB_WIRE) 
683                         draw_bonevert_solid();
684                 else 
685                         draw_bonevert();
686         }
687         
688         /*      Draw tip point */
689         if (id != -1)
690                 GPU_select_load_id(id | BONESEL_TIP);
691         
692         if (dt <= OB_WIRE) {
693                 if (armflag & ARM_EDITMODE) {
694                         if (boneflag & BONE_TIPSEL) {
695                                 UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
696                         }
697                         else {
698                                 UI_GetThemeColor4fv(TH_VERTEX, fcolor);
699                         }
700                 }
701         }
702         else {
703                 if (armflag & ARM_POSEMODE) 
704                         set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0);
705                 else {
706                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
707                 }
708         }
709         
710         gpuPushMatrix();
711         gpuTranslate2f(0.0f, 1.0f);
712         if (dt > OB_WIRE) 
713                 draw_bonevert_solid();
714         else 
715                 draw_bonevert();
716         gpuPopMatrix();
717 }
718
719 /* 16 values of sin function (still same result!) */
720 static const float si[16] = {
721         0.00000000f,
722         0.20129852f, 0.39435585f,
723         0.57126821f, 0.72479278f,
724         0.84864425f, 0.93775213f,
725         0.98846832f, 0.99871650f,
726         0.96807711f, 0.89780453f,
727         0.79077573f, 0.65137248f,
728         0.48530196f, 0.29936312f,
729         0.10116832f
730 };
731 /* 16 values of cos function (still same result!) */
732 static const float co[16] = {
733         1.00000000f,
734         0.97952994f, 0.91895781f,
735         0.82076344f, 0.68896691f,
736         0.52896401f, 0.34730525f,
737         0.15142777f, -0.05064916f,
738         -0.25065253f, -0.44039415f,
739         -0.61210598f, -0.75875812f,
740         -0.87434661f, -0.95413925f,
741         -0.99486932f
742 };
743
744
745
746 /* smat, imat = mat & imat to draw screenaligned */
747 static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChannel *pchan, EditBone *ebone)
748 {
749         float head, tail, dist /*, length*/;
750         float *headvec, *tailvec, dirvec[3];
751         
752         /* figure out the sizes of spheres */
753         if (ebone) {
754                 /* this routine doesn't call get_matrix_editbone() that calculates it */
755                 ebone->length = len_v3v3(ebone->head, ebone->tail);
756
757                 /*length = ebone->length;*/ /*UNUSED*/
758                 tail = ebone->rad_tail;
759                 dist = ebone->dist;
760                 if (ebone->parent && (ebone->flag & BONE_CONNECTED))
761                         head = ebone->parent->rad_tail;
762                 else
763                         head = ebone->rad_head;
764                 headvec = ebone->head;
765                 tailvec = ebone->tail;
766         }
767         else {
768                 /*length = pchan->bone->length;*/ /*UNUSED*/
769                 tail = pchan->bone->rad_tail;
770                 dist = pchan->bone->dist;
771                 if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
772                         head = pchan->parent->bone->rad_tail;
773                 else
774                         head = pchan->bone->rad_head;
775                 headvec = pchan->pose_head;
776                 tailvec = pchan->pose_tail;
777         }
778         
779         /* ***** draw it ***** */
780         
781         /* move vector to viewspace */
782         sub_v3_v3v3(dirvec, tailvec, headvec);
783         mul_mat3_m4_v3(smat, dirvec);
784         /* clear zcomp */
785         dirvec[2] = 0.0f;
786
787         if (head != tail) {
788                 /* correction when viewing along the bones axis
789                  * it pops in and out but better then artifacts, [#23841] */
790                 float view_dist = len_v2(dirvec);
791
792                 if (head - view_dist > tail) {
793                         tailvec = headvec;
794                         tail = head;
795                         zero_v3(dirvec);
796                         dirvec[0] = 0.00001;  /* XXX. weak but ok */
797                 }
798                 else if (tail - view_dist > head) {
799                         headvec = tailvec;
800                         head = tail;
801                         zero_v3(dirvec);
802                         dirvec[0] = 0.00001;  /* XXX. weak but ok */
803                 }
804         }
805
806         /* move vector back */
807         mul_mat3_m4_v3(imat, dirvec);
808         
809         if (0.0f != normalize_v3(dirvec)) {
810                 float norvec[3], vec1[3], vec2[3], vec[3];
811                 int a;
812                 
813                 //mul_v3_fl(dirvec, head);
814                 cross_v3_v3v3(norvec, dirvec, imat[2]);
815
816                 Gwn_VertFormat *format = immVertexFormat();
817                 unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
818
819                 immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
820                 immBegin(GWN_PRIM_TRI_STRIP, 66);
821                 immUniformColor4ub(255, 255, 255, 50);
822                 
823                 for (a = 0; a < 16; a++) {
824                         vec[0] = -si[a] * dirvec[0] + co[a] * norvec[0];
825                         vec[1] = -si[a] * dirvec[1] + co[a] * norvec[1];
826                         vec[2] = -si[a] * dirvec[2] + co[a] * norvec[2];
827
828                         madd_v3_v3v3fl(vec1, headvec, vec, head);
829                         madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
830                         
831                         immVertex3fv(pos, vec1);
832                         immVertex3fv(pos, vec2);
833                 }
834                 
835                 for (a = 15; a >= 0; a--) {
836                         vec[0] = si[a] * dirvec[0] + co[a] * norvec[0];
837                         vec[1] = si[a] * dirvec[1] + co[a] * norvec[1];
838                         vec[2] = si[a] * dirvec[2] + co[a] * norvec[2];
839
840                         madd_v3_v3v3fl(vec1, tailvec, vec, tail);
841                         madd_v3_v3v3fl(vec2, tailvec, vec, tail + dist);
842                         
843                         immVertex3fv(pos, vec1);
844                         immVertex3fv(pos, vec2);
845                 }
846                 /* make it cyclic... */
847                 
848                 vec[0] = -si[0] * dirvec[0] + co[0] * norvec[0];
849                 vec[1] = -si[0] * dirvec[1] + co[0] * norvec[1];
850                 vec[2] = -si[0] * dirvec[2] + co[0] * norvec[2];
851
852                 madd_v3_v3v3fl(vec1, headvec, vec, head);
853                 madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
854
855                 immVertex3fv(pos, vec1);
856                 immVertex3fv(pos, vec2);
857                 
858                 immEnd();
859                 immUnbindProgram();
860         }
861 }
862
863
864 /* smat, imat = mat & imat to draw screenaligned */
865 static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
866                                   int armflag, int boneflag, short constflag, unsigned int id,
867                                   bPoseChannel *pchan, EditBone *ebone)
868 {
869         float head, tail /*, length*/;
870         float *headvec, *tailvec, dirvec[3];
871
872         Gwn_VertFormat *format = immVertexFormat();
873         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
874
875         immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
876         
877         /* figure out the sizes of spheres */
878         if (ebone) {
879                 /* this routine doesn't call get_matrix_editbone() that calculates it */
880                 ebone->length = len_v3v3(ebone->head, ebone->tail);
881                 
882                 /*length = ebone->length;*/ /*UNUSED*/
883                 tail = ebone->rad_tail;
884                 if (ebone->parent && (boneflag & BONE_CONNECTED))
885                         head = ebone->parent->rad_tail;
886                 else
887                         head = ebone->rad_head;
888                 headvec = ebone->head;
889                 tailvec = ebone->tail;
890         }
891         else {
892                 /*length = pchan->bone->length;*/ /*UNUSED*/
893                 tail = pchan->bone->rad_tail;
894                 if ((pchan->parent) && (boneflag & BONE_CONNECTED))
895                         head = pchan->parent->bone->rad_tail;
896                 else
897                         head = pchan->bone->rad_head;
898                 headvec = pchan->pose_head;
899                 tailvec = pchan->pose_tail;
900         }
901         
902         /* sphere root color */
903         if (armflag & ARM_EDITMODE) {
904                 if (boneflag & BONE_ROOTSEL) {
905                         UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
906                 }
907                 else {
908                         UI_GetThemeColor4fv(TH_VERTEX, fcolor);
909                 }
910         }
911         else if (armflag & ARM_POSEMODE)
912                 set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
913
914         immUniformColor4fv(fcolor);
915
916         /*      Draw root point if we are not connected */
917         if ((boneflag & BONE_CONNECTED) == 0) {
918                 if (id != -1)
919                         GPU_select_load_id(id | BONESEL_ROOT);
920                 
921                 imm_drawcircball(headvec, head, imat, pos);
922         }
923         
924         /*      Draw tip point */
925         if (armflag & ARM_EDITMODE) {
926                 if (boneflag & BONE_TIPSEL) {
927                         UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
928                 }
929                 else {
930                         UI_GetThemeColor4fv(TH_VERTEX, fcolor);
931                 }
932         }
933         
934         if (id != -1)
935                 GPU_select_load_id(id | BONESEL_TIP);
936         
937         imm_drawcircball(tailvec, tail, imat, pos);
938         
939         /* base */
940         if (armflag & ARM_EDITMODE) {
941                 if (boneflag & BONE_SELECTED) {
942                         UI_GetThemeColor4fv(TH_SELECT, fcolor);
943                 }
944                 else {
945                         UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
946                 }
947         }
948         
949         sub_v3_v3v3(dirvec, tailvec, headvec);
950         
951         /* move vector to viewspace */
952         mul_mat3_m4_v3(smat, dirvec);
953         /* clear zcomp */
954         dirvec[2] = 0.0f;
955         /* move vector back */
956         mul_mat3_m4_v3(imat, dirvec);
957         
958         if (0.0f != normalize_v3(dirvec)) {
959                 float norvech[3], norvect[3], vec[3];
960                 
961                 copy_v3_v3(vec, dirvec);
962                 
963                 mul_v3_fl(dirvec, head);
964                 cross_v3_v3v3(norvech, dirvec, imat[2]);
965                 
966                 mul_v3_fl(vec, tail);
967                 cross_v3_v3v3(norvect, vec, imat[2]);
968                 
969                 if (id != -1)
970                         GPU_select_load_id(id | BONESEL_BONE);
971                 
972                 immBegin(GWN_PRIM_LINES, 4);
973
974                 add_v3_v3v3(vec, headvec, norvech);
975                 immVertex3fv(pos, vec);
976
977                 add_v3_v3v3(vec, tailvec, norvect);
978                 immVertex3fv(pos, vec);
979
980                 sub_v3_v3v3(vec, headvec, norvech);
981                 immVertex3fv(pos, vec);
982
983                 sub_v3_v3v3(vec, tailvec, norvect);
984                 immVertex3fv(pos, vec);
985                 
986                 immEnd();
987         }
988
989         immUnbindProgram();
990 }
991
992 /* does wire only for outline selecting */
993 static void draw_sphere_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
994                              bPoseChannel *pchan, EditBone *ebone)
995 {
996         Gwn_Batch *sphere = GPU_batch_preset_sphere(1);
997         float head, tail, length;
998         float fac1, fac2, size1, size2;
999         const float light_vec[3] = {0.0f, 0.0f, 1.0f};
1000
1001         /* dt is always OB_SOlID */
1002         GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
1003         GWN_batch_uniform_3fv(sphere, "light", light_vec);
1004
1005         gpuPushMatrix();
1006
1007         /* figure out the sizes of spheres */
1008         if (ebone) {
1009                 length = ebone->length;
1010                 tail = ebone->rad_tail;
1011                 if (ebone->parent && (boneflag & BONE_CONNECTED))
1012                         head = ebone->parent->rad_tail;
1013                 else
1014                         head = ebone->rad_head;
1015         }
1016         else {
1017                 length = pchan->bone->length;
1018                 tail = pchan->bone->rad_tail;
1019                 if (pchan->parent && (boneflag & BONE_CONNECTED))
1020                         head = pchan->parent->bone->rad_tail;
1021                 else
1022                         head = pchan->bone->rad_head;
1023         }
1024         
1025         /* move to z-axis space */
1026         gpuRotateAxis(-90.0f, 'X');
1027
1028         /* sphere root color */
1029         if (armflag & ARM_EDITMODE) {
1030                 if (boneflag & BONE_ROOTSEL)
1031                         UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
1032                 else
1033                         UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
1034         }
1035         else if (armflag & ARM_POSEMODE)
1036                 set_pchan_color(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
1037         else if (dt == OB_SOLID)
1038                 UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
1039         
1040         /*      Draw root point if we are not connected */
1041         if ((boneflag & BONE_CONNECTED) == 0) {
1042                 if (id != -1)
1043                         GPU_select_load_id(id | BONESEL_ROOT);
1044                 gpuPushMatrix();
1045                 gpuScaleUniform(head);
1046                 GWN_batch_uniform_4fv(sphere, "color", fcolor);
1047                 GWN_batch_draw(sphere);
1048                 gpuPopMatrix();
1049         }
1050         
1051         /*      Draw tip point */
1052         if (armflag & ARM_EDITMODE) {
1053                 if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
1054                 else UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
1055         }
1056
1057         if (id != -1)
1058                 GPU_select_load_id(id | BONESEL_TIP);
1059         
1060         gpuTranslate3f(0.0f, 0.0f, length);
1061
1062         gpuPushMatrix();
1063         gpuScaleUniform(tail);
1064         GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */
1065         GWN_batch_uniform_4fv(sphere, "color", fcolor);
1066         GWN_batch_draw(sphere);
1067         gpuPopMatrix();
1068
1069         gpuTranslate3f(0.0f, 0.0f, -length);
1070         
1071         /* base */
1072         if (armflag & ARM_EDITMODE) {
1073                 if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_SELECT, fcolor);
1074                 else UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
1075         }
1076         else if (armflag & ARM_POSEMODE)
1077                 set_pchan_color(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
1078         else if (dt == OB_SOLID)
1079                 UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
1080
1081         GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */
1082         GWN_batch_uniform_4fv(sphere, "color", fcolor);
1083         
1084         fac1 = (length - head) / length;
1085         fac2 = (length - tail) / length;
1086         
1087         if (length > (head + tail)) {
1088                 size1 = fac2 * tail + (1.0f - fac2) * head;
1089                 size2 = fac1 * head + (1.0f - fac1) * tail;
1090
1091                 if (id != -1)
1092                         GPU_select_load_id(id | BONESEL_BONE);
1093                 
1094                 /* draw sphere on extrema */
1095                 gpuPushMatrix();
1096                 gpuTranslate3f(0.0f, 0.0f, length - tail);
1097                 gpuScaleUniform(size1);
1098
1099                 GWN_batch_draw(sphere);
1100                 gpuPopMatrix();
1101
1102                 gpuPushMatrix();
1103                 gpuTranslate3f(0.0f, 0.0f, head);
1104                 gpuScaleUniform(size2);
1105
1106                 GWN_batch_draw(sphere);
1107                 gpuPopMatrix();
1108
1109                 /* draw cynlinder between spheres */
1110                 glEnable(GL_POLYGON_OFFSET_FILL);
1111                 glPolygonOffset(-1.0f, -1.0f);
1112
1113                 Gwn_VertFormat *format = immVertexFormat();
1114                 unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
1115                 unsigned int nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
1116
1117                 immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING);
1118                 immUniformColor4fv(fcolor);
1119                 immUniform3fv("light", light_vec);
1120
1121                 gpuTranslate3f(0.0f, 0.0f, head);
1122                 imm_draw_cylinder_fill_normal_3d(pos, nor, size2, size1, length - head - tail, 16, 1);
1123
1124                 immUnbindProgram();
1125                 
1126                 glDisable(GL_POLYGON_OFFSET_FILL);
1127         }
1128         else {
1129                 size1 = fac1 * head + (1.0f - fac1) * tail;
1130
1131                 /* 1 sphere in center */
1132                 gpuTranslate3f(0.0f, 0.0f, (head + length - tail) / 2.0f);
1133
1134                 gpuScaleUniform(size1);
1135                 GWN_batch_draw(sphere);
1136         }
1137         
1138         gpuPopMatrix();
1139 }
1140
1141 static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id,
1142                            bPoseChannel *pchan, EditBone *ebone)
1143 {
1144         float length;
1145         
1146         if (pchan) 
1147                 length = pchan->bone->length;
1148         else 
1149                 length = ebone->length;
1150         
1151         Gwn_VertFormat *format = immVertexFormat();
1152         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
1153
1154         gpuPushMatrix();
1155         gpuScaleUniform(length);
1156         
1157         /* this chunk not in object mode */
1158         if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) {
1159                 glLineWidth(4.0f);
1160                 glPointSize(8.0f);
1161
1162                 if (armflag & ARM_POSEMODE)
1163                         set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
1164                 else if (armflag & ARM_EDITMODE) {
1165                         UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
1166                 }
1167
1168                 /* line */
1169                 immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
1170                 immUniformColor4fv(fcolor);
1171
1172                 if (id != -1)
1173                         GPU_select_load_id(id | BONESEL_BONE);
1174
1175                 immBegin(GWN_PRIM_LINES, 2);
1176                 immVertex3f(pos, 0.0f, 1.0f, 0.0f);
1177                 immVertex3f(pos, 0.0f, 0.0f, 0.0f);
1178                 immEnd();
1179
1180                 immUnbindProgram();
1181
1182                 immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
1183                 immUniformColor4fv(fcolor);
1184
1185                 /*      Draw root point if we are not connected */
1186                 if ((boneflag & BONE_CONNECTED) == 0) {
1187                         if (G.f & G_PICKSEL)
1188                                 GPU_select_load_id(id | BONESEL_ROOT);
1189
1190                         immBegin(GWN_PRIM_POINTS, 1);
1191                         immVertex3f(pos, 0.0f, 0.0f, 0.0f);
1192                         immEnd();
1193                 }
1194
1195                 /* tip */
1196                 if (G.f & G_PICKSEL)
1197                         GPU_select_load_id(id | BONESEL_TIP);
1198
1199                 immBegin(GWN_PRIM_POINTS, 1);
1200                 immVertex3f(pos, 0.0f, 1.0f, 0.0f);
1201                 immEnd();
1202
1203                 immUnbindProgram();
1204
1205
1206                 /* further we send no names */
1207                 if (id != -1)
1208                         GPU_select_load_id(id & 0xFFFF);  /* object tag, for bordersel optim */
1209                 
1210                 if (armflag & ARM_POSEMODE)
1211                         set_pchan_color(PCHAN_COLOR_LINEBONE, boneflag, constflag);
1212         }
1213
1214         /* Now draw the inner color */
1215         glLineWidth(2.0f);
1216         glPointSize(5.0f);
1217
1218         /* line */
1219         if (armflag & ARM_EDITMODE) {
1220                 if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor);
1221                 else UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
1222         }
1223
1224         immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
1225         immUniformColor4fv(fcolor);
1226
1227         immBegin(GWN_PRIM_LINES, 2);
1228         immVertex3f(pos, 0.0f, 1.0f, 0.0f);
1229         immVertex3f(pos, 0.0f, 0.0f, 0.0f);
1230         immEnd();
1231
1232         immUnbindProgram();
1233
1234         immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
1235
1236         /*Draw root point if we are not connected */
1237         if ((boneflag & BONE_CONNECTED) == 0) {
1238                 if (armflag & ARM_EDITMODE) {
1239                         if (boneflag & BONE_ROOTSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
1240                         else UI_GetThemeColor4fv(TH_VERTEX, fcolor);
1241                 }
1242                 immUniformColor4fv(fcolor);
1243                 immBegin(GWN_PRIM_POINTS, 1);
1244                 immVertex3f(pos, 0.0f, 0.0f, 0.0f);
1245                 immEnd();
1246         }
1247
1248         /* tip */
1249         if ((G.f & G_PICKSEL) == 0) {
1250                 /* no bitmap in selection mode, crashes 3d cards... */
1251                 if (armflag & ARM_EDITMODE) {
1252                         if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
1253                         else UI_GetThemeColor4fv(TH_VERTEX, fcolor);
1254                 }
1255                 immUniformColor4fv(fcolor);
1256                 immBegin(GWN_PRIM_POINTS, 1);
1257                 immVertex3f(pos, 0.0f, 1.0f, 0.0f);
1258                 immEnd();
1259         }
1260
1261         immUnbindProgram();
1262
1263         gpuPopMatrix();
1264 }
1265
1266 /* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings 
1267  *
1268  * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight"
1269  * position here anyway), and that we can simply apply the bbone settings to get the desired effect...
1270  */
1271 static void ebone_spline_preview(EditBone *ebone, Mat4 result_array[MAX_BBONE_SUBDIV])
1272 {
1273         float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f;
1274         float mat3[3][3];
1275         float data[MAX_BBONE_SUBDIV + 1][4], *fp;
1276         int a;
1277         
1278         length = ebone->length;
1279         
1280         hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
1281         hlength2 = ebone->ease2 * length * 0.390464f;
1282         
1283         /* find the handle points, since this is inside bone space, the
1284          * first point = (0, 0, 0)
1285          * last point =  (0, length, 0)
1286          *
1287          * we also just apply all the "extra effects", since they're the whole reason we're doing this...
1288          */
1289         h1[0] = ebone->curveInX;
1290         h1[1] = hlength1;
1291         h1[2] = ebone->curveInY;
1292         roll1 = ebone->roll1;
1293         
1294         h2[0] = ebone->curveOutX;
1295         h2[1] = -hlength2;
1296         h2[2] = ebone->curveOutY;
1297         roll2 = ebone->roll2;
1298         
1299         /* make curve */
1300         if (ebone->segments > MAX_BBONE_SUBDIV)
1301                 ebone->segments = MAX_BBONE_SUBDIV;
1302
1303         BKE_curve_forward_diff_bezier(0.0f,  h1[0],                               h2[0],                               0.0f,   data[0],     MAX_BBONE_SUBDIV, 4 * sizeof(float));
1304         BKE_curve_forward_diff_bezier(0.0f,  h1[1],                               length + h2[1],                      length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float));
1305         BKE_curve_forward_diff_bezier(0.0f,  h1[2],                               h2[2],                               0.0f,   data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
1306         BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2,  data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float));
1307
1308         equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */
1309
1310         /* make transformation matrices for the segments for drawing */
1311         for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) {
1312                 sub_v3_v3v3(h1, fp + 4, fp);
1313                 vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
1314                 
1315                 copy_m4_m3(result_array[a].mat, mat3);
1316                 copy_v3_v3(result_array[a].mat[3], fp);
1317                 
1318                 /* "extra" scale facs... */
1319                 {
1320                         const int num_segments = ebone->segments;
1321                         
1322                         const float scaleFactorIn  = 1.0f + (ebone->scaleIn  - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
1323                         const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1)            / (float)num_segments);
1324                         
1325                         const float scalefac = scaleFactorIn * scaleFactorOut;
1326                         float bscalemat[4][4], bscale[3];
1327                         
1328                         bscale[0] = scalefac;
1329                         bscale[1] = 1.0f;
1330                         bscale[2] = scalefac;
1331                         
1332                         size_to_mat4(bscalemat, bscale);
1333                         
1334                         /* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */
1335                         mul_m4_series(result_array[a].mat, result_array[a].mat, bscalemat);
1336                 }
1337         }
1338 }
1339
1340 static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebone, float xwidth, float length, float zwidth)
1341 {
1342         int segments = 0;
1343         
1344         if (pchan) 
1345                 segments = pchan->bone->segments;
1346         else if (ebone)
1347                 segments = ebone->segments;
1348         
1349         if (segments > 1) {
1350                 float dlen = length / (float)segments;
1351                 Mat4 bbone[MAX_BBONE_SUBDIV];
1352                 int a;
1353                 
1354                 if (pchan) {
1355                         b_bone_spline_setup(pchan, 0, bbone);
1356                 }
1357                 else if (ebone) {
1358                         ebone_spline_preview(ebone, bbone);
1359                 }
1360                 
1361                 for (a = 0; a < segments; a++) {
1362                         gpuPushMatrix();
1363                         gpuMultMatrix(bbone[a].mat);
1364                         if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
1365                         else drawcube_size(xwidth, dlen, zwidth);
1366                         gpuPopMatrix();
1367                 }
1368         }
1369         else {
1370                 if (dt == OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
1371                 else drawcube_size(xwidth, length, zwidth);
1372         }
1373 }
1374
1375 static void draw_b_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
1376                         bPoseChannel *pchan, EditBone *ebone)
1377 {
1378         float xwidth, length, zwidth;
1379         
1380         if (pchan) {
1381                 xwidth = pchan->bone->xwidth;
1382                 length = pchan->bone->length;
1383                 zwidth = pchan->bone->zwidth;
1384         }
1385         else {
1386                 xwidth = ebone->xwidth;
1387                 length = ebone->length;
1388                 zwidth = ebone->zwidth;
1389         }
1390         
1391         /* draw points only if... */
1392         if (armflag & ARM_EDITMODE) {
1393                 /* move to unitspace */
1394                 gpuPushMatrix();
1395                 gpuScaleUniform(length);
1396                 draw_bone_points(dt, armflag, boneflag, id);
1397                 gpuPopMatrix();
1398                 length *= 0.95f;  /* make vertices visible */
1399         }
1400
1401         /* colors for modes */
1402         if (armflag & ARM_POSEMODE) {
1403                 if (dt <= OB_WIRE)
1404                         set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
1405                 else 
1406                         set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
1407         }
1408         else if (armflag & ARM_EDITMODE) {
1409                 if (dt == OB_WIRE) {
1410                         set_ebone_color(boneflag);
1411                 }
1412                 else {
1413                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
1414                 }
1415         }
1416         
1417         if (id != -1) {
1418                 GPU_select_load_id((GLuint) id | BONESEL_BONE);
1419         }
1420         
1421         /* set up solid drawing */
1422         if (dt > OB_WIRE) {
1423                 if (armflag & ARM_POSEMODE)
1424                         set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
1425                 else {
1426                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
1427                 }
1428                 
1429                 flat_color = false;
1430                 draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
1431         }
1432         else {
1433                 /* wire */
1434                 if (armflag & ARM_POSEMODE) {
1435                         if (constflag && ((G.f & G_PICKSEL) == 0)) {
1436                                 /* set constraint colors */
1437                                 if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
1438                                         glEnable(GL_BLEND);
1439                                         
1440                                         flat_color = true;
1441                                         draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
1442                                         
1443                                         glDisable(GL_BLEND);
1444                                 }
1445                                 
1446                                 /* restore colors */
1447                                 set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
1448                         }
1449                 }
1450                 
1451                 draw_b_bone_boxes(OB_WIRE, pchan, ebone, xwidth, length, zwidth);
1452         }
1453 }
1454
1455 static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
1456 {
1457         Gwn_VertFormat *format = immVertexFormat();
1458         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
1459
1460         immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
1461         immUniformColor4fv(fcolor);
1462
1463         if ((segments > 1) && (pchan)) {
1464                 float dlen = length / (float)segments;
1465                 Mat4 *bbone = bbones;
1466                 int a;
1467
1468                 for (a = 0; a < segments; a++, bbone++) {
1469                         gpuPushMatrix();
1470                         gpuMultMatrix(bbone->mat);
1471
1472                         immBegin(GWN_PRIM_LINES, 2);
1473                         immVertex3f(pos, 0.0f, 0.0f, 0.0f);
1474                         immVertex3f(pos, 0.0f, dlen, 0.0f);
1475                         immEnd();
1476
1477                         gpuPopMatrix();
1478                 }
1479         }
1480         else {
1481                 gpuPushMatrix();
1482
1483                 immBegin(GWN_PRIM_LINES, 2);
1484                 immVertex3f(pos, 0.0f, 0.0f, 0.0f);
1485                 immVertex3f(pos, 0.0f, length, 0.0f);
1486                 immEnd();
1487
1488                 gpuPopMatrix();
1489         }
1490
1491         immUnbindProgram();
1492 }
1493
1494 static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
1495                            bPoseChannel *pchan, EditBone *ebone)
1496 {
1497         Mat4 bbones_array[MAX_BBONE_SUBDIV];
1498         Mat4 *bbones = NULL;
1499         int segments = 0;
1500         float length;
1501         
1502         if (pchan) {
1503                 segments = pchan->bone->segments;
1504                 length = pchan->bone->length;
1505                 
1506                 if (segments > 1) {
1507                         b_bone_spline_setup(pchan, 0, bbones_array);
1508                         bbones = bbones_array;
1509                 }
1510         }
1511         else 
1512                 length = ebone->length;
1513         
1514         /* draw points only if... */
1515         if (armflag & ARM_EDITMODE) {
1516                 /* move to unitspace */
1517                 gpuPushMatrix();
1518                 gpuScaleUniform(length);
1519                 flat_color = true;
1520                 draw_bone_points(dt, armflag, boneflag, id);
1521                 gpuPopMatrix();
1522                 length *= 0.95f;  /* make vertices visible */
1523         }
1524         
1525         /* this chunk not in object mode */
1526         if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) {
1527                 if (id != -1)
1528                         GPU_select_load_id((GLuint) id | BONESEL_BONE);
1529                 
1530                 draw_wire_bone_segments(pchan, bbones, length, segments);
1531                 
1532                 /* further we send no names */
1533                 if (id != -1)
1534                         GPU_select_load_id(id & 0xFFFF);    /* object tag, for bordersel optim */
1535         }
1536         
1537         /* colors for modes */
1538         if (armflag & ARM_POSEMODE) {
1539                 set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
1540         }
1541         else if (armflag & ARM_EDITMODE) {
1542                 set_ebone_color(boneflag);
1543         }
1544         
1545         /* draw normal */
1546         draw_wire_bone_segments(pchan, bbones, length, segments);
1547 }
1548
1549 static void draw_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, float length)
1550 {
1551         
1552         /* Draw a 3d octahedral bone, we use normalized space based on length */
1553         gpuScaleUniform(length);
1554
1555         /* set up solid drawing */
1556         if (dt > OB_WIRE) {
1557                 UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
1558                 flat_color = false;
1559         }
1560         else
1561                 flat_color = true;
1562         
1563         /* colors for posemode */
1564         if (armflag & ARM_POSEMODE) {
1565                 if (dt <= OB_WIRE)
1566                         set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
1567                 else 
1568                         set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
1569         }
1570         
1571         
1572         draw_bone_points(dt, armflag, boneflag, id);
1573         
1574         /* now draw the bone itself */
1575         if (id != -1) {
1576                 GPU_select_load_id((GLuint) id | BONESEL_BONE);
1577         }
1578         
1579         /* wire? */
1580         if (dt <= OB_WIRE) {
1581                 /* colors */
1582                 if (armflag & ARM_EDITMODE) {
1583                         set_ebone_color(boneflag);
1584                 }
1585                 else if (armflag & ARM_POSEMODE) {
1586                         if (constflag && ((G.f & G_PICKSEL) == 0)) {
1587                                 /* draw constraint colors */
1588                                 if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
1589                                         glEnable(GL_BLEND);
1590                                         
1591                                         draw_bone_solid_octahedral();
1592                                         
1593                                         glDisable(GL_BLEND);
1594                                 }
1595                                 
1596                                 /* restore colors */
1597                                 set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
1598                         }
1599                 }
1600                 draw_bone_octahedral();
1601         }
1602         else {
1603                 /* solid */
1604                 if (armflag & ARM_POSEMODE)
1605                         set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
1606                 else
1607                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
1608
1609                 draw_bone_solid_octahedral();
1610         }
1611 }
1612
1613 static void draw_custom_bone(
1614         const struct EvaluationContext *eval_ctx,
1615         Scene *scene, ViewLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob,
1616         const short dt, int armflag, int boneflag, unsigned int id, float length)
1617 {
1618         if (ob == NULL) return;
1619         
1620         gpuScaleUniform(length);
1621         
1622         /* colors for posemode */
1623         if (armflag & ARM_POSEMODE) {
1624                 set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, 0);
1625         }
1626         
1627         if (id != -1) {
1628                 GPU_select_load_id((GLuint) id | BONESEL_BONE);
1629         }
1630
1631         draw_object_instance(eval_ctx, scene, sl, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE, fcolor);
1632 }
1633
1634
1635 static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
1636 {
1637         bConstraint *con;
1638         bPoseChannel *parchan;
1639
1640         const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
1641
1642         immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
1643
1644         float viewport_size[4];
1645         glGetFloatv(GL_VIEWPORT, viewport_size);
1646         immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
1647
1648         immUniform1i("num_colors", 0);  /* "simple" mode */
1649         immUniformColor4fv(fcolor);
1650         immUniform1f("dash_width", 6.0f);
1651         immUniform1f("dash_factor", 0.5f);
1652
1653         for (con = pchan->constraints.first; con; con = con->next) {
1654                 if (con->enforce == 0.0f)
1655                         continue;
1656                 
1657                 switch (con->type) {
1658                         case CONSTRAINT_TYPE_KINEMATIC:
1659                         {
1660                                 bKinematicConstraint *data = (bKinematicConstraint *)con->data;
1661                                 int segcount = 0;
1662                                 float ik_tip[3];
1663                                 
1664                                 /* if only_temp, only draw if it is a temporary ik-chain */
1665                                 if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP))
1666                                         continue;
1667
1668                                 /* exclude tip from chain? */
1669                                 if ((data->flag & CONSTRAINT_IK_TIP) == 0)
1670                                         parchan = pchan->parent;
1671                                 else
1672                                         parchan = pchan;
1673                                 
1674                                 copy_v3_v3(ik_tip, parchan->pose_tail);
1675                                 
1676                                 /* Find the chain's root */
1677                                 while (parchan->parent) {
1678                                         segcount++;
1679                                         /* FIXME: revise the breaking conditions */
1680                                         if (segcount == data->rootbone || segcount > 255) break;  /* 255 is weak */
1681                                         parchan = parchan->parent;
1682                                 }
1683
1684                                 if (parchan) {
1685                                         immBegin(GWN_PRIM_LINES, 2);
1686                                         immVertex3fv(shdr_pos, ik_tip);
1687                                         immVertex3fv(shdr_pos, parchan->pose_head);
1688                                         immEnd();
1689                                 }
1690                                 
1691                                 break;
1692                         }
1693                         case CONSTRAINT_TYPE_SPLINEIK: 
1694                         {
1695                                 bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
1696                                 int segcount = 0;
1697                                 float ik_tip[3];
1698                                 
1699                                 parchan = pchan;
1700                                 copy_v3_v3(ik_tip, parchan->pose_tail);
1701                                 
1702                                 /* Find the chain's root */
1703                                 while (parchan->parent) {
1704                                         segcount++;
1705                                         /* FIXME: revise the breaking conditions */
1706                                         if (segcount == data->chainlen || segcount > 255) break;  /* 255 is weak */
1707                                         parchan = parchan->parent;
1708                                 }
1709                                 /* Only draw line in case our chain is more than one bone long! */
1710                                 if (parchan != pchan) { /* XXX revise the breaking conditions to only stop at the tail? */
1711                                         immBegin(GWN_PRIM_LINES, 2);
1712                                         immVertex3fv(shdr_pos, ik_tip);
1713                                         immVertex3fv(shdr_pos, parchan->pose_head);
1714                                         immEnd();
1715                                 }
1716                                 break;
1717                         }
1718                 }
1719         }
1720
1721         immUnbindProgram();
1722 }
1723
1724 static void imm_sphere_project(unsigned int pos, float ax, float az)
1725 {
1726         float dir[3], sine, q3;
1727
1728         sine = 1.0f - ax * ax - az * az;
1729         q3 = (sine < 0.0f) ? 0.0f : (2.0f * sqrtf(sine));
1730
1731         dir[0] = -az * q3;
1732         dir[1] = 1.0f - 2.0f * sine;
1733         dir[2] = ax * q3;
1734
1735         immVertex3fv(pos, dir);
1736 }
1737
1738 static void draw_dof_ellipse(unsigned int pos, float ax, float az)
1739 {
1740         const int n = 16;
1741         const int tri = n * n - 2 * n + 1; /* Yay fancy math ! */
1742         const float staticSine[16] = {
1743                 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
1744                 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
1745                 0.743144825477f, 0.809016994375f, 0.866025403784f,
1746                 0.913545457643f, 0.951056516295f, 0.978147600734f,
1747                 0.994521895368f, 1.0f
1748         };
1749
1750         int i, j;
1751         float x, z, px, pz;
1752
1753         glEnable(GL_BLEND);
1754         glDepthMask(0);
1755
1756         immUniformColor4ub(70, 70, 70, 50);
1757
1758         immBegin(GWN_PRIM_TRIS, tri * 3);
1759         pz = 0.0f;
1760         for (i = 1; i < n; i++) {
1761                 z = staticSine[i];
1762                 
1763                 px = 0.0f;
1764                 for (j = 1; j <= (n - i); j++) {
1765                         x = staticSine[j];
1766                         
1767                         if (j == n - i) {
1768                                 imm_sphere_project(pos, ax * px, az * z);
1769                                 imm_sphere_project(pos, ax * px, az * pz);
1770                                 imm_sphere_project(pos, ax * x, az * pz);
1771                         }
1772                         else {
1773                                 imm_sphere_project(pos, ax * x, az * z);
1774                                 imm_sphere_project(pos, ax * x, az * pz);
1775                                 imm_sphere_project(pos, ax * px, az * pz);
1776
1777                                 imm_sphere_project(pos, ax * px, az * pz);
1778                                 imm_sphere_project(pos, ax * px, az * z);
1779                                 imm_sphere_project(pos, ax * x, az * z);
1780                         }
1781                         
1782                         px = x;
1783                 }
1784                 pz = z;
1785         }
1786         immEnd();
1787
1788         glDisable(GL_BLEND);
1789         glDepthMask(1);
1790
1791         immUniformColor3ub(0, 0, 0);
1792
1793         immBegin(GWN_PRIM_LINE_STRIP, n);
1794         for (i = 0; i < n; i++)
1795                 imm_sphere_project(pos, staticSine[n - i - 1] * ax, staticSine[i] * az);
1796         immEnd();
1797 }
1798
1799 static void draw_pose_dofs(Object *ob)
1800 {
1801         bArmature *arm = ob->data;
1802         bPoseChannel *pchan;
1803         Bone *bone;
1804
1805         Gwn_VertFormat *format = immVertexFormat();
1806         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
1807
1808         immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
1809
1810         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1811                 bone = pchan->bone;
1812                 
1813                 if ((bone != NULL) && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
1814                         if (bone->flag & BONE_SELECTED) {
1815                                 if (bone->layer & arm->layer) {
1816                                         if (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_ZLIMIT)) {
1817                                                 if (BKE_pose_channel_in_IK_chain(ob, pchan)) {
1818                                                         float corner[4][3], posetrans[3], mat[4][4];
1819                                                         float phi = 0.0f, theta = 0.0f, scale;
1820                                                         int a, i;
1821                                                         
1822                                                         /* in parent-bone pose, but own restspace */
1823                                                         gpuPushMatrix();
1824                                                         
1825                                                         copy_v3_v3(posetrans, pchan->pose_mat[3]);
1826                                                         gpuTranslate3fv(posetrans);
1827                                                         
1828                                                         if (pchan->parent) {
1829                                                                 copy_m4_m4(mat, pchan->parent->pose_mat);
1830                                                                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
1831                                                                 gpuMultMatrix(mat);
1832                                                         }
1833                                                         
1834                                                         copy_m4_m3(mat, pchan->bone->bone_mat);
1835                                                         gpuMultMatrix(mat);
1836                                                         
1837                                                         scale = bone->length * pchan->size[1];
1838                                                         gpuScaleUniform(scale);
1839                                                         
1840                                                         if (((pchan->ikflag & BONE_IK_XLIMIT) != 0) &&
1841                                                             ((pchan->ikflag & BONE_IK_ZLIMIT) != 0))
1842                                                         {
1843                                                                 float amin[3], amax[3];
1844
1845                                                                 for (i = 0; i < 3; i++) {
1846                                                                         /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
1847                                                                         amin[i] = sinf(pchan->limitmin[i] * 0.5f);
1848                                                                         amax[i] = sinf(pchan->limitmax[i] * 0.5f);
1849                                                                 }
1850
1851                                                                 gpuScale3f(1.0f, -1.0f, 1.0f);
1852                                                                 if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
1853                                                                         draw_dof_ellipse(pos, amin[0], amin[2]);
1854                                                                 if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
1855                                                                         draw_dof_ellipse(pos, amin[0], amax[2]);
1856                                                                 if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
1857                                                                         draw_dof_ellipse(pos, amax[0], amin[2]);
1858                                                                 if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
1859                                                                         draw_dof_ellipse(pos, amax[0], amax[2]);
1860                                                                 gpuScale3f(1.0f, -1.0f, 1.0f); /* XXX same as above, is this intentional? */
1861                                                         }
1862                                                         
1863                                                         /* arcs */
1864                                                         if (pchan->ikflag & BONE_IK_ZLIMIT) {
1865                                                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
1866                                                                 theta = RAD2DEGF(0.5f * (pchan->limitmin[2] + pchan->limitmax[2]));
1867                                                                 gpuPushMatrix();
1868                                                                 gpuRotateAxis(theta, 'Z');
1869                                                                 
1870                                                                 immUniformColor3ub(50, 50, 255);  /* blue, Z axis limit */
1871                                                                 immBegin(GWN_PRIM_LINE_STRIP, 33);
1872                                                                 for (a = -16; a <= 16; a++) {
1873                                                                         /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
1874                                                                         float fac = ((float)a) / 16.0f * 0.5f;
1875                                                                         
1876                                                                         phi = fac * (pchan->limitmax[2] - pchan->limitmin[2]);
1877                                                                         
1878                                                                         i = (a == -16) ? 0 : 1;
1879                                                                         corner[i][0] = sinf(phi);
1880                                                                         corner[i][1] = cosf(phi);
1881                                                                         corner[i][2] = 0.0f;
1882                                                                         immVertex3fv(pos, corner[i]);
1883                                                                 }
1884                                                                 immEnd();
1885                                                                 
1886                                                                 gpuPopMatrix();
1887                                                         }
1888                                                         
1889                                                         if (pchan->ikflag & BONE_IK_XLIMIT) {
1890                                                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
1891                                                                 theta = RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0]));
1892                                                                 gpuPushMatrix();
1893                                                                 gpuRotateAxis(theta, 'X');
1894                                                                 
1895                                                                 immUniformColor3ub(255, 50, 50);  /* Red, X axis limit */
1896                                                                 immBegin(GWN_PRIM_LINE_STRIP, 33);
1897                                                                 for (a = -16; a <= 16; a++) {
1898                                                                         /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
1899                                                                         float fac = ((float)a) / 16.0f * 0.5f;
1900                                                                         phi = (float)M_PI_2 + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
1901                                                                         
1902                                                                         i = (a == -16) ? 2 : 3;
1903                                                                         corner[i][0] = 0.0f;
1904                                                                         corner[i][1] = sinf(phi);
1905                                                                         corner[i][2] = cosf(phi);
1906                                                                         immVertex3fv(pos, corner[i]);
1907                                                                 }
1908                                                                 immEnd();
1909                                                                 
1910                                                                 gpuPopMatrix();
1911                                                         }
1912                                                         
1913                                                         /* out of cone, out of bone */
1914                                                         gpuPopMatrix();
1915                                                 }
1916                                         }
1917                                 }
1918                         }
1919                 }
1920         }
1921
1922         immUnbindProgram();
1923 }
1924
1925 static void bone_matrix_translate_y(float mat[4][4], float y)
1926 {
1927         float trans[3];
1928
1929         copy_v3_v3(trans, mat[1]);
1930         mul_v3_fl(trans, y);
1931         add_v3_v3(mat[3], trans);
1932 }
1933
1934 /* assumes object is Armature with pose */
1935 static void draw_pose_bones(
1936         const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *sl, View3D *v3d, ARegion *ar, Base *base,
1937         const short dt, const unsigned char ob_wire_col[4],
1938         const bool do_const_color, const bool is_outline)
1939 {
1940         RegionView3D *rv3d = ar->regiondata;
1941         Object *ob = base->object;
1942         bArmature *arm = ob->data;
1943         bPoseChannel *pchan;
1944         Bone *bone;
1945         float smat[4][4], imat[4][4], bmat[4][4];
1946         int index = -1;
1947         const enum {
1948                 DASH_RELATIONSHIP_LINES = 1,
1949                 DASH_HELP_LINES = 2,
1950         } do_dashed = (
1951                 (is_outline ? 0 : DASH_RELATIONSHIP_LINES) |
1952                 ((v3d->flag & V3D_HIDE_HELPLINES) ? 0 : DASH_HELP_LINES));
1953         bool draw_wire = false;
1954         int flag;
1955         bool is_cull_enabled;
1956         
1957         /* being set below */
1958         arm->layer_used = 0;
1959
1960         rgba_uchar_to_float(fcolor, ob_wire_col);
1961
1962         /* precalc inverse matrix for drawing screen aligned */
1963         if (arm->drawtype == ARM_ENVELOPE) {
1964                 /* precalc inverse matrix for drawing screen aligned */
1965                 copy_m4_m4(smat, rv3d->viewmatob);
1966                 mul_mat3_m4_fl(smat, 1.0f / len_v3(ob->obmat[0]));
1967                 invert_m4_m4(imat, smat);
1968                 
1969                 /* and draw blended distances */
1970                 if (arm->flag & ARM_POSEMODE) {
1971                         glEnable(GL_BLEND);
1972                         
1973                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1974                         
1975                         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1976                                 bone = pchan->bone;
1977                                 if (bone) {
1978                                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] 
1979                                          * NOTE: this is the only case with (NO_DEFORM == 0) flag, as this is for envelope influence drawing
1980                                          */
1981                                         if (((bone->flag & (BONE_HIDDEN_P | BONE_NO_DEFORM | BONE_HIDDEN_PG)) == 0) &&
1982                                             ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0))
1983                                         {
1984                                                 if (bone->flag & (BONE_SELECTED)) {
1985                                                         if (bone->layer & arm->layer)
1986                                                                 draw_sphere_bone_dist(smat, imat, pchan, NULL);
1987                                                 }
1988                                         }
1989                                 }
1990                         }
1991                         
1992                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1993                         glDisable(GL_BLEND);
1994                 }
1995         }
1996         
1997         /* little speedup, also make sure transparent only draws once */
1998         glCullFace(GL_BACK);
1999         if (v3d->flag2 & V3D_BACKFACE_CULLING) {
2000                 glEnable(GL_CULL_FACE);
2001                 is_cull_enabled = true;
2002         }
2003         else {
2004                 is_cull_enabled = false;
2005         }
2006
2007         /* if solid we draw that first, with selection codes, but without names, axes etc */
2008         if (dt > OB_WIRE) {
2009                 if (arm->flag & ARM_POSEMODE) 
2010                         index = base->object->select_color;
2011                 
2012                 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
2013                         bone = pchan->bone;
2014                         arm->layer_used |= bone->layer;
2015                         
2016                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
2017                         if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) &&
2018                             ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0))
2019                         {
2020                                 if (bone->layer & arm->layer) {
2021                                         const bool use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
2022                                         gpuPushMatrix();
2023                                         
2024                                         if (use_custom && pchan->custom_tx) {
2025                                                 gpuMultMatrix(pchan->custom_tx->pose_mat);
2026                                         }
2027                                         else {
2028                                                 gpuMultMatrix(pchan->pose_mat);
2029                                         }
2030                                         
2031                                         /* catch exception for bone with hidden parent */
2032                                         flag = bone->flag;
2033                                         if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
2034                                                 flag &= ~BONE_CONNECTED;
2035                                         }
2036                                         
2037                                         /* set temporary flag for drawing bone as active, but only if selected */
2038                                         if (bone == arm->act_bone)
2039                                                 flag |= BONE_DRAW_ACTIVE;
2040                                         
2041                                         if (do_const_color) {
2042                                                 /* keep color */
2043                                         }
2044                                         else {
2045                                                 /* set color-set to use */
2046                                                 set_pchan_colorset(ob, pchan);
2047                                         }
2048
2049                                         /* may be 2x width from custom bone's outline option */
2050                                         glLineWidth(1.0f);
2051
2052                                         if (use_custom) {
2053                                                 /* if drawwire, don't try to draw in solid */
2054                                                 if (pchan->bone->flag & BONE_DRAWWIRE) {
2055                                                         draw_wire = true;
2056                                                 }
2057                                                 else {
2058                                                         if (is_cull_enabled && (v3d->flag2 & V3D_BACKFACE_CULLING) == 0) {
2059                                                                 is_cull_enabled = false;
2060                                                                 glDisable(GL_CULL_FACE);
2061                                                         }
2062
2063                                                         draw_custom_bone(eval_ctx, scene, sl, v3d, rv3d, pchan->custom,
2064                                                                          OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
2065                                                 }
2066                                         }
2067                                         else {
2068                                                 if (is_cull_enabled == false) {
2069                                                         is_cull_enabled = true;
2070                                                         glEnable(GL_CULL_FACE);
2071                                                 }
2072
2073                                                 if (arm->drawtype == ARM_LINE) {
2074                                                         /* nothing in solid */
2075                                                 }
2076                                                 else if (arm->drawtype == ARM_WIRE) {
2077                                                         /* nothing in solid */
2078                                                 }
2079                                                 else if (arm->drawtype == ARM_ENVELOPE) {
2080                                                         draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
2081                                                 }
2082                                                 else if (arm->drawtype == ARM_B_BONE) {
2083                                                         draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
2084                                                 }
2085                                                 else {
2086                                                         draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
2087                                                 }
2088                                         }
2089
2090                                         gpuPopMatrix();
2091                                 }
2092                         }
2093                         
2094                         if (index != -1)
2095                                 index += 0x10000;  /* pose bones count in higher 2 bytes only */
2096                 }
2097                 
2098                 /* very very confusing... but in object mode, solid draw, we cannot do GPU_select_load_id yet,
2099                  * stick bones and/or wire custom-shapes are drawn in next loop 
2100                  */
2101                 if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == false) && index != -1) {
2102                         /* object tag, for bordersel optim */
2103                         GPU_select_load_id(index & 0xFFFF);
2104                         index = -1;
2105                 }
2106         }
2107         
2108         /* custom bone may draw outline double-width */
2109         if (arm->flag & ARM_POSEMODE) {
2110                 glLineWidth(1.0f);
2111         }
2112
2113         /* draw custom bone shapes as wireframes */
2114         if (!(arm->flag & ARM_NO_CUSTOM) &&
2115             (draw_wire || (dt <= OB_WIRE)) )
2116         {
2117                 if (arm->flag & ARM_POSEMODE)
2118                         index = base->object->select_color;
2119                         
2120                 /* only draw custom bone shapes that need to be drawn as wires */
2121                 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
2122                         bone = pchan->bone;
2123                         
2124                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
2125                         if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) &&
2126                             ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0) )
2127                         {
2128                                 if (bone->layer & arm->layer) {
2129                                         if (pchan->custom) {
2130                                                 if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
2131                                                         gpuPushMatrix();
2132                                                         
2133                                                         if (pchan->custom_tx) {
2134                                                                 gpuMultMatrix(pchan->custom_tx->pose_mat);
2135                                                         }
2136                                                         else {
2137                                                                 gpuMultMatrix(pchan->pose_mat);
2138                                                         }
2139                                                         
2140                                                         /* prepare colors */
2141                                                         if (do_const_color) {
2142                                                                 /* 13 October 2009, Disabled this to make ghosting show the right colors (Aligorith) */
2143                                                         }
2144                                                         else if (arm->flag & ARM_POSEMODE)
2145                                                                 set_pchan_colorset(ob, pchan);
2146                                                         else {
2147                                                                 rgba_uchar_to_float(fcolor, ob_wire_col);
2148                                                         }
2149                                                                 
2150                                                         /* catch exception for bone with hidden parent */
2151                                                         flag = bone->flag;
2152                                                         if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))
2153                                                                 flag &= ~BONE_CONNECTED;
2154                                                                 
2155                                                         /* set temporary flag for drawing bone as active, but only if selected */
2156                                                         if (bone == arm->act_bone)
2157                                                                 flag |= BONE_DRAW_ACTIVE;
2158                                                         
2159                                                         draw_custom_bone(eval_ctx, scene, sl, v3d, rv3d, pchan->custom,
2160                                                                          OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
2161                                                         
2162                                                         gpuPopMatrix();
2163                                                 }
2164                                         }
2165                                 }
2166                         }
2167                         
2168                         if (index != -1) 
2169                                 index += 0x10000;  /* pose bones count in higher 2 bytes only */
2170                 }
2171                 /* stick or wire bones have not been drawn yet so don't clear object selection in this case */
2172                 if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && draw_wire && index != -1) {
2173                         /* object tag, for bordersel optim */
2174                         GPU_select_load_id(index & 0xFFFF);
2175                         index = -1;
2176                 }
2177         }
2178
2179         /* wire draw over solid only in posemode */
2180         if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
2181                 /* draw line check first. we do selection indices */
2182                 if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
2183                         if (arm->flag & ARM_POSEMODE) 
2184                                 index = base->object->select_color;
2185                 }
2186                 /* if solid && posemode, we draw again with polygonoffset */
2187                 else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
2188                         ED_view3d_polygon_offset(rv3d, 1.0);
2189                 }
2190                 else {
2191                         /* and we use selection indices if not done yet */
2192                         if (arm->flag & ARM_POSEMODE) 
2193                                 index = base->object->select_color;
2194                 }
2195
2196                 if (is_cull_enabled == false) {
2197                         is_cull_enabled = true;
2198                         glEnable(GL_CULL_FACE);
2199                 }
2200
2201                 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
2202                         bone = pchan->bone;
2203                         arm->layer_used |= bone->layer;
2204                         
2205                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
2206                         if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) &&
2207                             ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0))
2208                         {
2209                                 if (bone->layer & arm->layer) {
2210                                         const short constflag = pchan->constflag;
2211                                         if ((do_dashed & DASH_RELATIONSHIP_LINES) && (pchan->parent)) {
2212                                                 /* Draw a line from our root to the parent's tip 
2213                                                  * - only if V3D_HIDE_HELPLINES is enabled...
2214                                                  */
2215                                                 if ((do_dashed & DASH_HELP_LINES) && ((bone->flag & BONE_CONNECTED) == 0)) {
2216                                                         const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
2217
2218                                                         immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
2219
2220                                                         float viewport_size[4];
2221                                                         glGetFloatv(GL_VIEWPORT, viewport_size);
2222                                                         immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
2223
2224                                                         immUniform1i("num_colors", 0);  /* "simple" mode */
2225                                                         immUniformColor4fv(fcolor);
2226                                                         immUniform1f("dash_width", 6.0f);
2227                                                         immUniform1f("dash_factor", 0.5f);
2228
2229                                                         if (arm->flag & ARM_POSEMODE) {
2230                                                                 GPU_select_load_id(index & 0xFFFF);  /* object tag, for bordersel optim */
2231                                                                 immUniformThemeColor(TH_WIRE);
2232                                                         }
2233
2234                                                         immBegin(GWN_PRIM_LINES, 2);
2235                                                         immVertex3fv(shdr_pos, pchan->parent->pose_tail);
2236                                                         immVertex3fv(shdr_pos, pchan->pose_head);
2237                                                         immEnd();
2238
2239                                                         immUnbindProgram();
2240                                                 }
2241                                                 
2242                                                 /* Draw a line to IK root bone 
2243                                                  *  - only if temporary chain (i.e. "autoik")
2244                                                  */
2245                                                 if (arm->flag & ARM_POSEMODE) {
2246                                                         if (constflag & PCHAN_HAS_IK) {
2247                                                                 if (bone->flag & BONE_SELECTED) {
2248                                                                         if (constflag & PCHAN_HAS_TARGET) {
2249                                                                                 rgba_float_args_set(fcolor, 200.f / 255.f, 120.f / 255.f, 0.f / 255.f, 1.0f);
2250                                                                         }
2251                                                                         /* add theme! */
2252                                                                         else rgba_float_args_set(fcolor, 200.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f);
2253
2254                                                                         GPU_select_load_id(index & 0xFFFF);
2255                                                                         pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
2256                                                                 }
2257                                                         }
2258                                                         else if (constflag & PCHAN_HAS_SPLINEIK) {
2259                                                                 if (bone->flag & BONE_SELECTED) {
2260                                                                         /* add theme! */
2261                                                                         rgba_float_args_set(fcolor, 150.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f);
2262
2263                                                                         GPU_select_load_id(index & 0xFFFF);
2264                                                                         pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
2265                                                                 }
2266                                                         }
2267                                                 }
2268                                         }
2269                                         
2270                                         gpuPushMatrix();
2271                                         if (arm->drawtype != ARM_ENVELOPE)
2272                                                 gpuMultMatrix(pchan->pose_mat);
2273                                         
2274                                         /* catch exception for bone with hidden parent */
2275                                         flag = bone->flag;
2276                                         if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))
2277                                                 flag &= ~BONE_CONNECTED;
2278                                         
2279                                         /* set temporary flag for drawing bone as active, but only if selected */
2280                                         if (bone == arm->act_bone)
2281                                                 flag |= BONE_DRAW_ACTIVE;
2282                                         
2283                                         /* extra draw service for pose mode */
2284
2285                                         /* set color-set to use */
2286                                         if (do_const_color) {
2287                                                 /* keep color */
2288                                         }
2289                                         else {
2290                                                 set_pchan_colorset(ob, pchan);
2291                                         }
2292                                         
2293                                         if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
2294                                                 /* custom bone shapes should not be drawn here! */
2295                                         }
2296                                         else if (arm->drawtype == ARM_ENVELOPE) {
2297                                                 if (dt < OB_SOLID)
2298                                                         draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
2299                                         }
2300                                         else if (arm->drawtype == ARM_LINE)
2301                                                 draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
2302                                         else if (arm->drawtype == ARM_WIRE)
2303                                                 draw_wire_bone(dt, arm->flag, flag, constflag, index, pchan, NULL);
2304                                         else if (arm->drawtype == ARM_B_BONE)
2305                                                 draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
2306                                         else
2307                                                 draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
2308                                         
2309                                         gpuPopMatrix();
2310                                 }
2311                         }
2312                         
2313                         /* pose bones count in higher 2 bytes only */
2314                         if (index != -1) 
2315                                 index += 0x10000;
2316                 }
2317                 /* restore things */
2318                 if (!ELEM(arm->drawtype, ARM_WIRE, ARM_LINE) && (dt > OB_WIRE) && (arm->flag & ARM_POSEMODE))
2319                         ED_view3d_polygon_offset(rv3d, 0.0);
2320         }
2321         
2322         /* restore */
2323         if (is_cull_enabled) {
2324                 glDisable(GL_CULL_FACE);
2325         }
2326         
2327         /* draw DoFs */
2328         if (arm->flag & ARM_POSEMODE) {
2329                 if (((base->flag_legacy & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) {
2330                         draw_pose_dofs(ob);
2331                 }
2332         }
2333
2334         /* finally names and axes */
2335         if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) &&
2336             (is_outline == 0) &&
2337             ((base->flag_legacy & OB_FROMDUPLI) == 0))
2338         {
2339                 /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */
2340                 if ((G.f & G_PICKSEL) == 0) {
2341                         float vec[3];
2342
2343                         unsigned char col[4];
2344                         col[0] = ob_wire_col[0];
2345                         col[1] = ob_wire_col[1];
2346                         col[2] = ob_wire_col[2];
2347                         col[3] = 255;
2348                         
2349                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2350                         
2351                         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
2352                                 if ((pchan->bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) {
2353                                         if (pchan->bone->layer & arm->layer) {
2354                                                 if (arm->flag & (ARM_EDITMODE | ARM_POSEMODE)) {
2355                                                         bone = pchan->bone;
2356                                                         UI_GetThemeColor3ubv((bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
2357                                                 }
2358                                                 else if (dt > OB_WIRE) {
2359                                                         UI_GetThemeColor3ubv(TH_TEXT, col);
2360                                                 }
2361                                                 
2362                                                 /*  Draw names of bone  */
2363                                                 if (arm->flag & ARM_DRAWNAMES) {
2364                                                         mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
2365                                                         view3d_cached_text_draw_add(vec, pchan->name, strlen(pchan->name), 10, 0, col);
2366                                                 }
2367                                                 
2368                                                 /*      Draw additional axes on the bone tail  */
2369                                                 if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) {
2370                                                         gpuPushMatrix();
2371                                                         copy_m4_m4(bmat, pchan->pose_mat);
2372                                                         bone_matrix_translate_y(bmat, pchan->bone->length);
2373                                                         gpuMultMatrix(bmat);
2374                                                         
2375                                                         float viewmat_pchan[4][4];
2376                                                         mul_m4_m4m4(viewmat_pchan, rv3d->viewmatob, bmat);
2377                                                         drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS, col);
2378                                                         
2379                                                         gpuPopMatrix();
2380                                                 }
2381                                         }
2382                                 }
2383                         }
2384                         
2385                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2386                 }
2387         }
2388
2389         if (index != -1) {
2390                 GPU_select_load_id(-1);
2391         }
2392 }
2393
2394 /* in editmode, we don't store the bone matrix... */
2395 static void get_matrix_editbone(EditBone *ebone, float bmat[4][4])
2396 {
2397         ebone->length = len_v3v3(ebone->tail, ebone->head);
2398         ED_armature_ebone_to_mat4(ebone, bmat);
2399 }
2400
2401 static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
2402 {
2403         RegionView3D *rv3d = ar->regiondata;
2404         EditBone *eBone;
2405         bArmature *arm = ob->data;
2406         float smat[4][4], imat[4][4], bmat[4][4];
2407         unsigned int index;
2408         int flag;
2409         
2410         /* being set in code below */
2411         arm->layer_used = 0;
2412
2413         ED_view3d_check_mats_rv3d(rv3d);
2414
2415         /* envelope (deform distance) */
2416         if (arm->drawtype == ARM_ENVELOPE) {
2417                 /* precalc inverse matrix for drawing screen aligned */
2418                 copy_m4_m4(smat, rv3d->viewmatob);
2419                 mul_mat3_m4_fl(smat, 1.0f / len_v3(ob->obmat[0]));
2420                 invert_m4_m4(imat, smat);
2421                 
2422                 /* and draw blended distances */
2423                 glEnable(GL_BLEND);
2424                 
2425                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2426
2427                 for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
2428                         if (eBone->layer & arm->layer) {
2429                                 if ((eBone->flag & (BONE_HIDDEN_A | BONE_NO_DEFORM)) == 0) {
2430                                         if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL))
2431                                                 draw_sphere_bone_dist(smat, imat, NULL, eBone);
2432                                 }
2433                         }
2434                 }
2435                 
2436                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2437                 glDisable(GL_BLEND);
2438         }
2439         
2440         /* if solid we draw it first */
2441         if ((dt > OB_WIRE) && (arm->drawtype != ARM_LINE)) {
2442                 for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) {
2443                         if (eBone->layer & arm->layer) {
2444                                 if ((eBone->flag & BONE_HIDDEN_A) == 0) {
2445                                         gpuPushMatrix();
2446                                         get_matrix_editbone(eBone, bmat);
2447                                         gpuMultMatrix(bmat);
2448                                         
2449                                         /* catch exception for bone with hidden parent */
2450                                         flag = eBone->flag;
2451                                         if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) {
2452                                                 flag &= ~BONE_CONNECTED;
2453                                         }
2454                                                 
2455                                         /* set temporary flag for drawing bone as active, but only if selected */
2456                                         if (eBone == arm->act_edbone)
2457                                                 flag |= BONE_DRAW_ACTIVE;
2458                                         
2459                                         if (arm->drawtype == ARM_ENVELOPE)
2460                                                 draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
2461                                         else if (arm->drawtype == ARM_B_BONE)
2462                                                 draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
2463                                         else if (arm->drawtype == ARM_WIRE)
2464                                                 draw_wire_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
2465                                         else {
2466                                                 draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
2467                                         }
2468                                         
2469                                         gpuPopMatrix();
2470                                 }
2471                         }
2472                 }
2473         }
2474         
2475         /* if wire over solid, set offset */
2476         index = -1;
2477         GPU_select_load_id(-1);
2478         if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
2479                 if (G.f & G_PICKSEL)
2480                         index = 0;
2481         }
2482         else if (dt > OB_WIRE) 
2483                 ED_view3d_polygon_offset(rv3d, 1.0);
2484         else if (arm->flag & ARM_EDITMODE) 
2485                 index = 0;  /* do selection codes */
2486         
2487         for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
2488                 arm->layer_used |= eBone->layer;
2489                 if (eBone->layer & arm->layer) {
2490                         if ((eBone->flag & BONE_HIDDEN_A) == 0) {
2491                                 
2492                                 /* catch exception for bone with hidden parent */
2493                                 flag = eBone->flag;
2494                                 if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) {
2495                                         flag &= ~BONE_CONNECTED;
2496                                 }
2497                                         
2498                                 /* set temporary flag for drawing bone as active, but only if selected */
2499                                 if (eBone == arm->act_edbone)
2500                                         flag |= BONE_DRAW_ACTIVE;
2501                                 
2502                                 if (arm->drawtype == ARM_ENVELOPE) {
2503                                         if (dt < OB_SOLID)
2504                                                 draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
2505                                 }
2506                                 else {
2507                                         gpuPushMatrix();
2508                                         get_matrix_editbone(eBone, bmat);
2509                                         gpuMultMatrix(bmat);
2510                                         
2511                                         if (arm->drawtype == ARM_LINE) 
2512                                                 draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
2513                                         else if (arm->drawtype == ARM_WIRE)
2514                                                 draw_wire_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
2515                                         else if (arm->drawtype == ARM_B_BONE)
2516                                                 draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
2517                                         else
2518                                                 draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
2519                                         
2520                                         gpuPopMatrix();
2521                                 }
2522                                 
2523                                 /* offset to parent */
2524                                 if (eBone->parent) {
2525                                         const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
2526
2527                                         GPU_select_load_id(-1);  /* -1 here is OK! */
2528
2529                                         immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
2530
2531                                         float viewport_size[4];
2532                                         glGetFloatv(GL_VIEWPORT, viewport_size);
2533                                         immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
2534
2535                                         immUniform1i("num_colors", 0);  /* "simple" mode */
2536                                         immUniformThemeColor(TH_WIRE_EDIT);
2537                                         immUniform1f("dash_width", 6.0f);
2538                                         immUniform1f("dash_factor", 0.5f);
2539
2540                                         immBegin(GWN_PRIM_LINES, 2);
2541                                         immVertex3fv(shdr_pos, eBone->parent->tail);
2542                                         immVertex3fv(shdr_pos, eBone->head);
2543                                         immEnd();
2544
2545                                         immUnbindProgram();
2546                                 }
2547                         }
2548                 }
2549                 if (index != -1) index++;
2550         }
2551         
2552         /* restore */
2553         if (index != -1) {
2554                 GPU_select_load_id(-1);
2555         }
2556
2557         if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
2558                 /* pass */
2559         }
2560         else if (dt > OB_WIRE) {
2561                 ED_view3d_polygon_offset(rv3d, 0.0);
2562         }
2563         
2564         /* finally names and axes */
2565         if (arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) {
2566                 /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */
2567                 if ((G.f & G_PICKSEL) == 0) {
2568                         float vec[3];
2569                         unsigned char col[4];
2570                         col[3] = 255;
2571                         
2572                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2573                         
2574                         for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
2575                                 if (eBone->layer & arm->layer) {
2576                                         if ((eBone->flag & BONE_HIDDEN_A) == 0) {
2577
2578                                                 UI_GetThemeColor3ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
2579
2580                                                 /*      Draw name */
2581                                                 if (arm->flag & ARM_DRAWNAMES) {
2582                                                         mid_v3_v3v3(vec, eBone->head, eBone->tail);
2583                                                         view3d_cached_text_draw_add(vec, eBone->name, strlen(eBone->name), 10, 0, col);
2584                                                 }
2585                                                 /*      Draw additional axes */
2586                                                 if (arm->flag & ARM_DRAWAXES) {
2587                                                         gpuPushMatrix();
2588                                                         get_matrix_editbone(eBone, bmat);
2589                                                         bone_matrix_translate_y(bmat, eBone->length);
2590                                                         gpuMultMatrix(bmat);
2591
2592                                                         float viewmat_ebone[4][4];
2593                                                         mul_m4_m4m4(viewmat_ebone, rv3d->viewmatob, bmat);
2594                                                         drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS, col);
2595                                                         
2596                                                         gpuPopMatrix();
2597                                                 }
2598                                                 
2599                                         }
2600                                 }
2601                         }
2602                         
2603                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2604                 }
2605         }
2606 }
2607
2608 /* ****************************** Armature Visualization ******************************** */
2609
2610 /* ---------- Paths --------- */
2611
2612 /* draw bone paths
2613  *      - in view space 
2614  */
2615 static void draw_pose_paths(Scene *scene, View3D *v3d, ARegion *ar, Object *ob)
2616 {
2617         bAnimVizSettings *avs = &ob->pose->avs;
2618         bArmature *arm = ob->data;
2619         bPoseChannel *pchan;
2620         
2621         /* setup drawing environment for paths */
2622         draw_motion_paths_init(v3d, ar);
2623         
2624         /* draw paths where they exist and they releated bone is visible */
2625         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
2626                 if ((pchan->bone->layer & arm->layer) && (pchan->mpath))
2627                         draw_motion_path_instance(scene, ob, pchan, avs, pchan->mpath);
2628         }
2629         
2630         /* cleanup after drawing */
2631         draw_motion_paths_cleanup(v3d);
2632 }
2633
2634
2635 /* ---------- Ghosts --------- */
2636
2637 /* helper function for ghost drawing - sets/removes flags for temporarily 
2638  * hiding unselected bones while drawing ghosts
2639  */
2640 static void ghost_poses_tag_unselected(Object *ob, short unset)
2641 {
2642         bArmature *arm = ob->data;
2643         bPose *pose = ob->pose;
2644         bPoseChannel *pchan;
2645         
2646         /* don't do anything if no hiding any bones */
2647         if ((arm->flag & ARM_GHOST_ONLYSEL) == 0)
2648                 return;
2649                 
2650         /* loop over all pchans, adding/removing tags as appropriate */
2651         for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
2652                 if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
2653                         if (unset) {
2654                                 /* remove tags from all pchans if cleaning up */
2655                                 pchan->bone->flag &= ~BONE_HIDDEN_PG;
2656                         }
2657                         else {
2658                                 /* set tags on unselected pchans only */
2659                                 if ((pchan->bone->flag & BONE_SELECTED) == 0)
2660                                         pchan->bone->flag |= BONE_HIDDEN_PG;
2661                         }
2662                 }
2663         }
2664 }
2665
2666 /* draw ghosts that occur within a frame range 
2667  *  note: object should be in posemode
2668  */
2669 static void draw_ghost_poses_range(
2670         const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *sl, View3D *v3d, ARegion *ar, Base *base)
2671 {
2672         Object *ob = base->object;
2673         AnimData *adt = BKE_animdata_from_id(&ob->id);
2674         bArmature *arm = ob->data;
2675         bPose *posen, *poseo;
2676         float start, end, stepsize, range, colfac;
2677         int cfrao, flago;
2678         unsigned char col[4];
2679         
2680         start = (float)arm->ghostsf;
2681         end = (float)arm->ghostef;
2682         if (end <= start)
2683                 return;
2684         
2685         /* prevent infinite loops if this is set to 0 - T49527 */
2686         if (arm->ghostsize < 1)
2687                 arm->ghostsize = 1;
2688         
2689         stepsize = (float)(arm->ghostsize);
2690         range = (float)(end - start);
2691         
2692         /* store values */
2693         ob->mode &= ~OB_MODE_POSE;
2694         cfrao = CFRA;
2695         flago = arm->flag;
2696         arm->flag &= ~(ARM_DRAWNAMES | ARM_DRAWAXES);
2697         
2698         /* copy the pose */
2699         poseo = ob->pose;
2700         BKE_pose_copy_data(&posen, ob->pose, 1);
2701         ob->pose = posen;
2702         BKE_pose_rebuild(ob, ob->data);    /* child pointers for IK */
2703         ghost_poses_tag_unselected(ob, 0);      /* hide unselected bones if need be */
2704         
2705         glEnable(GL_BLEND);
2706         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2707         
2708         /* draw from first frame of range to last */
2709         for (CFRA = (int)start; CFRA <= end; CFRA += (int)stepsize) {
2710                 colfac = (end - (float)CFRA) / range;
2711                 UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
2712                 
2713                 BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
2714                 BKE_pose_where_is(eval_ctx, scene, ob);
2715                 draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false);
2716         }
2717         glDisable(GL_BLEND);
2718         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2719         
2720         /* before disposing of temp pose, use it to restore object to a sane state */
2721         BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)cfrao, ADT_RECALC_ALL);
2722         
2723         /* clean up temporary pose */
2724         ghost_poses_tag_unselected(ob, 1);      /* unhide unselected bones if need be */
2725         BKE_pose_free(posen);
2726         
2727         /* restore */
2728         CFRA = cfrao;
2729         ob->pose = poseo;
2730         arm->flag = flago;
2731         ob->mode |= OB_MODE_POSE;
2732 }
2733
2734 /* draw ghosts on keyframes in action within range 
2735  *      - object should be in posemode 
2736  */
2737 static void draw_ghost_poses_keys(
2738         const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *sl,
2739         View3D *v3d, ARegion *ar, Base *base)
2740 {
2741         Object *ob = base->object;
2742         AnimData *adt = BKE_animdata_from_id(&ob->id);