トップページ > 過去ログ > 記事閲覧
atan2関数による角度算出について
名前:もやし 日時: 2012/04/24 00:21

現在atan2関数を使って2つのベクトルの成す角を求めて回転させる量をとっているのですが、これだとなぜか私のプログラムでは xy 平面と zy 平面で挙動がおかしくなります。 それと、この方法で実装しようとしているのは3Dで扱うモデルが常に十字キーの入力によって画面に対して奥、手前、左右方向へそれぞれ移動させることです。 モデルの回転は角を求めないといけませんからatan2は必須だと思っていたのですが、例外(引数 0 付近)もきっちり処理せねばならないということなのでしょうか。何か優秀な処理方法があれば教えてくださるとありがたいです。 以下がソースになります。 #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 ] ; // それぞれの距離 distance_Camera はカメラの回転による誤差補正に使う float distance_Camera = 0.0f ; // 原点からカメラの距離 float distance_Direction = 0.0f ; // 原点から線分の先端の距離 float distance_Camera_additional = 0.0f ; // フォントのハンドル int FontHandle = 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による割り込みか EXCAPE キーが入力されるまで実行 while( ProcessMessage( ) != -1 && CheckHitKey( KEY_INPUT_ESCAPE ) != 1 ) { // 描画対象を消去 ClearDrawScreen( ) ; // 入力処理 InputProcess( ) ; // 線分の処理 DirectionProcess( ) ; // カメラ処理 CameraProcess( ) ; //描画処理 DrawProcess( ) ; // 裏画面の描画対象を表画面に反映 ScreenFlip( ) ; //WaitKey( ) ; } // DXライブラリ終了処理 DxLib_End( ) ; return 0 ; } void InitProcess( ) { // 裏画面描画に設定 SetDrawScreen( DX_SCREEN_BACK ) ; // カメラの初期位置も z に負の方向にセット Camera = VGet( 30 , 30 , 30 ) ; // 手前クリップ距離と奥クリップ距離を設定 SetCameraNearFar( 1.0f , 10000.0f ) ; // カメラの位置を設定 注視点は原点より少し上に設定 SetCameraPositionAndTarget_UpVecY( Camera , VGet( 0 , 10 , 0 ) ) ; // 初期位置を z に負の方向にセット Direction = VGet( 5 , 0 , 5 ) ; // 距離を設定 distance_Camera = sqrt( pow( Camera.x , 2 ) + pow( Camera.z , 2 ) ) ; // 長さを設定 distance_Direction = sqrt( pow( Direction.x , 2 ) + pow( Direction.z , 2 ) ) ; // フォントデータを作成 FontHandle = CreateFontToHandle( NULL , 13 , 5 , DX_FONTTYPE_EDGE ) ; } void InputProcess( ) { // キーボードの入力状態を取得する GetHitKeyStateAll( buffer ) ; // 線分の長さを変更 if( buffer[ KEY_INPUT_L ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) direction_angle += 0.01f ; if( buffer[ KEY_INPUT_R ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) direction_angle -= 0.01f ; // 距離を変更する if( buffer[ KEY_INPUT_L ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 && distance_Direction > 5 ) distance_Direction += -0.01f ; if( buffer[ KEY_INPUT_R ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 && distance_Direction < 20 ) distance_Direction += +0.01f ; // カメラの回転値を与える 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.01f ; if( buffer[ KEY_INPUT_DOWN ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 0 ) distance_Camera += +0.01f ; // カメラに対する線分の直角移動 if( buffer[ KEY_INPUT_LEFT ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) direction_angle = atan2( Direction.x * Camera.z - Direction.z * Camera.x , Direction.x * Camera.x + Direction.z * Camera.z ) - PHI_F / 2 ; if( buffer[ KEY_INPUT_RIGHT ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) direction_angle = atan2( Direction.x * Camera.z - Direction.z * Camera.x , Direction.x * Camera.x + Direction.z * Camera.z ) + PHI_F / 2 ; if( buffer[ KEY_INPUT_UP ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) direction_angle = atan2( Direction.x * Camera.z - Direction.z * Camera.x , Direction.x * Camera.x + Direction.z * Camera.z ) + PHI_F ; if( buffer[ KEY_INPUT_DOWN ] == 1 && buffer[ KEY_INPUT_LSHIFT ] == 1 ) direction_angle = atan2( Direction.x * Camera.z - Direction.z * Camera.x , Direction.x * Camera.x + Direction.z * Camera.z ) ; } void DirectionProcess( ) { // 回転 Direction.x = cos( direction_angle ) * Direction.x - sin( direction_angle ) * Direction.z ; Direction.z = sin( direction_angle ) * Direction.x + cos( direction_angle ) * Direction.z ; // 回転に伴う距離変化の補正 Direction.x *= distance_Direction / sqrt( pow( Direction.x , 2 ) + pow( Direction.z , 2 ) ) ; Direction.z *= distance_Direction / sqrt( pow( Direction.x , 2 ) + pow( Direction.z , 2 ) ) ; // 回転値を戻す direction_angle = 0.0f ; } void CameraProcess( ) { // 回転 Camera.x = cos( camera_angle ) * Camera.x - sin( camera_angle ) * Camera.z ; Camera.z = sin( camera_angle ) * Camera.x + cos( camera_angle ) * Camera.z ; // 回転に伴う距離変化の補正 Camera.x *= distance_Camera / sqrt( pow( Camera.x , 2 ) + pow( Camera.z , 2 ) ) ; Camera.z *= distance_Camera / sqrt( pow( Camera.x , 2 ) + pow( Camera.z , 2 ) ) ; // 距離の変更を加える Camera.x *= sqrt( pow( Camera.x , 2 ) + pow( Camera.z , 2 ) ) / distance_Camera ; Camera.z *= sqrt( pow( Camera.x , 2 ) + pow( Camera.z , 2 ) ) / distance_Camera ; // カメラの位置をリセット SetCameraPositionAndTarget_UpVecY( Camera , VGet( 0 , 10 , 0 ) ) ; // 回転値を戻す camera_angle = 0.0f ; } void DrawProcess( ) { // 軸の表示 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 ) ; } あと、シフト+十字キーで線分を動かしたときに初期角度以外でブレが見られるのですがその原因がわかる方が居られましたら教えてくださるとありがたいです。

