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

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

詳細はこちら
C++

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

3DCG

コンピュータの演算により、3次元空間の仮想物体を、2次元平面上で表現する手法である。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

解決済

2回答

3456閲覧

クォータニオンによる中心点を中心にラジアン度カメラを回転する視点移動を実装したい。原点の算出法など

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

3DCG

コンピュータの演算により、3次元空間の仮想物体を、2次元平面上で表現する手法である。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

0クリップ

投稿2020/04/03 04:21

編集2020/04/10 02:36

参考サイトなどを見て計算式をプログラムに落とし込んだが何が原因でカメラが注視点を中心に回転しくれないのかわからない。”地球を中心に回る月のような月”
rotate();関数の引数は(座標,ラジアン,中心点,回転軸)ようになっています。"座標"を"中心点"を中心とした"回転軸"に"ラジアン"回転するということを目的としています。

質問1、rotate関数ですがクォータニオンの計算をしてカメラを回転させたいがクォータニオン同士の掛け算や
ベクトルの外積、内積の計算が正しいのか、注視点はいいのか?

質問2、"回転軸ベクトル"とは何をすれば算出されるのでしょうか?

質問3、どうすればクォータニオンによる中心点を中心にラジアン度 カメラ回転を実装できるのか知りたい。

やりたいこと 周回軌道のようなモン〇ンのような3アクションゲームのカメラのようなカメラ動作をしてほしい。

イメージ説明

参考サイト1 : http://marupeke296.com/DXG_No10_Quaternion.html
参考サイト2 : http://marupeke296.com/COL_Basic_No1_InnerAndOuterProduct.html
参考サイト3 :https://home.hiroshima-u.ac.jp/kyoshida/MathExercise/2015(1stSemester)/exercise1(no03).pdf

以下rotete_x();関数部です。引数にカメラ座標と注視点座標とラジアンを入れて回転させる予定

