3D空間でのカメラの向きと進行方向について
Posted: 2012年7月23日(月) 03:14
DXライブラリ、C言語、VC++2008EE、WindowsXP、メタセコイアという環境で3Dモデルを使ったゲームを作成しようと思っているのですが、今回カメラの扱いに慣れるためのプログラムを組んでみたところ、カメラの向きと進行方向が上手く一致せず困っています。
普通に「右が押されたらx++」「下が押されたらz--」という処理をしたところ、カメラの向きが左を向いているにも関わらず、右を押したらx軸通りに右へ、下を押したらz軸通りに下へ、という感じで進んでしまいます。
そこで「ゲームプログラミングの館 3.7章 特定の角度で弾を飛ばす」のプログラムを参考に、プログラムを以下のように組みました。
85-86行目の部分
ここで2Dのプログラムをそのまま応用してみたのですが、やっぱりうまい具合に動いてくれませんでした。
カメラの注視点に向かって進むにはどういった式にすればいいのでしょうか?
F欄工業高に通っているため、高3でありながら「ベクトル」や「行列」「空間図形」と言ったものを習わずにここまで来ました。
プログラムで3Dを扱うとなるとやはり独学でも「ベクトル」や「行列」、せめて「空間図形」は学んでおくべきですかね・・・。
とにかくカメラが向いている先に向かって進む方法を教えてもらいたいです。お願いします。
普通に「右が押されたらx++」「下が押されたらz--」という処理をしたところ、カメラの向きが左を向いているにも関わらず、右を押したらx軸通りに右へ、下を押したらz軸通りに下へ、という感じで進んでしまいます。
そこで「ゲームプログラミングの館 3.7章 特定の角度で弾を飛ばす」のプログラムを参考に、プログラムを以下のように組みました。
#include "./DxLib/DxLib.h"
#include <math.h>
//フルスクリーンで起動するかのメッセージボックス
int ChangeWindowMessageBox();
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMessageBox(),DxLib_Init(),SetDrawScreen(DX_SCREEN_BACK);
int ModelHandle1 = MV1LoadModel( "Model/test1.mqo" );
int ModelHandle2 = MV1LoadModel( "Model/test2.mqo" );
//カメラの位置
float Camera_Pos_X = 250.00f, Camera_Pos_Y = 350.00f, Camera_Pos_Z = 0.00f;
//カメラの注視点
float Camera_Rota_V = -0.00f, Camera_Rota_H = -0.00f, Camera_Rota_T = -0.00f;
//カメラの視野(っていうか双眼鏡みたいな役目)
float Camera_Fov = 50.0f, Camera_Fov_Parcent = 100.0f;
while( !ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey( KEY_INPUT_ESCAPE ) ){
//シフトと同時押しの処理
if( CheckHitKey( KEY_INPUT_LSHIFT ) || CheckHitKey( KEY_INPUT_RSHIFT ) ){
if( CheckHitKey( KEY_INPUT_UP ) && Camera_Rota_V >= -90.0f*PHI_F/180.0f )
Camera_Rota_V -= PHI_F/180.0f;
if( CheckHitKey( KEY_INPUT_DOWN ) && Camera_Rota_V <= 90.0f*PHI_F/180.0f )
Camera_Rota_V += PHI_F/135.0f;
if( CheckHitKey( KEY_INPUT_LEFT ) )
Camera_Rota_H -= PHI_F/135.0f;
if( CheckHitKey( KEY_INPUT_RIGHT ) )
Camera_Rota_H += PHI_F/135.0f;
}
//Ctrlと同時押しの処理
else if( CheckHitKey( KEY_INPUT_LCONTROL ) || CheckHitKey( KEY_INPUT_RCONTROL ) ){
if( CheckHitKey( KEY_INPUT_UP ) && Camera_Fov > 10.0f ) {
Camera_Fov--;
Camera_Fov_Parcent += 100.0f / 40.0f;
}
if( CheckHitKey( KEY_INPUT_DOWN ) && Camera_Fov < 50.0f ){
Camera_Fov++;
Camera_Fov_Parcent -= 100.0f / 40.0f;
}
if( CheckHitKey( KEY_INPUT_RIGHT ) && Camera_Rota_T > -90.0f*PHI_F/180.0f )
Camera_Rota_T -= PHI_F/135.0f;
if( CheckHitKey( KEY_INPUT_LEFT ) && Camera_Rota_T < 90.0f*PHI_F/180.f )
Camera_Rota_T += PHI_F/135.0f;
}
//単体で押された時の処理
else{
if( CheckHitKey( KEY_INPUT_F1 ) || CheckHitKey( KEY_INPUT_SPACE ) ) Camera_Rota_V = -0.0f;
if( CheckHitKey( KEY_INPUT_F2 ) || CheckHitKey( KEY_INPUT_SPACE ) ) Camera_Rota_H = -0.0f;
if( CheckHitKey( KEY_INPUT_F3 ) || CheckHitKey( KEY_INPUT_SPACE ) ) Camera_Rota_T = -0.0f;
if( CheckHitKey( KEY_INPUT_F4 ) || CheckHitKey( KEY_INPUT_SPACE ) ) Camera_Pos_X = 250.0f;
if( CheckHitKey( KEY_INPUT_F5 ) || CheckHitKey( KEY_INPUT_SPACE ) ) Camera_Pos_Y = 350.0f;
if( CheckHitKey( KEY_INPUT_F6 ) || CheckHitKey( KEY_INPUT_SPACE ) ) Camera_Pos_Z = 0.0f;
if( CheckHitKey( KEY_INPUT_F7 ) || CheckHitKey( KEY_INPUT_SPACE ) ){
Camera_Fov = 50.0f;
Camera_Fov_Parcent = 100.0f;
}
if( CheckHitKey( KEY_INPUT_UP ) ) Camera_Pos_Z += 10.0f;
if( CheckHitKey( KEY_INPUT_DOWN ) ) Camera_Pos_Z -= 10.0f;
if( CheckHitKey( KEY_INPUT_LEFT ) ) Camera_Pos_X -= 10.0f;
if( CheckHitKey( KEY_INPUT_RIGHT ) ) Camera_Pos_X += 10.0f;
}
//モデルの変形処理
MV1SetPosition( ModelHandle1, VGet( -50,240,600 ) );
MV1SetRotationXYZ( ModelHandle1, VGet( -30.0f*PHI_F/180.0f,-90.0f*PHI_F/180.0f, 0.0f) );
MV1SetPosition( ModelHandle2, VGet( 500,240,600 ) );
MV1SetRotationXYZ( ModelHandle2, VGet( 0.0f,90.0f*PHI_F/180.0f, 0.0f) );
//カメラの処理
SetCameraNearFar( 10, 1000 );
SetupCamera_Perspective( Camera_Fov*PHI_F/180.0f );
//↓ここでx=cos(angle)*r、y=sin(angle)*rを応用してみた
SetCameraPositionAndAngle( VGet( cos( Camera_Rota_H )*Camera_Pos_X, Camera_Pos_Y, sin( Camera_Rota_H )*Camera_Pos_Z ),
Camera_Rota_V, Camera_Rota_H, Camera_Rota_T );
//モデルの描画
MV1DrawModel( ModelHandle1 );
MV1DrawModel( ModelHandle2 );
//数値が見えるように
DrawFormatString( 5, 0, GetColor( 255,255,255 ), "CameraRota[V] : %f <%.1f°>", -Camera_Rota_V, -Camera_Rota_V*180.0f/PHI_F );
DrawFormatString( 5,20, GetColor( 255,255,255 ), "CameraRota[H] : %f <%.1f°>", -Camera_Rota_H, -Camera_Rota_H*180.0f/PHI_F );
DrawFormatString( 5,40, GetColor( 255,255,255 ), "CameraRota[T] : %f <%.1f°>", -Camera_Rota_T, -Camera_Rota_T*180.0f/PHI_F );
DrawFormatString( 5,60, GetColor( 255,255,255 ), "CameraFov : %.1f <%.1f%%>", Camera_Fov, Camera_Fov_Parcent );
DrawFormatString( 5,80, GetColor( 255,255,255 ), "CameraPos [X] : %.1f", Camera_Pos_X );
DrawFormatString( 5,100, GetColor( 255,255,255 ),"CameraPos [Y] : %.1f", Camera_Pos_Y );
DrawFormatString( 5,120,GetColor( 255,255,255 ), "CameraPos [Z] : %.1f", Camera_Pos_Z );
}
DxLib_End();
return 0;
}
//フルスクリーンで起動するかのメッセージボックス
int ChangeWindowMessageBox(){
int Flag = MessageBox( NULL,
TEXT("フルスクリーンで表示しますか?"),
TEXT("スクリーン設定"),
MB_YESNO | MB_ICONQUESTION
);
if( Flag == IDNO )
if( ChangeWindowMode( TRUE ) != 0 )
return -1;
return 0;
}
SetCameraPositionAndAngle( VGet( cos( Camera_Rota_H )*Camera_Pos_X, Camera_Pos_Y, sin( Camera_Rota_H )*Camera_Pos_Z ),
Camera_Rota_V, Camera_Rota_H, Camera_Rota_T );
カメラの注視点に向かって進むにはどういった式にすればいいのでしょうか?
F欄工業高に通っているため、高3でありながら「ベクトル」や「行列」「空間図形」と言ったものを習わずにここまで来ました。
プログラムで3Dを扱うとなるとやはり独学でも「ベクトル」や「行列」、せめて「空間図形」は学んでおくべきですかね・・・。
とにかくカメラが向いている先に向かって進む方法を教えてもらいたいです。お願いします。

