角度からベクトル

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

角度からベクトル

#1

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

画像
たとえばこの画像で黒線の長さが1とします。
x軸からa度、y軸からb度、z軸からc度離れているとして、
各軸の要素?を求めるにはどうすればいいですか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: 角度からベクトル

#2

投稿記事 by h2so5 » 13年前

具体的にどの部分がa度,b度,c度なのか図示してください。

ヒューガ

Re: 角度からベクトル

#3

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

画像
ここで赤がa緑がb青がcです

non
記事: 1097
登録日時: 14年前

Re: 角度からベクトル

#4

投稿記事 by non » 13年前

軸からですか?
平面からの角度ではいけませんか?
non

ヒューガ

Re: 角度からベクトル

#5

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

ごめんなさい平面です

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

Re: 角度からベクトル

#6

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

2軸で回すなら基準方向のベクトルを行列演算すれば求められますよ。
Z回転は物体のローテーションになります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#7

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

行列もベクトルもまだ習ってないのでよくわかりません・・・
ベクトルの大きさは1、各座標平面からの角度はわかっている状態で、基軸成分を求める式です。

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

Re: 角度からベクトル

#8

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

ヒューガ さんが書きました:行列もベクトルもまだ習ってないのでよくわかりません・・・
ベクトルの大きさは1、各座標平面からの角度はわかっている状態で、基軸成分を求める式です。
まだ高校生2年生未満って事でしょうか?
三角関数は分かりますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#9

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

まだ高校1年生です・・・
三角関数ならわかります。

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

Re: 角度からベクトル

#10

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

各平面との角度が分かるのなら原点、平面、黒い線で直角三角形を形作りますから三角関数で計算できます。
やってみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#11

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

ひらめきません・・・
おかしい動きになってしまいます・・・

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

Re: 角度からベクトル

#12

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

ヒューガ さんが書きました:ひらめきません・・・
おかしい動きになってしまいます・・・
どういう計算をしたのでしょうか?
あと机上で紙に書いて確認したほうが良いと思います。

あとゲームは通常便利ですから軸周りの回転で管理します。
なんか飛行関係のゲームの様ですから軸周りの回転であるロール、ヨー、ピッチで管理したほうが良いと思いますよ。
ちなみに、行列計算になりますがパターンを覚えれば行列を知らなくても使えます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: 角度からベクトル

#13

投稿記事 by かずま » 13年前

ヒューガ さんが書きました: たとえばこの画像で黒線の長さが1とします。
x軸からa度、y軸からb度、z軸からc度離れているとして、
各軸の要素?を求めるにはどうすればいいですか?

コード:

    x = cos(a);
    y = cos(b);
    z = cos(c);
ヒューガ さんが書きました:ごめんなさい平面です
では、a はどの平面から黒線への角度なんですか?

ヒューガ

Re: 角度からベクトル

#14

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

aはx-z平面からの角度
bはy-z平面からの角度
cはよく考えたらいらないですね・・・

ヒューガ

Re: 角度からベクトル

#15

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

式は

コード:

	my.pitch=MGetRotAxis(VGet(cos(my.Rxyz.y),sin(my.Rxyz.z),sin(my.Rxyz.y)),my.Rxyz.x);
	my.yaw=MGetRotAxis(VGet(cos(my.Rxyz.z+PI/2),cos(my.Rxyz.x+PI/2),cos(my.Rxyz.x)),my.Rxyz.y);
	my.roll=MGetRotAxis(VGet(sin(my.Rxyz.y),sin(my.Rxyz.x),cos(my.Rxyz.y)),my.Rxyz.z);

my.Rxyzは機体のローカルな傾斜です。
これではまともに動いてくれないのです・・・

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

Re: 角度からベクトル

#16

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

ヒューガ さんが書きました:my.Rxyzは機体のローカルな傾斜です。
要はローカル座標系における機体の姿勢って事ですね。
三角関数だけで片付けるのはややこしい処理になるので、数学的な理解を置いておいて行列を使ったほうが良いと思います。
サンプルコードを用意しましょうか? こうすれば良いと言う使い方だけ覚えるんで良いと思います。

ただし、飛行機系のゲームは行列ではなくクォータニオン(四元数※間違い訂正)を使わないとジンバルロックと言う問題や上昇下降中に操作性が変わると言う問題を引き起こします。
「ジンバルロックを体験してみよう!2(PV3Dジャイロスコープ編) - wonderfl build flash online」
http://wonderfl.net/c/uTHS/
とりあえずは行列で良いと思いますが関数で分離しておいて将来的にクォータニオン対応を考えてみて下さい。