/*回転 回転する座標、ラジアン、中心、軸*/ /*回転する座標、ラジアン、中心、軸*/ void Game::rotate(Vector *pos,const float ang, const Vector targetV,const Vector axis) { //Quaternion Prev(0, Vector(*x - mx, *y - my, *z - mz)); Quaternion P(0, Vector(pos->x, pos->y, pos->z));//回転させる点 Quaternion P2(0, Vector(pos->x - targetV.x, pos->y - targetV.y, pos->z - targetV.z));//回転させる点 Quaternion PP(0, Vector(targetV.x - pos->x, targetV.y - pos->y, targetV.z - pos->z));//回転させる点 Quaternion PP3(0,Vector(targetV.x , targetV.y , targetV.z ));//回転させる点 Quaternion Q(cos(ang / 2), Vector( axis.x * sin(ang / 2), axis.y * sin(ang / 2), axis.z * sin(ang / 2))); Quaternion R(cos(ang / 2), Vector(-axis.x * sin(ang / 2) , -axis.y * sin(ang / 2), -axis.z * sin(ang / 2))); Quaternion result = (R * P2) * Q;//順番が大事 ofs << "pos.x:" << pos->x << std::endl; ofs << "pos.y:" << pos->y << std::endl; ofs << "pos.z:" << pos->z << "\n" << std::endl; ofs << "result.x:" << result.v.x << std::endl; ofs << "result.y:" << result.v.y << std::endl; ofs << "result.z:" << result.v.z << "\n\n\n" << std::endl; pos->x = result.v.x; pos->y = result.v.y; pos->z = result.v.z; } void Game::Update() { /*カメラ回転*/ if (Input::keyboard(KEY_INPUT_LEFT) > 0) { // rotate(&cameraX, &cameraZ, +ROTATE_SPEED, targetX, targetZ,); } else if (Input::keyboard(KEY_INPUT_RIGHT) > 0) { // rotate(&cameraX, &cameraZ, -ROTATE_SPEED, targetX, targetZ); } else if (Input::keyboard(KEY_INPUT_UP) > 0) { // rotate_X(&cameraX, &cameraY,&cameraZ, -ROTATE_SPEED, targetX, targetY,targetZ); DrawFormatString(100,100,GetColor(255,255,255),"UP"); } else if (Input::keyboard(KEY_INPUT_DOWN) > 0) { // rotate_X(&cameraX, &cameraY, &cameraZ, +ROTATE_SPEED, targetX, targetY, targetZ); DrawFormatString(100, 100, GetColor(255, 255, 255), "Down"); } if (Input::keyboard(KEY_INPUT_W) > 0) { } else if (Input::keyboard(KEY_INPUT_S) > 0) { } /*色 変更*/ if(Input::keyboard(KEY_INPUT_SPACE) == 1) { ModeChange = !ModeChange; } /* false spcカラーを変更*/ if (Input::keyboard(KEY_INPUT_Z) > 0 && ModeChange == false) { color_spc.r += -1; color_spc.g += -1; color_spc.b += -1; } else if (Input::keyboard(KEY_INPUT_X) > 0 && ModeChange == false) { color_spc.r += 1; color_spc.g += 1; color_spc.b += 1; /*true difカラー変更*/ }else if (Input::keyboard(KEY_INPUT_Z) > 0 && ModeChange == true) { color_dif.r += -1; color_dif.g += -1; color_dif.b += -1; } else if (Input::keyboard(KEY_INPUT_X) > 0 && ModeChange == true) { color_dif.r += 1; color_dif.g += 1; color_dif.b += 1; } if (Input::keyboard(KEY_INPUT_F1) == 1) { TextureMode = !TextureMode; } }

ヘッダー部

#ifndef ___Vector_H #define ___Vector_H //template<typename type> class Vector { private: public: float x; float y; float z; Vector(float xx, float yy, float zz); Vector(); static Vector cross(Vector a, Vector b);//外積 static float dot(Vector a, Vector b);//内積 static Vector mul_scalar(float a, Vector v);//スカラーとベクトルの掛け算 Vector operator = (Vector v); Vector operator + (Vector v); }; //template<typename type> class Quaternion { public: /*実部*/ float a; /*虚部*/ // Vector<type> v; Vector v; Quaternion(float aa, Vector vv); Quaternion(); Quaternion operator * (Quaternion t); }; #endif

ソースファイル

#include "Vector.hpp" /*ベクトル x スカラーの掛け算*/ Vector Vector::mul_scalar(float a, Vector v) { return Vector(a * v.x,a * v.y,a * v.z); } /*外積 ベクトル x ベクトル*/ Vector Vector::cross(Vector a,Vector b) { return Vector( (a.y * b.z) - (a.z * b.y), (a.z * b.x) - (a.x * b.z), (a.x * b.y) - (a.y * b.x)); } /*内積*/ float Vector::dot(Vector a, Vector b) { return (a.x * b.x) + (a.y * b.y) + (a.z * a.z); } /*コンストラクタ*/ Vector::Vector(float xx,float yy,float zz) { x = xx; y = yy; z = zz; } /*コンストラクタ*/ Vector::Vector() { x = 0.0f; y = 0.0f; z = 0.0f; } /*オペレーター = */ Vector Vector::operator = (Vector v) { this->x = v.x; this->y = v.y; this->z = v.z; return *this; } /*オペレーター + */ Vector Vector::operator + (Vector v) { Vector t; t.x = this->x + v.x; t.y = this->y + v.y; t.z = this->z + v.z; return t; } /*コンストラクタ 実部、虚部(Vector) */ Quaternion::Quaternion(float aa, Vector vv) { a = aa;//実部 /*虚部*/ v = vv; } /*コンストラクタ 引数なし*/ Quaternion::Quaternion() { a = 0.0f;//実部 /*虚部*/ v.x = 0.0f; v.y = 0.0f; v.z = 0.0f; } /*クォータニオン同士の掛け算 A = (a; U) B = (b; V) AB = (ab - U・V; aV + bU + U×V) */ Quaternion Quaternion::operator * ( Quaternion t ) { return Quaternion(this->a * t.a - Vector::dot(this->v,t.v),Vector(Vector::mul_scalar(this->a,t.v) + Vector::mul_scalar(t.a,this->v) + Vector::cross(this->v,t.v))); }

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

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

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

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

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

fana

2020/04/07 04:54

コードが時々刻々と別物に差し替えられていく. 読み手から見れば,突然変更された意図も意義も不明であり,元々存在した問題や挙動等が保存されているのかどうかも不明. そのようなやり方をされては,既存の回答もコメントも質問文やコードとはミスマッチになり,一体何の話をしているのかも定まらない. (現時点で私が見ているコードに於いては)元々の問題であったrotete_x()という関数が消滅したし,それをコールしている処理すらなくなったから,もはや問題そのものが消滅しているわけで,解決すべき課題は失われたと見える) 正直,やり口が独りよがりすぎてついていけません.
Tto777

