Blender V2.61 - r43446
|
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