角度からベクトル
Re: 角度からベクトル
さっきの式の間違いが見つかりました。
positionに角度を変更したい回転軸、
flightvectorに変更の基準となる回転軸、
rotationに1フレームで動く角度を入れて、
それを6通りの軸の組み合わせでやることで出来ました。
ここでまたひとつ問題が。
戦闘機の頭をz軸のベクトルに合わせ、
戦闘機の背中をy軸に合わせたいのです。
どうすればいいでしょうか?
positionに角度を変更したい回転軸、
flightvectorに変更の基準となる回転軸、
rotationに1フレームで動く角度を入れて、
それを6通りの軸の組み合わせでやることで出来ました。
ここでまたひとつ問題が。
戦闘機の頭をz軸のベクトルに合わせ、
戦闘機の背中をy軸に合わせたいのです。
どうすればいいでしょうか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: 角度からベクトル
コードは掲載してくださいね。ヒューガ さんが書きました:さっきの式の間違いが見つかりました。
positionに角度を変更したい回転軸、
flightvectorに変更の基準となる回転軸、
rotationに1フレームで動く角度を入れて、
それを6通りの軸の組み合わせでやることで出来ました。
ここでまたひとつ問題が。
戦闘機の頭をz軸のベクトルに合わせ、
戦闘機の背中をy軸に合わせたいのです。
どうすればいいでしょうか?
あと機軸は変化するのにZ軸とY軸に合わせて良いのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 角度からベクトル
VECTOR quaternion(VECTOR axis,VECTOR changevector,float rotation){
float rotap,rotaq,rotar,rotac;
VECTOR vectp,vectq,vectr,vectc;
rotap=0;
rotaq=cos(rotation/2);
rotar=cos(rotation/2);
vectp=changevector;
vectq=VGet(axis.x*sin(rotation/2),axis.y*sin(rotation/2),axis.z*sin(rotation/2));
vectr=VGet(-axis.x*sin(rotation/2),-axis.y*sin(rotation/2),-axis.z*sin(rotation/2));
rotac=rotar*rotap-VDot(vectr,vectp);
vectc=VAdd(VAdd(VGet(vectp.x*rotar,vectp.y*rotar,vectp.z*rotar),VGet(rotap*vectr.x,rotap*vectr.y,rotap*vectr.z)),VCross(vectr,vectp));
changevector=VAdd(VAdd(VGet(vectq.x*rotac,vectq.y*rotac,vectq.z*rotac),VGet(rotaq*vectc.x,rotaq*vectc.y,rotaq*vectc.z)),VCross(vectc,vectq));
return changevector;
}
void move_my(){
my.AxisY=quaternion(my.AxisX,my.AxisY,my.pitch);
my.AxisZ=quaternion(my.AxisX,my.AxisZ,my.pitch);
my.AxisX=quaternion(my.AxisY,my.AxisX,my.yaw);
my.AxisZ=quaternion(my.AxisY,my.AxisZ,my.yaw);
my.AxisX=quaternion(my.AxisZ,my.AxisX,my.roll);
my.AxisY=quaternion(my.AxisZ,my.AxisY,my.roll);
my.xyz=VGet(my.xyz.x+=my.AxisZ.x*-10,my.xyz.y+=my.AxisZ.y*-10,my.xyz.z+=my.AxisZ.z*-10);
}
x-z平面からベクトルまでの角度をmy.Rxyz.x,y-z平面からベクトルまでの角度をmy.Rxyz.y
ごめんなさい、my.Rxyz.zはどうつかえばいいのでしょう・・・
最終的にはMV1SetRotationXYZ(my.model,my.Rxyz);
で機体の角度を決定します。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: 角度からベクトル
Rxyzが突然出てきてますが、どこで計算しているんでしょうか?
あとzはロールで使うと思いますが?
【補足】
提案ですがベクトルから機体の向きをセットするのは、これが良いと思います。
「MV1SetRotationZYAxis」
http://homepage2.nifty.com/natupaji/DxL ... .html#R3N8
あとzはロールで使うと思いますが?
【補足】
提案ですがベクトルから機体の向きをセットするのは、これが良いと思います。
「MV1SetRotationZYAxis」
http://homepage2.nifty.com/natupaji/DxL ... .html#R3N8
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: 角度からベクトル
参考に、とりあえずオイラー角版をアップしておきます。出来れば、これにクォータニオンを対応させてみて下さい。
超適当飛行体モデルもアップしておきます。
→ 作成されたクォータニオンが目的の動作が出来るかの確認って事ですね。オイラー角同等以上の飛行体の挙動を実現できるならOKです。
超適当飛行体モデルもアップしておきます。
→ 作成されたクォータニオンが目的の動作が出来るかの確認って事ですね。オイラー角同等以上の飛行体の挙動を実現できるならOKです。
#include "DxLib.h"
typedef struct {
int model;
VECTOR position;
MATRIX rotateMatrix;
MATRIX matrix;
} my_t;
my_t my;
void load()
{
my.model = MV1LoadModel( "test.mqo" );
}
void load_main()
{
load();
}
void graph_my()
{
MV1DrawModel( my.model );
}
void graph_main()
{
graph_my();
}
// 自機の座標・傾きを更新
void update_my()
{
// モデルの回転状態(機体軸で回転)
float RotX = 0.0f;
float RotY = 0.0f;
float RotZ = 0.0f;
if(1==CheckHitKey(KEY_INPUT_UP)) { RotX=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_DOWN)) { RotX=-(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_RIGHT)) { RotY=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_LEFT)) { RotY=-(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_A)) { RotZ=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_S)) { RotZ=-(PHI/180); }
// モデルの表示マトリクス。
MATRIX matrix = MMult( MMult( MGetRotZ( RotZ ), MGetRotX( RotX ) ), MGetRotY( RotY ) );//回転マトリクス
my.rotateMatrix = MMult( matrix, my.rotateMatrix );
my.matrix = MMult( my.rotateMatrix, MGetTranslate(my.position) );
MV1SetMatrix( my.model, my.matrix ) ;
}
// 飛行ベクトルを得る。
void update_fvec()
{
// 飛行ベクトルを得る。
VECTOR FlightVector = VTransformSR( VGet(0.0f,0.0f,5.0f), my.matrix ); //ここで飛行体の移動ベクトルが得られる。
// 移動ベクトルとして位置に加算。
my.position = VAdd( my.position, FlightVector );
// 飛行ベクトルの表示
FlightVector = VScale( FlightVector, 50.0f ); //表示用に拡大
FlightVector = VAdd( FlightVector, my.position );
DrawCone3D( FlightVector, my.position,20.0f,8,GetColor(255,255,255),GetColor(255,255,255), TRUE);
DrawFormatString( 0, 0, GetColor( 255,255,255 ), "FlightVector x=%f y=%f z=%f", FlightVector.x, FlightVector.y, FlightVector.z ) ;
}
void update_main()
{
update_my();
update_fvec();
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );
load_main();
my.position = VGet( 0.0f, 0.0f, 600.0f );
my.rotateMatrix = MGetIdent();
my.matrix = MGetIdent();
SetCameraPositionAndTarget_UpVecY(VGet(0,0,0),VGet(0,0,100));
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 ) {
update_main();
graph_main();
}
DxLib_End();
return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: 角度からベクトル
えーとまず1度ずつの回転をxyz軸分掛けて
それを現在の方向に掛けて方向転換
方向転換分を現在位置からの回転行列にして
その行列をモデルに適用。
回転行列のz軸方向にベクトルを向ける
ということぐらいしかわかりません・・・
作っているゲームは元にしたゲームに近い動きをしてくれています。
今のところ問題ありません
それを現在の方向に掛けて方向転換
方向転換分を現在位置からの回転行列にして
その行列をモデルに適用。
回転行列のz軸方向にベクトルを向ける
ということぐらいしかわかりません・・・
作っているゲームは元にしたゲームに近い動きをしてくれています。
今のところ問題ありません
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: 角度からベクトル
ここのルールなのですがソースコードは他の人が参考にできるように動くものを掲載して頂くことになっていますので、よろしくお願いします。ヒューガ さんが書きました:えーとまず1度ずつの回転をxyz軸分掛けて
それを現在の方向に掛けて方向転換
方向転換分を現在位置からの回転行列にして
その行列をモデルに適用。
回転行列のz軸方向にベクトルを向ける
ということぐらいしかわかりません・・・
作っているゲームは元にしたゲームに近い動きをしてくれています。
今のところ問題ありません
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: 角度からベクトル
えーと、コードを載せて頂けないのでしょうか?ヒューガ さんが書きました:わかりました。お騒がせしてごめんなさい。
他の人の参考になりそうなので、ぜひ掲載をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: 角度からベクトル
ありがとうございます。
【追記】
参考になる様にオイラー角とクォータニオン両方で比較できるコードを作りました。
使用キー:1でオイラー角、2でクォータニオンに切り替わります。
ロールがA,S ピッチが↓↑ ヨーが←→のキーに対応しています。
前にも書いた通り大気中を飛ぶ飛行機の運動物理はまったく再現しておりません。
※ 、慣性・空気抵抗・加速・揚力・空力の物理要因が一切ありません
適当モデル:http://dixq.net/forum/download/file.php?id=819
【追記】
参考になる様にオイラー角とクォータニオン両方で比較できるコードを作りました。
使用キー:1でオイラー角、2でクォータニオンに切り替わります。
ロールがA,S ピッチが↓↑ ヨーが←→のキーに対応しています。
前にも書いた通り大気中を飛ぶ飛行機の運動物理はまったく再現しておりません。
※ 、慣性・空気抵抗・加速・揚力・空力の物理要因が一切ありません
適当モデル:http://dixq.net/forum/download/file.php?id=819
#include "DxLib.h"
#include "math.h"
typedef struct {
int model;
VECTOR position;
MATRIX rotateMatrix;
MATRIX matrix;
VECTOR AxisX,AxisY,AxisZ;
} my_t;
my_t my;
bool bQuaternion = false;
void load()
{
my.model = MV1LoadModel( "test.mqo" );
}
void load_main()
{
load();
}
void graph_my()
{
MV1DrawModel( my.model );
}
void graph_main()
{
graph_my();
}
//---------------------------------------------------------
// オイラー角版
//---------------------------------------------------------
// 自機の座標・傾きを更新
void update_my()
{
// モデルの回転状態(機体軸で回転)
float RotX = 0.0f;
float RotY = 0.0f;
float RotZ = 0.0f;
if(1==CheckHitKey(KEY_INPUT_UP)) { RotX=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_DOWN)) { RotX=-(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_RIGHT)) { RotY=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_LEFT)) { RotY=-(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_A)) { RotZ=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_S)) { RotZ=-(PHI/180); }
// モデルの表示マトリクス。
MATRIX matrix = MMult( MMult( MGetRotZ( RotZ ), MGetRotX( -RotX ) ), MGetRotY( RotY ) );//回転マトリクス
my.rotateMatrix = MMult( matrix, my.rotateMatrix );
my.matrix = MMult( my.rotateMatrix, MGetTranslate(my.position) );
MV1SetMatrix( my.model, my.matrix ) ;
}
// 飛行ベクトルを得る。
void update_fvec()
{
// 飛行ベクトルを得る。
VECTOR FlightVector = VTransformSR( VGet(0.0f,0.0f,5.0f), my.matrix ); //ここで飛行体の移動ベクトルが得られる。
// 移動ベクトルとして位置に加算。
my.position = VAdd( my.position, FlightVector );
// 飛行ベクトルの表示
FlightVector = VScale( FlightVector, 50.0f ); //表示用に拡大
FlightVector = VAdd( FlightVector, my.position );
DrawCone3D( FlightVector, my.position,20.0f,8,GetColor(255,255,255),GetColor(255,255,255), TRUE);
DrawFormatString( 0, 0, GetColor( 255,255,255 ), "FlightVector x=%f y=%f z=%f", FlightVector.x, FlightVector.y, FlightVector.z ) ;
}
void update_main()
{
update_my();
update_fvec();
}
//---------------------------------------------------------
// クォータニオン版
//---------------------------------------------------------
VECTOR quaternion(VECTOR axis,VECTOR changevector,float rotation){
float rotap,rotaq,rotar,rotac;
VECTOR vectp,vectq,vectr,vectc;
rotap=0;
rotaq=cos(rotation/2);
rotar=cos(rotation/2);
vectp=changevector;
vectq=VGet(axis.x*sin(rotation/2),axis.y*sin(rotation/2),axis.z*sin(rotation/2));
vectr=VGet(-axis.x*sin(rotation/2),-axis.y*sin(rotation/2),-axis.z*sin(rotation/2));
rotac=rotar*rotap-VDot(vectr,vectp);
vectc=VAdd(VAdd(VGet(vectp.x*rotar,vectp.y*rotar,vectp.z*rotar),VGet(rotap*vectr.x,rotap*vectr.y,rotap*vectr.z)),VCross(vectr,vectp));
changevector=VAdd(VAdd(VGet(vectq.x*rotac,vectq.y*rotac,vectq.z*rotac),VGet(rotaq*vectc.x,rotaq*vectc.y,rotaq*vectc.z)),VCross(vectc,vectq));
return changevector;
}
// 自機の座標・傾きを更新
void update_Qmy()
{
// モデルの回転状態(機体軸でクォータニオン回転)
float RotX = 0.0f;
float RotY = 0.0f;
float RotZ = 0.0f;
if(1==CheckHitKey(KEY_INPUT_UP)) { RotX=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_DOWN)) { RotX=-(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_RIGHT)) { RotY=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_LEFT)) { RotY=-(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_A)) { RotZ=(PHI/180); }
if(1==CheckHitKey(KEY_INPUT_S)) { RotZ=-(PHI/180); }
// クォータニオン回転の計算
my.AxisY=quaternion(my.AxisX,my.AxisY,RotX);
my.AxisZ=quaternion(my.AxisX,my.AxisZ,RotX);
my.AxisX=quaternion(my.AxisY,my.AxisX,-RotY);
my.AxisZ=quaternion(my.AxisY,my.AxisZ,-RotY);
my.AxisX=quaternion(my.AxisZ,my.AxisX,-RotZ);
my.AxisY=quaternion(my.AxisZ,my.AxisY,-RotZ);
// モデルの表示データを設定。
MV1SetMatrix( my.model, MGetIdent() ) ;//マトリクスの初期化
MV1SetRotationZYAxis(my.model,my.AxisZ,my.AxisY,0.0f);
MV1SetPosition( my.model, my.position );
}
// 飛行ベクトルを得る。
void update_Qfvec()
{
// 飛行ベクトルを得る。
VECTOR FlightVector = my.AxisZ;
// 移動ベクトルとして位置に加算。
FlightVector = VScale( FlightVector, 5.0f ); //に拡大
my.position = VAdd( my.position, FlightVector );
}
void update_Qmain()
{
update_Qmy();
update_Qfvec();
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );
load_main();
my.position = VGet( 0.0f, 0.0f, 600.0f );
my.rotateMatrix = MGetIdent();
my.matrix = MGetIdent();
my.AxisX= VGet(1,0,0);
my.AxisY= VGet(0,1,0);
my.AxisZ= VGet(0,0,1);
SetCameraPositionAndTarget_UpVecY(VGet(0,0,0),VGet(0,0,100));
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 ) {
if(1==CheckHitKey(KEY_INPUT_1)) {
bQuaternion = false;
}
if(1==CheckHitKey(KEY_INPUT_2)) {
bQuaternion = true;
}
if( bQuaternion ) {
update_Qmain();
} else {
update_main();
}
graph_main();
}
DxLib_End();
return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。