2020/04/07 10:57

他の質問含め今までついていってあげたのが賞賛ものですよ。 ヘルプバンパイアは放置してあげるのが本人の為でもあり将来の他人の為になります。
退会済みユーザー

退会済みユーザー

2020/04/07 10:59

すいませんでした。
fana

2020/04/08 04:00 編集

バンパイア云々は度外視するにしても,この進め方だと,「他者が後で参考にできるログ」という形で情報が残り得ないであろう点が問題かと.
退会済みユーザー

退会済みユーザー

2020/04/07 11:10

調べてもわからない場所があったので質問したのですがそれがよくなかったのでしょうか?失礼しました。紙の上に書いたりして落ち着いてよく考えたのですがわからなかったので
yumetodo

2020/04/10 11:14 編集

質問することが悪いのではなくて、質問が絞られていないこと、あなたと同じ疑問を持った他の人を考えていないこと(履歴見ましたが単なる誤字の修正にとどまらない書き換えがなされていますよね?)、マルチポストしたこと(https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=view&no=4866 )などが問題なのです。とくに後から遡及できる可能性を消したことはteratailにおいては重大な問題です。端的に言うと回答者との信頼関係を毀損したわけですね。別にこういうことをやらかしてくる質問者は何もあなたが初めてではないですが、時折こうして遭遇するとうんざりしてしまうのが回答者の本心でしょう。 さしあたって、DxLibの掲示板の方でクォータニオンを自分で頑張らなくてもSetCameraPositionAndTarget系を使えばどうですかという回答が付いているのですし、それで満足したのか、不十分なのか、明らかにして、十分だったのなら本来は褒められませんがもうすでにマルチポストされてしまったのですから、そっちで解決しましたと書いてこの質問をcloseされるべきですし、不十分ならば、やはりクォータニオンを自力で演算することになるわけですから、勉強します、で一度この質問を閉じるべきでしょう。
fana

2020/04/14 04:26 編集

DXなんとかいうライブラリの使用経験はないけれども,ググって出てくるリファレンスを見るにSetCameraPositionAnd云々とかいう関数群は引数に「カメラの位置」を要求している物に見える.(おそらくこれらはViewマトリクスをどこぞに設定するための手段であろう) で,本件はそもそもこの「カメラの位置」を得る方法に関するものなのだと捉えていたのだが……マルチポスト先では「その関数使えばいけるから解決」とかいう話になっている.その関数に引数を与えることができるというのならば問題自体がどこにも存在しなかったのではないのか?
guest

回答2

0

ベストアンサー

やりたいこと 周回軌道のようなモン〇ンのカメラのようなカメラ動作をしてほしい。

モン〇ンを知らないので,最終的にどうなればよいのか想像がつかないですが…

提示コードを見た感じ,「どこを中心に回転させるか」という観点が抜けているようにも見えます.
「3次元空間のどこかにある「原点」を中心にして回っているのが意図とは異なる」という話なのであれば,「どこの周りを回るのか」という話の実装が必要でしょう.
(回転中心までオフセットして,回転して,オフセット量を戻す)

バグっている状態で視点が動いてしまうと把握困難でしょうから,
まずは演算結果がどうなっているのかを把握するために,
本物の「カメラ」はどこかに(ある程度広く見渡せるような場所にでも)固定しておいて,座標(cameraX,cameraY,cameraZ)に何か適当な物体を描画する形にして動作確認してみてはいかがでしょうか.

投稿2020/04/07 02:38

fana

総合スコア11987

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

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

fana

2020/04/07 02:43

あと,可能ならデバッグ時には3軸を描画した方がいいですよ. 「原点」の位置も把握しやすくなりますし.
fana

2020/04/07 02:57 編集