Page: 1 |

Re: atan2関数による角度算出について ( No.1 )
名前:もやし 日時:2012/04/24 00:23

すみません、若干コメントアウトで間違いの部分がありますが読み飛ばしてください。
Re: atan2関数による角度算出について ( No.2 )
名前:h2so5 日時:2012/04/24 16:47

本題と関係無いですが、 sqrt( pow( Direction.x , 2 ) + pow( Direction.z , 2 ) ) ; という書き方は冗長なので hypot(Direction.x, Direction.z); をお勧めします。
Re: atan2関数による角度算出について ( No.3 )
名前:いっち 日時:2012/04/24 19:45

もやしさん> 「DXライブラリサンプルプログラム」の「2.3Dアクション基本」はご参考になりませんか? > h t t p://homepage2.nifty.com/natupaji/DxLib/program/dxprogram_3DAction.html
Re: atan2関数による角度算出について ( No.4 )
名前:もやし 日時:2012/04/24 23:13

h2so5さん、ご指摘ありがとうございます。以後そのようにさせていただきます。 いっちさん // プレイヤーの向きを変える処理 の部分を読んでもいまいち何が行われいているのかわからなかったのでもしよろしければ簡単な処理の意味を教えてくださるとありがたいです。 私はあるホームページで外積と内積を用いて角度(-180<θ<180)を求めることができるとありましたので何も考えず流用してしまったのがいけないようです。 たとえば、-90°回転していて、次の回転が135°だとします。 このとき、TargetAngle = atan2( pl.TargetMoveDirection.x, pl.TargetMoveDirection.z ) ; と SaAngle = TargetAngle - pl.Angle ; によってSaAngleは225°を得ることになり、次の処理でSaAngle225-180で45°を得ることになります。 次のPLAYER_ANGLE_SPEEDの減算で44.8°を得ることになります。 pl.Angle = TargetAngle - SaAngle ;によって135-44.8=90.2°の回転を得るわけですが、 MV1SetRotationXYZ( pl.ModelHandle, VGet( 0.0f, pl.Angle + PHI_F, 0.0f ) ) ; によって180°が加算されているから結局-180°<θ<180°で見れば-89.8°の回転を得ることになるんですよね。 これだと向いている方向と逆向きに回転しているような気がするのですが、なぜなのでしょうか。
Re: atan2関数による角度算出について ( No.5 )
名前:もやし 日時:2012/04/24 23:35

すみません、また間違えました。 によってSaAngleは225°を得ることになり、次の処理でSaAngle225-180で45°を得ることになります。 という部分はSaAngle225-360で-135°を得ることになるようです。この差が負だから-134.8°を得ることになると思います。 よってpl.Angle = TargetAngle - SaAngle ;によって 269.8°を得ることができ1フレーム辺りに若干の回転がなされるということですね。 初めて間もないのでいろいろわからないことが多いのですが、 // 差がマイナスの場合は足す SaAngle += PLAYER_ANGLE_SPEED ; の部分に入るときは差が大きくなるかと思いきや小さくなったり、最後に目標の座標と差を加算しているのがとても不自然に思えたりと困惑しております。 やはりこのやり方が一般的な処理方法になっているんでしょうか。
Re: atan2関数による角度算出について ( No.6 )
名前:いっち 日時:2012/04/25 00:21