●過去のクォータニオンの参考ログ。
「揚力のベクトルを求める。(フライトシミュ) • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=4596
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: 角度からベクトル

#17

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

よく考えたらDXライブラリのモデル回転は標準搭載されているので何も考えなくて良いと気づきました。
※ あっ飛行ベクトルを忘れていたので後で追加します。
※※ 他にもマズイことに気づいたので出直してきます。

コード:

バグっていたので一旦消します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: 角度からベクトル

#18

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

このプログラムは飛行体としては問題があります。それは何処か分かりますか?考えてみて下さい。
あと、MATRIXなどの使い方として理解できますか?

参考。マトリクス(行列入門)
「わくわくプログラミング自習室 Blogs - 【DXライブラリ3D入門】モデルを移動する、回転する ~変形と行列」
http://i-libro.net/wpmu/blog/archives/618

コード:

#include "DxLib.h"


typedef struct {
	int model;
	VECTOR position;
	VECTOR rotate;
	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()
{
	//	モデルの回転状態(ただし、これはX,Yに関しては絶対軸の回転を行う)
	if(1==CheckHitKey(KEY_INPUT_UP))	{	my.rotate.x+=(PHI/180);	}
	if(1==CheckHitKey(KEY_INPUT_DOWN))	{	my.rotate.x-=(PHI/180);	}
	if(1==CheckHitKey(KEY_INPUT_RIGHT))	{	my.rotate.y+=(PHI/180);	}
	if(1==CheckHitKey(KEY_INPUT_LEFT))	{	my.rotate.y-=(PHI/180);	}
	if(1==CheckHitKey(KEY_INPUT_A))		{	my.rotate.z+=(PHI/180);	}
	if(1==CheckHitKey(KEY_INPUT_S))		{	my.rotate.z-=(PHI/180);	}
	//	リセット
	if(1==CheckHitKey(KEY_INPUT_RETURN)){	my.rotate = VGet( 0.0f, 0.0f, 0.0f );	}
	
	//	モデルの表示マトリクス。
	float RotX = my.rotate.x;
	float RotY = my.rotate.y;
	float RotZ = my.rotate.z;
	MATRIX matrix = MMult( MMult( MGetRotZ( RotZ ), MGetRotX( RotX ) ), MGetRotY( RotY ) );//絶対軸の回転
	my.matrix = MMult( matrix, 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.rotate = VGet( 0.0f, 0.0f, 0.0f );

	while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 ) {
		update_main();
		graph_main();
	}

	DxLib_End();
	return 0;
}

by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#19

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

最初に動かした回転の軸はローカルになりますが他はグローバルになりますね。
行列は移動や回転など掛けた順に動くということぐらいにしか・・・

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

Re: 角度からベクトル

#20

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

まぁ、分かってもらいたいのは行列の掛け算には順番があると言うことです。
回転行列x移動行列

移動行列x回転行列
では結果が変わります。

回転行列1x移動行列x回転行列2で回転行列1と回転行列2の働きは全然違います。
ぜひ試して実感してみて下さい。
数学理論よりも実感で覚えれば十分使えると思います。

で飛行体を4次元数を使わなくても私の知る限りジンバルロックせずに済む方法はありますが、少し嘘があるのと計算誤差が結構溜まるので宙返りすると完全には水平に戻りません(要補正)。
それは
進行方向の回転行列 = 今回の変更分の回転行列(急激に方向を変えないこと) x 進行方向の回転行列
として計算する方法です。
フライト系は専門ではないのでワナがあるかも知れませんし、カメラワークまで検証していないので困るかも知れませんが行列が有る程度実感できたらサンプルを後ほど提示します。
※ 飛行機と言うよりは重力制御の宇宙船と行ったほうが良いかも知れませんが、慣性・空気抵抗・加速・揚力・空力の物理要因が一切ありません。もちろん飛行機には必要です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#21

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

クォータニオンを使うつもりで勉強していますが
A = (a; U)
B = (b; V)
AB = (ab - U・V; aV + bU + U×V)
という式のab,aV,bUはそれぞれの乗算ということでいいんですね?

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

Re: 角度からベクトル

#22

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

そのはずです(さすがにクォータニオンの公式と実装を覚えてません)。

現在アクセス不能でサルベージしたのがあるので、こちらを参考にしてみてはどうでしょう。
四元数・4元数・クォータニオン・ Quaternionで回転
http://webcache.googleusercontent.com/s ... clnk&gl=jp
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#23

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

さっきの式の転載元と同じところでしたwww
しかしまだわからないところがあります。
たとえばさっきの式のaVというのはベクトルの要素にaを乗算するということでしょうか?
それと上のサイトに
<原点以外を回転の中心にしたい場合は、座標に下駄を履かせて、回して、下駄を戻す操作をしてください。
とありますが下駄をはかせるとはどういうことでしょうか?

ヒューガ

Re: 角度からベクトル

#24

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

もうひとつ。
見よう見まねで式を作っているのですが上のサイトにもある
ab-U
という式ですがどういうことでしょうか?

コード:

float a;
float b;
VECTOR U;
float scalar;
scalar=a*b-U;
こんなことできませんよね?
どうやってやるのでしょうか?

ヒューガ

Re: 角度からベクトル

#25

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

ごめんなさい内積はベクトルになるんじゃなかった
無視してください

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

Re: 角度からベクトル

#26

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

ヒューガ さんが書きました:<原点以外を回転の中心にしたい場合は、座標に下駄を履かせて、回して、下駄を戻す操作をしてください。
とありますが下駄をはかせるとはどういうことでしょうか?
中心軸をずらして回転させるってことです。回転は原点を中心に回転します。
この場合の下駄は座標です。背の高さをごまかすことを下駄を履かせるってところから来た比喩です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#27

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

見よう見まねで式を立ててみたんですがうまくいきません・・・
間違っているところがあれば指摘してください

コード:

void quaternion(VECTOR position,VECTOR flightvector,float rotation){
	float rotap,rotaq,rotar,rotac;
	VECTOR vectp,vectq,vectr,vectc;
	rotap=0;rotaq=cos(rotation/2);rotar=cos(rotation/2);
	vectp=position;
	vectq=VGet(flightvector.x*sin(rotation/2),flightvector.y*sin(rotation/2),flightvector.z*sin(rotation/2));
	vectr=VGet(-flightvector.x*sin(rotation/2),-flightvector.y*sin(rotation/2),-flightvector.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));
	flightvector=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));
}
positionには現在の座標を、flightvectorには戦闘機の向いてる方向、rotationには(おそらく)グローバル座標の角度を入れています。