rotate()の側には回転中心の話が入ってますね. 「rotate_x()にも同じ話が要るのでは?」というのが回答の趣旨ですが,Game::Update()を見るとrotate()とrotate_x()とを何かしら使い分けている(?)みたいだし,rotate_x()が担う処理内容次第になりますかね.
退会済みユーザー

退会済みユーザー

2020/04/07 04:54

rotate関数部の引数を修正しました。回転軸とはどのように算出するのでしょうか?試しにカメラ座標 - 中心点を試しましたがやはり挙動がおかしいです。
fana

2020/04/07 05:00 編集

「質問への追記・修正、ベストアンサー選択の依頼」の欄に記述しましたが… やりとりの状況が「ある1つの問題点に関する質問」というよりも,あなたの開発進捗に沿ったデバッグ依頼みたくなってしまっていると感じますので,残念ですが,本件からは手を引かせていただこうかと. 現時点でできるアドバイスとしては,実装するまえに,まずは計算内容に関する学習を行うべきではないか,ということでしょうか.
fana

2020/04/07 05:05

「回転軸」に関しては,他の方の回答のコメント欄で既述です.
退会済みユーザー

退会済みユーザー

2020/04/07 05:07

わかりました。質問自体を削除したいのですが削除依頼がまだ有効ではないので削除可能になりましたら質問を削除します。
fana

2020/04/07 05:12

現状の流れについていけないと言っているのはあくまでも私ひとりだけなのであって,手を引くのは私の勝手でしかありません. この質問には別の方々が回答やコメントを付けてくれているわけですし,削除するというのはそれはそれで良くない行為に思えます.
guest

0

うん、プログラムの構造の意味が分かりません。
とりあえず、指摘点をざっと上げておきます。

C++

