トップページ > 記事閲覧
VMDカメラについて
名前:catman 日時: 2014/12/28 17:03

Dxlibでプログラミングの勉強をしている者です ttp://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=2084 を使いVMDに保存したカメラデータを反映させた所 瞬時にカメラが移動するような場面で画面がちらついてしまいます おそらくフレームを補完している為間のフレームを表示しているのだろうと思いますが ちゃんとしたタイミングで表示させる事は出来ないでしょうか?
メンテ

Page: 1 |

Re: VMDカメラについて ( No.1 )
名前:管理人 日時:2014/12/29 09:56

> おそらくフレームを補完している為間のフレームを表示しているのだろうと思いますが 恐らくその通りだと思います > ちゃんとしたタイミングで表示させる事は出来ないでしょうか? VMDのデータは30FPSなので、件のスレッドに掲載されているプログラムの ttp://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=2084 Time += 30.0f / 60.0f ; この部分を Time += 1.0f ; に変更すれば補間による表示が無くなりちらつきは無くなると思います ただ、30.0f / 60.0f に比べてスピードが倍になってしまうので、プログラムの方も フレームレートを半分にしなければなりませんが・・・ 抜本的な解決策があるかを確認してみたいと思いますので、よろしければ お試しになったVMDファイルをメールで BQE00322(あっとまーく)nifty.com ( (あっとまーく)を@に置き換えてください ) に送っていただけないでしょうか? m(_ _;m
メンテ
Re: VMDカメラについて ( No.2 )
名前:管理人 日時:2014/12/30 01:59

メールありがとうございます、手元でも現象を確認できました まず30FPSにしたところ予想した通り瞬時にカメラが移動した際のちらつきは抑えられました 次に30FPSより高いFPSにしたい場合ですが、VMDデータには「瞬時に移動するので補間はしない」などの 情報が無いようなので、少し無理矢理ですが「次のキーまでのフレーム数が1の場合は補間しない」という 処理を追加することで30FPSより高いFPSにしてもちらつかないようにすることができました 件のスレッドのサンプルプログラムをちらつかないように変更してみましたので、よろしければご覧ください 尚、今回の処理を実装するに当たって「再生時間からアニメーションのキー番号を割り出す」関数 MV1GetAnimKeyDataIndexFromTime を追加しましたので、下記のプログラムを実行する際は関数を追加した こちらのバージョンをお使いください m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibDotNet.zip // .NET用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) #include "DxLib.h" #define PI 3.1415926535897932384626433832795f // 指定のキーと次のキーまでの時間を取得する static float MV1CheckAnimKeyDataNextKeyTime( int MHandle, int AnimKeySetIndex, int KeyIndex ) { // 最後のキーだった場合は次のキーまでの時間は0 if( MV1GetAnimKeySetDataNum( MHandle, AnimKeySetIndex ) - 1 == KeyIndex ) { return 0.0f ; } // 次のキーまでの時間を返す return MV1GetAnimKeyDataTime( MHandle, AnimKeySetIndex, KeyIndex + 1 ) - MV1GetAnimKeyDataTime( MHandle, AnimKeySetIndex, KeyIndex ) ; } // MV1GetAnimKeyDataToVectorFromTime のキーとキーの間の時間が1の場合は補間しないラッピング関数 static VECTOR MV1GetAnimKeyDataToVectorFromTime_Rap( int MHandle, int AnimKeySetIndex, float Time ) { int KeyIndex ; // 指定の時間でのキー番号を取得 KeyIndex = MV1GetAnimKeyDataIndexFromTime( MHandle, AnimKeySetIndex, Time ) ; // キーとキーの間の時間が 1.00001f より短かったら補間をしない if( MV1CheckAnimKeyDataNextKeyTime( MHandle, AnimKeySetIndex, KeyIndex ) < 1.00001f ) { return MV1GetAnimKeyDataToVector( MHandle, AnimKeySetIndex, KeyIndex ) ; } else { return MV1GetAnimKeyDataToVectorFromTime( MHandle, AnimKeySetIndex, Time ) ; } } // MV1GetAnimKeyDataToLinearFromTime のキーとキーの間の時間が1の場合は補間しないラッピング関数 static float MV1GetAnimKeyDataToLinearFromTime_Rap( int MHandle, int AnimKeySetIndex, float Time ) { int KeyIndex ; // 指定の時間でのキー番号を取得 KeyIndex = MV1GetAnimKeyDataIndexFromTime( MHandle, AnimKeySetIndex, Time ) ; // キーとキーの間の時間が 1.00001f より短かったら補間をしない if( MV1CheckAnimKeyDataNextKeyTime( MHandle, AnimKeySetIndex, KeyIndex ) < 1.00001f ) { return MV1GetAnimKeyDataToLinear( MHandle, AnimKeySetIndex, KeyIndex ) ; } else { return MV1GetAnimKeyDataToLinearFromTime( MHandle, AnimKeySetIndex, Time ) ; } } // VMDカメラモーションからカメラのパラメータを抽出してDXライブラリの設定に反映させる void SetupVMDCameraMotionParam( int CameraHandle, float Time ) { MATRIX VRotMat, HRotMat, MixRotMat, TwistRotMat ; VECTOR CamLoc, CamDir, CamUp ; VECTOR Location, Rotation ; float Length, ViewAngle ; // カメラの注視点を取得 Location = MV1GetAnimKeyDataToVectorFromTime_Rap( CameraHandle, 0, Time ) ; // カメラの回転値を取得 Rotation = MV1GetAnimKeyDataToVectorFromTime_Rap( CameraHandle, 1, Time ) ; // カメラの注視点までの距離の符号を逆転したものを取得 Length = MV1GetAnimKeyDataToLinearFromTime_Rap( CameraHandle, 2, Time ) ; // カメラの視野角を取得 ViewAngle = MV1GetAnimKeyDataToLinearFromTime_Rap( CameraHandle, 3, Time ) ; // 垂直方向の回転行列を取得 VRotMat = MGetRotX( -Rotation.x ) ; // 水平方向の回転行列を取得 HRotMat = MGetRotY( -Rotation.y ) ; // 垂直方向の回転行列と水平方向の回転行列を合成 MixRotMat = MMult( VRotMat, HRotMat ) ; // カメラの向きを算出 CamDir = VTransform( VGet( 0.0f, 0.0f, 1.0f ), MixRotMat ) ; // 捻り回転行列を取得 TwistRotMat = MGetRotAxis( CamDir, -Rotation.z ) ; // 捻り回転行列を合成行列に合成 MixRotMat = MMult( MixRotMat, TwistRotMat ) ; // カメラの上方向の向きを算出 CamUp = VTransform( VGet( 0.0f, 1.0f, 0.0f ), MixRotMat ) ; // カメラの座標を算出 CamLoc = VTransform( VGet( 0.0f, 0.0f, Length ), MixRotMat ) ; CamLoc = VAdd( CamLoc, Location ) ; // カメラの注視点を算出 Location = VAdd( CamLoc, CamDir ) ; // 視野角をセット SetupCamera_Perspective( ViewAngle / 180.0f * PI ) ; // カメラの座標と注視点と上方向をセット SetCameraPositionAndTargetAndUpVec( CamLoc, Location, CamUp ) ; } // WinMain int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int ModelHandle, CameraHandle, AttachAnimIndex ; float Time ; // ウインドウモードで起動 ChangeWindowMode( TRUE ); // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1; // 描画先を裏画面にする SetDrawScreen( DX_SCREEN_BACK ); // モデルを読み込み ModelHandle = MV1LoadModel( "初音ミク_2.pmd" ) ; if(ModelHandle == -1) return -1; // カメラモーションの読み込み CameraHandle = MV1LoadModel( "Camera_2.vmd" ) ; if(CameraHandle == -1) return -1; // モデルにアニメーションをアタッチ AttachAnimIndex = MV1AttachAnim( ModelHandle, 0 ) ; // 初期設定では Near クリップが遠すぎるのでクリップの範囲を変更 SetCameraNearFar( 1.0f, 1000.0f ) ; // メインループ Time = 0.0f ; while( ProcessMessage() == 0 ) { // 画面のクリア ClearDrawScreen(); // モーションの時間を進める( モーションの時間に到達したら0に戻す ) Time += 30.0f / 60.0f ; if( Time > MV1GetAttachAnimTotalTime( ModelHandle, AttachAnimIndex ) ) { Time = 0.0f ; } MV1SetAttachAnimTime( ModelHandle, AttachAnimIndex, Time ) ; // VMDカメラモーションのパラメータをDXライブラリの設定に反映させる SetupVMDCameraMotionParam( CameraHandle, Time ) ; // モデルを描画 MV1DrawModel( ModelHandle ) ; // 再生時間の表示 DrawFormatString( 0, 0, GetColor( 255,255,255 ), "Time %.1f/%.1f", Time, MV1GetAttachAnimTotalTime( ModelHandle, AttachAnimIndex ) ) ; // 裏画面の内容を表画面に反映 ScreenFlip(); } // DXライブラリの後始末 DxLib_End(); // ソフトの終了 return 0; }
メンテ
Re: VMDカメラについて ( No.3 )
名前:catman 日時:2014/12/30 10:06

