🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

5286閲覧

原点ではなく点Pを中心に回転するという処理を実装したい。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/12/07 23:50

編集2020/12/08 11:30

提示コードのここですのコメント部の二行ですが 
質問1、現在はコードでは原点中心に回転するコードになっており自分のやりたいことは原点ではなく
物体を中心に回転してほしいので物体Pの座標を中心に回転するにはどうすればいいのでしょうか?

質問2 また視点である二行目はどうすれば常に物体を見つめるという状態を作れるのでしょうか?

回転は実装できましたがその後がわからなく参考サイトではそのあたりの回答がないので困っています。
参考サイト: https://teratail.com/questions/251067

cpp

1//アップデート 2void Game::Update() 3{ 4 5 printf("camera: %.2f, %.2f, %.2f \n\n",camera->getPosition().x, camera->getPosition().y, camera->getPosition().z); 6 7 // glm::qua<float> P(0, mh->getPosition().x, mh->getPosition().y, mh->getPosition().z); 8 glm::qua<float> P(0, camera->getPosition().x, camera->getPosition().y, camera->getPosition().z); 9 10 11 printf("P.x: %.2f\n", P.x); 12 printf("P.y: %.2f\n", P.y); 13 printf("P.z: %.2f\n\n\n", P.z); 14 15 16 17 glm::vec3 v(0.0f,-1.0f,0.0f); //回転する向き 18 glm::qua<float> Q(cos((PI_ * speed) / 2.0f), glm::dot(v.x, sin((PI_ * speed) / 2.0f)), glm::dot(v.y, sin((PI_ * speed) / 2.0f)), glm::dot(v.z, sin((PI_ * speed) / 2.0f))); 19 glm::qua<float> R(cos((PI_ * speed) / 2.0f), glm::dot( -v.x, sin((PI_ * speed) / 2.0f)), glm::dot(-v.y, sin((PI_ * speed) / 2.0f)), glm::dot(-v.z, sin((PI_ * speed) / 2.0f))); 20 21 glm::qua<float> f = (R * P * Q); 22 23 glm::vec3 w(0,0,0); 24 25 w.x = f.x; 26 w.y = f.y; 27 w.z = f.z; 28 29 /* 30 printf("w.x: %.2f\n", w.x); 31 printf("w.y: %.2f\n", w.y); 32 printf("w.z: %.2f\n\n\n", w.z); 33 */ 34 35 // ここのコード 36 camera->setMove( w ); 37 //camera->setCenter( mh->getPosition()); 38 39 40 41 //camera->setMove(pos); 42 mh->Update(); 43 44 KeyInput(); //キー入力 45} 46

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2020/12/08 03:01 編集

