Blender V2.61 - r43446

drawarmature.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <math.h>
00036 
00037 
00038 #include "DNA_anim_types.h"
00039 #include "DNA_armature_types.h"
00040 #include "DNA_constraint_types.h"
00041 #include "DNA_scene_types.h"
00042 #include "DNA_screen_types.h"
00043 #include "DNA_view3d_types.h"
00044 #include "DNA_object_types.h"
00045 
00046 #include "BLI_blenlib.h"
00047 #include "BLI_math.h"
00048 #include "BLI_dlrbTree.h"
00049 #include "BLI_utildefines.h"
00050 
00051 #include "BKE_animsys.h"
00052 #include "BKE_action.h"
00053 #include "BKE_armature.h"
00054 #include "BKE_global.h"
00055 #include "BKE_modifier.h"
00056 #include "BKE_nla.h"
00057 
00058 
00059 #include "BIF_gl.h"
00060 #include "BIF_glutil.h"
00061 
00062 #include "ED_armature.h"
00063 #include "ED_keyframes_draw.h"
00064 
00065 #include "BLF_api.h"
00066 
00067 #include "UI_resources.h"
00068 
00069 #include "view3d_intern.h"
00070 
00071 
00072 /* *************** Armature Drawing - Coloring API ***************************** */
00073 
00074 /* global here is reset before drawing each bone */
00075 static ThemeWireColor *bcolor= NULL;
00076 
00077 /* values of colCode for set_pchan_glcolor */
00078 enum {
00079     PCHAN_COLOR_NORMAL  = 0,        /* normal drawing */
00080     PCHAN_COLOR_SOLID,              /* specific case where "solid" color is needed */
00081     PCHAN_COLOR_CONSTS,             /* "constraint" colors (which may/may-not be suppressed) */
00082     
00083     PCHAN_COLOR_SPHEREBONE_BASE,    /* for the 'stick' of sphere (envelope) bones */
00084     PCHAN_COLOR_SPHEREBONE_END,     /* for the ends of sphere (envelope) bones */
00085     PCHAN_COLOR_LINEBONE            /* for the middle of line-bones */
00086 };
00087 
00088 /* This function sets the color-set for coloring a certain bone */
00089 static void set_pchan_colorset (Object *ob, bPoseChannel *pchan)
00090 {
00091     bPose *pose= (ob) ? ob->pose : NULL;
00092     bArmature *arm= (ob) ? ob->data : NULL;
00093     bActionGroup *grp= NULL;
00094     short color_index= 0;
00095     
00096     /* sanity check */
00097     if (ELEM4(NULL, ob, arm, pose, pchan)) {
00098         bcolor= NULL;
00099         return;
00100     }
00101     
00102     /* only try to set custom color if enabled for armature */
00103     if (arm->flag & ARM_COL_CUSTOM) {   
00104         /* currently, a bone can only use a custom color set if it's group (if it has one),
00105          * has been set to use one
00106          */
00107         if (pchan->agrp_index) {
00108             grp= (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
00109             if (grp)
00110                 color_index= grp->customCol;
00111         }
00112     }
00113     
00114     /* bcolor is a pointer to the color set to use. If NULL, then the default
00115      * color set (based on the theme colors for 3d-view) is used. 
00116      */
00117     if (color_index > 0) {
00118         bTheme *btheme= UI_GetTheme();
00119         bcolor= &btheme->tarm[(color_index - 1)];
00120     }
00121     else if (color_index == -1) {
00122         /* use the group's own custom color set */
00123         bcolor= (grp)? &grp->cs : NULL;
00124     }
00125     else 
00126         bcolor= NULL;
00127 }
00128 
00129 /* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */
00130 static void cp_shade_color3ub (unsigned char cp[3], const int offset)
00131 {
00132     int r, g, b;
00133     
00134     r= offset + (int) cp[0];
00135     CLAMP(r, 0, 255);
00136     g= offset + (int) cp[1];
00137     CLAMP(g, 0, 255);
00138     b= offset + (int) cp[2];
00139     CLAMP(b, 0, 255);
00140     
00141     cp[0]= r;
00142     cp[1]= g;
00143     cp[2]= b;
00144 }
00145 
00146 /* This function sets the gl-color for coloring a certain bone (based on bcolor) */
00147 static short set_pchan_glColor (short colCode, int boneflag, short constflag)
00148 {
00149     switch (colCode) {
00150     case PCHAN_COLOR_NORMAL:
00151     {
00152         if (bcolor) {
00153             unsigned char cp[3];
00154             
00155             if (boneflag & BONE_DRAW_ACTIVE) {
00156                 copy_v3_v3_char((char *)cp, bcolor->active);
00157                 if(!(boneflag & BONE_SELECTED)) {
00158                     cp_shade_color3ub(cp, -80);
00159                 }
00160             }
00161             else if (boneflag & BONE_SELECTED) {
00162                 copy_v3_v3_char((char *)cp, bcolor->select);
00163             }
00164             else {
00165                 /* a bit darker than solid */
00166                 copy_v3_v3_char((char *)cp, bcolor->solid);
00167                 cp_shade_color3ub(cp, -50);
00168             }
00169             
00170             glColor3ubv(cp);
00171         }
00172         else {
00173             if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, 40);
00174             else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */
00175             else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
00176             else UI_ThemeColor(TH_WIRE);
00177         }
00178         
00179         return 1;
00180     }
00181         break;
00182     
00183     case PCHAN_COLOR_SOLID:
00184     {
00185         if (bcolor) {
00186             glColor3ubv((unsigned char *)bcolor->solid);
00187         }
00188         else 
00189             UI_ThemeColor(TH_BONE_SOLID);
00190             
00191         return 1;
00192     }
00193         break;
00194         
00195     case PCHAN_COLOR_CONSTS:
00196     {
00197         if ( (bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS) ) {
00198             if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80);
00199             else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
00200             else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80);
00201             else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
00202             
00203             return 1;
00204         }
00205         else 
00206             return 0;
00207     }
00208         break;
00209         
00210     case PCHAN_COLOR_SPHEREBONE_BASE:
00211     {
00212         if (bcolor) {
00213             unsigned char cp[3];
00214             
00215             if (boneflag & BONE_DRAW_ACTIVE) {
00216                 copy_v3_v3_char((char *)cp, bcolor->active);
00217             }
00218             else if (boneflag & BONE_SELECTED) {
00219                 copy_v3_v3_char((char *)cp, bcolor->select);
00220             }
00221             else {
00222                 copy_v3_v3_char((char *)cp, bcolor->solid);
00223             }
00224             
00225             glColor3ubv(cp);
00226         }
00227         else {
00228             if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40);
00229             else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
00230             else UI_ThemeColor(TH_BONE_SOLID);
00231         }
00232         
00233         return 1;
00234     }
00235         break;
00236     case PCHAN_COLOR_SPHEREBONE_END:
00237     {
00238         if (bcolor) {
00239             unsigned char cp[3];
00240             
00241             if (boneflag & BONE_DRAW_ACTIVE) {
00242                 copy_v3_v3_char((char *)cp, bcolor->active);
00243                 cp_shade_color3ub(cp, 10);
00244             }
00245             else if (boneflag & BONE_SELECTED) {
00246                 copy_v3_v3_char((char *)cp, bcolor->select);
00247                 cp_shade_color3ub(cp, -30);
00248             }
00249             else {
00250                 copy_v3_v3_char((char *)cp, bcolor->solid);
00251                 cp_shade_color3ub(cp, -30);
00252             }
00253             
00254             glColor3ubv(cp);
00255         }
00256         else {
00257             if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10);
00258             else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30);
00259             else UI_ThemeColorShade(TH_BONE_SOLID, -30);
00260         }
00261     }
00262         break;
00263         
00264     case PCHAN_COLOR_LINEBONE:
00265     {
00266         /* inner part in background color or constraint */
00267         if ( (constflag) && ((bcolor==NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) ) {
00268             if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0);
00269             else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0);
00270             else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0);
00271             else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120);
00272             else if (constflag) UI_ThemeColor(TH_BONE_POSE);    /* PCHAN_HAS_ACTION */ 
00273         }
00274         else {
00275             if (bcolor) {
00276                 char *cp= bcolor->solid;
00277                 glColor4ub(cp[0], cp[1], cp[2], 204);   
00278             }
00279             else
00280                 UI_ThemeColorShade(TH_BACK, -30);
00281         }
00282         
00283         return 1;
00284     }
00285         break;
00286     }
00287     
00288     return 0;
00289 }
00290 
00291 static void set_ebone_glColor(const unsigned int boneflag)
00292 {
00293     if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
00294     else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, 0.15f); /* unselected active */
00295     else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20);
00296     else UI_ThemeColor(TH_WIRE);
00297 }
00298 
00299 /* *************** Armature drawing, helper calls for parts ******************* */
00300 
00301 /* half the cube, in Y */
00302 static float cube[8][3] = {
00303 {-1.0,  0.0, -1.0},
00304 {-1.0,  0.0,  1.0},
00305 {-1.0,  1.0,  1.0},
00306 {-1.0,  1.0, -1.0},
00307 { 1.0,  0.0, -1.0},
00308 { 1.0,  0.0,  1.0},
00309 { 1.0,  1.0,  1.0},
00310 { 1.0,  1.0, -1.0},
00311 };
00312 
00313 static void drawsolidcube_size(float xsize, float ysize, float zsize)
00314 {
00315     static GLuint displist=0;
00316     float n[3]= {0.0f};
00317     
00318     glScalef(xsize, ysize, zsize);
00319 
00320     if(displist==0) {
00321         displist= glGenLists(1);
00322         glNewList(displist, GL_COMPILE);
00323 
00324         glBegin(GL_QUADS);
00325         n[0]= -1.0;
00326         glNormal3fv(n); 
00327         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
00328         n[0]=0;
00329         n[1]= -1.0;
00330         glNormal3fv(n); 
00331         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
00332         n[1]=0;
00333         n[0]= 1.0;
00334         glNormal3fv(n); 
00335         glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
00336         n[0]=0;
00337         n[1]= 1.0;
00338         glNormal3fv(n); 
00339         glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
00340         n[1]=0;
00341         n[2]= 1.0;
00342         glNormal3fv(n); 
00343         glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
00344         n[2]= -1.0;
00345         glNormal3fv(n); 
00346         glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
00347         glEnd();
00348 
00349         glEndList();
00350     }
00351 
00352     glCallList(displist);
00353 }
00354 
00355 static void drawcube_size(float xsize, float ysize, float zsize)
00356 {
00357     static GLuint displist=0;
00358     
00359     if(displist == 0) {
00360         displist= glGenLists(1);
00361         glNewList(displist, GL_COMPILE);
00362         
00363         glBegin(GL_LINE_STRIP);
00364         glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
00365         glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
00366         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
00367         glEnd();
00368         
00369         glBegin(GL_LINES);
00370         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
00371         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
00372         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
00373         glEnd();
00374         
00375         glEndList();
00376     }
00377 
00378     glScalef(xsize, ysize, zsize);
00379     glCallList(displist);
00380     
00381 }
00382 
00383 
00384 static void draw_bonevert(void)
00385 {
00386     static GLuint displist=0;
00387     
00388     if (displist == 0) {
00389         GLUquadricObj   *qobj;
00390         
00391         displist= glGenLists(1);
00392         glNewList(displist, GL_COMPILE);
00393             
00394         glPushMatrix();
00395         
00396         qobj    = gluNewQuadric(); 
00397         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
00398         gluDisk(qobj, 0.0,  0.05, 16, 1);
00399         
00400         glRotatef(90, 0, 1, 0);
00401         gluDisk(qobj, 0.0,  0.05, 16, 1);
00402         
00403         glRotatef(90, 1, 0, 0);
00404         gluDisk(qobj, 0.0,  0.05, 16, 1);
00405         
00406         gluDeleteQuadric(qobj);  
00407         
00408         glPopMatrix();
00409         glEndList();
00410     }
00411 
00412     glCallList(displist);
00413 }
00414 
00415 static void draw_bonevert_solid(void)
00416 {
00417     static GLuint displist=0;
00418     
00419     if (displist == 0) {
00420         GLUquadricObj   *qobj;
00421         
00422         displist= glGenLists(1);
00423         glNewList(displist, GL_COMPILE);
00424         
00425         qobj    = gluNewQuadric();
00426         gluQuadricDrawStyle(qobj, GLU_FILL); 
00427         glShadeModel(GL_SMOOTH);
00428         gluSphere(qobj, 0.05, 8, 5);
00429         glShadeModel(GL_FLAT);
00430         gluDeleteQuadric(qobj);  
00431         
00432         glEndList();
00433     }
00434 
00435     glCallList(displist);
00436 }
00437 
00438 static float bone_octahedral_verts[6][3]= {
00439     { 0.0f, 0.0f,  0.0f},
00440     { 0.1f, 0.1f,  0.1f},
00441     { 0.1f, 0.1f, -0.1f},
00442     {-0.1f, 0.1f, -0.1f},
00443     {-0.1f, 0.1f,  0.1f},
00444     { 0.0f, 1.0f,  0.0f}
00445 };
00446 
00447 static unsigned int bone_octahedral_wire_sides[8]= {0, 1, 5, 3, 0, 4, 5, 2};
00448 static unsigned int bone_octahedral_wire_square[8]= {1, 2, 3, 4, 1};
00449 
00450 static unsigned int bone_octahedral_solid_tris[8][3]= {
00451     {2, 1, 0}, /* bottom */
00452     {3, 2, 0},
00453     {4, 3, 0},
00454     {1, 4, 0},
00455 
00456     {5, 1, 2}, /* top */
00457     {5, 2, 3},
00458     {5, 3, 4},
00459     {5, 4, 1}
00460 };
00461 
00462 /* aligned with bone_octahedral_solid_tris */
00463 static float bone_octahedral_solid_normals[8][3]= {
00464     { 0.70710683f, -0.70710683f,  0.00000000f},
00465     {-0.00000000f, -0.70710683f, -0.70710683f},
00466     {-0.70710683f, -0.70710683f,  0.00000000f},
00467     { 0.00000000f, -0.70710683f,  0.70710683f},
00468     { 0.99388373f,  0.11043154f, -0.00000000f},
00469     { 0.00000000f,  0.11043154f, -0.99388373f},
00470     {-0.99388373f,  0.11043154f,  0.00000000f},
00471     { 0.00000000f,  0.11043154f,  0.99388373f}
00472 };
00473 
00474 static void draw_bone_octahedral(void)
00475 {
00476     static GLuint displist=0;
00477     
00478     if (displist == 0) {
00479         displist= glGenLists(1);
00480         glNewList(displist, GL_COMPILE);
00481 
00482         /*  Section 1, sides */
00483         glEnableClientState(GL_VERTEX_ARRAY);
00484         glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts);
00485         glDrawElements(GL_LINE_LOOP,
00486                        sizeof(bone_octahedral_wire_sides)/sizeof(*bone_octahedral_wire_sides),
00487                        GL_UNSIGNED_INT,
00488                        bone_octahedral_wire_sides);
00489 
00490         /*  Section 1, square */
00491         glDrawElements(GL_LINE_LOOP,
00492                        sizeof(bone_octahedral_wire_square)/sizeof(*bone_octahedral_wire_square),
00493                        GL_UNSIGNED_INT,
00494                        bone_octahedral_wire_square);
00495         glDisableClientState(GL_VERTEX_ARRAY);
00496         
00497         glEndList();
00498     }
00499 
00500     glCallList(displist);
00501 }   
00502 
00503 static void draw_bone_solid_octahedral(void)
00504 {
00505     static GLuint displist=0;
00506 
00507     if (displist == 0) {
00508         int i;
00509 
00510         displist= glGenLists(1);
00511         glNewList(displist, GL_COMPILE);
00512 
00513 #if 1
00514         glBegin(GL_TRIANGLES);
00515         for(i= 0; i < 8; i++) {
00516             glNormal3fv(bone_octahedral_solid_normals[i]);
00517             glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
00518             glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
00519             glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
00520         }
00521 
00522         glEnd();
00523 
00524 #else   /* not working because each vert needs a different normal */
00525         glEnableClientState(GL_NORMAL_ARRAY);
00526         glEnableClientState(GL_VERTEX_ARRAY);
00527         glNormalPointer(GL_FLOAT, 0, bone_octahedral_solid_normals);
00528         glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts);
00529         glDrawElements(GL_TRIANGLES, sizeof(bone_octahedral_solid_tris)/sizeof(unsigned int), GL_UNSIGNED_INT, bone_octahedral_solid_tris);
00530         glDisableClientState(GL_NORMAL_ARRAY);
00531         glDisableClientState(GL_VERTEX_ARRAY);
00532 #endif
00533 
00534         glEndList();
00535     }
00536 
00537     glCallList(displist);
00538 }   
00539 
00540 /* *************** Armature drawing, bones ******************* */
00541 
00542 
00543 static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
00544 {
00545     /*  Draw root point if we are not connected */
00546     if ((boneflag & BONE_CONNECTED)==0) {
00547         if (id != -1)
00548             glLoadName(id | BONESEL_ROOT);
00549         
00550         if(dt <= OB_WIRE) {
00551             if (armflag & ARM_EDITMODE) {
00552                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00553                 else UI_ThemeColor(TH_VERTEX);
00554             }
00555         }
00556         else {
00557             if (armflag & ARM_POSEMODE) 
00558                 set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
00559             else
00560                 UI_ThemeColor(TH_BONE_SOLID);
00561         }
00562         
00563         if (dt > OB_WIRE) 
00564             draw_bonevert_solid();
00565         else 
00566             draw_bonevert();
00567     }
00568     
00569     /*  Draw tip point */
00570     if (id != -1)
00571         glLoadName(id | BONESEL_TIP);
00572     
00573     if (dt <= OB_WIRE) {
00574         if (armflag & ARM_EDITMODE) {
00575             if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00576             else UI_ThemeColor(TH_VERTEX);
00577         }
00578     }
00579     else {
00580         if (armflag & ARM_POSEMODE) 
00581             set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
00582         else
00583             UI_ThemeColor(TH_BONE_SOLID);
00584     }
00585     
00586     glTranslatef(0.0f, 1.0f, 0.0f);
00587     if (dt > OB_WIRE) 
00588         draw_bonevert_solid();
00589     else 
00590         draw_bonevert();
00591     glTranslatef(0.0f, -1.0f, 0.0f);
00592     
00593 }
00594 
00595 /* 16 values of sin function (still same result!) */
00596 static float si[16] = {
00597     0.00000000f,
00598     0.20129852f, 0.39435585f,
00599     0.57126821f, 0.72479278f,
00600     0.84864425f, 0.93775213f,
00601     0.98846832f, 0.99871650f,
00602     0.96807711f, 0.89780453f,
00603     0.79077573f, 0.65137248f,
00604     0.48530196f, 0.29936312f,
00605     0.10116832f
00606 };
00607 /* 16 values of cos function (still same result!) */
00608 static float co[16] ={
00609     1.00000000f,
00610     0.97952994f, 0.91895781f,
00611     0.82076344f, 0.68896691f,
00612     0.52896401f, 0.34730525f,
00613     0.15142777f, -0.05064916f,
00614     -0.25065253f, -0.44039415f,
00615     -0.61210598f, -0.75875812f,
00616     -0.87434661f, -0.95413925f,
00617     -0.99486932f
00618 };
00619 
00620 
00621 
00622 /* smat, imat = mat & imat to draw screenaligned */
00623 static void draw_sphere_bone_dist(float smat[][4], float imat[][4], bPoseChannel *pchan, EditBone *ebone)
00624 {
00625     float head, tail, dist /*, length*/;
00626     float *headvec, *tailvec, dirvec[3];
00627     
00628     /* figure out the sizes of spheres */
00629     if (ebone) {
00630         /* this routine doesn't call get_matrix_editbone() that calculates it */
00631         ebone->length = len_v3v3(ebone->head, ebone->tail);
00632 
00633         /*length= ebone->length;*/ /*UNUSED*/
00634         tail= ebone->rad_tail;
00635         dist= ebone->dist;
00636         if (ebone->parent && (ebone->flag & BONE_CONNECTED))
00637             head= ebone->parent->rad_tail;
00638         else
00639             head= ebone->rad_head;
00640         headvec= ebone->head;
00641         tailvec= ebone->tail;
00642     }
00643     else {
00644         /*length= pchan->bone->length;*/ /*UNUSED*/
00645         tail= pchan->bone->rad_tail;
00646         dist= pchan->bone->dist;
00647         if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
00648             head= pchan->parent->bone->rad_tail;
00649         else
00650             head= pchan->bone->rad_head;
00651         headvec= pchan->pose_head;
00652         tailvec= pchan->pose_tail;
00653     }
00654     
00655     /* ***** draw it ***** */
00656     
00657     /* move vector to viewspace */
00658     sub_v3_v3v3(dirvec, tailvec, headvec);
00659     mul_mat3_m4_v3(smat, dirvec);
00660     /* clear zcomp */
00661     dirvec[2]= 0.0f;
00662 
00663     if(head != tail) {
00664     /* correcyion when viewing along the bones axis
00665      * it pops in and out but better then artifacts, [#23841] */
00666         float view_dist= len_v2(dirvec);
00667 
00668         if(head - view_dist > tail) {
00669             tailvec= headvec;
00670             tail = head;
00671             zero_v3(dirvec);
00672             dirvec[0]= 0.00001; // XXX. weak but ok
00673         }
00674         else if(tail - view_dist > head) {
00675             headvec= tailvec;
00676             head = tail;
00677             zero_v3(dirvec);
00678             dirvec[0]= 0.00001; // XXX. weak but ok
00679         }
00680     }
00681 
00682     /* move vector back */
00683     mul_mat3_m4_v3(imat, dirvec);
00684     
00685     if (0.0f != normalize_v3(dirvec)) {
00686         float norvec[3], vec1[3], vec2[3], vec[3];
00687         int a;
00688         
00689         //mul_v3_fl(dirvec, head);
00690         cross_v3_v3v3(norvec, dirvec, imat[2]);
00691         
00692         glBegin(GL_QUAD_STRIP);
00693         
00694         for (a=0; a<16; a++) {
00695             vec[0]= - *(si+a) * dirvec[0] + *(co+a) * norvec[0];
00696             vec[1]= - *(si+a) * dirvec[1] + *(co+a) * norvec[1];
00697             vec[2]= - *(si+a) * dirvec[2] + *(co+a) * norvec[2];
00698 
00699             madd_v3_v3v3fl(vec1, headvec, vec, head);
00700             madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
00701             
00702             glColor4ub(255, 255, 255, 50);
00703             glVertex3fv(vec1);
00704             //glColor4ub(255, 255, 255, 0);
00705             glVertex3fv(vec2);
00706         }
00707         
00708         for (a=15; a>=0; a--) {
00709             vec[0]= *(si+a) * dirvec[0] + *(co+a) * norvec[0];
00710             vec[1]= *(si+a) * dirvec[1] + *(co+a) * norvec[1];
00711             vec[2]= *(si+a) * dirvec[2] + *(co+a) * norvec[2];
00712 
00713             madd_v3_v3v3fl(vec1, tailvec, vec, tail);
00714             madd_v3_v3v3fl(vec2, tailvec, vec, tail + dist);
00715             
00716             //glColor4ub(255, 255, 255, 50);
00717             glVertex3fv(vec1);
00718             //glColor4ub(255, 255, 255, 0);
00719             glVertex3fv(vec2);
00720         }
00721         /* make it cyclic... */
00722         
00723         vec[0]= - *(si) * dirvec[0] + *(co) * norvec[0];
00724         vec[1]= - *(si) * dirvec[1] + *(co) * norvec[1];
00725         vec[2]= - *(si) * dirvec[2] + *(co) * norvec[2];
00726 
00727         madd_v3_v3v3fl(vec1, headvec, vec, head);
00728         madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
00729 
00730         //glColor4ub(255, 255, 255, 50);
00731         glVertex3fv(vec1);
00732         //glColor4ub(255, 255, 255, 0);
00733         glVertex3fv(vec2);
00734         
00735         glEnd();
00736     }
00737 }
00738 
00739 
00740 /* smat, imat = mat & imat to draw screenaligned */
00741 static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
00742 {
00743     float head, tail /*, length*/;
00744     float *headvec, *tailvec, dirvec[3];
00745     
00746     /* figure out the sizes of spheres */
00747     if (ebone) {
00748         /* this routine doesn't call get_matrix_editbone() that calculates it */
00749         ebone->length = len_v3v3(ebone->head, ebone->tail);
00750         
00751         /*length= ebone->length;*/ /*UNUSED*/
00752         tail= ebone->rad_tail;
00753         if (ebone->parent && (boneflag & BONE_CONNECTED))
00754             head= ebone->parent->rad_tail;
00755         else
00756             head= ebone->rad_head;
00757         headvec= ebone->head;
00758         tailvec= ebone->tail;
00759     }
00760     else {
00761         /*length= pchan->bone->length;*/ /*UNUSED*/
00762         tail= pchan->bone->rad_tail;
00763         if ((pchan->parent) && (boneflag & BONE_CONNECTED))
00764             head= pchan->parent->bone->rad_tail;
00765         else
00766             head= pchan->bone->rad_head;
00767         headvec= pchan->pose_head;
00768         tailvec= pchan->pose_tail;
00769     }
00770     
00771     /* sphere root color */
00772     if (armflag & ARM_EDITMODE) {
00773         if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00774         else UI_ThemeColor(TH_VERTEX);
00775     }
00776     else if (armflag & ARM_POSEMODE)
00777         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
00778     
00779     /*  Draw root point if we are not connected */
00780     if ((boneflag & BONE_CONNECTED)==0) {
00781         if (id != -1)
00782             glLoadName(id | BONESEL_ROOT);
00783         
00784         drawcircball(GL_LINE_LOOP, headvec, head, imat);
00785     }
00786     
00787     /*  Draw tip point */
00788     if (armflag & ARM_EDITMODE) {
00789         if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00790         else UI_ThemeColor(TH_VERTEX);
00791     }
00792     
00793     if (id != -1)
00794         glLoadName(id | BONESEL_TIP);
00795     
00796     drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
00797     
00798     /* base */
00799     if (armflag & ARM_EDITMODE) {
00800         if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
00801         else UI_ThemeColor(TH_WIRE);
00802     }
00803     
00804     sub_v3_v3v3(dirvec, tailvec, headvec);
00805     
00806     /* move vector to viewspace */
00807     mul_mat3_m4_v3(smat, dirvec);
00808     /* clear zcomp */
00809     dirvec[2]= 0.0f;
00810     /* move vector back */
00811     mul_mat3_m4_v3(imat, dirvec);
00812     
00813     if (0.0f != normalize_v3(dirvec)) {
00814         float norvech[3], norvect[3], vec[3];
00815         
00816         copy_v3_v3(vec, dirvec);
00817         
00818         mul_v3_fl(dirvec, head);
00819         cross_v3_v3v3(norvech, dirvec, imat[2]);
00820         
00821         mul_v3_fl(vec, tail);
00822         cross_v3_v3v3(norvect, vec, imat[2]);
00823         
00824         if (id != -1)
00825             glLoadName(id | BONESEL_BONE);
00826         
00827         glBegin(GL_LINES);
00828 
00829         add_v3_v3v3(vec, headvec, norvech);
00830         glVertex3fv(vec);
00831 
00832         add_v3_v3v3(vec, tailvec, norvect);
00833         glVertex3fv(vec);
00834 
00835         sub_v3_v3v3(vec, headvec, norvech);
00836         glVertex3fv(vec);
00837 
00838         sub_v3_v3v3(vec, tailvec, norvect);
00839         glVertex3fv(vec);
00840         
00841         glEnd();
00842     }
00843 }
00844 
00845 /* does wire only for outline selecting */
00846 static void draw_sphere_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
00847 {
00848     GLUquadricObj   *qobj;
00849     float head, tail, length;
00850     float fac1, fac2;
00851     
00852     glPushMatrix();
00853     qobj    = gluNewQuadric();
00854 
00855     /* figure out the sizes of spheres */
00856     if (ebone) {
00857         length= ebone->length;
00858         tail= ebone->rad_tail;
00859         if (ebone->parent && (boneflag & BONE_CONNECTED))
00860             head= ebone->parent->rad_tail;
00861         else
00862             head= ebone->rad_head;
00863     }
00864     else {
00865         length= pchan->bone->length;
00866         tail= pchan->bone->rad_tail;
00867         if (pchan->parent && (boneflag & BONE_CONNECTED))
00868             head= pchan->parent->bone->rad_tail;
00869         else
00870             head= pchan->bone->rad_head;
00871     }
00872     
00873     /* move to z-axis space */
00874     glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
00875 
00876     if (dt==OB_SOLID) {
00877         /* set up solid drawing */
00878         glEnable(GL_COLOR_MATERIAL);
00879         glEnable(GL_LIGHTING);
00880         
00881         gluQuadricDrawStyle(qobj, GLU_FILL); 
00882         glShadeModel(GL_SMOOTH);
00883     }
00884     else {
00885         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
00886     }
00887     
00888     /* sphere root color */
00889     if (armflag & ARM_EDITMODE) {
00890         if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00891         else UI_ThemeColorShade(TH_BONE_SOLID, -30);
00892     }
00893     else if (armflag & ARM_POSEMODE)
00894         set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
00895     else if (dt==OB_SOLID) 
00896         UI_ThemeColorShade(TH_BONE_SOLID, -30);
00897     
00898     /*  Draw root point if we are not connected */
00899     if ((boneflag & BONE_CONNECTED)==0) {
00900         if (id != -1)
00901             glLoadName(id | BONESEL_ROOT);
00902         gluSphere(qobj, head, 16, 10);
00903     }
00904     
00905     /*  Draw tip point */
00906     if (armflag & ARM_EDITMODE) {
00907         if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00908         else UI_ThemeColorShade(TH_BONE_SOLID, -30);
00909     }
00910 
00911     if (id != -1)
00912         glLoadName(id | BONESEL_TIP);
00913     
00914     glTranslatef(0.0f, 0.0f, length);
00915     gluSphere(qobj, tail, 16, 10);
00916     glTranslatef(0.0f, 0.0f, -length);
00917     
00918     /* base */
00919     if (armflag & ARM_EDITMODE) {
00920         if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
00921         else UI_ThemeColor(TH_BONE_SOLID);
00922     }
00923     else if (armflag & ARM_POSEMODE)
00924         set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
00925     else if (dt == OB_SOLID)
00926         UI_ThemeColor(TH_BONE_SOLID);
00927     
00928     fac1= (length-head)/length;
00929     fac2= (length-tail)/length;
00930     
00931     if (length > (head+tail)) {
00932         if (id != -1)
00933             glLoadName (id | BONESEL_BONE);
00934         
00935         glEnable(GL_POLYGON_OFFSET_FILL);
00936         glPolygonOffset(-1.0f, -1.0f);
00937         
00938         glTranslatef(0.0f, 0.0f, head);
00939         gluCylinder(qobj, fac1*head + (1.0f-fac1)*tail, fac2*tail + (1.0f-fac2)*head, length-head-tail, 16, 1);
00940         glTranslatef(0.0f, 0.0f, -head);
00941         
00942         glDisable(GL_POLYGON_OFFSET_FILL);
00943         
00944         /* draw sphere on extrema */
00945         glTranslatef(0.0f, 0.0f, length-tail);
00946         gluSphere(qobj, fac2*tail + (1.0f-fac2)*head, 16, 10);
00947         glTranslatef(0.0f, 0.0f, -length+tail);
00948         
00949         glTranslatef(0.0f, 0.0f, head);
00950         gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
00951     }
00952     else {      
00953         /* 1 sphere in center */
00954         glTranslatef(0.0f, 0.0f, (head + length-tail)/2.0f);
00955         gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
00956     }
00957     
00958     /* restore */
00959     if (dt==OB_SOLID) {
00960         glShadeModel(GL_FLAT);
00961         glDisable(GL_LIGHTING);
00962         glDisable(GL_COLOR_MATERIAL);
00963     }
00964     
00965     glPopMatrix();
00966     gluDeleteQuadric(qobj);  
00967 }
00968 
00969 static GLubyte bm_dot6[]= {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0}; 
00970 static GLubyte bm_dot8[]= {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}; 
00971 
00972 static GLubyte bm_dot5[]= {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0}; 
00973 static GLubyte bm_dot7[]= {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38}; 
00974 
00975 
00976 static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
00977 {
00978     float length;
00979     
00980     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00981     
00982     if (pchan) 
00983         length= pchan->bone->length;
00984     else 
00985         length= ebone->length;
00986     
00987     glPushMatrix();
00988     glScalef(length, length, length);
00989     
00990     /* this chunk not in object mode */
00991     if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
00992         glLineWidth(4.0f);
00993         if (armflag & ARM_POSEMODE)
00994             set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
00995         else if (armflag & ARM_EDITMODE) {
00996             UI_ThemeColor(TH_WIRE);
00997         }
00998         
00999         /*  Draw root point if we are not connected */
01000         if ((boneflag & BONE_CONNECTED)==0) {
01001             if (G.f & G_PICKSEL) {  // no bitmap in selection mode, crashes 3d cards...
01002                 glLoadName (id | BONESEL_ROOT);
01003                 glBegin(GL_POINTS);
01004                 glVertex3f(0.0f, 0.0f, 0.0f);
01005                 glEnd();
01006             }
01007             else {
01008                 glRasterPos3f(0.0f, 0.0f, 0.0f);
01009                 glBitmap(8, 8, 4, 4, 0, 0, bm_dot8);
01010             }
01011         }
01012         
01013         if (id != -1)
01014             glLoadName((GLuint) id|BONESEL_BONE);
01015         
01016         glBegin(GL_LINES);
01017         glVertex3f(0.0f, 0.0f, 0.0f);
01018         glVertex3f(0.0f, 1.0f, 0.0f);
01019         glEnd();
01020         
01021         /* tip */
01022         if (G.f & G_PICKSEL) {  
01023             /* no bitmap in selection mode, crashes 3d cards... */
01024             glLoadName(id | BONESEL_TIP);
01025             glBegin(GL_POINTS);
01026             glVertex3f(0.0f, 1.0f, 0.0f);
01027             glEnd();
01028         }
01029         else {
01030             glRasterPos3f(0.0f, 1.0f, 0.0f);
01031             glBitmap(8, 8, 4, 4, 0, 0, bm_dot7);
01032         }
01033         
01034         /* further we send no names */
01035         if (id != -1)
01036             glLoadName(id & 0xFFFF);    /* object tag, for bordersel optim */
01037         
01038         if (armflag & ARM_POSEMODE)
01039             set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag);
01040     }
01041     
01042     glLineWidth(2.0);
01043     
01044     /*Draw root point if we are not connected */
01045     if ((boneflag & BONE_CONNECTED)==0) {
01046         if ((G.f & G_PICKSEL)==0) { 
01047             /* no bitmap in selection mode, crashes 3d cards... */
01048             if (armflag & ARM_EDITMODE) {
01049                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
01050                 else UI_ThemeColor(TH_VERTEX);
01051             }
01052             glRasterPos3f(0.0f, 0.0f, 0.0f);
01053             glBitmap(8, 8, 4, 4, 0, 0, bm_dot6);
01054         }
01055     }
01056     
01057     if (armflag & ARM_EDITMODE) {
01058         if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
01059         else UI_ThemeColorShade(TH_BACK, -30);
01060     }
01061     glBegin(GL_LINES);
01062     glVertex3f(0.0f, 0.0f, 0.0f);
01063     glVertex3f(0.0f, 1.0f, 0.0f);
01064     glEnd();
01065     
01066     /* tip */
01067     if ((G.f & G_PICKSEL)==0) { 
01068         /* no bitmap in selection mode, crashes 3d cards... */
01069         if (armflag & ARM_EDITMODE) {
01070             if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
01071             else UI_ThemeColor(TH_VERTEX);
01072         }
01073         glRasterPos3f(0.0f, 1.0f, 0.0f);
01074         glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
01075     }
01076     
01077     glLineWidth(1.0);
01078     
01079     glPopMatrix();
01080 }
01081 
01082 static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
01083 {
01084     int segments= 0;
01085     
01086     if (pchan) 
01087         segments= pchan->bone->segments;
01088     
01089     if ((segments > 1) && (pchan)) {
01090         float dlen= length/(float)segments;
01091         Mat4 *bbone= b_bone_spline_setup(pchan, 0);
01092         int a;
01093         
01094         for (a=0; a<segments; a++, bbone++) {
01095             glPushMatrix();
01096             glMultMatrixf(bbone->mat);
01097             if (dt==OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
01098             else drawcube_size(xwidth, dlen, zwidth);
01099             glPopMatrix();
01100         }
01101     }
01102     else {
01103         glPushMatrix();
01104         if (dt==OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
01105         else drawcube_size(xwidth, length, zwidth);
01106         glPopMatrix();
01107     }
01108 }
01109 
01110 static void draw_b_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
01111 {
01112     float xwidth, length, zwidth;
01113     
01114     if (pchan) {
01115         xwidth= pchan->bone->xwidth;
01116         length= pchan->bone->length;
01117         zwidth= pchan->bone->zwidth;
01118     }
01119     else {
01120         xwidth= ebone->xwidth;
01121         length= ebone->length;
01122         zwidth= ebone->zwidth;
01123     }
01124     
01125     /* draw points only if... */
01126     if (armflag & ARM_EDITMODE) {
01127         /* move to unitspace */
01128         glPushMatrix();
01129         glScalef(length, length, length);
01130         draw_bone_points(dt, armflag, boneflag, id);
01131         glPopMatrix();
01132         length*= 0.95f; // make vertices visible
01133     }
01134 
01135     /* colors for modes */
01136     if (armflag & ARM_POSEMODE) {
01137         if (dt <= OB_WIRE)
01138             set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01139         else 
01140             set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01141     }
01142     else if (armflag & ARM_EDITMODE) {
01143         if (dt==OB_WIRE) {
01144             set_ebone_glColor(boneflag);
01145         }
01146         else 
01147             UI_ThemeColor(TH_BONE_SOLID);
01148     }
01149     
01150     if (id != -1) {
01151         glLoadName ((GLuint) id|BONESEL_BONE);
01152     }
01153     
01154     /* set up solid drawing */
01155     if (dt > OB_WIRE) {
01156         glEnable(GL_COLOR_MATERIAL);
01157         glEnable(GL_LIGHTING);
01158         
01159         if (armflag & ARM_POSEMODE)
01160             set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01161         else
01162             UI_ThemeColor(TH_BONE_SOLID);
01163         
01164         draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
01165         
01166         /* disable solid drawing */
01167         glDisable(GL_COLOR_MATERIAL);
01168         glDisable(GL_LIGHTING);
01169     }
01170     else {  
01171         /* wire */
01172         if (armflag & ARM_POSEMODE) {
01173             if (constflag) {
01174                 /* set constraint colors */
01175                 if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
01176                     glEnable(GL_BLEND);
01177                     
01178                     draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
01179                     
01180                     glDisable(GL_BLEND);
01181                 }
01182                 
01183                 /* restore colors */
01184                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01185             }
01186         }       
01187         
01188         draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);      
01189     }
01190 }
01191 
01192 static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
01193 {
01194     if ((segments > 1) && (pchan)) {
01195         float dlen= length/(float)segments;
01196         Mat4 *bbone = bbones;
01197         int a;
01198         
01199         for (a=0; a<segments; a++, bbone++) {
01200             glPushMatrix();
01201             glMultMatrixf(bbone->mat);
01202             
01203             glBegin(GL_LINES);
01204             glVertex3f(0.0f, 0.0f, 0.0f);
01205             glVertex3f(0.0f, dlen, 0.0f);
01206             glEnd(); // GL_LINES
01207             
01208             glPopMatrix();
01209         }
01210     }
01211     else {
01212         glPushMatrix();
01213         
01214         glBegin(GL_LINES);
01215         glVertex3f(0.0f, 0.0f, 0.0f);
01216         glVertex3f(0.0f, length, 0.0f);
01217         glEnd();
01218         
01219         glPopMatrix();
01220     }
01221 }
01222 
01223 static void draw_wire_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
01224 {
01225     Mat4 *bbones = NULL;
01226     int segments = 0;
01227     float length;
01228     
01229     if (pchan) {
01230         segments= pchan->bone->segments;
01231         length= pchan->bone->length;
01232         
01233         if (segments > 1)
01234             bbones = b_bone_spline_setup(pchan, 0);
01235     }
01236     else 
01237         length= ebone->length;
01238     
01239     /* draw points only if... */
01240     if (armflag & ARM_EDITMODE) {
01241         /* move to unitspace */
01242         glPushMatrix();
01243         glScalef(length, length, length);
01244         draw_bone_points(dt, armflag, boneflag, id);
01245         glPopMatrix();
01246         length *= 0.95f;    // make vertices visible
01247     }
01248     
01249     /* this chunk not in object mode */
01250     if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
01251         if (id != -1)
01252             glLoadName((GLuint) id|BONESEL_BONE);
01253         
01254         draw_wire_bone_segments(pchan, bbones, length, segments);
01255         
01256         /* further we send no names */
01257         if (id != -1)
01258             glLoadName(id & 0xFFFF);    /* object tag, for bordersel optim */
01259     }
01260     
01261     /* colors for modes */
01262     if (armflag & ARM_POSEMODE) {
01263         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01264     }
01265     else if (armflag & ARM_EDITMODE) {
01266         set_ebone_glColor(boneflag);
01267     }
01268     
01269     /* draw normal */
01270     draw_wire_bone_segments(pchan, bbones, length, segments);
01271 }
01272 
01273 static void draw_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, float length)
01274 {
01275     
01276     /*  Draw a 3d octahedral bone, we use normalized space based on length,
01277         for glDisplayLists */
01278     
01279     glScalef(length, length, length);
01280 
01281     /* set up solid drawing */
01282     if (dt > OB_WIRE) {
01283         glEnable(GL_COLOR_MATERIAL);
01284         glEnable(GL_LIGHTING);
01285         UI_ThemeColor(TH_BONE_SOLID);
01286     }
01287     
01288     /* colors for posemode */
01289     if (armflag & ARM_POSEMODE) {
01290         if (dt <= OB_WIRE)
01291             set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01292         else 
01293             set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01294     }
01295     
01296     
01297     draw_bone_points(dt, armflag, boneflag, id);
01298     
01299     /* now draw the bone itself */
01300     if (id != -1) {
01301         glLoadName((GLuint) id|BONESEL_BONE);
01302     }
01303     
01304     /* wire? */
01305     if (dt <= OB_WIRE) {
01306         /* colors */
01307         if (armflag & ARM_EDITMODE) {
01308             set_ebone_glColor(boneflag);
01309         }
01310         else if (armflag & ARM_POSEMODE) {
01311             if (constflag) {
01312                 /* draw constraint colors */
01313                 if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {   
01314                     glEnable(GL_BLEND);
01315                     
01316                     draw_bone_solid_octahedral();
01317                     
01318                     glDisable(GL_BLEND);
01319                 }
01320                 
01321                 /* restore colors */
01322                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01323             }
01324         }       
01325         draw_bone_octahedral();
01326     }
01327     else {  
01328         /* solid */
01329         if (armflag & ARM_POSEMODE)
01330             set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01331         else
01332             UI_ThemeColor(TH_BONE_SOLID);
01333         draw_bone_solid_octahedral();
01334     }
01335 
01336     /* disable solid drawing */
01337     if (dt > OB_WIRE) {
01338         glDisable(GL_COLOR_MATERIAL);
01339         glDisable(GL_LIGHTING);
01340     }
01341 }
01342 
01343 static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int armflag, int boneflag, unsigned int id, float length)
01344 {
01345     if(ob==NULL) return;
01346     
01347     glScalef(length, length, length);
01348     
01349     /* colors for posemode */
01350     if (armflag & ARM_POSEMODE) {
01351         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, 0);
01352     }
01353     
01354     if (id != -1) {
01355         glLoadName((GLuint) id|BONESEL_BONE);
01356     }
01357     
01358     draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
01359 }
01360 
01361 
01362 static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
01363 {
01364     bConstraint *con;
01365     bPoseChannel *parchan;
01366     
01367     for (con= pchan->constraints.first; con; con= con->next) {
01368         if (con->enforce == 0.0f)
01369             continue;
01370         
01371         switch (con->type) {
01372             case CONSTRAINT_TYPE_KINEMATIC:
01373             {
01374                 bKinematicConstraint *data = (bKinematicConstraint*)con->data;
01375                 int segcount= 0;
01376                 
01377                 /* if only_temp, only draw if it is a temporary ik-chain */
01378                 if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP))
01379                     continue;
01380                 
01381                 setlinestyle(3);
01382                 glBegin(GL_LINES);
01383                 
01384                 /* exclude tip from chain? */
01385                 if ((data->flag & CONSTRAINT_IK_TIP)==0)
01386                     parchan= pchan->parent;
01387                 else
01388                     parchan= pchan;
01389                 
01390                 glVertex3fv(parchan->pose_tail);
01391                 
01392                 /* Find the chain's root */
01393                 while (parchan->parent) {
01394                     segcount++;
01395                     if(segcount==data->rootbone || segcount>255) break; // 255 is weak
01396                     parchan= parchan->parent;
01397                 }
01398                 if (parchan)
01399                     glVertex3fv(parchan->pose_head);
01400                 
01401                 glEnd();
01402                 setlinestyle(0);
01403             }
01404                 break;
01405             case CONSTRAINT_TYPE_SPLINEIK: 
01406             {
01407                 bSplineIKConstraint *data = (bSplineIKConstraint*)con->data;
01408                 int segcount= 0;
01409                 
01410                 setlinestyle(3);
01411                 glBegin(GL_LINES);
01412                 
01413                 parchan= pchan;
01414                 glVertex3fv(parchan->pose_tail);
01415                 
01416                 /* Find the chain's root */
01417                 while (parchan->parent) {
01418                     segcount++;
01419                     // FIXME: revise the breaking conditions
01420                     if(segcount==data->chainlen || segcount>255) break; // 255 is weak
01421                     parchan= parchan->parent;
01422                 }
01423                 if (parchan) // XXX revise the breaking conditions to only stop at the tail?
01424                     glVertex3fv(parchan->pose_head);
01425                 
01426                 glEnd();
01427                 setlinestyle(0);
01428             }
01429                 break;
01430         }
01431     }
01432 }
01433 
01434 static void bgl_sphere_project(float ax, float az)
01435 {
01436     float dir[3], sine, q3;
01437 
01438     sine= 1.0f - ax*ax - az*az;
01439     q3= (sine < 0.0f)? 0.0f: (float)(2.0*sqrt(sine));
01440 
01441     dir[0]= -az*q3;
01442     dir[1]= 1.0f - 2.0f*sine;
01443     dir[2]= ax*q3;
01444 
01445     glVertex3fv(dir);
01446 }
01447 
01448 static void draw_dof_ellipse(float ax, float az)
01449 {
01450     static float staticSine[16] = {
01451         0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
01452         0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
01453         0.743144825477f, 0.809016994375f, 0.866025403784f,
01454         0.913545457643f, 0.951056516295f, 0.978147600734f,
01455         0.994521895368f, 1.0f
01456     };
01457 
01458     int i, j, n=16;
01459     float x, z, px, pz;
01460 
01461     glEnable(GL_BLEND);
01462     glDepthMask(0);
01463 
01464     glColor4ub(70, 70, 70, 50);
01465 
01466     glBegin(GL_QUADS);
01467     pz= 0.0f;
01468     for(i=1; i<n; i++) {
01469         z= staticSine[i];
01470         
01471         px= 0.0f;
01472         for(j=1; j<n-i+1; j++) {
01473             x = staticSine[j];
01474             
01475             if(j == n-i) {
01476                 glEnd();
01477                 glBegin(GL_TRIANGLES);
01478                 bgl_sphere_project(ax*px, az*z);
01479                 bgl_sphere_project(ax*px, az*pz);
01480                 bgl_sphere_project(ax*x, az*pz);
01481                 glEnd();
01482                 glBegin(GL_QUADS);
01483             }
01484             else {
01485                 bgl_sphere_project(ax*x, az*z);
01486                 bgl_sphere_project(ax*x, az*pz);
01487                 bgl_sphere_project(ax*px, az*pz);
01488                 bgl_sphere_project(ax*px, az*z);
01489             }
01490             
01491             px= x;
01492         }
01493         pz= z;
01494     }
01495     glEnd();
01496 
01497     glDisable(GL_BLEND);
01498     glDepthMask(1);
01499 
01500     glColor3ub(0, 0, 0);
01501 
01502     glBegin(GL_LINE_STRIP);
01503     for (i=0; i<n; i++)
01504         bgl_sphere_project(staticSine[n-i-1]*ax, staticSine[i]*az);
01505     glEnd();
01506 }
01507 
01508 static void draw_pose_dofs(Object *ob)
01509 {
01510     bArmature *arm= ob->data;
01511     bPoseChannel *pchan;
01512     Bone *bone;
01513     
01514     for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01515         bone= pchan->bone;
01516         
01517         if ( (bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) {
01518             if (bone->flag & BONE_SELECTED) {
01519                 if (bone->layer & arm->layer) {
01520                     if (pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT)) {
01521                         if (ED_pose_channel_in_IK_chain(ob, pchan)) {
01522                             float corner[4][3], posetrans[3], mat[4][4];
01523                             float phi=0.0f, theta=0.0f, scale;
01524                             int a, i;
01525                             
01526                             /* in parent-bone pose, but own restspace */
01527                             glPushMatrix();
01528                             
01529                             copy_v3_v3(posetrans, pchan->pose_mat[3]);
01530                             glTranslatef(posetrans[0], posetrans[1], posetrans[2]);
01531                             
01532                             if (pchan->parent) {
01533                                 copy_m4_m4(mat, pchan->parent->pose_mat);
01534                                 mat[3][0]= mat[3][1]= mat[3][2]= 0.0f;
01535                                 glMultMatrixf(mat);
01536                             }
01537                             
01538                             copy_m4_m3(mat, pchan->bone->bone_mat);
01539                             glMultMatrixf(mat);
01540                             
01541                             scale= bone->length*pchan->size[1];
01542                             glScalef(scale, scale, scale);
01543                             
01544                             if (pchan->ikflag & BONE_IK_XLIMIT) {
01545                                 if (pchan->ikflag & BONE_IK_ZLIMIT) {
01546                                     float amin[3], amax[3];
01547                                     
01548                                     for (i=0; i<3; i++) {
01549                                         /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
01550                                         amin[i]= (float)sin(pchan->limitmin[i]*0.5f);
01551                                         amax[i]= (float)sin(pchan->limitmax[i]*0.5f);
01552                                     }
01553                                     
01554                                     glScalef(1.0f, -1.0f, 1.0f);
01555                                     if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
01556                                         draw_dof_ellipse(amin[0], amin[2]);
01557                                     if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
01558                                         draw_dof_ellipse(amin[0], amax[2]);
01559                                     if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
01560                                         draw_dof_ellipse(amax[0], amin[2]);
01561                                     if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
01562                                         draw_dof_ellipse(amax[0], amax[2]);
01563                                     glScalef(1.0f, -1.0f, 1.0f);
01564                                 }
01565                             }
01566                             
01567                             /* arcs */
01568                             if (pchan->ikflag & BONE_IK_ZLIMIT) {
01569                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
01570                                 theta= RAD2DEGF(0.5f * (pchan->limitmin[2]+pchan->limitmax[2]));
01571                                 glRotatef(theta, 0.0f, 0.0f, 1.0f);
01572                                 
01573                                 glColor3ub(50, 50, 255);    // blue, Z axis limit
01574                                 glBegin(GL_LINE_STRIP);
01575                                 for (a=-16; a<=16; a++) {
01576                                     float fac= ((float)a)/16.0f * 0.5f; /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
01577                                     
01578                                     phi= fac * (pchan->limitmax[2] - pchan->limitmin[2]);
01579                                     
01580                                     i= (a == -16) ? 0 : 1;
01581                                     corner[i][0]= (float)sin(phi);
01582                                     corner[i][1]= (float)cos(phi);
01583                                     corner[i][2]= 0.0f;
01584                                     glVertex3fv(corner[i]);
01585                                 }
01586                                 glEnd();
01587                                 
01588                                 glRotatef(-theta, 0.0f, 0.0f, 1.0f);
01589                             }                   
01590                             
01591                             if (pchan->ikflag & BONE_IK_XLIMIT) {
01592                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
01593                                 theta= RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0]));
01594                                 glRotatef(theta, 1.0f, 0.0f, 0.0f);
01595                                 
01596                                 glColor3ub(255, 50, 50);    // Red, X axis limit
01597                                 glBegin(GL_LINE_STRIP);
01598                                 for (a=-16; a<=16; a++) {
01599                                     float fac= ((float)a)/16.0f * 0.5f; /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
01600                                     phi= (float)(0.5*M_PI) + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
01601                                     
01602                                     i= (a == -16) ? 2 : 3;
01603                                     corner[i][0]= 0.0f;
01604                                     corner[i][1]= (float)sin(phi);
01605                                     corner[i][2]= (float)cos(phi);
01606                                     glVertex3fv(corner[i]);
01607                                 }
01608                                 glEnd();
01609                                 
01610                                 glRotatef(-theta, 1.0f, 0.0f, 0.0f);
01611                             }
01612                             
01613                             /* out of cone, out of bone */
01614                             glPopMatrix(); 
01615                         }
01616                     }
01617                 }
01618             }
01619         }
01620     }
01621 }
01622 
01623 static void bone_matrix_translate_y(float mat[][4], float y)
01624 {
01625     float trans[3];
01626 
01627     copy_v3_v3(trans, mat[1]);
01628     mul_v3_fl(trans, y);
01629     add_v3_v3(mat[3], trans);
01630 }
01631 
01632 /* assumes object is Armature with pose */
01633 static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, const short is_ghost, const short is_outline)
01634 {
01635     RegionView3D *rv3d= ar->regiondata;
01636     Object *ob= base->object;
01637     bArmature *arm= ob->data;
01638     bPoseChannel *pchan;
01639     Bone *bone;
01640     GLfloat tmp;
01641     float smat[4][4], imat[4][4], bmat[4][4];
01642     int index= -1;
01643     short do_dashed= 3, draw_wire= 0;
01644     int flag;
01645     
01646     /* being set below */
01647     arm->layer_used= 0;
01648     
01649     /* hacky... prevent outline select from drawing dashed helplines */
01650     glGetFloatv(GL_LINE_WIDTH, &tmp);
01651     if (tmp > 1.1f) do_dashed &= ~1;
01652     if (v3d->flag & V3D_HIDE_HELPLINES) do_dashed &= ~2;
01653     
01654     /* precalc inverse matrix for drawing screen aligned */
01655     if (arm->drawtype==ARM_ENVELOPE) {
01656         /* precalc inverse matrix for drawing screen aligned */
01657         copy_m4_m4(smat, rv3d->viewmatob);
01658         mul_mat3_m4_fl(smat, 1.0f/len_v3(ob->obmat[0]));
01659         invert_m4_m4(imat, smat);
01660         
01661         /* and draw blended distances */
01662         if (arm->flag & ARM_POSEMODE) {
01663             glEnable(GL_BLEND);
01664             //glShadeModel(GL_SMOOTH);
01665             
01666             if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
01667             
01668             for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01669                 bone= pchan->bone;
01670                 if (bone) {
01671                     /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] 
01672                      * NOTE: this is the only case with NO_DEFORM==0 flag, as this is for envelope influence drawing 
01673                      */
01674                     if ( (bone->flag & (BONE_HIDDEN_P|BONE_NO_DEFORM|BONE_HIDDEN_PG))==0 && 
01675                          ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01676                     {
01677                         if (bone->flag & (BONE_SELECTED)) {
01678                             if (bone->layer & arm->layer)
01679                                 draw_sphere_bone_dist(smat, imat, pchan, NULL);
01680                         }
01681                     }
01682                 }
01683             }
01684             
01685             if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
01686             glDisable(GL_BLEND);
01687             //glShadeModel(GL_FLAT);
01688         }
01689     }
01690     
01691     /* little speedup, also make sure transparent only draws once */
01692     glCullFace(GL_BACK); 
01693     glEnable(GL_CULL_FACE);
01694     
01695     /* if solid we draw that first, with selection codes, but without names, axes etc */
01696     if (dt > OB_WIRE) {
01697         if (arm->flag & ARM_POSEMODE) 
01698             index= base->selcol;
01699         
01700         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01701             bone= pchan->bone;
01702             arm->layer_used |= bone->layer;
01703             
01704             /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
01705             if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
01706                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01707             {
01708                 if (bone->layer & arm->layer) {
01709                     int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
01710                     glPushMatrix();
01711                     
01712                     if (use_custom && pchan->custom_tx) {
01713                         glMultMatrixf(pchan->custom_tx->pose_mat);
01714                     } 
01715                     else {
01716                         glMultMatrixf(pchan->pose_mat);
01717                     }
01718                     
01719                     /* catch exception for bone with hidden parent */
01720                     flag= bone->flag;
01721                     if ( (bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)) )
01722                         flag &= ~BONE_CONNECTED;
01723                     
01724                     /* set temporary flag for drawing bone as active, but only if selected */
01725                     if (bone == arm->act_bone)
01726                         flag |= BONE_DRAW_ACTIVE;
01727                     
01728                     /* set color-set to use */
01729                     set_pchan_colorset(ob, pchan);
01730                     
01731                     if (use_custom) {
01732                         /* if drawwire, don't try to draw in solid */
01733                         if (pchan->bone->flag & BONE_DRAWWIRE) 
01734                             draw_wire= 1;
01735                         else
01736                             draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_SOLID, arm->flag, flag, index, bone->length);
01737                     }
01738                     else if (arm->drawtype==ARM_LINE)
01739                         ;   /* nothing in solid */
01740                     else if (arm->drawtype==ARM_WIRE)
01741                         ;   /* nothing in solid */
01742                     else if (arm->drawtype==ARM_ENVELOPE)
01743                         draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
01744                     else if (arm->drawtype==ARM_B_BONE)
01745                         draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
01746                     else
01747                         draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
01748                         
01749                     glPopMatrix();
01750                 }
01751             }
01752             
01753             if (index!= -1) 
01754                 index+= 0x10000;    // pose bones count in higher 2 bytes only
01755         }
01756         
01757         /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
01758          * stick bones and/or wire custom-shapes are drawn in next loop 
01759          */
01760         if (ELEM(arm->drawtype,ARM_LINE,ARM_WIRE)==0 && (draw_wire == 0)) {
01761             /* object tag, for bordersel optim */
01762             glLoadName(index & 0xFFFF); 
01763             index= -1;
01764         }
01765     }
01766     
01767     /* draw custom bone shapes as wireframes */
01768     if ( !(arm->flag & ARM_NO_CUSTOM) &&
01769          ((draw_wire) || (dt <= OB_WIRE)) ) 
01770     {
01771         if (arm->flag & ARM_POSEMODE)
01772             index= base->selcol;
01773             
01774         /* only draw custom bone shapes that need to be drawn as wires */
01775         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01776             bone= pchan->bone;
01777             
01778             /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
01779             if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
01780                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01781             {
01782                 if (bone->layer & arm->layer) {
01783                     if (pchan->custom) {
01784                         if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
01785                             glPushMatrix();
01786                             
01787                             if(pchan->custom_tx) {
01788                                 glMultMatrixf(pchan->custom_tx->pose_mat);
01789                             } 
01790                             else {
01791                                 glMultMatrixf(pchan->pose_mat);
01792                             }
01793                             
01794                             /* prepare colors */
01795                             if(is_ghost) {
01796                                 /* 13 October 2009, Disabled this to make ghosting show the right colors (Aligorith) */
01797                             }
01798                             else if (arm->flag & ARM_POSEMODE)  
01799                                 set_pchan_colorset(ob, pchan);
01800                             else {
01801                                 if ((scene->basact)==base) {
01802                                     if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
01803                                     else UI_ThemeColor(TH_WIRE);
01804                                 }
01805                                 else {
01806                                     if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
01807                                     else UI_ThemeColor(TH_WIRE);
01808                                 }
01809                             }
01810                                 
01811                             /* catch exception for bone with hidden parent */
01812                             flag= bone->flag;
01813                             if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
01814                                 flag &= ~BONE_CONNECTED;
01815                                 
01816                             /* set temporary flag for drawing bone as active, but only if selected */
01817                             if (bone == arm->act_bone)
01818                                 flag |= BONE_DRAW_ACTIVE;
01819                             
01820                             draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_WIRE, arm->flag, flag, index, bone->length);
01821                             
01822                             glPopMatrix();
01823                         }
01824                     }
01825                 }
01826             }
01827             
01828             if (index != -1) 
01829                 index+= 0x10000;    // pose bones count in higher 2 bytes only
01830         }
01831         /* stick or wire bones have not been drawn yet so dont clear object selection in this case */
01832         if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)==0 && draw_wire) {
01833             /* object tag, for bordersel optim */
01834             glLoadName(index & 0xFFFF); 
01835             index= -1;
01836         }
01837     }
01838     
01839     /* wire draw over solid only in posemode */
01840     if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
01841         /* draw line check first. we do selection indices */
01842         if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
01843             if (arm->flag & ARM_POSEMODE) 
01844                 index= base->selcol;
01845         }
01846         /* if solid && posemode, we draw again with polygonoffset */
01847         else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
01848             bglPolygonOffset(rv3d->dist, 1.0);
01849         }
01850         else {
01851             /* and we use selection indices if not done yet */
01852             if (arm->flag & ARM_POSEMODE) 
01853                 index= base->selcol;
01854         }
01855         
01856         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01857             bone= pchan->bone;
01858             arm->layer_used |= bone->layer;
01859             
01860             /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
01861             if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
01862                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01863             {
01864                 if (bone->layer & arm->layer) {
01865                     const short constflag= pchan->constflag;
01866                     if ((do_dashed & 1) && (pchan->parent)) {
01867                         /* Draw a line from our root to the parent's tip 
01868                          *  - only if V3D_HIDE_HELPLINES is enabled...
01869                          */
01870                         if ( (do_dashed & 2) && ((bone->flag & BONE_CONNECTED)==0) ) {
01871                             if (arm->flag & ARM_POSEMODE) {
01872                                 glLoadName(index & 0xFFFF); // object tag, for bordersel optim
01873                                 UI_ThemeColor(TH_WIRE);
01874                             }
01875                             setlinestyle(3);
01876                             glBegin(GL_LINES);
01877                             glVertex3fv(pchan->pose_head);
01878                             glVertex3fv(pchan->parent->pose_tail);
01879                             glEnd();
01880                             setlinestyle(0);
01881                         }
01882                         
01883                         /* Draw a line to IK root bone 
01884                          *  - only if temporary chain (i.e. "autoik")
01885                          */
01886                         if (arm->flag & ARM_POSEMODE) {
01887                             if (constflag & PCHAN_HAS_IK) {
01888                                 if (bone->flag & BONE_SELECTED) {
01889                                     if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
01890                                     else glColor3ub(200, 200, 50);  // add theme!
01891                                     
01892                                     glLoadName(index & 0xFFFF);
01893                                     pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
01894                                 }
01895                             }
01896                             else if (constflag & PCHAN_HAS_SPLINEIK) {
01897                                 if (bone->flag & BONE_SELECTED) {
01898                                     glColor3ub(150, 200, 50);   // add theme!
01899                                     
01900                                     glLoadName(index & 0xFFFF);
01901                                     pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
01902                                 }
01903                             }   
01904                         }
01905                     }
01906                     
01907                     glPushMatrix();
01908                     if (arm->drawtype != ARM_ENVELOPE)
01909                         glMultMatrixf(pchan->pose_mat);
01910                     
01911                     /* catch exception for bone with hidden parent */
01912                     flag= bone->flag;
01913                     if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
01914                         flag &= ~BONE_CONNECTED;
01915                     
01916                     /* set temporary flag for drawing bone as active, but only if selected */
01917                     if (bone == arm->act_bone)
01918                         flag |= BONE_DRAW_ACTIVE;
01919                     
01920                     /* extra draw service for pose mode */
01921 
01922                     /* set color-set to use */
01923                     set_pchan_colorset(ob, pchan);
01924                     
01925                     if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM))
01926                         ; // custom bone shapes should not be drawn here!
01927                     else if (arm->drawtype==ARM_ENVELOPE) {
01928                         if (dt < OB_SOLID)
01929                             draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
01930                     }
01931                     else if (arm->drawtype==ARM_LINE)
01932                         draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
01933                     else if (arm->drawtype==ARM_WIRE)
01934                         draw_wire_bone(dt, arm->flag, flag, constflag, index, pchan, NULL);
01935                     else if (arm->drawtype==ARM_B_BONE)
01936                         draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
01937                     else
01938                         draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
01939                     
01940                     glPopMatrix();
01941                 }
01942             }
01943             
01944             /* pose bones count in higher 2 bytes only */
01945             if (index != -1) 
01946                 index+= 0x10000;    
01947         }
01948         /* restore things */
01949         if (!ELEM(arm->drawtype, ARM_WIRE, ARM_LINE) && (dt>OB_WIRE) && (arm->flag & ARM_POSEMODE))
01950             bglPolygonOffset(rv3d->dist, 0.0);
01951     }   
01952     
01953     /* restore */
01954     glDisable(GL_CULL_FACE);
01955     
01956     /* draw DoFs */
01957     if (arm->flag & ARM_POSEMODE)
01958         draw_pose_dofs(ob);
01959 
01960     /* finally names and axes */
01961     if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES) && is_outline == 0) {
01962         /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
01963         if ((G.f & G_PICKSEL) == 0) {
01964             float vec[3];
01965             
01966             unsigned char col[4];
01967             float col_f[4];
01968             glGetFloatv(GL_CURRENT_COLOR, col_f); /* incase this is not set below */
01969             rgb_float_to_byte(col_f, col);
01970             col[3]= 255;
01971             
01972             if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
01973             
01974             for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
01975                 if ((pchan->bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0) {
01976                     if (pchan->bone->layer & arm->layer) {
01977                         if (arm->flag & (ARM_EDITMODE|ARM_POSEMODE)) {
01978                             bone= pchan->bone;
01979                             UI_GetThemeColor3ubv((bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
01980                         }
01981                         else if (dt > OB_WIRE) {
01982                             UI_GetThemeColor3ubv(TH_TEXT, col);
01983                         }
01984                         
01985                         /*  Draw names of bone  */
01986                         if (arm->flag & ARM_DRAWNAMES) {
01987                             mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
01988                             view3d_cached_text_draw_add(vec, pchan->name, 10, 0, col);
01989                         }   
01990                         
01991                         /*  Draw additional axes on the bone tail  */
01992                         if ( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ) {
01993                             glPushMatrix();
01994                             copy_m4_m4(bmat, pchan->pose_mat);
01995                             bone_matrix_translate_y(bmat, pchan->bone->length);
01996                             glMultMatrixf(bmat);
01997                             
01998                             glColor3ubv(col);
01999                             drawaxes(pchan->bone->length*0.25f, OB_ARROWS);
02000                             
02001                             glPopMatrix();
02002                         }
02003                     }
02004                 }
02005             }
02006             
02007             if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02008         }
02009     }
02010 }
02011 
02012 /* in editmode, we don't store the bone matrix... */
02013 static void get_matrix_editbone(EditBone *eBone, float bmat[][4])
02014 {
02015     float       delta[3];
02016     float       mat[3][3];
02017     
02018     /* Compose the parent transforms (i.e. their translations) */
02019     sub_v3_v3v3(delta, eBone->tail, eBone->head);   
02020     
02021     eBone->length = (float)sqrt(delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]);
02022     
02023     vec_roll_to_mat3(delta, eBone->roll, mat);
02024     copy_m4_m3(bmat, mat);
02025 
02026     add_v3_v3(bmat[3], eBone->head);
02027 }
02028 
02029 static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
02030 {
02031     RegionView3D *rv3d= ar->regiondata;
02032     EditBone *eBone;
02033     bArmature *arm= ob->data;
02034     float smat[4][4], imat[4][4], bmat[4][4];
02035     unsigned int index;
02036     int flag;
02037     
02038     /* being set in code below */
02039     arm->layer_used= 0;
02040     
02041     /* envelope (deform distance) */
02042     if(arm->drawtype==ARM_ENVELOPE) {
02043         /* precalc inverse matrix for drawing screen aligned */
02044         copy_m4_m4(smat, rv3d->viewmatob);
02045         mul_mat3_m4_fl(smat, 1.0f/len_v3(ob->obmat[0]));
02046         invert_m4_m4(imat, smat);
02047         
02048         /* and draw blended distances */
02049         glEnable(GL_BLEND);
02050         //glShadeModel(GL_SMOOTH);
02051         
02052         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02053 
02054         for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
02055             if (eBone->layer & arm->layer) {
02056                 if ((eBone->flag & (BONE_HIDDEN_A|BONE_NO_DEFORM))==0) {
02057                     if (eBone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL))
02058                         draw_sphere_bone_dist(smat, imat, NULL, eBone);
02059                 }
02060             }
02061         }
02062         
02063         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02064         glDisable(GL_BLEND);
02065         //glShadeModel(GL_FLAT);
02066     }
02067     
02068     /* if solid we draw it first */
02069     if ((dt > OB_WIRE) && (arm->drawtype != ARM_LINE)) {
02070         for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
02071             if (eBone->layer & arm->layer) {
02072                 if ((eBone->flag & BONE_HIDDEN_A)==0) {
02073                     glPushMatrix();
02074                     get_matrix_editbone(eBone, bmat);
02075                     glMultMatrixf(bmat);
02076                     
02077                     /* catch exception for bone with hidden parent */
02078                     flag= eBone->flag;
02079                     if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))
02080                         flag &= ~BONE_CONNECTED;
02081                         
02082                     /* set temporary flag for drawing bone as active, but only if selected */
02083                     if (eBone == arm->act_edbone)
02084                         flag |= BONE_DRAW_ACTIVE;
02085                     
02086                     if (arm->drawtype==ARM_ENVELOPE)
02087                         draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
02088                     else if(arm->drawtype==ARM_B_BONE)
02089                         draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
02090                     else if (arm->drawtype==ARM_WIRE)
02091                         draw_wire_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
02092                     else {
02093                         draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
02094                     }
02095                     
02096                     glPopMatrix();
02097                 }
02098             }
02099         }
02100     }
02101     
02102     /* if wire over solid, set offset */
02103     index= -1;
02104     glLoadName(-1);
02105     if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
02106         if(G.f & G_PICKSEL)
02107             index= 0;
02108     }
02109     else if (dt > OB_WIRE) 
02110         bglPolygonOffset(rv3d->dist, 1.0f);
02111     else if (arm->flag & ARM_EDITMODE) 
02112         index= 0;   /* do selection codes */
02113     
02114     for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
02115         arm->layer_used |= eBone->layer;
02116         if (eBone->layer & arm->layer) {
02117             if ((eBone->flag & BONE_HIDDEN_A)==0) {
02118                 
02119                 /* catch exception for bone with hidden parent */
02120                 flag= eBone->flag;
02121                 if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))
02122                     flag &= ~BONE_CONNECTED;
02123                     
02124                 /* set temporary flag for drawing bone as active, but only if selected */
02125                 if (eBone == arm->act_edbone)
02126                     flag |= BONE_DRAW_ACTIVE;
02127                 
02128                 if (arm->drawtype == ARM_ENVELOPE) {
02129                     if (dt < OB_SOLID)
02130                         draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
02131                 }
02132                 else {
02133                     glPushMatrix();
02134                     get_matrix_editbone(eBone, bmat);
02135                     glMultMatrixf(bmat);
02136                     
02137                     if (arm->drawtype == ARM_LINE) 
02138                         draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
02139                     else if (arm->drawtype==ARM_WIRE)
02140                         draw_wire_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
02141                     else if (arm->drawtype == ARM_B_BONE)
02142                         draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
02143                     else
02144                         draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
02145                     
02146                     glPopMatrix();
02147                 }
02148                 
02149                 /* offset to parent */
02150                 if (eBone->parent) {
02151                     UI_ThemeColor(TH_WIRE);
02152                     glLoadName (-1);        // -1 here is OK!
02153                     setlinestyle(3);
02154                     
02155                     glBegin(GL_LINES);
02156                     glVertex3fv(eBone->parent->tail);
02157                     glVertex3fv(eBone->head);
02158                     glEnd();
02159                     
02160                     setlinestyle(0);
02161                 }
02162             }
02163         }
02164         if(index!=-1) index++;
02165     }
02166     
02167     /* restore */
02168     if(index!=-1) glLoadName(-1);
02169     if ELEM(arm->drawtype,ARM_LINE,ARM_WIRE);
02170     else if (dt>OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f);
02171     
02172     /* finally names and axes */
02173     if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
02174         // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
02175         if ((G.f & G_PICKSEL) == 0) {
02176             float vec[3];
02177             unsigned char col[4];
02178             col[3]= 255;
02179             
02180             if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02181             
02182             for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
02183                 if(eBone->layer & arm->layer) {
02184                     if ((eBone->flag & BONE_HIDDEN_A)==0) {
02185 
02186                         UI_GetThemeColor3ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
02187 
02188                         /*  Draw name */
02189                         if (arm->flag & ARM_DRAWNAMES) {
02190                             mid_v3_v3v3(vec, eBone->head, eBone->tail);
02191                             glRasterPos3fv(vec);
02192                             view3d_cached_text_draw_add(vec, eBone->name, 10, 0, col);
02193                         }                   
02194                         /*  Draw additional axes */
02195                         if (arm->flag & ARM_DRAWAXES) {
02196                             glPushMatrix();
02197                             get_matrix_editbone(eBone, bmat);
02198                             bone_matrix_translate_y(bmat, eBone->length);
02199                             glMultMatrixf(bmat);
02200 
02201                             glColor3ubv(col);
02202                             drawaxes(eBone->length*0.25f, OB_ARROWS);
02203                             
02204                             glPopMatrix();
02205                         }
02206                         
02207                     }
02208                 }
02209             }
02210             
02211             if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02212         }
02213     }
02214 }
02215 
02216 /* ****************************** Armature Visualisation ******************************** */
02217 
02218 /* ---------- Paths --------- */
02219 
02220 /* draw bone paths
02221  *  - in view space 
02222  */
02223 static void draw_pose_paths(Scene *scene, View3D *v3d, ARegion *ar, Object *ob)
02224 {
02225     bAnimVizSettings *avs= &ob->pose->avs;
02226     bArmature *arm= ob->data;
02227     bPoseChannel *pchan;
02228     
02229     /* setup drawing environment for paths */
02230     draw_motion_paths_init(v3d, ar);
02231     
02232     /* draw paths where they exist and they releated bone is visible */
02233     for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
02234         if ((pchan->bone->layer & arm->layer) && (pchan->mpath))
02235             draw_motion_path_instance(scene, ob, pchan, avs, pchan->mpath);
02236     }
02237     
02238     /* cleanup after drawing */
02239     draw_motion_paths_cleanup(v3d);
02240 }
02241 
02242 
02243 /* ---------- Ghosts --------- */
02244 
02245 /* helper function for ghost drawing - sets/removes flags for temporarily 
02246  * hiding unselected bones while drawing ghosts
02247  */
02248 static void ghost_poses_tag_unselected(Object *ob, short unset)
02249 {
02250     bArmature *arm= ob->data;
02251     bPose *pose= ob->pose;
02252     bPoseChannel *pchan;
02253     
02254     /* don't do anything if no hiding any bones */
02255     if ((arm->flag & ARM_GHOST_ONLYSEL)==0)
02256         return;
02257         
02258     /* loop over all pchans, adding/removing tags as appropriate */
02259     for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
02260         if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
02261             if (unset) {
02262                 /* remove tags from all pchans if cleaning up */
02263                 pchan->bone->flag &= ~BONE_HIDDEN_PG;
02264             }
02265             else {
02266                 /* set tags on unselected pchans only */
02267                 if ((pchan->bone->flag & BONE_SELECTED)==0)
02268                     pchan->bone->flag |= BONE_HIDDEN_PG;
02269             }
02270         }
02271     }
02272 }
02273 
02274 /* draw ghosts that occur within a frame range 
02275  *  note: object should be in posemode 
02276  */
02277 static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
02278 {
02279     Object *ob= base->object;
02280     AnimData *adt= BKE_animdata_from_id(&ob->id);
02281     bArmature *arm= ob->data;
02282     bPose *posen, *poseo;
02283     float start, end, stepsize, range, colfac;
02284     int cfrao, flago, ipoflago;
02285     
02286     start = (float)arm->ghostsf;
02287     end = (float)arm->ghostef;
02288     if (end <= start)
02289         return;
02290     
02291     stepsize= (float)(arm->ghostsize);
02292     range= (float)(end - start);
02293     
02294     /* store values */
02295     ob->mode &= ~OB_MODE_POSE;
02296     cfrao= CFRA;
02297     flago= arm->flag;
02298     arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
02299     ipoflago= ob->ipoflag; 
02300     ob->ipoflag |= OB_DISABLE_PATH;
02301     
02302     /* copy the pose */
02303     poseo= ob->pose;
02304     copy_pose(&posen, ob->pose, 1);
02305     ob->pose= posen;
02306     armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
02307     ghost_poses_tag_unselected(ob, 0);      /* hide unselected bones if need be */
02308     
02309     glEnable(GL_BLEND);
02310     if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02311     
02312     /* draw from first frame of range to last */
02313     for (CFRA= (int)start; CFRA < end; CFRA += (int)stepsize) {
02314         colfac = (end - (float)CFRA) / range;
02315         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02316         
02317         BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02318         where_is_pose(scene, ob);
02319         draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02320     }
02321     glDisable(GL_BLEND);
02322     if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02323 
02324     ghost_poses_tag_unselected(ob, 1);      /* unhide unselected bones if need be */
02325     free_pose(posen);
02326     
02327     /* restore */
02328     CFRA= cfrao;
02329     ob->pose= poseo;
02330     arm->flag= flago;
02331     armature_rebuild_pose(ob, ob->data);
02332     ob->mode |= OB_MODE_POSE;
02333     ob->ipoflag= ipoflago; 
02334 }
02335 
02336 /* draw ghosts on keyframes in action within range 
02337  *  - object should be in posemode 
02338  */
02339 static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
02340 {
02341     Object *ob= base->object;
02342     AnimData *adt= BKE_animdata_from_id(&ob->id);
02343     bAction *act= (adt) ? adt->action : NULL;
02344     bArmature *arm= ob->data;
02345     bPose *posen, *poseo;
02346     DLRBT_Tree keys;
02347     ActKeyColumn *ak, *akn;
02348     float start, end, range, colfac, i;
02349     int cfrao, flago;
02350     
02351     start = (float)arm->ghostsf;
02352     end = (float)arm->ghostef;
02353     if (end <= start)
02354         return;
02355     
02356     /* get keyframes - then clip to only within range */
02357     BLI_dlrbTree_init(&keys);
02358     action_to_keylist(adt, act, &keys, NULL);
02359     BLI_dlrbTree_linkedlist_sync(&keys);
02360     
02361     range= 0;
02362     for (ak= keys.first; ak; ak= akn) {
02363         akn= ak->next;
02364         
02365         if ((ak->cfra < start) || (ak->cfra > end))
02366             BLI_freelinkN((ListBase *)&keys, ak);
02367         else
02368             range++;
02369     }
02370     if (range == 0) return;
02371     
02372     /* store values */
02373     ob->mode &= ~OB_MODE_POSE;
02374     cfrao= CFRA;
02375     flago= arm->flag;
02376     arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
02377     ob->ipoflag |= OB_DISABLE_PATH;
02378     
02379     /* copy the pose */
02380     poseo= ob->pose;
02381     copy_pose(&posen, ob->pose, 1);
02382     ob->pose= posen;
02383     armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
02384     ghost_poses_tag_unselected(ob, 0);      /* hide unselected bones if need be */
02385     
02386     glEnable(GL_BLEND);
02387     if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02388     
02389     /* draw from first frame of range to last */
02390     for (ak=keys.first, i=0; ak; ak=ak->next, i++) {
02391         colfac = i/range;
02392         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02393         
02394         CFRA= (int)ak->cfra;
02395         
02396         BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02397         where_is_pose(scene, ob);
02398         draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02399     }
02400     glDisable(GL_BLEND);
02401     if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02402 
02403     ghost_poses_tag_unselected(ob, 1);      /* unhide unselected bones if need be */
02404     BLI_dlrbTree_free(&keys);
02405     free_pose(posen);
02406     
02407     /* restore */
02408     CFRA= cfrao;
02409     ob->pose= poseo;
02410     arm->flag= flago;
02411     armature_rebuild_pose(ob, ob->data);
02412     ob->mode |= OB_MODE_POSE;
02413 }
02414 
02415 /* draw ghosts around current frame
02416  *  - object is supposed to be armature in posemode 
02417  */
02418 static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
02419 {
02420     Object *ob= base->object;
02421     AnimData *adt= BKE_animdata_from_id(&ob->id);
02422     bArmature *arm= ob->data;
02423     bPose *posen, *poseo;
02424     float cur, start, end, stepsize, range, colfac, actframe, ctime;
02425     int cfrao, flago;
02426     
02427     /* pre conditions, get an action with sufficient frames */
02428     if ELEM(NULL, adt, adt->action)
02429         return;
02430 
02431     calc_action_range(adt->action, &start, &end, 0);
02432     if (start == end)
02433         return;
02434 
02435     stepsize= (float)(arm->ghostsize);
02436     range= (float)(arm->ghostep)*stepsize + 0.5f;   /* plus half to make the for loop end correct */
02437     
02438     /* store values */
02439     ob->mode &= ~OB_MODE_POSE;
02440     cfrao= CFRA;
02441     actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0);
02442     flago= arm->flag;
02443     arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
02444     
02445     /* copy the pose */
02446     poseo= ob->pose;
02447     copy_pose(&posen, ob->pose, 1);
02448     ob->pose= posen;
02449     armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
02450     ghost_poses_tag_unselected(ob, 0);      /* hide unselected bones if need be */
02451     
02452     glEnable(GL_BLEND);
02453     if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02454     
02455     /* draw from darkest blend to lowest */
02456     for(cur= stepsize; cur<range; cur+=stepsize) {
02457         ctime= cur - (float)fmod(cfrao, stepsize);  /* ensures consistent stepping */
02458         colfac= ctime/range;
02459         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02460         
02461         /* only within action range */
02462         if (actframe+ctime >= start && actframe+ctime <= end) {
02463             CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP);
02464             
02465             if (CFRA != cfrao) {
02466                 BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02467                 where_is_pose(scene, ob);
02468                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02469             }
02470         }
02471         
02472         ctime= cur + (float)fmod((float)cfrao, stepsize) - stepsize+1.0f;   /* ensures consistent stepping */
02473         colfac= ctime/range;
02474         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02475         
02476         /* only within action range */
02477         if ((actframe-ctime >= start) && (actframe-ctime <= end)) {
02478             CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP);
02479             
02480             if (CFRA != cfrao) {
02481                 BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02482                 where_is_pose(scene, ob);
02483                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02484             }
02485         }
02486     }
02487     glDisable(GL_BLEND);
02488     if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02489 
02490     ghost_poses_tag_unselected(ob, 1);      /* unhide unselected bones if need be */
02491     free_pose(posen);
02492     
02493     /* restore */
02494     CFRA= cfrao;
02495     ob->pose= poseo;
02496     arm->flag= flago;
02497     armature_rebuild_pose(ob, ob->data);
02498     ob->mode |= OB_MODE_POSE;
02499 }
02500 
02501 /* ********************************** Armature Drawing - Main ************************* */
02502 
02503 /* called from drawobject.c, return 1 if nothing was drawn */
02504 int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag, const short is_outline)
02505 {
02506     Object *ob= base->object;
02507     bArmature *arm= ob->data;
02508     int retval= 0;
02509 
02510     if(v3d->flag2 & V3D_RENDER_OVERRIDE)
02511         return 1;
02512     
02513     if(dt>OB_WIRE && !ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
02514         /* we use color for solid lighting */
02515         glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
02516         glEnable(GL_COLOR_MATERIAL);
02517         glColor3ub(255,255,255);    // clear spec
02518         glDisable(GL_COLOR_MATERIAL);
02519         
02520         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
02521         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting...
02522     }
02523     
02524     /* arm->flag is being used to detect mode... */
02525     /* editmode? */
02526     if(arm->edbo) {
02527         arm->flag |= ARM_EDITMODE;
02528         draw_ebones(v3d, ar, ob, dt);
02529         arm->flag &= ~ARM_EDITMODE;
02530     }
02531     else{
02532         /*  Draw Pose */
02533         if(ob->pose && ob->pose->chanbase.first) {
02534             /* drawing posemode selection indices or colors only in these cases */
02535             if(!(base->flag & OB_FROMDUPLI)) {
02536                 if(G.f & G_PICKSEL) {
02537 #if 0               /* nifty but actually confusing to allow bone selection out of posemode */
02538                     if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
02539                         if(ob==modifiers_isDeformedByArmature(OBACT))
02540                             arm->flag |= ARM_POSEMODE;
02541                     }
02542                     else
02543 #endif
02544                     if(ob->mode & OB_MODE_POSE) {
02545                         arm->flag |= ARM_POSEMODE;
02546                     }
02547                 }
02548                 else if(ob->mode & OB_MODE_POSE) {
02549                     if (arm->ghosttype == ARM_GHOST_RANGE) {
02550                         draw_ghost_poses_range(scene, v3d, ar, base);
02551                     }
02552                     else if (arm->ghosttype == ARM_GHOST_KEYS) {
02553                         draw_ghost_poses_keys(scene, v3d, ar, base);
02554                     }
02555                     else if (arm->ghosttype == ARM_GHOST_CUR) {
02556                         if (arm->ghostep)
02557                             draw_ghost_poses(scene, v3d, ar, base);
02558                     }
02559                     if ((flag & DRAW_SCENESET)==0) {
02560                         if(ob==OBACT) 
02561                             arm->flag |= ARM_POSEMODE;
02562                         else if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
02563                             if(ob==modifiers_isDeformedByArmature(OBACT))
02564                                 arm->flag |= ARM_POSEMODE;
02565                         }
02566                         draw_pose_paths(scene, v3d, ar, ob);
02567                     }
02568                 }   
02569             }
02570             draw_pose_bones(scene, v3d, ar, base, dt, FALSE, is_outline);
02571             arm->flag &= ~ARM_POSEMODE; 
02572             
02573             if(ob->mode & OB_MODE_POSE)
02574                 UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
02575         }
02576         else retval= 1;
02577     }
02578     /* restore */
02579     glFrontFace(GL_CCW);
02580 
02581     return retval;
02582 }
02583 
02584 /* *************** END Armature drawing ******************* */
02585 
02586