Re: 行列適用済みのアニメーション ( No.1 ) |
- 名前:管理人 日時:2012/09/02 05:22
すみません、どのような機能をご所望なのかが分かりません
機能の詳細と、されたいことを教えて頂けないでしょうか?
|
Re: 行列適用済みのアニメーション ( No.2 ) |
- 名前:maruo 日時:2012/09/09 01:09
分かりづらい書き方をしてすいませんm(_ _)m
MV1SetMatrix版とかわけわからんですよね(^^;
アニメーションに付加させる係数みたいなイメージでした。
やりたいことの例として、人型モデルのアニメーションで
立ちアニメーション、前方向走りアニメーション、斜め前方向走りアニメーション時にカメラ視点に合わせて頭の回転という感じで
※斜め前方向走りは前方向走りを利用してMV1SetMatrixで回転させて使ってます。
こちらに動画アップしました。
https://docs.google.com/file/d/0B7sIGCzrXiuHd3loUFZnQmg0dTA/edit
これ自体はMV1SetMatrix、MV1GetFrameBaseLocalMatrix、MV1SetFrameUserLocalMatrix等を使うことで意図した動きになっていて
髪などの斜め前走りに合わせて動いて欲しい箇所をフレーム単位で戻す回転をさせて調整しています。
こういったやり方ではなく、
合成前のアニメーション側を回転させて実現できれば、
(先ほどの例だと、前走りアニメーション全体と頭を回転でモデル側の回転はなし)
ブレンド率が使えて便利かなと思い、要望を出させていただきました。
が、よく考えてみると、あまり意味がないうえに計算回数が増えるだけ?(^^;
|
Re: 行列適用済みのアニメーション ( No.3 ) |
- 名前:管理人 日時:2012/09/09 08:25
ご解説ありがとうございます、少しmaruoさんの意図されていることが分かった気がします
その上での疑問なのですが、MV1SetMatrix によるモデル全体の向きの変更と頭の向きは
変えないという方法で斜め走りを実現されているとのことですが、
こちらは頭の向きだけ変更するだけでは目的を達成できないのでしょうか?
頭の向きだけを変更すれば、モデル全体に対して MV1SetMatrix を使用する必要はなくなりますし、
アニメーション機能に対しても同様の機能は必要はなくなると思うのですが・・・
|
Re: 行列適用済みのアニメーション ( No.4 ) |
- 名前:maruo 日時:2012/10/03 01:46
レスが遅れて申し訳ありません。
まとめてからにしようと思ったのですが
その最中に気になったことがあったのでその部分の解答をお願いしますm(_ _)m
以下は意味のないソースになるのでしょうか?
MATRIX FrameLocalMat;
MV1ResetFrameUserLocalMatrix(ModelHandle, 4);
FrameLocalMat = DxLib::MV1GetFrameLocalMatrix(ModelHandle, 4);
MV1SetFrameUserLocalMatrix(ModelHandle, 4, FrameLocalMat);
|
Re: 行列適用済みのアニメーション ( No.5 ) |
- 名前:maruo 日時:2012/10/04 19:44
ちょっと訂正です。
>以下は意味のないソースになるのでしょうか?
以下は意味のないソースにならないのでしょうか?
|
Re: 行列適用済みのアニメーション ( No.6 ) |
- 名前:管理人 日時:2012/10/14 23:36
載せていただいたコードでフレームの座標や回転が変化するかといえば、変化はありませんので、
姿勢を変えたいという目的としては意味はありませんが、
MV1SetFrameUserLocalMatrix で独自の行列が設定されたフレームはアニメーションの
影響を受けなくなりますので、アニメーションが行われているフレームに対して
載せていただいたコードを実行した後に MV1SetAttachAnimTime などでアニメーションの
時間を変更した場合、MV1SetFrameUserLocalMatrix を行ったフレームだけは変更する前の
時間の状態になりますので、載せていただいたコードを実行した場合としなかった場合とでは
挙動に違いがあり、意味があると言えます
|
Re: 行列適用済みのアニメーション ( No.7 ) |
- 名前:maruo 日時:2012/10/18 21:33
レスありがとうございますm(_ _)m
どうにも上手くいかなくて調べてたのですが
以下のソースコードでフレーム頭の箇所にその症状がでます。
https://docs.google.com/open?id=0B7sIGCzrXiuHQTl3SzJTQ3BPVTA
ここに使用したアニメーションファイルをアップしました。
#include <DxLib.h>
#pragma comment(lib, "winmm.lib")
int ModelHandle;
bool TestUserFrame = false;
bool TestAnim = false;
int AnimNum[2] = {0,1};
int Index[2] = {-1,-1};
float Rate[2] = {1.f,0.f};
// モデル「初音ミクVer2」の4(頭)です
// この値を3(首)にすると問題なく動きました
int TestFrameNum = 4;
void ResetAnim()
{
Rate[0] = 1.0f;
MV1SetAttachAnimBlendRate( ModelHandle, Index[0], Rate[0] );
MV1SetAttachAnimTime( ModelHandle, Index[0], 0.0f );
Rate[1] = 0.0f;
MV1SetAttachAnimBlendRate( ModelHandle, Index[1], Rate[1] );
MV1SetAttachAnimTime( ModelHandle, Index[1], 0.0f );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
::timeBeginPeriod(1);
ChangeWindowMode ( TRUE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 )
return -1 ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
const DWORD FPS = 60;
const DWORD TIME_SCALE = 1000;
MV1SetLoadModelUsePhysicsMode( DX_LOADMODEL_PHYSICS_DISABLE ) ;
MV1SetLoadModelAnimFilePath( _T("CommonAnim.vmd") ) ;
ModelHandle = MV1LoadModel( _T("初音ミクVer2.pmd") );
VECTOR CameraPos, TargetPos, Vect1, Vect2 ;
TargetPos = VGet( 0.0f, 0.0f, 0.0f );
Vect1 = VGet( 0.0f, 0.0f, -50.0f );
MV1SetMatrix( ModelHandle, MGetTranslate( VGet( 0.f, -10.f, 0.f ) ) );
MATRIX Matrix = MGetIdent();
Vect2 = VTransform( Vect1, Matrix ) ;
CameraPos = VAdd( TargetPos, Vect2 ) ;
SetCameraPositionAndTarget_UpVecY( CameraPos, TargetPos ) ;
SetCameraScreenCenter( 320.0f, 240.0f );
int ParentNum = MV1GetFrameParent( ModelHandle, TestFrameNum );
Index[0] = MV1AttachAnim( ModelHandle, AnimNum[0], -1, TRUE );
Index[1] = MV1AttachAnim( ModelHandle, AnimNum[1], -1, TRUE );
ResetAnim();
// ESCキーが押されるかウインドウが閉じられるまでループ
while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
{
DWORD NextTime = ::timeGetTime() * TIME_SCALE;
MV1ResetFrameUserLocalMatrix( ModelHandle, TestFrameNum );
if( CheckHitKey( KEY_INPUT_1 ) == 1 )
{
ResetAnim();
TestAnim = false;
TestUserFrame = false;
}
else if( CheckHitKey( KEY_INPUT_2 ) == 1 )
{
ResetAnim();
TestAnim = true;
TestUserFrame = false;
}
// これを実行すると頭の向きがワープしたようになる
else if( CheckHitKey( KEY_INPUT_3 ) == 1 )
{
ResetAnim();
TestAnim = true;
TestUserFrame = true;
}
else if( TestAnim )
{
Rate[0] -= 0.005f;
if( Rate[0] < 0.0f )
Rate[0] = 0.0f;
Rate[1] += 0.005f;
if( Rate[1] > 1.0f )
Rate[1] = 1.0f;
MV1SetAttachAnimBlendRate( ModelHandle, Index[0], Rate[0] );
MV1SetAttachAnimBlendRate( ModelHandle, Index[1], Rate[1] );
if( TestUserFrame )
{
MATRIX LocalMat;
LocalMat = MV1GetFrameLocalMatrix( ModelHandle, TestFrameNum );
MV1SetFrameUserLocalMatrix( ModelHandle, TestFrameNum, LocalMat );
}
else
{
// これでMV1GetFrameLocalMatrixと同じ値が得られますか?
MATRIX WorldMat, InvMat, UserMat;
WorldMat = MV1GetFrameLocalWorldMatrix( ModelHandle, TestFrameNum );
InvMat = MInverse( MV1GetFrameLocalWorldMatrix( ModelHandle, ParentNum ) );
UserMat = MMult( WorldMat, InvMat );
MV1SetFrameUserLocalMatrix( ModelHandle, TestFrameNum, UserMat );
}
}
// 画面をクリア
ClearDrawScreen() ;
// モデルの描画
MV1DrawModel( ModelHandle ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
DWORD NowTime = ::timeGetTime();
NowTime *= TIME_SCALE;
int t = (int)(NextTime-NowTime);
if(0 < t)
Sleep(t/TIME_SCALE);
NextTime += TIME_SCALE * 1000 / FPS;
}
DxLib_End() ;
::timeEndPeriod(1);
return 0 ;
}
|
Re: 行列適用済みのアニメーション ( No.8 ) |
- 名前:管理人 日時:2012/10/20 19:28
載せていただいた再現プログラムで現象を確認できました
原因は描画時の行列計算処理と MV1GetFrameLocalMatrix 内での行列計算処理に違いがあった為でした
修正版をアップしましたので、よろしければお使いください 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)」をして下さい)
> // これでMV1GetFrameLocalMatrixと同じ値が得られますか?
すみません、今回の修正で同じ値が得られるようになりました
|
Re: 行列適用済みのアニメーション ( No.9 ) |
- 名前:maruo 日時:2012/10/21 15:35
修正ありがとうございます。
問題なく動作するのを確認致しましたm(_ _)m
簡潔にまとめると
回転などのアニメーションをブレンド率(フレーム単位含む)で調整したい
ってことになるのかな
これ自体は事前にアニメーションファイルを用意してやればできるのですが
事前に用意できない場合(回転させる値が決まっていないなど)があるので要望になってしまいました。
#include <DxLib.h>
#pragma comment(lib, "winmm.lib")
int ModelHandle;
bool TestRotY = false;
bool TestAnim = false;
int AnimNum[2] = {0,1};
int Index[2] = {-1,-1};
float Rate[2] = {1.f,0.f};
float AngleMax[2] = { DX_PI_F * 0.25f, DX_PI_F * 0.25f };
float AngleX = 0.0f;
MATRIX TranslateMat = MGetTranslate( VGet( 0.f, -10.f, 0.f ) );
// モデル「初音ミクVer2」の4(頭)です
int TestFrameNum = 4;
void ResetAnim()
{
Rate[0] = 1.0f;
MV1SetAttachAnimBlendRate( ModelHandle, Index[0], Rate[0] );
MV1SetAttachAnimTime( ModelHandle, Index[0], 0.0f );
Rate[1] = 0.0f;
MV1SetAttachAnimBlendRate( ModelHandle, Index[1], Rate[1] );
MV1SetAttachAnimTime( ModelHandle, Index[1], 0.0f );
// AngleX = 0.0f;
MV1SetMatrix( ModelHandle, TranslateMat );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
::timeBeginPeriod(1);
ChangeWindowMode ( TRUE ) ;
SetBackgroundColor( 155, 155, 155);
// DXライブラリの初期化
if( DxLib_Init() < 0 )
return -1 ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
const DWORD FPS = 60;
const DWORD TIME_SCALE = 1000;
MV1SetLoadModelUsePhysicsMode( DX_LOADMODEL_PHYSICS_DISABLE ) ;
MV1SetLoadModelAnimFilePath( _T("CommonAnim.vmd") ) ;
ModelHandle = MV1LoadModel( _T("初音ミクVer2/初音ミクVer2.pmd") );
SetCameraNearFar( 1.0f, 2000.0f );
VECTOR CameraPos, TargetPos, Vect1, Vect2 ;
TargetPos = VGet( 0.0f, 0.0f, 0.0f );
Vect1 = VGet( 0.0f, 0.0f, -50.0f );
// 軸XYZ
VECTOR Axis[3];
Axis[0] = VGet(1.0f,0.0f,0.0f);
Axis[1] = VGet(0.0f,1.0f,0.0f);
Axis[2] = VGet(0.0f,0.0f,1.0f);
MATRIX Matrix = MGetIdent();
Vect2 = VTransform( Vect1, Matrix ) ;
CameraPos = VAdd( TargetPos, Vect2 ) ;
SetCameraPositionAndTarget_UpVecY( CameraPos, TargetPos ) ;
SetCameraScreenCenter( 320.0f, 240.0f );
int ParentNum = MV1GetFrameParent( ModelHandle, TestFrameNum );
Index[0] = MV1AttachAnim( ModelHandle, AnimNum[0], -1, TRUE );
Index[1] = MV1AttachAnim( ModelHandle, AnimNum[1], -1, TRUE );
ResetAnim();
// ESCキーが押されるかウインドウが閉じられるまでループ
while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
{
DWORD NextTime = ::timeGetTime() * TIME_SCALE;
if( CheckHitKey( KEY_INPUT_UP ) == 1 )
{
AngleX += 0.01f;
if( AngleX > AngleMax[0] )
AngleX = AngleMax[0];
}
else if( CheckHitKey( KEY_INPUT_DOWN ) == 1 )
{
AngleX -= 0.01f;
if( AngleX < -AngleMax[0] )
AngleX = -AngleMax[0];
}
if( CheckHitKey( KEY_INPUT_1 ) == 1 )
{
ResetAnim();
TestAnim = false;
TestRotY = false;
}
else if( CheckHitKey( KEY_INPUT_2 ) == 1 )
{
TestAnim = true;
TestRotY = false;
}
else if( CheckHitKey( KEY_INPUT_3 ) == 1 )
{
TestAnim = true;
TestRotY = true;
}
MATRIX MatLocal, MatWorld, MatUser, MatRotX, MatRotY, MatRotAll, MatWorldCenter;
MatRotAll = MatRotX = MatRotY = MGetIdent();
MV1ResetFrameUserLocalMatrix( ModelHandle, TestFrameNum );
MV1SetAttachAnimBlendRate( ModelHandle, Index[0], Rate[0] );
MV1SetAttachAnimBlendRate( ModelHandle, Index[1], Rate[1] );
/// Y軸の回転をモデルに適用
MatRotY = MGetRotAxis( Axis[1], AngleMax[1] * Rate[1] );
MV1SetMatrix( ModelHandle, MMult( MatRotY, TranslateMat ) );
MatLocal = MV1GetFrameLocalMatrix( ModelHandle, TestFrameNum );
MatWorld = MV1GetFrameLocalWorldMatrix( ModelHandle, TestFrameNum );
/// Z軸
MatWorldCenter = MV1GetMatrix( ModelHandle );//MV1GetFrameLocalWorldMatrix( ModelHandle, 0 );
Axis[2] = VGet( MatWorldCenter.m[2][0], MatWorldCenter.m[2][1], MatWorldCenter.m[2][2] );
/// X軸
Axis[0] = VCross( Axis[1], Axis[2] );
MatRotX = MGetRotAxis( Axis[0], AngleX );
if( TestRotY )
MatRotY = MInverse( MatRotY );
MatRotAll = MMult( MatRotAll, MatRotX );
MatRotAll = MMult( MatRotAll, MatRotY );
/// 差分を適用
MatUser = MMult( MMult( MatWorld, MatRotAll ), MInverse( MatWorld ) );
MatUser = MMult( MatLocal, MatUser );
/// 位置を戻す
MatUser.m[3][0] = MatLocal.m[3][0];
MatUser.m[3][1] = MatLocal.m[3][1];
MatUser.m[3][2] = MatLocal.m[3][2];
MV1SetFrameUserLocalMatrix( ModelHandle, TestFrameNum, MatUser );
if( TestAnim )
{
Rate[0] -= 0.005f;
if( Rate[0] < 0.0f )
Rate[0] = 0.0f;
Rate[1] += 0.005f;
if( Rate[1] > 1.0f )
Rate[1] = 1.0f;
}
// 画面をクリア
ClearDrawScreen() ;
// モデルの描画
MV1DrawModel( ModelHandle ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
DWORD NowTime = ::timeGetTime();
NowTime *= TIME_SCALE;
int t = (int)(NextTime-NowTime);
if(0 < t)
Sleep(t/TIME_SCALE);
NextTime += TIME_SCALE * 1000 / FPS;
}
DxLib_End() ;
::timeEndPeriod(1);
return 0 ;
}
このソースコードでやると
頭を回転させることで髪などの修正箇所がでてきて、その調整が非常に厳しい感じになって
回転を適用したアニメーションをMV1SetAttachAnimBlendRateToFrameみたいな感じで合成できれば
だいぶ違和感を減らせられるんじゃないかと思いました。
※最終的には髪は物理エンジンに頼ろうと思ってるので例として適してなかったかもです(^^;
このようなやり方がないか探してて、↓の差分モーションというのが見つかりました。
http://game.watch.impress.co.jp/docs/series/3dcg/20120803_550608.html
ちょっと違うんですが、やりたいこととは近い感じなのかな。
|
|