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