1class Position{ 2 /* 3 全体を見ましたが、クラス名はPositionではなくVectorと表記するのが正しいです。 4 演算式ですが、C++にはoperatorと言う機能があるのでそっちをお使い下さい。 5 6 それとシステム的な問題で嫌う人も多いですが、ここではunionが意外に便利!! 7 union { 8 struct { 9 float x; 10 float y; 11 float z; 12 }; 13 float v[3]; 14 }; 15 */ 16}; 17 18class Quaternion 19{ 20public: 21 /* 22 しっかりと設計したいなら下記のようにお願い致します。 23 ベクトルとクォータニオンは全くの別物です。 24 Axis-angleとごっちゃになっていませんか? 25 union { 26 struct { 27 float x; 28 float y; 29 float z; 30 float w; 31 }; 32 float q[4]; 33 }; 34 */ 35 36 //ここも直して下さい。aaとvvでは意味が分かりません。 37 //Quaternion(float aa, Position vv);//意味不明 38 explicit Quaternion(Quaternion q);//これなら意味がわかる。 39 40 //ここは追加しといた方が後々便利かも... 41 Quaternion(Vector axis, float angle); 42 43 //C++にはoperatorと言う機能があるのでそっちをお使い下さい。 44 //プラス、関数の中見を拝見しましたが、演算式が間違っています。 45 //クォータニオン同士の乗算は、もっと式が複雑で長いはずです。 46 static Quaternion mul(Quaternion a, Quaternion b); 47};

投稿2020/04/06 02:01

編集2020/04/06 02:09
stdio

総合スコア3307

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

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

退会済みユーザー

退会済みユーザー

2020/04/06 04:48

質問ですがクォータニオンの掛け算が違うという指摘がありましたがサイトの"クォータニオンを使った計算"という式は違うのでしょうか? また R*P*Q と掛け算をする場合はまずR *P の結果を RPを * Qするという計算でいいのでしょうか? 違うとしたら三つを同時に掛け算するという方法なのでしょうか? https://wgld.org/d/webgl/w031.html
stdio

2020/04/06 06:19

処理的にもメモリ的にも演算式的にもかさばりますが、任意軸回転なら4x4のMatrixでも可能なのでまずはそちらで出来るかどうか確認すると良いでしょう。クォータニオンは理数系の大学院生が学ぶことなので、まずは自分のペースでゆっくり学んで下さい。
退会済みユーザー

退会済みユーザー

2020/04/06 07:36

質問ですがVECTOR vの回転させる軸はこれでいいのでしょうか?
stdio

2020/04/06 07:46

X軸回転ならここまで複雑な計算式は不要なはずです。
stdio

2020/04/06 07:52 編集

すみません、-1,0,0? 何の話ですか? まず、roll_pitch_yawの話している時点で違います。
退会済みユーザー

退会済みユーザー

2020/04/06 09:27 編集

サイト部の http://marupeke296.com/DXG_No10_Quaternion.html "回転軸の方向を表すベクトル"の意味が知りたいのですが何をすればいいのでしょうか?検索しても色々出てこないので困ってます。
fana

2020/04/06 09:14

> 回転軸の方向を表すベクトル いや,そのまんま日本語として解釈すればよいのでは… 例えば「X軸まわりの回転」をしたいなら,X軸と平行なベクトルってこと. 単位ベクトルなら (1,0,0)か(-1,0,0)でしょう.
退会済みユーザー

退会済みユーザー

2020/04/06 09:26

質問ですが、ではなぜ上手く回らないのでしょうか? VECTOR v = VTransform(VGet(-1,0,0),t);
fana

2020/04/06 10:07 編集

何がどうなったら「上手く回る」と言うのかが外野には謎なのでなんとも言えません. 少なくとも,現状とやりたいことの内容が私には質問文から読み取れないので. コードを見ても, MGetRotX()なるDXライブラリの関数と自前実装のクォータニオンを組み合わせて何かやってる演算の意味(意図)も,やっぱりわからないですし.(未使用な引数があったりすると,単にコードが未完成なだけにも見えるし)
退会済みユーザー

退会済みユーザー

2020/04/06 11:33

質問内容を大幅に編集したので回答できますでしょうか?
stdio

2020/04/07 01:01

どの辺が大幅なのでしょうか? 私の指摘したところは「C++において最低これぐらい出来ていて当たり前」の部分なのでそこを直したからと言って意味が伝わるわけではありませんし、相変わらずQuaternionの乗算は間違えたままです。 Quaternionに中にVector vを保有している点も私にはさっぱり分かりません。QuaternionとVectorは全くの別物です。 「自前実装のクォータニオンを組み合わせて何かやってる演算の意味」もだんだん分からなくなってきました。何かしたいの?
fana

2020/04/07 01:38

> Quaternionに中にVector vを保有している そこはこの型の内部実装方法でしかないので,別にそれでも良いんじゃないでしょうか(結果としてOUTPUTが合ってさえいれば).
ozwk

2020/04/07 02:30 編集

Quaternionをスカラー部とベクトル部の組で表記する方法があるので 別にVectorで保持してても問題ないです。 長ったらしくなるクォータニオン積がこの表記法だと内積と外積とスカラー倍で短く書けるメリットがあります
退会済みユーザー

退会済みユーザー

2020/04/07 07:14

質問ですが 原点が(0,0,0)を中心としていたためおかしいということききずきました。targetを中心つまり原点にするにはどのような計算をしたらいいのでしょうか?
stdio

2020/04/07 08:56

ozwkさん、確かに今回のQuaternionはQuaternion Rotateでしたね。私も大学院を卒業している訳ではないので、その定義の証明式があったら見てみたいわ。 syoshinsya_さん、座標の原点は(0,0,0)で良いのですよ。 モンハンのカメラはtargetがプレイヤーに固定されていたはずです。カメラの回転はワールド座標のX,Z軸を起点にしているのではなく、targetとcameraPointのベクトルの軸が回転しています。
退会済みユーザー

退会済みユーザー

2020/04/07 09:53

似たような質問かもしれませんが targetとcameraPointのベクトルの軸を取得するにはどうすればいいのでしょうか? cameraPos - targetではどうやらできないようです。その他の数式については色々調べて修正したので動かない原因はここにあると思うのです。
stdio

2020/04/08 02:56

それはVectorクラスに引き算ののoperator用意していないからですよ。
退会済みユーザー

退会済みユーザー

2020/04/08 03:43

書き方が悪かったです自分がやりたいのはつまりcameraPos - targetであって一つの一つの要素を引き算しています
yumetodo

2020/04/10 11:01

ところで >それとシステム的な問題で嫌う人も多いですが、ここではunionが意外に便利!! 多分誤った用法では?aliasにならないのでUB踏むパターンでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問