
たとえばこの画像で黒線の長さが1とします。
x軸からa度、y軸からb度、z軸からc度離れているとして、
各軸の要素?を求めるにはどうすればいいですか?
まだ高校生2年生未満って事でしょうか?ヒューガ さんが書きました:行列もベクトルもまだ習ってないのでよくわかりません・・・
ベクトルの大きさは1、各座標平面からの角度はわかっている状態で、基軸成分を求める式です。
どういう計算をしたのでしょうか?ヒューガ さんが書きました:ひらめきません・・・
おかしい動きになってしまいます・・・
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は機体のローカルな傾斜です。
#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;
}
中心軸をずらして回転させるってことです。回転は原点を中心に回転します。ヒューガ さんが書きました:<原点以外を回転の中心にしたい場合は、座標に下駄を履かせて、回して、下駄を戻す操作をしてください。
とありますが下駄をはかせるとはどういうことでしょうか?
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に1フレームで動く角度を入れて、
それを6通りの軸の組み合わせでやることで出来ました。
ここでまたひとつ問題が。
戦闘機の頭をz軸のベクトルに合わせ、
戦闘機の背中をy軸に合わせたいのです。
どうすればいいでしょうか?
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);
}
#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;
}
ここのルールなのですがソースコードは他の人が参考にできるように動くものを掲載して頂くことになっていますので、よろしくお願いします。ヒューガ さんが書きました:えーとまず1度ずつの回転をxyz軸分掛けて
それを現在の方向に掛けて方向転換
方向転換分を現在位置からの回転行列にして
その行列をモデルに適用。
回転行列のz軸方向にベクトルを向ける
ということぐらいしかわかりません・・・
作っているゲームは元にしたゲームに近い動きをしてくれています。
今のところ問題ありません
えーと、コードを載せて頂けないのでしょうか?ヒューガ さんが書きました:わかりました。お騒がせしてごめんなさい。
#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;
}