|
Blender
V2.59
|
00001 /* 00002 * $Id: drawanimviz.c 37671 2011-06-20 17:50:59Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2009 by the Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Joshua Leung 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <stdlib.h> 00036 #include <string.h> 00037 #include <math.h> 00038 00039 #include "BLO_sys_types.h" 00040 00041 #include "DNA_anim_types.h" 00042 #include "DNA_armature_types.h" 00043 #include "DNA_scene_types.h" 00044 #include "DNA_screen_types.h" 00045 #include "DNA_view3d_types.h" 00046 #include "DNA_object_types.h" 00047 00048 #include "BLI_blenlib.h" 00049 #include "BLI_math.h" 00050 #include "BLI_dlrbTree.h" 00051 00052 #include "BKE_animsys.h" 00053 #include "BKE_action.h" 00054 00055 #include "BIF_gl.h" 00056 00057 #include "ED_armature.h" 00058 #include "ED_keyframes_draw.h" 00059 00060 #include "BLF_api.h" 00061 00062 #include "UI_resources.h" 00063 00064 #include "view3d_intern.h" 00065 00066 /* ************************************ Motion Paths ************************************* */ 00067 00068 // TODO: 00069 // - options to draw paths with lines 00070 // - include support for editing the path verts 00071 00072 /* Set up drawing environment for drawing motion paths */ 00073 void draw_motion_paths_init(View3D *v3d, ARegion *ar) 00074 { 00075 RegionView3D *rv3d= ar->regiondata; 00076 00077 if (v3d->zbuf) glDisable(GL_DEPTH_TEST); 00078 00079 glPushMatrix(); 00080 glLoadMatrixf(rv3d->viewmat); 00081 } 00082 00083 /* Draw the given motion path for an Object or a Bone 00084 * - assumes that the viewport has already been initialised properly 00085 * i.e. draw_motion_paths_init() has been called 00086 */ 00087 void draw_motion_path_instance(Scene *scene, 00088 Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath) 00089 { 00090 //RegionView3D *rv3d= ar->regiondata; 00091 bMotionPathVert *mpv, *mpv_start; 00092 int i, stepsize= avs->path_step; 00093 int sfra, efra, len; 00094 00095 00096 /* get frame ranges */ 00097 if (avs->path_type == MOTIONPATH_TYPE_ACFRA) { 00098 int sind; 00099 00100 /* With "Around Current", we only choose frames from around 00101 * the current frame to draw. However, this range is still 00102 * restricted by the limits of the original path. 00103 */ 00104 sfra= CFRA - avs->path_bc; 00105 efra= CFRA + avs->path_ac; 00106 if (sfra < mpath->start_frame) sfra= mpath->start_frame; 00107 if (efra > mpath->end_frame) efra= mpath->end_frame; 00108 00109 len= efra - sfra; 00110 00111 sind= sfra - mpath->start_frame; 00112 mpv_start= (mpath->points + sind); 00113 } 00114 else { 00115 sfra= mpath->start_frame; 00116 efra = sfra + mpath->length; 00117 len = mpath->length; 00118 mpv_start= mpath->points; 00119 } 00120 00121 if(len <= 0) { 00122 return; 00123 } 00124 00125 /* draw curve-line of path */ 00126 glShadeModel(GL_SMOOTH); 00127 00128 glBegin(GL_LINE_STRIP); 00129 for (i=0, mpv=mpv_start; i < len; i++, mpv++) { 00130 short sel= (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT); 00131 float intensity; /* how faint */ 00132 00133 /* set color 00134 * - more intense for active/selected bones, less intense for unselected bones 00135 * - black for before current frame, green for current frame, blue for after current frame 00136 * - intensity decreases as distance from current frame increases 00137 */ 00138 #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max-min)) + min) 00139 if ((sfra+i) < CFRA) { 00140 /* black - before cfra */ 00141 if (sel) { 00142 // intensity= 0.5f; 00143 intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f); 00144 } 00145 else { 00146 //intensity= 0.8f; 00147 intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f); 00148 } 00149 UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity); 00150 } 00151 else if ((sfra+i) > CFRA) { 00152 /* blue - after cfra */ 00153 if (sel) { 00154 //intensity = 0.5f; 00155 intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f); 00156 } 00157 else { 00158 //intensity = 0.8f; 00159 intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f); 00160 } 00161 UI_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity); 00162 } 00163 else { 00164 /* green - on cfra */ 00165 if (sel) { 00166 intensity= 0.5f; 00167 } 00168 else { 00169 intensity= 0.99f; 00170 } 00171 UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10); 00172 } 00173 00174 /* draw a vertex with this color */ 00175 glVertex3fv(mpv->co); 00176 } 00177 00178 glEnd(); 00179 glShadeModel(GL_FLAT); 00180 00181 glPointSize(1.0); 00182 00183 /* draw little black point at each frame 00184 * NOTE: this is not really visible/noticable 00185 */ 00186 glBegin(GL_POINTS); 00187 for (i=0, mpv=mpv_start; i < len; i++, mpv++) 00188 glVertex3fv(mpv->co); 00189 glEnd(); 00190 00191 /* Draw little white dots at each framestep value */ 00192 UI_ThemeColor(TH_TEXT_HI); 00193 glBegin(GL_POINTS); 00194 for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) 00195 glVertex3fv(mpv->co); 00196 glEnd(); 00197 00198 /* Draw big green dot where the current frame is */ 00199 // NOTE: only do this when drawing keyframes for now... 00200 if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) { 00201 UI_ThemeColor(TH_CFRAME); 00202 glPointSize(6.0f); 00203 00204 glBegin(GL_POINTS); 00205 mpv = mpv_start + (CFRA - sfra); 00206 glVertex3fv(mpv->co); 00207 glEnd(); 00208 00209 glPointSize(1.0f); 00210 UI_ThemeColor(TH_TEXT_HI); 00211 } 00212 00213 // XXX, this isnt up to date but probably should be kept so. 00214 invert_m4_m4(ob->imat, ob->obmat); 00215 00216 /* Draw frame numbers at each framestep value */ 00217 if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) { 00218 unsigned char col[4]; 00219 UI_GetThemeColor3ubv(TH_TEXT_HI, col); 00220 col[3]= 255; 00221 00222 for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) { 00223 char str[32]; 00224 float co[3]; 00225 00226 /* only draw framenum if several consecutive highlighted points don't occur on same point */ 00227 if (i == 0) { 00228 sprintf(str, "%d", (i+sfra)); 00229 mul_v3_m4v3(co, ob->imat, mpv->co); 00230 view3d_cached_text_draw_add(co, str, 0, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, col); 00231 } 00232 else if ((i > stepsize) && (i < len-stepsize)) { 00233 bMotionPathVert *mpvP = (mpv - stepsize); 00234 bMotionPathVert *mpvN = (mpv + stepsize); 00235 00236 if ((equals_v3v3(mpv->co, mpvP->co)==0) || (equals_v3v3(mpv->co, mpvN->co)==0)) { 00237 sprintf(str, "%d", (sfra+i)); 00238 mul_v3_m4v3(co, ob->imat, mpv->co); 00239 view3d_cached_text_draw_add(co, str, 0, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, col); 00240 } 00241 } 00242 } 00243 } 00244 00245 /* Keyframes - dots and numbers */ 00246 if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) { 00247 unsigned char col[4]; 00248 00249 AnimData *adt= BKE_animdata_from_id(&ob->id); 00250 DLRBT_Tree keys; 00251 00252 /* build list of all keyframes in active action for object or pchan */ 00253 BLI_dlrbTree_init(&keys); 00254 00255 if (adt) { 00256 /* it is assumed that keyframes for bones are all grouped in a single group 00257 * unless an option is set to always use the whole action 00258 */ 00259 if ((pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT)==0) { 00260 bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name); 00261 00262 if (agrp) { 00263 agroup_to_keylist(adt, agrp, &keys, NULL); 00264 BLI_dlrbTree_linkedlist_sync(&keys); 00265 } 00266 } 00267 else { 00268 action_to_keylist(adt, adt->action, &keys, NULL); 00269 BLI_dlrbTree_linkedlist_sync(&keys); 00270 } 00271 } 00272 00273 /* Draw slightly-larger yellow dots at each keyframe */ 00274 UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col); 00275 col[3]= 255; 00276 00277 glPointSize(4.0f); // XXX perhaps a bit too big 00278 glColor3ubv(col); 00279 00280 glBegin(GL_POINTS); 00281 for (i=0, mpv=mpv_start; i < len; i++, mpv++) { 00282 float mframe= (float)(sfra + i); 00283 00284 if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) 00285 glVertex3fv(mpv->co); 00286 } 00287 glEnd(); 00288 00289 glPointSize(1.0f); 00290 00291 /* Draw frame numbers of keyframes */ 00292 if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) { 00293 float co[3]; 00294 for (i=0, mpv=mpv_start; i < len; i++, mpv++) { 00295 float mframe= (float)(sfra + i); 00296 00297 if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) { 00298 char str[32]; 00299 00300 sprintf(str, "%d", (sfra+i)); 00301 mul_v3_m4v3(co, ob->imat, mpv->co); 00302 view3d_cached_text_draw_add(co, str, 0, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, col); 00303 } 00304 } 00305 } 00306 00307 BLI_dlrbTree_free(&keys); 00308 } 00309 } 00310 00311 /* Clean up drawing environment after drawing motion paths */ 00312 void draw_motion_paths_cleanup(View3D *v3d) 00313 { 00314 if (v3d->zbuf) glEnable(GL_DEPTH_TEST); 00315 glPopMatrix(); 00316 } 00317 00318 #if 0 // XXX temp file guards 00319 00320 /* ***************************** Onion Skinning (Ghosts) ******************************** */ 00321 00322 #if 0 // XXX only for bones 00323 /* helper function for ghost drawing - sets/removes flags for temporarily 00324 * hiding unselected bones while drawing ghosts 00325 */ 00326 static void ghost_poses_tag_unselected(Object *ob, short unset) 00327 { 00328 bArmature *arm= ob->data; 00329 bPose *pose= ob->pose; 00330 bPoseChannel *pchan; 00331 00332 /* don't do anything if no hiding any bones */ 00333 if ((arm->flag & ARM_GHOST_ONLYSEL)==0) 00334 return; 00335 00336 /* loop over all pchans, adding/removing tags as appropriate */ 00337 for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { 00338 if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { 00339 if (unset) { 00340 /* remove tags from all pchans if cleaning up */ 00341 pchan->bone->flag &= ~BONE_HIDDEN_PG; 00342 } 00343 else { 00344 /* set tags on unselected pchans only */ 00345 if ((pchan->bone->flag & BONE_SELECTED)==0) 00346 pchan->bone->flag |= BONE_HIDDEN_PG; 00347 } 00348 } 00349 } 00350 } 00351 #endif // XXX only for bones 00352 00353 /* draw ghosts that occur within a frame range 00354 * note: object should be in posemode 00355 */ 00356 static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base) 00357 { 00358 Object *ob= base->object; 00359 AnimData *adt= BKE_animdata_from_id(&ob->id); 00360 bArmature *arm= ob->data; 00361 bPose *posen, *poseo; 00362 float start, end, stepsize, range, colfac; 00363 int cfrao, flago, ipoflago; 00364 00365 start = (float)arm->ghostsf; 00366 end = (float)arm->ghostef; 00367 if (end <= start) 00368 return; 00369 00370 stepsize= (float)(arm->ghostsize); 00371 range= (float)(end - start); 00372 00373 /* store values */ 00374 ob->mode &= ~OB_MODE_POSE; 00375 cfrao= CFRA; 00376 flago= arm->flag; 00377 arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); 00378 ipoflago= ob->ipoflag; 00379 ob->ipoflag |= OB_DISABLE_PATH; 00380 00381 /* copy the pose */ 00382 poseo= ob->pose; 00383 copy_pose(&posen, ob->pose, 1); 00384 ob->pose= posen; 00385 armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ 00386 ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ 00387 00388 glEnable(GL_BLEND); 00389 if (v3d->zbuf) glDisable(GL_DEPTH_TEST); 00390 00391 /* draw from first frame of range to last */ 00392 for (CFRA= (int)start; CFRA < end; CFRA += (int)stepsize) { 00393 colfac = (end - (float)CFRA) / range; 00394 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); 00395 00396 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); 00397 where_is_pose(scene, ob); 00398 draw_pose_bones(scene, v3d, ar, base, OB_WIRE); 00399 } 00400 glDisable(GL_BLEND); 00401 if (v3d->zbuf) glEnable(GL_DEPTH_TEST); 00402 00403 ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ 00404 free_pose(posen); 00405 00406 /* restore */ 00407 CFRA= cfrao; 00408 ob->pose= poseo; 00409 arm->flag= flago; 00410 armature_rebuild_pose(ob, ob->data); 00411 ob->mode |= OB_MODE_POSE; 00412 ob->ipoflag= ipoflago; 00413 } 00414 00415 /* draw ghosts on keyframes in action within range 00416 * - object should be in posemode 00417 */ 00418 static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base) 00419 { 00420 Object *ob= base->object; 00421 AnimData *adt= BKE_animdata_from_id(&ob->id); 00422 bAction *act= (adt) ? adt->action : NULL; 00423 bArmature *arm= ob->data; 00424 bPose *posen, *poseo; 00425 DLRBT_Tree keys; 00426 ActKeyColumn *ak, *akn; 00427 float start, end, range, colfac, i; 00428 int cfrao, flago; 00429 00430 start = (float)arm->ghostsf; 00431 end = (float)arm->ghostef; 00432 if (end <= start) 00433 return; 00434 00435 /* get keyframes - then clip to only within range */ 00436 BLI_dlrbTree_init(&keys); 00437 action_to_keylist(adt, act, &keys, NULL); 00438 BLI_dlrbTree_linkedlist_sync(&keys); 00439 00440 range= 0; 00441 for (ak= keys.first; ak; ak= akn) { 00442 akn= ak->next; 00443 00444 if ((ak->cfra < start) || (ak->cfra > end)) 00445 BLI_freelinkN((ListBase *)&keys, ak); 00446 else 00447 range++; 00448 } 00449 if (range == 0) return; 00450 00451 /* store values */ 00452 ob->mode &= ~OB_MODE_POSE; 00453 cfrao= CFRA; 00454 flago= arm->flag; 00455 arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); 00456 ob->ipoflag |= OB_DISABLE_PATH; 00457 00458 /* copy the pose */ 00459 poseo= ob->pose; 00460 copy_pose(&posen, ob->pose, 1); 00461 ob->pose= posen; 00462 armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ 00463 ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ 00464 00465 glEnable(GL_BLEND); 00466 if (v3d->zbuf) glDisable(GL_DEPTH_TEST); 00467 00468 /* draw from first frame of range to last */ 00469 for (ak=keys.first, i=0; ak; ak=ak->next, i++) { 00470 colfac = i/range; 00471 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); 00472 00473 CFRA= (int)ak->cfra; 00474 00475 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); 00476 where_is_pose(scene, ob); 00477 draw_pose_bones(scene, v3d, ar, base, OB_WIRE); 00478 } 00479 glDisable(GL_BLEND); 00480 if (v3d->zbuf) glEnable(GL_DEPTH_TEST); 00481 00482 ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ 00483 BLI_dlrbTree_free(&keys); 00484 free_pose(posen); 00485 00486 /* restore */ 00487 CFRA= cfrao; 00488 ob->pose= poseo; 00489 arm->flag= flago; 00490 armature_rebuild_pose(ob, ob->data); 00491 ob->mode |= OB_MODE_POSE; 00492 } 00493 00494 /* draw ghosts around current frame 00495 * - object is supposed to be armature in posemode 00496 */ 00497 static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) 00498 { 00499 Object *ob= base->object; 00500 AnimData *adt= BKE_animdata_from_id(&ob->id); 00501 bArmature *arm= ob->data; 00502 bPose *posen, *poseo; 00503 float cur, start, end, stepsize, range, colfac, actframe, ctime; 00504 int cfrao, flago; 00505 00506 /* pre conditions, get an action with sufficient frames */ 00507 if ELEM(NULL, adt, adt->action) 00508 return; 00509 00510 calc_action_range(adt->action, &start, &end, 0); 00511 if (start == end) 00512 return; 00513 00514 stepsize= (float)(arm->ghostsize); 00515 range= (float)(arm->ghostep)*stepsize + 0.5f; /* plus half to make the for loop end correct */ 00516 00517 /* store values */ 00518 ob->mode &= ~OB_MODE_POSE; 00519 cfrao= CFRA; 00520 actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); 00521 flago= arm->flag; 00522 arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); 00523 00524 /* copy the pose */ 00525 poseo= ob->pose; 00526 copy_pose(&posen, ob->pose, 1); 00527 ob->pose= posen; 00528 armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ 00529 ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ 00530 00531 glEnable(GL_BLEND); 00532 if (v3d->zbuf) glDisable(GL_DEPTH_TEST); 00533 00534 /* draw from darkest blend to lowest */ 00535 for(cur= stepsize; cur<range; cur+=stepsize) { 00536 ctime= cur - (float)fmod(cfrao, stepsize); /* ensures consistent stepping */ 00537 colfac= ctime/range; 00538 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); 00539 00540 /* only within action range */ 00541 if (actframe+ctime >= start && actframe+ctime <= end) { 00542 CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP); 00543 00544 if (CFRA != cfrao) { 00545 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); 00546 where_is_pose(scene, ob); 00547 draw_pose_bones(scene, v3d, ar, base, OB_WIRE); 00548 } 00549 } 00550 00551 ctime= cur + (float)fmod((float)cfrao, stepsize) - stepsize+1.0f; /* ensures consistent stepping */ 00552 colfac= ctime/range; 00553 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); 00554 00555 /* only within action range */ 00556 if ((actframe-ctime >= start) && (actframe-ctime <= end)) { 00557 CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP); 00558 00559 if (CFRA != cfrao) { 00560 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); 00561 where_is_pose(scene, ob); 00562 draw_pose_bones(scene, v3d, ar, base, OB_WIRE); 00563 } 00564 } 00565 } 00566 glDisable(GL_BLEND); 00567 if (v3d->zbuf) glEnable(GL_DEPTH_TEST); 00568 00569 ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ 00570 free_pose(posen); 00571 00572 /* restore */ 00573 CFRA= cfrao; 00574 ob->pose= poseo; 00575 arm->flag= flago; 00576 armature_rebuild_pose(ob, ob->data); 00577 ob->mode |= OB_MODE_POSE; 00578 } 00579 00580 00581 00582 #endif // XXX temp file guards