もやしさん> もやしさんの仰っている処理はおそらく Player_AngleProcess 内の事だと思うのですが、 Player_AngleProcess はキャラクターに振り向くアニメーションをつけるための処理であり、 モデルの移動とは関係ないように思います。 もやしさんのなさりたいことはカメラに合わせてモデルを移動させる事ではないのでしょうか?
Re: atan2関数による角度算出について ( No.7 )
名前:もやし 日時:2012/04/25 20:41

>もやしさんのなさりたいことはカメラに合わせてモデルを移動させる事ではないのでしょうか? すみません、質問内容にまた不備がありました申し訳ないです。 >十字キーの入力によって画面に対して奥、手前、左右方向へそれぞれ移動させることです この部分の「移動」が「回転」でした。 >もやしさんの仰っている処理はおそらく Player_AngleProcess 内の事だと思うのですが、 はいそのとおりでPlayer_AngleProcess内のことです。 実はカメラに合わせてモデルを移動させることに関してはできているんです。 自分で考えた方法なので計算量が優れているかはわかりませんが、カメラの位置のベクトルから入力の上下左右で進む方向のベクトルを決めます。 自分のいるところをカメラの位置、視点をモデルの位置とすればベクトル(x,z)に対して左が入力されれば(z,-x)、 右なら(-z、x)、下ならそのまま(x,z)、上なら(-x,-z)という風にして進む方向のベクトルを求めてしまいます。 その後正規化してそれを幾分かスカラー倍して次の移動先を得ることができました。 しかし、これだとモデルの回転については全く考えていなかったので、 最後に回転させた方向(途中でいじらないので初期配置)方向を向きながらxz平面を移動するだけになってしまったのでモデルの向くべき方向をベクトルを利用してどう表現しようかわからなくなってしまい質問させていただきました。 >Player_AngleProcess はキャラクターに振り向くアニメーションをつけるための処理であり、 モデルの移動とは関係ないように思います。 モデルの移動する方向のベクトル(pl.TargetMoveDirection)を用いて回転する方向が決まったり回転を付加する回数が決まっているように感じられるので、 モデルの移動に直接関係があるように思うのですがいかがなものなのでしょうか。
Re: atan2関数による角度算出について ( No.8 )
名前:いっち 日時:2012/04/25 23:10

ほとんどお分かりになっているようですが Player_AngleProcess の処理の流れを文字に起こすと以下のような感じになると思います。 @[最終的に向けたい角度] - [現在向いている角度] から [角度の差] を求める A[角度の差] を -π 〜 π の間で表現することにより右回り、左回りを決める B[角度の差] の絶対値 を少し([PLAYER_ANGLE_SPEED])小さくする([角度の差]を 0 に近づける->[角度の差]を無くす) C[最終的に向けたい角度] - [角度の差] を [現在向いている角度] に設定する > MV1SetRotationXYZ( pl.ModelHandle, VGet( 0.0f, pl.Angle + PHI_F, 0.0f ) ) ; ここで "pl.Angle + PHI_F" としているのはモデルのデフォルトの方向と pl.Angle で管理する方向に誤差があるので補正を行っているだけだと思います。 > モデルの向くべき方向をベクトルを利用してどう表現しようかわからなくなってしまい質問させていただきました。 ベクトルでモデルの姿勢を制御する場合は MV1SetRotationZYAxis が使えると思います。 > >Player_AngleProcess はキャラクターに振り向くアニメーションをつけるための処理であり、モデルの移動とは関係ないように思います。 > モデルの移動する方向のベクトル(pl.TargetMoveDirection)を用いて回転する方向が決まったり回転を付加する回数が決まっているように感じられるので、 > モデルの移動に直接関係があるように思うのですがいかがなものなのでしょうか。 Player_AngleProcess の中身を全てコメントアウトしてみると分かりますが、 モデルの姿勢が変わらなくなるだけでモデルの移動には問題ありません。
Re: atan2関数による角度算出について ( No.9 )
名前:もやし 日時:2012/04/29 12:34

いっちさんの >ベクトルでモデルの姿勢を制御する場合は 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 ) ; }
Re: atan2関数による角度算出について ( No.10 )
名前:いっち 日時:2012/04/29 16:51

> 最後にお伺いしたいのですが、171行目において逆ベクトルを指定しているのですが、 > MV1SetRotationZYAxis関数が指定する z 軸方向は負の方向が基準なのでしょうか。 モデルによるのではないでしょうか? "DxChara.x"は DxLibModelViewer で見る限り背中側が Z+ になっているようです。
Re: atan2関数による角度算出について ( No.11 )
名前:もやし(解決) 日時:2012/04/29 18:59

>"DxChara.x"は DxLibModelViewer で見る限り背中側が Z+ になっているようです。 なるほど、背中側が+になっているということでしたか、調べてくださってありがとうございます。 いっちさんのおかげで思っているような処理を実装することができました、ありがとうございました。

Page: 1 |