- ベストアンサー
ベクトルの問題
毎回参考にさせて頂いております。 今回ベクトルの問題で困っております、 オブジェクトAが X100 Y100 Z100におり オブジェクトBが X200 Y50 Z50にいる場合 (オブジェクトAはどこを向いているか分からない) オブジェクトAがオブジェクトBの方向を向くようにしたい (オブジェクトAやオブジェクトBの位置が変わっても)のですが 方法が分かりません、また、公式などがありましたら計算式を 載せて頂けると有難いです。宜しくお願い致します。 P.S 本問題は、C言語プログラミングにて実装したいと 考えております。もしプログラミングも分かる方いらっしゃいましたら、併せてお願い致します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
> 今回仮の向きをvecZ(0,0,1)して考えております この向きは、オブジェクトAに対する相対座標でいいのですか? ソースコードについて気づいた点を述べます。 > //正規化したオブジェクトCの平方根を求める > vector = sqrt((オブジェクトC.x * オブジェクトC.x) + (オブジェクトC.z * オブジェクトC.z)); まず、ここはすぐ前で正規化しているので計算する必要性はありません。 > if(オブジェクトC.x >= 0) > { > vector = -vector; > vecZ.z = -1; > rad = -(D3DXVec3Dot(&vecZ,&target) / vector) + D3DX_PI; > } > else > { > rad = D3DXVec3Dot(&vecZ,&target) / vector; > } こちらについては、私がクォータニオンというものをよく理解していないのでコメントは差し控えます。 替わりにというわけではないですが、三つの軸の内一つの軸を無視した方法ではなく、行列を用いて一回で回転させるソースコードを載せておきます。 基本的には回答番号2で説明した方法と同じようにベクトルの内積から回転角度を求めてオブジェクトを回転させるだけですが、一回で回転させるための回転軸をベクトルの外積を用いているのと、回転行列をD3DXMatrixRotationAxisで求めているところが違います。 #include <stdio.h> #include <d3dx9math.h> int main(void) { D3DXVECTOR3 objA(100, 100, 100); // オブジェクトAの座標 D3DXVECTOR3 objB(200, 50, 50); // オブジェクトBの座標 D3DXVECTOR3 sightA(0, 0, 1); // オブジェクトAの向いている座標 D3DXVECTOR3 curr, next, axis, rotated; // オブジェクトAの現在の向きと次の向き、回転軸、回転後の向き D3DXMATRIX rot; // オブジェクトAの回転行列 float theta; // オブジェクトAの回転角度 // オブジェクトAの現在の方向と次に向く方向を求める D3DXVec3Subtract(&curr, &sightA, &objA); printf("(x, y, z) = (%f, %f, %f) [curr]\n", curr.x, curr.y, curr.z); D3DXVec3Subtract(&next, &objB, &objA); printf("(x, y, z) = (%f, %f, %f) [next]\n", next.x, next.y, next.z); // currとnextから外積を求めて、オブジェクトAの回転軸を求める D3DXVec3Cross(&axis, &curr, &next); printf("(x, y, z) = (%f, %f, %f) [axis]\n", axis.x, axis.y, axis.z); // オブジェクトAの回転角度行列を求める theta = acos(D3DXVec3Dot(&curr, &next) / D3DXVec3Length(&curr) / D3DXVec3Length(&next)); printf("theta = %f\n", theta); // オブジェクトAの回転行列を求める D3DXMatrixRotationAxis(&rot, &axis, theta); // currを回転させる // うまく回転できれば、nextと向きが同じになる D3DXVec3TransformNormal(&rotated, &curr, &rot); printf("(x, y, z) = (%f, %f, %f) [rotated]\n", rotated.x, rotated.y, rotated.z); return 0; }
その他の回答 (3)
すみません。 思いっきり間違えてしまいました。 > オブジェクトA及びBの座標はそれぞれa = (xA, yA)及びb = (xB, yB)とします。 これを、 「z軸を無視したオブジェクトAの向き及びAからBへの向きをそれぞれa = (xA, yA)及びb = (xB, yB)とします。」 に訂正いたします。 つまり、オブジェクトAの座標が(100, 100, 100)、オブジェクトBの座標が(200, 50, 50)、オブジェクトAが座標(1, 2, 3)を向いているとした場合、 a = (1-100, 2-100) = (-99, -98) b = (200-100, 50-100) = (100, -50) となります。 あと今更ながら気づいたのですが、 > (オブジェクトAはどこを向いているか分からない) 「まったくどこを向いているかわからない」ということはないですよね? 本当にどこを向いているのかわからなければ、「不可能」というのが質問の答えになってしまいます。
お礼
返事が遅くなってしまい申し訳ございません。 試験勉強の為、確認が遅くなってしまいました。 私のやり方でプログラムをしてみたのですが、中々うまくいきません 確認して頂けるのでしたら、計算が分からないので教えていただけないでしょうか、宜しくお願いいたします。 オブジェクトA(100, 100, 100)、オブジェクトBの座標が(200, 50, 50)の場合での計算です 今回仮の向きをvecZ(0,0,1)して考えております (1).オブジェクトAからオブジェクトBを引いて方向ベクトルを求める. オブジェクトC = オブジェクトA - オブジェクトB (2).(1)で求まったものの、解(オブジェクトC)より、Y軸は今回無いものと考えて0を入れる。 オブジェクトC.y = 0 (3).オブジェクトCを正規化する (4).正規化したオブジェクトCの平方根を求める sqrt((オブジェクトC.x * オブジェクトC.x) + (オブジェクトC.z * オブジェクトC.z) (5).オブジェクトC.xが 0以上の場合 -((vecZ・オブジェクトCの内積) / -(4)の回答) + 3.14 そうでない場合は (vecZ・オブジェクトCの内積 / -(4)の回答) + 3.14 この解が回転させる値として行っているのですが、うまくいきません。 説明が下手で申し訳ありませんが宜しくお願いいたします。 以下にプログラムも書かせて頂きますので分かりましたらお願いいたします。 objectC= objectA- objectB; // 方向計算 objectC.y = 0.0f; //Y軸は今回無いものと考える D3DXVec3Normalize(&objectC,&objectC); // オブジェクトCを正規化 //正規化したオブジェクトCの平方根を求める vector = sqrt((オブジェクトC.x * オブジェクトC.x) + (オブジェクトC.z * オブジェクトC.z)); if(オブジェクトC.x >= 0) { vector = -vector; vecZ.z = -1; rad = -(D3DXVec3Dot(&vecZ,&target) / vector) + D3DX_PI; } else { rad = D3DXVec3Dot(&vecZ,&target) / vector; }
x, y, z軸に平行な軸でオブジェクトAを必要なだけ回転させるだけです。 どれ位回転させればいいのか? z軸に平行な軸で説明します。 オブジェクトA及びBの座標はそれぞれa = (xA, yA)及びb = (xB, yB)とします。 ベクトルaとbのなす角θは θ = arccos(a・b/|a||b|) (ただし、θ=0~π) = arccos{(xA*xB+yA*yB)/√{(xA^2+yA^2)(xB^2+yB^2)}} で求められますので、この角度だけオブジェクトを回転させます。 回転の方向は+と-の2方向ありますが、判定は難しくはありません。 同様に、x及びy軸に平行な軸について回転させればオブジェクトAがオブジェクトBの方向を向くことになります。 > もしプログラミングも分かる方いらっしゃいましたら、併せてお願い致します。 まず、あなたが実装できるところまでして、わからないところを示してください。
- fjfsgh
- ベストアンサー率16% (5/30)
ベクトルの差をとればいいと思うのですが、問題の本質がよく読めません。
補足
返事が遅くなってしまい申し訳ございません。 私は、まだ技術経験がが浅く、計算方法が分かりません。 ゲームとしては、キャラクターAが、キャラクタBの方向を 向くような設定を作りたく思っております。 プログラムではこのような形なのですが、もしお分かりでしたら ご指導頂けないでしょうか宜しくお願いいたします。 objectC= objectA- objectB; // 方向計算 objectC.y = 0.0f; //Y軸は今回無いものと考える D3DXVec3Normalize(&objectC,&objectC); // オブジェクトCを正規化 //正規化したオブジェクトCの平方根を求める vector = sqrt((オブジェクトC.x * オブジェクトC.x) + (オブジェクトC.z * オブジェクトC.z)); if(オブジェクトC.x >= 0) { vector = -vector; vecZ.z = -1; rad = -(D3DXVec3Dot(&vecZ,&target) / vector) + D3DX_PI; } else { rad = D3DXVec3Dot(&vecZ,&target) / vector; }
お礼
返信が遅くなってしまい申し訳ございませんでした。 細かいご回答ありがとうございました。 今回、お答えいただいた方法で、 うまく回転をする事が出来ました。 やはり数学は難しいので今後も勉強していきたいと思います。 また、ご機会がございましたら、ご回答お願い致します。 本当に有難うございました