いっちさんの
>ベクトルでモデルの姿勢を制御する場合は MV1SetRotationZYAxis が使えると思います。
この助言をヒントにソースを書き換えてみました。
カメラの方向に対して直角・平行の向きのベクトルを利用してモデルの回転を実装することができました。
これで回転値を気にせずベクトルだけで向きを直角方向に向けることができそうです。
回転させるアニメーションを実装したくなった場合は本家のサンプルを参考にしたいと思います。
最後にお伺いしたいのですが、171行目において逆ベクトルを指定しているのですが、
MV1SetRotationZYAxis関数が指定する z 軸方向は負の方向が基準なのでしょうか。
以下ソースです。
#include <DxLib.h>
#include <math.h>
void InitProcess( ) ; // 初期化処理
void InputProcess( ) ; // 入力処理
void DirectionProcess( ) ; // モデルの向きに関する処理
void CameraProcess( ) ; // カメラの処理
void DrawProcess( ) ; // 描画処理
VECTOR Direction ; // モデルの向いているベクトル
VECTOR Camera ; // カメラのベクトル
// 回転値
float camera_angle = 0.0f ;
float direction_angle = 0.0f ;
// キーボード入力状態取得配列
char buffer[ 256 ] ;
// それぞれの距離
float distance_Camera = 0.0f ; // 原点からのカメラの距離
float distance_Direction = 0.0f ; // 原点からモデルが向いている方向のベクトルの位置の距離
// フォントのハンドル
int FontHandle = 0 ;
// モデルのハンドル
int ModelHandle = 0 ;
int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdShow , int cmdLine )
{
// ウィンドウモードに変更しサイズを指定
ChangeWindowMode( TRUE ) ;
SetGraphMode( 1280 , 1024 , 32 ) ;
// DXライブラリの初期化
if( DxLib_Init( ) == -1 )
return 0 ;
// 初期化系処理
InitProcess( ) ;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// メインループはOSによる割り込みか ESCAPE キーが入力されるまで実行
while( ProcessMessage( ) != -1 && CheckHitKey( KEY_INPUT_ESCAPE ) != 1 ) {
// 描画対象を消去
ClearDrawScreen( ) ;
// 入力処理
InputProcess( ) ;
// モデルの向き等の処理
DirectionProcess( ) ;
// カメラ処理
CameraProcess( ) ;
//描画処理
DrawProcess( ) ;
// 裏画面の描画対象を表画面に反映
ScreenFlip( ) ;
}
// DXライブラリ終了処理
DxLib_End( ) ;
return 0 ;
}
void InitProcess( )
{
// 裏画面描画に設定
SetDrawScreen( DX_SCREEN_BACK ) ;
// モデルの読み込み
ModelHandle = MV1LoadModel( "DxChara.x" ) ;
// モデルのスケールを変更
MV1SetScale( ModelHandle , VGet( 0.01f , 0.01f , 0.01f ) ) ;
// モデルを原点に配置
MV1SetPosition( ModelHandle , VGet( 0.0f , 0.0f , 0.0f ) ) ;
// カメラの初期位置セット
Camera = VGet( 50 , 50 , 50 ) ;
// 手前クリップ距離と奥クリップ距離を設定
SetCameraNearFar( 1.0f , 10000.0f ) ;
// カメラの位置を設定 注視点は原点より少し上に設定
SetCameraPositionAndTarget_UpVecY( Camera , VGet( 0 , 10 , 0 ) ) ;
// 初期位置を z に負の方向にセット
Direction = VGet( 10 , 0 , 10 ) ;
// はじめにパイ回しておくとなぜかうまくいく
MV1SetRotationXYZ( ModelHandle, VGet( 0.0f , PHI_F , 0.0f ) ) ;
// 距離を設定
distance_Camera = sqrt( pow( Camera.x , 2 ) + pow( Camera.y , 2 ) + pow( Camera.z , 2 ) ) ;
// 長さを設定
distance_Direction = sqrt( pow( Direction.x , 2 ) + pow( Direction.y , 2 ) + pow( Direction.z , 2 ) ) ;
// フォントデータを作成
FontHandle = CreateFontToHandle( NULL , 13 , 5 , DX_FONTTYPE_EDGE ) ;
// ライトを初期位置で見やすいように設定
SetLightDirection( VGet( -Camera.x , -Camera.y , -Camera.z ) ) ;
}
void InputProcess( )
{
// キーボードの入力状態を取得する
GetHitKeyStateAll( buffer ) ;
// 線分に回転値を与える
if( buffer[ KEY_INPUT_L ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) direction_angle += 0.1f ;
if( buffer[ KEY_INPUT_R ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) direction_angle -= 0.1f ;
// 距離を変更する
if( buffer[ KEY_INPUT_L ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 && distance_Direction < 90.0f ) distance_Direction += 1.0f ;
if( buffer[ KEY_INPUT_R ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 && distance_Direction > 15.0f ) distance_Direction -= 1.0f ;
// カメラの回転値を与える
if( buffer[ KEY_INPUT_LEFT ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) camera_angle -= 0.01f ;
if( buffer[ KEY_INPUT_RIGHT ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) camera_angle += 0.01f ;
// カメラの距離を変更
if( buffer[ KEY_INPUT_UP ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) distance_Camera -= 0.5f ;
if( buffer[ KEY_INPUT_DOWN ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) distance_Camera += 0.5f ;
// カメラに対する線分の直角回転
if( buffer[ KEY_INPUT_LEFT ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) Direction = VGet( Camera.z , 0.0f , -Camera.x ) ;
if( buffer[ KEY_INPUT_RIGHT ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) Direction = VGet( -Camera.z , 0.0f , Camera.x ) ;
if( buffer[ KEY_INPUT_UP ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) Direction = VGet( -Camera.x , 0.0f , -Camera.z ) ;
if( buffer[ KEY_INPUT_DOWN ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) Direction = VGet( Camera.x , 0.0f , Camera.z ) ;
// モデルの上向き下向きを設定
if( buffer[ KEY_INPUT_U ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) Direction.y += 0.01f ;
if( buffer[ KEY_INPUT_D ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) Direction.y -= 0.01f ;
}
void DirectionProcess( )
{
float PreX = Direction.x ;
float PreY = Direction.y ;
float PreZ = Direction.z ;
// 回転
Direction.x = cos( direction_angle ) * PreX - sin( direction_angle ) * PreZ ;
Direction.z = sin( direction_angle ) * PreX + cos( direction_angle ) * PreZ ;
PreX = Direction.x ;
PreZ = Direction.z ;
// 距離変化
Direction.x *= distance_Direction / sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) ;
Direction.y *= distance_Direction / sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) ;
Direction.z *= distance_Direction / sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) ;
PreX = Direction.x ;
PreY = Direction.y ;
PreZ = Direction.z ;
// 回転方向は指定した z 軸方向のベクトル向き なぜか逆ベクトルの指定でうまくいく
MV1SetRotationZYAxis( ModelHandle, VGet( -Direction.x , -Direction.y , -Direction.z ) , VGet( 0.0f , 1.0f , 0.0f ), 0.0f ) ;
// 回転値を戻す
direction_angle = 0.0f ;
}
void CameraProcess( )
{
float PreX = Camera.x ;
float PreY = Camera.y ;
float PreZ = Camera.z ;
// 回転
Camera.x = cos( camera_angle ) * PreX - sin( camera_angle ) * PreZ ;
Camera.z = sin( camera_angle ) * PreX + cos( camera_angle ) * PreZ ;
PreX = Camera.x ;
PreY = Camera.y ;
PreZ = Camera.z ;
// 距離変化
Camera.x *= distance_Camera / sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) ;
Camera.y *= distance_Camera / sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) ;
Camera.z *= distance_Camera / sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) ;
PreX = Camera.x ;
PreY = Camera.y ;
PreZ = Camera.z ;
// 距離の変更を加える
Camera.x *= sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) / distance_Camera ;
Camera.y *= sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) / distance_Camera ;
Camera.z *= sqrt( pow( PreX , 2 ) + pow( PreY , 2 ) + pow( PreZ , 2 ) ) / distance_Camera ;
PreX = Camera.x ;
PreY = Camera.y ;
PreZ = Camera.z ;
// カメラの位置を再セット
SetCameraPositionAndTarget_UpVecY( Camera , VGet( 0.0f , 0.0f , 0.0f ) ) ;
// 回転値を戻す
camera_angle = 0.0f ;
}
void DrawProcess( )
{
// モデルの描画
MV1DrawModel( ModelHandle ) ;
// 軸の表示
DrawLine3D( VGet( 0 , 0 , 0 ) , VGet( 10000 , 0 , 0 ) , GetColor( 255 , 0 , 0 ) ) ;
DrawLine3D( VGet( 0 , 0 , 0 ) , VGet( 0 , 10000 , 0 ) , GetColor( 0 , 255 , 0 ) ) ;
DrawLine3D( VGet( 0 , 0 , 0 ) , VGet( 0 , 0 , 10000 ) , GetColor( 0 , 0 , 255 ) ) ;
// 回転線分の表示
DrawLine3D( VGet( 0 , 0 , 0 ) , Direction , GetColor( 0 , 255 , 255 ) ) ;
// 各種データ表示
DrawFormatStringToHandle( 0 , 0 , GetColor( 255 , 255 , 255 ) , FontHandle , "Direction.x = %f" , Direction.x ) ;
DrawFormatStringToHandle( 0 , 13 , GetColor( 255 , 255 , 255 ) , FontHandle , "Direction.y = %f" , Direction.y ) ;
DrawFormatStringToHandle( 0 , 26 , GetColor( 255 , 255 , 255 ) , FontHandle , "Direction.z = %f" , Direction.z ) ;
DrawFormatStringToHandle( 0 , 39 , GetColor( 255 , 255 , 255 ) , FontHandle , "Camera.x = %f" , Camera.x ) ;
DrawFormatStringToHandle( 0 , 52 , GetColor( 255 , 255 , 255 ) , FontHandle , "Camera.y = %f" , Camera.y ) ;
DrawFormatStringToHandle( 0 , 65 , GetColor( 255 , 255 , 255 ) , FontHandle , "Camera.z = %f" , Camera.z ) ;
DrawFormatStringToHandle( 0 , 78 , GetColor( 255 , 255 , 255 ) , FontHandle , "distance_Camera = %f" , distance_Camera ) ;
DrawFormatStringToHandle( 0 , 91 , GetColor( 255 , 255 , 255 ) , FontHandle , "distance_Direction = %f" , distance_Direction ) ;
}