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