対応ありがとうございます ちらつかずに再生させる事が出来ました
メンテ
Re: VMDカメラについて ( No.4 )
名前:catman 日時:2014/12/30 10:20

すみませんもうひとつ質問があるのですが メールで送らせてもらった素材セットにあるPMXをDxlibで表示すると 遠くから見た時に目に白い縞々が出来てしまいます(黒目が白目にめり込んでいる?) 2つのPCで試してみましたが両方なりました これは仕様でしょうか?
メンテ
Re: VMDカメラについて ( No.5 )
名前:管理人 日時:2014/12/31 04:19

仕様といえば仕様です・・・Zバッファの精度が足りていないのが原因です SetCameraNearFar 関数で、第一引数の Near を実用上問題ない範囲でなるべく大きな値を 指定するようにしてみてください ( Far も実用上問題ない範囲で小さな値にするべきですが、Near 程の大きな影響はありません ) 私がテストで再生した際は Near を 10.0f、Far を 500.0f にしたところ、件の縞々は出なくなりました もし実用範囲内のどのような値を指定しても現象が回避できない場合は、DxLib_Init を呼び出す前の箇所に SetZBufferBitDepth( 24 ) ; という記述を増やしてみてください、若干の速度低下と引き換えにZバッファ自体の精度を上げられます
メンテ
Re: VMDカメラについて ( No.6 )
名前:catman 日時:2014/12/31 16:02

ありがとうございます 今までNearFarは適当に設定していましたがなるほど Zバッファなるものがあるのですね もう少し3Dについて勉強してみたいと思います
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存