コード:

void control_my(){
	if(key.up>0)my.Rxyz.x+=PI/180.0f;
	if(key.down>0)my.Rxyz.x-=PI/180.0f;
	if(key.right>0)my.Rxyz.z+=PI/180.0f;
	if(key.left>0)my.Rxyz.z-=PI/180.0f;
	if(key.lyaw>0)my.Rxyz.y+=PI/180.0f;
	if(key.ryaw>0)my.Rxyz.y-=PI/180.0f;
}
これが操作系統です

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

Re: 角度からベクトル

#28

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

そんなシンプルになるはずがないのですが参考にした式と対比して教えてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

Re: 角度からベクトル

#29

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

参考にした式は上記サイトの
A = (a; U)
B = (b; V)
AB = (ab - U・V; aV + bU + U×V)
P = (0; x, y, z)
Q = (cos(θ/2); α sin(θ/2), β sin(θ/2), γ sin(θ/2))
R = (cos(θ/2); -α sin(θ/2), -β sin(θ/2), -γ sin(θ/2))
R P Q = (0; 答え)
です。
まず
Pの実部は0、Qの実部は入力角の半分のコサイン値、Rの実部も同じ
Pの虚部に現在の座標を現すベクトル
Qの虚部に現在向いている方向のx成分*入力角の半分のサイン値、y成分*入力角の半分のサイン値、z成分*入力角の半分のサイン値をベクトルにしたもの
Rの虚部に現在向いている方向のx成分を正負反転*入力角の半分のサイン値、y成分を正負反転*入力角の半分のサイン値、z成分を正負反転*入力角の半分のサイン値をベクトルにしたもの
最初にRとQで計算し、結果をCとします。
Cの実部にRの実部とPの実部を乗算したものからRの虚部とPの虚部を内積したものを引きます。
Cの虚部にPの虚部とRの実部を乗算したもの、Pの実部とRの虚部を乗算したもの、Rの虚部とPの虚部の外積したものを加算していれます。
最後に進行方向のベクトルとして、
Qの虚部とCの実部を乗算したものと、Cの虚部とQの実部を乗算したものと、Cの虚部とQの虚部の外積したものを加算していれます。
こんな感じです

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

Re: 角度からベクトル

#30

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

元のコードのクォータニオンの計算と突き合わせをするプログラムを作ってみて下さい。
目的:両方の計算の違いを確認すること。
ヒューガさんのコードでパッと目に気になったのはR P Q = (0; 答え)と違う計算順番です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヒューガ

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) ダウンロード数: 174 回

コード:

#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言語何でも質問掲示板” へ戻る