Orange: Display types and variable size for Empties.
[blender-staging.git] / source / blender / src / drawarmature.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BMF_Api.h"
41
42 #include "DNA_action_types.h"
43 #include "DNA_armature_types.h"
44 #include "DNA_constraint_types.h"
45 #include "DNA_ID.h"
46 #include "DNA_nla_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_view3d_types.h"
52
53 #include "BLI_blenlib.h"
54 #include "BLI_arithb.h"
55
56 #include "BKE_action.h"
57 #include "BKE_armature.h"
58 #include "BKE_constraint.h"
59 #include "BKE_depsgraph.h"
60 #include "BKE_DerivedMesh.h"
61 #include "BKE_global.h"
62 #include "BKE_main.h"
63 #include "BKE_object.h"
64 #include "BKE_utildefines.h"
65
66 #include "BIF_editarmature.h"
67 #include "BIF_gl.h"
68 #include "BIF_glutil.h"
69 #include "BIF_graphics.h"
70 #include "BIF_interface.h"
71 #include "BIF_poseobject.h"
72 #include "BIF_mywindow.h"
73 #include "BIF_resources.h"
74 #include "BIF_screen.h"
75
76 #include "BDR_editobject.h"
77 #include "BDR_drawobject.h"
78
79 #include "BSE_edit.h"
80 #include "BSE_view.h"
81
82 #include "mydevice.h"
83 #include "blendef.h"
84 #include "nla.h"
85
86 /* half the cube, in Y */
87 static float cube[8][3] = {
88 {-1.0,  0.0, -1.0},
89 {-1.0,  0.0,  1.0},
90 {-1.0,  1.0,  1.0},
91 {-1.0,  1.0, -1.0},
92 { 1.0,  0.0, -1.0},
93 { 1.0,  0.0,  1.0},
94 { 1.0,  1.0,  1.0},
95 { 1.0,  1.0, -1.0},
96 };
97
98
99 /* *************** Armature drawing, helper calls for parts ******************* */
100
101 static void drawsolidcube_size(float xsize, float ysize, float zsize)
102 {
103         float n[3];
104         
105         glScalef(xsize, ysize, zsize);
106         
107         n[0]=0; n[1]=0; n[2]=0;
108         glBegin(GL_QUADS);
109         n[0]= -1.0;
110         glNormal3fv(n); 
111         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
112         n[0]=0;
113         glEnd();
114         
115         glBegin(GL_QUADS);
116         n[1]= -1.0;
117         glNormal3fv(n); 
118         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
119         n[1]=0;
120         glEnd();
121         
122         glBegin(GL_QUADS);
123         n[0]= 1.0;
124         glNormal3fv(n); 
125         glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
126         n[0]=0;
127         glEnd();
128         
129         glBegin(GL_QUADS);
130         n[1]= 1.0;
131         glNormal3fv(n); 
132         glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
133         n[1]=0;
134         glEnd();
135         
136         glBegin(GL_QUADS);
137         n[2]= 1.0;
138         glNormal3fv(n); 
139         glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
140         n[2]=0;
141         glEnd();
142         
143         glBegin(GL_QUADS);
144         n[2]= -1.0;
145         glNormal3fv(n); 
146         glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
147         glEnd();
148         
149 }
150
151 static void drawcube_size(float xsize, float ysize, float zsize)
152 {
153         
154         glScalef(xsize, ysize, zsize);
155         
156         glBegin(GL_LINE_STRIP);
157         glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
158         glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
159         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
160         glEnd();
161         
162         glBegin(GL_LINE_STRIP);
163         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
164         glEnd();
165         
166         glBegin(GL_LINE_STRIP);
167         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
168         glEnd();
169         
170         glBegin(GL_LINE_STRIP);
171         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
172         glEnd();
173         
174 }
175
176
177 static void draw_bonevert(void)
178 {
179         static GLuint displist=0;
180         
181         if(displist==0) {
182                 GLUquadricObj   *qobj;
183                 
184                 displist= glGenLists(1);
185                 glNewList(displist, GL_COMPILE_AND_EXECUTE);
186                                 
187                 glPushMatrix();
188                 
189                 qobj    = gluNewQuadric(); 
190                 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
191                 gluDisk( qobj, 0.0,  0.05, 16, 1);
192                 
193                 glRotatef (90, 0, 1, 0);
194                 gluDisk( qobj, 0.0,  0.05, 16, 1);
195                 
196                 glRotatef (90, 1, 0, 0);
197                 gluDisk( qobj, 0.0,  0.05, 16, 1);
198                 
199                 gluDeleteQuadric(qobj);  
200                 
201                 glPopMatrix();
202                 glEndList();
203         }
204         else glCallList(displist);
205 }
206
207 static void draw_bonevert_solid(void)
208 {
209         static GLuint displist=0;
210         
211         if(displist==0) {
212                 GLUquadricObj   *qobj;
213                 
214                 displist= glGenLists(1);
215                 glNewList(displist, GL_COMPILE_AND_EXECUTE);
216                 
217                 qobj    = gluNewQuadric();
218                 gluQuadricDrawStyle(qobj, GLU_FILL); 
219                 glShadeModel(GL_SMOOTH);
220                 gluSphere( qobj, 0.05, 8, 5);
221                 glShadeModel(GL_FLAT);
222                 gluDeleteQuadric(qobj);  
223                 
224                 glEndList();
225         }
226         else glCallList(displist);
227 }
228
229 static void draw_bone_octahedral()
230 {
231         static GLuint displist=0;
232         
233         if(displist==0) {
234                 float vec[6][3];        
235                 
236                 displist= glGenLists(1);
237                 glNewList(displist, GL_COMPILE_AND_EXECUTE);
238
239                 vec[0][0]= vec[0][1]= vec[0][2]= 0.0;
240                 vec[5][0]= vec[5][2]= 0.0; vec[5][1]= 1.0;
241                 
242                 vec[1][0]= 0.1; vec[1][2]= 0.1; vec[1][1]= 0.1;
243                 vec[2][0]= 0.1; vec[2][2]= -0.1; vec[2][1]= 0.1;
244                 vec[3][0]= -0.1; vec[3][2]= -0.1; vec[3][1]= 0.1;
245                 vec[4][0]= -0.1; vec[4][2]= 0.1; vec[4][1]= 0.1;
246                 
247                 /*      Section 1, sides */
248                 glBegin(GL_LINE_LOOP);
249                 glVertex3fv(vec[0]);
250                 glVertex3fv(vec[1]);
251                 glVertex3fv(vec[5]);
252                 glVertex3fv(vec[3]);
253                 glVertex3fv(vec[0]);
254                 glVertex3fv(vec[4]);
255                 glVertex3fv(vec[5]);
256                 glVertex3fv(vec[2]);
257                 glEnd();
258                 
259                 /*      Section 1, square */
260                 glBegin(GL_LINE_LOOP);
261                 glVertex3fv(vec[1]);
262                 glVertex3fv(vec[2]);
263                 glVertex3fv(vec[3]);
264                 glVertex3fv(vec[4]);
265                 glEnd();
266                 
267                 glEndList();
268         }
269         else glCallList(displist);
270 }       
271
272 static void draw_bone_solid_octahedral(void)
273 {
274         static GLuint displist=0;
275         
276         if(displist==0) {
277                 float vec[6][3], nor[3];        
278                 
279                 displist= glGenLists(1);
280                 glNewList(displist, GL_COMPILE_AND_EXECUTE);
281                 
282                 vec[0][0]= vec[0][1]= vec[0][2]= 0.0;
283                 vec[5][0]= vec[5][2]= 0.0; vec[5][1]= 1.0;
284                 
285                 vec[1][0]= 0.1; vec[1][2]= 0.1; vec[1][1]= 0.1;
286                 vec[2][0]= 0.1; vec[2][2]= -0.1; vec[2][1]= 0.1;
287                 vec[3][0]= -0.1; vec[3][2]= -0.1; vec[3][1]= 0.1;
288                 vec[4][0]= -0.1; vec[4][2]= 0.1; vec[4][1]= 0.1;
289                 
290                 
291                 glBegin(GL_TRIANGLES);
292                 /* bottom */
293                 CalcNormFloat(vec[2], vec[1], vec[0], nor);
294                 glNormal3fv(nor);
295                 glVertex3fv(vec[2]);glVertex3fv(vec[1]);glVertex3fv(vec[0]);
296                 
297                 CalcNormFloat(vec[3], vec[2], vec[0], nor);
298                 glNormal3fv(nor);
299                 glVertex3fv(vec[3]);glVertex3fv(vec[2]);glVertex3fv(vec[0]);
300                 
301                 CalcNormFloat(vec[4], vec[3], vec[0], nor);
302                 glNormal3fv(nor);
303                 glVertex3fv(vec[4]);glVertex3fv(vec[3]);glVertex3fv(vec[0]);
304
305                 CalcNormFloat(vec[1], vec[4], vec[0], nor);
306                 glNormal3fv(nor);
307                 glVertex3fv(vec[1]);glVertex3fv(vec[4]);glVertex3fv(vec[0]);
308
309                 /* top */
310                 CalcNormFloat(vec[5], vec[1], vec[2], nor);
311                 glNormal3fv(nor);
312                 glVertex3fv(vec[5]);glVertex3fv(vec[1]);glVertex3fv(vec[2]);
313                 
314                 CalcNormFloat(vec[5], vec[2], vec[3], nor);
315                 glNormal3fv(nor);
316                 glVertex3fv(vec[5]);glVertex3fv(vec[2]);glVertex3fv(vec[3]);
317                 
318                 CalcNormFloat(vec[5], vec[3], vec[4], nor);
319                 glNormal3fv(nor);
320                 glVertex3fv(vec[5]);glVertex3fv(vec[3]);glVertex3fv(vec[4]);
321                 
322                 CalcNormFloat(vec[5], vec[4], vec[1], nor);
323                 glNormal3fv(nor);
324                 glVertex3fv(vec[5]);glVertex3fv(vec[4]);glVertex3fv(vec[1]);
325                 
326                 glEnd();
327                 
328                 glEndList();
329         }
330         else glCallList(displist);
331 }       
332
333 /* *************** Armature drawing, bones ******************* */
334
335
336 static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
337 {
338         /*      Draw root point if we are not connected */
339         if (!(boneflag & BONE_CONNECTED)){
340                 if (id != -1)
341                         glLoadName (id | BONESEL_ROOT);
342                 
343                 if(dt<=OB_WIRE) {
344                         if(armflag & ARM_EDITMODE) {
345                                 if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
346                                 else BIF_ThemeColor(TH_VERTEX);
347                         }
348                 }
349                 else 
350                         BIF_ThemeColor(TH_BONE_SOLID);
351                 
352                 if(dt>OB_WIRE) draw_bonevert_solid();
353                 else draw_bonevert();
354         }
355         
356         /*      Draw tip point */
357         if (id != -1)
358                 glLoadName (id | BONESEL_TIP);
359         
360         if(dt<=OB_WIRE) {
361                 if(armflag & ARM_EDITMODE) {
362                         if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
363                         else BIF_ThemeColor(TH_VERTEX);
364                 }
365         }
366         else {
367                 BIF_ThemeColor(TH_BONE_SOLID);
368         }
369         
370         glTranslatef(0.0, 1.0, 0.0);
371         if(dt>OB_WIRE) draw_bonevert_solid();
372         else draw_bonevert();
373         glTranslatef(0.0, -1.0, 0.0);
374         
375 }
376
377 /* 16 values of sin function (still same result!) */
378 static float si[16] = {
379         0.00000000,
380         0.20129852, 0.39435585,
381         0.57126821, 0.72479278,
382         0.84864425, 0.93775213,
383         0.98846832, 0.99871650,
384         0.96807711, 0.89780453,
385         0.79077573, 0.65137248,
386         0.48530196, 0.29936312,
387         0.10116832
388 };
389 /* 16 values of cos function (still same result!) */
390 static float co[16] ={
391         1.00000000,
392         0.97952994, 0.91895781,
393         0.82076344, 0.68896691,
394         0.52896401, 0.34730525,
395         0.15142777, -0.05064916,
396         -0.25065253, -0.44039415,
397         -0.61210598, -0.75875812,
398         -0.87434661, -0.95413925,
399         -0.99486932
400 };
401
402
403
404 /* smat, imat = mat & imat to draw screenaligned */
405 static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag, bPoseChannel *pchan, EditBone *ebone)
406 {
407         float head, tail, length, dist;
408         float *headvec, *tailvec, dirvec[3];
409         
410         /* figure out the sizes of spheres */
411         if(ebone) {
412                 /* this routine doesn't call set_matrix_editbone() that calculates it */
413                 ebone->length = VecLenf(ebone->head, ebone->tail);
414                 
415                 length= ebone->length;
416                 tail= ebone->rad_tail;
417                 dist= ebone->dist;
418                 if (ebone->parent && (ebone->flag & BONE_CONNECTED))
419                         head= ebone->parent->rad_tail;
420                 else
421                         head= ebone->rad_head;
422                 headvec= ebone->head;
423                 tailvec= ebone->tail;
424         }
425         else {
426                 length= pchan->bone->length;
427                 tail= pchan->bone->rad_tail;
428                 dist= pchan->bone->dist;
429                 if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
430                         head= pchan->parent->bone->rad_tail;
431                 else
432                         head= pchan->bone->rad_head;
433                 headvec= pchan->pose_head;
434                 tailvec= pchan->pose_tail;
435         }
436         
437         /* ***** draw it ***** */
438         
439         /* move vector to viewspace */
440         VecSubf(dirvec, tailvec, headvec);
441         Mat4Mul3Vecfl(smat, dirvec);
442         /* clear zcomp */
443         dirvec[2]= 0.0;
444         /* move vector back */
445         Mat4Mul3Vecfl(imat, dirvec);
446         
447         if(0.0f != Normalise(dirvec)) {
448                 float norvec[3], vec1[3], vec2[3], vec[3];
449                 int a;
450                 
451                 //VecMulf(dirvec, head);
452                 Crossf(norvec, dirvec, imat[2]);
453                 
454                 glBegin(GL_QUAD_STRIP);
455
456                 for(a=0; a<16; a++) {
457                         vec[0]= - *(si+a) * dirvec[0] + *(co+a) * norvec[0];
458                         vec[1]= - *(si+a) * dirvec[1] + *(co+a) * norvec[1];
459                         vec[2]= - *(si+a) * dirvec[2] + *(co+a) * norvec[2];
460                         
461                         vec1[0]= headvec[0] + head*vec[0];
462                         vec1[1]= headvec[1] + head*vec[1];
463                         vec1[2]= headvec[2] + head*vec[2];
464                         vec2[0]= headvec[0] + (head+dist)*vec[0];
465                         vec2[1]= headvec[1] + (head+dist)*vec[1];
466                         vec2[2]= headvec[2] + (head+dist)*vec[2];
467                         
468                         glColor4ub(255, 255, 255, 50);
469                         glVertex3fv(vec1);
470                         //glColor4ub(255, 255, 255, 0);
471                         glVertex3fv(vec2);
472                 }
473                 
474                 for(a=15; a>=0; a--) {
475                         vec[0]= *(si+a) * dirvec[0] + *(co+a) * norvec[0];
476                         vec[1]= *(si+a) * dirvec[1] + *(co+a) * norvec[1];
477                         vec[2]= *(si+a) * dirvec[2] + *(co+a) * norvec[2];
478                         
479                         vec1[0]= tailvec[0] + tail*vec[0];
480                         vec1[1]= tailvec[1] + tail*vec[1];
481                         vec1[2]= tailvec[2] + tail*vec[2];
482                         vec2[0]= tailvec[0] + (tail+dist)*vec[0];
483                         vec2[1]= tailvec[1] + (tail+dist)*vec[1];
484                         vec2[2]= tailvec[2] + (tail+dist)*vec[2];
485                         
486                         //glColor4ub(255, 255, 255, 50);
487                         glVertex3fv(vec1);
488                         //glColor4ub(255, 255, 255, 0);
489                         glVertex3fv(vec2);
490                 }
491                 /* make it cyclic... */
492                 
493                 vec[0]= - *(si) * dirvec[0] + *(co) * norvec[0];
494                 vec[1]= - *(si) * dirvec[1] + *(co) * norvec[1];
495                 vec[2]= - *(si) * dirvec[2] + *(co) * norvec[2];
496                 
497                 vec1[0]= headvec[0] + head*vec[0];
498                 vec1[1]= headvec[1] + head*vec[1];
499                 vec1[2]= headvec[2] + head*vec[2];
500                 vec2[0]= headvec[0] + (head+dist)*vec[0];
501                 vec2[1]= headvec[1] + (head+dist)*vec[1];
502                 vec2[2]= headvec[2] + (head+dist)*vec[2];
503                 
504                 //glColor4ub(255, 255, 255, 50);
505                 glVertex3fv(vec1);
506                 //glColor4ub(255, 255, 255, 0);
507                 glVertex3fv(vec2);
508                 
509                 glEnd();
510         }
511 }
512
513
514 /* smat, imat = mat & imat to draw screenaligned */
515 static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
516 {
517         float head, tail, length;
518         float *headvec, *tailvec, dirvec[3];
519         
520         /* figure out the sizes of spheres */
521         if(ebone) {
522                 /* this routine doesn't call set_matrix_editbone() that calculates it */
523                 ebone->length = VecLenf(ebone->head, ebone->tail);
524
525                 length= ebone->length;
526                 tail= ebone->rad_tail;
527                 if (ebone->parent && (boneflag & BONE_CONNECTED))
528                         head= ebone->parent->rad_tail;
529                 else
530                         head= ebone->rad_head;
531                 headvec= ebone->head;
532                 tailvec= ebone->tail;
533         }
534         else {
535                 length= pchan->bone->length;
536                 tail= pchan->bone->rad_tail;
537                 if (pchan->parent && (boneflag & BONE_CONNECTED))
538                         head= pchan->parent->bone->rad_tail;
539                 else
540                         head= pchan->bone->rad_head;
541                 headvec= pchan->pose_head;
542                 tailvec= pchan->pose_tail;
543         }
544         
545         /* sphere root color */
546         if(armflag & ARM_EDITMODE) {
547                 if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
548                 else BIF_ThemeColor(TH_VERTEX);
549         }
550         else if(armflag & ARM_POSEMODE) {
551                 /* in black or selection color */
552                 if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
553                 else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
554                 else BIF_ThemeColor(TH_WIRE);
555         }
556         
557         /*      Draw root point if we are not connected */
558         if (!(boneflag & BONE_CONNECTED)){
559                 if (id != -1)
560                         glLoadName (id | BONESEL_ROOT);
561                 
562                 drawcircball(GL_LINE_LOOP, headvec, head, imat);
563         }
564         
565         /*      Draw tip point */
566         if(armflag & ARM_EDITMODE) {
567                 if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
568                 else BIF_ThemeColor(TH_VERTEX);
569         }
570         
571         if (id != -1)
572                 glLoadName (id | BONESEL_TIP);
573         
574         drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
575         
576         /* base */
577         if(armflag & ARM_EDITMODE) {
578                 if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_SELECT);
579                 else BIF_ThemeColor(TH_WIRE);
580         }
581         
582         VecSubf(dirvec, tailvec, headvec);
583         
584         /* move vector to viewspace */
585         Mat4Mul3Vecfl(smat, dirvec);
586         /* clear zcomp */
587         dirvec[2]= 0.0;
588         /* move vector back */
589         Mat4Mul3Vecfl(imat, dirvec);
590         
591         if(0.0f != Normalise(dirvec)) {
592                 float norvech[3], norvect[3], vec[3];
593                 
594                 VECCOPY(vec, dirvec);
595                 
596                 VecMulf(dirvec, head);
597                 Crossf(norvech, dirvec, imat[2]);
598                 
599                 VecMulf(vec, tail);
600                 Crossf(norvect, vec, imat[2]);
601                 
602                 if (id != -1)
603                         glLoadName (id | BONESEL_BONE);
604
605                 glBegin(GL_LINES);
606                 vec[0]= headvec[0] + norvech[0];
607                 vec[1]= headvec[1] + norvech[1];
608                 vec[2]= headvec[2] + norvech[2];
609                 glVertex3fv(vec);
610                 vec[0]= tailvec[0] + norvect[0];
611                 vec[1]= tailvec[1] + norvect[1];
612                 vec[2]= tailvec[2] + norvect[2];
613                 glVertex3fv(vec);
614                 vec[0]= headvec[0] - norvech[0];
615                 vec[1]= headvec[1] - norvech[1];
616                 vec[2]= headvec[2] - norvech[2];
617                 glVertex3fv(vec);
618                 vec[0]= tailvec[0] - norvect[0];
619                 vec[1]= tailvec[1] - norvect[1];
620                 vec[2]= tailvec[2] - norvect[2];
621                 glVertex3fv(vec);
622                 
623                 glEnd();
624         }
625 }
626
627 /* does wire only for outline selecting */
628 static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
629 {
630         GLUquadricObj   *qobj;
631         float head, tail, length;
632         float fac1, fac2;
633         
634         glPushMatrix();
635         qobj    = gluNewQuadric();
636
637         /* figure out the sizes of spheres */
638         if(ebone) {
639                 length= ebone->length;
640                 tail= ebone->rad_tail;
641                 if (ebone->parent && (boneflag & BONE_CONNECTED))
642                         head= ebone->parent->rad_tail;
643                 else
644                         head= ebone->rad_head;
645         }
646         else {
647                 length= pchan->bone->length;
648                 tail= pchan->bone->rad_tail;
649                 if (pchan->parent && (boneflag & BONE_CONNECTED))
650                         head= pchan->parent->bone->rad_tail;
651                 else
652                         head= pchan->bone->rad_head;
653         }
654         
655         /* move to z-axis space */
656         glRotatef (-90.0f, 1.0f, 0.0f, 0.0f);
657
658         if(dt==OB_SOLID) {
659                 /* set up solid drawing */
660                 glEnable(GL_COLOR_MATERIAL);
661                 glEnable(GL_LIGHTING);
662                 
663                 gluQuadricDrawStyle(qobj, GLU_FILL); 
664                 glShadeModel(GL_SMOOTH);
665         }
666         else {
667                 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
668         }
669         
670         /* sphere root color */
671         if(armflag & ARM_EDITMODE) {
672                 if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
673                 else BIF_ThemeColorShade(TH_BONE_SOLID, -30);
674         }
675         else if(armflag & ARM_POSEMODE) {
676                 if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 10);
677                 else if (boneflag & BONE_SELECTED) BIF_ThemeColorShade(TH_BONE_POSE, -30);
678                 else BIF_ThemeColorShade(TH_BONE_SOLID, -30);
679                 
680         }
681         else if(dt==OB_SOLID) 
682                 BIF_ThemeColorShade(TH_BONE_SOLID, -30);
683         
684         /*      Draw root point if we are not connected */
685         if (!(boneflag & BONE_CONNECTED)){
686                 if (id != -1)
687                         glLoadName (id | BONESEL_ROOT);
688                 gluSphere( qobj, head, 16, 10);
689         }
690         
691         /*      Draw tip point */
692         if(armflag & ARM_EDITMODE) {
693                 if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
694                 else BIF_ThemeColorShade(TH_BONE_SOLID, -30);
695         }
696
697         if (id != -1)
698                 glLoadName (id | BONESEL_TIP);
699         
700         glTranslatef(0.0, 0.0, length);
701         gluSphere( qobj, tail, 16, 10);
702         glTranslatef(0.0, 0.0, -length);
703         
704         /* base */
705         if(armflag & ARM_EDITMODE) {
706                 if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_SELECT);
707                 else BIF_ThemeColor(TH_BONE_SOLID);
708         }
709         else if(armflag & ARM_POSEMODE) {
710                 if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
711                 else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
712                 else BIF_ThemeColor(TH_BONE_SOLID);
713                 
714         }
715         else if(dt==OB_SOLID)
716                 BIF_ThemeColor(TH_BONE_SOLID);
717         
718         fac1= (length-head)/length;
719         fac2= (length-tail)/length;
720         
721         if(length > head+tail) {
722                 if (id != -1)
723                         glLoadName (id | BONESEL_BONE);
724                 
725                 glEnable(GL_POLYGON_OFFSET_FILL);
726                 glPolygonOffset(-1.0, -1.0);
727                 
728                 glTranslatef(0.0f, 0.0f, head);
729                 gluCylinder(qobj, fac1*head + (1.0f-fac1)*tail, fac2*tail + (1.0f-fac2)*head, length-head-tail, 16, 1);
730                 glTranslatef(0.0f, 0.0f, -head);
731
732                 glDisable(GL_POLYGON_OFFSET_FILL);
733                 
734                 /* draw sphere on extrema */
735                 glTranslatef(0.0f, 0.0f, length-tail);
736                 gluSphere( qobj, fac2*tail + (1.0f-fac2)*head, 16, 10);
737                 glTranslatef(0.0f, 0.0f, -length+tail);
738
739                 glTranslatef(0.0f, 0.0f, head);
740                 gluSphere( qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
741         }
742         else {          
743                 /* 1 sphere in center */
744                 glTranslatef(0.0f, 0.0f, (head + length-tail)/2.0);
745                 gluSphere( qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
746         }
747         
748         /* restore */
749         if(dt==OB_SOLID) {
750                 glShadeModel(GL_FLAT);
751                 glDisable(GL_LIGHTING);
752                 glDisable(GL_COLOR_MATERIAL);
753         }
754         
755         glPopMatrix();
756         gluDeleteQuadric(qobj);  
757 }
758
759 static char bm_dot6[]= {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0}; 
760 static char bm_dot8[]= {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}; 
761
762 static char bm_dot5[]= {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0}; 
763 static char bm_dot7[]= {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38}; 
764
765
766 static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
767 {
768         float length;
769         
770         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
771         
772         if(pchan) 
773                 length= pchan->bone->length;
774         else 
775                 length= ebone->length;
776         
777         glPushMatrix();
778         glScalef(length, length, length);
779         
780         /* this chunk not in object mode */
781         if(armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
782                 glLineWidth(4.0);
783                 if(armflag & ARM_POSEMODE) {
784                         /* outline in black or selection color */
785                         if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
786                         else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
787                         else BIF_ThemeColor(TH_WIRE);
788                 }
789                 else if (armflag & ARM_EDITMODE) {
790                         BIF_ThemeColor(TH_WIRE);
791                 }
792                 
793                 /*      Draw root point if we are not connected */
794                 if (!(boneflag & BONE_CONNECTED)){
795                         if (G.f & G_PICKSEL) {  // no bitmap in selection mode, crashes 3d cards...
796                                 glLoadName (id | BONESEL_ROOT);
797                                 glBegin(GL_POINTS);
798                                 glVertex3f(0.0f, 0.0f, 0.0f);
799                                 glEnd();
800                         }
801                         else {
802                                 glRasterPos3f(0.0f, 0.0f, 0.0f);
803                                 glBitmap(8, 8, 4, 4, 0, 0, bm_dot8);
804                         }
805                 }
806                 
807                 if (id != -1)
808                         glLoadName ((GLuint) id|BONESEL_BONE);
809                 
810                 glBegin(GL_LINES);
811                 glVertex3f(0.0f, 0.0f, 0.0f);
812                 glVertex3f(0.0f, 1.0f, 0.0f);
813                 glEnd();
814                 
815                 /* tip */
816                 if (G.f & G_PICKSEL) {  // no bitmap in selection mode, crashes 3d cards...
817                         glLoadName (id | BONESEL_TIP);
818                         glBegin(GL_POINTS);
819                         glVertex3f(0.0f, 1.0f, 0.0f);
820                         glEnd();
821                 }
822                 else {
823                         glRasterPos3f(0.0f, 1.0f, 0.0f);
824                         glBitmap(8, 8, 4, 4, 0, 0, bm_dot7);
825                 }
826                 
827                 /* further we send no names */
828                 if (id != -1)
829                         glLoadName (id & 0xFFFF);       // object tag, for bordersel optim
830                 
831                 if(armflag & ARM_POSEMODE) {
832                         /* inner part in background color or constraint */
833                         if(constflag) {
834                                 if(constflag & PCHAN_HAS_STRIDE) glColor3ub(0, 0, 200);
835                                 else if(constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0);
836                                 else if(constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0);
837                                 else if(constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120);
838                                 else BIF_ThemeColor(TH_BONE_POSE);      // PCHAN_HAS_ACTION 
839                         }
840                         else BIF_ThemeColor(TH_BACK);
841                 }
842         }
843         
844         glLineWidth(2.0);
845         
846         /*      Draw root point if we are not connected */
847         if (!(boneflag & BONE_CONNECTED)){
848                 if ((G.f & G_PICKSEL)==0) {     // no bitmap in selection mode, crashes 3d cards...
849                         if(armflag & ARM_EDITMODE) {
850                                 if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
851                                 else BIF_ThemeColor(TH_VERTEX);
852                         }
853                         glRasterPos3f(0.0f, 0.0f, 0.0f);
854                         glBitmap(8, 8, 4, 4, 0, 0, bm_dot6);
855                 }
856         }
857         
858    if(armflag & ARM_EDITMODE) {
859            if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_EDGE_SELECT);
860            else BIF_ThemeColor(TH_BACK);
861    }
862         glBegin(GL_LINES);
863         glVertex3f(0.0f, 0.0f, 0.0f);
864         glVertex3f(0.0f, 1.0f, 0.0f);
865         glEnd();
866         
867         /* tip */
868         if ((G.f & G_PICKSEL)==0) {     // no bitmap in selection mode, crashes 3d cards...
869                 if(armflag & ARM_EDITMODE) {
870                         if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
871                         else BIF_ThemeColor(TH_VERTEX);
872                 }
873                 glRasterPos3f(0.0f, 1.0f, 0.0f);
874                 glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
875         }
876         
877         glLineWidth(1.0);
878         
879         glPopMatrix();
880 }
881
882 static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
883 {
884         int segments= 0;
885         
886         if(pchan) segments= pchan->bone->segments;
887         
888         if(segments>1 && pchan) {
889                 float dlen= length/(float)segments;
890                 Mat4 *bbone= b_bone_spline_setup(pchan);
891                 int a;
892                 
893                 for(a=0; a<segments; a++, bbone++) {
894                         glPushMatrix();
895                         glMultMatrixf(bbone->mat);
896                         if(dt==OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
897                         else drawcube_size(xwidth, dlen, zwidth);
898                         glPopMatrix();
899                 }
900         }
901         else {
902                 glPushMatrix();
903                 if(dt==OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
904                 else drawcube_size(xwidth, length, zwidth);
905                 glPopMatrix();
906         }
907 }
908
909 static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
910 {
911         float xwidth, length, zwidth;
912         
913         if(pchan) {
914                 xwidth= pchan->bone->xwidth;
915                 length= pchan->bone->length;
916                 zwidth= pchan->bone->zwidth;
917         }
918         else {
919                 xwidth= ebone->xwidth;
920                 length= ebone->length;
921                 zwidth= ebone->zwidth;
922         }
923         
924         /* draw points only if... */
925         if(armflag & ARM_EDITMODE) {
926                 /* move to unitspace */
927                 glPushMatrix();
928                 glScalef(length, length, length);
929                 draw_bone_points(dt, armflag, boneflag, id);
930                 glPopMatrix();
931                 length*= 0.95f; // make vertices visible
932         }
933
934         /* colors for modes */
935         if (armflag & ARM_POSEMODE) {
936                 if(dt==OB_WIRE) {
937                         if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
938                         else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
939                         else BIF_ThemeColor(TH_WIRE);
940                 }
941                 else 
942                         BIF_ThemeColor(TH_BONE_SOLID);
943         }
944         else if (armflag & ARM_EDITMODE) {
945                 if(dt==OB_WIRE) {
946                         if (boneflag & BONE_ACTIVE) BIF_ThemeColor(TH_EDGE_SELECT);
947                         else if (boneflag & BONE_SELECTED) BIF_ThemeColorShade(TH_EDGE_SELECT, -20);
948                         else BIF_ThemeColor(TH_WIRE);
949                 }
950                 else 
951                         BIF_ThemeColor(TH_BONE_SOLID);
952         }
953         
954         if (id != -1) {
955                 glLoadName ((GLuint) id|BONESEL_BONE);
956         }
957         
958         /* set up solid drawing */
959         if(dt > OB_WIRE) {
960                 glEnable(GL_COLOR_MATERIAL);
961                 glEnable(GL_LIGHTING);
962                 BIF_ThemeColor(TH_BONE_SOLID);
963                 
964                 draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
965                 
966                 /* disable solid drawing */
967                 glDisable(GL_COLOR_MATERIAL);
968                 glDisable(GL_LIGHTING);
969         }
970         else {  // wire
971                 if (armflag & ARM_POSEMODE){
972                         if(constflag) {
973                                 glEnable(GL_BLEND);
974                                 
975                                 if(constflag & PCHAN_HAS_STRIDE) glColor4ub(0, 0, 200, 80);
976                                 else if(constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80);
977                                 else if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
978                                 else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
979                                 else BIF_ThemeColor4(TH_BONE_POSE);     // PCHAN_HAS_ACTION 
980                                 
981                                 draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
982                                 
983                                 glDisable(GL_BLEND);
984                                 
985                                 /* restore colors */
986                                 if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
987                                 else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
988                                 else BIF_ThemeColor(TH_WIRE);
989                         }
990                 }               
991                 
992                 draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);              
993         }
994 }
995
996 static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length)
997 {
998         
999         /*      Draw a 3d octahedral bone, we use normalized space based on length,
1000             for glDisplayLists */
1001         
1002         glScalef(length, length, length);
1003
1004         /* set up solid drawing */
1005         if(dt > OB_WIRE) {
1006                 glEnable(GL_COLOR_MATERIAL);
1007                 glEnable(GL_LIGHTING);
1008                 BIF_ThemeColor(TH_BONE_SOLID);
1009         }
1010         
1011         /* colors for posemode */
1012         if (armflag & ARM_POSEMODE) {
1013                 if(dt==OB_WIRE) {
1014                         if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
1015                         else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
1016                         else BIF_ThemeColor(TH_WIRE);
1017                 }
1018                 else 
1019                         BIF_ThemeColor(TH_BONE_SOLID);
1020         }
1021         
1022         
1023         draw_bone_points(dt, armflag, boneflag, id);
1024         
1025         /* now draw the bone itself */
1026         
1027         if (id != -1) {
1028                 glLoadName ((GLuint) id|BONESEL_BONE);
1029         }
1030         
1031         /* wire? */
1032         if(dt <= OB_WIRE) {
1033                 /* colors */
1034                 if (armflag & ARM_EDITMODE) {
1035                         if (boneflag & BONE_ACTIVE) BIF_ThemeColor(TH_EDGE_SELECT);
1036                         else if (boneflag & BONE_SELECTED) BIF_ThemeColorShade(TH_EDGE_SELECT, -20);
1037                         else BIF_ThemeColor(TH_WIRE);
1038                 }
1039                 else if (armflag & ARM_POSEMODE){
1040                         if(constflag) {
1041                                 glEnable(GL_BLEND);
1042                                 
1043                                 if(constflag & PCHAN_HAS_STRIDE) glColor4ub(0, 0, 200, 80);
1044                                 else if(constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80);
1045                                 else if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
1046                                 else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
1047                                 else BIF_ThemeColor4(TH_BONE_POSE);     // PCHAN_HAS_ACTION 
1048                                         
1049                                 draw_bone_solid_octahedral();
1050                                 glDisable(GL_BLEND);
1051
1052                                 /* restore colors */
1053                                 if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
1054                                 else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
1055                                 else BIF_ThemeColor(TH_WIRE);
1056                         }
1057                 }               
1058                 draw_bone_octahedral();
1059         }
1060         else {  /* solid */
1061
1062                 BIF_ThemeColor(TH_BONE_SOLID);
1063                 draw_bone_solid_octahedral();
1064         }
1065
1066         /* disable solid drawing */
1067         if(dt>OB_WIRE) {
1068                 glDisable(GL_COLOR_MATERIAL);
1069                 glDisable(GL_LIGHTING);
1070         }
1071 }
1072
1073 static void draw_custom_bone(Object *ob, int dt, int armflag, int boneflag, unsigned int id, float length)
1074 {
1075         
1076         if(ob==NULL || ob->type!=OB_MESH) return;
1077         
1078         glScalef(length, length, length);
1079         
1080         /* colors for posemode */
1081         if (armflag & ARM_POSEMODE) {
1082                 if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
1083                 else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
1084                 else BIF_ThemeColor(TH_WIRE);
1085         }
1086         
1087         if (id != -1) {
1088                 glLoadName ((GLuint) id|BONESEL_BONE);
1089         }
1090         
1091         draw_object_instance(ob, dt, armflag & ARM_POSEMODE);
1092 }
1093
1094
1095 static void pchan_draw_IK_root_lines(bPoseChannel *pchan)
1096 {
1097         bConstraint *con;
1098         bPoseChannel *parchan;
1099         
1100         for(con= pchan->constraints.first; con; con= con->next) {
1101                 if(con->type == CONSTRAINT_TYPE_KINEMATIC) {
1102                         bKinematicConstraint *data = (bKinematicConstraint*)con->data;
1103                         int segcount= 0;
1104                         
1105                         setlinestyle(3);
1106                         glBegin(GL_LINES);
1107                         
1108                         /* exclude tip from chain? */
1109                         if(!(data->flag & CONSTRAINT_IK_TIP))
1110                                 parchan= pchan->parent;
1111                         else
1112                                 parchan= pchan;
1113                         
1114                         glVertex3fv(parchan->pose_tail);
1115                         
1116                         /* Find the chain's root */
1117                         while (parchan->parent){
1118                                 segcount++;
1119                                 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
1120                                 parchan= parchan->parent;
1121                         }
1122                         if(parchan)
1123                                 glVertex3fv(parchan->pose_head);
1124                         
1125                         glEnd();
1126                         setlinestyle(0);
1127                 }
1128         }
1129 }
1130
1131 static void bgl_sphere_project(float ax, float az)
1132 {
1133         float dir[3], sine, q3;
1134
1135         sine= 1.0f-ax*ax-az*az;
1136         q3= (sine < 0.0f)? 0.0f: 2.0f*sqrt(sine);
1137
1138         dir[0]= -az*q3;
1139         dir[1]= 1.0f-2.0f*sine;
1140         dir[2]= ax*q3;
1141
1142         glVertex3fv(dir);
1143 }
1144
1145 static void draw_dof_ellipse(float ax, float az)
1146 {
1147         static float staticSine[16] = {
1148                 0.0, 0.104528463268, 0.207911690818, 0.309016994375,
1149                 0.406736643076, 0.5, 0.587785252292, 0.669130606359,
1150                 0.743144825477, 0.809016994375, 0.866025403784,
1151                 0.913545457643, 0.951056516295, 0.978147600734,
1152                 0.994521895368, 1.0
1153         };
1154
1155         int i, j, n=16;
1156         float x, z, px, pz;
1157
1158         glEnable(GL_BLEND);
1159         glDepthMask(0);
1160
1161         glColor4ub(70, 70, 70, 50);
1162
1163         glBegin(GL_QUADS);
1164         pz= 0.0f;
1165         for(i=1; i<n; i++) {
1166                 z= staticSine[i];
1167
1168                 px= 0.0f;
1169                 for(j=1; j<n-i+1; j++) {
1170                         x = staticSine[j];
1171
1172                         if(j == n-i) {
1173                                 glEnd();
1174                                 glBegin(GL_TRIANGLES);
1175                                 bgl_sphere_project(ax*px, az*z);
1176                                 bgl_sphere_project(ax*px, az*pz);
1177                                 bgl_sphere_project(ax*x, az*pz);
1178                                 glEnd();
1179                                 glBegin(GL_QUADS);
1180                         }
1181                         else {
1182                                 bgl_sphere_project(ax*x, az*z);
1183                                 bgl_sphere_project(ax*x, az*pz);
1184                                 bgl_sphere_project(ax*px, az*pz);
1185                                 bgl_sphere_project(ax*px, az*z);
1186                         }
1187
1188                         px= x;
1189                 }
1190                 pz= z;
1191         }
1192         glEnd();
1193
1194         glDisable(GL_BLEND);
1195         glDepthMask(1);
1196
1197         glColor3ub(0, 0, 0);
1198
1199         glBegin(GL_LINE_STRIP);
1200         for(i=0; i<n; i++)
1201                 bgl_sphere_project(staticSine[n-i-1]*ax, staticSine[i]*az);
1202         glEnd();
1203 }
1204
1205 static void draw_pose_dofs(Object *ob)
1206 {
1207         bArmature *arm= ob->data;
1208         bPoseChannel *pchan;
1209         Bone *bone;
1210         
1211         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1212                 bone= pchan->bone;
1213                 if(bone && !(bone->flag & BONE_HIDDEN_P)) {
1214                         if(bone->flag & BONE_SELECTED) {
1215                                 if(bone->layer & arm->layer) {
1216                                         if(pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT)) {
1217                                                 if(pose_channel_in_IK_chain(ob, pchan)) {
1218                                                         float corner[4][3], posetrans[3], mat[4][4];
1219                                                         float phi=0.0f, theta=0.0f, scale;
1220                                                         int a, i;
1221
1222                                                         /* in parent-bone pose, but own restspace */
1223                                                         glPushMatrix();
1224
1225                                                         VECCOPY(posetrans, pchan->pose_mat[3]);
1226                                                         glTranslatef(posetrans[0], posetrans[1], posetrans[2]);
1227
1228                                                         if(pchan->parent) {
1229                                                                 Mat4CpyMat4(mat, pchan->parent->pose_mat);
1230                                                                 mat[3][0]= mat[3][1]= mat[3][2]= 0.0f;
1231                                                                 glMultMatrixf(mat);
1232                                                         }
1233
1234                                                         Mat4CpyMat3(mat, pchan->bone->bone_mat);
1235                                                         glMultMatrixf(mat);
1236
1237                                                         scale= bone->length*pchan->size[1];
1238                                                         glScalef(scale, scale, scale);
1239
1240                                                         if(pchan->ikflag & BONE_IK_XLIMIT) {
1241                                                                 if(pchan->ikflag & BONE_IK_ZLIMIT) {
1242                                                                         float amin[3], amax[3];
1243
1244                                                                         for(i=0; i<3; i++) {
1245                                                                                 amin[i]= sin(pchan->limitmin[i]*M_PI/360.0);
1246                                                                                 amax[i]= sin(pchan->limitmax[i]*M_PI/360.0);
1247                                                                         }
1248                                                                         
1249                                                                         glScalef(1.0, -1.0, 1.0);
1250                                                                         if (amin[0] != 0.0 && amin[2] != 0.0)
1251                                                                                 draw_dof_ellipse(amin[0], amin[2]);
1252                                                                         if (amin[0] != 0.0 && amax[2] != 0.0)
1253                                                                                 draw_dof_ellipse(amin[0], amax[2]);
1254                                                                         if (amax[0] != 0.0 && amin[2] != 0.0)
1255                                                                                 draw_dof_ellipse(amax[0], amin[2]);
1256                                                                         if (amax[0] != 0.0 && amax[2] != 0.0)
1257                                                                                 draw_dof_ellipse(amax[0], amax[2]);
1258                                                                         glScalef(1.0, -1.0, 1.0);
1259                                                                 }
1260                                                         }
1261                                                         
1262                                                         /* arcs */
1263                                                         if(pchan->ikflag & BONE_IK_ZLIMIT) {
1264                                                                 theta= 0.5*(pchan->limitmin[2]+pchan->limitmax[2]);
1265                                                                 glRotatef(theta, 0.0f, 0.0f, 1.0f);
1266
1267                                                                 glColor3ub(50, 50, 255);        // blue, Z axis limit
1268                                                                 glBegin(GL_LINE_STRIP);
1269                                                                 for(a=-16; a<=16; a++) {
1270                                                                         float fac= ((float)a)/16.0f;
1271                                                                         phi= fac*(M_PI/360.0f)*(pchan->limitmax[2]-pchan->limitmin[2]);
1272                                                                         
1273                                                                         if(a==-16) i= 0; else i= 1;
1274                                                                         corner[i][0]= sin(phi);
1275                                                                         corner[i][1]= cos(phi);
1276                                                                         corner[i][2]= 0.0f;
1277                                                                         glVertex3fv(corner[i]);
1278                                                                 }
1279                                                                 glEnd();
1280
1281                                                                 glRotatef(-theta, 0.0f, 0.0f, 1.0f);
1282                                                         }                                       
1283
1284                                                         if(pchan->ikflag & BONE_IK_XLIMIT) {
1285                                                                 theta=  0.5*( pchan->limitmin[0]+pchan->limitmax[0]);
1286                                                                 glRotatef(theta, 1.0f, 0.0f, 0.0f);
1287
1288                                                                 glColor3ub(255, 50, 50);        // Red, X axis limit
1289                                                                 glBegin(GL_LINE_STRIP);
1290                                                                 for(a=-16; a<=16; a++) {
1291                                                                         float fac= ((float)a)/16.0f;
1292                                                                         phi= 0.5f*M_PI + fac*(M_PI/360.0f)*(pchan->limitmax[0]-pchan->limitmin[0]);
1293
1294                                                                         if(a==-16) i= 2; else i= 3;
1295                                                                         corner[i][0]= 0.0f;
1296                                                                         corner[i][1]= sin(phi);
1297                                                                         corner[i][2]= cos(phi);
1298                                                                         glVertex3fv(corner[i]);
1299                                                                 }
1300                                                                 glEnd();
1301
1302                                                                 glRotatef(-theta, 1.0f, 0.0f, 0.0f);
1303                                                         }
1304
1305                                                         glPopMatrix(); // out of cone, out of bone
1306                                                 }
1307                                         }
1308                                 }
1309                         }
1310                 }
1311         }
1312 }
1313
1314 /* assumes object is Armature with pose */
1315 static void draw_pose_channels(Base *base, int dt)
1316 {
1317         Object *ob= base->object;
1318         bArmature *arm= ob->data;
1319         bPoseChannel *pchan;
1320         Bone *bone;
1321         GLfloat tmp;
1322         float smat[4][4], imat[4][4];
1323         int index= -1;
1324         int do_dashed= 1;
1325         short flag, constflag;
1326         
1327         /* hacky... prevent outline select from drawing dashed helplines */
1328         glGetFloatv(GL_LINE_WIDTH, &tmp);
1329         if(tmp > 1.1) do_dashed= 0;
1330         if (G.vd->flag & V3D_HIDE_HELPLINES) do_dashed= 0;
1331         
1332         /* precalc inverse matrix for drawing screen aligned */
1333         if(arm->drawtype==ARM_ENVELOPE) {
1334                 /* precalc inverse matrix for drawing screen aligned */
1335                 mygetmatrix(smat);
1336                 Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0]));
1337                 Mat4Invert(imat, smat);
1338                 
1339                 /* and draw blended distances */
1340                 if(arm->flag & ARM_POSEMODE) {
1341                         glEnable(GL_BLEND);
1342                         //glShadeModel(GL_SMOOTH);
1343                         
1344                         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
1345                         
1346                         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1347                                 bone= pchan->bone;
1348                                 if(bone && !(bone->flag & (BONE_HIDDEN_P|BONE_NO_DEFORM))) {
1349                                         if(bone->flag & (BONE_SELECTED))
1350                                                 if(bone->layer & arm->layer)
1351                                                         draw_sphere_bone_dist(smat, imat, bone->flag, pchan, NULL);
1352                                 }
1353                         }
1354                         
1355                         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
1356                         glDisable(GL_BLEND);
1357                         //glShadeModel(GL_FLAT);
1358                 }
1359         }
1360         
1361         /* little speedup, also make sure transparent only draws once */
1362         glCullFace(GL_BACK); 
1363         glEnable(GL_CULL_FACE);
1364         
1365         /* if solid we draw that first, with selection codes, but without names, axes etc */
1366         if(dt>OB_WIRE) {
1367                 if(arm->flag & ARM_POSEMODE) index= base->selcol;
1368                 
1369                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1370                         bone= pchan->bone;
1371                         if(bone && !(bone->flag & BONE_HIDDEN_P)) {
1372                                 if(bone->layer & arm->layer) {
1373                                         glPushMatrix();
1374                                         glMultMatrixf(pchan->pose_mat);
1375                                         
1376                                         /* catch exception for bone with hidden parent */
1377                                         flag= bone->flag;
1378                                         if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
1379                                                 flag &= ~BONE_CONNECTED;
1380                                         
1381                                         if(pchan->custom)
1382                                                 draw_custom_bone(pchan->custom, OB_SOLID, arm->flag, flag, index, bone->length);
1383                                         else if(arm->drawtype==ARM_LINE)
1384                                                 ;       /* nothing in solid */
1385                                         else if(arm->drawtype==ARM_ENVELOPE)
1386                                                 draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
1387                                         else if(arm->drawtype==ARM_B_BONE)
1388                                                 draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
1389                                         else {
1390                                                 draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
1391                                         }
1392                                         glPopMatrix();
1393                                 }
1394                         }
1395                         if (index!= -1) index+= 0x10000;        // pose bones count in higher 2 bytes only
1396                 }
1397                 /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet, stick bones are dawn in next loop */
1398                 if(arm->drawtype!=ARM_LINE) {
1399                         glLoadName (index & 0xFFFF);    // object tag, for bordersel optim
1400                         index= -1;
1401                 }
1402         }
1403         
1404         /* wire draw over solid only in posemode */
1405         if( dt<=OB_WIRE || (arm->flag & ARM_POSEMODE) || arm->drawtype==ARM_LINE) {
1406         
1407                 /* draw line check first. we do selection indices */
1408                 if (arm->drawtype==ARM_LINE) {
1409                         if (arm->flag & ARM_POSEMODE) index= base->selcol;
1410                 }
1411                 /* if solid && posemode, we draw again with polygonoffset */
1412                 else if (dt>OB_WIRE && (arm->flag & ARM_POSEMODE))
1413                         bglPolygonOffset(1.0);
1414                 else
1415                         /* and we use selection indices if not done yet */
1416                         if (arm->flag & ARM_POSEMODE) index= base->selcol;
1417                 
1418                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1419                         bone= pchan->bone;
1420                         if(bone && !(bone->flag & BONE_HIDDEN_P)) {
1421                                 if(bone->layer & arm->layer) {
1422                                         if (do_dashed && bone->parent) {
1423                                                 /*      Draw a line from our root to the parent's tip */
1424                                                 if(!(bone->flag & BONE_CONNECTED) ){
1425                                                         if (arm->flag & ARM_POSEMODE) {
1426                                                                 glLoadName (index & 0xFFFF);    // object tag, for bordersel optim
1427                                                                 BIF_ThemeColor(TH_WIRE);
1428                                                         }
1429                                                         setlinestyle(3);
1430                                                         glBegin(GL_LINES);
1431                                                         glVertex3fv(pchan->pose_head);
1432                                                         glVertex3fv(pchan->parent->pose_tail);
1433                                                         glEnd();
1434                                                         setlinestyle(0);
1435                                                 }
1436                                                 //      Draw a line to IK root bone
1437                                                 if(arm->flag & ARM_POSEMODE) {
1438                                                         if(pchan->constflag & PCHAN_HAS_IK) {
1439                                                                 if(bone->flag & BONE_SELECTED) {
1440                                                                         
1441                                                                         if(pchan->constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
1442                                                                         else glColor3ub(200, 200, 50);  // add theme!
1443
1444                                                                         glLoadName (index & 0xFFFF);
1445                                                                         pchan_draw_IK_root_lines(pchan);
1446                                                                 }
1447                                                         }
1448                                                 }
1449                                         }
1450                                         
1451                                         if(arm->drawtype!=ARM_ENVELOPE) {
1452                                                 glPushMatrix();
1453                                                 glMultMatrixf(pchan->pose_mat);
1454                                         }
1455                                         
1456                                         /* catch exception for bone with hidden parent */
1457                                         flag= bone->flag;
1458                                         if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
1459                                                 flag &= ~BONE_CONNECTED;
1460                                         
1461                                         /* extra draw service for pose mode */
1462                                         constflag= pchan->constflag;
1463                                         if(pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE))
1464                                                 constflag |= PCHAN_HAS_ACTION;
1465                                         if(pchan->flag & POSE_STRIDE)
1466                                                 constflag |= PCHAN_HAS_STRIDE;
1467
1468                                         if(pchan->custom) {
1469                                                 if(dt<OB_SOLID)
1470                                                         draw_custom_bone(pchan->custom, OB_WIRE, arm->flag, flag, index, bone->length);
1471                                         }
1472                                         else if(arm->drawtype==ARM_ENVELOPE) {
1473                                                 if(dt<OB_SOLID)
1474                                                         draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
1475                                         }
1476                                         else if(arm->drawtype==ARM_LINE)
1477                                                 draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
1478                                         else if(arm->drawtype==ARM_B_BONE)
1479                                                 draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
1480                                         else {
1481                                                 draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
1482                                         }
1483                                         
1484                                         if(arm->drawtype!=ARM_ENVELOPE)
1485                                                 glPopMatrix();
1486                                 }
1487                         }
1488                         if (index!= -1) index+= 0x10000;        // pose bones count in higher 2 bytes only
1489                 }
1490                 /* restore things */
1491                 if (arm->drawtype!=ARM_LINE && dt>OB_WIRE && (arm->flag & ARM_POSEMODE))
1492                         bglPolygonOffset(0.0);
1493                 
1494         }       
1495         
1496         /* restore */
1497         glDisable(GL_CULL_FACE);
1498         
1499         /* draw DoFs */
1500         if (arm->flag & ARM_POSEMODE)
1501                 draw_pose_dofs(ob);
1502
1503         /* finally names and axes */
1504         if(arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
1505                 // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
1506                 if((G.f & G_PICKSEL) == 0) {
1507                         float vec[3];
1508                         
1509                         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
1510                         
1511                         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1512                                 if((pchan->bone->flag & BONE_HIDDEN_P)==0) {
1513                                         if(pchan->bone->layer & arm->layer) {
1514                                                 if (arm->flag & (ARM_EDITMODE|ARM_POSEMODE)) {
1515                                                         bone= pchan->bone;
1516                                                         if(bone->flag & BONE_SELECTED) BIF_ThemeColor(TH_TEXT_HI);
1517                                                         else BIF_ThemeColor(TH_TEXT);
1518                                                 }
1519                                                 else if(dt > OB_WIRE) BIF_ThemeColor(TH_TEXT);
1520                                                 
1521                                                 if (arm->flag & ARM_DRAWNAMES){
1522                                                         VecMidf(vec, pchan->pose_head, pchan->pose_tail);
1523                                                         glRasterPos3fv(vec);
1524                                                         BMF_DrawString(G.font, " ");
1525                                                         BMF_DrawString(G.font, pchan->name);
1526                                                 }                               
1527                                                 /*      Draw additional axes */
1528                                                 if( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ){
1529                                                         glPushMatrix();
1530                                                         glMultMatrixf(pchan->pose_mat);
1531                                                         glTranslatef(0.0f, pchan->bone->length, 0.0f);
1532                                                         drawaxes(0.25f*pchan->bone->length, 0, OB_ARROWS);
1533                                                         glPopMatrix();
1534                                                 }
1535                                         }
1536                                 }
1537                         }
1538                         
1539                         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
1540                 }
1541         }
1542
1543 }
1544
1545 /* in editmode, we don't store the bone matrix... */
1546 static void set_matrix_editbone(EditBone *eBone)
1547 {
1548         float           delta[3],offset[3];
1549         float           mat[3][3], bmat[4][4];
1550         
1551         /*      Compose the parent transforms (i.e. their translations) */
1552         VECCOPY (offset, eBone->head);
1553         
1554         glTranslatef (offset[0],offset[1],offset[2]);
1555         
1556         VecSubf(delta, eBone->tail, eBone->head);       
1557         
1558         eBone->length = sqrt (delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]);
1559         
1560         vec_roll_to_mat3(delta, eBone->roll, mat);
1561         Mat4CpyMat3(bmat, mat);
1562                                 
1563         glMultMatrixf (bmat);
1564         
1565 }
1566
1567 static void draw_ebones(Object *ob, int dt)
1568 {
1569         EditBone *eBone;
1570         bArmature *arm= ob->data;
1571         float smat[4][4], imat[4][4];
1572         unsigned int index;
1573         int flag;
1574         
1575         /* envelope (deform distance) */
1576         if(arm->drawtype==ARM_ENVELOPE) {
1577                 /* precalc inverse matrix for drawing screen aligned */
1578                 mygetmatrix(smat);
1579                 Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0]));
1580                 Mat4Invert(imat, smat);
1581                 
1582                 /* and draw blended distances */
1583                 glEnable(GL_BLEND);
1584                 //glShadeModel(GL_SMOOTH);
1585                 
1586                 if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
1587
1588                 for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
1589                         if(eBone->layer & arm->layer)
1590                                 if(!(eBone->flag & (BONE_HIDDEN_A|BONE_NO_DEFORM)))
1591                                         if(eBone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL))
1592                                                 draw_sphere_bone_dist(smat, imat, eBone->flag, NULL, eBone);
1593                 }
1594                 
1595                 if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
1596                 glDisable(GL_BLEND);
1597                 //glShadeModel(GL_FLAT);
1598         }
1599         
1600         /* if solid we draw it first */
1601         if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) {
1602                 index= 0;
1603                 for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
1604                         if(eBone->layer & arm->layer) {
1605                                 if(!(eBone->flag & BONE_HIDDEN_A)) {
1606                                         glPushMatrix();
1607                                         set_matrix_editbone(eBone);
1608                                         
1609                                         /* catch exception for bone with hidden parent */
1610                                         flag= eBone->flag;
1611                                         if(eBone->parent && ((eBone->parent->flag & BONE_HIDDEN_A) || (eBone->parent->layer & arm->layer)==0) )
1612                                                 flag &= ~BONE_CONNECTED;
1613                                         
1614                                         if(arm->drawtype==ARM_ENVELOPE)
1615                                                 draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
1616                                         else if(arm->drawtype==ARM_B_BONE)
1617                                                 draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
1618                                         else {
1619                                                 draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
1620                                         }
1621                                         
1622                                         glPopMatrix();
1623                                 }
1624                         }
1625                 }
1626         }
1627         
1628         /* if wire over solid, set offset */
1629         index= -1;
1630         glLoadName(-1);
1631         if(arm->drawtype==ARM_LINE) {
1632                 if(G.f & G_PICKSEL)
1633                         index= 0;
1634         }
1635         else if (dt>OB_WIRE) 
1636                 bglPolygonOffset(1.0);
1637         else if(arm->flag & ARM_EDITMODE) 
1638                 index= 0;       // do selection codes
1639         
1640         for (eBone=G.edbo.first; eBone; eBone=eBone->next){
1641                 if(eBone->layer & arm->layer) {
1642                         if(!(eBone->flag & BONE_HIDDEN_A)) {
1643                                 
1644                                 /* catch exception for bone with hidden parent */
1645                                 flag= eBone->flag;
1646                                 if(eBone->parent && ((eBone->parent->flag & BONE_HIDDEN_A) || (eBone->parent->layer & arm->layer)==0) )
1647                                         flag &= ~BONE_CONNECTED;
1648                                 
1649                                 if(arm->drawtype==ARM_ENVELOPE) {
1650                                         if(dt<OB_SOLID)
1651                                                 draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
1652                                 }
1653                                 else {
1654                                         glPushMatrix();
1655                                         set_matrix_editbone(eBone);
1656                                         
1657                                         if(arm->drawtype==ARM_LINE) 
1658                                                 draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
1659                                         else if(arm->drawtype==ARM_B_BONE)
1660                                                 draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
1661                                         else
1662                                                 draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
1663
1664                                         glPopMatrix();
1665                                 }
1666                         
1667                                 /* offset to parent */
1668                                 if (eBone->parent) {
1669                                         BIF_ThemeColor(TH_WIRE);
1670                                         glLoadName (-1);                // -1 here is OK!
1671                                         setlinestyle(3);
1672                                         
1673                                         glBegin(GL_LINES);
1674                                         glVertex3fv(eBone->parent->tail);
1675                                         glVertex3fv(eBone->head);
1676                                         glEnd();
1677                                         
1678                                         setlinestyle(0);
1679                                 }
1680                         }
1681                 }
1682                 if(index!=-1) index++;
1683         }
1684         
1685         /* restore */
1686         if(arm->drawtype==ARM_LINE);
1687         else if (dt>OB_WIRE) bglPolygonOffset(0.0);
1688         
1689         /* finally names and axes */
1690         if(arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
1691                 // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
1692                 if((G.f & G_PICKSEL) == 0) {
1693                         float vec[3];
1694                         
1695                         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
1696                         
1697                         for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
1698                                 if(eBone->layer & arm->layer) {
1699                                         if(!(eBone->flag & BONE_HIDDEN_A)) {
1700                                                 
1701                                                 if(eBone->flag & BONE_SELECTED) BIF_ThemeColor(TH_TEXT_HI);
1702                                                 else BIF_ThemeColor(TH_TEXT);
1703                                                 
1704                                                 /*      Draw name */
1705                                                 if(arm->flag & ARM_DRAWNAMES){
1706                                                         VecMidf(vec, eBone->head, eBone->tail);
1707                                                         glRasterPos3fv(vec);
1708                                                         BMF_DrawString(G.font, " ");
1709                                                         BMF_DrawString(G.font, eBone->name);
1710                                                 }                                       
1711                                                 /*      Draw additional axes */
1712                                                 if(arm->flag & ARM_DRAWAXES){
1713                                                         glPushMatrix();
1714                                                         set_matrix_editbone(eBone);
1715                                                         glTranslatef(0.0f, eBone->length, 0.0f);
1716                                                         drawaxes(eBone->length*0.25f, 0, OB_ARROWS);
1717                                                         glPopMatrix();
1718                                                 }
1719                                                 
1720                                         }
1721                                 }
1722                         }
1723                         
1724                         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
1725                 }
1726         }
1727 }
1728
1729 /* in view space */
1730 static void draw_pose_paths(Object *ob)
1731 {
1732         bArmature *arm= ob->data;
1733         bPoseChannel *pchan;
1734         float *fp;
1735         int a;
1736         
1737         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
1738         
1739         glPushMatrix();
1740         glLoadMatrixf(G.vd->viewmat);
1741         
1742         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1743                 if(pchan->bone->layer & arm->layer) {
1744                         if(pchan->path) {
1745                                 
1746                                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
1747                                 glBegin(GL_LINE_STRIP);
1748                                 for(a=0, fp= pchan->path; a<pchan->pathlen; a++, fp+=3)
1749                                         glVertex3fv(fp);
1750                                 glEnd();
1751                                 
1752                                 glPointSize(1.0);
1753                                 BIF_ThemeColor(TH_WIRE);
1754                                 glBegin(GL_POINTS);
1755                                 for(a=0, fp= pchan->path; a<pchan->pathlen; a++, fp+=3)
1756                                         glVertex3fv(fp);
1757                                 glEnd();
1758                                 
1759                                 BIF_ThemeColor(TH_TEXT_HI);
1760                                 glBegin(GL_POINTS);
1761                                 for(a=0, fp= pchan->path; a<pchan->pathlen; a+=10, fp+=30)
1762                                         glVertex3fv(fp);
1763                                 glEnd();
1764                         }
1765                 }
1766         }
1767         
1768         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
1769         glPopMatrix();
1770 }
1771
1772 /* object is supposed to be armature in posemode */
1773 static void draw_ghost_poses(Base *base)
1774 {
1775         Object *ob= base->object;
1776         bArmature *arm= ob->data;
1777         bPose *posen, *poseo;
1778         bActionStrip *strip;
1779         float cur, start, end, stepsize, range, colfac, actframe, ctime;
1780         int cfrao, maptime, flago, ipoflago;
1781         
1782         /* pre conditions, get an action with sufficient frames */
1783         if(ob->action==NULL)
1784                 return;
1785
1786         calc_action_range(ob->action, &start, &end, 0);
1787         if(start==end)
1788                 return;
1789
1790         stepsize= (float)(arm->ghostsize);
1791         range= (float)(arm->ghostep)*stepsize + 0.5f;   /* plus half to make the for loop end correct */
1792         
1793         /* we only map time for armature when an active strip exists */
1794         for (strip=ob->nlastrips.first; strip; strip=strip->next)
1795                 if(strip->flag & ACTSTRIP_ACTIVE)
1796                         break;
1797         
1798         maptime= (strip!=NULL);
1799         
1800         /* store values */
1801         ob->flag &= ~OB_POSEMODE;
1802         cfrao= CFRA;
1803         if(maptime) actframe= get_action_frame(ob, (float)CFRA);
1804         else actframe= CFRA;
1805         flago= arm->flag;
1806         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
1807         ipoflago= ob->ipoflag; 
1808         ob->ipoflag |= OB_DISABLE_PATH;
1809         
1810         /* copy the pose */
1811         poseo= ob->pose;
1812         copy_pose(&posen, ob->pose, 1);
1813         ob->pose= posen;
1814         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
1815         
1816         glEnable(GL_BLEND);
1817         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
1818         
1819         /* draw from darkest blend to lowest */
1820         for(cur= stepsize; cur<range; cur+=stepsize) {
1821                 
1822                 ctime= cur - fmod((float)cfrao, stepsize);      /* ensures consistant stepping */
1823                 colfac= ctime/range;
1824                 BIF_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0f*sqrt(colfac)));
1825                 
1826                 /* only within action range */
1827                 if(actframe+ctime >= start && actframe+ctime <= end) {
1828                         
1829                         if(maptime) CFRA= (int)get_action_frame_inv(ob, actframe+ctime);
1830                         else CFRA= (int)floor(actframe+ctime);
1831                         
1832                         if(CFRA!=cfrao) {
1833                                 do_all_pose_actions(ob);
1834                                 where_is_pose(ob);
1835                                 draw_pose_channels(base, OB_WIRE);
1836                         }
1837                 }
1838                 
1839                 ctime= cur + fmod((float)cfrao, stepsize) - stepsize+1.0f;      /* ensures consistant stepping */
1840                 colfac= ctime/range;
1841                 BIF_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0f*sqrt(colfac)));
1842                 
1843                 /* only within action range */
1844                 if(actframe-ctime >= start && actframe-ctime <= end) {
1845                         
1846                         if(maptime) CFRA= (int)get_action_frame_inv(ob, actframe-ctime);
1847                         else CFRA= (int)floor(actframe-ctime);
1848
1849                         if(CFRA!=cfrao) {
1850                                 do_all_pose_actions(ob);
1851                                 where_is_pose(ob);
1852                                 draw_pose_channels(base, OB_WIRE);
1853                         }
1854                 }
1855         }
1856         glDisable(GL_BLEND);
1857         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
1858
1859         free_pose_channels(posen);
1860         MEM_freeN(posen);
1861         
1862         /* restore */
1863         CFRA= cfrao;
1864         ob->pose= poseo;
1865         arm->flag= flago;
1866         armature_rebuild_pose(ob, ob->data);
1867         ob->flag |= OB_POSEMODE;
1868         ob->ipoflag= ipoflago; 
1869
1870 }
1871
1872 /* called from drawobject.c, return 1 if nothing was drawn */
1873 int draw_armature(Base *base, int dt)
1874 {
1875         Object *ob= base->object;
1876         bArmature *arm= ob->data;
1877         int retval= 0;
1878         
1879         if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) {
1880                 /* we use color for solid lighting */
1881                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1882                 glEnable(GL_COLOR_MATERIAL);
1883                 glColor3ub(0,0,0);      // clear spec
1884                 glDisable(GL_COLOR_MATERIAL);
1885                 
1886                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1887                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting...
1888         }
1889         
1890         /* arm->flag is being used to detect mode... */
1891         /* editmode? */
1892         if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
1893                 if(ob==G.obedit) arm->flag |= ARM_EDITMODE;
1894                 draw_ebones(ob, dt);
1895                 arm->flag &= ~ARM_EDITMODE;
1896         }
1897         else{
1898                 /*      Draw Pose */
1899                 if(ob->pose && ob->pose->chanbase.first) {
1900                         /* drawing posemode selection indices or colors only in these cases */
1901                         if(G.f & G_PICKSEL) {
1902                                 if(ob->flag & OB_POSEMODE) arm->flag |= ARM_POSEMODE;
1903                         }
1904                         else if(ob->flag & OB_POSEMODE) {
1905         
1906                                 if(arm->ghostep) {
1907                                         draw_ghost_poses(base);
1908                                 }
1909                                 
1910                                 if(ob==OBACT) 
1911                                         arm->flag |= ARM_POSEMODE;
1912                                 else if(G.f & G_WEIGHTPAINT)
1913                                         arm->flag |= ARM_POSEMODE;
1914                                 
1915                                 draw_pose_paths(ob);
1916                         }       
1917                         
1918                         draw_pose_channels(base, dt);
1919                         arm->flag &= ~ARM_POSEMODE; 
1920                         
1921                         if(ob->flag & OB_POSEMODE)
1922                                 BIF_ThemeColor(TH_WIRE);        /* restore, for extra draw stuff */
1923                 }
1924                 else retval= 1;
1925         }
1926         /* restore */
1927         glFrontFace(GL_CCW);
1928
1929         return retval;
1930 }
1931
1932 /* *************** END Armature drawing ******************* */
1933