2点の三次元座標から角度を求める方法について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Priest

2点の三次元座標から角度を求める方法について

#1

投稿記事 by Priest » 12年前

はじめまして。
少し上手くいかないことがあって投稿させていただきます。
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行目について気付くことがありましたらよろしくお願いします。

Priest

Re: 2点の三次元座標から角度を求める方法について

#2

投稿記事 by Priest » 12年前

[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な一例:
画像
垂直方向が入ると失敗する例:
画像
垂直方向が入っても成功する例:
画像

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: 2点の三次元座標から角度を求める方法について

#3

投稿記事 by h2so5 » 12年前

ヒント:
スクリーンショット 2013-01-16 8.28.37.png
スクリーンショット 2013-01-16 8.28.37.png (18.46 KiB) 閲覧数: 16019 回

Priest

Re: 2点の三次元座標から角度を求める方法について

#4

投稿記事 by Priest » 12年前

うわあああああああああああああああああああああああああああ!

クリティカルなヒントありがとうございました!
無事次のステップに進められそうです。
数学明るいとか明るくない以前の問題だったですね。

ホヅミ
記事: 110
登録日時: 14年前

Re: 2点の三次元座標から角度を求める方法について

#5

投稿記事 by ホヅミ » 12年前

今後のためにどう解決したのかも書いてくれると幸いです。

Priest

Re: 2点の三次元座標から角度を求める方法について

#6

投稿記事 by Priest » 12年前

コード:

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軸に対して平行になる時だったんですね。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: 2点の三次元座標から角度を求める方法について

#7

投稿記事 by h2so5 » 12年前

斜辺を求めるときに便利な標準関数として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++は対応しています。

Priest

Re: 2点の三次元座標から角度を求める方法について

#8

投稿記事 by Priest » 12年前

実装しました。ありがとうございます。

もし見ていたらでいいので、どなたかご回答ください。

この実装において、私のコードではhypotの返り値をfloatでキャストしてあげる必要がありました。
このプログラムでは全ての小数をfloatで扱っていますが、この際doubleに全部変えようか悩んでいます。

三次元の計算において、これらの精度の差が実行結果に大きくかかわることはありますか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: 2点の三次元座標から角度を求める方法について

#9

投稿記事 by h2so5 » 12年前

floatを使用している場合は、hypotの代わりにhypotfが使えます。
Priest さんが書きました:三次元の計算において、これらの精度の差が実行結果に大きくかかわることはありますか?
複雑な物理演算などを行う場合などを除いて、一般的にゲームで浮動小数点数の精度が問題になることはあまり無いと思います。
DXライブラリを使っている場合はAPI引数がfloatなので基本的にfloatで良いのではないかと思います。

Priest

Re: 2点の三次元座標から角度を求める方法について

#10

投稿記事 by Priest » 12年前

精度に問題がないのであれば、今から全部変えるのは面…使用メモリ量削減の観点から変更の必要性はなしと判断しました。

変な質問の回答まで時間を割いて頂き、ありがとうございました!

閉鎖

“C言語何でも質問掲示板” へ戻る