1 /**
2 *** キャラクタアニメーションのための人体モデルの表現・基本処理 ライブラリ・サンプルプログラム 3 *** Copyright (c) 2015-, Masaki OSHITA (www.oshita-lab.org)
4 *** Released under the MIT license http://opensource.org/licenses/mit-license.php 5 **/ 6 7 /** 8 *** 複数の基本デモのアプリケーション 9 *** (レポート課題の作成・提出が行いやすいように、全てのデモを一つのソースファイルにまとめたもの) 10 **/ 11 12 13 // Windows関数定義の読み込み 14 #ifdef WIN32 15 #include <windows.h> 16 #endif 17 18 // GLUT を使用 19 #include <GL/glut.h> 20 21 // 22 // 行列・ベクトルの表現には vecmath C++ライブラリ(http://objectclub.jp/download/vecmath1)を使用 23 // 24 #include <Vector3.h> 25 #include <Point3.h> 26 #include <Matrix3.h> 27 #include <Matrix4.h> 28 #include <Color3.h> 29 30 // STL を使用 31 #include <vector> 32 #include <string> 33 using namespace std; 34 35 // 標準算術関数・定数の定義 36 #define _USE_MATH_DEFINES 37 #include <math.h> 38 39 40 // ライブラリ・クラス定義の読み込み 41 #include "SimpleHuman.h" 42 #include "SimpleHumanGLUT.h" 43 #include "BVH.h" 44 45 46 47 /////////////////////////////////////////////////////////////////////////////// 48 // 49 // 動作再生アプリケーション 50 // 51 52 53 // 54 // 動作再生アプリケーションクラス 55 //
56 class MotionPlaybackApp : public GLUTBaseApp 57 { 58 protected: 59 // キャラクタ情報 60 61 // キャラクタの骨格 62 Skeleton * body; 63 64 // キャラクタの姿勢 65 Posture * curr_posture; 66 67 protected: 68 // 動作再生のための変数 69 70 // 動作データ 71 Motion * motion; 72 73 // アニメーション再生中かどうかを表すフラグ 74 bool on_animation; 75 76 // アニメーションの再生時間 77 float animation_time; 78 79 // アニメーションの再生速度 80 float animation_speed; 81 82 // 現在の表示フレーム番号 83 int frame_no; 84 85 public: 86 // コンストラクタ 87 MotionPlaybackApp(); 88 89 // デストラクタ 90 virtual ~MotionPlaybackApp(); 91 92 public: 93 // イベント処理 94 95 // 初期化
96 virtual void Initialize(); 97
98 // 開始・リセット
99 virtual void Start(); 100
101 // 画面描画
102 virtual void Display(); 103
104 // キーボードのキー押下
105 virtual void Keyboard( unsigned char key, int mx, int my ); 106
107 // アニメーション処理
109
110 public:
111 // 補助処理
112
113 // BVH動作ファイルの読み込み、骨格・姿勢の初期化
114 void LoadBVH( const char * file_name ); 115 116 // ファイルダイアログを表示してBVH動作ファイルを選択・読み込み 117 void OpenNewBVH(); 118 }; 119 120 121 // 122 // コンストラクタ 123 // 124 MotionPlaybackApp::MotionPlaybackApp() 125 {
126 app_name = "Motion Playback"; 127 body = NULL; 128 curr_posture = NULL; 129 motion = NULL; 130 on_animation = true; 131 animation_time = 0.0f; 132 animation_speed = 1.0f; 133 frame_no = 0; 134 } 135 136 137 // 138 // デストラクタ 139 // 140 MotionPlaybackApp::~MotionPlaybackApp() 141 { 142 if ( motion ) 143 delete motion; 144 if ( curr_posture ) 145 delete curr_posture; 146 if ( body ) 147 delete body; 148 } 149 150 151 // 152 // 初期化 153 // H3 void MotionPlaybackApp::Initialize() 155 { 156 GLUTBaseApp::Initialize(); 157 158 // サンプルBVH動作データを読み込み 159 LoadBVH( "sample_walking1.bvh" ); 160 } 161 162 163 // 164 // 開始・リセット 165 // H3 void MotionPlaybackApp::Start() 167 { 168 GLUTBaseApp::Start(); 169 170 on_animation = true; 171 animation_time = 0.0f; 172 frame_no = 0; 173 174 Animation( 0.0f ); 175 } 176 177 178 // 179 // 画面描画 180 // H3 void MotionPlaybackApp::Display() 182 { 183 GLUTBaseApp::Display(); 184 185 // キャラクタを描画 186 if ( curr_posture ) 187 { 188 glColor3f( 1.0f, 1.0f, 1.0f ); 189 DrawPosture( *curr_posture );
190 DrawPostureShadow( *curr_posture, shadow_dir, shadow_color );
191 }
192
193 // 現在のモード、時間・フレーム番号を表示
194 DrawTextInformation( 0, "Motion Playback" ); 195 char message[64];
196 if ( motion )
197 sprintf( message, "%.2f (%d)", animation_time, frame_no ); 198 else
199 sprintf( message, "Press 'L' key to Load a BVH file" ); 200 DrawTextInformation( 1, message ); 201 } 202 203 204 // 205 // キーボードのキー押下 206 //
H3 void MotionPlaybackApp::Keyboard( unsigned char key, int mx, int my ) 208 { 209 GLUTBaseApp::Keyboard( key, mx, my ); 210 211 // s キーでアニメーションの停止・再開 212 if ( key == 's' ) 213 on_animation = !on_animation; 214 215 // w キーでアニメーションの再生速度を変更 216 if ( key == 'w' )
217 animation_speed = ( animation_speed == 1.0f ) ? 0.1f : 1.0f; 218
219 // n キーで次のフレーム
220 if ( ( key == 'n' ) && !on_animation && motion )
221 { 222 on_animation = true; 223 Animation( motion->interval ); 224 on_animation = false; 225 } 226 227 // p キーで前のフレーム
228 if ( ( key == 'p' ) && !on_animation && motion && ( frame_no > 0 ) )
229 { 230 on_animation = true; 231 Animation( - motion->interval ); 232 on_animation = false; 233 } 234 235 // l キーで再生動作の変更 236 if ( key == 'l' ) 237 { 238 // ファイルダイアログを表示してBVHファイルを選択・読み込み 239 OpenNewBVH(); 240 } 241 } 242 243 244 // 245 // アニメーション処理 246 //
H3 void MotionPlaybackApp::Animation( float delta ) 248 { 249 // アニメーション再生中でなければ終了 250 if ( !on_animation ) 251 return; 252 253 // 動作データが読み込まれていなければ終了 254 if ( !motion ) 255 return; 256 257 // 時間を進める
258 animation_time += delta * animation_speed; 259 if ( animation_time > motion->GetDuration() ) 260 animation_time -= motion->GetDuration(); 261
262 // 現在のフレーム番号を計算
263 frame_no = animation_time / motion->interval; 264
265 // 動作データから現在時刻の姿勢を取得
266 motion->GetPosture( animation_time, *curr_posture ); 267 } 268 269 270 // 271 // BVH動作ファイルの読み込み、骨格・姿勢の初期化 272 //
H3 void MotionPlaybackApp::LoadBVH( const char * file_name ) 274 { 275 // BVH動作データを読み込み 276 BVH * bvh = new BVH( file_name ); 277 278 // 読み込みに失敗したら終了 279 if ( !bvh->IsLoadSuccess() ) 280 { 281 delete bvh; 282 bvh = NULL; 283 body = NULL; 284 return; 285 } 286 287 // BVH動作から骨格モデルと動作データをを生成 288 motion = CoustructBVHMotion( bvh ); 289 if ( !motion ) 290 return; 291 body = motion->body; 292 delete bvh; 293 294 // 姿勢の初期化 295 if ( curr_posture ) 296 delete curr_posture; 297 curr_posture = new Posture(); 298 InitPosture( *curr_posture, body ); 299 300 // 再生開始 301 Start(); 302 } 303 304 305 // 306 // ファイルダイアログを表示してBVH動作ファイルを選択・読み込み 307 // H3 void MotionPlaybackApp::OpenNewBVH() 309 { 310 #ifdef WIN32
311 const int file_name_len = 256; 312 char file_name[file_name_len] = ""; 313
314 // ファイルダイアログの設定
315 OPENFILENAME open_file;
316 memset( &open_file, 0, sizeof( OPENFILENAME ) ); 317 open_file.lStructSize = sizeof( OPENFILENAME ); 318 open_file.hwndOwner = NULL;
319 open_file.lpstrFilter = "BVH Motion Data (*.bvh)\0*.bvh\0All (*.*)\0*.*\0"; 320 open_file.nFilterIndex = 1;
321 open_file.lpstrFile = file_name; 322 open_file.nMaxFile = file_name_len;
323 open_file.lpstrTitle = "Select a BVH file"; 324 open_file.lpstrDefExt = "bvh";
325 open_file.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 326
327 // ファイルダイアログを表示
328 BOOL ret = GetOpenFileName( &open_file ); 329 330 // ファイルが指定されたら新しい動作を設定 331 if (ret) 332 { 333 // BVH動作データの読み込み、骨格・姿勢の初期化 334 LoadBVH( file_name ); 335 336 // 動作再生の開始 337 Start(); 338 } 339 #endif // WIN32 340 } 341 342 343 344 /////////////////////////////////////////////////////////////////////////////// 345 // 346 // キーフレーム動作再生アプリケーション 347 // 348 349 350 // 351 // キーフレーム動作再生アプリケーションクラス 352 //
353 class KeyframeMotionPlaybackApp : public MotionPlaybackApp 354 { 355 protected: 356 // 動作再生のための変数 357 358 // キーフレーム動作データ 359 KeyframeMotion * keyframe_motion; 360 361 // キーフレーム動作からの取得姿勢 362 Posture * keyframe_posture; 363 364 // キーフレーム動作と元の動作を同期して再生するための時間のオフセット 365 float motion_time_offset; 366 367 protected: 368 // 描画設定 369 370 // 元の動作を並べて再生表示 371 bool draw_original_motion; 372 373 // キーフレームの姿勢を並べて表示 374 bool draw_key_poses; 375 376 377 public: 378 // コンストラクタ 379 KeyframeMotionPlaybackApp(); 380 381 // デストラクタ 382 virtual ~KeyframeMotionPlaybackApp(); 383 384 public: 385 // イベント処理 386 387 // 初期化
388 virtual void Initialize(); 389
390 // 画面描画
391 virtual void Display(); 392
393 // キーボードのキー押下
394 virtual void Keyboard( unsigned char key, int mx, int my ); 395
396 // アニメーション処理
397 virtual void Animation( float delta ); 398 }; 399 400 401 // 補助処理(グローバル関数)のプロトタイプ宣言 402 403 // キーフレーム動作から姿勢を取得
404 void GetKeyframeMotionPosture( const KeyframeMotion & motion, float time, Posture & p ); 405 406 407 // 408 // コンストラクタ 409 // 410 KeyframeMotionPlaybackApp::KeyframeMotionPlaybackApp() 411 {
412 app_name = "Keyframe Motion Playback"; 413 414 keyframe_motion = NULL; 415 keyframe_posture = NULL; 416 motion_time_offset = 0.0f; 417 418 draw_original_motion = true; 419 draw_key_poses = true; 420 } 421 422 423 // 424 // デストラクタ 425 // 426 KeyframeMotionPlaybackApp::~KeyframeMotionPlaybackApp() 427 { 428 if ( keyframe_motion ) 429 delete keyframe_motion; 430 if ( keyframe_posture ) 431 delete keyframe_posture; 432 }
433 434 435 // 436 // 初期化 437 // H3 void KeyframeMotionPlaybackApp::Initialize() 439 { 440 GLUTBaseApp::Initialize(); 441
442 const char * sample_motions = "sample_walking1.bvh"; 443 const int num_keytimes = 3;
444 const float sample_keytimes[ num_keytimes ] = { 2.35f, 3.00f, 3.74f }; 445 446 // BVH動作データを読み込み 447 LoadBVH( sample_motions ); 448 if ( !motion ) 449 return; 450 451 // キーフレームの時刻を設定
452 vector< float > key_times( num_keytimes ); 453 for ( int i=0; i<num_keytimes; i++ )
454 key_times[ i ] = sample_keytimes[ i ] - sample_keytimes[ 0 ]; 455
456 // BVH動作から取得した姿勢をキーフレームの姿勢として設定
457 vector< Posture > key_poses( num_keytimes ); 458 for ( int i=0; i<num_keytimes; i++ )
459 motion->GetPosture( sample_keytimes[ i ], key_poses[ i ] ); 460
461 // キーフレーム動作を初期化
462 keyframe_motion = new KeyframeMotion();
463 keyframe_motion->Init( body, num_keytimes, &key_times.front(), &key_poses.front() ); 464
465 // キーフレーム動作から取得する姿勢の初期化
466 keyframe_posture = new Posture( body ); 467 468 // キーフレーム動作と元の動作を同期して再生するための時間のオフセットを設定 469 motion_time_offset = sample_keytimes[ 0 ]; 470 471 // サンプルBVH動作に合わせて視点調節 472 camera_yaw += 180.0f; 473 } 474 475 476 // 477 // 画面描画 478 // H3 void KeyframeMotionPlaybackApp::Display() 480 { 481 GLUTBaseApp::Display(); 482 483 // キーフレーム動作から取得した姿勢を描画 484 if ( keyframe_posture ) 485 { 486 glColor3f( 1.0f, 1.0f, 1.0f ); 487 DrawPosture( *keyframe_posture );
488 DrawPostureShadow( *keyframe_posture, shadow_dir, shadow_color );
489 }
490
491 // 元のBVH動作から取得した姿勢を描画
492 if ( draw_original_motion && curr_posture )
493 { 494 glPushMatrix(); 495 glTranslatef( 1.0f, 0.0f, 0.0f ); 496 497 glColor3f( 0.0f, 0.0f, 1.0f ); 498 DrawPosture( *curr_posture );
499 DrawPostureShadow( *curr_posture, shadow_dir, shadow_color ); 500 glPopMatrix();
501 }
502
503 // キーフレーム動作のキー姿勢を描画
504 if ( draw_key_poses && keyframe_posture )
505 {
506 glPushMatrix();
507 glTranslatef( - 1.0f, 0.0f, 0.0f ); 508
509 for ( int i=0; i<keyframe_motion->num_keyframes; i++ )
510 { 511 glPushMatrix(); 512 glTranslatef( 0.0f, 0.0f, 1.0f * ( i - ( keyframe_motion->num_keyframes - 1 ) * 0.5f ) ); 513 514 glColor3f( 0.8f, 0.8f, 0.8f ); 515 DrawPosture( keyframe_motion->key_poses[ i ] );
516 DrawPostureShadow( keyframe_motion->key_poses[ i ], shadow_dir, shadow_color ); 517 glPopMatrix(); 518 } 519 glPopMatrix(); 520 } 521 522 // 現在のモード、時間・フレーム番号を表示
523 DrawTextInformation( 0, "Keyframe Motion Playback" ); 524 char message[64];
525 if ( motion )
526 sprintf( message, "%.2f (%d)", animation_time, frame_no ); 527 else
528 sprintf( message, "Press 'L' key to Load a BVH file" ); 529 DrawTextInformation( 1, message ); 530 } 531 532 533 // 534 // キーボードのキー押下 535 //
H3 void KeyframeMotionPlaybackApp::Keyboard( unsigned char key, int mx, int my ) 537 {
538 // 基底クラスの処理を実行
539 MotionPlaybackApp::Keyboard( key, mx, my ); 540
541 // d キーで描画設定を変更 542 if ( key == 'd' )
543 {
544 if ( draw_original_motion && draw_key_poses ) 545 draw_key_poses = false;
546 else if ( draw_original_motion && !draw_key_poses )
547 {
548 draw_original_motion = false; 549 draw_key_poses = true;
550 }
551 else if ( !draw_original_motion && draw_key_poses ) 552 draw_key_poses = false; 553 else 554 { 555 draw_original_motion = true; 556 draw_key_poses = true; 557 } 558 } 559 } 560 561 562 // 563 // アニメーション処理 564 //
H3 void KeyframeMotionPlaybackApp::Animation( float delta ) 566 { 567 // アニメーション再生中でなければ終了 568 if ( !on_animation ) 569 return; 570 571 // 動作データが読み込まれていなければ終了 572 if ( !keyframe_motion ) 573 return; 574 575 // 時間を進める
576 animation_time += delta * animation_speed;
577 if ( animation_time > keyframe_motion->GetDuration() ) 578 animation_time -= keyframe_motion->GetDuration();
579 frame_no = ( animation_time + motion_time_offset ) / motion->interval; 580
581 // 動作データから現在時刻の姿勢を取得
582 motion->GetPosture( animation_time + motion_time_offset, *curr_posture ); 583
584 // キーフレーム動作データから現在時刻の姿勢を取得
585 GetKeyframeMotionPosture( *keyframe_motion, animation_time, *keyframe_posture ); 586 } 587 588 589 // 590 // キーフレーム動作から姿勢を取得 591 //
592 void GetKeyframeMotionPosture( const KeyframeMotion & motion, float time, Posture & p ) 593 {
594 // 指定時刻に対応する区間番号を取得
595 int no = -1;
596 for ( int i=0; i<motion.num_keyframes-1; i++ )
597 {
598 if ( ( time >= motion.key_times[ i ] ) && ( time <= motion.key_times[ i+1 ] ) )
599 { 600 no = i; 601 break; 602 } 603 } 604 if ( no == -1 ) 605 return; 606 607 // ※レポート課題 608 609 // 指定時刻に応じて前後のキー姿勢の補間の割合を計算 610 float s = 0.0f; 611 // s = ???; 612 613 // 前後のキー姿勢を補間 614 // PostureInterpolation( ??? ); 615 p = motion.key_poses[ no ]; 616 } 617 618 619 620 /////////////////////////////////////////////////////////////////////////////// 621 // 622 // 順運動学計算アプリケーション 623 // 624 625 626 // 627 // 順運動学計算アプリケーションクラス 628 // (動作再生アプリケーションに順運動学計算を追加) 629 //
630 class ForwardKinematicsApp : public MotionPlaybackApp 631 {
632 protected:
633 // 順運動学計算結果の変数
634
635 // 全体節の位置・向き(座標系)
636 vector< Matrix4f > segment_frames; 637
638 // 全関節の位置
639 vector< Point3f > joint_positions; 640 641 public: 642 // コンストラクタ 643 ForwardKinematicsApp(); 644 645 public: 646 // イベント処理 647 648 // 開始・リセット
649 virtual void Start(); 650
651 // 画面描画
652 virtual void Display(); 653
654 // アニメーション処理
655 virtual void Animation( float delta ); 656 }; 657 658 659 // 補助処理(グローバル関数)のプロトタイプ宣言 660 661 // 順運動学計算
662 void MyForwardKinematics( const Posture & posture, vector< Matrix4f > & seg_frame_array, vector< Point3f > & joi_pos_array ); 663
664 // 順運動学計算のための反復計算(ルート体節から末端体節に向かって繰り返し再帰呼び出し)
665 void MyForwardKinematicsIteration( const Segment * segment, const Segment * prev_segment, const Posture & posture, 666 Matrix4f * seg_frame_array, Point3f * joi_pos_array = NULL );
667 668 669 670 // 671 // コンストラクタ 672 // 673 ForwardKinematicsApp::ForwardKinematicsApp() 674 {
675 app_name = "Forward Kinematics"; 676 } 677 678 679 // 680 // 開始・リセット 681 // H3 void ForwardKinematicsApp::Start() 683 { 684 MotionPlaybackApp::Start(); 685 686 if ( !body ) 687 return; 688 689 // 配列初期化 690 segment_frames.resize( body->num_segments ); 691 joint_positions.resize( body->num_joints ); 692
693 ForwardKinematics( *curr_posture, segment_frames, joint_positions ); 694 } 695 696 697 // 698 // 画面描画 699 // H3 void ForwardKinematicsApp::Display() 701 { 702 GLUTBaseApp::Display(); 703 704 // キャラクタを描画 705 if ( curr_posture ) 706 { 707 glColor3f( 1.0f, 1.0f, 1.0f ); 708 DrawPosture( *curr_posture );
709 DrawPostureShadow( *curr_posture, shadow_dir, shadow_color );
710 }
711 712
713 // 関節・体節の位置・向きを描画
714
715 const float axis_length = 0.2f; 716 float line_width; 717 Matrix4f frame; 718 719 // デプステストを無効にして、前面に上書きする 720 glDisable( GL_DEPTH_TEST ); 721 722 // 関節点を描画(球を描画)
723 for ( int i=0; i<joint_positions.size(); i++ )
724 {
725 // 関節位置に球を描画
726 const Point3f & pos = joint_positions[ i ]; 727 glColor3f( 0.0f, 0.0f, 1.0f );
728 glPushMatrix();
729 glTranslatef( pos.x, pos.y, pos.z ); 730 glutSolidSphere( 0.025f, 16, 16 ); 731 glPopMatrix();
732 }
733
734 // 体節の座標系を描画(座標軸を描画)
735 glGetFloatv( GL_LINE_WIDTH, &line_width ); 736 glLineWidth( 2.0f );
737 for ( int i=0; i<segment_frames.size(); i++ )
738 {
739
740 glPushMatrix();
741 frame.transpose( segment_frames[ i ] ); 742 glMultMatrixf( & frame.m00 );
743 glBegin( GL_LINES ); 744 glColor3f( 1.0f, 0.0f, 0.0f ); 745 glVertex3f( 0.0f, 0.0f, 0.0f ); 746 glVertex3f( axis_length, 0.0f, 0.0f ); 747 glColor3f( 0.0f, 1.0f, 0.0f ); 748 glVertex3f( 0.0f, 0.0f, 0.0f ); 749 glVertex3f( 0.0f, axis_length, 0.0f ); 750 glColor3f( 0.0f, 0.0f, 1.0f ); 751 glVertex3f( 0.0f, 0.0f, 0.0f ); 752 glVertex3f( 0.0f, 0.0f, axis_length ); 753 glEnd(); 754 glPopMatrix(); 755 } 756 glLineWidth( line_width );
757
758 glEnable( GL_DEPTH_TEST ); 759
760
761 // 現在のモード、時間・フレーム番号を表示
762 DrawTextInformation( 0, "Forward Kinematics" ); 763 char message[64];
764 if ( motion )
765 sprintf( message, "%.2f (%d)", animation_time, frame_no ); 766 else
767 sprintf( message, "Press 'L' key to Load a BVH file" ); 768 DrawTextInformation( 1, message ); 769 } 770 771 772 // 773 // アニメーション処理 774 //
H3 void ForwardKinematicsApp::Animation( float delta ) 776 { 777 MotionPlaybackApp::Animation( delta ); 778 779 // アニメーション再生中でなければ終了 780 if ( !on_animation ) 781 return; 782 783 if ( !curr_posture ) 784 return; 785 786 // 順運動学計算
787 MyForwardKinematics( *curr_posture, segment_frames, joint_positions ); 788 } 789 790 791 // 792 // 順運動学計算 793 //
794 void MyForwardKinematics( const Posture & posture, vector< Matrix4f > & seg_frame_array, vector< Point3f > & joi_pos_array ) 795 { 796 // 配列初期化 797 seg_frame_array.resize( posture.body->num_segments ); 798 joi_pos_array.resize( posture.body->num_joints ); 799 800 // ルート体節の位置・向きを設定
801 seg_frame_array[ 0 ].set( posture.root_ori, posture.root_pos, 1.0f ); 802
803 // Forward Kinematics 計算のための反復計算(ルート体節から末端体節に向かって繰り返し計算)
804 MyForwardKinematicsIteration( posture.body->segments[ 0 ], NULL, posture, &seg_frame_array.front(), &joi_pos_array.front() ); 805 } 806 807 808 // 809 // Forward Kinematics 計算のための反復計算(ルート体節から末端体節に向かって繰り返し再帰呼び出し) 810 // H3 void MyForwardKinematicsIteration(
812 const Segment * segment, const Segment * prev_segment, const Posture & posture, 813 Matrix4f * seg_frame_array, Point3f * joi_pos_array )
814 {
815 const Skeleton * body = posture.body; 816 Joint * next_joint;
817 Segment * next_segment; 818 Matrix4f mat;
819
820 // 現在の体節に接続している各関節に対して繰り返し
821 for ( int j=0; j<segment->joints.size(); j++ )
822 { 823 // 次の関節・次の体節を取得 824 next_joint = segment->joints[ j ]; 825 if ( next_joint->segments[ 0 ] != segment ) 826 next_segment = next_joint->segments[ 0 ]; 827 else 828 next_segment = next_joint->segments[ 1 ]; 829 830 // 前の体節側(ルート体節側)の関節はスキップ 831 if ( next_segment == prev_segment ) 832 continue; 833 834 // 現在の体節の変換行列を取得
835 mat = seg_frame_array[ segment->index ]; 836 837 // 次の関節・体節の変換行列を計算 838 839 // ※ レポート課題 840 841 // 次の関節の位置を設定 842 // if ( joi_pos_array ) 843 // joi_pos_array[ next_joint->index ] = ???; 844 845 // 次の体節の変換行列を設定 846 // if ( seg_frame_array ) 847 // seg_frame_array[ next_segment->index ] = ???; 848 849 // 次の体節に対して繰り返し(再帰呼び出し)
850 MyForwardKinematicsIteration( next_segment, segment, posture, seg_frame_array, joi_pos_array );
851 } 852 } 853 854 855 856 /////////////////////////////////////////////////////////////////////////////// 857 // 858 // 姿勢補間アプリケーション 859 // 860 861 862 // 863 // 姿勢補間アプリケーションクラス 864 //
865 class PostureInterpolationApp : public GLUTBaseApp 866 { 867 protected: 868 // キャラクタ情報 869 870 // キャラクタの骨格 871 Skeleton * body; 872 873 // キャラクタの姿勢 874 Posture * curr_posture; 875 876 protected: 877 // 姿勢補間のための変数 878 879 // サンプル姿勢 880 Posture * posture0; 881 Posture * posture1; 882 883 // サンプル姿勢の描画色 884 Color3f posture0_color; 885 Color3f posture1_color; 886 887 // 姿勢補間の重み 888 float weight; 889 890 // 現在姿勢の描画色 891 Color3f figure_color; 892 893 public: 894 // コンストラクタ 895 PostureInterpolationApp(); 896 897 // デストラクタ 898 virtual ~PostureInterpolationApp(); 899 900 public: 901 // イベント処理 902 903 // 初期化
904 virtual void Initialize(); 905
906 // 開始・リセット 907 virtual void Start(); 908
909 // 画面描画
910 virtual void Display(); 911
912 // マウスドラッグ
913 virtual void MouseDrag( int mx, int my ); 914 915 public: 916 // 補助処理 917 918 // 姿勢更新 919 void UpdatePosture(); 920 }; 921 922 923 // 補助処理(グローバル関数)のプロトタイプ宣言 924 925 // 姿勢補間(2つの姿勢を補間)
926 void PostureInterpolation( const Posture & p0, const Posture & p1, float ratio, Posture & p ); 927 928 929 930 // 931 // コンストラクタ 932 // 933 PostureInterpolationApp::PostureInterpolationApp() 934 {
935 app_name = "Posture Interpolation"; 936 body = NULL; 937 curr_posture = NULL; 938 939 posture0 = NULL; 940 posture1 = NULL; 941 weight = 0.0f; 942 figure_color.set( 1.0f, 1.0f, 1.0f ); 943 } 944 945 946 // 947 // デストラクタ 948 // 949 PostureInterpolationApp::~PostureInterpolationApp() 950 { 951 } 952 953 954 // 955 // 初期化 956 // H3 void PostureInterpolationApp::Initialize() 958 { 959 GLUTBaseApp::Initialize(); 960 961 // アプリケーションのテストに使用するサンプル姿勢(動作データ・時刻・描画色)
962 const char * sample_motion = "sample_walking1.bvh"; 963 const float sample_keytimes[ 2 ] = { 3.00f, 3.74f };
964 const Color3f sample_colors[] = { Color3f( 0.5f, 1.0f, 0.5f ), Color3f( 0.5f, 0.5f, 1.0f ) }; 965 const float sample_orientation[ 2 ] = { 180.0f, 180.0f };
966 967 // 動作データの読み込み、骨格・姿勢の初期化 968 BVH * bvh = new BVH( sample_motion ); 969 if ( bvh->IsLoadSuccess() ) 970 { 971 // BVH動作から骨格モデルを生成
973
974 // 姿勢の初期化
975 if ( new_body )
976 {
977 body = new_body;
978 curr_posture = new Posture(); 979 InitPosture( *curr_posture, body );
980 }
981 }
982
983 // サンプル姿勢の初期化
984 if ( body && curr_posture && bvh && bvh->IsLoadSuccess() )
985 {
986 // サンプル姿勢を動作データから取得
987 posture0 = new Posture( body ); 988 posture1 = new Posture( body );
989 GetBVHPosture( bvh, sample_keytimes[ 0 ] / bvh->GetInterval(), *posture0 ); 990 GetBVHPosture( bvh, sample_keytimes[ 1 ] / bvh->GetInterval(), *posture1 ); 991 posture0_color = sample_colors[ 0 ]; 992 posture1_color = sample_colors[ 1 ]; 993 994 // 水平方向の回転が指定されていれば回転を適用 995 Matrix3f rot; 996 if ( sample_orientation[ 0 ] != 0.0f ) 997 {
998 rot.rotY( sample_orientation[ 0 ] * M_PI / 180.0f ); 999 posture0->root_ori.mul( rot, posture0->root_ori );
1000 }
1001 if ( sample_orientation[ 1 ] != 0.0f )
1002 {
1003 rot.rotY( sample_orientation[ 1 ] * M_PI / 180.0f ); 1004 posture1->root_ori.mul( rot, posture1->root_ori );
1005 } 1006 1007 // サンプル姿勢を描画する位置を設定(現在姿勢の左右に配置) 1008 posture0->root_pos.x = -1.0f; 1009 posture0->root_pos.z = 0.0f; 1010 posture1->root_pos.x = 1.0f; 1011 posture1->root_pos.z = 0.0f; 1012 1013 // 現在姿勢を初期化 1014 *curr_posture = *posture0; 1015 } 1016 } 1017 1018 1019 // 1020 // 開始・リセット 1021 // H3 void PostureInterpolationApp::Start() 1023 { 1024 GLUTBaseApp::Start(); 1025 1026 // 重みの初期化 1027 weight = 0.5f; 1028 1029 // 姿勢更新 1030 UpdatePosture(); 1031 } 1032 1033 1034 // 1035 // 画面描画 1036 // H3 void PostureInterpolationApp::Display() 1038 { 1039 GLUTBaseApp::Display(); 1040 1041 // キャラクタを描画 1042 if ( curr_posture ) 1043 {
1044 glColor3f( figure_color.x, figure_color.y, figure_color.z ); 1045 DrawPosture( *curr_posture );
1046 DrawPostureShadow( *curr_posture, shadow_dir, shadow_color ); 1047 }
1048
1049 // サンプル姿勢を描画
1050 if ( posture0 ) 1051 {
1052 glColor3f( posture0_color.x, posture0_color.y, posture0_color.z ); 1053 DrawPosture( *posture0 );
1054 DrawPostureShadow( *posture0, shadow_dir, shadow_color ); 1055 }
1056 if ( posture1 ) 1057 {
1058 glColor3f( posture1_color.x, posture1_color.y, posture1_color.z ); 1059 DrawPosture( *posture1 );
1060 DrawPostureShadow( *posture1, shadow_dir, shadow_color ); 1061 }
1062
1063 // 現在のモード、補間重みを表示
1064 DrawTextInformation( 0, "Posture Interpolation" ); 1065 char message[ 64 ];
1066 sprintf( message, "Weight: %.2f", weight ); 1067 DrawTextInformation( 1, message ); 1068 } 1069 1070 1071 // 1072 // マウスドラッグ 1073 //
H3 void PostureInterpolationApp::MouseDrag( int mx, int my ) 1075 {
1076 // 左ボタンの左右ドラッグに応じて重みを計算
1077 if ( drag_mouse_l ) 1078 {
1079 // 重み計算
1081 if ( weight < 0.0f ) 1082 weight = 0.0f; 1083 if ( weight > 1.0f ) 1084 weight = 1.0f; 1085 1086 // 姿勢更新 1087 UpdatePosture(); 1088 } 1089 1090 GLUTBaseApp::MouseDrag( mx, my ); 1091 } 1092 1093 1094 // 1095 // 姿勢更新 1096 // H3 void PostureInterpolationApp::UpdatePosture() 1098 {
1099 if ( !curr_posture || !posture0 || !posture1 ) 1100 return;
1101
1102 // 姿勢補間
1103 PostureInterpolation( *posture0, *posture1, weight, *curr_posture ); 1104 1105 // 腰の水平位置は原点に固定 1106 curr_posture->root_pos.x = 0.0f; 1107 curr_posture->root_pos.z = 0.0f; 1108 1109 // 重みに応じて描画色を設定
1110 figure_color.scaleAdd( weight, posture1_color - posture0_color, posture0_color ); 1111 } 1112 1113 1114 // 1115 // 姿勢補間(2つの姿勢を補間) 1116 //
1117 void PostureInterpolation( const Posture & p0, const Posture & p1, float ratio, Posture & p ) 1118 {
1119 // 2つの姿勢の骨格モデルが異なる場合は終了
1120 if ( ( p0.body != p1.body ) || ( p0.body != p.body ) ) 1121 return;
1122
1123 // 骨格モデルを取得
1124 const Skeleton * body = p0.body; 1125
1126 // 2つの姿勢の各関節の回転を補間
1127 for ( int i = 0; i<body->num_joints; i++ ) 1128 { 1129 // ※ レポート課題 1130 } 1131 1132 // 2つの姿勢のルートの向きを補間 1133 // ※ レポート課題 1134 1135 // 2つの姿勢のルートの位置を補間 1136 // ※ レポート課題 1137 1138 p = p0; 1139 1140 } 1141 1142 1143 1144 /////////////////////////////////////////////////////////////////////////////// 1145 // 1146 // 動作遷移・接続アプリケーション 1147 // 1148 1149 1150 // 1151 // 動作のメタ情報を表す構造体 1152 // 1153 struct MotionInfo 1154 { 1155 // 動作情報 1156 Motion * motion; 1157 1158 // 動作の開始・終了時刻(動作のローカル時間) 1159 float begin_time; 1160 float end_time; 1161 1162 // 動作接続・遷移のためのブレンド区間の終了・開始時刻(動作のローカル時間)
1163 //( begin_time <= blend_end_time < blend_begin_time <= end_time ) 1164 float blend_end_time;
1165 float blend_begin_time; 1166
1167 // キーフレーム配列 [キーフレーム番号]
1168 vector< float > keytimes; 1169 1170 // 描画色 1171 Color3f color; 1172 }; 1173 1174 1175 // 動作のメタ情報を初期化
1176 void InitMotionInfo( MotionInfo * info, Motion * m = NULL ); 1177
1178 // サンプル動作セットの読み込み
1179 Skeleton * LoadSampleMotions( vector< MotionInfo * > & motion_list, Skeleton * body = NULL ); 1180 1181 1182 1183 // 1184 // 動作遷移・接続アプリケーションクラス 1185 //
1186 class MotionTransitionApp : public GLUTBaseApp 1187 {
1189 // キャラクタ情報 1190 1191 // キャラクタの骨格 1192 Skeleton * body; 1193 1194 // キャラクタの姿勢 1195 Posture * curr_posture; 1196 1197 protected: 1198 // 動作データの情報 1199 1200 // 動作データリスト(動作遷移・補間用の複数の動作)
1201 vector< MotionInfo * > motion_list; 1202 1203 protected: 1204 // 動作再生のための変数 1205 1206 // 現在の再生動作データ 1207 Motion * curr_motion; 1208 1209 // アニメーション中かどうかを表すフラグ 1210 bool on_animation; 1211 1212 // アニメーションの再生時間 1213 float animation_time; 1214 1215 // アニメーションの再生速度 1216 float animation_speed; 1217 1218 // 現在の表示フレーム番号 1219 int frame_no; 1220 1221 // 現在姿勢の描画色 1222 Color3f figure_color; 1223 1224 protected: 1225 // 動作再生(動作遷移・接続)の入力 1226 1227 // 現在の再生動作番号 1228 int curr_motion_no; 1229 1230 // 次の再生動作番号 1231 int next_motion_no; 1232 1233 // 次の再生動作 実行待ちの再生動作番号 1234 int waiting_motion_no; 1235 1236 // 動作接続(位置・向き合わせ)を適用するかどうかの設定 1237 bool enable_connection; 1238 1239 // 動作遷移(前後の動作のブレンディング)を適用するかどうかの設定 1240 bool enable_transition; 1241 1242 protected: 1243 // 動作接続のための変数 1244 1245 // 現在の再生動作の位置・向きを合わせるための変換行列 1246 Matrix4f curr_motion_mat; 1247 1248 // 現在の動作の再生開始時刻(グローバル時刻) 1249 float curr_start_frame; 1250 1251 protected: 1252 // 動作遷移のための変数 1253 1254 // 動作遷移のブレンド中かどうかのフラグ 1255 bool on_motion_transition; 1256 1257 // 次の再生動作の位置・向きを合わせるための変換行列 1258 Matrix4f next_motion_mat; 1259 1260 // 次の動作の姿勢(動作遷移時のブレンド用) 1261 Posture * next_motion_posture; 1262 1263 1264 public: 1265 // コンストラクタ 1266 MotionTransitionApp(); 1267 1268 // デストラクタ 1269 virtual ~MotionTransitionApp(); 1270 1271 public: 1272 // イベント処理 1273 1274 // 初期化
1275 virtual void Initialize(); 1276
1277 // 開始・リセット 1278 virtual void Start(); 1279
1280 // 画面描画
1281 virtual void Display(); 1282
1283 // マウスクリック
1284 virtual void MouseClick( int button, int state, int mx, int my ); 1285
1286 // キーボードのキー押下
1287 virtual void Keyboard( unsigned char key, int mx, int my ); 1288
1289 // キーボードの特殊キー押下
1290 virtual void KeyboardSpecial( unsigned char key, int mx, int my ); 1291
1292 // アニメーション処理
1293 virtual void Animation( float delta ); 1294
1295 public: 1296 // 補助処理
1297
1298 // 次の動作を変更
1299 void SetNextMotion( int no = -1 ); 1300
1301 // 動作再生処理(動作接続を考慮、動作遷移は考慮しない)
1302 void AnimationWithConnection( float delta ); 1303
1304 // 動作再生処理(動作接続・遷移を考慮)
1305 void AnimationWithConnectionTransition( float delta ); 1306 }; 1307 1308 1309 // 補助処理(グローバル関数)のプロトタイプ宣言 1310 1311 // 姿勢補間(2つの姿勢を補間)
1312 void PostureInterpolation( const Posture & p0, const Posture & p1, float ratio, Posture & p ); 1313
1314 // 変換行列の水平向き(方位角)成分を計算
1315 float ComputeOrientation( const Matrix3f & ori ); 1316
1317 // 2つの姿勢の位置・向きを合わせるための変換行列を計算
1318 //(next_frame の位置・向きを、prev_frame の位置向きに合わせるための変換行列 trans_mat を計算)
1319 void ComputeConnectionTransformation( const Matrix4f & prev_frame, const Matrix4f & next_frame, Matrix4f & trans_mat ); 1320
1321 // 姿勢の位置・向きに変換行列を適用
1322 void TransformPosture( const Matrix4f & trans, Posture & posture ); 1323 1324 1325 1326 // 1327 // 動作のメタ情報を初期化 1328 //
H3 void InitMotionInfo( MotionInfo * info, Motion * m ) 1330 {
1331 info->motion = m;
1332 info->begin_time = 0.0f;
1333 info->end_time = info->motion ? info->motion->GetDuration() : 0.0f; 1334 info->blend_end_time = info->begin_time; 1335 info->blend_begin_time = info->end_time; 1336 } 1337 1338 1339 // 1340 // サンプル動作セットの読み込み 1341 //
1342 Skeleton * LoadSampleMotions( vector< MotionInfo * > & motion_list, Skeleton * body ) 1343 {
1344 // アプリケーションのテストに使用する動作データの定義(BVHファイル名・キー時刻・描画色)
1345 // 各歩行動作の、右足が地面から離れる、右足が着く、左足が離れる、左足が着く、右足が離れるの5つのキー時刻を設定
1346 const int num_motions = 2; 1347 const int num_keytimes = 5;
1348 const char * sample_motions[ num_motions ] = { 1349 "sample_walking1.bvh",
1350 "sample_walking2.bvh" };
1351 const float sample_keytimes[ num_motions ][ num_keytimes ] = { 1352 { 2.35f, 3.00f, 3.08f, 3.68f, 3.74f },
1353 { 1.30f, 2.07f, 2.12f, 2.88f, 2.94f } 1354 };
1355 const Color3f sample_colors[] = {
1356 Color3f( 0.5f, 1.0f, 0.5f ), Color3f( 0.5f, 0.5f, 1.0f ), 1357 };
1358
1359 MotionInfo * info = NULL; 1360
1361 // 動作データの読み込み、動作情報の設定
1362 for ( int i=0; i<num_motions; i++ ) 1363 {
1364 // BVH動作ファイルの読み込み
1365 BVH * new_bvh = new BVH( sample_motions[ i ] ); 1366 if ( !new_bvh || !new_bvh->IsLoadSuccess() )
1367 continue;
1368
1369 // 骨格モデル・動作情報の生成(骨格モデルの生成は最初の一度のみ)
1370 Motion * new_motion = CoustructBVHMotion( new_bvh, body ); 1371 if ( !new_motion ) 1372 continue; 1373 if ( !body ) 1374 body = new_motion->body; 1375 1376 // 動作のメタ情報の設定
1377 info = new MotionInfo();
1378 InitMotionInfo( info, new_motion ); 1379 for ( int j=0; j<num_keytimes; j++ )
1380 info->keytimes.push_back( sample_keytimes[ i ][ j ] ); 1381 info->begin_time = info->keytimes[ 0 ];
1382 info->blend_end_time = info->keytimes[ 1 ];
1383 info->blend_begin_time = info->keytimes[ info->keytimes.size() - 2 ]; 1384 info->end_time = info->keytimes[ info->keytimes.size() - 1 ];
1385 info->color = sample_colors[ i ]; 1386 1387 // 動作リストに追加 1388 motion_list.push_back( info ); 1389 } 1390 1391 return body; 1392 } 1393 1394 1395 // 1396 // コンストラクタ 1397 // 1398 MotionTransitionApp::MotionTransitionApp() 1399 {
1400 app_name = "Motion Transition"; 1401
1402 body = NULL;
1403 curr_posture = NULL; 1404 curr_motion = NULL;
1405 on_animation = true; 1406 animation_time = 0.0f; 1407 animation_speed = 1.0f; 1408 frame_no = 0; 1409 1410 next_motion_posture = NULL; 1411 1412 enable_connection = true; 1413 enable_transition = true; 1414 } 1415 1416 1417 // 1418 // デストラクタ 1419 // 1420 MotionTransitionApp::~MotionTransitionApp() 1421 {
1422 for ( int i=0; motion_list.size(); i++ ) 1423 {
1424 delete motion_list[ i ]->motion; 1425 delete motion_list[ i ]; 1426 } 1427 motion_list.clear(); 1428 1429 if ( next_motion_posture ) 1430 delete next_motion_posture; 1431 if ( curr_posture ) 1432 delete curr_posture; 1433 if ( body ) 1434 delete body; 1435 } 1436 1437 1438 // 1439 // 初期化 1440 // H3 void MotionTransitionApp::Initialize() 1442 { 1443 GLUTBaseApp::Initialize(); 1444 1445 // サンプル動作セットの読み込み 1446 if ( motion_list.size() == 0 )
1447 body = LoadSampleMotions( motion_list ); 1448 1449 // 姿勢の初期化 1450 if ( body ) 1451 { 1452 if ( curr_posture ) 1453 delete curr_posture; 1454 if ( next_motion_posture ) 1455 delete next_motion_posture; 1456
1457 curr_posture = new Posture( body ); 1458 InitPosture( *curr_posture, body );
1459 next_motion_posture = new Posture( body ); 1460 } 1461 } 1462 1463 1464 // 1465 // 開始・リセット 1466 // H3 void MotionTransitionApp::Start() 1468 { 1469 GLUTBaseApp::Start(); 1470 1471 // 動作データが正しく初期化されていなければ終了 1472 if ( motion_list.size() == 0 ) 1473 { 1474 curr_motion = NULL; 1475 curr_motion_no = -1; 1476 return; 1477 } 1478 1479 curr_motion_no = 0; 1480 next_motion_no = -1; 1481 waiting_motion_no = -1;
1482 figure_color = motion_list[ curr_motion_no ]->color; 1483
1484 Point3f init_pos( 0.0f, 0.0f, 0.0f ); 1485 Matrix3f init_ori;
1486 init_ori.rotY( 180.0f * M_PI / 180.0f );
1487 curr_motion_mat.set( init_ori, init_pos, 1.0f ); 1488
1489 if ( motion_list.size() > 0 )
1490 curr_motion = motion_list[ curr_motion_no ]->motion; 1491 else 1492 { 1493 curr_motion = NULL; 1494 curr_motion_no = -1; 1495 } 1496 1497 animation_time = 0.0f; 1498 frame_no = 0; 1499 1500 curr_start_frame = animation_time; 1501 on_motion_transition = false; 1502 1503 Animation( 0.0f ); 1504 } 1505 1506 1507 // 1508 // 画面描画 1509 // H3 void MotionTransitionApp::Display() 1511 { 1512 GLUTBaseApp::Display();
1513
1514 // キャラクタを描画
1515 if ( curr_posture ) 1516 {
1517 glColor3f( figure_color.x, figure_color.y, figure_color.z ); 1518 DrawPosture( *curr_posture );
1519 DrawPostureShadow( *curr_posture, shadow_dir, shadow_color ); 1520 }
1521
1522 // 現在のモード、現在・次の再生動作、時間・フレーム番号を表示
1523 char message[ 64 ];
1524 DrawTextInformation( 0, "Motion Transition" ); 1525 if ( curr_motion_no != -1 )
1526 {
1527 if ( ( next_motion_no != -1 ) && ( next_motion_no != curr_motion_no ) )
1528 sprintf( message, "%s -> %s", motion_list[ curr_motion_no ]->motion->name.c_str(), motion_list[ next_motion_no ]->motion->name. c_str() );
1529 else
1530 sprintf( message, "%s", motion_list[ curr_motion_no ]->motion->name.c_str() ); 1531 DrawTextInformation( 1, message );
1532 }
1533 if ( curr_motion )
1534 sprintf( message, "%.2f (%d)", animation_time, frame_no ); 1535 else
1536 sprintf( message, "Failed to open the sample motions" ); 1537 DrawTextInformation( 2, message );
1538
1539 // 動作接続・遷移の設定を表示
1540 if ( !enable_connection || !enable_transition ) 1541 {
1542 if ( !enable_connection && !enable_transition )
1543 sprintf( message, "Connection: Off, Transition: Off" ); 1544 else if ( !enable_connection )
1545 sprintf( message, "Connection: Off" ); 1546 else if ( !enable_transition )
1547 sprintf( message, "Transition: Off" ); 1548 DrawTextInformation( 3, message ); 1549 } 1550 } 1551 1552 1553 // 1554 // マウスクリック 1555 //
H3 void MotionTransitionApp::MouseClick( int button, int state, int mx, int my ) 1557 {
1558 GLUTBaseApp::MouseClick( button, state, mx, my ); 1559
1560 // 左ボタンが押されたら、次の再生動作を変更
1561 if ( ( button == GLUT_LEFT_BUTTON ) && ( state == GLUT_DOWN ) ) 1562 { 1563 SetNextMotion(); 1564 } 1565 } 1566 1567 1568 // 1569 // キーボードのキー押下 1570 //
H3 void MotionTransitionApp::Keyboard( unsigned char key, int mx, int my ) 1572 { 1573 GLUTBaseApp::Keyboard( key, mx, my ); 1574 1575 // s キーでアニメーションの停止・再開 1576 if ( key == 's' ) 1577 on_animation = !on_animation; 1578 1579 // w キーでアニメーションの再生速度を変更 1580 if ( key == 'w' ) 1581 animation_speed = ( animation_speed == 1.0f ) ? 0.1f : 1.0f; 1582 1583 // n キーで次のフレーム
1584 if ( ( key == 'n' ) && !on_animation && curr_motion ) 1585 { 1586 on_animation = true; 1587 Animation( curr_motion->interval ); 1588 on_animation = false; 1589 } 1590 1591 // p キーで前のフレーム
1592 if ( ( key == 'p' ) && !on_animation && curr_motion && ( frame_no > 0 ) ) 1593 { 1594 on_animation = true; 1595 Animation( - curr_motion->interval ); 1596 on_animation = false; 1597 } 1598 1599 // d キーで動作接続・遷移の設定を変更 1600 if ( key == 'd' ) 1601 {
1602 if ( enable_connection && enable_transition ) 1603 enable_transition = false;
1604 else if ( enable_connection && !enable_transition ) 1605 enable_connection = false;
1606 else if ( !enable_connection && !enable_transition )
1607 { 1608 enable_connection = true; 1609 enable_transition = true; 1610 } 1611 1612 if ( !enable_transition ) 1613 on_motion_transition = false; 1614 } 1615 } 1616 1617 1618 // 1619 // キーボードの特殊キー押下
1620 //
H3 void MotionTransitionApp::KeyboardSpecial( unsigned char key, int mx, int my ) 1622 { 1623 // カーソル上キーが押されたら、次の再生動作を変更 1624 if ( key == GLUT_KEY_UP ) 1625 { 1626 SetNextMotion(); 1627 } 1628 } 1629 1630 1631 // 1632 // アニメーション処理 1633 //
H3 void MotionTransitionApp::Animation( float delta ) 1635 { 1636 // アニメーション再生中でなければ終了 1637 if ( !on_animation ) 1638 return; 1639 1640 // 動作再生処理(動作接続を考慮、動作遷移は考慮しない)
1641 if ( enable_connection && !enable_transition ) 1642 AnimationWithConnection( delta ); 1643 // 動作再生処理(動作接続・遷移を考慮) 1644 else 1645 AnimationWithConnectionTransition( delta ); 1646 1647 // 注視点を更新
1648 view_center.set( curr_posture->root_pos.x, 0.0f, curr_posture->root_pos.z ); 1649 } 1650 1651 1652 // 1653 // 次の動作を変更 1654 //
H3 void MotionTransitionApp::SetNextMotion( int no ) 1656 { 1657 if ( motion_list.size() == 0 ) 1658 return; 1659 1660 // 次の動作が指定されなかった場合は、現在の再生動作の次の番号の動作を次の動作とする 1661 if ( no < 0 ) 1662 no = ( curr_motion_no + 1) % motion_list.size(); 1663 else 1664 no = no % motion_list.size(); 1665 1666 // 動作遷移中は次の動作の変更はできないため、待ち動作として設定 1667 if ( on_motion_transition ) 1668 { 1669 waiting_motion_no = no; 1670 return; 1671 } 1672 1673 // 次の動作を設定 1674 next_motion_no = no; 1675 } 1676 1677 1678 // 1679 // 動作再生処理(動作接続を考慮、動作遷移は考慮しない) 1680 //
H3 void MotionTransitionApp::AnimationWithConnection( float delta ) 1682 {
1683 // 時間を進める
1684 animation_time += delta * animation_speed; 1685 1686 // 現在の再生動作が設定されていなければ終了 1687 if ( !curr_motion ) 1688 { 1689 frame_no = 0; 1690 return; 1691 } 1692 1693 // 現在・次の再生動作の情報を取得
1694 Motion * next_motion = NULL;
1695 MotionInfo * curr_motion_info = NULL; 1696 MotionInfo * next_motion_info = NULL; 1697 if ( next_motion_no == -1 )
1698 next_motion_no = curr_motion_no;
1699 curr_motion_info = motion_list[ curr_motion_no ]; 1700 next_motion_info = motion_list[ next_motion_no ]; 1701 next_motion = next_motion_info->motion;
1702
1703 // 現在の動作の開始・終了時刻を取得(動作のローカル時間)
1704 float curr_motion_begin_time = curr_motion_info->begin_time; 1705 float curr_motion_end_time = curr_motion_info->end_time; 1706
1707 // 次の動作の開始時刻を取得(動作のローカル時間)
1708 float next_motion_begin_time = next_motion_info->begin_time; 1709
1710 // 現在の動作の開始からの経過時間を計算
1711 float local_time = animation_time - curr_start_frame; 1712
1713 // 現在のフレーム番号を計算(表示用)
1714 frame_no = local_time / curr_motion->interval; 1715
1716 // 現在の動作の終了時刻を超えたら、次の動作へ動作接続
1717 if ( local_time > curr_motion_end_time - curr_motion_begin_time ) 1718 {
1719 // 現在の動作の終了姿勢・位置・向き(ワールド座標系)を取得
1720 Matrix4f curr_end_frame;
1721 curr_motion->GetPosture( curr_motion_end_time, *curr_posture ); 1722 TransformPosture( curr_motion_mat, *curr_posture );
1723 curr_end_frame.set( curr_posture->root_ori, curr_posture->root_pos, 1.0f ); 1724
1725 // 次の動作の開始姿勢・位置・向き(動作データのワールド座標系)を取得
1726 Matrix4f next_begin_frame;
1728 next_begin_frame.set( next_motion_posture->root_ori, next_motion_posture->root_pos, 1.0f ); 1729
1730 // 現在の動作の終了姿勢と次の動作の開始姿勢の姿勢の位置・向きを合わせるための変換行列を計算
1731 //(next_begin_frame の位置・向きを、curr_end_frame の位置向きに合わせるための変換行列 trans_mat を計算) 1732 ComputeConnectionTransformation( curr_end_frame, next_begin_frame, next_motion_mat );
1733
1734 // 現在の動作を次の動作に切り替え
1735 curr_motion = next_motion; 1736 curr_motion_no = next_motion_no;
1737 curr_start_frame = curr_start_frame + curr_motion_end_time - curr_motion_begin_time; 1738 curr_motion_begin_time = next_motion_begin_time;
1739 curr_motion_mat = next_motion_mat;
1740 local_time = animation_time - curr_start_frame; 1741 1742 // 次の動作の設定をクリア 1743 next_motion_no = -1; 1744 } 1745 1746 // 現在の動作から現在時刻の姿勢を取得
1747 curr_motion->GetPosture( local_time + curr_motion_begin_time, *curr_posture ); 1748
1749 // 変換行列を適用
1750 TransformPosture( curr_motion_mat, *curr_posture ); 1751 1752 // 姿勢の描画色を設定 1753 figure_color = curr_motion_info->color; 1754 } 1755 1756 1757 // 1758 // 動作再生処理(動作接続・遷移を考慮) 1759 //
H3 void MotionTransitionApp::AnimationWithConnectionTransition( float delta ) 1761 {
1762 // 時間を進める
1763 animation_time += delta * animation_speed; 1764 1765 // 現在の再生動作が設定されていなければ終了 1766 if ( !curr_motion ) 1767 { 1768 frame_no = 0; 1769 return; 1770 } 1771 1772 // 現在・次の再生動作の情報を取得
1773 Motion * next_motion = NULL;
1774 MotionInfo * curr_motion_info = NULL; 1775 MotionInfo * next_motion_info = NULL; 1776 if ( next_motion_no == -1 )
1777 next_motion_no = curr_motion_no;
1778 curr_motion_info = motion_list[ curr_motion_no ]; 1779 next_motion_info = motion_list[ next_motion_no ]; 1780 next_motion = next_motion_info->motion;
1781
1782 // 現在の動作の開始時刻・終了時刻・ブレンド開始時刻を取得(動作のローカル時間)
1783 float curr_motion_begin_time = curr_motion_info->begin_time; 1784 float curr_motion_end_time = curr_motion_info->end_time;
1785 float curr_motion_blend_begin_time = curr_motion_info->blend_begin_time; 1786
1787 // 次の動作の開始時刻・ブレンド終了時刻を取得(動作のローカル時間)
1788 float next_motion_begin_time = next_motion_info->begin_time;
1789 float next_motion_blend_end_time = next_motion_info->blend_end_time; 1790
1791 // 現在の動作の開始からの経過時間を計算
1792 float local_time = animation_time - curr_start_frame; 1793
1794 // 現在のフレーム番号を計算(表示用)
1795 frame_no = local_time / curr_motion->interval; 1796
1797 // 動作接続・遷移の動作ブレンドの開始
1798 if ( !on_motion_transition && ( local_time > curr_motion_blend_begin_time - curr_motion_begin_time ) ) 1799 {
1800 // 現在の動作・次の動作の位置・向きを合わせる時刻を決定(それぞれの動作のローカル時刻)
1801 float curr_motion_time = curr_motion_end_time; 1802 float next_motion_time = next_motion_begin_time; 1803 1804 // ※ レポート課題 1805 // curr_motion_time = ???; 1806 // next_motion_time = ???; 1807 1808 // 現在の動作の終了姿勢・位置・向き(ワールド座標系)を取得 1809 Matrix4f curr_end_frame;
1810 curr_motion->GetPosture( curr_motion_time, *curr_posture ); 1811 TransformPosture( curr_motion_mat, *curr_posture );
1812 curr_end_frame.set( curr_posture->root_ori, curr_posture->root_pos, 1.0f ); 1813
1814 // 次の動作の開始姿勢・位置・向き(動作データのワールド座標系)を取得
1815 Matrix4f next_begin_frame;
1816 next_motion->GetPosture( next_motion_time, *next_motion_posture );
1817 next_begin_frame.set( next_motion_posture->root_ori, next_motion_posture->root_pos, 1.0f ); 1818
1819 // 現在の動作の終了姿勢と次の動作の開始姿勢の姿勢の位置・向きを合わせるための変換行列を計算
1820 //(next_begin_frame の位置・向きを、curr_end_frame の位置向きに合わせるための変換行列 trans_mat を計算) 1821 ComputeConnectionTransformation( curr_end_frame, next_begin_frame, next_motion_mat );
1822 1823 // 動作ブレンドを開始 1824 on_motion_transition = true; 1825 } 1826 1827 // 動作接続・遷移の動作ブレンドの完了
1828 if ( local_time - ( curr_motion_end_time - curr_motion_begin_time ) >= next_motion_blend_end_time - next_motion_begin_time ) 1829 {
1830 // 現在の動作を次の動作に切り替え
1831 curr_motion = next_motion; 1832 curr_motion_no = next_motion_no; 1833 curr_motion_info = next_motion_info;
1834 curr_start_frame = curr_start_frame + curr_motion_end_time - curr_motion_begin_time; 1835 curr_motion_begin_time = next_motion_begin_time;
1836 curr_motion_mat = next_motion_mat;
1837 local_time = animation_time - curr_start_frame; 1838 1839 // 次の動作の設定をクリア 1840 next_motion_no = -1; 1841 if ( waiting_motion_no != -1 ) 1842 { 1843 next_motion_no = waiting_motion_no; 1844 waiting_motion_no = -1; 1845 } 1846 1847 // 動作ブレンドを終了 1848 on_motion_transition = false; 1849 } 1850 1851 // 現在の動作から現在時刻の姿勢を取得
1852 curr_motion->GetPosture( local_time + curr_motion_begin_time, *curr_posture ); 1853
1854 // 変換行列を適用
1855 TransformPosture( curr_motion_mat, *curr_posture ); 1856
1857 // 動作接続・遷移のためのブレンド中は、次の動作の姿勢とブレンド
1858 if ( on_motion_transition && enable_transition ) 1859 {
1860 // 次の動作のローカル時間での時刻を計算
1861 float next_local_time = local_time - ( curr_motion_end_time - curr_motion_begin_time ) + next_motion_begin_time; 1862
1863 // 次の動作から現在時刻の姿勢を取得
1864 next_motion->GetPosture( next_local_time, *next_motion_posture ); 1865
1866 // 変換行列を適用
1867 TransformPosture( next_motion_mat, *next_motion_posture ); 1868 1869 // ブレンド比率を計算 1870 float blend_ratio = 0.0f; 1871 1872 // ※ レポート課題 1873 1874 1875 // 前後の動作の姿勢をブレンド
1876 PostureInterpolation( *curr_posture, *next_motion_posture, blend_ratio, *curr_posture ); 1877
1878 // 姿勢の描画色を設定
1879 figure_color.scaleAdd( blend_ratio, next_motion_info->color - curr_motion_info->color, curr_motion_info->color ); 1880 } 1881 else 1882 { 1883 // 姿勢の描画色を設定 1884 figure_color = curr_motion_info->color; 1885 } 1886 } 1887 1888 1889 // 1890 // 変換行列の水平向き(方位角)成分を計算 1891 //
1892 float ComputeOrientation( const Matrix3f & ori ) 1893 {
1894 Vector3f fig_ori;
1895 ori.getColumn( 2, &fig_ori );
1896 return atan2( fig_ori.x, fig_ori.z ) * 180.0f / M_PI; 1897 }
1898 1899 1900 //
1901 // 2つの姿勢の位置・向きを合わせるための変換行列を計算
1902 // (next_frame の位置・向きを、prev_frame の位置向きに合わせるための変換行列 trans_mat を計算) 1903 //
1904 void ComputeConnectionTransformation( const Matrix4f & prev_frame, const Matrix4f & next_frame, Matrix4f & trans_mat ) 1905 { 1906 // ※ レポート課題 1907 1908 trans_mat.setIdentity(); 1909 1910 } 1911 1912 1913 // 1914 // 姿勢の位置・向きに変換行列を適用 1915 //
1916 void TransformPosture( const Matrix4f & trans, Posture & posture ) 1917 {
1918 // 変換行列を適用 1919 Matrix3f rot; 1920 trans.get( &rot );
1921 posture.root_ori.mul( rot, posture.root_ori ); 1922 trans.transform( &posture.root_pos ); 1923 } 1924 1925 1926 1927 /////////////////////////////////////////////////////////////////////////////// 1928 // 1929 // 動作補間アプリケーション 1930 // 1931 1932 1933 // 1934 // 動作補間アプリケーションクラス 1935 //
1936 class MotionInterpolationApp : public GLUTBaseApp 1937 { 1938 protected: 1939 // キャラクタ情報 1940 1941 // キャラクタの骨格 1942 Skeleton * body; 1943
1944 // キャラクタの姿勢 1945 Posture * curr_posture; 1946 1947 protected: 1948 // 動作再生のための変数 1949 1950 // アニメーション中かどうかを表すフラグ 1951 bool on_animation; 1952 1953 // アニメーションの再生時間 1954 float animation_time; 1955 1956 // アニメーションの再生速度 1957 float animation_speed; 1958 1959 protected: 1960 // 動作データの情報 1961 1962 // 動作データ情報(動作補間に用いる2つの動作) 1963 MotionInfo * motions[ 2 ]; 1964 1965 protected: 1966 // 動作補間のための変数 1967 1968 // 動作補間の重み 1969 float weight; 1970 1971 // サンプル動作からの取得姿勢 1972 Posture * motion_posture[ 2 ]; 1973 1974 // 現在姿勢の描画色 1975 Color3f figure_color; 1976 1977 protected: 1978 // 動作接続のための変数 1979 1980 // 繰り返し動作の再生開始時刻 1981 float cycle_start_time; 1982 1983 // サンプル動作の位置・向きを合わせるための変換行列 1984 Matrix4f motion_trans_mat[ 2 ]; 1985 1986 public: 1987 // コンストラクタ 1988 MotionInterpolationApp(); 1989 1990 // デストラクタ 1991 virtual ~MotionInterpolationApp(); 1992 1993 public: 1994 // イベント処理 1995 1996 // 初期化
1997 virtual void Initialize(); 1998
1999 // 開始・リセット 2000 virtual void Start(); 2001
2002 // 画面描画
2003 virtual void Display(); 2004
2005 // マウスドラッグ
2006 virtual void MouseDrag( int mx, int my ); 2007
2008 // キーボードのキー押下
2009 virtual void Keyboard( unsigned char key, int mx, int my ); 2010
2011 // アニメーション処理
2012 virtual void Animation( float delta ); 2013 }; 2014 2015 2016 // 補助処理(グローバル関数)のプロトタイプ宣言 2017 2018 // 2つの姿勢の位置・向きを合わせるための変換行列を計算
2019 //(next_frame の位置・向きを、prev_frame の位置向きに合わせるための変換行列 trans_mat を計算)
2020 void ComputeConnectionTransformation( const Matrix4f & prev_frame, const Matrix4f & next_frame, Matrix4f & trans_mat ); 2021
2022 // 姿勢の位置・向きに変換行列を適用
2023 void TransformPosture( const Matrix4f & trans, Posture & posture ); 2024 2025 2026 2027 // 2028 // コンストラクタ 2029 // 2030 MotionInterpolationApp::MotionInterpolationApp() 2031 {
2032 app_name = "Motion Interpolation"; 2033 2034 body = NULL; 2035 curr_posture = NULL; 2036 on_animation = true; 2037 animation_time = 0.0f; 2038 animation_speed = 1.0f; 2039 2040 motions[ 0 ] = NULL; 2041 motions[ 1 ] = NULL; 2042 weight = 0.0f; 2043 motion_posture[ 0 ] = NULL; 2044 motion_posture[ 1 ] = NULL; 2045 } 2046 2047 2048 // 2049 // デストラクタ 2050 // 2051 MotionInterpolationApp::~MotionInterpolationApp()
2052 {
2053 for ( int i=0; i<2; i++ ) 2054 {
2055 if ( motions[ i ] )
2056 {
2057 if ( motions[ i ]->motion ) 2058 delete motions[ i ]->motion; 2059 delete motions[ i ]; 2060 } 2061 } 2062 2063 if ( curr_posture ) 2064 delete curr_posture; 2065 if ( body ) 2066 delete body; 2067 } 2068 2069 2070 // 2071 // 初期化 2072 // H3 void MotionInterpolationApp::Initialize() 2074 { 2075 GLUTBaseApp::Initialize(); 2076 2077 // サンプル動作セットの読み込み 2078 if ( !motions[ 0 ] ) 2079 {
2080 vector< MotionInfo * > motion_list; 2081 body = LoadSampleMotions( motion_list ); 2082 motions[ 0 ] = motion_list[ 0 ]; 2083 motions[ 1 ] = motion_list[ 1 ]; 2084 } 2085 2086 // 姿勢の初期化 2087 if ( body ) 2088 { 2089 if ( curr_posture ) 2090 delete curr_posture; 2091 if ( motion_posture[ 0 ] ) 2092 delete motion_posture[ 0 ]; 2093 if ( motion_posture[ 1 ] ) 2094 delete motion_posture[ 1 ]; 2095
2096 curr_posture = new Posture( body ); 2097 InitPosture( *curr_posture, body );
2098 motion_posture[ 0 ] = new Posture( body ); 2099 motion_posture[ 1 ] = new Posture( body ); 2100 } 2101 } 2102 2103 2104 // 2105 // 開始・リセット 2106 // H3 void MotionInterpolationApp::Start() 2108 { 2109 GLUTBaseApp::Start(); 2110 2111 weight = 0.0f; 2112 2113 on_animation = true; 2114 animation_time = 0.0f; 2115 2116 cycle_start_time = 0.0f; 2117 2118 // 各サンプル動作の接続のための変換行列を計算 2119 Matrix4f init_frame; 2120 init_frame.setIdentity(); 2121 Matrix4f motion_start_frame; 2122 for ( int i=0; i<2; i++ ) 2123 {
2124 // 動作データが読み込まれていなければスキップ
2125 if ( !motions[ i ] || !motions[ i ]->motion || !curr_posture )
2126 continue;
2127
2128 // 動作データから開始姿勢を取得、位置・向きを取得
2129 motions[ i ]->motion->GetPosture( motions[ i ]->keytimes[ 0 ], *motion_posture[ i ] );
2130 motion_start_frame.set( motion_posture[ i ]->root_ori, motion_posture[ i ]->root_pos, 1.0f ); 2131
2132 // 変換行列を計算
2133 ComputeConnectionTransformation( motion_start_frame, motion_start_frame, motion_trans_mat[ i ] ); 2134 } 2135 2136 Animation( 0.0f ); 2137 } 2138 2139 2140 // 2141 // 画面描画 2142 // H3 void MotionInterpolationApp::Display() 2144 { 2145 GLUTBaseApp::Display(); 2146 2147 // キャラクタを描画 2148 if ( curr_posture ) 2149 {
2150 glColor3f( figure_color.x, figure_color.y, figure_color.z ); 2151 DrawPosture( *curr_posture );
2152 DrawPostureShadow( *curr_posture, shadow_dir, shadow_color ); 2153 }
2154
2155 // 現在のモード、補間重みを表示
2156 DrawTextInformation( 0, "Motion Interpolation" ); 2157 char message[ 64 ];
2158 sprintf( message, "%.2f", animation_time ); 2159 DrawTextInformation( 1, message );
2160 sprintf( message, "Weight: %.2f", weight ); 2161 DrawTextInformation( 2, message ); 2162 } 2163 2164 2165 // 2166 // マウスドラッグ 2167 //
H3 void MotionInterpolationApp::MouseDrag( int mx, int my ) 2169 {
2170 // 左ボタンの左右ドラッグに応じて重みを計算
2171 if ( drag_mouse_l ) 2172 {
2173 // 重み計算
2174 weight += (float) ( mx - last_mouse_x ) * 2.0f / win_width; 2175 if ( weight < 0.0f ) 2176 weight = 0.0f; 2177 if ( weight > 1.0f ) 2178 weight = 1.0f; 2179 2180 // 姿勢更新 2181 if ( on_animation ) 2182 Animation( 0.0f ); 2183 else 2184 { 2185 on_animation = true; 2186 Animation( 0.0f ); 2187 on_animation = false; 2188 } 2189 } 2190 2191 GLUTBaseApp::MouseDrag( mx, my ); 2192 } 2193 2194 2195 // 2196 // キーボードのキー押下 2197 //
H3 void MotionInterpolationApp::Keyboard( unsigned char key, int mx, int my ) 2199 { 2200 GLUTBaseApp::Keyboard( key, mx, my ); 2201 2202 // s キーでアニメーションの停止・再開 2203 if ( key == 's' ) 2204 on_animation = !on_animation; 2205 2206 // w キーでアニメーションの再生速度を変更 2207 if ( key == 'w' ) 2208 animation_speed = ( animation_speed == 1.0f ) ? 0.1f : 1.0f; 2209 2210 // n キーで次のフレーム
2211 if ( ( key == 'n' ) && !on_animation && motions[ 0 ] ) 2212 {
2213 on_animation = true;
2214 Animation( motions[ 0 ]->motion->interval ); 2215 on_animation = false;
2216 } 2217
2218 // p キーで前のフレーム
2219 if ( ( key == 'p' ) && !on_animation && motions[ 0 ] ) 2220 {
2221 on_animation = true;
2222 Animation( - motions[ 0 ]->motion->interval ); 2223 on_animation = false; 2224 } 2225 } 2226 2227 2228 // 2229 // アニメーション処理 2230 //
H3 void MotionInterpolationApp::Animation( float delta ) 2232 {
2233 // サンプル動作が設定されていなければ終了
2234 if ( !motions[ 0 ] || !motions[ 1 ] || !motions[ 0 ]->motion || !motions[ 1 ]->motion ) 2235 return; 2236 2237 // アニメーション再生中でなければ終了 2238 if ( !on_animation ) 2239 return; 2240 2241 // 時間を進める
2242 animation_time += delta * animation_speed; 2243
2244 // 補間動作のキー時刻を計算(サンプル動作のキー時刻を重みで平均)
2245 int num_keyframes = motions[ 0 ]->keytimes.size(); 2246 float time0, time1;
2247 vector< float > keytimes( num_keyframes ); 2248 keytimes[ 0 ] = 0.0f;
2249 for ( int i=1; i<num_keyframes; i++ ) 2250 {
2251 time0 = motions[ 0 ]->keytimes[ i ] - motions[ 0 ]->keytimes[ 0 ]; 2252 time1 = motions[ 1 ]->keytimes[ i ] - motions[ 1 ]->keytimes[ 0 ]; 2253 keytimes[ i ] = time0 * ( 1.0f - weight ) + time1 * weight;
2254 } 2255
2256 // 現在の繰り返し動作が終了したら、次の繰り返しを開始
2257 float cycle_time = animation_time - cycle_start_time; 2258 if ( cycle_time > keytimes[ num_keyframes - 1 ] ) 2259 {
2260 cycle_start_time += keytimes[ num_keyframes - 1 ]; 2261 cycle_time = animation_time - cycle_start_time; 2262
2263 // 現在の繰り返し動作の終了時点での補間姿勢の位置・向きを取得
2264 Matrix4f curr_end_frame;
2265 curr_end_frame.set( curr_posture->root_ori, curr_posture->root_pos, 1.0f ); 2266
2268 Matrix4f motion_start_frame; 2269 for ( int i = 0; i < 2; i++ )
2270 {
2271 // 動作データから開始姿勢を取得、位置・向きを取得
2272 motions[ i ]->motion->GetPosture( motions[ i ]->keytimes[ 0 ], *motion_posture[ i ] );
2273 motion_start_frame.set( motion_posture[ i ]->root_ori, motion_posture[ i ]->root_pos, 1.0f ); 2274
2275 // 変換行列を計算
2276 ComputeConnectionTransformation( curr_end_frame, motion_start_frame, motion_trans_mat[ i ] );
2277 } 2278 } 2279 2280 // 正規化時間(区間番号と区間内の正規化時間)を計算 2281 int seg_no = 0; 2282 float seg_time = 0.0f; 2283 2284 // ※ レポート課題 2285 2286 2287 // サンプル動作から姿勢を取得 2288 float motion_time = 0.0f; 2289 for ( int i = 0; i < 2; i++ ) 2290 {
2291 // 動作データの時間を計算
2292
2293 // ※ レポート課題
2294
2295 motion_time = motions[ i ]->keytimes[ 0 ]; 2296
2297
2298 // 動作データから姿勢を取得
2299 motions[ i ]->motion->GetPosture( motion_time, *motion_posture[ i ] ); 2300
2301 // 変換行列を適用
2302 TransformPosture( motion_trans_mat[ i ], *motion_posture[ i ] ); 2303 }
2304
2305 // 各サンプル動作の姿勢を補間
2306 PostureInterpolation( *motion_posture[ 0 ], *motion_posture[ 1 ], weight, *curr_posture ); 2307
2308 // 重みに応じて描画色を設定
2309 figure_color.scaleAdd( weight, motions[ 1 ]->color - motions[ 0 ]->color, motions[ 0 ]->color ); 2310
2311 // 注視点を更新
2312 view_center.set( curr_posture->root_pos.x, 0.0f, curr_posture->root_pos.z ); 2313 } 2314 2315 2316 2317 /////////////////////////////////////////////////////////////////////////////// 2318 // 2319 // 逆運動学計算(CCD法)アプリケーション 2320 // 2321 2322 2323 // 2324 // 逆運動学計算(CCD法)アプリケーション 2325 //
2326 class InverseKinematicsCCDApp : public GLUTBaseApp 2327 { 2328 protected: 2329 // キャラクタ情報 2330 2331 // キャラクタの骨格 2332 Skeleton * body; 2333 2334 // キャラクタの姿勢 2335 Posture * curr_posture; 2336 2337 protected: 2338 // IK計算のための変数 2339 2340 // 関節点の位置
2341 vector< Point3f > joint_world_positions; 2342 vector< Point3f > joint_screen_positions; 2343 2344 // 支点・末端関節 2345 int base_joint_no; 2346 int ee_joint_no; 2347 2348 // 関節点の描画設定 2349 bool draw_joints; 2350 2351 public: 2352 // コンストラクタ 2353 InverseKinematicsCCDApp(); 2354 2355 // デストラクタ 2356 virtual ~InverseKinematicsCCDApp(); 2357 2358 public: 2359 // イベント処理 2360 2361 // 初期化
2362 virtual void Initialize(); 2363
2364 // 開始・リセット 2365 virtual void Start(); 2366
2367 // 画面描画
2368 virtual void Display(); 2369
2370 // マウスクリック
2371 virtual void MouseClick( int button, int state, int mx, int my ); 2372
2373 // マウスドラッグ
2374 virtual void MouseDrag( int mx, int my ); 2375
2376 // キーボードのキー押下
2377 virtual void Keyboard( unsigned char key, int mx, int my ); 2378
2379 public:
2380 // Inverse Kinematics 処理 2381
2382 // Inverse Kinematics 計算(CCD 法)
2383 virtual void ApplyInverseKinematics( Posture & posture, int base_joint_no, int ee_joint_no, Point3f ee_joint_position ); 2384
2385 public:
2386 // 関節点の選択・移動のための補助処理
2387
2388 // 関節点の位置の更新
2389 void UpdateJointPositions( const Posture & posture ); 2390
2391 // 関節点の描画 2392 void DrawJoint(); 2393
2394 // 関節点の選択
2395 void SelectJoint( int mouse_x, int mouse_y, bool ee_or_base ); 2396
2397 // 関節点の移動(視線に垂直な平面上で上下左右に移動する)
2398 void MoveJoint( int mouse_dx, int mouse_dy ); 2399 }; 2400 2401 2402 // 補助処理(グローバル関数)のプロトタイプ宣言 2403 2404 // 末端関節から支点関節へのパス(関節の配列と各関節における末端関節の方向)を探索
2405 void FindJointPath( const Skeleton * body, int base_joint_no, int ee_joint_no, vector< int > & joint_path, vector< int > & joint_path_sign s );
2406
2407 // Inverse Kinematics 計算(CCD 法)
2408 void ApplyInverseKinematicsCCD( Posture & posture, int base_joint_no, int ee_joint_no, Point3f ee_joint_position ); 2409 2410 2411 2412 // 2413 // コンストラクタ 2414 // 2415 InverseKinematicsCCDApp::InverseKinematicsCCDApp() 2416 {
2417 app_name = "Inverse Kinematics (CCD)"; 2418 body = NULL; 2419 curr_posture = NULL; 2420 2421 base_joint_no = -1; 2422 ee_joint_no = -1; 2423 draw_joints = true; 2424 } 2425 2426 2427 // 2428 // デストラクタ 2429 // 2430 InverseKinematicsCCDApp::~InverseKinematicsCCDApp() 2431 { 2432 if ( curr_posture ) 2433 delete curr_posture; 2434 if ( body ) 2435 delete body; 2436 } 2437 2438 2439 // 2440 // 初期化 2441 // H3 void InverseKinematicsCCDApp::Initialize() 2443 { 2444 GLUTBaseApp::Initialize(); 2445 2446 // 骨格モデルの初期化に使用する BVHファイル
2447 const char * file_name = "sample_walking1.bvh"; 2448 2449 // 動作データを読み込み 2450 BVH * bvh = new BVH( file_name ); 2451 2452 // BVH動作から骨格モデルを生成 2453 if ( bvh->IsLoadSuccess() ) 2454 {
2455 Skeleton * new_body = CoustructBVHSkeleton( bvh ); 2456
2457 // 姿勢の初期化
2458 if ( new_body )
2459 {
2460 body = new_body;
2461 curr_posture = new Posture(); 2462 InitPosture( *curr_posture, body );
2463 } 2464 } 2465 2466 // 動作データを削除 2467 delete bvh; 2468 } 2469 2470 2471 // 2472 // 開始・リセット 2473 // H3 void InverseKinematicsCCDApp::Start() 2475 { 2476 GLUTBaseApp::Start(); 2477 2478 if ( !curr_posture ) 2479 return; 2480 2481 // 姿勢初期化 2482 InitPosture( *curr_posture );