いつか見たことある質問だなと思ったら4月まで遡ってしまいました [C++ - クォータニオンによる中心点を中心にラジアン度カメラを回転する視点移動を実装したい。原点の算出法など|teratail](https://teratail.com/questions/251067 )
fana

2020/12/08 02:01 編集

> モ○ハンなどで右スティックを動かすと視点がキャラクタを中心に回るあのカメラ回転 たまに,このように物事を説明する人がいるけど,特定のタイトルを挙げても万人には伝わらないのだから,きちっと物事を定義した方が良いと思う.(実際,知らないし) で,以下,確認事項: ・カメラ(視点)の位置というのは,常に キャラクタの位置を中心とした(固定半径の?)円の周上にあるのでしょうか?  言い換えれば,カメラの位置というのは,キャラクタの位置とある角度θが与えられれば確定できるのでしょうか? ・カメラが向く方向というのは,カメラの位置とキャラクタの位置だけから定まるのでしょうか? 上記が共にYesであれば,カメラの位置と姿勢というのはキャラクタ位置とθとから直接求められる話であろうと思うので,クォータミオンがどうのとか言わずに,直に求めてしまう方が楽なのではないか,と.
退会済みユーザー

退会済みユーザー

2020/12/08 06:58

タイトルを文章を修正しました。
guest

回答2

0

ベストアンサー

物体を中心に回転してほしいので物体Pの座標を中心に回転するにはどうすればいいのでしょうか?

現在位置を四元数を用いた計算で回転させて……という更新の仕方ではなく,もっとシンプルに,
各時刻における座標をダイレクトに計算すれば良いのではないかと思います.

カメラが物体Pの位置を中心とした円周上を動くような話なのであれば,円周上の位置を示す値θを更新(増減)し,
カメラ座標は{θの値,Pの座標,円の半径}から求めればよいでしょう.
(計算内容がものすごく簡単ですし,物体Pが動けばカメラは常に勝手に付いてきますし.)

どうすれば常に物体を見つめるという状態を作れるのでしょうか

カメラ姿勢を表す回転マトリクスの要素9個(=カメラ座標系の3つの基底ベクトル)の値を決めれば良いのでしょうから,例えば以下のように計算すればどうでしょうか.

上記で計算できたカメラ座標をC,物体Pの座標をそのままPと記すならば,
カメラ→物体P の方向というのは単純に P - C ですよね.
これを単位化してやれば,カメラ座標系の3つの基底ベクトルのうちの1つが定まります.
で,さらに1つを適当に(カメラ位置Cにおける円の接線方向単位ベクトルだとか,あるいは世界の「上」方向単位ベクトルだとか)定めて,最後の1つは外積から求めてやれば良いのではないかと.

投稿2020/12/08 07:45

fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/12/08 07:48

「円」じゃくて「球」だとか「円筒」だとか何とかいう場合でも同様. カメラの位置姿勢が物体Pの位置に追従して定まるのであれば,素直にその「追従」の関係を実装すれば良いだろう,と.
退会済みユーザー

退会済みユーザー

2020/12/08 10:15

上の説明ですが具体的はどう実装したらいいのでしょうか?ちょっと説明が難しくてどうすればいいのかわかりませんw
fana

2020/12/08 11:36

そんな草生やすほど難しいことを書いたつもりはないのですが… どこが不明ですか?
退会済みユーザー

退会済みユーザー

2020/12/08 11:38

> 物体を中心に回転してほしいので物体Pの座標を中心に回転するにはどうすればいいのでしょうか? です。具体的にどんなプログラムをすればいいかがわかりません。紙の上でちゃんと考えています。どうすればいのでしょうか?
fana

2020/12/08 11:45

話を簡単にするために,カメラ位置の「高さ」は何か適当に固定されるとしましょう. (あるいは,Pの「高さ」に適当な定数を加算したものとするとか) そしたら残りは2次元の話ですよね.CとPから「高さ」方向の次元を除外した平面上の世界で円周上の座標を考えるだけです.すなわち, C.x = P.x + r * cos(θ) C.y = P.y + r * sin(θ) みたいなので良いんじゃないですか?という話です. (実際の3次元世界でX,Y,Zのどの軸が「高さ」以外の2つの方向になるのか知りませんが,そこは適当に読み変えてください)
退会済みユーザー

退会済みユーザー

2020/12/08 11:49

なるほど。質問ですがZ軸はどうなるのでしょうか?
fana

2020/12/08 11:55

えっと,困りましたね… 例えば,あなたの考えている世界において,高さ(上下方向)に相当するのが Y 軸であったならば, > カメラ位置の「高さ」は何か適当に固定されるとしましょう というのは, C.y = 定数 という話です.すると,後は,C.xとC.zを決めればよく,であれば C.x = P.x + r * cos(θ) C.z = P.z + r * sin(θ) とかすりゃあいいよね,っていう話です. > (実際の3次元世界でX,Y,Zのどの軸が「高さ」以外の2つの方向になるのか知りませんが,そこは適当に読み変えてください) というのはそういう意味です. さらに言えば,xとzとでどっちをcosにしてどっちをsinにするのか?というのも,あなたの考えている世界でのθの仕様に合わせてやれば良いです.
退会済みユーザー

退会済みユーザー

2020/12/08 11:57

なるほど。質問ですがrとはどんあ値が来るのでしょうか・
fana

2020/12/08 12:02

円の半径です. (ひょっとして,この手の数式等を一度も見たことないタイプの方ですか?)
退会済みユーザー

退会済みユーザー

2020/12/08 12:16

はいそうです。学校ではずっと寝逃げしてましたので。w
fana

2020/12/08 12:22

うーん… 本件みたいなのは, 「まず数式を立てて → それをもうすっかりそのままの形で実装するよね」 的なジャンルなので, プログラミングとは全く別に,数式側の話に関して少なくとも高校レベルくらい?(三角関数とか出てくるくらい)までの理解が必要かと思います. まともな速度で実装を進めるためには,数学を要復習かと見えます. たとえばググる等してこの話と同様の内容をどこかに見つけたとして, 「ここで r は円の半径である」とかいちいち断りがある方が稀ではないかと想像します. ここに書いた式をぱっと見でわかる(というか,このコメント欄での解説自体が一切不要な)状態でないと,何かしらの調べ事をするにしても非常に厳しいのではないかと.
fana

2020/12/08 12:24

面倒な話でしょう? 私も,より上位の存在から,日々同じようなことを言われています. つらい.
退会済みユーザー

退会済みユーザー

2020/12/08 23:49

「現在位置を四元数を用いた計算で回転させて」という方法を教えてくますでしょうか?  glmライブラリがあるのでこっちのがわかるかもしれません
fana

2020/12/09 02:03

話の内容が別になるので回答を分けました. 「ライブラリがあるから→わかる」という話は謎です. ライブラリ等に覆い隠された部分があればあるほど,(隠されているのだから)話の詳細がわからない方向に向かうように思います.
guest

0

「現在位置を四元数を用いた計算で回転させて」という方法

  • (正直,先に書いた別回答と比べると無意味に面倒なだけの話と思えます)
  • (あなたのAPPでの実装形態と完全に合致する話はできないので「例」となります)

話の前提(仮定):
カメラの座標C(3次元の座標)とカメラの回転姿勢を示す何か(ここでは行列Rだとしよう)をカメラの位置姿勢を表すための状態としてAPPが保持していて,毎時刻にCRを更新していく話なのだとする.

で,各時刻でのデータ更新処理においては,カメラ位置姿勢の更新処理よりも先に物体Pの位置の更新処理が行われるとすると,

  • P_prev : 物体Pの前時刻(更新前)での位置
  • P_curr : 物体Pの現時刻(更新後)での位置

という2つのデータをカメラ位置姿勢の更新処理に入力できるだろう.
さらに,カメラ位置の更新のための回転量として

  • : 物体Pを中心とした円弧上でのカメラ移動量を表すための角度値

もカメラ位置姿勢の更新処理に入力されるとしよう.(これはユーザ操作か何かによって決まる値かな?)

位置Cの更新:

  • 前時刻における,物体Pから見たカメラの相対位置を計算:

C_rel = C - P_prev

  • 相対位置を,回転量を用いて(現時刻の値に)更新する:

C_rel = 四元数を用いた計算によってC_relをdθだけ回転した結果

  • 現時刻における相対位置を絶対位置に変換:

C = C_rel + P_curr

姿勢Rの更新:

こっちはただの姿勢回転なので

R = 四元数を用いた計算によってRをdθだけ回転した結果

という形で更新すればよいだろうと思う.


#四元数を用いた回転計算の具体内容については,ググるなりして下さい.(私ではその内容を説明できませんし)

投稿2020/12/09 01:58

fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/12/09 02:40

(補足) 位置の回転について: ”原点を中心に回転させる手段” が手元にあるならば,"任意の点を中心とした回転処理"というのは, 「回転中心としたい位置が原点であるような座標系の上で(原点中心の)回転計算すれば良いよね」という話になる. 元の世界 → 回転を実施する世界(ここで回転) → 元の世界 としてやればいい. ここで「→」は座標変換変換処理だが,内容は単なる座標オフセットだから加減算である.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問