ページ 1 / 1
2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 03:35
by Priest
はじめまして。
少し上手くいかないことがあって投稿させていただきます。
C言語+DXライブラリを用いて、三次元シューティングゲームを作っています。
三次元空間上に2つの点(自機と敵機)があり、
片方(自機)からもう片方(敵機)を見た時の水平方向の(y軸を軸にした)角度と、
垂直方向の(x軸を軸にした)角度を求めたいと思っています。
自機はPc[0]、敵機はPc[1]で、
それぞれの座標(x, y, z)は(Pc
.Pos.x, Pc.Pos.y, Pc.Pos.z)で表現しています。
また、Pcのメンバー変数RotTarはh(水平方向の角度),v(垂直方向の角度)を保持しています。
コード:
Pc[0].RotTar.h = atan2( Pc[1].Pos.x - Pc[0].Pos.x, Pc[1].Pos.z - Pc[0].Pos.z );
Pc[0].RotTar.v = atan2( Pc[1].Pos.y - Pc[0].Pos.y, Pc[1].Pos.z - Pc[0].Pos.z );
上記のコードで、水平方向の角度はしっかり求まるのですが、垂直方向が上手く求まりません。
ある一定範囲内の角度からなら上手くいくこともありました。
なので場合分けが必要なのかと考えましたが、数学には明るくなく頓挫してしまいました。
2行目について気付くことがありましたらよろしくお願いします。
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 04:16
by Priest
[quote="Priest"]
コード:
Pc[0].RotTar.h = atan2( Pc[1].Pos.x - Pc[0].Pos.x, Pc[1].Pos.z - Pc[0].Pos.z );
Pc[0].RotTar.v = atan2( Pc[1].Pos.y - Pc[0].Pos.y, Pc[1].Pos.z - Pc[0].Pos.z );
quote]
上記のコードは少し古いものでした。
正しくは以下になります。
コード:
Pc[0].RotTar.h = atan2( Pc[1].Pos.x - Pc[0].Pos.x, Pc[1].Pos.z - Pc[0].Pos.z );
Pc[0].RotTar.v = -atan2( Pc[1].Pos.y - Pc[0].Pos.y, Pc[1].Pos.z - Pc[0].Pos.z );
ついでに挙動を示す画像を用意しました。
それぞれ、赤枠で囲ったのがターゲットになります。
水平方向なら角度計算OKな一例:

垂直方向が入ると失敗する例:

垂直方向が入っても成功する例:

Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 08:31
by h2so5
ヒント:

- スクリーンショット 2013-01-16 8.28.37.png (18.46 KiB) 閲覧数: 16013 回
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 09:16
by Priest
うわあああああああああああああああああああああああああああ!
クリティカルなヒントありがとうございました!
無事次のステップに進められそうです。
数学明るいとか明るくない以前の問題だったですね。
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 09:59
by ホヅミ
今後のためにどう解決したのかも書いてくれると幸いです。
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 13:57
by Priest
コード:
Pc[0].RotTar.v=-atan2(Pc[1].Pos.y-Pc[0].Pos.y,sqrt(pow(Pc[1].Pos.z-Pc[0].Pos.z,2)+pow(Pc[1].Pos.x-Pc[0].Pos.x,2)));
図を参考に、上記のように2行目を修正し、解決しました。
当初、ある条件なら成功すると言いましたが、
その条件とは自機とターゲットの配置がZ軸に対して平行になる時だったんですね。
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 14:09
by h2so5
斜辺を求めるときに便利な標準関数としてhypotがあります。
コード:
Pc[0].RotTar.v=-atan2(Pc[1].Pos.y-Pc[0].Pos.y, hypot(Pc[1].Pos.z-Pc[0].Pos.z, Pc[1].Pos.x-Pc[0].Pos.x));
C99の標準関数で知名度が低いみたいですがGCCやVC++は対応しています。
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 14:51
by Priest
実装しました。ありがとうございます。
もし見ていたらでいいので、どなたかご回答ください。
この実装において、私のコードではhypotの返り値をfloatでキャストしてあげる必要がありました。
このプログラムでは全ての小数をfloatで扱っていますが、この際doubleに全部変えようか悩んでいます。
三次元の計算において、これらの精度の差が実行結果に大きくかかわることはありますか?
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 15:11
by h2so5
floatを使用している場合は、hypotの代わりにhypotfが使えます。
Priest さんが書きました:三次元の計算において、これらの精度の差が実行結果に大きくかかわることはありますか?
複雑な物理演算などを行う場合などを除いて、一般的にゲームで浮動小数点数の精度が問題になることはあまり無いと思います。
DXライブラリを使っている場合はAPI引数がfloatなので基本的にfloatで良いのではないかと思います。
Re: 2点の三次元座標から角度を求める方法について
Posted: 2013年1月16日(水) 15:17
by Priest
精度に問題がないのであれば、今から全部変えるのは面…使用メモリ量削減の観点から変更の必要性はなしと判断しました。
変な質問の回答まで時間を割いて頂き、ありがとうございました!