角度からベクトル

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ヒューガ

Re: 角度からベクトル

#31

投稿記事 by ヒューガ » 13年前

さっきの式の間違いが見つかりました。
positionに角度を変更したい回転軸、
flightvectorに変更の基準となる回転軸、
rotationに1フレームで動く角度を入れて、
それを6通りの軸の組み合わせでやることで出来ました。
ここでまたひとつ問題が。
戦闘機の頭をz軸のベクトルに合わせ、
戦闘機の背中をy軸に合わせたいのです。
どうすればいいでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 角度からベクトル

#32

投稿記事 by softya(ソフト屋) » 13年前

ヒューガ さんが書きました:さっきの式の間違いが見つかりました。
positionに角度を変更したい回転軸、
flightvectorに変更の基準となる回転軸、
rotationに1フレームで動く角度を入れて、
それを6通りの軸の組み合わせでやることで出来ました。
ここでまたひとつ問題が。
戦闘機の頭をz軸のベクトルに合わせ、
戦闘機の背中をy軸に合わせたいのです。
どうすればいいでしょうか?
コードは掲載してくださいね。
あと機軸は変化するのにZ軸とY軸に合わせて良いのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#33

投稿記事 by ヒューガ » 13年前

コード:

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;
}
axisを基準にchangevectorのベクトルをrotation分偏向したものを返します。

コード:

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);
}
これで進行方向が決まりました。上のコードでは速度を10として進行方向に進みます。
x-z平面からベクトルまでの角度をmy.Rxyz.x,y-z平面からベクトルまでの角度をmy.Rxyz.y
ごめんなさい、my.Rxyz.zはどうつかえばいいのでしょう・・・
最終的にはMV1SetRotationXYZ(my.model,my.Rxyz);
で機体の角度を決定します。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 角度からベクトル

#34

投稿記事 by softya(ソフト屋) » 13年前

Rxyzが突然出てきてますが、どこで計算しているんでしょうか?
あとzはロールで使うと思いますが?

【補足】
提案ですがベクトルから機体の向きをセットするのは、これが良いと思います。
「MV1SetRotationZYAxis」
http://homepage2.nifty.com/natupaji/DxL ... .html#R3N8
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#35

投稿記事 by ヒューガ » 13年前

MV1SetRotationZYAxisで動きました!ありがとうございました!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 角度からベクトル

#36

投稿記事 by softya(ソフト屋) » 13年前

参考に、とりあえずオイラー角版をアップしておきます。出来れば、これにクォータニオンを対応させてみて下さい。
超適当飛行体モデルもアップしておきます。
 → 作成されたクォータニオンが目的の動作が出来るかの確認って事ですね。オイラー角同等以上の飛行体の挙動を実現できるならOKです。
test.zip
(1.1 KiB) ダウンロード数: 175 回

コード:

#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: 角度からベクトル

#37

投稿記事 by ヒューガ » 13年前

えーとまず1度ずつの回転をxyz軸分掛けて
それを現在の方向に掛けて方向転換
方向転換分を現在位置からの回転行列にして
その行列をモデルに適用。
回転行列のz軸方向にベクトルを向ける
ということぐらいしかわかりません・・・
作っているゲームは元にしたゲームに近い動きをしてくれています。
今のところ問題ありません

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 角度からベクトル

#38

投稿記事 by softya(ソフト屋) » 13年前

ヒューガ さんが書きました:えーとまず1度ずつの回転をxyz軸分掛けて
それを現在の方向に掛けて方向転換
方向転換分を現在位置からの回転行列にして
その行列をモデルに適用。
回転行列のz軸方向にベクトルを向ける
ということぐらいしかわかりません・・・
作っているゲームは元にしたゲームに近い動きをしてくれています。
今のところ問題ありません
ここのルールなのですがソースコードは他の人が参考にできるように動くものを掲載して頂くことになっていますので、よろしくお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#39

投稿記事 by ヒューガ » 13年前

わかりました。お騒がせしてごめんなさい。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 角度からベクトル

#40

投稿記事 by softya(ソフト屋) » 13年前

ヒューガ さんが書きました:わかりました。お騒がせしてごめんなさい。
えーと、コードを載せて頂けないのでしょうか?
他の人の参考になりそうなので、ぜひ掲載をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#41

投稿記事 by ヒューガ » 13年前

進行方向と背中の決定は上記のコードで

コード:

MV1SetRotationZYAxis(my.model,my.AxisZ,my.AxisY,0.0f);
これで機体の姿勢を決定します。
該当箇所はこれだけかと

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 角度からベクトル

#42

投稿記事 by softya(ソフト屋) » 13年前

ありがとうございます。

【追記】
参考になる様にオイラー角とクォータニオン両方で比較できるコードを作りました。
使用キー: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(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る